<commit_before>/**
 *
 * GeometryCanvasCifdata
 *
 */

import { compose } from 'recompose';
import React from 'react';
import PropTypes, { instanceOf } from 'prop-types';
import { withStyles } from 'material-ui/styles';
import Paper from 'material-ui/Paper';
/*import Button from 'material-ui/Button';*/
/*import Chip from 'material-ui/Chip';*/
/*import AddIcon from 'material-ui-icons/Add';*/
/*import RemoveIcon from 'material-ui-icons/Remove';*/
import { Md3dRotation, } from 'react-icons/lib/md';
import { withCookies, Cookies } from 'react-cookie';

import { isMobile } from 'react-device-detect';

const jQuery = require('jquery');
window.jQuery = jQuery;
const { ChemDoodle } = require('utils/ChemDoodleWeb');

const styles = (theme) => ({
  button: {
    margin: theme.spacing.unit,
  },
});

class GeometryCanvasCifdata extends React.Component { // eslint-disable-line react/prefer-stateless-function
  constructor(props) {
    super(props);
    this.state = {
      orientation: 'test orientation',
      perspective: (this.props.cookies.get('perspective') === 'true'),
    };
    this.downloadStructure = this.downloadStructure.bind(this);
  }
  componentDidMount() {
    const script = document.createElement('script');
    script.type = 'text/javascript';
    script.async = true;
    script.innerHTML = `
function _load_lib(url, callback){
  id =  'load_' + url;
  var s = document.createElement('script');
  s.src = url;
  s.id = id;
  s.async = true;
  s.onreadystatechange = s.onload = callback;
  s.onerror = function(){console.warn("failed to load library " + url);};
  document.getElementsByTagName("head")[0].appendChild(s);

}
// Load Libraries
  var rotationMatrix = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1.3]
  rotationMatrix = ChemDoodle.lib.mat4.rotate(rotationMatrix, -.8, [1,0,0]);
  rotationMatrix = ChemDoodle.lib.mat4.rotate(rotationMatrix, +.1, [0,0,1]);

  if(typeof cif_${this.props.uniqueId} === 'undefined' ) {
   let cif_${this.props.uniqueId}
  }
  if(typeof tfcanvas_${this.props.uniqueId} === 'undefined' ) {
   let tfcanvas_${this.props.uniqueId}
  }
  //Code
  tfcanvas_${this.props.uniqueId} = new ChemDoodle.TransformCanvas3D('${this.props.id}_view');
  cif_${this.props.uniqueId} = ChemDoodle.readCIF(\`${this.props.cifdata}\`,  ${this.props.x}, ${this.props.y}, ${this.props.z});
  if (typeof alpha_${this.props.uniqueId} === 'undefined') {
  let alpha_${this.props.uniqueId} = 0.;
  }
  if (typeof beta_${this.props.uniqueId} === 'undefined') {
  let beta_${this.props.uniqueId} = 0.;
  }
  if (typeof gamma_${this.props.uniqueId} === 'undefined') {
  let gamma_${this.props.uniqueId} = 0.;
  }

  if(typeof altLabels === 'undefined') {
    var altLabels
  }
  altLabels = ${JSON.stringify(this.props.altLabels)};
  cif_${this.props.uniqueId}.molecule.atoms.map(function(atom, i){
    if(altLabels.hasOwnProperty(i)) {
    atom.altLabel = altLabels[i];
    }
  });

  tfcanvas_${this.props.uniqueId}.specs.set3DRepresentation('Ball and Stick');
  tfcanvas_${this.props.uniqueId}.specs.backgroundColor = '${this.props.color}';
  tfcanvas_${this.props.uniqueId}.specs.projectionPerspective_3D = ${this.state.perspective};
  tfcanvas_${this.props.uniqueId}.specs.compass_display = true;
  tfcanvas_${this.props.uniqueId}.specs.compass_size_3D = 50;
  tfcanvas_${this.props.uniqueId}.specs.atoms_displayLabels_3D = true;
  tfcanvas_${this.props.uniqueId}.specs.crystals_unitCellLineWidth = 5;
  tfcanvas_${this.props.uniqueId}.specs.shapes_color = 'black';
  tfcanvas_${this.props.uniqueId}.specs.shapes_lineWidth = 1;
  tfcanvas_${this.props.uniqueId}.loadContent([cif_${this.props.uniqueId}.molecule], [cif_${this.props.uniqueId}.unitCell]);
  tfcanvas_${this.props.uniqueId}.rotationMatrix = rotationMatrix; tfcanvas_${this.props.uniqueId}.updateScene()

  window.addEventListener('deviceorientation', (e) => {

  /*ALPHA*/
  /*if(typeof alpha_${this.props.uniqueId} !== 'undefined') {*/
    /*if(.01 < Math.abs(alpha_${this.props.uniqueId} - e.alpha) < 1.5) {*/
    /*tfcanvas_${this.props.uniqueId}.rotationMatrix = ChemDoodle.lib.mat4.rotate(tfcanvas_${this.props.uniqueId}.rotationMatrix,(e.alpha -  alpha_${this.props.uniqueId}) * 0.015,  tfcanvas_${this.props.uniqueId}.rotationMatrix.slice(8, 11));*/
    /*}*/
  /*}*/

  /*GAMMA*/
  /*if (typeof gamma_${this.props.uniqueId} !== 'undefined') {*/
    /*if(.01 < Math.abs(gamma_${this.props.uniqueId} - e.gamma) < 1.5) {*/
  /*tfcanvas_${this.props.uniqueId}.rotationMatrix = ChemDoodle.lib.mat4.rotate(tfcanvas_${this.props.uniqueId}.rotationMatrix,(e.gamma -  gamma_${this.props.uniqueId}) * 0.015,  tfcanvas_${this.props.uniqueId}.rotationMatrix.slice(8, 11));*/
    /*}*/
  /*}*/

  /*BETA*/
  if (typeof beta_${this.props.uniqueId} !== 'undefined') {
    if(0.01 < Math.abs(beta_${this.props.uniqueId} - e.beta) < 1.5) {
  tfcanvas_${this.props.uniqueId}.rotationMatrix =  ChemDoodle.lib.mat4.rotate(tfcanvas_${this.props.uniqueId}.rotationMatrix, -(e.beta -  beta_${this.props.uniqueId}) * 0.015,  [1, 0, 0]);
    }
  }

  alpha_${this.props.uniqueId} = e.alpha;
  beta_${this.props.uniqueId} = e.beta;
  gamma_${this.props.uniqueId} = e.gamma;
   tfcanvas_${this.props.uniqueId}.updateScene()

  }, true);
    `;
    const item = document.getElementById(`${this.props.id}_view`);

    item.appendChild(script);
  }
  componentDidUpdate() {
    this.componentDidMount();
  }
  downloadStructure() {
    axios.get(url, params).then((response) => {
      const tempUrl = window.URL.createObjectURL(new Blob([response.data]));
      const link = document.createElement('a');
      link.href = tempUrl;
      link.setAttribute('download', `dft_input_${(new Date()).getTime()}.zip`);
      document.body.appendChild(link);
      link.click();
    }).catch(() => {
    });
  }
  render() {
    return (

        {isMobile === false ? null :
 <Md3dRotation />{'\u00A0\u00A0'} Tilt device to rotate.
 }
        <Paper height={14}>
          <p id={`${this.props.id}_script`} >
            <canvas
              id={`${this.props.id}_view`}
              height={this.props.height}
              width={this.props.width}
              style={{
                borderWidth: this.props.borderWidth,
                borderColor: '#000000',
                borderStyle: 'solid',
              }}
            />

        </Paper>
        {/*
        <Button
          raised
          className={this.props.classes.button}
        >
          <MdFullscreen /> Fullscreen
        </Button>
        <Button
          raised
          color="primary"
          className={this.props.classes.button}
          onClick={this.downloadStructure}>
          <MdFileDownload /> Download
        </Button>
        */}

    );
  }
}
GeometryCanvasCifdata.defaultProps = {
  height: Math.max(Math.min(window.innerWidth * 0.5, 600), 300),
  width: Math.max(Math.min(window.innerWidth * 0.5, 600), 300),
  color: '#fff',
  cifdata: '',
  cifurl: '',
  x: 2,
  y: 2,
  z: 1,
  borderWidth: 0,
  altLabels: {},
  perspective: true,
};

GeometryCanvasCifdata.propTypes = {
  uniqueId: PropTypes.string.isRequired,
  cifdata: PropTypes.string.isRequired,
  id: PropTypes.string.isRequired,
  height: PropTypes.number,
  width: PropTypes.number,
  color: PropTypes.string,
  x: PropTypes.number,
  y: PropTypes.number,
  z: PropTypes.number,
  borderWidth: PropTypes.number,
  altLabels: PropTypes.object,
  perspective: PropTypes.bool,
  cookies: instanceOf(Cookies).isRequired,
};

export default compose(
  withStyles(styles, { withTheme: true }),
  withCookies,
)(GeometryCanvasCifdata);

/* withStyles(styles, { withTheme: true })(*/
/* withCookies(*/
/* GeometryCanvasCifdata*/
/* )*/
/* );*/
<commit_msg>Fine-tuned canvas hint<commit_after>/**
 *
 * GeometryCanvasCifdata
 *
 */

import { compose } from 'recompose';
import React from 'react';
import PropTypes, { instanceOf } from 'prop-types';
import { withStyles } from 'material-ui/styles';
import Paper from 'material-ui/Paper';
/* import Button from 'material-ui/Button';*/
/* import Chip from 'material-ui/Chip';*/
/* import AddIcon from 'material-ui-icons/Add';*/
/* import RemoveIcon from 'material-ui-icons/Remove';*/
import { Md3dRotation } from 'react-icons/lib/md';
import { withCookies, Cookies } from 'react-cookie';

import { isMobile } from 'react-device-detect';

const jQuery = require('jquery');
window.jQuery = jQuery;
const { ChemDoodle } = require('utils/ChemDoodleWeb');

const styles = (theme) => ({
  button: {
    margin: theme.spacing.unit,
  },
});

