<commit_before>import window from '../window';
import * as util from '../util';
import Collection from '../collection';
import * as is from '../is';
import Promise from '../promise';
import define from '../define';

import addRemove from './add-remove';
import animation from './animation';
import events from './events';
import exportFormat from './export';
import layout from './layout';
import notification from './notification';
import renderer from './renderer';
import search from './search';
import style from './style';
import viewport from './viewport';

let Core = function( opts ){
  let cy = this;

  opts = util.extend( {}, opts );

  let container = opts.container;

  // allow for passing a wrapped jquery object
  // e.g. cytoscape({ container: $('#cy') })
  if( container && !is.htmlElement( container ) && is.htmlElement( container[0] ) ){
    container = container[0];
  }

  let reg = container ? container._cyreg : null; // e.g. already registered some info (e.g. readies) via jquery
  reg = reg || {};

  if( reg && reg.cy ){
    reg.cy.destroy();

    reg = {}; // old instance => replace reg completely
  }

  let readies = reg.readies = reg.readies || [];

  if( container ){ container._cyreg = reg; } // make sure container assoc'd reg points to this cy
  reg.cy = cy;

  let head = window !== undefined && container !== undefined && !opts.headless;
  let options = opts;
  options.layout = util.extend( { name: head ? 'grid' : 'null' }, options.layout );
  options.renderer = util.extend( { name: head ? 'canvas' : 'null' }, options.renderer );

  let defVal = function( def, val, altVal ){
    if( val !== undefined ){
      return val;
    } else if( altVal !== undefined ){
      return altVal;
    } else {
      return def;
    }
  };

  let _p = this._private = {
    container: container, // html dom ele container
    ready: false, // whether ready has been triggered
    options: options, // cached options
    elements: new Collection( this ), // elements in the graph
    listeners: [], // list of listeners
    aniEles: new Collection( this ), // elements being animated
    scratch: {}, // scratch object for core
    layout: null,
    renderer: null,
    destroyed: false, // whether destroy was called
    notificationsEnabled: true, // whether notifications are sent to the renderer
    minZoom: 1e-50,
    maxZoom: 1e50,
    zoomingEnabled: defVal( true, options.zoomingEnabled ),
    userZoomingEnabled: defVal( true, options.userZoomingEnabled ),
    panningEnabled: defVal( true, options.panningEnabled ),
    userPanningEnabled: defVal( true, options.userPanningEnabled ),
    boxSelectionEnabled: defVal( true, options.boxSelectionEnabled ),
    autolock: defVal( false, options.autolock, options.autolockNodes ),
    autoungrabify: defVal( false, options.autoungrabify, options.autoungrabifyNodes ),
    autounselectify: defVal( false, options.autounselectify ),
    styleEnabled: options.styleEnabled === undefined ? head : options.styleEnabled,
    zoom: is.number( options.zoom ) ? options.zoom : 1,
    pan: {
      x: is.plainObject( options.pan ) && is.number( options.pan.x ) ? options.pan.x : 0,
      y: is.plainObject( options.pan ) && is.number( options.pan.y ) ? options.pan.y : 0
    },
    animation: { // object for currently-running animations
      current: [],
      queue: []
    },
    hasCompoundNodes: false
  };

  this.createEmitter();

  // set selection type
  this.selectionType( options.selectionType );

  // init zoom bounds
  this.zoomRange({ min: options.minZoom, max: options.maxZoom });

  let loadExtData = function( extData, next ){
    let anyIsPromise = extData.some( is.promise );

    if( anyIsPromise ){
      return Promise.all( extData ).then( next ); // load all data asynchronously, then exec rest of init
    } else {
      next( extData ); // exec synchronously for convenience
    }
  };

  // start with the default stylesheet so we have something before loading an external stylesheet
  if( _p.styleEnabled ){
    cy.setStyle([]);
  }

  // create the renderer
  let rendererOptions = util.assign({}, options, options.renderer); // allow rendering hints in top level options
  cy.initRenderer( rendererOptions );

  let setElesAndLayout = function( elements, onload, ondone ){
    cy.notifications( false );

    // remove old elements
    let oldEles = cy.mutableElements();
    if( oldEles.length > 0 ){
      oldEles.remove();
    }

    if( elements != null ){
      if( is.plainObject( elements ) || is.array( elements ) ){
        cy.add( elements );
      }
    }

    cy.one( 'layoutready', function( e ){
      cy.notifications( true );
      cy.emit( e ); // we missed this event by turning notifications off, so pass it on

      cy.one( 'load', onload );
      cy.emitAndNotify( 'load' );
    } ).one( 'layoutstop', function(){
      cy.one( 'done', ondone );
      cy.emit( 'done' );
    } );

    let layoutOpts = util.extend( {}, cy._private.options.layout );
    layoutOpts.eles = cy.elements();

    cy.layout( layoutOpts ).run();
  };

  loadExtData([ options.style, options.elements ], function( thens ){
    let initStyle = thens[0];
    let initEles = thens[1];

    // init style
    if( _p.styleEnabled ){
      cy.style().append( initStyle );
    }

    // initial load
    setElesAndLayout( initEles, function(){ // onready
      cy.startAnimationLoop();
      _p.ready = true;

      // if a ready callback is specified as an option, the bind it
      if( is.fn( options.ready ) ){
        cy.on( 'ready', options.ready );
      }

      // bind all the ready handlers registered before creating this instance
      for( let i = 0; i < readies.length; i++ ){
        let fn = readies[ i ];
        cy.on( 'ready', fn );
      }
      if( reg ){ reg.readies = []; } // clear b/c we've bound them all and don't want to keep it around in case a new core uses the same div etc

      cy.emit( 'ready' );
    }, options.done );

  } );
};

let corefn = Core.prototype; // short alias

util.extend( corefn, {
  instanceString: function(){
    return 'core';
  },

  isReady: function(){
    return this._private.ready;
  },

  isDestroyed: function(){
    return this._private.destroyed;
  },

  ready: function( fn ){
    if( this.isReady() ){
      this.emitter().emit( 'ready', [], fn ); // just calls fn as though triggered via ready event
    } else {
      this.on( 'ready', fn );
    }

    return this;
  },

  destroy: function(){
    let cy = this;
    if( cy.isDestroyed() ) return;

    cy.stopAnimationLoop();

    cy.destroyRenderer();

    this.emit( 'destroy' );

    cy._private.destroyed = true;

    return cy;
  },

  hasElementWithId: function( id ){
    return this._private.elements.hasElementWithId( id );
  },

  getElementById: function( id ){
    return this._private.elements.getElementById( id );
  },

  hasCompoundNodes: function(){
    return this._private.hasCompoundNodes;
  },

  headless: function(){
    return this._private.renderer.isHeadless();
  },

  styleEnabled: function(){
    return this._private.styleEnabled;
  },

  addToPool: function( eles ){
    this._private.elements.merge( eles );

    return this; // chaining
  },

  removeFromPool: function( eles ){
    this._private.elements.unmerge( eles );

    return this;
  },

  container: function(){
    return this._private.container || null;
  },

  mount: function( container, rendererOptions ){
    if( container == null ){ return; }

    let cy = this;
    let _p = cy._private;
    let options = _p.options;

    let rOpts = rendererOptions ? rendererOptions : { name: 'canvas' };
    options.renderer = rOpts;

    if( !is.htmlElement( container ) && is.htmlElement( container[0] ) ){
      container = container[0];
    }

    cy.stopAnimationLoop();

    cy.destroyRenderer();

    _p.container = container;
    _p.styleEnabled = true;

    cy.initRenderer( rOpts );

    cy.startAnimationLoop();

    cy.style( options.style );

    cy.emit( 'mount' );

    return cy;
  },

  unmount: function(){
    let cy = this;

    cy.stopAnimationLoop();

    cy.destroyRenderer();

    cy.initRenderer( { name: 'null' } );

    cy.emit( 'unmount' );

    return cy;
  },

  options: function(){
    return util.copy( this._private.options );
  },

  json: function( obj ){
    let cy = this;
    let _p = cy._private;
    let eles = cy.mutableElements();
    let getFreshRef = ele => cy.getElementById(ele.id());

    if( is.plainObject( obj ) ){ // set

      cy.startBatch();

      if( obj.elements ){
        let idInJson = {};

        let updateEles = function( jsons, gr ){
          let toAdd = [];
          let toMod = [];

          for( let i = 0; i < jsons.length; i++ ){
            let json = jsons[ i ];
            let id = json.data.id;
            let ele = cy.getElementById( id );

            idInJson[ id ] = true;

            if( ele.length !== 0 ){ // existing element should be updated
              toMod.push({ ele, json });
            } else { // otherwise should be added
              if( gr ){
                json.group = gr;

                toAdd.push( json );
              } else {
                toAdd.push( json );
              }
            }
          }

          cy.add( toAdd );

          for( let i = 0; i < toMod.length; i++ ){
            let { ele, json } = toMod[i];

            ele.json(json);
          }
        };

        if( is.array( obj.elements ) ){ // elements: []
          updateEles( obj.elements );

        } else { // elements: { nodes: [], edges: [] }
          let grs = [ 'nodes', 'edges' ];
          for( let i = 0; i < grs.length; i++ ){
            let gr = grs[ i ];
            let elements = obj.elements[ gr ];

            if( is.array( elements ) ){
              updateEles( elements, gr );
            }
          }
        }

        let parentsToRemove = cy.collection();

        (eles
          .filter(ele => !idInJson[ ele.id() ])
          .forEach(ele => {
            if ( ele.isParent() ) {
              parentsToRemove.merge(ele);
            } else {
              ele.remove();
            }
          })
        );

        // so that children are not removed w/parent
        parentsToRemove.forEach(ele => ele.children().move({ parent: null }));

        // intermediate parents may be moved by prior line, so make sure we remove by fresh refs
        parentsToRemove.forEach(ele => getFreshRef(ele).remove());
      }

      if( obj.style ){
        cy.style( obj.style );
      }

      if( obj.zoom != null && obj.zoom !== _p.zoom ){
        cy.zoom( obj.zoom );
      }

      if( obj.pan ){
        if( obj.pan.x !== _p.pan.x || obj.pan.y !== _p.pan.y ){
          cy.pan( obj.pan );
        }
      }

      let fields = [
        'minZoom', 'maxZoom', 'zoomingEnabled', 'userZoomingEnabled',
        'panningEnabled', 'userPanningEnabled',
        'boxSelectionEnabled',
        'autolock', 'autoungrabify', 'autounselectify'
      ];

      for( let i = 0; i < fields.length; i++ ){
        let f = fields[ i ];

        if( obj[ f ] != null ){
          cy[ f ]( obj[ f ] );
        }
      }

      cy.endBatch();

      return this; // chaining
    } else { // get
      let flat = !!obj;
      let json = {};

      if( flat ){
        json.elements = this.elements().map( ele => ele.json() );
      } else {
        json.elements = {};

        eles.forEach( function( ele ){
          let group = ele.group();

          if( !json.elements[ group ] ){
            json.elements[ group ] = [];
          }

          json.elements[ group ].push( ele.json() );
        } );
      }

      if( this._private.styleEnabled ){
        json.style = cy.style().json();
      }

      let options = _p.options;

      json.zoomingEnabled = _p.zoomingEnabled;
      json.userZoomingEnabled = _p.userZoomingEnabled;
      json.zoom = _p.zoom;
      json.minZoom = _p.minZoom;
      json.maxZoom = _p.maxZoom;
      json.panningEnabled = _p.panningEnabled;
      json.userPanningEnabled = _p.userPanningEnabled;
      json.pan = util.copy( _p.pan );
      json.boxSelectionEnabled = _p.boxSelectionEnabled;
      json.renderer = util.copy( options.renderer );
      json.hideEdgesOnViewport = options.hideEdgesOnViewport;
      json.textureOnViewport = options.textureOnViewport;
      json.wheelSensitivity = options.wheelSensitivity;
      json.motionBlur = options.motionBlur;

      return json;
    }
  },

  scratch: define.data( {
    field: 'scratch',
    bindingEvent: 'scratch',
    allowBinding: true,
    allowSetting: true,
    settingEvent: 'scratch',
    settingTriggersEvent: true,
    triggerFnName: 'trigger',
    allowGetting: true
  } ),

  removeScratch: define.removeData( {
    field: 'scratch',
    event: 'scratch',
    triggerFnName: 'trigger',
    triggerEvent: true
  } )

} );