class GeometryCanvasCifdata extends React.Component { // eslint-disable-line react/prefer-stateless-function
  constructor(props) {
    super(props);
    this.state = {
      orientation: 'test orientation',
      perspective: (this.props.cookies.get('perspective') === 'true'),
    };
    this.downloadStructure = this.downloadStructure.bind(this);
  }
  componentDidMount() {
    const script = document.createElement('script');
    script.type = 'text/javascript';
    script.async = true;
    script.innerHTML = `
function _load_lib(url, callback){
  id =  'load_' + url;
  var s = document.createElement('script');
  s.src = url;
  s.id = id;
  s.async = true;
  s.onreadystatechange = s.onload = callback;
  s.onerror = function(){console.warn("failed to load library " + url);};
  document.getElementsByTagName("head")[0].appendChild(s);

}
// Load Libraries
  var rotationMatrix = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1.3]
  rotationMatrix = ChemDoodle.lib.mat4.rotate(rotationMatrix, -.8, [1,0,0]);
  rotationMatrix = ChemDoodle.lib.mat4.rotate(rotationMatrix, +.1, [0,0,1]);

  if(typeof cif_${this.props.uniqueId} === 'undefined' ) {
   let cif_${this.props.uniqueId}
  }
  if(typeof tfcanvas_${this.props.uniqueId} === 'undefined' ) {
   let tfcanvas_${this.props.uniqueId}
  }
  //Code
  tfcanvas_${this.props.uniqueId} = new ChemDoodle.TransformCanvas3D('${this.props.id}_view');
  cif_${this.props.uniqueId} = ChemDoodle.readCIF(\`${this.props.cifdata}\`,  ${this.props.x}, ${this.props.y}, ${this.props.z});
  if (typeof alpha_${this.props.uniqueId} === 'undefined') {
  let alpha_${this.props.uniqueId} = 0.;
  }
  if (typeof beta_${this.props.uniqueId} === 'undefined') {
  let beta_${this.props.uniqueId} = 0.;
  }
  if (typeof gamma_${this.props.uniqueId} === 'undefined') {
  let gamma_${this.props.uniqueId} = 0.;
  }

  if(typeof altLabels === 'undefined') {
    var altLabels
  }
  altLabels = ${JSON.stringify(this.props.altLabels)};
  cif_${this.props.uniqueId}.molecule.atoms.map(function(atom, i){
    if(altLabels.hasOwnProperty(i)) {
    atom.altLabel = altLabels[i];
    }
  });

  tfcanvas_${this.props.uniqueId}.specs.set3DRepresentation('Ball and Stick');
  tfcanvas_${this.props.uniqueId}.specs.backgroundColor = '${this.props.color}';
  tfcanvas_${this.props.uniqueId}.specs.projectionPerspective_3D = ${this.state.perspective};
  tfcanvas_${this.props.uniqueId}.specs.compass_display = true;
  tfcanvas_${this.props.uniqueId}.specs.compass_size_3D = 50;
  tfcanvas_${this.props.uniqueId}.specs.atoms_displayLabels_3D = true;
  tfcanvas_${this.props.uniqueId}.specs.crystals_unitCellLineWidth = 5;
  tfcanvas_${this.props.uniqueId}.specs.shapes_color = 'black';
  tfcanvas_${this.props.uniqueId}.specs.shapes_lineWidth = 1;
  tfcanvas_${this.props.uniqueId}.loadContent([cif_${this.props.uniqueId}.molecule], [cif_${this.props.uniqueId}.unitCell]);
  tfcanvas_${this.props.uniqueId}.rotationMatrix = rotationMatrix; tfcanvas_${this.props.uniqueId}.updateScene()

  window.addEventListener('deviceorientation', (e) => {

  /*ALPHA*/
  /*if(typeof alpha_${this.props.uniqueId} !== 'undefined') {*/
    /*if(.01 < Math.abs(alpha_${this.props.uniqueId} - e.alpha) < 1.5) {*/
    /*tfcanvas_${this.props.uniqueId}.rotationMatrix = ChemDoodle.lib.mat4.rotate(tfcanvas_${this.props.uniqueId}.rotationMatrix,(e.alpha -  alpha_${this.props.uniqueId}) * 0.015,  tfcanvas_${this.props.uniqueId}.rotationMatrix.slice(8, 11));*/
    /*}*/
  /*}*/

  /*GAMMA*/
  /*if (typeof gamma_${this.props.uniqueId} !== 'undefined') {*/
    /*if(.01 < Math.abs(gamma_${this.props.uniqueId} - e.gamma) < 1.5) {*/
  /*tfcanvas_${this.props.uniqueId}.rotationMatrix = ChemDoodle.lib.mat4.rotate(tfcanvas_${this.props.uniqueId}.rotationMatrix,(e.gamma -  gamma_${this.props.uniqueId}) * 0.015,  tfcanvas_${this.props.uniqueId}.rotationMatrix.slice(8, 11));*/
    /*}*/
  /*}*/

  /*BETA*/
  if (typeof beta_${this.props.uniqueId} !== 'undefined') {
    if(0.01 < Math.abs(beta_${this.props.uniqueId} - e.beta) < 1.5) {
  tfcanvas_${this.props.uniqueId}.rotationMatrix =  ChemDoodle.lib.mat4.rotate(tfcanvas_${this.props.uniqueId}.rotationMatrix, -(e.beta -  beta_${this.props.uniqueId}) * 0.015,  [1, 0, 0]);
    }
  }

  alpha_${this.props.uniqueId} = e.alpha;
  beta_${this.props.uniqueId} = e.beta;
  gamma_${this.props.uniqueId} = e.gamma;
   tfcanvas_${this.props.uniqueId}.updateScene()

  }, true);
    `;
    const item = document.getElementById(`${this.props.id}_view`);

    item.appendChild(script);
  }
  componentDidUpdate() {
    this.componentDidMount();
  }
  /* downloadStructure() {*/
  /* axios.get(url, params).then((response) => {*/
  /* const tempUrl = window.URL.createObjectURL(new Blob([response.data]));*/
  /* const link = document.createElement('a');*/
  /* link.href = tempUrl;*/
  /* link.setAttribute('download', `dft_input_${(new Date()).getTime()}.zip`);*/
  /* document.body.appendChild(link);*/
  /* link.click();*/
  /* }).catch(() => {*/
  /* });*/
  /* }*/
  render() {
    return (

        {isMobile === false ? null :
 <Md3dRotation />{'\u00A0\u00A0'} Tilt device to rotate.
 }
        <Paper height={14}>
          <p id={`${this.props.id}_script`} >
            <canvas
              id={`${this.props.id}_view`}
              height={this.props.height}
              width={this.props.width}
              style={{
                borderWidth: this.props.borderWidth,
                borderColor: '#000000',
                borderStyle: 'solid',
              }}
            />

        </Paper>
        {/*
        <Button
          raised
          className={this.props.classes.button}
        >
          <MdFullscreen /> Fullscreen
        </Button>
        <Button
          raised
          color="primary"
          className={this.props.classes.button}
          onClick={this.downloadStructure}>
          <MdFileDownload /> Download
        </Button>
        */}

    );
  }
}
GeometryCanvasCifdata.defaultProps = {
  height: Math.max(Math.min(window.innerWidth * 0.5, 600), 300),
  width: Math.max(Math.min(window.innerWidth * 0.5, 600), 300),
  color: '#fff',
  cifdata: '',
  cifurl: '',
  x: 2,
  y: 2,
  z: 1,
  borderWidth: 0,
  altLabels: {},
  perspective: true,
};

GeometryCanvasCifdata.propTypes = {
  uniqueId: PropTypes.string.isRequired,
  cifdata: PropTypes.string.isRequired,
  id: PropTypes.string.isRequired,
  height: PropTypes.number,
  width: PropTypes.number,
  color: PropTypes.string,
  x: PropTypes.number,
  y: PropTypes.number,
  z: PropTypes.number,
  borderWidth: PropTypes.number,
  altLabels: PropTypes.object,
  perspective: PropTypes.bool,
  cookies: instanceOf(Cookies).isRequired,
};

export default compose(
  withStyles(styles, { withTheme: true }),
  withCookies,
)(GeometryCanvasCifdata);

/* withStyles(styles, { withTheme: true })(*/
/* withCookies(*/
/* GeometryCanvasCifdata*/
/* )*/
/* );*/
<|endoftext|>