corefn.$id = corefn.getElementById;

[
  addRemove,
  animation,
  events,
  exportFormat,
  layout,
  notification,
  renderer,
  search,
  style,
  viewport,
].forEach( function( props ){
  util.extend( corefn, props );
} );

export default Core;
<commit_msg>`cy.width()` and `cy.height()` incorrectly reported for headless instance after it is mounted #2385<commit_after>import window from '../window';
import * as util from '../util';
import Collection from '../collection';
import * as is from '../is';
import Promise from '../promise';
import define from '../define';

import addRemove from './add-remove';
import animation from './animation';
import events from './events';
import exportFormat from './export';
import layout from './layout';
import notification from './notification';
import renderer from './renderer';
import search from './search';
import style from './style';
import viewport from './viewport';

let Core = function( opts ){
  let cy = this;

  opts = util.extend( {}, opts );

  let container = opts.container;

  // allow for passing a wrapped jquery object
  // e.g. cytoscape({ container: $('#cy') })
  if( container && !is.htmlElement( container ) && is.htmlElement( container[0] ) ){
    container = container[0];
  }

  let reg = container ? container._cyreg : null; // e.g. already registered some info (e.g. readies) via jquery
  reg = reg || {};

  if( reg && reg.cy ){
    reg.cy.destroy();

    reg = {}; // old instance => replace reg completely
  }

  let readies = reg.readies = reg.readies || [];

  if( container ){ container._cyreg = reg; } // make sure container assoc'd reg points to this cy
  reg.cy = cy;

  let head = window !== undefined && container !== undefined && !opts.headless;
  let options = opts;
  options.layout = util.extend( { name: head ? 'grid' : 'null' }, options.layout );
  options.renderer = util.extend( { name: head ? 'canvas' : 'null' }, options.renderer );

  let defVal = function( def, val, altVal ){
    if( val !== undefined ){
      return val;
    } else if( altVal !== undefined ){
      return altVal;
    } else {
      return def;
    }
  };

  let _p = this._private = {
    container: container, // html dom ele container
    ready: false, // whether ready has been triggered
    options: options, // cached options
    elements: new Collection( this ), // elements in the graph
    listeners: [], // list of listeners
    aniEles: new Collection( this ), // elements being animated
    scratch: {}, // scratch object for core
    layout: null,
    renderer: null,
    destroyed: false, // whether destroy was called
    notificationsEnabled: true, // whether notifications are sent to the renderer
    minZoom: 1e-50,
    maxZoom: 1e50,
    zoomingEnabled: defVal( true, options.zoomingEnabled ),
    userZoomingEnabled: defVal( true, options.userZoomingEnabled ),
    panningEnabled: defVal( true, options.panningEnabled ),
    userPanningEnabled: defVal( true, options.userPanningEnabled ),
    boxSelectionEnabled: defVal( true, options.boxSelectionEnabled ),
    autolock: defVal( false, options.autolock, options.autolockNodes ),
    autoungrabify: defVal( false, options.autoungrabify, options.autoungrabifyNodes ),
    autounselectify: defVal( false, options.autounselectify ),
    styleEnabled: options.styleEnabled === undefined ? head : options.styleEnabled,
    zoom: is.number( options.zoom ) ? options.zoom : 1,
    pan: {
      x: is.plainObject( options.pan ) && is.number( options.pan.x ) ? options.pan.x : 0,
      y: is.plainObject( options.pan ) && is.number( options.pan.y ) ? options.pan.y : 0
    },
    animation: { // object for currently-running animations
      current: [],
      queue: []
    },
    hasCompoundNodes: false
  };

  this.createEmitter();

  // set selection type
  this.selectionType( options.selectionType );

  // init zoom bounds
  this.zoomRange({ min: options.minZoom, max: options.maxZoom });

  let loadExtData = function( extData, next ){
    let anyIsPromise = extData.some( is.promise );

    if( anyIsPromise ){
      return Promise.all( extData ).then( next ); // load all data asynchronously, then exec rest of init
    } else {
      next( extData ); // exec synchronously for convenience
    }
  };

  // start with the default stylesheet so we have something before loading an external stylesheet
  if( _p.styleEnabled ){
    cy.setStyle([]);
  }

  // create the renderer
  let rendererOptions = util.assign({}, options, options.renderer); // allow rendering hints in top level options
  cy.initRenderer( rendererOptions );

  let setElesAndLayout = function( elements, onload, ondone ){
    cy.notifications( false );

    // remove old elements
    let oldEles = cy.mutableElements();
    if( oldEles.length > 0 ){
      oldEles.remove();
    }

    if( elements != null ){
      if( is.plainObject( elements ) || is.array( elements ) ){
        cy.add( elements );
      }
    }

    cy.one( 'layoutready', function( e ){
      cy.notifications( true );
      cy.emit( e ); // we missed this event by turning notifications off, so pass it on

      cy.one( 'load', onload );
      cy.emitAndNotify( 'load' );
    } ).one( 'layoutstop', function(){
      cy.one( 'done', ondone );
      cy.emit( 'done' );
    } );

    let layoutOpts = util.extend( {}, cy._private.options.layout );
    layoutOpts.eles = cy.elements();

    cy.layout( layoutOpts ).run();
  };

  loadExtData([ options.style, options.elements ], function( thens ){
    let initStyle = thens[0];
    let initEles = thens[1];

    // init style
    if( _p.styleEnabled ){
      cy.style().append( initStyle );
    }

    // initial load
    setElesAndLayout( initEles, function(){ // onready
      cy.startAnimationLoop();
      _p.ready = true;

      // if a ready callback is specified as an option, the bind it
      if( is.fn( options.ready ) ){
        cy.on( 'ready', options.ready );
      }

      // bind all the ready handlers registered before creating this instance
      for( let i = 0; i < readies.length; i++ ){
        let fn = readies[ i ];
        cy.on( 'ready', fn );
      }
      if( reg ){ reg.readies = []; } // clear b/c we've bound them all and don't want to keep it around in case a new core uses the same div etc

      cy.emit( 'ready' );
    }, options.done );

  } );
};

let corefn = Core.prototype; // short alias

util.extend( corefn, {
  instanceString: function(){
    return 'core';
  },

  isReady: function(){
    return this._private.ready;
  },

  isDestroyed: function(){
    return this._private.destroyed;
  },

  ready: function( fn ){
    if( this.isReady() ){
      this.emitter().emit( 'ready', [], fn ); // just calls fn as though triggered via ready event
    } else {
      this.on( 'ready', fn );
    }

    return this;
  },

  destroy: function(){
    let cy = this;
    if( cy.isDestroyed() ) return;

    cy.stopAnimationLoop();

    cy.destroyRenderer();

    this.emit( 'destroy' );

    cy._private.destroyed = true;

    return cy;
  },

  hasElementWithId: function( id ){
    return this._private.elements.hasElementWithId( id );
  },

  getElementById: function( id ){
    return this._private.elements.getElementById( id );
  },

  hasCompoundNodes: function(){
    return this._private.hasCompoundNodes;
  },

  headless: function(){
    return this._private.renderer.isHeadless();
  },

  styleEnabled: function(){
    return this._private.styleEnabled;
  },

  addToPool: function( eles ){
    this._private.elements.merge( eles );

    return this; // chaining
  },

  removeFromPool: function( eles ){
    this._private.elements.unmerge( eles );

    return this;
  },

  container: function(){
    return this._private.container || null;
  },

  mount: function( container, rendererOptions ){
    if( container == null ){ return; }

    let cy = this;
    let _p = cy._private;
    let options = _p.options;

    let rOpts = rendererOptions ? rendererOptions : { name: 'canvas' };
    options.renderer = rOpts;

    if( !is.htmlElement( container ) && is.htmlElement( container[0] ) ){
      container = container[0];
    }

    cy.stopAnimationLoop();

    cy.destroyRenderer();

    _p.container = container;
    _p.styleEnabled = true;

    cy.invalidateSize();

    cy.initRenderer( rOpts );

    cy.startAnimationLoop();

    cy.style( options.style );

    cy.emit( 'mount' );

    return cy;
  },

  unmount: function(){
    let cy = this;

    cy.stopAnimationLoop();

    cy.destroyRenderer();

    cy.initRenderer( { name: 'null' } );

    cy.emit( 'unmount' );

    return cy;
  },

  options: function(){
    return util.copy( this._private.options );
  },

  json: function( obj ){
    let cy = this;
    let _p = cy._private;
    let eles = cy.mutableElements();
    let getFreshRef = ele => cy.getElementById(ele.id());

    if( is.plainObject( obj ) ){ // set

      cy.startBatch();

      if( obj.elements ){
        let idInJson = {};

        let updateEles = function( jsons, gr ){
          let toAdd = [];
          let toMod = [];

          for( let i = 0; i < jsons.length; i++ ){
            let json = jsons[ i ];
            let id = json.data.id;
            let ele = cy.getElementById( id );

            idInJson[ id ] = true;

            if( ele.length !== 0 ){ // existing element should be updated
              toMod.push({ ele, json });
            } else { // otherwise should be added
              if( gr ){
                json.group = gr;

                toAdd.push( json );
              } else {
                toAdd.push( json );
              }
            }
          }

          cy.add( toAdd );

          for( let i = 0; i < toMod.length; i++ ){
            let { ele, json } = toMod[i];

            ele.json(json);
          }
        };

        if( is.array( obj.elements ) ){ // elements: []
          updateEles( obj.elements );

        } else { // elements: { nodes: [], edges: [] }
          let grs = [ 'nodes', 'edges' ];
          for( let i = 0; i < grs.length; i++ ){
            let gr = grs[ i ];
            let elements = obj.elements[ gr ];

            if( is.array( elements ) ){
              updateEles( elements, gr );
            }
          }
        }

        let parentsToRemove = cy.collection();

        (eles
          .filter(ele => !idInJson[ ele.id() ])
          .forEach(ele => {
            if ( ele.isParent() ) {
              parentsToRemove.merge(ele);
            } else {
              ele.remove();
            }
          })
        );

        // so that children are not removed w/parent
        parentsToRemove.forEach(ele => ele.children().move({ parent: null }));

        // intermediate parents may be moved by prior line, so make sure we remove by fresh refs
        parentsToRemove.forEach(ele => getFreshRef(ele).remove());
      }

      if( obj.style ){
        cy.style( obj.style );
      }

      if( obj.zoom != null && obj.zoom !== _p.zoom ){
        cy.zoom( obj.zoom );
      }

      if( obj.pan ){
        if( obj.pan.x !== _p.pan.x || obj.pan.y !== _p.pan.y ){
          cy.pan( obj.pan );
        }
      }

      let fields = [
        'minZoom', 'maxZoom', 'zoomingEnabled', 'userZoomingEnabled',
        'panningEnabled', 'userPanningEnabled',
        'boxSelectionEnabled',
        'autolock', 'autoungrabify', 'autounselectify'
      ];

      for( let i = 0; i < fields.length; i++ ){
        let f = fields[ i ];

        if( obj[ f ] != null ){
          cy[ f ]( obj[ f ] );
        }
      }

      cy.endBatch();

      return this; // chaining
    } else { // get
      let flat = !!obj;
      let json = {};

      if( flat ){
        json.elements = this.elements().map( ele => ele.json() );
      } else {
        json.elements = {};

        eles.forEach( function( ele ){
          let group = ele.group();

          if( !json.elements[ group ] ){
            json.elements[ group ] = [];
          }

          json.elements[ group ].push( ele.json() );
        } );
      }

      if( this._private.styleEnabled ){
        json.style = cy.style().json();
      }

      let options = _p.options;

      json.zoomingEnabled = _p.zoomingEnabled;
      json.userZoomingEnabled = _p.userZoomingEnabled;
      json.zoom = _p.zoom;
      json.minZoom = _p.minZoom;
      json.maxZoom = _p.maxZoom;
      json.panningEnabled = _p.panningEnabled;
      json.userPanningEnabled = _p.userPanningEnabled;
      json.pan = util.copy( _p.pan );
      json.boxSelectionEnabled = _p.boxSelectionEnabled;
      json.renderer = util.copy( options.renderer );
      json.hideEdgesOnViewport = options.hideEdgesOnViewport;
      json.textureOnViewport = options.textureOnViewport;
      json.wheelSensitivity = options.wheelSensitivity;
      json.motionBlur = options.motionBlur;

      return json;
    }
  },

  scratch: define.data( {
    field: 'scratch',
    bindingEvent: 'scratch',
    allowBinding: true,
    allowSetting: true,
    settingEvent: 'scratch',
    settingTriggersEvent: true,
    triggerFnName: 'trigger',
    allowGetting: true
  } ),

  removeScratch: define.removeData( {
    field: 'scratch',
    event: 'scratch',
    triggerFnName: 'trigger',
    triggerEvent: true
  } )

} );

corefn.$id = corefn.getElementById;

[
  addRemove,
  animation,
  events,
  exportFormat,
  layout,
  notification,
  renderer,
  search,
  style,
  viewport,
].forEach( function( props ){
  util.extend( corefn, props );
} );

export default Core;
<|endoftext|>


<commit_before>const initialState = {
	cards: {
		specialEvents: 	{ id: 'specialEvents', active: false, autoActivated: false, name: 'Special Events', component: 'SpecialEventsCard' },
		schedule: 		{ id: 'schedule', active: true, name: 'Class Schedule', component: 'ScheduleCard' },
		weather: 		{ id: 'weather', active: true, name: 'Weather', component: 'WeatherCard' },
		shuttle: 		{ id: 'shuttle', active: true, name: 'Shuttle', component: 'ShuttleCard' },
		dining: 		{ id: 'dining', active: true, name: 'Dining', component: 'DiningCard' },
		events: 		{ id: 'events', active: true, name: 'Events', component: 'EventsCard' },
		quicklinks: 	{ id: 'quicklinks', active: true, name: 'Links', component: 'QuicklinksCard' },
		news: 			{ id: 'news', active: true, name: 'News', component: 'NewsCard' },
	},
	cardOrder: ['specialEvents', 'weather', 'schedule', 'shuttle', 'dining', 'events', 'quicklinks', 'news'],
};

function cards(state = initialState, action) {
	var newState = { ...state };

	switch (action.type) {
		case 'SET_CARD_STATE':
			return {
				...state,
				cards: {
					...state.cards,
					[action.id]: { ...state.cards[action.id], active: action.active }
				}
			};
		case 'SET_AUTOACTIVATED_STATE':
			newState.cards[action.id] = Object.assign({}, newState.cards[action.id], { autoActivated: action.autoActivated });

			return newState;
		case 'SHOW_CARD': {
			if (newState.cards[action.id] && !newState.cards[action.id].active) {
				return {
					...state,
					cards: {
						...state.cards,
						[action.id]: { ...state.cards[action.id], active: true }
					}
				};
			}
			return newState;
		}
		case 'HIDE_CARD':
			if (newState.cards[action.id] && newState.cards[action.id].active) {
				return {
					...state,
					cards: {
						...state.cards,
						[action.id]: { ...state.cards[action.id], active: false }
					}
				};
			}
			return newState;
		case 'SET_CARD_ORDER':
			newState.cardOrder = action.cardOrder.slice();

			return newState;
	}

	return state;
}

module.exports = cards;
<commit_msg>Set class schedule as first card<commit_after>const initialState = {
	cards: {
		specialEvents: 	{ id: 'specialEvents', active: false, autoActivated: false, name: 'Special Events', component: 'SpecialEventsCard' },
		schedule: 		{ id: 'schedule', active: true, name: 'Class Schedule', component: 'ScheduleCard' },
		weather: 		{ id: 'weather', active: true, name: 'Weather', component: 'WeatherCard' },
		shuttle: 		{ id: 'shuttle', active: true, name: 'Shuttle', component: 'ShuttleCard' },
		dining: 		{ id: 'dining', active: true, name: 'Dining', component: 'DiningCard' },
		events: 		{ id: 'events', active: true, name: 'Events', component: 'EventsCard' },
		quicklinks: 	{ id: 'quicklinks', active: true, name: 'Links', component: 'QuicklinksCard' },
		news: 			{ id: 'news', active: true, name: 'News', component: 'NewsCard' },
	},
	cardOrder: ['specialEvents', 'schedule', 'weather',  'shuttle', 'dining', 'events', 'quicklinks', 'news'],
};

function cards(state = initialState, action) {
	var newState = { ...state };

	switch (action.type) {
		case 'SET_CARD_STATE':
			return {
				...state,
				cards: {
					...state.cards,
					[action.id]: { ...state.cards[action.id], active: action.active }
				}
			};
		case 'SET_AUTOACTIVATED_STATE':
			newState.cards[action.id] = Object.assign({}, newState.cards[action.id], { autoActivated: action.autoActivated });

			return newState;
		case 'SHOW_CARD': {
			if (newState.cards[action.id] && !newState.cards[action.id].active) {
				return {
					...state,
					cards: {
						...state.cards,
						[action.id]: { ...state.cards[action.id], active: true }
					}
				};
			}
			return newState;
		}
		case 'HIDE_CARD':
			if (newState.cards[action.id] && newState.cards[action.id].active) {
				return {
					...state,
					cards: {
						...state.cards,
						[action.id]: { ...state.cards[action.id], active: false }
					}
				};
			}
			return newState;
		case 'SET_CARD_ORDER':
			newState.cardOrder = action.cardOrder.slice();

			return newState;
	}

	return state;
}

module.exports = cards;
<|endoftext|>


<commit_before>/**
 *
 * htmlQM Module
 *
 */