<commit_before>(function(global) {

    /**
     The FormValidator is used to validate forms.
     @status Experimental
     @param {Object} [settings={}] - the settings to configure the validator
     @param {Object} [settings.regex] - the regular expressions used to validate text based elements
     @returns {Object} The created form validator instance
     @example
     // example without using new
     var formValidator = app.util.FormValidator({
        regex: {
            email: /^[\w-]+([^@,\s\<\>\(\)]*[\w-]+)?\@[\w-]+(\.[\w-]+)*\.[a-z]{2,}$/i,
            numeric: /^[0-9]+$/
        }
     });

     // example using new
     var formValidator = new app.util.FormValidator({
        regex: {
            email: /^[\w-]+([^@,\s\<\>\(\)]*[\w-]+)?\@[\w-]+(\.[\w-]+)*\.[a-z]{2,}$/i,
            numeric: /^[0-9]+$/
        }
     });
     */
    function FormValidator(settings) {
        if (!(this instanceof FormValidator)) {
            return new FormValidator(settings);
        }

        settings = settings || {};

        this.getSettings = function() {
            return settings;
        };
    }

    /**
     Validates the passed specifications. Each spec should have a selector as key, and a value combined of type and rule properties.
     The type should be 'text' in case of input[type=text] or textarea, 'radio' in case of radio button group, 'select' in case of
     select box and 'checkbox' in case of checkbox group.  Each text rule is combined of type and errMsg. In case of 'text' based validations,
     the type value should match the key name of a given regex in FormValidator settings. In case of select boxes, radio buttons, checkboxes
     the rule property is omitted and a single errMsg is passed. The defaultValue property passed only in select box cases is needed to define
     the default select option which should not remain the same after the user's interaction.
     @param {Object} [specs={}] - the specifications to be validated
     @returns {Object} A jQuery Promise having as promise value the whole spec object in case of successful validation or the failed specs otherwise.
     @example
     var formValidator = app.util.FormValidator({
                    regex: {
                        email: /^[\w-]+([^@,\s\<\>\(\)]*[\w-]+)?\@[\w-]+(\.[\w-]+)*\.[a-z]{2,}$/i,
                        numeric: /^[0-9]+$/,
                        notEmpty: /\S+/
                    }
                });
     var specs = {
        '#email-field': {
            type: 'text',
            rules: [{
                    type: 'notEmpty',
                    errMsg: 'Empty text!'
                },{
                    type: 'email',
                    errMsg: 'Wrong email format!'
                },
            ]
        },
        '.streetNumber': {
            type: 'text',
            rules: [{
                type: 'numeric',
                errMsg: 'Wrong street number'
            }]
        },
        '.text-area': {
            type: 'text',
            rule: [{
                type: 'notEmpty',
                errMsg: 'Empty text!'
            }]
        },
        '.customer-type': {
            type: 'radio',
            errMsg: 'Not selected radio button!'
        },
        '.terms-of-use': {
            type: 'checkbox',
            errMsg: 'Not selected checkbox!'
        },
        '.gender': {
            type: 'select',
            defaultValue: 'test',
            errMsg: 'Not selected selectbox!'
        }
     };

     var promise = formValidator.validate( specs );

     */
    FormValidator.prototype.validate = function(specs) {
        specs = specs || {};

        var self = this,
            deferred = $.Deferred(),
            failedRules = [],
            $element, spec, rules,
            _isValidText = function(val, type) {
                var regex = self.getSettings().regex[type];
                return val && regex && regex.test(val);
            },
            _reportFailedSpec = function(selector, errorMsg) {
                failedRules.push({
                    selector: selector,
                    errMsg: errorMsg
                });
            };

        Object
            .keys(specs)
            .forEach(function(elementSelector) {
                $element = $(elementSelector);
                spec = specs[elementSelector];
                if ($element.length) {
                    if (spec.type === 'text' && spec.rules.length > 0) {
                        $(spec.rules).each(function(index, rule) {
                            if (!(_isValidText($element.val(), rule.type))) {
                                _reportFailedSpec(elementSelector, rule.errMsg);
                                return false;
                            }
                        });
                    } else if (spec.type === 'checkbox' || spec.type === 'radio') {
                        if (!($element.is(':checked'))) {
                            _reportFailedSpec(elementSelector, spec.errMsg);
                        }
                    } else if (spec.type === 'select') {
                        if ($element.val() === spec.defaultValue) {
                            _reportFailedSpec(elementSelector, spec.errMsg);
                        }
                    }
                }
            });

        if (failedRules.length) {
            deferred.reject(failedRules);
        } else {
            deferred.resolve(specs);
        }

        return deferred.promise();
    };

    global.app = global.app || {};
    global.app.util = global.app.util || {};
    global.app.util.FormValidator = FormValidator;

})(window);<commit_msg>Update FormValidator documentation<commit_after>(function(global) {

    /**
     The FormValidator is used to validate forms.
     @status Experimental
     @param {Object} [settings={}] - the settings to configure the validator
     @param {Object} [settings.regex] - the regular expressions used to validate text based elements
     @returns {Object} The created form validator instance
     @example
     // example without using new
     var formValidator = app.util.FormValidator({
        regex: {
            email: /^[\w-]+([^@,\s\<\>\(\)]*[\w-]+)?\@[\w-]+(\.[\w-]+)*\.[a-z]{2,}$/i,
            numeric: /^[0-9]+$/
        }
     });

     // example using new
     var formValidator = new app.util.FormValidator({
        regex: {
            email: /^[\w-]+([^@,\s\<\>\(\)]*[\w-]+)?\@[\w-]+(\.[\w-]+)*\.[a-z]{2,}$/i,
            numeric: /^[0-9]+$/
        }
     });
     */
    function FormValidator(settings) {
        if (!(this instanceof FormValidator)) {
            return new FormValidator(settings);
        }

        settings = settings || {};

        this.getSettings = function() {
            return settings;
        };
    }

    /**
     Validates the passed specifications. All form specifications defining the validation rules, must have unique element selectors as property names e.g #email-field.
     Specification referring to text fields must have as property value the 'type' and 'rules' properties. The type property must have value equal to 'text'. The 'rules'
     property is an array of validation rules and each validation rule consists of 'type' and 'errMsg' properties. The type property should match the name of a regex key
     set in the FormValidator constructor. In cases of checkboxes and radio buttons validation the 'rules' property is not used. Only the 'type' and 'errMsg' properties
     are used in such cases. The 'type' property must have value equal to 'radio' in case of radio buttons and 'checkbox' in case of checkboxes. In case of select boxes
     the type property must have value equal to 'select'. Additionally, the specification must contain the 'defaultValue' property which defines the default value
     of the select box so that the library can understand whether the value has been changed or not. A detailed exmaple can be found below, as well as inside the unit
     tests file.
     @param {Object} [specs={}] - the specifications to be validated
     @returns {Object} A jQuery Promise having as promise value the whole spec object in case of successful validation or the failed specs otherwise.
     @example
     var formValidator = app.util.FormValidator({
                    regex: {
                        email: /^[\w-]+([^@,\s\<\>\(\)]*[\w-]+)?\@[\w-]+(\.[\w-]+)*\.[a-z]{2,}$/i,
                        numeric: /^[0-9]+$/,
                        notEmpty: /\S+/
                    }
                });
     var specs = {
        '#email-field': {
            type: 'text',
            rules: [{
                    type: 'notEmpty',
                    errMsg: 'Empty text!'
                },{
                    type: 'email',
                    errMsg: 'Wrong email format!'
                },
            ]
        },
        '.streetNumber': {
            type: 'text',
            rules: [{
                type: 'numeric',
                errMsg: 'Wrong street number'
            }]
        },
        '.text-area': {
            type: 'text',
            rule: [{
                type: 'notEmpty',
                errMsg: 'Empty text!'
            }]
        },
        '.customer-type': {
            type: 'radio',
            errMsg: 'Not selected radio button!'
        },
        '.terms-of-use': {
            type: 'checkbox',
            errMsg: 'Not selected checkbox!'
        },
        '.gender': {
            type: 'select',
            defaultValue: 'test',
            errMsg: 'Not selected selectbox!'
        }
     };

     var promise = formValidator.validate( specs );

     */
    FormValidator.prototype.validate = function(specs) {
        specs = specs || {};

        var self = this,
            deferred = $.Deferred(),
            failedRules = [],
            $element, spec, rules,
            _isValidText = function(val, type) {
                var regex = self.getSettings().regex[type];
                return val && regex && regex.test(val);
            },
            _reportFailedSpec = function(selector, errorMsg) {
                failedRules.push({
                    selector: selector,
                    errMsg: errorMsg
                });
            };

        Object
            .keys(specs)
            .forEach(function(elementSelector) {
                $element = $(elementSelector);
                spec = specs[elementSelector];
                if ($element.length) {
                    if (spec.type === 'text' && spec.rules.length > 0) {
                        $(spec.rules).each(function(index, rule) {
                            if (!(_isValidText($element.val(), rule.type))) {
                                _reportFailedSpec(elementSelector, rule.errMsg);
                                return false;
                            }
                        });
                    } else if (spec.type === 'checkbox' || spec.type === 'radio') {
                        if (!($element.is(':checked'))) {
                            _reportFailedSpec(elementSelector, spec.errMsg);
                        }
                    } else if (spec.type === 'select') {
                        if ($element.val() === spec.defaultValue) {
                            _reportFailedSpec(elementSelector, spec.errMsg);
                        }
                    }
                }
            });

        if (failedRules.length) {
            deferred.reject(failedRules);
        } else {
            deferred.resolve(specs);
        }

        return deferred.promise();
    };

    global.app = global.app || {};
    global.app.util = global.app.util || {};
    global.app.util.FormValidator = FormValidator;

})(window);<|endoftext|>


<commit_before>var child_process = require('child_process')
var fs = require('fs');
var max_sleep = 300
var step = 10
//Added a comment that achieves no real goal.
//Non-blocking loop
//Adjustable step
//Status line
//Add a rough time indicator
//First cut at libfaketime support

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error",
  "Almost there",
  "Nearly got it",
  "Not quite working",
  "Ooops!",
  "Did I do that?",
  "Commit all the required changes",
  "Really commit all the required changes",
  "Should work now",
  "Back out the last commit",
  "Reverting changes",
  "One more time...",
  "Re-commiting last",
  "One more User Story done",
  "Can work my way through the Kanban",
  "Sprint complete",
  "Well that seemed pretty easy",
  "What do you mean you can't pack up the commit?",
  "Merge in master",
  "Fast-forwarding changes"
]

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (inFile == outFile) {
    console.error("Aborted: infile and outfile must be different")
    return(-1);
  }
  if (process.argv [ 4 ]) max_sleep = process.argv [ 4 ]
  if (process.argv [ 5 ]) step = parseInt(process.argv [ 5 ])
  console.info("Writing from %s to %s, with up to %s seconds between commits of %s bytes", inFile, outFile, max_sleep, step)
  var outFD = fs.openSync(outFile, 'w')
  fs.readFile(inFile, function(err,data) {
    var length = data.length
    var commit_count = Math.ceil(length / step)
    var commit_time = commit_count * max_sleep / 2
    var commit_time_hour = Math.floor(commit_time / 3600)
    var commit_time_rem = commit_time - (commit_time_hour * 3600)
    var commit_time_min = Math.floor(commit_time_rem / 60)
    var commit_time_sec = commit_time_rem - (commit_time_min * 60)
    console.info("Input file is %s Bytes, this will generate %s commits and take approximately %s hours %s minutes %s seconds", length, commit_count, commit_time_hour, commit_time_min, commit_time_sec)
    var t_offset = 0
    if (process.env.FAKETIME) {
      // 20% buffer, to reduce the likelihood of going in to the future
      t_offset = commit_time * -1.2;
      faketime(t_offset);
    }
    try {
      child_process.execFileSync('git', ['add', outFile])
    } catch (e) {
      console.error("Couldn't add %s to git: %s", outFile, e)
    }
    var counter = 0
    process.stdout.write("Queueing up the first commit...\r");
    var timeout;
    if (process.env.FAKETIME) {
      faketime(t_offset);
      timeout = 20;
    } else {
      timeout = randomIntFromInterval(0, max_sleep) * 1000
    }
    setTimeout(commit, timeout, t_offset, outFD, outFile, data, counter, length);
  })
} else {
  console.info("Usage:")
  console.info("node commit.js infile outfile [max_time_in_seconds] [step]")
}

function sleep(seconds) {
  var endTime = new Date().getTime() + (seconds * 1000);
  while (new Date().getTime() <= endTime) {;}
}

function randomIntFromInterval(min,max)
{
   return Math.floor(Math.random()*(max-min+1)+min);
}

function commit(t_offset, outFD, outFile, data, counter, length)
{
  if (counter < length)
  {
    var message = commit_messages[randomIntFromInterval(0, commit_messages.length - 1)]
    var args = ['commit', outFile, '-m', message]
    if (counter + step >= length) step = length -<commit_msg>Fixing an error introduced in the last commit<commit_after>var child_process = require('child_process')
var fs = require('fs');
var max_sleep = 300
var step = 10
//Added a comment that achieves no real goal.
//Non-blocking loop
//Adjustable step
//Status line
//Add a rough time indicator
//First cut at libfaketime support

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error",
  "Almost there",
  "Nearly got it",
  "Not quite working",
  "Ooops!",
  "Did I do that?",
  "Commit all the required changes",
  "Really commit all the required changes",
  "Should work now",
  "Back out the last commit",
  "Reverting changes",
  "One more time...",
  "Re-commiting last",
  "One more User Story done",
  "Can work my way through the Kanban",
  "Sprint complete",
  "Well that seemed pretty easy",
  "What do you mean you can't pack up the commit?",
  "Merge in master",
  "Fast-forwarding changes"
]

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (inFile == outFile) {
    console.error("Aborted: infile and outfile must be different")
    return(-1);
  }
  if (process.argv [ 4 ]) max_sleep = process.argv [ 4 ]
  if (process.argv [ 5 ]) step = parseInt(process.argv [ 5 ])
  console.info("Writing from %s to %s, with up to %s seconds between commits of %s bytes", inFile, outFile, max_sleep, step)
  var outFD = fs.openSync(outFile, 'w')
  fs.readFile(inFile, function(err,data) {
    var length = data.length
    var commit_count = Math.ceil(length / step)
    var commit_time = commit_count * max_sleep / 2
    var commit_time_hour = Math.floor(commit_time / 3600)
    var commit_time_rem = commit_time - (commit_time_hour * 3600)
    var commit_time_min = Math.floor(commit_time_rem / 60)
    var commit_time_sec = commit_time_rem - (commit_time_min * 60)
    console.info("Input file is %s Bytes, this will generate %s commits and take approximately %s hours %s minutes %s seconds", length, commit_count, commit_time_hour, commit_time_min, commit_time_sec)
    var t_offset = 0
    if (process.env.FAKETIME) {
      // 20% buffer, to reduce the likelihood of going in to the future
      t_offset = commit_time * -1.2;
      faketime(t_offset);
    }
    try {
      child_process.execFileSync('git', ['add', outFile])
    } catch (e) {
      console.error("Couldn't add %s to git: %s", outFile, e)
    }
    var counter = 0
    process.stdout.write("Queueing up the first commit...\r");
    var timeout;
    if (process.env.FAKETIME) {
      faketime(t_offset);
      timeout = 20;
    } else {
      timeout = randomIntFromInterval(0, max_sleep) * 1000
    }
    setTimeout(commit, timeout, t_offset, outFD, outFile, data, counter, length);
  })
} else {
  console.info("Usage:")
  console.info("node commit.js infile outfile [max_time_in_seconds] [step]")
}