define(['jquery', 'underscore', 'MainModule', 'config', 'Helpers'], function($, _, QM, QMCONFIG, Helpers) {
  var QMHtml = {};

  QMHtml.VideoChat = {

    onCallTpl: function(params) {
      var htmlTemplate = _.template('
'+
          '
'+
          '<div class="message-avatar avatar contact-avatar_message info-avatar" style="background-image:url(<%= userAvatar %>)">
'+
          '<%= callTypeUС %> Call from <%= userName %>
'+
          '
'+
          '<button class="btn_decline" data-callType="<%= callType %>" data-dialog="<%= dialogId %>"'+
          ' data-id="<%= userId %>">Decline</button>'+
          '<button class="btn_accept" data-callType="<%= callType %>" data-session="<%= sessionId %>"'+
          ' data-dialog="<%= dialogId %>" data-id="<%= userId %>">Accept</button>'+
          '

')(params);

      return htmlTemplate;
    },

    buildTpl: function(params) {
      var htmlTemplate = _.template('
'+
          '<video id="remoteStream" class="mediacall-remote-stream is-hidden"></video>'+
          '<video id="localStream" class="mediacall-local mediacall-local-stream is-hidden"></video>'+
          '<img id="localUser" class="mediacall-local mediacall-local-avatar" src="<%=userAvatar%>" alt="avatar">'+
          '
'+
          '<img class="mediacall-remote-avatar" src="<%=contactAvatar%>" alt="avatar">'+
          '<%=contactName%>'+
          'connecting...
'+
          '
'+
          ''+
          '
'+
          '
'+
          '<button class="btn_mediacall btn_full-mode" data-id="<%=userId%>" data-dialog="<%=dialogId%>" disabled>'+
          '

'+
          '

</button>'+
          '<button class="btn_mediacall btn_camera_off" data-id="<%=userId%>" data-dialog="<%=dialogId%>">'+
          '</button>'+
          '<button class="btn_mediacall btn_mic_off" data-id="<%=userId%>" data-dialog="<%=dialogId%>">'+
          '</button>'+
          '<button class="btn_mediacall btn_hangup" data-id="<%=userId%>" data-dialog="<%=dialogId%>">'+
          '</button>'+
          '

')(params);

      return htmlTemplate;
    },

    showError: function() {
      var isBottom = Helpers.isBeginOfChat(),
          $chat = $('.l-chat:visible'),
          htmlTemplate = _.template('
'+
                        ''+
                        '

'+
                        '

Devices are not found

');

      $chat.find('.mCSB_container').append(htmlTemplate);

      if (isBottom) {
        $('.l-chat:visible .scrollbar_message').mCustomScrollbar("scrollTo", "bottom");
      }
    },

    noWebRTC: function() {
      var isBottom = Helpers.isBeginOfChat(),
          $chat = $('.l-chat:visible'),
          htmlTemplate = _.template('
'+
                        ''+
                        '

'+
                        '

'+
                        'Audio and Video calls aren\'t supported by your browser. Please use Google Chrome, Opera or Firefox.

');

      $chat.find('.mCSB_container').append(htmlTemplate);

      if (isBottom) {
        $('.l-chat:visible .scrollbar_message').mCustomScrollbar("scrollTo", "bottom");
      }
    }

  };

  return QMHtml;
});
<commit_msg>removed QMCONFIG from qmhtml.js<commit_after>/**
 *
 * htmlQM Module
 *
 */

define(['jquery', 'underscore', 'MainModule', 'Helpers'], function($, _, QM, Helpers) {
  var QMHtml = {};

  QMHtml.VideoChat = {

    onCallTpl: function(params) {
      var htmlTemplate = _.template('
'+
          '
'+
          '<div class="message-avatar avatar contact-avatar_message info-avatar" style="background-image:url(<%= userAvatar %>)">
'+
          '<%= callTypeUС %> Call from <%= userName %>
'+
          '
'+
          '<button class="btn_decline" data-callType="<%= callType %>" data-dialog="<%= dialogId %>"'+
          ' data-id="<%= userId %>">Decline</button>'+
          '<button class="btn_accept" data-callType="<%= callType %>" data-session="<%= sessionId %>"'+
          ' data-dialog="<%= dialogId %>" data-id="<%= userId %>">Accept</button>'+
          '

')(params);

      return htmlTemplate;
    },

    buildTpl: function(params) {
      var htmlTemplate = _.template('
'+
          '<video id="remoteStream" class="mediacall-remote-stream is-hidden"></video>'+
          '<video id="localStream" class="mediacall-local mediacall-local-stream is-hidden"></video>'+
          '<img id="localUser" class="mediacall-local mediacall-local-avatar" src="<%=userAvatar%>" alt="avatar">'+
          '
'+
          '<img class="mediacall-remote-avatar" src="<%=contactAvatar%>" alt="avatar">'+
          '<%=contactName%>'+
          'connecting...
'+
          '
'+
          ''+
          '
'+
          '
'+
          '<button class="btn_mediacall btn_full-mode" data-id="<%=userId%>" data-dialog="<%=dialogId%>" disabled>'+
          '

'+
          '

</button>'+
          '<button class="btn_mediacall btn_camera_off" data-id="<%=userId%>" data-dialog="<%=dialogId%>">'+
          '</button>'+
          '<button class="btn_mediacall btn_mic_off" data-id="<%=userId%>" data-dialog="<%=dialogId%>">'+
          '</button>'+
          '<button class="btn_mediacall btn_hangup" data-id="<%=userId%>" data-dialog="<%=dialogId%>">'+
          '</button>'+
          '

')(params);

      return htmlTemplate;
    },

    showError: function() {
      var isBottom = Helpers.isBeginOfChat(),
          $chat = $('.l-chat:visible'),
          htmlTemplate = _.template('
'+
                        ''+
                        '

'+
                        '

Devices are not found

');

      $chat.find('.mCSB_container').append(htmlTemplate);

      if (isBottom) {
        $('.l-chat:visible .scrollbar_message').mCustomScrollbar("scrollTo", "bottom");
      }
    },

    noWebRTC: function() {
      var isBottom = Helpers.isBeginOfChat(),
          $chat = $('.l-chat:visible'),
          htmlTemplate = _.template('
'+
                        ''+
                        '

'+
                        '

'+
                        'Audio and Video calls aren\'t supported by your browser. Please use Google Chrome, Opera or Firefox.

');

      $chat.find('.mCSB_container').append(htmlTemplate);

      if (isBottom) {
        $('.l-chat:visible .scrollbar_message').mCustomScrollbar("scrollTo", "bottom");
      }
    }

  };

  return QMHtml;
});
<|endoftext|>


<commit_before>import React, { Component } from 'react'
import classnames from 'classnames';
import { Route, Link } from 'react-router-dom';
import urbitOb from 'urbit-ob';

//TODO textarea + join button to make an api call
export class JoinScreen extends Component {
  constructor(props) {
    super(props);

    this.state = {
      book: '/',
      error: false
    };

    this.bookChange = this.bookChange.bind(this);
  }

  componentDidUpdate(prevProps, prevState) {
      const { props, state } = this;
      if (state.book in props.notebooks) {
        props.history.push('/~publish');
      }
   }

  onClickJoin() {
    const { props, state } = this;

    let text = state.book;
    // an error condition to prevent double joins?
    if (text in props.notebooks ||
        text.length === 0) {
      this.setState({
        error: true,
      });
      return;
    }

    let book = text.split('/');
    let ship = book[0];
    book.splice(0, 1);
    book = '/' + book.join('/');

    if (book.length < 2 || !urbitOb.isValidPatp(ship)) {
      this.setState({
        error: true,
      });
      return;
    }

    let actionData = {
      subscribe: {
        who: ship.replace('~',''),
        book: /\/?(.*)/.exec(book)[1]
      }
    }

    console.log('actionData', actionData);

    // TODO: askHistory setting
    window.api.action("publish","publish-action", actionData);

  }

  bookChange(event) {
    this.setState({
      book: event.target.value
    });
  }

  render() {
    const { props } = this;

    let joinClasses = "db f9 green2 ba pa2 b--green2 bg-gray0-d pointer";
    if ((!this.state.book) || (this.state.book === "/")) {
      joinClasses = 'db f9 gray2 ba pa2 b--gray3 bg-gray0-d pointer';
    }

    let errElem = ();
    if (this.state.error) {
      errElem = (

          Notebook must have a valid name.

      );
    }

    return (

          <Link to="/~chat/">{"⟵ All Notebooks"}</Link>

Subscribe to an Existing Notebook

Enter a ~ship/notebook-name

Notebook names use lowercase, hyphens, and slashes.

          <textarea
            ref={ e => { this.textarea = e; } }
            className="f7 mono ba b--gray3 b--gray2-d bg-gray0-d white-d pa3 mb2 db"
            placeholder="~zod/dream-journal"
            spellCheck="false"
            rows={1}
            onKeyPress={e => {
              if (e.key === "Enter") {
                this.onClickJoin();
              }
            }}
            style={{
              resize: 'none',
            }}
            onChange={this.bookChange} />
          {errElem}

          <button
            onClick={this.onClickJoin.bind(this)}
            className={joinClasses}
          >Join Chat</button>

    );
  }
}

export default JoinScreen
<commit_msg>improve validation<commit_after>import React, { Component } from 'react'
import classnames from 'classnames';
import { Route, Link } from 'react-router-dom';
import urbitOb from 'urbit-ob';

//TODO textarea + join button to make an api call
export class JoinScreen extends Component {
  constructor(props) {
    super(props);

    this.state = {
      book: '/',
      error: false
    };

    this.bookChange = this.bookChange.bind(this);
  }

  notebooksInclude(text, notebookObj) {
    let verdict = false;
    let keyPair = [];
    // validate that it's a worthwhile thing to check
    // certainly a unit would be nice here
    if (text.indexOf('/') === -1) {
      return verdict;
    } else {
      keyPair = text.split('/');
    };
    // check both levels of object
    if (keyPair[0] in notebookObj) {
      if (keyPair[1] in notebookObj[keyPair[0]]) {
        verdict = true;
      }
    }
    return verdict;
  }

  onClickJoin() {
    const { props, state } = this;

    let text = state.book;
    // an error condition to prevent double joins?
    if (this.notebooksInclude(state.book,props.notebooks) ||
        text.length === 0) {
      props.history.push('/~publish');
    }

    let book = text.split('/');
    let ship = book[0];
    book.splice(0, 1);
    book = '/' + book.join('/');

    if (book.length < 2 || !urbitOb.isValidPatp(ship)) {
      this.setState({
        error: true,
      });
      return;
    }

    let actionData = {
      subscribe: {
        who: ship.replace('~',''),
        book: /\/?(.*)/.exec(book)[1]
      }
    }

    console.log('actionData', actionData);

    // TODO: askHistory setting
    window.api.action("publish","publish-action", actionData);

  }

  bookChange(event) {
    this.setState({
      book: event.target.value
    });
  }

  render() {
    const { props } = this;

    let joinClasses = "db f9 green2 ba pa2 b--green2 bg-gray0-d pointer";
    if ((!this.state.book) || (this.state.book === "/")) {
      joinClasses = 'db f9 gray2 ba pa2 b--gray3 bg-gray0-d pointer';
    }

    let errElem = ();
    if (this.state.error) {
      errElem = (

          Notebook must have a valid name.

      );
    }

    return (

          <Link to="/~chat/">{"⟵ All Notebooks"}</Link>

Subscribe to an Existing Notebook

Enter a ~ship/notebook-name

Notebook names use lowercase, hyphens, and slashes.

          <textarea
            ref={ e => { this.textarea = e; } }
            className="f7 mono ba b--gray3 b--gray2-d bg-gray0-d white-d pa3 mb2 db"
            placeholder="~zod/dream-journal"
            spellCheck="false"
            rows={1}
            onKeyPress={e => {
              if (e.key === "Enter") {
                this.onClickJoin();
              }
            }}
            style={{
              resize: 'none',
            }}
            onChange={this.bookChange} />
          {errElem}

          <button
            onClick={this.onClickJoin.bind(this)}
            className={joinClasses}
          >Join Chat</button>

    );
  }
}

export default JoinScreen
<|endoftext|>


<commit_before>'use strict';

(function() {
  angular
    .module('app')
    .config(['$stateProvider', '$urlRouterProvider',
      function($stateProvider, $urlRouterProvider) {
        $stateProvider
          .state('site', {
            abstract: true,
            templateUrl: '/templates/site.html'
          }).state('site.laws', {
            url: '/',
            templateUrl: '/templates/law/index.html',
            controller: 'LawIndexController'
          }).state('site.404', {
            params: { message: undefined },
            templateUrl: '/templates/site/404.html',
            controller: 'StaticPageController'
          }).state('site.message', {
            params: { title: undefined, message: undefined },
            templateUrl: '/templates/site/message.html',
            controller: 'StaticPageController'
          });

        $urlRouterProvider.otherwise( function($injector, $location) {
          if ($location.path() === '') {
            $location.replace().path('/');
          } else {
            console.error($location.path(), '404: route not found!');
            $injector.get('grMessage').error404();
          }
        });
      }
    ]);
})();
<commit_msg>Apply site controller to the root state in embedded mode<commit_after>'use strict';

(function() {
  angular
    .module('app')
    .config(['$stateProvider', '$urlRouterProvider', 'grEmbeddingParamsProvider',
      function($stateProvider, $urlRouterProvider, grEmbeddingParamsProvider) {
        $stateProvider
          .state('site', {
            abstract: true,
            templateUrl: '/templates/site.html',
            controller: grEmbeddingParamsProvider.getParams().isEmbeddedMode ?
              'SiteController' : undefined
          }).state('site.laws', {
            url: '/',
            templateUrl: '/templates/law/index.html',
            controller: 'LawIndexController'
          }).state('site.404', {
            params: { message: undefined },
            templateUrl: '/templates/site/404.html',
            controller: 'StaticPageController'
          }).state('site.message', {
            params: { title: undefined, message: undefined },
            templateUrl: '/templates/site/message.html',
            controller: 'StaticPageController'
          });

        $urlRouterProvider.otherwise( function($injector, $location) {
          if ($location.path() === '') {
            $location.replace().path('/');
          } else {
            console.error($location.path(), '404: route not found!');
            $injector.get('grMessage').error404();
          }
        });
      }
    ]);
})();
<|endoftext|>


<commit_before>// Redis client
var redis = require('redis');
var colors = require('./color');

var config_redis = {
    host: "127.0.0.1",
    port: "6379",
    retry_strategy: function (options) {
        if (options.error && options.error.code === 'ECONNREFUSED') {
            // End reconnecting on a specific error and flush all commands with a individual error
            return new Error('The server refused the connection');
        }
        if (options.total_retry_time > 1000 * 60 * 60) {
            // End reconnecting after a specific timeout and flush all commands with a individual error
            return new Error('Retry time exhausted');
        }
        if (options.attempt > 10) {
            // End reconnecting with built in error
            return undefined;
        }
        // reconnect after
        return Math.min(options.attempt * 100, 3000);
    }
};

// connexion database
var redis_client = redis.createClient(config_redis);

// Redis init client
redis_client.on('connect', function() {
    console.log(colors.info('\nRedis connection has been established successfully.'));
});

module.exports = redis_client;<commit_msg>Updating output error & env var<commit_after>// Redis client
var redis = require('redis');
var colors = require('color');

var config_redis = {
    host: process.env.APP_REDIS_HOST || '127.0.0.1',
    port: process.env.APP_REDIS_PORT || 6379,
    retry_strategy: function (options) {
        if (options.error && options.error.code === 'ECONNREFUSED') {
            // End reconnecting on a specific error and flush all commands with a individual error
            return new Error('Redis: the server refused the connection');
        }
        if (options.total_retry_time > 1000 * 60 * 60) {
            // End reconnecting after a specific timeout and flush all commands with a individual error
            return new Error('Redis: Retry time exhausted');
        }
        if (options.attempt > 10) {
            // End reconnecting with built in error
            return undefined;
        }
        // reconnect after
        return Math.min(options.attempt * 100, 3000);
    }
};

// connexion database
var redis_client = redis.createClient(config_redis);

// Redis init client
redis_client.on('connect', function() {
    console.log(colors.info('\nRedis: connection has been established successfully.'));
});

module.exports = redis_client;<|endoftext|>


<commit_before>/* eslint-disable camelcase */
import { later } from '@ember/runloop';
import DS from 'ember-data';
import PaginatedCollectionPromise from 'travis/utils/paginated-collection-promise';
import config from 'travis/config/environment';
import { service } from 'ember-decorators/service';
import FilteredArrayManager from 'travis/utils/filtered-array-manager';
import fetchLivePaginatedCollection from 'travis/utils/fetch-live-paginated-collection';

export default DS.Store.extend({
  @service auth: null,

  defaultAdapter: 'application',
  adapter: 'application',

  init() {
    this._super(...arguments);
    this.filteredArraysManager = FilteredArrayManager.create({ store: this });
    return this.set('pusherEventHandlerGuards', {});
  },

  // Fetch a filtered collection.
  //
  // modelName      - a type of the model passed as a string, for example 'repo'
  // queryParams    - params that will be passed to the store.query function when
  //                  fetching records on the initial call. Passing null or
  //                  undefined here will stop any requests from happening,
  //                  filtering will be based only on existing records
  // filterFunction - a function that will be called to determine wheather a
  //                  record should be included in the filtered collection. A
  //                  passed function will be called with a record as an
  //                  argument
  // dependencies   - a list of dependencies that will trigger the re-evaluation
  //                  of a record. When one of the dependencies changes on any
  //                  of the records in the store, it may be added or removed
  //                  from a filtered array.
  // forceReload    - if set to true, store.query will be run on each call
  //                  instead of only running it on the first run
  //
  // Example:
  //
  //   store.filter(
  //     'repo',
  //     { starred: true },
  //     (repo) => repo.get('starred'),
  //     ['starred'],
  //     true
  //   )
  //
  // Rationale for our own implementation of store.filter:
  //
  // The default implementation of filter is rather limited and misses a few
  // scenarios important to us. The problem is that when you use the default
  // store.filter implementation, it evaluates if a record should be added to a
  // filtered array only when a new record is added to the store or when a
  // property on a record itself changes. That means that we can't observe
  // computed properties that depend on anything else than defined properties.
  // Our implementation allows to pass dependencies as an optional argument,
  // which allows to pass any property as a dependency.
  //
  // One more change in relation to the default filter representation is that
  // the default store.filter implementation will always fetch new records. The
  // new implementation has an identity map built in and it will always fetch
  // the same array for the same set of arguments. Thanks to that running
  // store.filter multiple times will return immediately on the second and
  // subsequent tries.
  //
  // If you need to also fetch new results each time the function is run, you
  // can set forceReload option to true, but it will still resolve immediately
  // once a first query is already finished.
  //
  // For more info you may also see comments in FilteredArraysManager.
  filter(modelName, queryParams, filterFunction, dependencies, forceReload) {
    if (!dependencies) {
      // just do what filter would normally do
      return this._super(...arguments);
    } else {
      return this.filteredArraysManager.fetchArray(...arguments);
    }
  },

  // Returns a collection with pagination data. If the first page is requested,
  // the collection will be live updated. Otherwise keeping the calculations and
  // figuring out if the record should be put on the page is not easily
  // achieveable (or even impossible in some cases).
  //
  // modelName   - a type of the model as a string, for example 'repo'
  // queryParams - params for a store.query call that will be fired to fetch the
  //               data from the server
  // options     - additional options:
  //               filter      - a filter function that will be used to test if a
  //                             record should be added or removed from the array. It
  //                             will be called with a record under test as an
  //                             argument. It only matters for live updates
  //               sort        - either a string or a function to sort the collection
  //                             with. If it's a string, it should be the name of the
  //                             property to sort by, with an optional ':asc' or
  //                             ':desc' suffixes, for example 'id:desc'. If it's a
  //                             function it will be called with 2 records to compare
  //                             as an argument
  //               dependencies - a set of dependencies that will be watched to
  //                              re-evaluate if a record should be a part of a
  //                              collection
  //               forceReload  - if set to true, store.query will be run on
  //                              call
  //
  // Examples:
  //
  //   store.paginated(
  //     'repo',
  //     { active: true, offset: 0, limit: 10 },
  //     {
  //       filter: (repo) => repo.get('active'),
  //       sort: 'id:desc',
  //       dependencies: ['active'],
  //       forceReload: true
  //     }
  //
  paginated(modelName, queryParams, options) {
    if (!queryParams.offset) {
      // we're on the first page, live updates can be enabled
      return fetchLivePaginatedCollection(this, ...arguments);
    } else {
      return PaginatedCollectionPromise.create({
        content: this.query(...arguments)
      });
    }
  },

  addPusherEventHandlerGuard(name, callback) {
    return this.get('pusherEventHandlerGuards')[name] = callback;
  },

  removePusherEventHandlerGuard(name) {
    return delete this.get('pusherEventHandlerGuards')[name];
  },

  canHandleEvent(event, data) {
    let callback, name, ref, ref1;
    ref = event.split(':');
    name = ref[0];
    ref1 = this.get('pusherEventHandlerGuards');
    for (name in ref1) {
      callback = ref1[name];
      if (!callback(event, data)) {
        return false;
      }
    }
    return true;
  },

  receivePusherEvent(event, data) {
    let build, commit, job, name, ref, ref1, ref2, type;
    ref = event.split(':');
    name = ref[0];
    type = ref[1];

    if (!this.canHandleEvent(event, data)) {
      return;
    }

    if (name === 'job' && ((ref1 = data.job) != null ? ref1.commit : void 0)) {
      this.push(this.normalize('commit', data.job.commit));
    }

    if (name === 'build' && ((ref2 = data.build) != null ? ref2.commit : void 0)) {
      build = data.build;
      commit = {
        id: build.commit_id,
        author_email: build.author_email,
        author_name: build.author_name,
        branch: build.branch,
        committed_at: build.committed_at,
        committer_email: build.committer_email,
        committer_name: build.committer_name,
        compare_url: build.compare_url,
        message: build.message,
        sha: build.commit
      };
      delete data.build.commit;
      this.push(this.normalize('commit', commit));
    }

    if (name === 'branch') {
      // force reload of repo branches
      // delay to resolve race between github-sync and live
      const branchName = data.branch;

      later(() => {
        this.findRecord('branch', `/repo/${data.repository_id}/branch/${branchName}`);
      }, config.intervals.branchCreatedSyncDelay);

      delete data.branch;
    }

    if (event === 'job:log') {
      data = data.job;
      job = this.recordForId('job', data.id);
      return job.appendLog({
        number: parseInt(data.number),
        content: data._log,
        final: data.final
      });
    } else if (data[name]) {
      return this.loadOne(name, data);
    } else {
      if (!type) {
        throw `can't load data for ${name}`;
      }
    }
  },

  loadOne(type, json) {
    let data, default_branch, last_build_id;

    this.push(this.normalize(type, json));

    // we get other types of records only in a few situations and
    // it's not always needed to update data, so I'm specyfing which
    // things I want to update here:
    if (type === 'build' && (json.repository || json.repo)) {
      data = json.repository || json.repo;
      default_branch = data.default_branch;
      if (default_branch) {
        default_branch.default_branch = true;
        default_branch['@href'] = `/repo/${data.id}/branch/${default_branch.name}`;
      }
      last_build_id = default_branch.last_build_id;

      // a build is a synchronous relationship on a branch model, so we need to
      // have a build record present when we put default_branch from a repository
      // model into the store. We don't send last_build's payload in pusher, so
      // we need to get it here, if it's not already in the store. In the future
      // we may decide to make this relationship async, but I don't want to
      // change the code at the moment
      let lastBuild = this.peekRecord('build', last_build_id);
      if (!last_build_id || lastBuild) {
        return this.push(this.normalize('repo', data));
      } else {
        return this.findRecord('build', last_build_id).then(() => {
          this.push(this.normalize('repo', data));
        });
      }
    }
  }
});
<commit_msg>Remove pusher event handle guards<commit_after>/* eslint-disable camelcase */
import { later } from '@ember/runloop';
import DS from 'ember-data';
import PaginatedCollectionPromise from 'travis/utils/paginated-collection-promise';
import config from 'travis/config/environment';
import { service } from 'ember-decorators/service';
import FilteredArrayManager from 'travis/utils/filtered-array-manager';
import fetchLivePaginatedCollection from 'travis/utils/fetch-live-paginated-collection';

export default DS.Store.extend({
  @service auth: null,

  defaultAdapter: 'application',
  adapter: 'application',

  init() {
    this._super(...arguments);
    this.filteredArraysManager = FilteredArrayManager.create({ store: this });
  },

  // Fetch a filtered collection.
  //
  // modelName      - a type of the model passed as a string, for example 'repo'
  // queryParams    - params that will be passed to the store.query function when
  //                  fetching records on the initial call. Passing null or
  //                  undefined here will stop any requests from happening,
  //                  filtering will be based only on existing records
  // filterFunction - a function that will be called to determine wheather a
  //                  record should be included in the filtered collection. A
  //                  passed function will be called with a record as an
  //                  argument
  // dependencies   - a list of dependencies that will trigger the re-evaluation
  //                  of a record. When one of the dependencies changes on any
  //                  of the records in the store, it may be added or removed
  //                  from a filtered array.
  // forceReload    - if set to true, store.query will be run on each call
  //                  instead of only running it on the first run
  //
  // Example:
  //
  //   store.filter(
  //     'repo',
  //     { starred: true },
  //     (repo) => repo.get('starred'),
  //     ['starred'],
  //     true
  //   )
  //
  // Rationale for our own implementation of store.filter:
  //
  // The default implementation of filter is rather limited and misses a few
  // scenarios important to us. The problem is that when you use the default
  // store.filter implementation, it evaluates if a record should be added to a
  // filtered array only when a new record is added to the store or when a
  // property on a record itself changes. That means that we can't observe
  // computed properties that depend on anything else than defined properties.
  // Our implementation allows to pass dependencies as an optional argument,
  // which allows to pass any property as a dependency.
  //
  // One more change in relation to the default filter representation is that
  // the default store.filter implementation will always fetch new records. The
  // new implementation has an identity map built in and it will always fetch
  // the same array for the same set of arguments. Thanks to that running
  // store.filter multiple times will return immediately on the second and
  // subsequent tries.
  //
  // If you need to also fetch new results each time the function is run, you
  // can set forceReload option to true, but it will still resolve immediately
  // once a first query is already finished.
  //
  // For more info you may also see comments in FilteredArraysManager.
  filter(modelName, queryParams, filterFunction, dependencies, forceReload) {
    if (!dependencies) {
      // just do what filter would normally do
      return this._super(...arguments);
    } else {
      return this.filteredArraysManager.fetchArray(...arguments);
    }
  },

  // Returns a collection with pagination data. If the first page is requested,
  // the collection will be live updated. Otherwise keeping the calculations and
  // figuring out if the record should be put on the page is not easily
  // achieveable (or even impossible in some cases).
  //
  // modelName   - a type of the model as a string, for example 'repo'
  // queryParams - params for a store.query call that will be fired to fetch the
  //               data from the server
  // options     - additional options:
  //               filter      - a filter function that will be used to test if a
  //                             record should be added or removed from the array. It
  //                             will be called with a record under test as an
  //                             argument. It only matters for live updates
  //               sort        - either a string or a function to sort the collection
  //                             with. If it's a string, it should be the name of the
  //                             property to sort by, with an optional ':asc' or
  //                             ':desc' suffixes, for example 'id:desc'. If it's a
  //                             function it will be called with 2 records to compare
  //                             as an argument
  //               dependencies - a set of dependencies that will be watched to
  //                              re-evaluate if a record should be a part of a
  //                              collection
  //               forceReload  - if set to true, store.query will be run on
  //                              call
  //
  // Examples:
  //
  //   store.paginated(
  //     'repo',
  //     { active: true, offset: 0, limit: 10 },
  //     {
  //       filter: (repo) => repo.get('active'),
  //       sort: 'id:desc',
  //       dependencies: ['active'],
  //       forceReload: true
  //     }
  //
  paginated(modelName, queryParams, options) {
    if (!queryParams.offset) {
      // we're on the first page, live updates can be enabled
      return fetchLivePaginatedCollection(this, ...arguments);
    } else {
      return PaginatedCollectionPromise.create({
        content: this.query(...arguments)
      });
    }
  },

  receivePusherEvent(event, data) {
    let build, commit, job, name, ref, ref1, ref2, type;
    ref = event.split(':');
    name = ref[0];
    type = ref[1];

    if (name === 'job' && ((ref1 = data.job) != null ? ref1.commit : void 0)) {
      this.push(this.normalize('commit', data.job.commit));
    }

    if (name === 'build' && ((ref2 = data.build) != null ? ref2.commit : void 0)) {
      build = data.build;
      commit = {
        id: build.commit_id,
        author_email: build.author_email,
        author_name: build.author_name,
        branch: build.branch,
        committed_at: build.committed_at,
        committer_email: build.committer_email,
        committer_name: build.committer_name,
        compare_url: build.compare_url,
        message: build.message,
        sha: build.commit
      };
      delete data.build.commit;
      this.push(this.normalize('commit', commit));
    }

    if (name === 'branch') {
      // force reload of repo branches
      // delay to resolve race between github-sync and live
      const branchName = data.branch;

      later(() => {
        this.findRecord('branch', `/repo/${data.repository_id}/branch/${branchName}`);
      }, config.intervals.branchCreatedSyncDelay);

      delete data.branch;
    }

    if (event === 'job:log') {
      data = data.job;
      job = this.recordForId('job', data.id);
      return job.appendLog({
        number: parseInt(data.number),
        content: data._log,
        final: data.final
      });
    } else if (data[name]) {
      return this.loadOne(name, data);
    } else {
      if (!type) {
        throw `can't load data for ${name}`;
      }
    }
  },

  loadOne(type, json) {
    let data, default_branch, last_build_id;

    this.push(this.normalize(type, json));

    // we get other types of records only in a few situations and
    // it's not always needed to update data, so I'm specyfing which
    // things I want to update here:
    if (type === 'build' && (json.repository || json.repo)) {
      data = json.repository || json.repo;
      default_branch = data.default_branch;
      if (default_branch) {
        default_branch.default_branch = true;
        default_branch['@href'] = `/repo/${data.id}/branch/${default_branch.name}`;
      }
      last_build_id = default_branch.last_build_id;

      // a build is a synchronous relationship on a branch model, so we need to
      // have a build record present when we put default_branch from a repository
      // model into the store. We don't send last_build's payload in pusher, so
      // we need to get it here, if it's not already in the store. In the future
      // we may decide to make this relationship async, but I don't want to
      // change the code at the moment
      let lastBuild = this.peekRecord('build', last_build_id);
      if (!last_build_id || lastBuild) {
        return this.push(this.normalize('repo', data));
      } else {
        return this.findRecord('build', last_build_id).then(() => {
          this.push(this.normalize('repo', data));
        });
      }
    }
  }
});
<|endoftext|>


<commit_before>const CUSTOM_PROPERTY_REGEX = /^--/;
const DEFAULT_STYLES = document.createElement("div").style;
const VENDOR_PREFIXES = ["Webkit", "Moz", "ms"];
const propertyNameCache = {};
// DOM properties that should NOT have "px" added when numeric
const IS_NON_DIMENSIONAL = /acit|ex(?:s|g|n|p|$)|rph|ows|mnc|ntw|ine[ch]|zoo|^ord/i;

/**
 * Returns the normalized (like vendor-prefixed) name of the given CSS property
 *
 * @param {string} property
 * @return {string}
 */
function normalizeProperty (property)
{
    if (propertyNameCache[property])
    {
        return propertyNameCache[property];
    }

    // if the property already exists, just use it
    if (property in DEFAULT_STYLES)
    {
        return property;
    }

    const capitalized = property[0].toUpperCase() + property.slice(1);

    for (let i = 0; i < VENDOR_PREFIXES.length; i++)
    {
        const prefixedName = `${VENDOR_PREFIXES[i]}${capitalized}`;

        if (prefixedName in DEFAULT_STYLES)
        {
            propertyNameCache[property] = prefixedName;
            return prefixedName;
        }
    }

    propertyNameCache[property] = property;
    return property;
}

/**
 * Sets all styles on the element
 *
 * @param {HTMLElement|HTMLElement[]} elements
 * @param {Object} styles
 */
export function setStyles (elements, styles)
{
    elements = Array.isArray(elements) ? elements : [elements];

    for (let i = 0; i < elements.length; i++)
    {
        const element = elements[i];
        const style = element.style;

        for (let property in styles)
        {
            if (!styles.hasOwnProperty(property))
            {
                continue;
            }

            // add "px" to all numbers of dimensional values
            const value = typeof styles[property] === "number" && false === IS_NON_DIMENSIONAL.test(property)
                ? `${styles[property]}px`
                : styles[property];

            if (CUSTOM_PROPERTY_REGEX.test(property))
            {
                style.setProperty(property, value);
            }
            else
            {
                property = normalizeProperty(property);
                style[property] = value;
            }
        }
    }
}

/**
 * Returns the computed styles for the given element
 *
 * @param {HTMLElement} element
 * @param {?string} pseudoElement
 * @return {CssStyle}
 */
function getComputedStyles (element, pseudoElement)
{
    // @legacy IE <= 11
    // IE throws on elements created in popups
    let view = element.ownerDocument.defaultView;

    if (!view || !view.opener)
    {
        view = window;
    }

    return view.getComputedStyle(element, pseudoElement);
}

/**
 * Returns the CSS property value for the given propery and element
 *
 * @param {HTMLElement} element
 * @param {string} property
 * @param {?string} pseudoElement
 * @return {string}
 */
export function getStyle (element, property, pseudoElement = null)
{
    if (!CUSTOM_PROPERTY_REGEX.test(property))
    {
        property = normalizeProperty(property);
    }

    const styles = getComputedStyles(element, pseudoElement);
    // getPropertyValue is needed for:
    //   .css('--customProperty) (#3144)
    const value = styles.getPropertyValue(property) || styles[property];

    // always return a value for opacity, the default is "1"
    if ("opacity" === property)
    {
        return value === "" ? "1" : value;
    }

    return value !== undefined
        ? value + ""
        : value;
}
<commit_msg>Update comment to fit code style<commit_after>const CUSTOM_PROPERTY_REGEX = /^--/;
const DEFAULT_STYLES = document.createElement("div").style;
const VENDOR_PREFIXES = ["Webkit", "Moz", "ms"];
const propertyNameCache = {};
// DOM properties that should NOT have "px" added when numeric
const IS_NON_DIMENSIONAL = /acit|ex(?:s|g|n|p|$)|rph|ows|mnc|ntw|ine[ch]|zoo|^ord/i;

/**
 * Returns the normalized (like vendor-prefixed) name of the given CSS property
 *
 * @param {string} property
 * @return {string}
 */
function normalizeProperty (property)
{
    if (propertyNameCache[property])
    {
        return propertyNameCache[property];
    }

    // if the property already exists, just use it
    if (property in DEFAULT_STYLES)
    {
        return property;
    }

    const capitalized = property[0].toUpperCase() + property.slice(1);

    for (let i = 0; i < VENDOR_PREFIXES.length; i++)
    {
        const prefixedName = `${VENDOR_PREFIXES[i]}${capitalized}`;

        if (prefixedName in DEFAULT_STYLES)
        {
            propertyNameCache[property] = prefixedName;
            return prefixedName;
        }
    }

    propertyNameCache[property] = property;
    return property;
}

/**
 * Sets all styles on the element
 *
 * @param {HTMLElement|HTMLElement[]} elements
 * @param {Object} styles
 */
export function setStyles (elements, styles)
{
    elements = Array.isArray(elements) ? elements : [elements];

    for (let i = 0; i < elements.length; i++)
    {
        const element = elements[i];
        const style = element.style;

        for (let property in styles)
        {
            if (!styles.hasOwnProperty(property))
            {
                continue;
            }

            // add "px" to all numbers of dimensional values
            const value = typeof styles[property] === "number" && false === IS_NON_DIMENSIONAL.test(property)
                ? `${styles[property]}px`
                : styles[property];

            if (CUSTOM_PROPERTY_REGEX.test(property))
            {
                style.setProperty(property, value);
            }
            else
            {
                property = normalizeProperty(property);
                style[property] = value;
            }
        }
    }
}

/**
 * Returns the computed styles for the given element
 *
 * @param {HTMLElement} element
 * @param {?string} pseudoElement
 * @return {CssStyle}
 */
function getComputedStyles (element, pseudoElement)
{
    // @legacy IE <= 11
    // IE throws on elements created in popups
    let view = element.ownerDocument.defaultView;

    if (!view || !view.opener)
    {
        view = window;
    }

    return view.getComputedStyle(element, pseudoElement);
}

/**
 * Returns the CSS property value for the given propery and element
 *
 * @param {HTMLElement} element
 * @param {string} property
 * @param {?string} pseudoElement
 * @return {string}
 */
export function getStyle (element, property, pseudoElement = null)
{
    if (!CUSTOM_PROPERTY_REGEX.test(property))
    {
        property = normalizeProperty(property);
    }

    const styles = getComputedStyles(element, pseudoElement);
    // getPropertyValue is needed for:
    //   getStyle(el, '--customProperty')
    const value = styles.getPropertyValue(property) || styles[property];

    // always return a value for opacity, the default is "1"
    if ("opacity" === property)
    {
        return value === "" ? "1" : value;
    }

    return value !== undefined
        ? value + ""
        : value;
}
<|endoftext|>


<commit_before>/* -----------------------------

TEXTING DOORMAT
Justin Smith - justin@isamaker.com
@justinIsAMaker

Listen for a pressure sensor to register over a certain number, then text me via Twilio
------------------------------ */

// Require Node libraries
var mraa = require('mraa');
var request = require('request');

//TWILIO
var twilio = require('twilio');
var client = new twilio.RestClient(
	'[ INSERT TWILIO PUBLIC KEY ]',
	'[ INSERT TWILIO PRIVATE KEY ]'
);

// Declare the sensor
var pressureSensor = new mraa.Aio(0);

// Declare the buzzer
var buzzer = new mraa.Gpio(6);
buzzer.dir(mraa.DIR_OUT);

console.log('MRAA Version: ' + mraa.getVersion());

function init(){
	checkForGuest();
}

function checkForGuest(){
	var guestPresent = pressureSensor.read();

	if(guestPresent >= 400){
		buzzer.write(1);
		console.log(guestPresent);

		client.sms.messages.create({
			to:'[ INSERT TARGET PHONE NUMBER ]',
			from:'+1[ INSERT TWILIO PHONE NUMBER ]',
			body: 'Your guest has arrived!'
		}, function(error, message){
			if(!error){
				console.log(message);
			} else {
				console.log(error);
			}
		});
		setTimeout(function(){
			buzzer.write(0);
			setTimeout(checkForGuest, 100);
		}, 5000);
	} else {
	setTimeout(checkForGuest, 100);
	}
} // END CHECK BUTTON PRESSED

init();
<commit_msg>Change the text message content<commit_after>/* -----------------------------

TEXTING DOORMAT
Justin Smith - justin@isamaker.com
@justinIsAMaker

Listen for a pressure sensor to register over a certain number, then text me via Twilio
------------------------------ */

// Require Node libraries
var mraa = require('mraa');
var request = require('request');

//TWILIO
var twilio = require('twilio');
var client = new twilio.RestClient(
	'[ INSERT TWILIO PUBLIC KEY ]',
	'[ INSERT TWILIO PRIVATE KEY ]'
);

// Declare the sensor
var pressureSensor = new mraa.Aio(0);

// Declare the buzzer
var buzzer = new mraa.Gpio(6);
buzzer.dir(mraa.DIR_OUT);

console.log('MRAA Version: ' + mraa.getVersion());

function init(){
	checkForGuest();
}

function checkForGuest(){
	var guestPresent = pressureSensor.read();
	console.log(guestPresent);
	if(guestPresent >= 400){
		buzzer.write(1);
		console.log('PRESENT: ' + guestPresent);

		client.sms.messages.create({
			to:'[ INSERT TARGET PHONE NUMBER ]',
			from:'+1[ INSERT TWILIO PHONE NUMBER ]',
			body: 'Head\'s up, someone is outside'
		}, function(error, message){
			if(!error){
				console.log(message);
			} else {
				console.log(error);
			}
		});
		setTimeout(function(){
			buzzer.write(0);
			setTimeout(checkForGuest, 100);
		}, 5000);
	} else {
	setTimeout(checkForGuest, 100);
	}
} // END CHECK BUTTON PRESSED

init();
<|endoftext|>


<commit_before>'use strict';
const fs = require('fs');
const fpath = require('path');
const utils = require('./utils.js');

function writeTestToFile(path, content) {
  fs.writeFile(path, content, (err) => {
    if (err) {
      utils.die(err);
    }
    console.log('Test written to ' + path); // eslint-disable-line
  });
}

export default function createTest(clientFunction, requestTransformer, responseTransformer,
                                   request, transformedRequest, response, transformedResponse, path, description) {

  if (utils.isDir(fpath.dirname(path)) === false) {
    utils.die('Test directory ' + fpath.dirname(path) + ' dosn\'t exist');
  }

  var cf_name = utils.functionName(clientFunction);
  var reqt_name = utils.functionName(requestTransformer);
  var rept_name = utils.functionName(responseTransformer);

  if (description === 'undefined') {
    description = 'Test Transformers (' + reqt_name + ' and ' + rept_name + ') used with client "' + cf_name + '"';
  }

  var content = ['\'use strict\';',
                 'import {expect} from \'chai\';',
                 '',
                 '// PLEASE INSERT NECESSARY REQUIRES FOR THE FOLLOWING FUNCTIONS: ',
                 '// ' + cf_name,
                 '// ' + reqt_name,
                 '// ' + rept_name,
                 '',
                 'describe(\'' + description + '\', () => {',
                 '',
                 '  it(\'Testing output of requestTransformer "' + reqt_name + '"\', (done) => {',
                 '',
                 '    let requestTransformerInput = ' + JSON.stringify(request) + ';',
                 '    let requestTransformeroutput = ' + JSON.stringify(transformedRequest) + ';',
                 '',
                 '    expect(' + reqt_name + '(requestTransformerInput)).to.equal(requestTransformeroutput);',
                 '    done();',
                 '  });',
                 '',
                 '  it(\'Testing output of responseTransformer "' + rept_name + '"\', (done) => {',
                 '',
                 '    let responseTransformerInput = ' + JSON.stringify(response) + ';',
                 '    let responseTransformeroutput = ' + JSON.stringify(transformedResponse) + ';',
                 '',
                 '    expect(' + rept_name + '(responseTransformerInput)).to.equal(responseTransformeroutput);',
                 '    done();',
                 '  });',
                 '});'].join('\n');

  writeTestToFile(path, content);
}
<commit_msg>Changed createTest to handle nested transformers<commit_after>'use strict';
const fs = require('fs');
const fpath = require('path');
const utils = require('./utils.js');

function writeTestToFile(path, content) {
  fs.writeFileSync(path, content, 'utf8');
  console.log('Test written to ' + path); // eslint-disable-line
}

function test2Str(type, transformerName, raw, transformed) {

  return ['  it(\'Testing output of ' + type + 'Transformer "' + transformerName + '"\', (done) => {',
          '',
          '    let ' + type + 'TransformerInput = ' + JSON.stringify(raw) + ';',
          '    let ' + type + 'TransformerOutput = ' + JSON.stringify(transformed) + ';',
          '',
          '    expect(' + transformerName + '(' + type + 'TransformerInput)).to.equal(' + type + 'TransformerOutput);',
          '    done();',
          '  });',
          '',
          ''].join('\n');

}

export default function createTest(clientFunction, requestTransformer, responseTransformer,
                                   request, transformedRequest, response, transformedResponse, path, description) {

  if (utils.isDir(fpath.dirname(path)) === false) {
    utils.die('Test directory ' + fpath.dirname(path) + ' dosn\'t exist');
  }

  var cf_name = utils.functionName(clientFunction);
  var reqt_name = utils.functionName(requestTransformer);
  var rept_name = utils.functionName(responseTransformer);

  if (!fs.existsSync(path)) {

    if (description === 'undefined') {
      description = 'Test Transformers (' + reqt_name + ' and ' + rept_name + ') used with client "' + cf_name + '"';
    }

    let content = ['\'use strict\';',
                   'import {expect} from \'chai\';',
                   '',
                   '// PLEASE INSERT NECESSARY REQUIRES FOR THE FOLLOWING FUNCTIONS: ',
                   '// ' + cf_name,
                   '// ' + reqt_name,
                   '// ' + rept_name,
                   '',
                   'describe(\'' + description + '\', () => {',
                   '',
                   ''].join('\n') +
                   test2Str('request', reqt_name, request, transformedRequest) +
                   test2Str('response', rept_name, response, transformedResponse) +
                   ['});'].join('\n');

    writeTestToFile(path, content);
  }
  else {

    let newContent = fs.readFileSync(path, 'utf8');
    let contentSplit = newContent.split(/(\/\/(\/|[\s\S])*\/\/.*)/);
    contentSplit[1] += '\n// ' + cf_name + '\n// ' + reqt_name +'\n// ' + rept_name;
    newContent = contentSplit.join('');

    contentSplit = newContent.split('\n');
    contentSplit[contentSplit.length - 2] += '\n' +
      test2Str('request', reqt_name, request, transformedRequest) +
      test2Str('response', rept_name, response, transformedResponse);

    newContent = contentSplit.join('\n');
    writeTestToFile(path, newContent);
  }
}
<|endoftext|>


<commit_before>/**
 * @main
 * @module hammer
 *
 * @class Hammer
 * @static
 */

/**
 * Hammer, use this to create instances
 * ````
 * var hammertime = new Hammer(myElement);
 * ````
 *
 * @method Hammer
 * @param {HTMLElement} element
 * @param {Object} [options={}]
 * @return {Hammer.Instance}
 */
var Hammer = function Hammer(element, options) {
  return new Hammer.Instance(element, options || {});
};

/**
 * version, as defined in package.json
 * the value will be set at each build
 * @property VERSION
 * @final
 * @type {String}
 */
Hammer.VERSION = '{{PKG_VERSION}}';

/**
 * default settings.
 * more settings are defined per gesture at `/gestures`. Each gesture can be disabled/enabled
 * by setting it's name (like `swipe`) to false.
 * You can set the defaults for all instances by changing this object before creating an instance.
 * @example
 * ````
 *  Hammer.defaults.drag = false;
 *  Hammer.defaults.stop_browser_behavior.touchAction = 'pan-y';
 *  delete Hammer.defaults.stop_browser_behavior.userSelect;
 * ````
 * @property defaults
 * @type {Object}
 */
Hammer.defaults = {
  /**
   * this setting object adds styles and attributes to the element to prevent the browser from doing
   * its native behavior. The css properties are auto prefixed for the browsers when needed.
   * @property defaults.stop_browser_behavior
   * @type {Object}
   */
  stop_browser_behavior: {
    /**
     * Disables text selection to improve the dragging gesture. When the value is `none` it also sets
     * `onselectstart=false` for IE on the element. Mainly for desktop browsers.
     * @property defaults.stop_browser_behavior.userSelect
     * @type {String}
     * @default 'none'
     */
    userSelect: 'none',

    /**
     * Specifies whether and how a given region can be manipulated by the user (for instance, by panning or zooming).
     * Used by IE10>. By default this makes the element blocking any touch event.
     * @property defaults.stop_browser_behavior.touchAction
     * @type {String}
     * @default: 'none'
     */
    touchAction: 'none',

    /**
     * Disables the default callout shown when you touch and hold a touch target.
     * On iOS, when you touch and hold a touch target such as a link, Safari displays
     * a callout containing information about the link. This property allows you to disable that callout.
     * @property defaults.stop_browser_behavior.touchCallout
     * @type {String}
     * @default 'none'
     */
    touchCallout: 'none',

    /**
     * Specifies whether zooming is enabled. Used by IE10>
     * @property defaults.stop_browser_behavior.contentZooming
     * @type {String}
     * @default 'none'
     */
    contentZooming: 'none',

    /**
     * Specifies that an entire element should be draggable instead of its contents.
     * Mainly for desktop browsers.
     * @property defaults.stop_browser_behavior.userDrag
     * @type {String}
     * @default 'none'
     */
    userDrag: 'none',

    /**
     * Overrides the highlight color shown when the user taps a link or a JavaScript
     * clickable element in Safari on iPhone. This property obeys the alpha value, if specified.
     *
     * If you don’t specify an alpha value, Safari on iPhone applies a default alpha value
     * to the color. To disable tap highlighting, set the alpha value to 0 (invisible).
     * If you set the alpha value to 1.0 (opaque), the element is not visible when tapped.
     * @property defaults.stop_browser_behavior.tapHighlightColor
     * @type {String}
     * @default 'rgba(0,0,0,0)'
     */
    tapHighlightColor: 'rgba(0,0,0,0)'
  }
};

/**
 * hammer document where the base events are added at
 * @property DOCUMENT
 * @type {HTMLElement}
 * @default window.document
 */
Hammer.DOCUMENT = window.document;

/**
 * detect support for pointer events
 * @property HAS_POINTEREVENTS
 * @type {Boolean}
 */
Hammer.HAS_POINTEREVENTS = window.navigator.pointerEnabled || window.navigator.msPointerEnabled;

/**
 * detect support for touch events
 * @property HAS_TOUCHEVENTS
 * @type {Boolean}
 */
Hammer.HAS_TOUCHEVENTS = ('ontouchstart' in window);

/**
 * interval in which Hammer recalculates current velocity/direction/angle in ms
 * @property CALCULATE_INTERVAL
 * @type {Number}
 * @default 16
 */
Hammer.CALCULATE_INTERVAL = 16;

/**
 * eventtypes per touchevent (start, move, end) are filled by `Event.determineEventTypes` on `setup`
 * the object contains the DOM event names per type (`EVENT_START`, `EVENT_MOVE`, `EVENT_END`)
 * @property EVENT_TYPES
 * @private
 * @writeOnce
 * @type {Object}
 */
var EVENT_TYPES = {};

/**
 * direction strings, for safe comparisons
 * @property DIRECTION_DOWN|LEFT|UP|RIGHT
 * @final
 * @type {String}
 * @default 'down' 'left' 'up' 'right'
 */
var DIRECTION_DOWN = Hammer.DIRECTION_DOWN = 'down';
var DIRECTION_LEFT = Hammer.DIRECTION_LEFT = 'left';
var DIRECTION_UP = Hammer.DIRECTION_UP = 'up';
var DIRECTION_RIGHT = Hammer.DIRECTION_RIGHT = 'right';

/**
 * pointertype strings, for safe comparisons
 * @property POINTER_MOUSE|TOUCH|PEN
 * @final
 * @type {String}
 * @default 'mouse' 'touch' 'pen'
 */
var POINTER_MOUSE = Hammer.POINTER_MOUSE = 'mouse';
var POINTER_TOUCH = Hammer.POINTER_TOUCH = 'touch';
var POINTER_PEN = Hammer.POINTER_PEN = 'pen';

/**
 * eventtypes
 * @property EVENT_START|MOVE|END|RELEASE|TOUCH
 * @final
 * @type {String}
 * @default 'start' 'change' 'move' 'end' 'release' 'touch'
 */
var EVENT_START = Hammer.EVENT_START = 'start';
var EVENT_MOVE = Hammer.EVENT_MOVE = 'move';
var EVENT_END = Hammer.EVENT_END = 'end';
var EVENT_RELEASE = Hammer.EVENT_RELEASE = 'release';
var EVENT_TOUCH = Hammer.EVENT_TOUCH = 'touch';

/**
 * if the window events are set...
 * @property READY
 * @writeOnce
 * @type {Boolean}
 * @default false
 */
Hammer.READY = false;

/**
 * plugins namespace
 * @property plugins
 * @type {Object}
 */
Hammer.plugins = Hammer.plugins || {};

/**
 * gestures namespace
 * see `/gestures` for the definitions
 * @property gestures
 * @type {Object}
 */
Hammer.gestures = Hammer.gestures || {};

/**
 * setup events to detect gestures on the document
 * this function is called when creating an new instance
 * @private
 */
function setup() {
  if(Hammer.READY) {
    return;
  }

  // find what eventtypes we add listeners to
  Event.determineEventTypes();

  // Register all gestures inside Hammer.gestures
  Utils.each(Hammer.gestures, function(gesture){
    Detection.register(gesture);
  });

  // Add touch events on the document
  Event.onTouch(Hammer.DOCUMENT, EVENT_MOVE, Detection.detect);
  Event.onTouch(Hammer.DOCUMENT, EVENT_END, Detection.detect);

  // Hammer is ready...!
  Hammer.READY = true;
}<commit_msg>save char<commit_after>/**
 * @main
 * @module hammer
 *
 * @class Hammer
 * @static
 */

/**
 * Hammer, use this to create instances
 * ````
 * var hammertime = new Hammer(myElement);
 * ````
 *
 * @method Hammer
 * @param {HTMLElement} element
 * @param {Object} [options={}]
 * @return {Hammer.Instance}
 */
var Hammer = function Hammer(element, options) {
  return new Hammer.Instance(element, options || {});
};

/**
 * version, as defined in package.json
 * the value will be set at each build
 * @property VERSION
 * @final
 * @type {String}
 */
Hammer.VERSION = '{{PKG_VERSION}}';

/**
 * default settings.
 * more settings are defined per gesture at `/gestures`. Each gesture can be disabled/enabled
 * by setting it's name (like `swipe`) to false.
 * You can set the defaults for all instances by changing this object before creating an instance.
 * @example
 * ````
 *  Hammer.defaults.drag = false;
 *  Hammer.defaults.stop_browser_behavior.touchAction = 'pan-y';
 *  delete Hammer.defaults.stop_browser_behavior.userSelect;
 * ````
 * @property defaults
 * @type {Object}
 */
Hammer.defaults = {
  /**
   * this setting object adds styles and attributes to the element to prevent the browser from doing
   * its native behavior. The css properties are auto prefixed for the browsers when needed.
   * @property defaults.stop_browser_behavior
   * @type {Object}
   */
  stop_browser_behavior: {
    /**
     * Disables text selection to improve the dragging gesture. When the value is `none` it also sets
     * `onselectstart=false` for IE on the element. Mainly for desktop browsers.
     * @property defaults.stop_browser_behavior.userSelect
     * @type {String}
     * @default 'none'
     */
    userSelect: 'none',

    /**
     * Specifies whether and how a given region can be manipulated by the user (for instance, by panning or zooming).
     * Used by IE10>. By default this makes the element blocking any touch event.
     * @property defaults.stop_browser_behavior.touchAction
     * @type {String}
     * @default: 'none'
     */
    touchAction: 'none',

    /**
     * Disables the default callout shown when you touch and hold a touch target.
     * On iOS, when you touch and hold a touch target such as a link, Safari displays
     * a callout containing information about the link. This property allows you to disable that callout.
     * @property defaults.stop_browser_behavior.touchCallout
     * @type {String}
     * @default 'none'
     */
    touchCallout: 'none',

    /**
     * Specifies whether zooming is enabled. Used by IE10>
     * @property defaults.stop_browser_behavior.contentZooming
     * @type {String}
     * @default 'none'
     */
    contentZooming: 'none',

    /**
     * Specifies that an entire element should be draggable instead of its contents.
     * Mainly for desktop browsers.
     * @property defaults.stop_browser_behavior.userDrag
     * @type {String}
     * @default 'none'
     */
    userDrag: 'none',

    /**
     * Overrides the highlight color shown when the user taps a link or a JavaScript
     * clickable element in Safari on iPhone. This property obeys the alpha value, if specified.
     *
     * If you don't specify an alpha value, Safari on iPhone applies a default alpha value
     * to the color. To disable tap highlighting, set the alpha value to 0 (invisible).
     * If you set the alpha value to 1.0 (opaque), the element is not visible when tapped.
     * @property defaults.stop_browser_behavior.tapHighlightColor
     * @type {String}
     * @default 'rgba(0,0,0,0)'
     */
    tapHighlightColor: 'rgba(0,0,0,0)'
  }
};

/**
 * hammer document where the base events are added at
 * @property DOCUMENT
 * @type {HTMLElement}
 * @default window.document
 */
Hammer.DOCUMENT = window.document;

/**
 * detect support for pointer events
 * @property HAS_POINTEREVENTS
 * @type {Boolean}
 */
Hammer.HAS_POINTEREVENTS = window.navigator.pointerEnabled || window.navigator.msPointerEnabled;

/**
 * detect support for touch events
 * @property HAS_TOUCHEVENTS
 * @type {Boolean}
 */
Hammer.HAS_TOUCHEVENTS = ('ontouchstart' in window);

/**
 * interval in which Hammer recalculates current velocity/direction/angle in ms
 * @property CALCULATE_INTERVAL
 * @type {Number}
 * @default 16
 */
Hammer.CALCULATE_INTERVAL = 16;

/**
 * eventtypes per touchevent (start, move, end) are filled by `Event.determineEventTypes` on `setup`
 * the object contains the DOM event names per type (`EVENT_START`, `EVENT_MOVE`, `EVENT_END`)
 * @property EVENT_TYPES
 * @private
 * @writeOnce
 * @type {Object}
 */
var EVENT_TYPES = {};

/**
 * direction strings, for safe comparisons
 * @property DIRECTION_DOWN|LEFT|UP|RIGHT
 * @final
 * @type {String}
 * @default 'down' 'left' 'up' 'right'
 */
var DIRECTION_DOWN = Hammer.DIRECTION_DOWN = 'down';
var DIRECTION_LEFT = Hammer.DIRECTION_LEFT = 'left';
var DIRECTION_UP = Hammer.DIRECTION_UP = 'up';
var DIRECTION_RIGHT = Hammer.DIRECTION_RIGHT = 'right';

/**
 * pointertype strings, for safe comparisons
 * @property POINTER_MOUSE|TOUCH|PEN
 * @final
 * @type {String}
 * @default 'mouse' 'touch' 'pen'
 */
var POINTER_MOUSE = Hammer.POINTER_MOUSE = 'mouse';
var POINTER_TOUCH = Hammer.POINTER_TOUCH = 'touch';
var POINTER_PEN = Hammer.POINTER_PEN = 'pen';

/**
 * eventtypes
 * @property EVENT_START|MOVE|END|RELEASE|TOUCH
 * @final
 * @type {String}
 * @default 'start' 'change' 'move' 'end' 'release' 'touch'
 */
var EVENT_START = Hammer.EVENT_START = 'start';
var EVENT_MOVE = Hammer.EVENT_MOVE = 'move';
var EVENT_END = Hammer.EVENT_END = 'end';
var EVENT_RELEASE = Hammer.EVENT_RELEASE = 'release';
var EVENT_TOUCH = Hammer.EVENT_TOUCH = 'touch';

/**
 * if the window events are set...
 * @property READY
 * @writeOnce
 * @type {Boolean}
 * @default false
 */
Hammer.READY = false;

/**
 * plugins namespace
 * @property plugins
 * @type {Object}
 */
Hammer.plugins = Hammer.plugins || {};

/**
 * gestures namespace
 * see `/gestures` for the definitions
 * @property gestures
 * @type {Object}
 */
Hammer.gestures = Hammer.gestures || {};

/**
 * setup events to detect gestures on the document
 * this function is called when creating an new instance
 * @private
 */
function setup() {
  if(Hammer.READY) {
    return;
  }

  // find what eventtypes we add listeners to
  Event.determineEventTypes();

  // Register all gestures inside Hammer.gestures
  Utils.each(Hammer.gestures, function(gesture){
    Detection.register(gesture);
  });

  // Add touch events on the document
  Event.onTouch(Hammer.DOCUMENT, EVENT_MOVE, Detection.detect);
  Event.onTouch(Hammer.DOCUMENT, EVENT_END, Detection.detect);

  // Hammer is ready...!
  Hammer.READY = true;
}<|endoftext|>