function sleep(seconds) {
  var endTime = new Date().getTime() + (seconds * 1000);
  while (new Date().getTime() <= endTime) {;}
}

function randomIntFromInterval(min,max)
{
   return Math.floor(Math.random()*(max-min+1)+min);
}

function commit(t_offset, outFD, outFile, data, counter, length)
{
  if (counter < length)
  {
    var message = commit_messages[randomIntFromInterval(0, commit_messages.length - 1)]
    var args = ['commit', outFile, '-m', message]
    if (counter + step >= length) step = length - <|endoftext|>


<commit_before>define(
  'ephox.alloy.keying.SpecialType',

  [
    'ephox.alloy.alien.Keys',
    'ephox.alloy.data.Fields',
    'ephox.alloy.keying.KeyingType',
    'ephox.alloy.navigation.KeyMatch',
    'ephox.alloy.navigation.KeyRules',
    'ephox.boulder.api.FieldSchema',
    'ephox.katamari.api.Fun',
    'ephox.katamari.api.Option'
  ],

  function (Keys, Fields, KeyingType, KeyMatch, KeyRules, FieldSchema, Fun, Option) {
    var schema = [
      Fields.onKeyboardHandler('onSpace'),
      Fields.onKeyboardHandler('onEnter'),
      Fields.onKeyboardHandler('onShiftEnter'),
      Fields.onKeyboardHandler('onLeft'),
      Fields.onKeyboardHandler('onRight'),
      Fields.onKeyboardHandler('onUp'),
      Fields.onKeyboardHandler('onDown'),
      Fields.onKeyboardHandler('onEscape'),
      FieldSchema.option('focusIn')
    ];

    var getRules = function (component, simulatedEvent, executeInfo) {
      return [
        KeyRules.rule( KeyMatch.inSet(Keys.SPACE()), executeInfo.onSpace()),
        KeyRules.rule(
          KeyMatch.and([ KeyMatch.isNotShift, KeyMatch.inSet( Keys.ENTER()) ]), executeInfo.onEnter()
        ),
        KeyRules.rule(
          KeyMatch.and([ KeyMatch.isShift, KeyMatch.inSet( Keys.ENTER()) ]), executeInfo.onShiftEnter()
        ),
        KeyRules.rule( KeyMatch.inSet(Keys.UP()), executeInfo.onUp()),
        KeyRules.rule( KeyMatch.inSet(Keys.DOWN()), executeInfo.onDown()),
        KeyRules.rule( KeyMatch.inSet(Keys.LEFT()), executeInfo.onLeft()),
        KeyRules.rule( KeyMatch.inSet(Keys.RIGHT()), executeInfo.onRight()),
        KeyRules.rule( KeyMatch.inSet(Keys.SPACE()), executeInfo.onSpace()),
        KeyRules.rule( KeyMatch.inSet(Keys.ESCAPE()), executeInfo.onEscape())
      ];
    };

    var focusIn = function (component, executeInfo) {
      return executeInfo.focusIn().bind(function (f) {
        return f(component, executeInfo);
      });
    };

    var getEvents = Fun.constant({ });
    var getApis = Fun.constant({ });

    return KeyingType.typical(schema, getRules, getEvents, getApis, Option.some(focusIn));
  }
);<commit_msg>adding tab and shift tab to special keying type<commit_after>define(
  'ephox.alloy.keying.SpecialType',

  [
    'ephox.alloy.alien.Keys',
    'ephox.alloy.data.Fields',
    'ephox.alloy.keying.KeyingType',
    'ephox.alloy.navigation.KeyMatch',
    'ephox.alloy.navigation.KeyRules',
    'ephox.boulder.api.FieldSchema',
    'ephox.katamari.api.Fun',
    'ephox.katamari.api.Option'
  ],

  function (Keys, Fields, KeyingType, KeyMatch, KeyRules, FieldSchema, Fun, Option) {
    var schema = [
      Fields.onKeyboardHandler('onSpace'),
      Fields.onKeyboardHandler('onEnter'),
      Fields.onKeyboardHandler('onShiftEnter'),
      Fields.onKeyboardHandler('onLeft'),
      Fields.onKeyboardHandler('onRight'),
      Fields.onKeyboardHandler('onTab'),
      Fields.onKeyboardHandler('onShiftTab'),
      Fields.onKeyboardHandler('onUp'),
      Fields.onKeyboardHandler('onDown'),
      Fields.onKeyboardHandler('onEscape'),
      FieldSchema.option('focusIn')
    ];

    var getRules = function (component, simulatedEvent, executeInfo) {
      return [
        KeyRules.rule( KeyMatch.inSet(Keys.SPACE()), executeInfo.onSpace()),
        KeyRules.rule(
          KeyMatch.and([ KeyMatch.isNotShift, KeyMatch.inSet( Keys.ENTER()) ]), executeInfo.onEnter()
        ),
        KeyRules.rule(
          KeyMatch.and([ KeyMatch.isShift, KeyMatch.inSet( Keys.ENTER()) ]), executeInfo.onShiftEnter()
        ),
        KeyRules.rule(
          KeyMatch.and([ KeyMatch.isShift, KeyMatch.inSet( Keys.TAB()) ]), executeInfo.onShiftTab()
        ),
        KeyRules.rule(
          KeyMatch.and([ KeyMatch.isNotShift, KeyMatch.inSet( Keys.TAB()) ]), executeInfo.onTab()
        ),

        KeyRules.rule( KeyMatch.inSet(Keys.UP()), executeInfo.onUp()),
        KeyRules.rule( KeyMatch.inSet(Keys.DOWN()), executeInfo.onDown()),
        KeyRules.rule( KeyMatch.inSet(Keys.LEFT()), executeInfo.onLeft()),
        KeyRules.rule( KeyMatch.inSet(Keys.RIGHT()), executeInfo.onRight()),
        KeyRules.rule( KeyMatch.inSet(Keys.SPACE()), executeInfo.onSpace()),
        KeyRules.rule( KeyMatch.inSet(Keys.ESCAPE()), executeInfo.onEscape())
      ];
    };

    var focusIn = function (component, executeInfo) {
      return executeInfo.focusIn().bind(function (f) {
        return f(component, executeInfo);
      });
    };

    var getEvents = Fun.constant({ });
    var getApis = Fun.constant({ });

    return KeyingType.typical(schema, getRules, getEvents, getApis, Option.some(focusIn));
  }
);<|endoftext|>


<commit_before>var fs = require('fs');
var child_process = require('child_process')
var max_sleep = 300

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (process.argv [ 4 ]) max_sleep = process.argv [ 4 ]
  console.info("Writing from %s to %s, with up to %s seconds between commits", inFile, outFile, max_sleep)
  var outFD = fs.openSync(outFile, 'w')
  fs.readFile(inFile, function(err,data) {
    var length = data.length
    console.info("Bytes: %s", length)
    try {
      child_process.execFileSync('/usr/bin/git', ['add', outFile])
    } catch (e) {
      console.error("Couldn't add %s to git: %s", outFile, e)
    <commit_msg>Update character<commit_after>var fs = require('fs');
var child_process = require('child_process')
var max_sleep = 300

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (process.argv [ 4 ]) max_sleep = process.argv [ 4 ]
  console.info("Writing from %s to %s, with up to %s seconds between commits", inFile, outFile, max_sleep)
  var outFD = fs.openSync(outFile, 'w')
  fs.readFile(inFile, function(err,data) {
    var length = data.length
    console.info("Bytes: %s", length)
    try {
      child_process.execFileSync('/usr/bin/git', ['add', outFile])
    } catch (e) {
      console.error("Couldn't add %s to git: %s", outFile, e)
    }<|endoftext|>


<commit_before>/**
 * Experience Sampling event page.
 *
 * This background page handles the various events for registering participants
 * and showing new surveys in response to API events.
 *
 * Participants must fill out both a consent form and a startup survey (with
 * demographics) before they can begin to answer real survey questions.
 */

var cesp = {};  // namespace variable

cesp.readyForSurveys = false;
cesp.operatingSystem = "";

// Settings.
cesp.SERVER_URL = 'https://chrome-experience-sampling.appspot.com';
cesp.SUBMIT_SURVEY_ACTION = '/_ah/api/cesp/v1/submitsurvey';
cesp.XHR_TIMEOUT = 4000;
cesp.NOTIFICATION_TITLE = 'New Chrome survey available!';
cesp.NOTIFICATION_BODY = 'Your feedback makes Chrome better.';
cesp.NOTIFICATION_BUTTON = 'Take survey!';
cesp.ICON_FILE = 'icon.png';
cesp.NOTIFICATION_DEFAULT_TIMEOUT = 10;  // minutes
cesp.NOTIFICATION_TAG = 'chromeSurvey';
cesp.ALARM_NAME = 'notificationTimeout';

// SETUP

/**
 * Sets up basic state for the extension. Called when extension is installed.
 */
function setupState() {
  chrome.storage.local.set({'pending_responses': []});
  chrome.runtime.getPlatformInfo(function(platformInfo) {
    cesp.operatingSystem = platformInfo.os;
  });
}

/**
 * Retrieves the registration status from Local Storage.
 */
function getConsentStatus() {
  chrome.storage.local.get(constants.CONSENT_KEY, maybeShowConsentForm);
}

/**
 * Checks whether consent has been granted yet; if not, opens the consent form.
 * @param {object} consentLookup Object containing consent status (or empty).
 */
function maybeShowConsentForm(consentLookup) {
  if (!consentLookup || consentLookup[constants.CONSENT_KEY] == null ||
      consentLookup[constants.CONSENT_KEY] == constants.CONSENT_PENDING) {
    chrome.storage.onChanged.addListener(storageUpdated);
    chrome.tabs.create({'url': chrome.extension.getURL('consent.html')});
  } else if (consentLookup[constants.CONSENT_KEY] ==
             constants.CONSENT_REJECTED) {
    chrome.management.uninstallSelf();
  } else if (consentLookup[constants.CONSENT_KEY] ==
             constants.CONSENT_GRANTED) {
    // Someone might have filled out the consent form previously but not
    // filled out the setup survey. Check to see if that's the case.
    chrome.storage.local.get(constants.SETUP_KEY, maybeShowSetupSurvey);
  }
}

/**
 * Checks whether the setup survey has been completed yet. If it has been, we
 * are now ready to start showing surveys. If not, we need to listen for
 * when it's completed.
 * @param {object} setupLookup Object containing setup survey status (or empty).
 */
function maybeShowSetupSurvey(setupLookup) {
  if (!setupLookup || setupLookup[constants.SETUP_KEY] == null ||
      setupLookup[constants.SETUP_KEY] == constants.SETUP_PENDING) {
    chrome.tabs.create({'url': chrome.extension.getURL('surveys/setup.html')});
  } else if (setupLookup[constants.SETUP_KEY] == constants.SETUP_COMPLETED) {
    cesp.readyForSurveys = true;
  }
}

/**
 * Listens for the setup survey submission. When that happens, signals that
 * the experience sampling is now ready to begin.
 * @param {object} changes The changed portions of the database.
 * @param {string} areaName The name of the storage area.
 */
function storageUpdated(changes, areaName) {
  if (changes && changes[constants.SETUP_KEY] &&
      changes[constants.SETUP_KEY].newValue == constants.SETUP_COMPLETED) {
    cesp.readyForSurveys = true;
  }
}

// Performs consent and registration checks on startup and install.
chrome.runtime.onInstalled.addListener(getConsentStatus);
chrome.runtime.onStartup.addListener(getConsentStatus);
chrome.runtime.onInstalled.addListener(setupState);

// SURVEY HANDLING

/**
 * Clears our existing notification(s).
 */
function clearNotifications(unused) {
  chrome.notifications.clear(cesp.NOTIFICATION_TAG, function(unused) {});
  chrome.alarms.clearAll();
}

/**
 * Creates a new notification to prompt the participant to take an experience
 * sampling survey.
 * @param {object} element The browser element of interest.
 * @param {object} decision The decision the participant made.
 */
function showSurveyNotification(element, decision) {
  if (!cesp.readyForSurveys) return;
  clearNotifications();

  var timePromptShown = new Date();
  var clickHandler = function(unused) {
    var timePromptClicked = new Date();
    loadSurvey(element, decision, timePromptShown, timePromptClicked);
    clearNotifications();
  };

  var opt = {
    type: 'basic',
    iconUrl: cesp.ICON_FILE,
    title: cesp.NOTIFICATION_TITLE,
    message: cesp.NOTIFICATION_BODY,
    eventTime: Date.now(),
    buttons: [{title: cesp.NOTIFICATION_BUTTON}]
  };
  chrome.notifications.create(
      cesp.NOTIFICATION_TAG,
      opt,
      function(id) {
        chrome.alarms.create(
            cesp.ALARM_NAME,
            {delayInMinutes: cesp.NOTIFICATION_DEFAULT_TIMEOUT});
      });
  chrome.notifications.onClicked.addListener(clickHandler);
  chrome.notifications.onButtonClicked.addListener(clickHandler);
}

/**
 * Creates a new tab with the experience sampling survey page.
 * @param {object} element The browser element of interest.
 * @param {object} decision The decision the participant made.
 * @param {object} timePromptShown Date object of when the survey prompt
 *     notification was shown to the participant.
 * @param {object} timePromptClicked Date object of when the participant
 *     clicked the survey prompt notification.
 */
function loadSurvey(element, decision, timePromptShown, timePromptClicked) {
  if (!cesp.readyForSurveys) return;

  var surveyLocations = {
    SSL: 'ssl.html',
    EXAMPLE: 'survey-example.html'
  };
  var surveyURL;
  var eventType = constants.FindEventType(element['name']);
  switch (eventType) {
    case constants.EventType.SSL:
      surveyURL = surveyLocations.SSL;
      break;
    case constants.EventType.UNKNOWN:
      surveyURL = surveyLocations.EXAMPLE;
      console.log('Unknown event type: ' + element['name']);
      break;
  }
  chrome.tabs.create(
      {'url': chrome.extension.getURL('surveys/' + surveyURL)},
      function() { console.log('Opened survey.'); });
}

// Trigger the new survey prompt when the participant makes a decision about an
// experience sampling element.
chrome.experienceSamplingPrivate.onDecision.addListener(showSurveyNotification);
// Clear the notification state when the survey times out.
chrome.alarms.onAlarm.addListener(clearNotifications);

/**
 * A survey response (question and answer).
 * @constructor
 * @param {string} question The question being answered.
 * @param {string} answer The answer to that question.
 */
function Response(question, answer) {
  this.question = question;
  this.answer = answer;
}

/**
 * A completed survey.
 * @constructor
 * @param {string} type The type of survey.
 * @param {int} participantId The participant ID.
 * @param {Date} dateTaken The date and time when the survey was taken.
 * @param {Array.Response} responses An array of Response objects.
*/
function Survey(type, participantId, dateTaken, responses) {
  this.type = type;
  this.participantId = participantId;
  this.dateTaken = dateTaken;
  this.responses = responses;
}

/**
 * Sends a survey to the CESP backend via XHR.
 * @param {Survey} survey The completed survey to send to the backend.
 * @param {function(string)} successCallback A function to call on receiving a
 *     successful response (HTTP 204). It should look like
 *     "function(response) {...};" where "response" is the text of the response
 *     (if there is any).
 * @param {function(!number=)} errorCallback A function to call on receiving an
 *     error from the server, or on timing out. It should look like
 *     "function(status) {...};" where "status" is an HTTP status code integer,
 *     if there is one. For a timeout, there is no status.
 */
function sendSurvey(survey, successCallback, errorCallback) {
  var url = cesp.SERVER_URL + cesp.SUBMIT_SURVEY_ACTION;
  var method = "POST";
  var dateTaken = survey.dateTaken.toISOString();
  // Get rid of timezone "Z" on end of ISO String for AppEngine compatibility.
  if (dateTaken.slice(-1) === "Z") {
    dateTaken = dateTaken.slice(0, -1);
  }
  var data = {
    "date_taken": dateTaken,
    "participant_id": survey.participantId,
    "responses": [],
    "survey_type": survey.type
  };
  for (var i = 0; i < survey.responses.length; i++) {
    data.responses.push(survey.responses[i]);
  }
  var xhr = new XMLHttpRequest();
  function onLoadHandler(event) {
    if (xhr.readyState === 4) {
      if (xhr.status === 204) {
        successCallback(xhr.response);
      } else {
        errorCallback(xhr.status);
      }
    }
  }
  function onErrorHandler(event) {
    errorCallback(xhr.status);
  }
  function onTimeoutHandler(event) {
    errorCallback();
  }
  xhr.open(method, url, true);
  xhr.setRequestHeader('Content-Type', 'application/JSON');
  xhr.timeout = cesp.XHR_TIMEOUT;
  xhr.onload = onLoadHandler;
  xhr.onerror = onErrorHandler;
  xhr.ontimeout = onTimeoutHandler;
  xhr.send(JSON.stringify(data));
}
<commit_msg>Add a check to showSurveyNotification to only proceed if we're under some maximum number of surveys to show each day.<commit_after>/**
 * Experience Sampling event page.
 *
 * This background page handles the various events for registering participants
 * and showing new surveys in response to API events.
 *
 * Participants must fill out both a consent form and a startup survey (with
 * demographics) before they can begin to answer real survey questions.
 */

var cesp = {};  // namespace variable

cesp.readyForSurveys = false;
cesp.operatingSystem = "";

// Settings.
cesp.SERVER_URL = 'https://chrome-experience-sampling.appspot.com';
cesp.SUBMIT_SURVEY_ACTION = '/_ah/api/cesp/v1/submitsurvey';
cesp.XHR_TIMEOUT = 4000;
cesp.NOTIFICATION_TITLE = 'New Chrome survey available!';
cesp.NOTIFICATION_BODY = 'Your feedback makes Chrome better.';
cesp.NOTIFICATION_BUTTON = 'Take survey!';
cesp.ICON_FILE = 'icon.png';
cesp.NOTIFICATION_DEFAULT_TIMEOUT = 10;  // minutes
cesp.NOTIFICATION_TAG = 'chromeSurvey';
cesp.ALARM_NAME = 'notificationTimeout';

// SETUP

/**
 * Sets up basic state for the extension. Called when extension is installed.
 */
function setupState() {
  chrome.storage.local.set({'pending_responses': []});
  chrome.runtime.getPlatformInfo(function(platformInfo) {
    cesp.operatingSystem = platformInfo.os;
  });
  // Set the count of surveys shown to 0, and reset it each day.
  chrome.storage.local.set({cesp.SURVEYS_SHOWN_TODAY: 0});
  chrome.alarms.create(cesp.SURVEY_THROTTLE_RESET_ALARM,
      {delayInMinutes: 5, periodInMinutes: 1440});
}

/**
 * Retrieves the registration status from Local Storage.
 */
function getConsentStatus() {
  chrome.storage.local.get(constants.CONSENT_KEY, maybeShowConsentForm);
}

/**
 * Checks whether consent has been granted yet; if not, opens the consent form.
 * @param {object} consentLookup Object containing consent status (or empty).
 */
function maybeShowConsentForm(consentLookup) {
  if (!consentLookup || consentLookup[constants.CONSENT_KEY] == null ||
      consentLookup[constants.CONSENT_KEY] == constants.CONSENT_PENDING) {
    chrome.storage.onChanged.addListener(storageUpdated);
    chrome.tabs.create({'url': chrome.extension.getURL('consent.html')});
  } else if (consentLookup[constants.CONSENT_KEY] ==
             constants.CONSENT_REJECTED) {
    chrome.management.uninstallSelf();
  } else if (consentLookup[constants.CONSENT_KEY] ==
             constants.CONSENT_GRANTED) {
    // Someone might have filled out the consent form previously but not
    // filled out the setup survey. Check to see if that's the case.
    chrome.storage.local.get(constants.SETUP_KEY, maybeShowSetupSurvey);
  }
}

/**
 * Checks whether the setup survey has been completed yet. If it has been, we
 * are now ready to start showing surveys. If not, we need to listen for
 * when it's completed.
 * @param {object} setupLookup Object containing setup survey status (or empty).
 */
function maybeShowSetupSurvey(setupLookup) {
  if (!setupLookup || setupLookup[constants.SETUP_KEY] == null ||
      setupLookup[constants.SETUP_KEY] == constants.SETUP_PENDING) {
    chrome.tabs.create({'url': chrome.extension.getURL('surveys/setup.html')});
  } else if (setupLookup[constants.SETUP_KEY] == constants.SETUP_COMPLETED) {
    cesp.readyForSurveys = true;
  }
}

/**
 * Listens for the setup survey submission. When that happens, signals that
 * the experience sampling is now ready to begin.
 * @param {object} changes The changed portions of the database.
 * @param {string} areaName The name of the storage area.
 */
function storageUpdated(changes, areaName) {
  if (changes && changes[constants.SETUP_KEY] &&
      changes[constants.SETUP_KEY].newValue == constants.SETUP_COMPLETED) {
    cesp.readyForSurveys = true;
  }
}

// Performs consent and registration checks on startup and install.
chrome.runtime.onInstalled.addListener(getConsentStatus);
chrome.runtime.onStartup.addListener(getConsentStatus);
chrome.runtime.onInstalled.addListener(setupState);

// SURVEY HANDLING

/**
 * Clears our existing notification(s).
 */
function clearNotifications(unused) {
  chrome.notifications.clear(cesp.NOTIFICATION_TAG, function(unused) {});
  chrome.alarms.clearAll();
}

/**
 * Creates a new notification to prompt the participant to take an experience
 * sampling survey.
 * @param {object} element The browser element of interest.
 * @param {object} decision The decision the participant made.
 */
function showSurveyNotification(element, decision) {
  if (!cesp.readyForSurveys) return;

  chrome.storage.local.get(cesp.SURVEYS_SHOWN_TODAY, function(items) {
    if (items[cesp.SURVEYS_SHOWN_TODAY] >= cesp.MAX_SURVEYS_PER_DAY) {
      return;
    }

    clearNotifications();

    var timePromptShown = new Date();
    var clickHandler = function(unused) {
      var timePromptClicked = new Date();
      loadSurvey(element, decision, timePromptShown, timePromptClicked);
      clearNotifications();
    };

    var opt = {
      type: 'basic',
      iconUrl: cesp.ICON_FILE,
      title: cesp.NOTIFICATION_TITLE,
      message: cesp.NOTIFICATION_BODY,
      eventTime: Date.now(),
      buttons: [{title: cesp.NOTIFICATION_BUTTON}]
    };
    chrome.notifications.create(
        cesp.NOTIFICATION_TAG,
        opt,
        function(id) {
          chrome.alarms.create(
              cesp.ALARM_NAME,
              {delayInMinutes: cesp.NOTIFICATION_DEFAULT_TIMEOUT});
        });
    chrome.notifications.onClicked.addListener(clickHandler);
    chrome.notifications.onButtonClicked.addListener(clickHandler);

    chrome.storage.local.set({
      cesp.SURVEYS_SHOWN_TODAY: items[cesp.SURVEYS_SHOWN_TODAY] + 1
    });
  }
}

/**
 * Creates a new tab with the experience sampling survey page.
 * @param {object} element The browser element of interest.
 * @param {object} decision The decision the participant made.
 * @param {object} timePromptShown Date object of when the survey prompt
 *     notification was shown to the participant.
 * @param {object} timePromptClicked Date object of when the participant
 *     clicked the survey prompt notification.
 */
function loadSurvey(element, decision, timePromptShown, timePromptClicked) {
  if (!cesp.readyForSurveys) return;

  var surveyLocations = {
    SSL: 'ssl.html',
    EXAMPLE: 'survey-example.html'
  };
  var surveyURL;
  var eventType = constants.FindEventType(element['name']);
  switch (eventType) {
    case constants.EventType.SSL:
      surveyURL = surveyLocations.SSL;
      break;
    case constants.EventType.UNKNOWN:
      surveyURL = surveyLocations.EXAMPLE;
      console.log('Unknown event type: ' + element['name']);
      break;
  }
  chrome.tabs.create(
      {'url': chrome.extension.getURL('surveys/' + surveyURL)},
      function() { console.log('Opened survey.'); });
}

// Trigger the new survey prompt when the participant makes a decision about an
// experience sampling element.
chrome.experienceSamplingPrivate.onDecision.addListener(showSurveyNotification);
// Clear the notification state when the survey times out.
chrome.alarms.onAlarm.addListener(clearNotifications);

/**
 * A survey response (question and answer).
 * @constructor
 * @param {string} question The question being answered.
 * @param {string} answer The answer to that question.
 */
function Response(question, answer) {
  this.question = question;
  this.answer = answer;
}

/**
 * A completed survey.
 * @constructor
 * @param {string} type The type of survey.
 * @param {int} participantId The participant ID.
 * @param {Date} dateTaken The date and time when the survey was taken.
 * @param {Array.Response} responses An array of Response objects.
*/
function Survey(type, participantId, dateTaken, responses) {
  this.type = type;
  this.participantId = participantId;
  this.dateTaken = dateTaken;
  this.responses = responses;
}

/**
 * Sends a survey to the CESP backend via XHR.
 * @param {Survey} survey The completed survey to send to the backend.
 * @param {function(string)} successCallback A function to call on receiving a
 *     successful response (HTTP 204). It should look like
 *     "function(response) {...};" where "response" is the text of the response
 *     (if there is any).
 * @param {function(!number=)} errorCallback A function to call on receiving an
 *     error from the server, or on timing out. It should look like
 *     "function(status) {...};" where "status" is an HTTP status code integer,
 *     if there is one. For a timeout, there is no status.
 */
function sendSurvey(survey, successCallback, errorCallback) {
  var url = cesp.SERVER_URL + cesp.SUBMIT_SURVEY_ACTION;
  var method = "POST";
  var dateTaken = survey.dateTaken.toISOString();
  // Get rid of timezone "Z" on end of ISO String for AppEngine compatibility.
  if (dateTaken.slice(-1) === "Z") {
    dateTaken = dateTaken.slice(0, -1);
  }
  var data = {
    "date_taken": dateTaken,
    "participant_id": survey.participantId,
    "responses": [],
    "survey_type": survey.type
  };
  for (var i = 0; i < survey.responses.length; i++) {
    data.responses.push(survey.responses[i]);
  }
  var xhr = new XMLHttpRequest();
  function onLoadHandler(event) {
    if (xhr.readyState === 4) {
      if (xhr.status === 204) {
        successCallback(xhr.response);
      } else {
        errorCallback(xhr.status);
      }
    }
  }
  function onErrorHandler(event) {
    errorCallback(xhr.status);
  }
  function onTimeoutHandler(event) {
    errorCallback();
  }
  xhr.open(method, url, true);
  xhr.setRequestHeader('Content-Type', 'application/JSON');
  xhr.timeout = cesp.XHR_TIMEOUT;
  xhr.onload = onLoadHandler;
  xhr.onerror = onErrorHandler;
  xhr.ontimeout = onTimeoutHandler;
  xhr.send(JSON.stringify(data));
}
<|endoftext|>


<commit_before>const path = require('path');
const webpack = require('webpack');
const yamljs = require('yamljs');

let reportUrl = '';
try {
  reportUrl = yamljs.parseFile('installers/launcher-config-windows.yaml').reportServer;
} catch (e) {} // eslint-disable-line

module.exports = {
  devtool: 'cheap-source-map',
  entry: './source/main/index.js',
  output: {
    path: path.join(__dirname, './dist/main'),
    filename: 'index.js'
  },
  /**
   * Set targed to Electron speciffic node.js env.
   * https://github.com/chentsulin/webpack-target-electron-renderer#how-this-module-works
   */
  target: 'electron-main',
  cache: true,
  /**
   * Disables webpack processing of __dirname and __filename.
   * If you run the bundle in node.js it falls back to these values of node.js.
   * https://github.com/webpack/webpack/issues/2010
   */
  node: {
    __dirname: false,
    __filename: false,
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env.API': JSON.stringify(process.env.API || 'ada'),
      'process.env.NETWORK': JSON.stringify(process.env.NETWORK || 'development'),
      'process.env.MOBX_DEV_TOOLS': process.env.MOBX_DEV_TOOLS || 0,
      'process.env.DAEDALUS_VERSION': JSON.stringify(process.env.DAEDALUS_VERSION || 'dev'),
      'process.env.REPORT_URL': JSON.stringify(reportUrl),
      'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development'),
    }),
  ],
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        include: /source/,
        exclude: /source\/renderer/,
        use: {
          loader: 'babel-loader',
        },
      },
    ]
  },
};
<commit_msg>[DDW-169] Only bake in NODE_ENV value for production build<commit_after>const path = require('path');
const webpack = require('webpack');
const yamljs = require('yamljs');

let reportUrl = '';
try {
  reportUrl = yamljs.parseFile('installers/launcher-config-windows.yaml').reportServer;
} catch (e) {} // eslint-disable-line

module.exports = {
  devtool: 'cheap-source-map',
  entry: './source/main/index.js',
  output: {
    path: path.join(__dirname, './dist/main'),
    filename: 'index.js'
  },
  /**
   * Set targed to Electron speciffic node.js env.
   * https://github.com/chentsulin/webpack-target-electron-renderer#how-this-module-works
   */
  target: 'electron-main',
  cache: true,
  /**
   * Disables webpack processing of __dirname and __filename.
   * If you run the bundle in node.js it falls back to these values of node.js.
   * https://github.com/webpack/webpack/issues/2010
   */
  node: {
    __dirname: false,
    __filename: false,
  },
  plugins: [
    new webpack.DefinePlugin(Object.assign({
      'process.env.API': JSON.stringify(process.env.API || 'ada'),
      'process.env.NETWORK': JSON.stringify(process.env.NETWORK || 'development'),
      'process.env.MOBX_DEV_TOOLS': process.env.MOBX_DEV_TOOLS || 0,
      'process.env.DAEDALUS_VERSION': JSON.stringify(process.env.DAEDALUS_VERSION || 'dev'),
      'process.env.REPORT_URL': JSON.stringify(reportUrl),
   }, process.env.NODE_ENV === 'production' ? {
     // Only bake in NODE_ENV value for production build.
     // This is so that the test suite based on the webpack build will
     // choose the correct path to ca.crt (see setupTls.js).
     'process.env.NODE_ENV': 'production',
   } : {})),
  ],
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        include: /source/,
        exclude: /source\/renderer/,
        use: {
          loader: 'babel-loader',
        },
      },
    ]
  },
};
<|endoftext|>


<commit_before>import React from 'react';
import styled from 'styled-components';

const Wrapper = styled.div`
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.4);

  @media (min-width: 769px) {
    background-color: rgba(0, 0, 0, 0.1);
    -webkit-transition: all 3s ease-out 0.1s;
    -moz-transition: all 3s ease-out 0.1s;
    -o-transition: all 3s ease-out 0.1s;
    transition: all 3s ease-out 0.1s;
  }
`;

const propTypes = {
  children: React.PropTypes.node,
};

export class OpaqueLayer extends React.Component {

  constructor(props) {
    super(props);
    this.children = props.children;
    this.state = {
      hasFadedIn: false
    }
  }

  componentDidMount() {
    setInterval(
      () => this.fadeIn(),
      1000
    );
  }

  fadeIn() {
    if (!this.state.hasFadedIn) {
      this.node.style.setProperty('background-color', 'rgba(0, 0, 0, 0.4)');
    }
  }

  render() {
    return (
      <Wrapper
        innerRef={(node) => (this.node = node)}
      >
        {this.children}
      </Wrapper>
    );
  }
}

OpaqueLayer.propTypes = propTypes;

export default OpaqueLayer;
<commit_msg>quickfollow<commit_after>import React from 'react';
import styled from 'styled-components';

const Wrapper = styled.div`
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.4);

  @media (min-width: 769px) {
    background-color: rgba(0, 0, 0, 0.1);
    -webkit-transition: all 3s ease-out 0.1s;
    -moz-transition: all 3s ease-out 0.1s;
    -o-transition: all 3s ease-out 0.1s;
    transition: all 3s ease-out 0.1s;
  }
`;

const propTypes = {
  children: React.PropTypes.node,
};

export class OpaqueLayer extends React.Component {

  constructor(props) {
    super(props);
    this.children = props.children;
    this.state = {
      hasFadedIn: false,
    };
  }

  componentDidMount() {
    setInterval(
      () => this.fadeIn(),
      1000
    );
  }

  fadeIn() {
    if (!this.state.hasFadedIn) {
      this.node.style.setProperty('background-color', 'rgba(0, 0, 0, 0.4)');
    }
  }

  render() {
    return (
      <Wrapper
        innerRef={(node) => (this.node = node)}
      >
        {this.children}
      </Wrapper>
    );
  }
}

OpaqueLayer.propTypes = propTypes;

export default OpaqueLayer;
<|endoftext|>


<commit_before>'use strict';

var <%= objectName %> = require('./<%= fileName %>.model');

exports.register = function (socket) {

  <%= objectName %>.schema.post('save', function (doc) {
    socket.emit('<%= objectName %>:save', doc);
  });

  <%= objectName %>.schema.post('remove', function (doc) {
    socket.emit('<%= objectName %>:remove', doc);
  });

}
<commit_msg>fix(lint): missing semicolon<commit_after>'use strict';

var <%= objectName %> = require('./<%= fileName %>.model');

exports.register = function (socket) {

  <%= objectName %>.schema.post('save', function (doc) {
    socket.emit('<%= objectName %>:save', doc);
  });

  <%= objectName %>.schema.post('remove', function (doc) {
    socket.emit('<%= objectName %>:remove', doc);
  });

};
<|endoftext|>


<commit_before>// Util
function getRandomColor() {
	var letters = '0123456789ABCDEF';
	var color = '#';
	for (var i = 0; i < 6; i++) {
		color += letters[Math.floor(Math.random() * 16)];
	}
	return color;
}

function getTextColour(hex) {
	hex = hex.slice(1);
	var r = parseInt(hex.substring(0,2), 16);
	var g = parseInt(hex.substring(2,4), 16);
	var b = parseInt(hex.substring(4,6), 16);
	var avg = ((2 * r) + b + (3 * g))/6;
	if (avg < 128) {
		return 'white';
	} else {
		return 'black';
	}
}

function get_node_color(uuid) {
	return nodes.get(uuid).icon.color;
}

// Global var
var scope_id = $('#references_network').data('event-id');
var container = document.getElementById('references_network');
var nodes = new vis.DataSet();
var edges = new vis.DataSet();
var map_id_to_uuid = new Map();
var map_fromto_to_rel_id = new Map();
var all_obj_relation = new Map();
var user_manipulation = $('#references_network').data('user-manipulation');
var data = {
	nodes: nodes,
	edges: edges
};

// Options
var network_options = {
	interaction: {
		hover: true
	},
	manipulation: {
		enabled: user_manipulation,
		initiallyActive: true,
		addEdge: add_reference,
		editEdge: false,
		addNode: false,
		deleteNode: false,
		deleteEdge: remove_reference
	},
	physics: {
		enabled: true,
		barnesHut: {
			gravitationalConstant: -10000,
			centralGravity: 3,
			springLength: 150,
			springConstant: 0.24,
			damping: 0.6,

		}
	},
	edges: {
		width: 3,
		arrows: 'to'
	},
	nodes: {
		chosen: {
			node: function(values, id, selected, hovering) {
				values.shadow = true;
				values.shadowSize = 5;
				values.shadowX = 2;
				values.shadowY = 2;
				values.shadowColor = "rgba(0,0,0,0.1)";
			}
		}
	},
	groups: {
		object: {
			shape: 'icon',
			icon: {
				face: 'FontAwesome',
				code: '\uf00a',
				size: 50
			},
			font: {
				size: 18, // px
				background: 'white'
			}
		},
		obj_relation: {
			size: 10,
			color: {
				border:'black'
			}
		},
		attribute: {
			shape: 'box',
			color: {
				background:'orange',
				border:'black'
			},
			size: 15
		},
	},
	locales: {
		en: {
			edit: 'Edit',
			del: 'Delete selected',
			back: 'Back',
			addEdge: 'Add Reference',
			edgeDescription: 'Click on an Object and drag the edge to another Object (or Attribute) to connect them.'
		}
	}
};

// Graph interaction
function collapse_node(parent_id) {
	if (parent_id === undefined) { //  node node selected
		return
	}
	var connected_nodes = network.getConnectedNodes(parent_id);
	var connected_edges = network.getConnectedEdges(parent_id);
	// Remove nodes
	for (var nodeID of connected_nodes) {
 		// Object's attribute are in UUID format (while other object or in simple integer)
		if (nodeID.length > 10) {
			nodes.remove(nodeID);
		}
	}

	// Remove edges
	for (var edgeID of connected_edges) {
 		// Object's attribute (edge) are in UUID format (while other object or in simple integer)
		if (edgeID.length > 10) {
			edges.remove(edgeID);
		}
	}
}

function expand_node(parent_id) {
	if (parent_id === undefined) { //  node node selected
		return;
	} else if (nodes.get(parent_id).group == "attribute") { //  cannot expand attribute
		return;
	}

	newNodes = [];
	newRelations = [];

	for(var attr of all_obj_relation.get(parent_id)) {
		var parent_color = get_node_color(parent_id);

		// Ensure unicity of nodes
		if (nodes.get(attr.uuid) !== null) {
			continue;
		}

		var node = {
			id: attr.uuid,
			label: attr.type + ': ' + attr.value,
			group: 'obj_relation',
			color: {
				background: parent_color
			},
			font: {
				color: getTextColour(parent_color)
			}
		};
		newNodes.push(node);

		var rel = {
			from: parent_id,
			to: attr.uuid,
			arrows: '',
			color: {
				opacity: 0.5,
				color: parent_color
			},
			length: 40
		};
		newRelations.push(rel);
	}

	nodes.add(newNodes);
	edges.add(newRelations);
}

function remove_reference(edgeData, callback) {
	edge_id = edgeData.edges[0];
	var fromto = edge_id;
	var relation_id = map_fromto_to_rel_id.get(fromto);
	deleteObject('object_references', 'delete', relation_id, scope_id);
}

function add_reference(edgeData, callback) {
	var uuid = map_id_to_uuid.get(edgeData.to);
	genericPopup('/objectReferences/add/'+edgeData.from, '#popover_form', function() {
		$('#targetSelect').val(uuid);
		$('option[value='+uuid+']').click()
	});
}

function reset_graphs() {
	nodes.clear();
	edges.clear();
}

function update_graph(data) {
	reset_graphs();

	newNodes = [];
	for(var node of data.items) {
		var group, label;
		if ( node.node_type == 'object' ) {
			group =  'object';
			label = '('+node.val+') ' + node.type;
			label = node.type;
		} else {
			group =  'attribute';
			label = node.type + ': ' + node.val;
		}
		var node = {
			id: node.id,
			label: label,
			group: group,
			mass: 5,
			icon: {
				color: getRandomColor()
			}
		};
		newNodes.push(node);
	}
	nodes.update(newNodes);

	newRelations = [];
	for(var rel of data.relations) {
		var fromto = rel.from + '-' + rel.to;
		var rel = {
			id: fromto,
			from: rel.from,
			to: rel.to,
			label: rel.type,
			title: rel.comment,
			color: {
				opacity: 1.0
			}
		};
		newRelations.push(rel);
	}
	edges.update(newRelations);
}

function reset_view() {
	network.moveTo({
		position: {
			x: 0,
			y: 0
		},
		animation: true,
	});
}

// Data
function extract_references(data) {
	var items = [];
	var relations = [];

	if (data.Attribute !== undefined) {
		for (var attr of data.Attribute) {
			map_id_to_uuid.set(attr.id, attr.uuid);
			items.push({
				'id': attr.id,
				'type': attr.type,
				'val': attr.value,
				'node_type': 'attribute'
			});
		}
	}

	if (data.Object !== undefined) {
		for (var obj of data.Object) {
			map_id_to_uuid.set(obj.id, obj.uuid);
			all_obj_relation.set(obj.id, obj.Attribute);
			items.push({
				'id': obj.id,
				'type': obj.name,
				'val': obj.value,
				'node_type': 'object'
			});

			for (var rel of obj.ObjectReference) {
				var fromto = obj.id + '-' + rel.referenced_id;
				map_fromto_to_rel_id.set(fromto, rel.id);
				relations.push({
					'from': obj.id,
					'to': rel.referenced_id,
					'type': rel.relationship_type,
					'comment': rel.comment != "" ? rel.comment : "[Comment not set]"
				});
			}
		}
	}

	return {
		items: items,
		relations: relations
	}
}

function fetch_data_and_update() {
	$.getJSON( "/events/getReferences/"+scope_id+"/event.json", function( data ) {
		extracted = extract_references(data);
		update_graph(extracted);
	});
}

$( document ).ready(function() {
	network = new vis.Network(container, data, network_options);
	network.on("selectNode", function (params) {
		network.moveTo({
			position: {
				x: params.pointer.canvas.x,
				y: params.pointer.canvas.y
			},
			animation: true,
		});
	});
	// Fit view only when page is loading for the first time
	network.on("stabilized", function(params) {
		network.fit({ animation: true });
		network.off("stabilized"); //  Removed listener
	});

	$(document).on("keydown", function(evt) {
		switch(evt.keyCode) {
			case 88: // x
				var selected_id = network.getSelectedNodes()[0];
				expand_node(selected_id);
				break;

			case 67: // c
				var selected_id = network.getSelectedNodes()[0];
				collapse_node(selected_id);
				break;
			case 86: // v
				reset_view();
				break;

			case 16: // <SHIFT>
				if (!user_manipulation) { // user can't modify references
					break;
				}
				network.addEdgeMode(); // toggle edit mode
				break;

			case 46: // <Delete>
				if (!user_manipulation) { // user can't modify references
					break;
				}
				var selected_id = network.getSelectedEdges()[0];
				var edge = { edges: [selected_id] }; // trick to use the same function
				remove_reference(edge);
				break;

			default:
				break;
		}
	});

	$(document).on("keyup", function(evt) {
		switch(evt.keyCode) {
			case 16: // <SHIFT>
				if (!user_manipulation) { // user can't modify references
					break;
				}
				network.disableEditMode(); // un-toggle edit mode
				break;
			default:
				break;
		}

	});

	fetch_data_and_update();
});
<commit_msg>reset_view() fits network instead of moving to center only<commit_after>// Util
function getRandomColor() {
	var letters = '0123456789ABCDEF';
	var color = '#';
	for (var i = 0; i < 6; i++) {
		color += letters[Math.floor(Math.random() * 16)];
	}
	return color;
}

function getTextColour(hex) {
	hex = hex.slice(1);
	var r = parseInt(hex.substring(0,2), 16);
	var g = parseInt(hex.substring(2,4), 16);
	var b = parseInt(hex.substring(4,6), 16);
	var avg = ((2 * r) + b + (3 * g))/6;
	if (avg < 128) {
		return 'white';
	} else {
		return 'black';
	}
}

function get_node_color(uuid) {
	return nodes.get(uuid).icon.color;
}

// Global var
var scope_id = $('#references_network').data('event-id');
var container = document.getElementById('references_network');
var nodes = new vis.DataSet();
var edges = new vis.DataSet();
var map_id_to_uuid = new Map();
var map_fromto_to_rel_id = new Map();
var all_obj_relation = new Map();
var user_manipulation = $('#references_network').data('user-manipulation');
var data = {
	nodes: nodes,
	edges: edges
};

// Options
var network_options = {
	interaction: {
		hover: true
	},
	manipulation: {
		enabled: user_manipulation,
		initiallyActive: true,
		addEdge: add_reference,
		editEdge: false,
		addNode: false,
		deleteNode: false,
		deleteEdge: remove_reference
	},
	physics: {
		enabled: true,
		barnesHut: {
			gravitationalConstant: -10000,
			centralGravity: 3,
			springLength: 150,
			springConstant: 0.24,
			damping: 0.6,

		}
	},
	edges: {
		width: 3,
		arrows: 'to'
	},
	nodes: {
		chosen: {
			node: function(values, id, selected, hovering) {
				values.shadow = true;
				values.shadowSize = 5;
				values.shadowX = 2;
				values.shadowY = 2;
				values.shadowColor = "rgba(0,0,0,0.1)";
			}
		}
	},
	groups: {
		object: {
			shape: 'icon',
			icon: {
				face: 'FontAwesome',
				code: '\uf00a',
				size: 50
			},
			font: {
				size: 18, // px
				background: 'white'
			}
		},
		obj_relation: {
			size: 10,
			color: {
				border:'black'
			}
		},
		attribute: {
			shape: 'box',
			color: {
				background:'orange',
				border:'black'
			},
			size: 15
		},
	},
	locales: {
		en: {
			edit: 'Edit',
			del: 'Delete selected',
			back: 'Back',
			addEdge: 'Add Reference',
			edgeDescription: 'Click on an Object and drag the edge to another Object (or Attribute) to connect them.'
		}
	}
};

// Graph interaction
function collapse_node(parent_id) {
	if (parent_id === undefined) { //  node node selected
		return
	}
	var connected_nodes = network.getConnectedNodes(parent_id);
	var connected_edges = network.getConnectedEdges(parent_id);
	// Remove nodes
	for (var nodeID of connected_nodes) {
 		// Object's attribute are in UUID format (while other object or in simple integer)
		if (nodeID.length > 10) {
			nodes.remove(nodeID);
		}
	}

	// Remove edges
	for (var edgeID of connected_edges) {
 		// Object's attribute (edge) are in UUID format (while other object or in simple integer)
		if (edgeID.length > 10) {
			edges.remove(edgeID);
		}
	}
}

function expand_node(parent_id) {
	if (parent_id === undefined) { //  node node selected
		return;
	} else if (nodes.get(parent_id).group == "attribute") { //  cannot expand attribute
		return;
	}

	newNodes = [];
	newRelations = [];

	for(var attr of all_obj_relation.get(parent_id)) {
		var parent_color = get_node_color(parent_id);

		// Ensure unicity of nodes
		if (nodes.get(attr.uuid) !== null) {
			continue;
		}

		var node = {
			id: attr.uuid,
			label: attr.type + ': ' + attr.value,
			group: 'obj_relation',
			color: {
				background: parent_color
			},
			font: {
				color: getTextColour(parent_color)
			}
		};
		newNodes.push(node);

		var rel = {
			from: parent_id,
			to: attr.uuid,
			arrows: '',
			color: {
				opacity: 0.5,
				color: parent_color
			},
			length: 40
		};
		newRelations.push(rel);
	}

	nodes.add(newNodes);
	edges.add(newRelations);
}

function remove_reference(edgeData, callback) {
	edge_id = edgeData.edges[0];
	var fromto = edge_id;
	var relation_id = map_fromto_to_rel_id.get(fromto);
	deleteObject('object_references', 'delete', relation_id, scope_id);
}

function add_reference(edgeData, callback) {
	var uuid = map_id_to_uuid.get(edgeData.to);
	genericPopup('/objectReferences/add/'+edgeData.from, '#popover_form', function() {
		$('#targetSelect').val(uuid);
		$('option[value='+uuid+']').click()
	});
}

function reset_graphs() {
	nodes.clear();
	edges.clear();
}

function update_graph(data) {
	reset_graphs();

	newNodes = [];
	for(var node of data.items) {
		var group, label;
		if ( node.node_type == 'object' ) {
			group =  'object';
			label = '('+node.val+') ' + node.type;
			label = node.type;
		} else {
			group =  'attribute';
			label = node.type + ': ' + node.val;
		}
		var node = {
			id: node.id,
			label: label,
			group: group,
			mass: 5,
			icon: {
				color: getRandomColor()
			}
		};
		newNodes.push(node);
	}
	nodes.update(newNodes);

	newRelations = [];
	for(var rel of data.relations) {
		var fromto = rel.from + '-' + rel.to;
		var rel = {
			id: fromto,
			from: rel.from,
			to: rel.to,
			label: rel.type,
			title: rel.comment,
			color: {
				opacity: 1.0
			}
		};
		newRelations.push(rel);
	}
	edges.update(newRelations);
}

function reset_view() {
	network.fit({animation: true });
}

// Data
function extract_references(data) {
	var items = [];
	var relations = [];

	if (data.Attribute !== undefined) {
		for (var attr of data.Attribute) {
			map_id_to_uuid.set(attr.id, attr.uuid);
			items.push({
				'id': attr.id,
				'type': attr.type,
				'val': attr.value,
				'node_type': 'attribute'
			});
		}
	}

	if (data.Object !== undefined) {
		for (var obj of data.Object) {
			map_id_to_uuid.set(obj.id, obj.uuid);
			all_obj_relation.set(obj.id, obj.Attribute);
			items.push({
				'id': obj.id,
				'type': obj.name,
				'val': obj.value,
				'node_type': 'object'
			});

			for (var rel of obj.ObjectReference) {
				var fromto = obj.id + '-' + rel.referenced_id;
				map_fromto_to_rel_id.set(fromto, rel.id);
				relations.push({
					'from': obj.id,
					'to': rel.referenced_id,
					'type': rel.relationship_type,
					'comment': rel.comment != "" ? rel.comment : "[Comment not set]"
				});
			}
		}
	}

	return {
		items: items,
		relations: relations
	}
}

function fetch_data_and_update() {
	$.getJSON( "/events/getReferences/"+scope_id+"/event.json", function( data ) {
		extracted = extract_references(data);
		update_graph(extracted);
	});
}

$( document ).ready(function() {
	network = new vis.Network(container, data, network_options);
	network.on("selectNode", function (params) {
		network.moveTo({
			position: {
				x: params.pointer.canvas.x,
				y: params.pointer.canvas.y
			},
			animation: true,
		});
	});
	// Fit view only when page is loading for the first time
	network.on("stabilized", function(params) {
		network.fit({ animation: true });
		network.off("stabilized"); //  Removed listener
	});

	$(document).on("keydown", function(evt) {
		switch(evt.keyCode) {
			case 88: // x
				var selected_id = network.getSelectedNodes()[0];
				expand_node(selected_id);
				break;

			case 67: // c
				var selected_id = network.getSelectedNodes()[0];
				collapse_node(selected_id);
				break;
			case 86: // v
				reset_view();
				break;

			case 16: // <SHIFT>
				if (!user_manipulation) { // user can't modify references
					break;
				}
				network.addEdgeMode(); // toggle edit mode
				break;

			case 46: // <Delete>
				if (!user_manipulation) { // user can't modify references
					break;
				}
				var selected_id = network.getSelectedEdges()[0];
				var edge = { edges: [selected_id] }; // trick to use the same function
				remove_reference(edge);
				break;

			default:
				break;
		}
	});

	$(document).on("keyup", function(evt) {
		switch(evt.keyCode) {
			case 16: // <SHIFT>
				if (!user_manipulation) { // user can't modify references
					break;
				}
				network.disableEditMode(); // un-toggle edit mode
				break;
			default:
				break;
		}

	});

	fetch_data_and_update();
});
<|endoftext|>


<commit_before>var fs = require('fs');
var child_process = require('child_process')
var max_sleep = 300
//Added a comment that achieves no real goal.

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error"
]

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (process.argv [ 4 ]) max_sleep = process.argv [ 4 ]
  console.info("Writing from %s to %s, with up to %s seconds between commits", inFile, outFile, max_sleep)
  var outFD = fs.openSync(outFile, 'w')
  fs.readFile(inFile, function(err,data) {
    var length = data.length
    console.info("Bytes: %s", length)
    try {
      ch<commit_msg>You feeling lucky punk?<commit_after>var fs = require('fs');
var child_process = require('child_process')
var max_sleep = 300
//Added a comment that achieves no real goal.

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error"
]

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (process.argv [ 4 ]) max_sleep = process.argv [ 4 ]
  console.info("Writing from %s to %s, with up to %s seconds between commits", inFile, outFile, max_sleep)
  var outFD = fs.openSync(outFile, 'w')
  fs.readFile(inFile, function(err,data) {
    var length = data.length
    console.info("Bytes: %s", length)
    try {
      chi<|endoftext|>


<commit_before>var request = require('request'),
	cheerio = require('cheerio'),
	express = require('express'),
	app = express(),
	server,
	headers = ['Måndag', 'Tisdag', 'Onsdag', 'Torsdag', 'Fredag'],
	edison_options = {
		uri: 'http://restaurangedison.se/Bizpart.aspx?tabId=191'
	};

// Add a proxy if http_proxy is set in the environment variables
if (process.env.http_proxy !== undefined) {
	edison_options.proxy = process.env.http_proxy;
}

// Static files (.html, .css, .js et c)
app.use(express.static(__dirname));

// Respond with the index.html file if root is requested
app.get('/', function(req, res) {
	res.sendfile('index.html');
});

app.get('/get_lunches', function(req, res) {
	request(edison_options, function (error, response, body) {
		var	finalLunches = [],
			$ = cheerio.load(body),
			baseParagraph = $('#MyBPControlLayout_Container_535_divContainer > span p'),
			paragraph = baseParagraph.eq(0),
			textNodes = paragraph.contents().filter(function(i, el) {
				// Filter out everything that is not text elements that actually has text
				return el.type === 'text' && el.data.trim() !== '';
			});

		textNodes.each(function(i, el) {
			var current = el.data.trim(),
				// Get the first word of the current element (May be "Fredag STÄNGT")
				currentFirst = current.split(' ')[0],
				header = 0;

			// Check if this word should be considered a header
			if (headers.indexOf(currentFirst) >= 0) {
				header = 1;
			}

			finalLunches.push({header: header, text: current});
		});

		// Send the response
		res.send(finalLunches);
	});
});

// Start the server
var port = process.env.OPENSHIFT_NODEJS_PORT || 3000;
var ip = process.env.OPENSHIFT_NODEJS_IP || '127.0.0.1';
server = app.listen(port, ip, function() {
	console.log('Listening on port %d', server.address().port);
});
<commit_msg>Updated server to reflect new Edison page<commit_after>var request = require('request'),
	cheerio = require('cheerio'),
	express = require('express'),
	app = express(),
	server,
	headers = ['Måndag', 'Tisdag', 'Onsdag', 'Torsdag', 'Fredag'],
	edison_options = {
		uri: 'http://restaurangedison.se/lunch'
	};

// Add a proxy if http_proxy is set in the environment variables
if (process.env.http_proxy !== undefined) {
	edison_options.proxy = process.env.http_proxy;
}

// Static files (.html, .css, .js et c)
app.use(express.static(__dirname));

// Respond with the index.html file if root is requested
app.get('/', function(req, res) {
	res.sendfile('index.html');
});

var parseLunches = function(body) {
	var weeklyInfo = [],
		$ = cheerio.load(body),
		days = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday'],
		weekElem = $('.week_number').first(); //This one is not needed yet

	days.forEach(function(e, i) {
		// Get all table rows for a day
		var $dayTableRows = $('div#'+e+' tr'),
		dayInfo = [];

		$dayTableRows.each(function(i, e){
			var $this = $(this),
			type = $this.find('.course_type').text(),
			food = $this.find('.course_description').text();
			dayInfo.push({
				type: type,
				food: food
			});
		});

		weeklyInfo.push({
			day: e,
			info: dayInfo
		});
	});

	return weeklyInfo;
}

var getLunches = function(req, res) {
	request(edison_options, function (error, response, body) {

		var weeklyInfo = parseLunches(body);

		// Send the response
		res.send(weeklyInfo);
	});
};

app.get('/get_lunches', getLunches);

// Start the server
var port = process.env.OPENSHIFT_NODEJS_PORT || 3000;
var ip = process.env.OPENSHIFT_NODEJS_IP || '127.0.0.1';
server = app.listen(port, ip, function() {
	console.log('Listening on port %d', server.address().port);
});
<|endoftext|>


<commit_before>var fs = require('fs');
var child_process = require('child_proces<commit_msg>Update character<commit_after>var fs = require('fs');
var child_process = require('child_process<|endoftext|>