<commit_before>// Copyright 2015, University of Colorado Boulder

/**
 * Tandem is a general instance registry that can be used to track creation/disposal of instances in PhET Simulations.
 * It is used for phetio.js instrumentation for PhET-iO support.
 *
 * @author Sam Reid (PhET Interactive Simulations)
 */
define( function( require ) {
  'use strict';

  // modules
  var inherit = require( 'PHET_CORE/inherit' );
  var tandemNamespace = require( 'TANDEM/tandemNamespace' );
  var toCamelCase = require( 'PHET_CORE/toCamelCase' );

  // text
  var packageString = require( 'text!REPOSITORY/package.json' );

  // constants
  var packageJSON = JSON.parse( packageString );

  // variables
  var launched = false;

  // increment names of required tandems to avoid collisions for uninstrumented sims with phetioValidateTandems=false
  var requiredTandemIndex = 0;

  // increment names of required tandems to avoid collisions for uninstrumented sims with phetioValidateTandems=false
  var optionalTandemIndex = 0;

  // increment names of required tandems to avoid collisions for uninstrumented sims with phetioValidateTandems=false
  var uninstrumentCodeIndex = 0;

  /**
   * @param {string} id - id as a string (or '' for a root id)
   * @param {Object} [options]
   * @constructor
   */
  function Tandem( id, options ) {

    options = _.extend( {
      static: false,
      enabled: true,
      tandemRequiredButNotSupplied: false, // When set to true, if there isn't a tandem supplied, it will fail out.
      tandemOptionalAndNotSupplied: false
    }, options );

    // @public (read-only)
    this.id = ( id !== undefined ) ? id : '';

    // @private (read-only)
    this.static = options.static;
    this.tandemRequiredButNotSupplied = options.tandemRequiredButNotSupplied;
    this.tandemOptionalAndNotSupplied = options.tandemOptionalAndNotSupplied;
    this.enabled = options.enabled;
  }

  var staticInstances = [];

  tandemNamespace.register( 'Tandem', Tandem );

  // Listeners that will be notified when items are registered/deregistered
  var instanceListeners = [];

  inherit( Object, Tandem, {

    // @public (read-only) permit checking whether something is probably a Tandem instance for error checking
    isTandem: true,

    /**
     * Adds an instance of any type.  For example, it could be an axon Property, scenery Node or Sun button.  Each
     * item should only be added to the registry once, but that is not enforced here in Tandem.  For PhET-iO, phet-io.js
     * enforces one entry per ID in phetio.addInstance
     *
     * This is used to register instances with PhET-iO.
     * @param {Object} instance - the instance to add
     * @param {function} type - the PhET-iO type function, such as TString or TProperty(TNumber('volts'))
     * @public
     */
    addInstance: function( instance, type ) {

      if ( window.phet && window.phet.chipper && phet.chipper.brand === 'phet-io' && this.enabled ) {

        if ( phet.phetio.queryParameters.phetioValidateTandems ) {
          assert && assert( !this.tandemRequiredButNotSupplied, 'Tandem was required but not supplied' );
        }

        // validateTandems is false and printMissingTandems flag is present for a tandem that is required but not supplied.
        else if ( phet.phetio.queryParameters.printMissingTandems && this.tandemRequiredButNotSupplied ) {
          var stackTrace = new Error().stack;
          console.log( 'Required Tandem not supplied.\n' +
                       'this.id = ' + this.id + '\n' +
                       'Stack trace: ' + stackTrace );
        }

        if ( !type ) {
          console.log( 'Missing type declaration for ' + this.id );
        }

        // ifphetio returns a no-op function, so to test whether a valid T wrapper type was passed, we search for the typeName
        assert && assert( type && type.typeName, 'type must be specified and have a typeName' );

        if ( this.tandemOptionalAndNotSupplied ) {
          if ( phet.phetio.queryParameters.printMissingTandems ) {
            var stackTrace2 = new Error().stack;

            // Generally PhETFont is not desired because there are so many untandemized instances.
            if ( stackTrace2.indexOf( 'PhetFont' ) === -1 ) {
              console.log( 'Optional Tandem not supplied.\n' +
                           'this.id = ' + this.id + '\n' +
                           'Stack trace: ' + stackTrace2 );
            }
          }

          // For optionally instrumented types that are not provided tandems, the instance isn't really "added"
          // but likewise, it in not an error
          return;
        }

        if ( this.static && !launched ) {
          staticInstances.push( { tandem: this, instance: instance, type: type } );
        }
        else {
          for ( var i = 0; i < instanceListeners.length; i++ ) {
            instanceListeners[ i ].addInstance( this.id, instance, type );
          }
        }
      }
    },

    /**
     * Removes an instance from the
     * @param {Object} instance - the instance to remove
     * @public
     */
    removeInstance: function( instance ) {

      // Only active when running as phet-io
      if ( phet.chipper.brand === 'phet-io' && this.enabled ) {
        for ( var i = 0; i < instanceListeners.length; i++ ) {
          instanceListeners[ i ].removeInstance( this.id, instance );
        }
      }
    },

    /**
     * Create a new Tandem by appending the given id
     * @param {string} id
     * @param {Object} [options]
     * @returns {Tandem}
     * @public
     */
    createTandem: function( id, options ) {

      // Make sure the id was provided
      assert && assert( typeof id === 'string' && id.length > 0, 'id must be defined' );

      var string = ( this.id.length > 0 ) ? ( this.id + '.' + id ) : id;

      // Any child of something static is also static
      options = _.extend( { static: this.static, enabled: this.enabled }, options );

      return new Tandem( string, options );
    },

    /**
     * Creates a group tandem for creating multiple indexed child tandems, such as:
     * sim.screen.model.electron_0
     * sim.screen.model.electron_1
     *
     * In this case, 'sim.screen.model.electron' is the group tandem id.
     *
     * Used for arrays, observable arrays, or when many elements of the same type are created and they do not otherwise
     * have unique identifiers.
     * @param id
     * @returns {GroupTandem}
     */
    createGroupTandem: function( id ) {

      // Unfortunately we must resort to globals here since loading through the namespace would create a cycle
      return new GroupTandem( this.id + '.' + id );
    },

    /**
     * Get the last part of the tandem (after the last .), used in Joist for creating button names dynamically based
     * on screen names
     * @return {string} the tail of the tandem
     */
    get tail() {
      assert && assert( this.id.indexOf( '.' ) >= 0, 'tandem ID does not have a tail' );

      var lastIndexOfDot = this.id.lastIndexOf( '.' );
      var tail = this.id.substring( lastIndexOfDot + 1 );
      assert && assert( tail.length > 0, 'tandem ID did not have a tail' );
      return tail;
    },

    /**
     * Returns a Tandem for everything except the tail.
     * @returns {Tandem}
     */
    get parentTandem() {
      assert && assert( this.id.indexOf( '.' ) >= 0, 'tandem ID does not have a tail' );

      var lastIndexOfDot = this.id.lastIndexOf( '.' );
      var headID = this.id.substring( 0, lastIndexOfDot );

      return new Tandem( headID, {
        static: this.static,
        tandemRequiredButNotSupplied: this.tandemRequiredButNotSupplied,
        enabled: this.enabled
      } );
    },

    /**
     * When using subtyping, the instance listeners must only be notified once rather than once for every level
     * in the inheritance hierarchy.  When a subtype constructor has a tandem.addInstance call, it should
     * pass a supertype tandem to the parent constructor so that it won't try to register the item twice.
     * @returns {SupertypeTandem}
     */
    createSupertypeTandem: function() {
      return new SupertypeTandem( this.id );
    }
  }, {

    /**
     * Some common code (such as CheckBox or RadioButton) must always be instrumented and hence requires a tandem to be
     * passed in.  The options hash indicates this with {tandem: Tandem.tandemRequired()}
     * @returns {Tandem}
     */
    tandemRequired: function() {
      return rootTandem.createTandem( 'requiredTandem' + (requiredTandemIndex++), {
        tandemRequiredButNotSupplied: true // will be checked in addInstance
      } );
    },

    /**
     *
     * Used to indicate a common code component that supports tandem, but doesn't not require it.
     * If a tandem is not passed through to this instance, then it will not be instrumented.
     * @returns {Tandem}
     */
    tandemOptional: function() {
      return rootTandem.createTandem( 'optionalTandem' + (optionalTandemIndex++), {
        tandemOptionalAndNotSupplied: true
      } );
    },

    /**
     * Adds a listener that will be notified when items are registered/deregistered
     * Listeners have the form
     * {
     *   addInstance(id,instance),
     *   removeInstance(id,instance)
     * }
     * where id is of type {string} and instance is of type {Object}
     *
     * @param {Object} instanceListener - described above
     * @public
     * @static
     */
    addInstanceListener: function( instanceListener ) {
      instanceListeners.push( instanceListener );
    },

    /**
     * Create a tandem based on the name of the running simulation.
     * @returns {Tandem}
     */
    createRootTandem: function() {
      return new Tandem( toCamelCase( packageJSON.name ) );
    },

    /**
     * Create a child of the root tandem.
     * @param {string} name
     * @returns {Tandem}
     */
    createStaticTandem: function( name ) {
      return Tandem.createRootTandem().createTandem( name, { static: true } );
    },

    /**
     * When the simulation is launched, all static instances are registered.
     */
    launch: function() {
      assert && assert( !launched, 'Tandem was launched twice' );
      launched = true;
      while ( staticInstances.length > 0 ) {
        var staticInstance = staticInstances.shift();
        staticInstance.tandem.addInstance( staticInstance.instance, staticInstance.type );
      }
    },

    /**
     * Catch cases where tandem is being supplied to a class that doesn't support tandem.
     * @param options
     */
    disallowTandem: function( options ) {

      if ( window.phet && window.phet.chipper && phet.chipper.brand === 'phet-io' &&
           phet.phetio && phet.phetio.queryParameters && phet.phetio.queryParameters.phetioValidateTandems ) {
        assert && assert( !options.tandem, 'tandem is not allowed' );
      }
    },

    /**
     * When running in PhET-iO brand, some code (such as user interface components) must be instrumented for PhET-iO.
     * Uninstrumented files should call this function to indicate they still need to be instrumented, so they aren't
     * missed.  See https://github.com/phetsims/phet-io/issues/668
     */
    indicateUninstrumentedCode: function() {

      // Guard against undefined errors
      if ( window.phet && window.phet.chipper && phet.chipper.brand === 'phet-io' &&
           phet.phetio && phet.phetio.queryParameters ) {

        // Assert if validating tandems
        if ( phet.phetio.queryParameters.phetioValidateTandems ) {
          assert && assert( false, 'Uninstrumented code detected' );
        }

        // Print stack trace if query parameter supplied
        if ( phet.phetio.queryParameters.printMissingTandems ) {
          var stackTrace = new Error().stack;
          console.log( 'Uninstrumented Code! Tandem not supplied: ' +  (uninstrumentCodeIndex ++) + '.\n' +
                       'Stack trace: ' + stackTrace );
        }

      }
    }
  } );

  var rootTandem = Tandem.createRootTandem();

  // Tandem checks for listeners added before the Tandem module was loaded.  This is necessary so that phetio.js can
  // receive notifications about items created during static initialization such as Solute.js
  // which is created before Sim.js runs.
  if ( window.tandemPreloadInstanceListeners ) {
    for ( var i = 0; i < window.tandemPreloadInstanceListeners.length; i++ ) {
      Tandem.addInstanceListener( window.tandemPreloadInstanceListeners[ i ] );
    }
  }

  /**
   * @param {string} id - id as a string (or '' for a root id)
   * @constructor
   * @private create with Tandem.createGroupTandem
   * Declared in the same file to avoid circular reference errors in module loading.
   */
  function GroupTandem( id ) {

    Tandem.call( this, id );

    // @private for generating indices from a pool
    this.groupElementIndex = 0;
  }

  tandemNamespace.register( 'Tandem.GroupTandem', GroupTandem );

  inherit( Tandem, GroupTandem, {

    createNextTandem: function() {
      return new Tandem( this.id + '_' + ( this.groupElementIndex++ ) );
    }
  } );

  /**
   * @param {string} id - id as a string (or '' for a root id)
   * @constructor
   * @private create with Tandem.createSupertypeTandem
   */
  function SupertypeTandem( id ) {
    Tandem.call( this, id );
  }

  tandemNamespace.register( 'Tandem.SupertypeTandem', SupertypeTandem );

  inherit( Tandem, SupertypeTandem, {

    // @public - Override to make no-op, see createSupertypeTandem
    addInstance: function( instance, type ) {},

    // @public - Override to make no-op, see createSupertypeTandem
    removeInstance: function( instance ) {}
  } );

  return Tandem;
} );

<commit_msg>Use @returns instead of @return, see https://github.com/phetsims/chipper/issues/557<commit_after>// Copyright 2015, University of Colorado Boulder

/**
 * Tandem is a general instance registry that can be used to track creation/disposal of instances in PhET Simulations.
 * It is used for phetio.js instrumentation for PhET-iO support.
 *
 * @author Sam Reid (PhET Interactive Simulations)
 */
define( function( require ) {
  'use strict';

  // modules
  var inherit = require( 'PHET_CORE/inherit' );
  var tandemNamespace = require( 'TANDEM/tandemNamespace' );
  var toCamelCase = require( 'PHET_CORE/toCamelCase' );

  // text
  var packageString = require( 'text!REPOSITORY/package.json' );

  // constants
  var packageJSON = JSON.parse( packageString );

  // variables
  var launched = false;

  // increment names of required tandems to avoid collisions for uninstrumented sims with phetioValidateTandems=false
  var requiredTandemIndex = 0;

  // increment names of required tandems to avoid collisions for uninstrumented sims with phetioValidateTandems=false
  var optionalTandemIndex = 0;

  // increment names of required tandems to avoid collisions for uninstrumented sims with phetioValidateTandems=false
  var uninstrumentCodeIndex = 0;

  /**
   * @param {string} id - id as a string (or '' for a root id)
   * @param {Object} [options]
   * @constructor
   */
  function Tandem( id, options ) {

    options = _.extend( {
      static: false,
      enabled: true,
      tandemRequiredButNotSupplied: false, // When set to true, if there isn't a tandem supplied, it will fail out.
      tandemOptionalAndNotSupplied: false
    }, options );

    // @public (read-only)
    this.id = ( id !== undefined ) ? id : '';

    // @private (read-only)
    this.static = options.static;
    this.tandemRequiredButNotSupplied = options.tandemRequiredButNotSupplied;
    this.tandemOptionalAndNotSupplied = options.tandemOptionalAndNotSupplied;
    this.enabled = options.enabled;
  }

  var staticInstances = [];

  tandemNamespace.register( 'Tandem', Tandem );

  // Listeners that will be notified when items are registered/deregistered
  var instanceListeners = [];

  inherit( Object, Tandem, {

    // @public (read-only) permit checking whether something is probably a Tandem instance for error checking
    isTandem: true,

    /**
     * Adds an instance of any type.  For example, it could be an axon Property, scenery Node or Sun button.  Each
     * item should only be added to the registry once, but that is not enforced here in Tandem.  For PhET-iO, phet-io.js
     * enforces one entry per ID in phetio.addInstance
     *
     * This is used to register instances with PhET-iO.
     * @param {Object} instance - the instance to add
     * @param {function} type - the PhET-iO type function, such as TString or TProperty(TNumber('volts'))
     * @public
     */
    addInstance: function( instance, type ) {

      if ( window.phet && window.phet.chipper && phet.chipper.brand === 'phet-io' && this.enabled ) {

        if ( phet.phetio.queryParameters.phetioValidateTandems ) {
          assert && assert( !this.tandemRequiredButNotSupplied, 'Tandem was required but not supplied' );
        }

        // validateTandems is false and printMissingTandems flag is present for a tandem that is required but not supplied.
        else if ( phet.phetio.queryParameters.printMissingTandems && this.tandemRequiredButNotSupplied ) {
          var stackTrace = new Error().stack;
          console.log( 'Required Tandem not supplied.\n' +
                       'this.id = ' + this.id + '\n' +
                       'Stack trace: ' + stackTrace );
        }

        if ( !type ) {
          console.log( 'Missing type declaration for ' + this.id );
        }

        // ifphetio returns a no-op function, so to test whether a valid T wrapper type was passed, we search for the typeName
        assert && assert( type && type.typeName, 'type must be specified and have a typeName' );

        if ( this.tandemOptionalAndNotSupplied ) {
          if ( phet.phetio.queryParameters.printMissingTandems ) {
            var stackTrace2 = new Error().stack;

            // Generally PhETFont is not desired because there are so many untandemized instances.
            if ( stackTrace2.indexOf( 'PhetFont' ) === -1 ) {
              console.log( 'Optional Tandem not supplied.\n' +
                           'this.id = ' + this.id + '\n' +
                           'Stack trace: ' + stackTrace2 );
            }
          }

          // For optionally instrumented types that are not provided tandems, the instance isn't really "added"
          // but likewise, it in not an error
          return;
        }

        if ( this.static && !launched ) {
          staticInstances.push( { tandem: this, instance: instance, type: type } );
        }
        else {
          for ( var i = 0; i < instanceListeners.length; i++ ) {
            instanceListeners[ i ].addInstance( this.id, instance, type );
          }
        }
      }
    },

    /**
     * Removes an instance from the
     * @param {Object} instance - the instance to remove
     * @public
     */
    removeInstance: function( instance ) {

      // Only active when running as phet-io
      if ( phet.chipper.brand === 'phet-io' && this.enabled ) {
        for ( var i = 0; i < instanceListeners.length; i++ ) {
          instanceListeners[ i ].removeInstance( this.id, instance );
        }
      }
    },

    /**
     * Create a new Tandem by appending the given id
     * @param {string} id
     * @param {Object} [options]
     * @returns {Tandem}
     * @public
     */
    createTandem: function( id, options ) {

      // Make sure the id was provided
      assert && assert( typeof id === 'string' && id.length > 0, 'id must be defined' );

      var string = ( this.id.length > 0 ) ? ( this.id + '.' + id ) : id;

      // Any child of something static is also static
      options = _.extend( { static: this.static, enabled: this.enabled }, options );

      return new Tandem( string, options );
    },

    /**
     * Creates a group tandem for creating multiple indexed child tandems, such as:
     * sim.screen.model.electron_0
     * sim.screen.model.electron_1
     *
     * In this case, 'sim.screen.model.electron' is the group tandem id.
     *
     * Used for arrays, observable arrays, or when many elements of the same type are created and they do not otherwise
     * have unique identifiers.
     * @param id
     * @returns {GroupTandem}
     */
    createGroupTandem: function( id ) {

      // Unfortunately we must resort to globals here since loading through the namespace would create a cycle
      return new GroupTandem( this.id + '.' + id );
    },

    /**
     * Get the last part of the tandem (after the last .), used in Joist for creating button names dynamically based
     * on screen names
     * @returns {string} the tail of the tandem
     */
    get tail() {
      assert && assert( this.id.indexOf( '.' ) >= 0, 'tandem ID does not have a tail' );

      var lastIndexOfDot = this.id.lastIndexOf( '.' );
      var tail = this.id.substring( lastIndexOfDot + 1 );
      assert && assert( tail.length > 0, 'tandem ID did not have a tail' );
      return tail;
    },

    /**
     * Returns a Tandem for everything except the tail.
     * @returns {Tandem}
     */
    get parentTandem() {
      assert && assert( this.id.indexOf( '.' ) >= 0, 'tandem ID does not have a tail' );

      var lastIndexOfDot = this.id.lastIndexOf( '.' );
      var headID = this.id.substring( 0, lastIndexOfDot );

      return new Tandem( headID, {
        static: this.static,
        tandemRequiredButNotSupplied: this.tandemRequiredButNotSupplied,
        enabled: this.enabled
      } );
    },

    /**
     * When using subtyping, the instance listeners must only be notified once rather than once for every level
     * in the inheritance hierarchy.  When a subtype constructor has a tandem.addInstance call, it should
     * pass a supertype tandem to the parent constructor so that it won't try to register the item twice.
     * @returns {SupertypeTandem}
     */
    createSupertypeTandem: function() {
      return new SupertypeTandem( this.id );
    }
  }, {

    /**
     * Some common code (such as CheckBox or RadioButton) must always be instrumented and hence requires a tandem to be
     * passed in.  The options hash indicates this with {tandem: Tandem.tandemRequired()}
     * @returns {Tandem}
     */
    tandemRequired: function() {
      return rootTandem.createTandem( 'requiredTandem' + (requiredTandemIndex++), {
        tandemRequiredButNotSupplied: true // will be checked in addInstance
      } );
    },

    /**
     *
     * Used to indicate a common code component that supports tandem, but doesn't not require it.
     * If a tandem is not passed through to this instance, then it will not be instrumented.
     * @returns {Tandem}
     */
    tandemOptional: function() {
      return rootTandem.createTandem( 'optionalTandem' + (optionalTandemIndex++), {
        tandemOptionalAndNotSupplied: true
      } );
    },

    /**
     * Adds a listener that will be notified when items are registered/deregistered
     * Listeners have the form
     * {
     *   addInstance(id,instance),
     *   removeInstance(id,instance)
     * }
     * where id is of type {string} and instance is of type {Object}
     *
     * @param {Object} instanceListener - described above
     * @public
     * @static
     */
    addInstanceListener: function( instanceListener ) {
      instanceListeners.push( instanceListener );
    },

    /**
     * Create a tandem based on the name of the running simulation.
     * @returns {Tandem}
     */
    createRootTandem: function() {
      return new Tandem( toCamelCase( packageJSON.name ) );
    },

    /**
     * Create a child of the root tandem.
     * @param {string} name
     * @returns {Tandem}
     */
    createStaticTandem: function( name ) {
      return Tandem.createRootTandem().createTandem( name, { static: true } );
    },

    /**
     * When the simulation is launched, all static instances are registered.
     */
    launch: function() {
      assert && assert( !launched, 'Tandem was launched twice' );
      launched = true;
      while ( staticInstances.length > 0 ) {
        var staticInstance = staticInstances.shift();
        staticInstance.tandem.addInstance( staticInstance.instance, staticInstance.type );
      }
    },

    /**
     * Catch cases where tandem is being supplied to a class that doesn't support tandem.
     * @param options
     */
    disallowTandem: function( options ) {

      if ( window.phet && window.phet.chipper && phet.chipper.brand === 'phet-io' &&
           phet.phetio && phet.phetio.queryParameters && phet.phetio.queryParameters.phetioValidateTandems ) {
        assert && assert( !options.tandem, 'tandem is not allowed' );
      }
    },

    /**
     * When running in PhET-iO brand, some code (such as user interface components) must be instrumented for PhET-iO.
     * Uninstrumented files should call this function to indicate they still need to be instrumented, so they aren't
     * missed.  See https://github.com/phetsims/phet-io/issues/668
     */
    indicateUninstrumentedCode: function() {

      // Guard against undefined errors
      if ( window.phet && window.phet.chipper && phet.chipper.brand === 'phet-io' &&
           phet.phetio && phet.phetio.queryParameters ) {

        // Assert if validating tandems
        if ( phet.phetio.queryParameters.phetioValidateTandems ) {
          assert && assert( false, 'Uninstrumented code detected' );
        }

        // Print stack trace if query parameter supplied
        if ( phet.phetio.queryParameters.printMissingTandems ) {
          var stackTrace = new Error().stack;
          console.log( 'Uninstrumented Code! Tandem not supplied: ' +  (uninstrumentCodeIndex ++) + '.\n' +
                       'Stack trace: ' + stackTrace );
        }

      }
    }
  } );

  var rootTandem = Tandem.createRootTandem();

  // Tandem checks for listeners added before the Tandem module was loaded.  This is necessary so that phetio.js can
  // receive notifications about items created during static initialization such as Solute.js
  // which is created before Sim.js runs.
  if ( window.tandemPreloadInstanceListeners ) {
    for ( var i = 0; i < window.tandemPreloadInstanceListeners.length; i++ ) {
      Tandem.addInstanceListener( window.tandemPreloadInstanceListeners[ i ] );
    }
  }

  /**
   * @param {string} id - id as a string (or '' for a root id)
   * @constructor
   * @private create with Tandem.createGroupTandem
   * Declared in the same file to avoid circular reference errors in module loading.
   */
  function GroupTandem( id ) {

    Tandem.call( this, id );

    // @private for generating indices from a pool
    this.groupElementIndex = 0;
  }

  tandemNamespace.register( 'Tandem.GroupTandem', GroupTandem );

  inherit( Tandem, GroupTandem, {

    createNextTandem: function() {
      return new Tandem( this.id + '_' + ( this.groupElementIndex++ ) );
    }
  } );

  /**
   * @param {string} id - id as a string (or '' for a root id)
   * @constructor
   * @private create with Tandem.createSupertypeTandem
   */
  function SupertypeTandem( id ) {
    Tandem.call( this, id );
  }

  tandemNamespace.register( 'Tandem.SupertypeTandem', SupertypeTandem );

  inherit( Tandem, SupertypeTandem, {

    // @public - Override to make no-op, see createSupertypeTandem
    addInstance: function( instance, type ) {},

    // @public - Override to make no-op, see createSupertypeTandem
    removeInstance: function( instance ) {}
  } );

  return Tandem;
} );

<|endoftext|>


<commit_before>const express = require('express');
const path = require('path');
const mongodb = require('mongodb').MongoClient;
const dotenv = require('dotenv');

dotenv.load();
const url = `mongodb://${process.env.DB_USERNAME}:${process.env.DB_PASSWORD}@ds123695.mlab.com:23695/url-shortener`
const app = express();
let db, collection;

mongodb.connect(url, (err, database) => {
	if (err) {
		console.log('Unable to connect to the mongoDB server. Error:', err);
	} else {
		db = database;
		collection = database.collection('urls');
		app.listen(3000, () => console.log("Server is listening at http://localhost:3000"));
	}
});

app.use(express.static(path.join(__dirname, 'public')));

app.set('views', path.join(__dirname, 'templates'));
app.set('view engine', 'pug');

app.get('/', (req, res) => {
	const fullUrl = req.protocol + '://' + req.get('host') + req.originalUrl;
	res.render('index', { url: fullUrl });
});

app.get('/new/*', (req, res) => {
	let docCount;
	collection.find().toArray((err, doc) => console.log(doc));
	collection.find().count({}, (err, count) => docCount = count + 1);
	collection.insert({
		original_url: req.params[0],
		shorten_id: docCount
	}, (err, data) => {
		res.end(JSON.stringify({
			original_url: req.params[0]
		}))
	});

	db.close();
});

<commit_msg>wrapped up the route under mongodb connection<commit_after>const express = require('express');
const path = require('path');
const mongodb = require('mongodb').MongoClient;
const shortid = require('shortid');
const dotenv = require('dotenv');
const validUrl = require('valid-url');

dotenv.load();
shortid.characters('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$@');

const url = `mongodb://${process.env.DB_USERNAME}:${process.env.DB_PASSWORD}@ds123695.mlab.com:23695/url-shortener`
const app = express();
let db, collection;

app.use(express.static(path.join(__dirname, 'public')));

app.set('views', path.join(__dirname, 'templates'));
app.set('view engine', 'pug');

mongodb.connect(url, (err, database) => {
  const errorMessage = JSON.stringify({
    errorCode: '500',
    message: "Encountered Server Error. Please refrewsh!"
  });

  if (err) {
    console.log('Unable to connect to the mongoDB server. Error:', err);
  } else {
    db = database;
    collection = database.collection('urls');
    app.listen(3000, () => console.log("Server is listening at http://localhost:3000"));

    // Root route starts
    app.get('/', (req, res) => {
      const fullUrl = req.protocol + '://' + req.get('host') + req.originalUrl;
      res.render('index', { url: fullUrl });
    });

    // Route for new url starts here
    app.get('/new/*', (req, res) => {
      if (validUrl.isUri(req.params[0])) {
        let docCount = shortid.generate();
        const hostUrl = req.protocol + '://' + req.get('host');
        const shortUrl = hostUrl + '/' + docCount;

        collection.insert({
          original_url: req.params[0],
          shorten_url: shortUrl
        }, (err, data) => {
          res.end(JSON.stringify({
            original_url: req.params[0],
            shorten_url: shortUrl
          }))
        });
      }
      else {
        res.end(JSON.stringify({
          error: "Wrong url format, make sure you have a valid protocol and real site."
        }));
      }
    });

    // Route to redirect starts here

    app.get('/:shorturl', (req, res) => {
      const hostUrl = req.protocol + '://' + req.get('host');
      const shortUrl = hostUrl + '/' + req.params.shorturl;
      collection.find({ shorten_url: shortUrl }).toArray((err, doc) => {
        console.log(doc);
        if (err) {
          res.sendStatus(500);
          res.end(errorMessage);
        }
        else {

          if (doc === undefined) {
            res.sendStatus(500);
            res.end(errorMessage);
          }
          else {
            res.redirect(doc[0].original_url);
          }

        }
      })
    });

  }
});<|endoftext|>


<commit_before>$(function(){
    singleAction();
});

$(window).smartresize(function() {
    singleAction()
    if (!$('body').hasClass('overflowing') && breakpoints() == 'large') {
        var offset = $(location.hash).offset();
        setTimeout(function(){
            $(window).scrollTop(offset.top);
        }, 50);
    }
});

$(window).on('load', function(){
    // initial scroll
    if (location.hash !== '') {
        var offset = $(location.hash).offset();
        setTimeout(function(){
            $(window).scrollTop(offset.top);
        }, 50);
    };
});

function singleAction() {
    var homeSections = $('#frontpage').children('section');
    var overflowing = false;

    $.each(homeSections, function(){
        $('body').removeClass('overflowing');
        var hasOverflow = $(this).children('.contents').innerHeight() > $(this)[0].scrollHeight;
        if (!hasOverflow) {
            $(this).addClass('full-screen');
        } else {
            $(this).removeClass('full-screen');
            overflowing = true;
        }
        // console.log([$(this)[0].scrollHeight, $(this).children('.contents').innerHeight()]);
        // console.log($(this)[0].className +' has overflow? '+ hasOverflow + '/'+overflowing);
    });

    /**
     * set inital values for sections and offsets
     */

        // check the hash
        var hash = location.hash;
        var section = $(hash);

        // if there is no hash, use the first section (#intro)
        if (hash == '' ) {
            hash = '#intro';
            location.hash = hash;
            section = $(hash);
        }

        findSections(section);

        // allow scroll
        var disableScroll = false

        // animate the first section differently on initial view
        var initialView = false;

        if (hash == '#intro') {
            initialView = true;
        } else {
            $('.dark-corner').css('top', '-200%');
            $('.intro-layout').css('top', '-4000px').addClass('already-seen');
        }

        $('.frontnav-item').each(function() {
            if ($(this).children('a').attr('href') == hash) {
                $(this).addClass('active');
            }
        });

        overflowing ? $('body').addClass('overflowing') : $('body').removeClass('overflowing');

    /**
     * Smoothly move to the next section on "scroll"
     */

        $('html').on('mousewheel DOMMouseScroll onmousewheel touchmove scroll', function(e) {
            // don't animate when viewed on a small screen
            if (breakpoints() == 'large' && !$('body').hasClass('overflowing')) {
                // if scrolling is disabled, i.e. there is already an animation don't do anything
                if (!disableScroll) {
                    // prevent defaults/don't bubble
                    if (e.target.id == 'el') return;
                    e.preventDefault();
                    e.stopPropagation();

                    // disable scroll --> throttle
                    disableScroll = true;
                    $(window).disablescroll();

                    //Determine Direction
                    if ( (e.originalEvent.wheelDelta && e.originalEvent.wheelDelta >= 0) || (e.originalEvent.detail && e.originalEvent.detail <= 0) ) {
                        // up
                        e.stopPropagation();
                        section = $(prevSection);

                        // if the scroll is back to intro
                        if (prevSection == '#intro' && nextSection !== '#concept') {
                            if (!$('.intro-layout').hasClass('already-seen')) {
                                $('.intro-layout').addClass('already-seen');
                            };

                            // reset the initial view
                            initialView = true;

                            // reverse the animation
                            $('html, body').animate({
                            scrollTop: prevOffset.top
                            }, 2000, function() {
                                location.hash = '#' + section.attr('id');
                            });

                            $('.dark-corner').animate({
                                top: '-50%',
                            }, 1000);

                            setTimeout(function() {
                                $('.intro-layout').animate({
                                    top: '0',
                                }, 3000);
                            }, 500);
                        } else {
                            $('html, body').animate({
                                scrollTop: prevOffset.top
                            }, 2000, function() {
                                location.hash = '#' + section.attr('id');
                            });
                        }
                        findSections(section);
                    } else {
                        // down
                        e.stopPropagation();
                        section = $(nextSection);

                        // if this is the first view of the first section
                        if (initialView) {

                            $('.dark-corner').animate({
                                top: '-200%',
                                // left: '-5%'
                            }, 1500);
                            setTimeout(function() {
                                $('.intro-layout').animate({
                                    top: '-4000px',
                                }, 4000);
                            }, 500);
                            setTimeout(function() {
                                $('html, body').animate({
                                    scrollTop: nextOffset.top,
                                }, 2000, function() {
                                    location.hash = '#' + section.attr('id');
                                    findSections(section);
                                });
                            }, 2000);
                            initialView = false;
                        } else {
                            $('html, body').animate({
                                scrollTop: nextOffset.top
                            }, 2000, function() {
                                location.hash = '#' + section.attr('id');
                            });
                            findSections(section);
                        }
                    }

                    // enable scrolling after 500ms
                    setTimeout(function(){
                        disableScroll = false;
                        $(window).disablescroll('undo');

                        $('.frontnav-item').each(function() {
                            $(this).removeClass('active');
                            if ($(this).children('a').attr('href') == '#' + section.attr('id')) {
                                $(this).addClass('active');
                            }
                        });
                    }, 1500);
                }
            }
        }); // scroll

    /**
     * Side Navigation clicks
     */
        $('.frontnav-item').on('click', function(e) {
            e.preventDefault();
            // disable scroll --> throttle
            disableScroll = true;
            $(window).disablescroll();

            var goto = $(this).children('a').attr('href');
            section = $(hash);

            var clickedItem = $(this); // maintain scope within setTimeout
            $(this).addClass('clicking');
            $(this).siblings().each(function() {
                $(this).removeClass('active');
            });
            setTimeout(function() {
                clickedItem.addClass('active').removeClass('clicking');
            }, 500);

            if (initialView) {
                initialView = false;

                $('.dark-corner').animate({
                    top: '-200%',
                    // left: '-5%'
                }, 1500);
                setTimeout(function() {
                    $('.intro-layout').animate({
                        top: '-4000px',
                    }, 4000);
                }, 500);

                setTimeout(function() {
                    $('html, body').animate({
                        scrollTop: $(goto).offset().top,
                    }, 2000, function() {
                        location.hash = '#' + $(goto).attr('id');
                        findSections($(goto));
                    });
                }, 2000);
            } else {
                if (goto == '#intro') {
                    if (!$('.intro-layout').hasClass('already-seen')) {
                        $('.intro-layout').addClass('already-seen');
                    };

                    // reset the initial view
                    initialView = true;

                    // reverse the animation
                    $('html, body').animate({
                        scrollTop: $(goto).offset().top,
                    }, 2000, function() {
                        location.hash = '#' + section.attr('id');
                        findSections($(goto));
                    });

                    $('.dark-corner').animate({
                        top: '-50%',
                    }, 1000);

                    setTimeout(function() {
                        $('.intro-layout').animate({
                            top: '0',
                        }, 3000);
                    }, 500);
                } else {
                    setTimeout(function() {
                        $('html, body').animate({
                            scrollTop: $(goto).offset().top,
                        }, 2000, function() {
                            location.hash = '#' + $(goto).attr('id');
                            findSections($(goto));
                        });
                    }, 100);
                    initialView = false;
                }
            }

            // enable scrolling after 1500ms
            setTimeout(function(){
                disableScroll = false;
                $(window).disablescroll('undo');
            }, 1500);
        });
};

function findSections(section) {
    // get the previous and next section
    prevSection = (section.prev().length == 1 ) ? '#' + section.prev().attr('id') : '#' + section.attr('id');
    nextSection = (section.next().length == 1 ) ? '#' + section.next().attr('id') : '#' + section.attr('id');

    // get the offset of the prev/next sections to scroll to them
    prevOffset = $(prevSection).offset();
    nextOffset = $(nextSection).offset();
}<commit_msg>firefox had a back to intro bug, fixed this<commit_after>$(function(){
    singleAction();
});

$(window).smartresize(function() {
    singleAction()
    if (!$('body').hasClass('overflowing') && breakpoints() == 'large') {
        var offset = $(location.hash).offset();
        setTimeout(function(){
            $(window).scrollTop(offset.top);
        }, 50);
    }
});

$(window).on('load', function(){
    // initial scroll
    if (location.hash !== '') {
        var offset = $(location.hash).offset();
        setTimeout(function(){
            $(window).scrollTop(offset.top);
        }, 50);
    };
});

function singleAction() {
    var homeSections = $('#frontpage').children('section');
    var overflowing = false;

    $.each(homeSections, function(){
        $('body').removeClass('overflowing');
        var hasOverflow = $(this).children('.contents').innerHeight() > $(this)[0].scrollHeight;
        if (!hasOverflow) {
            $(this).addClass('full-screen');
        } else {
            $(this).removeClass('full-screen');
            overflowing = true;
        }
        // console.log([$(this)[0].scrollHeight, $(this).children('.contents').innerHeight()]);
        // console.log($(this)[0].className +' has overflow? '+ hasOverflow + '/'+overflowing);
    });

    /**
     * set inital values for sections and offsets
     */

        // check the hash
        var hash = location.hash;
        var section = $(hash);

        // if there is no hash, use the first section (#intro)
        if (hash == '' ) {
            hash = '#intro';
            location.hash = hash;
            section = $(hash);
        }

        findSections(section);

        // allow scroll
        var disableScroll = false

        // animate the first section differently on initial view
        var initialView = false;

        if (hash == '#intro') {
            initialView = true;
        } else {
            $('.dark-corner').css('top', '-200%');
            $('.intro-layout').css('top', '-4000px').addClass('already-seen');
        }

        $('.frontnav-item').each(function() {
            if ($(this).children('a').attr('href') == hash) {
                $(this).addClass('active');
            }
        });

        overflowing ? $('body').addClass('overflowing') : $('body').removeClass('overflowing');

        var animationDuration = 1000;

    /**
     * Smoothly move to the next section on "scroll"
     */

        $('html').on('mousewheel DOMMouseScroll onmousewheel touchmove scroll', function(e) {
            // don't animate when viewed on a small screen
            if (breakpoints() == 'large' && !$('body').hasClass('overflowing')) {
                // if scrolling is disabled, i.e. there is already an animation don't do anything
                if (!disableScroll) {
                    // prevent defaults/don't bubble
                    if (e.target.id == 'el') return;
                    e.preventDefault();
                    e.stopPropagation();

                    // disable scroll --> throttle
                    disableScroll = true;
                    $(window).disablescroll();

                    //Determine Direction
                    if ( (e.originalEvent.wheelDelta && e.originalEvent.wheelDelta >= 0) || (e.originalEvent.detail && e.originalEvent.detail <= 0) ) {
                        // up
                        e.stopPropagation();
                        section = $(prevSection);

                        // if the scroll is back to intro
                        if (prevSection == '#intro' && nextSection !== '#concept') {
                            if (!$('.intro-layout').hasClass('already-seen')) {
                                $('.intro-layout').addClass('already-seen');
                            };

                            // reset the initial view
                            initialView = true;

                            // reverse the animation
                            $('html, body').animate({
                                scrollTop: prevOffset.top
                            }, animationDuration, function() {
                                location.hash = '#' + section.attr('id');
                            });

                            $('.dark-corner').animate({
                                top: '-50%',
                            }, animationDuration * .5);

                            setTimeout(function() {
                                $('.intro-layout').animate({
                                    top: '0',
                                }, animationDuration * 1.5);
                            }, animationDuration * .25);
                        } else {
                            $('html, body').animate({
                                scrollTop: prevOffset.top
                            }, animationDuration, function() {
                                location.hash = '#' + section.attr('id');
                            });
                        }
                        findSections(section);
                    } else {
                        // down
                        e.stopPropagation();
                        section = $(nextSection);

                        // if this is the first view of the first section
                        if (initialView) {

                            $('.dark-corner').animate({
                                top: '-200%',
                                // left: '-5%'
                            }, animationDuration * .75);
                            setTimeout(function() {
                                $('.intro-layout').animate({
                                    top: '-4000px',
                                }, animationDuration * 2);
                            }, animationDuration * .25);
                            setTimeout(function() {
                                $('html, body').animate({
                                    scrollTop: nextOffset.top,
                                }, animationDuration, function() {
                                    location.hash = '#' + section.attr('id');
                                    findSections(section);
                                });
                            }, animationDuration);
                            initialView = false;
                        } else {
                            $('html, body').animate({
                                scrollTop: nextOffset.top
                            }, animationDuration, function() {
                                location.hash = '#' + section.attr('id');
                            });
                            findSections(section);
                        }
                    }

                    // enable scrolling after animationDuration
                    setTimeout(function(){
                        disableScroll = false;
                        $(window).disablescroll('undo');

                        $('.frontnav-item').each(function() {
                            $(this).removeClass('active');
                            if ($(this).children('a').attr('href') == '#' + section.attr('id')) {
                                $(this).addClass('active');
                            }
                        });
                    }, animationDuration);
                }
            }
        }); // scroll

    /**
     * Side Navigation clicks
     */
        $('.frontnav-item').on('click', function(e) {
            e.preventDefault();
            // disable scroll --> throttle
            disableScroll = true;
            $(window).disablescroll();

            var goto = $(this).children('a').attr('href');
            section = $(hash);

            var clickedItem = $(this); // maintain scope within setTimeout
            $(this).addClass('clicking');
            $(this).siblings().each(function() {
                $(this).removeClass('active');
            });
            setTimeout(function() {
                clickedItem.addClass('active').removeClass('clicking');
            }, animationDuration * .25);

            if (initialView) {
                initialView = false;

                $('.dark-corner').animate({
                    top: '-200%',
                }, animationDuration * .75);
                setTimeout(function() {
                    $('.intro-layout').animate({
                        top: '-4000px',
                    }, animationDuration * 2);
                }, animationDuration * .25);

                setTimeout(function() {
                    $('html, body').animate({
                        scrollTop: $(goto).offset().top,
                    }, animationDuration, function() {
                        location.hash = '#' + $(goto).attr('id');
                        findSections($(goto));
                    });
                }, animationDuration);
            } else {
                console.log([prevSection, nextSection]);
                if (goto == '#intro') {
                    // if (!$('.intro-layout').hasClass('already-seen')) {
                    //     $('.intro-layout').addClass('already-seen');
                    // };

                    // reset the initial view
                    initialView = true;

                    findSections($(goto));

                    console.log([prevSection, nextSection]);

                    // reverse the animation
                    $('html, body').animate({
                        scrollTop: $(goto).offset().top,
                    }, animationDuration, function() {
                        location.hash = goto;
                        findSections($(goto));
                    });

                    $('.dark-corner').animate({
                        top: '-50%',
                    }, animationDuration * .5);

                    setTimeout(function() {
                        $('.intro-layout').animate({
                            top: '0',
                        }, animationDuration * 1.5);
                    }, animationDuration * .25);
                } else {
                    console.log(goto);
                    setTimeout(function() {
                        $('html, body').animate({
                            scrollTop: $(goto).offset().top,
                        }, animationDuration, function() {
                            location.hash = '#' + $(goto).attr('id');
                            findSections($(goto));
                        });
                    }, 100);
                    initialView = false;
                }
            }

            // enable scrolling after animationDuration
            setTimeout(function(){
                disableScroll = false;
                $(window).disablescroll('undo');
            }, animationDuration);
        });
};

function findSections(section) {
    // get the previous and next section
    prevSection = (section.prev().length == 1 ) ? '#' + section.prev().attr('id') : '#' + section.attr('id');
    nextSection = (section.next().length == 1 ) ? '#' + section.next().attr('id') : '#' + section.attr('id');

    // get the offset of the prev/next sections to scroll to them
    prevOffset = $(prevSection).offset();
    nextOffset = $(nextSection).offset();
}<|endoftext|>


<commit_before>// Agency Theme JavaScript

(function($) {
    "use strict"; // Start of use strict

    // jQuery for page scrolling feature - requires jQuery Easing plugin
    $('a.page-scroll').bind('click', function(event) {
        var $anchor = $(this);
        $('html, body').stop().animate({
            scrollTop: ($($anchor.attr('href')).offset().top - 50)
        }, 1250, 'easeInOutExpo');
        event.preventDefault();
    });

    // Highlight the top nav as scrolling occurs
    $('body').scrollspy({
        target: '.navbar-fixed-top',
        offset: 51
    });

    // Closes the Responsive Menu on Menu Item Click
    $('.navbar-collapse ul li a').click(function(){
            $('.navbar-toggle:visible').click();
    });

    // Offset for Main Navigation
    $('#mainNav').affix({
        offset: {
            top: 100
        }
    })

})(jQuery); // End of use strict

// Google Maps Scripts
var map = null;
// When the window has finished loading create our google map below
google.maps.event.addDomListener(window, 'load', init);
google.maps.event.addDomListener(window, 'resize', function() {
    map.setCenter(new google.maps.LatLng(28.442841, -81.401901));
});

function init() {
    // Basic options for a simple Google Map
    // For more options see: https://developers.google.com/maps/documentation/javascript/reference#MapOptions
    var mapOptions = {
        // How zoomed in you want the map to start at (always required)
        zoom: 15,

        // The latitude and longitude to center the map (always required)
        center: new google.maps.LatLng(28.442841, -81.401901),

        // Disables the default Google Maps UI components
        disableDefaultUI: true,
        scrollwheel: false,
        draggable: true,

        // How you would like to style the map.
        // This is where you would paste any style found on Snazzy Maps.
        styles: [{
            "featureType": "water",
            "elementType": "geometry",
            "stylers": [{
                "color": "#000000"
            }, {
                "lightness": 17
            }]
        }, {
            "featureType": "landscape",
            "elementType": "geometry",
            "stylers": [{
                "color": "#000000"
            }, {
                "lightness": 20
            }]
        }, {
            "featureType": "road.highway",
            "elementType": "geometry.fill",
            "stylers": [{
                "color": "#000000"
            }, {
                "lightness": 17
            }]
        }, {
            "featureType": "road.highway",
            "elementType": "geometry.stroke",
            "stylers": [{
                "color": "#000000"
            }, {
                "lightness": 29
            }, {
                "weight": 0.2
            }]
        }, {
            "featureType": "road.arterial",
            "elementType": "geometry",
            "stylers": [{
                "color": "#000000"
            }, {
                "lightness": 18
            }]
        }, {
            "featureType": "road.local",
            "elementType": "geometry",
            "stylers": [{
                "color": "#000000"
            }, {
                "lightness": 16
            }]
        }, {
            "featureType": "poi",
            "elementType": "geometry",
            "stylers": [{
                "color": "#000000"
            }, {
                "lightness": 21
            }]
        }, {
            "elementType": "labels.text.stroke",
            "stylers": [{
                "visibility": "on"
            }, {
                "color": "#000000"
            }, {
                "lightness": 16
            }]
        }, {
            "elementType": "labels.text.fill",
            "stylers": [{
                "saturation": 36
            }, {
                "color": "#000000"
            }, {
                "lightness": 40
            }]
        }, {
            "elementType": "labels.icon",
            "stylers": [{
                "visibility": "off"
            }]
        }, {
            "featureType": "transit",
            "elementType": "geometry",
            "stylers": [{
                "color": "#000000"
            }, {
                "lightness": 19
            }]
        }, {
            "featureType": "administrative",
            "elementType": "geometry.fill",
            "stylers": [{
                "color": "#000000"
            }, {
                "lightness": 20
            }]
        }, {
            "featureType": "administrative",
            "elementType": "geometry.stroke",
            "stylers": [{
                "color": "#000000"
            }, {
                "lightness": 17
            }, {
                "weight": 1.2
            }]
        }]
    };

    // Get the HTML DOM element that will contain your map
    // We are using a div with id="map" seen below in the <body>
    var mapElement = document.getElementById('map');

    // Create the Google Map using out element and options defined above
    map = new google.maps.Map(mapElement, mapOptions);

    // Custom Map Marker Icon - Customize the map-marker.png file to customize your icon
    var image = 'img/map-marker.png';
    var myLatLng = new google.maps.LatLng(28.442841, -81.401901);
    var beachMarker = new google.maps.Marker({
        position: myLatLng,
        map: map,
        icon: image,
        animation: google.maps.Animation.DROP,
        title: "Our location"
    });
}<commit_msg>remove dragablle<commit_after>// Agency Theme JavaScript

(function($) {
    "use strict"; // Start of use strict

    // jQuery for page scrolling feature - requires jQuery Easing plugin
    $('a.page-scroll').bind('click', function(event) {
        var $anchor = $(this);
        $('html, body').stop().animate({
            scrollTop: ($($anchor.attr('href')).offset().top - 50)
        }, 1250, 'easeInOutExpo');
        event.preventDefault();
    });

    // Highlight the top nav as scrolling occurs
    $('body').scrollspy({
        target: '.navbar-fixed-top',
        offset: 51
    });

    // Closes the Responsive Menu on Menu Item Click
    $('.navbar-collapse ul li a').click(function(){
            $('.navbar-toggle:visible').click();
    });

    // Offset for Main Navigation
    $('#mainNav').affix({
        offset: {
            top: 100
        }
    })

})(jQuery); // End of use strict

// Google Maps Scripts
var map = null;
// When the window has finished loading create our google map below
google.maps.event.addDomListener(window, 'load', init);
google.maps.event.addDomListener(window, 'resize', function() {
    map.setCenter(new google.maps.LatLng(28.442841, -81.401901));
});

function init() {
    // Basic options for a simple Google Map
    // For more options see: https://developers.google.com/maps/documentation/javascript/reference#MapOptions
    var mapOptions = {
        // How zoomed in you want the map to start at (always required)
        zoom: 15,

        // The latitude and longitude to center the map (always required)
        center: new google.maps.LatLng(28.442841, -81.401901),

        // Disables the default Google Maps UI components
        disableDefaultUI: true,
        scrollwheel: false,
        draggable: false,

        // How you would like to style the map.
        // This is where you would paste any style found on Snazzy Maps.
        styles: [{
            "featureType": "water",
            "elementType": "geometry",
            "stylers": [{
                "color": "#000000"
            }, {
                "lightness": 17
            }]
        }, {
            "featureType": "landscape",
            "elementType": "geometry",
            "stylers": [{
                "color": "#000000"
            }, {
                "lightness": 20
            }]
        }, {
            "featureType": "road.highway",
            "elementType": "geometry.fill",
            "stylers": [{
                "color": "#000000"
            }, {
                "lightness": 17
            }]
        }, {
            "featureType": "road.highway",
            "elementType": "geometry.stroke",
            "stylers": [{
                "color": "#000000"
            }, {
                "lightness": 29
            }, {
                "weight": 0.2
            }]
        }, {
            "featureType": "road.arterial",
            "elementType": "geometry",
            "stylers": [{
                "color": "#000000"
            }, {
                "lightness": 18
            }]
        }, {
            "featureType": "road.local",
            "elementType": "geometry",
            "stylers": [{
                "color": "#000000"
            }, {
                "lightness": 16
            }]
        }, {
            "featureType": "poi",
            "elementType": "geometry",
            "stylers": [{
                "color": "#000000"
            }, {
                "lightness": 21
            }]
        }, {
            "elementType": "labels.text.stroke",
            "stylers": [{
                "visibility": "on"
            }, {
                "color": "#000000"
            }, {
                "lightness": 16
            }]
        }, {
            "elementType": "labels.text.fill",
            "stylers": [{
                "saturation": 36
            }, {
                "color": "#000000"
            }, {
                "lightness": 40
            }]
        }, {
            "elementType": "labels.icon",
            "stylers": [{
                "visibility": "off"
            }]
        }, {
            "featureType": "transit",
            "elementType": "geometry",
            "stylers": [{
                "color": "#000000"
            }, {
                "lightness": 19
            }]
        }, {
            "featureType": "administrative",
            "elementType": "geometry.fill",
            "stylers": [{
                "color": "#000000"
            }, {
                "lightness": 20
            }]
        }, {
            "featureType": "administrative",
            "elementType": "geometry.stroke",
            "stylers": [{
                "color": "#000000"
            }, {
                "lightness": 17
            }, {
                "weight": 1.2
            }]
        }]
    };

    // Get the HTML DOM element that will contain your map
    // We are using a div with id="map" seen below in the <body>
    var mapElement = document.getElementById('map');

    // Create the Google Map using out element and options defined above
    map = new google.maps.Map(mapElement, mapOptions);

    // Custom Map Marker Icon - Customize the map-marker.png file to customize your icon
    var image = 'img/map-marker.png';
    var myLatLng = new google.maps.LatLng(28.442841, -81.401901);
    var beachMarker = new google.maps.Marker({
        position: myLatLng,
        map: map,
        icon: image,
        animation: google.maps.Animation.DROP,
        title: "Our location"
    });
}<|endoftext|>


<commit_before>/*!
 * Start Bootstrap - Agency Bootstrap Theme (http://startbootstrap.com)
 * Code licensed under the Apache License v2.0.
 * For details, see http://www.apache.org/licenses/LICENSE-2.0.
 */
var tag = document.createElement('script');

tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

      var player;
      function onYouTubeIframeAPIReady() {
        player = new YT.Player('video-container', {
          videoId: '-Nmgm3PwZFk',
          playerVars: { 'modestbranding': 1, 'showinfo': 0, 'controls':0, 'start': 24},
          events: {
            'onReady': onPlayerReady,
            'onStateChange': onPlayerStateChange
          }
        });
      }

 // 4. The API will call this function when the video player is ready.
      function onPlayerReady(event) {
        event.target.playVideo();
      }

      // 5. The API calls this function when the player's state changes.
      //    The function indicates that when playing a video (state=1),
      //    the player should play for six seconds and then stop.
      var done = false;
      function onPlayerStateChange(event) {
        if (event.data == YT.PlayerState.PLAYING && !done) {
          setTimeout(stopVideo, 1);
          done = true;
        }
      }
      function stopVideo() {
        player.pauseVideo();
      }
// jQuery for page scrolling feature - requires jQuery Easing plugin
$(function() {
    $('a.page-scroll').bind('click', function(event) {
        var $anchor = $(this);
        /*$('html, body').stop().animate({
            scrollTop: $($anchor.attr('href')).offset().top
        }, 1500, 'easeInOutExpo');
        event.preventDefault();
        */
    });
});

// Highlight the top nav as scrolling occurs
$('body').scrollspy({
   // target: '.navbar-fixed-top'
})

// Closes the Responsive Menu on Menu Item Click
$('.navbar-collapse ul li a').click(function() {
    $('.navbar-toggle:visible').click();
});

$(document).ready(function(){
    var videoElement = document.getElementById("mission-audio-player");
    var textTracks = videoElement.textTracks; // one for each track element
    var textTrack = textTracks[0]; // corresponds to the first track element
    console.log(textTrack);
    function resize(){
      var width  = $('#model-graphic').width();
      var height  = $('#model-graphic').height();
      var circlewidth = .36 * width;
      $('.more').width(circlewidth);
      $('.more').height(circlewidth);
      $(".more").css("line-height", circlewidth + "px");
      newWidth = width * .29;
      newWidthC = newWidth + 112;
      leftWidth = -width * .02;
      leftWidthC = leftWidth + 112;
      rightWidth = width *.6;
      rightWidthC = rightWidth + 112;
      topHeight = height * .04;
      topHeightC = topHeight - 50;
      newHeight = height * .38;
      newHeightC = newHeight - 50;
      bottomHeight = height * .6;
      bottomHeightC = bottomHeight - 50;
      $("#design").css({"left": newWidth + "px", "top" : topHeight + "px"});
      $("#design-caption").css({"left": newWidthC + "px", "top" : topHeightC + "px"});
      $("#connect-circle").css({"left": newWidth + "px", "top": newHeight + "px"});
      $("#connect-caption").css({"left": newWidthC + "px", "top" : newHeightC + "px"});
      $("#pursue").css({"left": leftWidth + "px", "top" : bottomHeight + "px"});
      $("#pursue-caption").css({"left": leftWidthC + "px", "top" : bottomHeightC + "px"});
      $("#venture").css({"left": rightWidth + "px", "top" : bottomHeight + "px"})
      $("#venture-caption").css({"left": rightWidthC + "px", "top" : bottomHeightC + "px"});
    }
    $(window).resize(function(){
      resize();
    });
    resize();
    $('.more-caption').hide();
    $('.below-popup').hide();
    $('#mission-audio-player').hide();
    $('.audience').hover(function(e){
      console.log(e);
      $('.below-popup').css( 'position', 'absolute' );
        $('.below-popup').css( 'top', e.pageY-20);
        $('.below-popup').css( 'left', e.pageX-70);
       $('.below-popup').show();
      },function(){
      $('.below-popup').hide();
    });
    $('#design').mouseenter(function() {
        $('#design-caption').show();
    })
    .mouseleave(function() {
        $('#design-caption').hide();
    });
    $('#connect-circle').mouseenter(function() {
        $('#connect-caption').show();
    })
    .mouseleave(function() {
        $('#connect-caption').hide();
    });
    $('#venture').mouseenter(function() {
        $('#venture-caption').show();
    })
    .mouseleave(function() {
        $('#venture-caption').hide();
    });
    $('#pursue').mouseenter(function() {
        $('#pursue-caption').show();
    })
    .mouseleave(function() {
        $('#pursue-caption').hide();
    });

    $('#mission-audio').click(function(){
      $('#mission-audio-player').show();
      var audio = document.getElementById("mission-audio-player");
      audio.play();
      $('#mission-audio').hide();
      player.pauseVideo();
    });
    $('.read-more').click(function(){
        window.location.href="https://beam.stanford.edu/about-us";
    });
    $('.launchpage-blue-button').click(function(){
        window.location.href="https://stanforduniversity.qualtrics.com/SE/?SID=SV_50A9JYkHiTxoqTX";
    });
    $('.video-overlay-left-button').click(function(){
        $('#video-overlay').toggle();
        player.seekTo(0);
        player.playVideo();
        var audio = document.getElementById("mission-audio-player");
        audio.pause();
        /*$('#video-overlay').toggle();
        $("video").get(0).setAttribute("controls","controls");
        if($("video").get(0).paused){
            $("video").get(0).play();
        }
        else {
            $("video").get(0).pause();
        } */
    });
});<commit_msg>adding subtitle support<commit_after>/*!
 * Start Bootstrap - Agency Bootstrap Theme (http://startbootstrap.com)
 * Code licensed under the Apache License v2.0.
 * For details, see http://www.apache.org/licenses/LICENSE-2.0.
 */
var tag = document.createElement('script');

tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

      var player;
      function onYouTubeIframeAPIReady() {
        player = new YT.Player('video-container', {
          videoId: '-Nmgm3PwZFk',
          playerVars: { 'modestbranding': 1, 'showinfo': 0, 'controls':0, 'start': 24},
          events: {
            'onReady': onPlayerReady,
            'onStateChange': onPlayerStateChange
          }
        });
      }

 // 4. The API will call this function when the video player is ready.
      function onPlayerReady(event) {
        event.target.playVideo();
      }

      // 5. The API calls this function when the player's state changes.
      //    The function indicates that when playing a video (state=1),
      //    the player should play for six seconds and then stop.
      var done = false;
      function onPlayerStateChange(event) {
        if (event.data == YT.PlayerState.PLAYING && !done) {
          setTimeout(stopVideo, 1);
          done = true;
        }
      }
      function stopVideo() {
        player.pauseVideo();
      }
// jQuery for page scrolling feature - requires jQuery Easing plugin
$(function() {
    $('a.page-scroll').bind('click', function(event) {
        var $anchor = $(this);
        /*$('html, body').stop().animate({
            scrollTop: $($anchor.attr('href')).offset().top
        }, 1500, 'easeInOutExpo');
        event.preventDefault();
        */
    });
});

// Highlight the top nav as scrolling occurs
$('body').scrollspy({
   // target: '.navbar-fixed-top'
})

// Closes the Responsive Menu on Menu Item Click
$('.navbar-collapse ul li a').click(function() {
    $('.navbar-toggle:visible').click();
});

$(document).ready(function(){
    var videoElement = document.getElementById("mission-audio-player");
    var textTracks = videoElement.textTracks; // one for each track element
    var textTrack = textTracks[0]; // corresponds to the first track element
    for (var j = 0; j < textTrack.cues.length; ++j) {
      var cue = textTrack.cues[j];
      cue.onenter = function(){
        console.log("enter");
      };

      cue.onexit = function(){
        // do something else
      };
    }
    function resize(){
      var width  = $('#model-graphic').width();
      var height  = $('#model-graphic').height();
      var circlewidth = .36 * width;
      $('.more').width(circlewidth);
      $('.more').height(circlewidth);
      $(".more").css("line-height", circlewidth + "px");
      newWidth = width * .29;
      newWidthC = newWidth + 112;
      leftWidth = -width * .02;
      leftWidthC = leftWidth + 112;
      rightWidth = width *.6;
      rightWidthC = rightWidth + 112;
      topHeight = height * .04;
      topHeightC = topHeight - 50;
      newHeight = height * .38;
      newHeightC = newHeight - 50;
      bottomHeight = height * .6;
      bottomHeightC = bottomHeight - 50;
      $("#design").css({"left": newWidth + "px", "top" : topHeight + "px"});
      $("#design-caption").css({"left": newWidthC + "px", "top" : topHeightC + "px"});
      $("#connect-circle").css({"left": newWidth + "px", "top": newHeight + "px"});
      $("#connect-caption").css({"left": newWidthC + "px", "top" : newHeightC + "px"});
      $("#pursue").css({"left": leftWidth + "px", "top" : bottomHeight + "px"});
      $("#pursue-caption").css({"left": leftWidthC + "px", "top" : bottomHeightC + "px"});
      $("#venture").css({"left": rightWidth + "px", "top" : bottomHeight + "px"})
      $("#venture-caption").css({"left": rightWidthC + "px", "top" : bottomHeightC + "px"});
    }
    $(window).resize(function(){
      resize();
    });
    resize();
    $('.more-caption').hide();
    $('.below-popup').hide();
    $('#mission-audio-player').hide();
    $('.audience').hover(function(e){
      console.log(e);
      $('.below-popup').css( 'position', 'absolute' );
        $('.below-popup').css( 'top', e.pageY-20);
        $('.below-popup').css( 'left', e.pageX-70);
       $('.below-popup').show();
      },function(){
      $('.below-popup').hide();
    });
    $('#design').mouseenter(function() {
        $('#design-caption').show();
    })
    .mouseleave(function() {
        $('#design-caption').hide();
    });
    $('#connect-circle').mouseenter(function() {
        $('#connect-caption').show();
    })
    .mouseleave(function() {
        $('#connect-caption').hide();
    });
    $('#venture').mouseenter(function() {
        $('#venture-caption').show();
    })
    .mouseleave(function() {
        $('#venture-caption').hide();
    });
    $('#pursue').mouseenter(function() {
        $('#pursue-caption').show();
    })
    .mouseleave(function() {
        $('#pursue-caption').hide();
    });

    $('#mission-audio').click(function(){
      $('#mission-audio-player').show();
      var audio = document.getElementById("mission-audio-player");
      audio.play();
      $('#mission-audio').hide();
      player.pauseVideo();
    });
    $('.read-more').click(function(){
        window.location.href="https://beam.stanford.edu/about-us";
    });
    $('.launchpage-blue-button').click(function(){
        window.location.href="https://stanforduniversity.qualtrics.com/SE/?SID=SV_50A9JYkHiTxoqTX";
    });
    $('.video-overlay-left-button').click(function(){
        $('#video-overlay').toggle();
        player.seekTo(0);
        player.playVideo();
        var audio = document.getElementById("mission-audio-player");
        audio.pause();
        /*$('#video-overlay').toggle();
        $("video").get(0).setAttribute("controls","controls");
        if($("video").get(0).paused){
            $("video").get(0).play();
        }
        else {
            $("video").get(0).pause();
        } */
    });
});<|endoftext|>


<commit_before>var vhome = document.getElementById("ihome");
var vabout = document.getElementById("iabout");
var vchildhood = document.getElementById("ichildhood");
var vcollege = document.getElementById("icollege");
var vnss = document.getElementById("inss");
var vlove = document.getElementById("ilove");
var vstep = document.getElementById("istep");
var vdad = document.getElementById("idad");
var vcontact = document.getElementById("icontact");
var vfeedback = document.getElementById("ifeedback");

var ta = document.getElementById('contentdiv');
var x = new XMLHttpRequest;
function funct(){
	ta.innerHTML = x.responseText;
}

function func(){
	x.abort();
	x.open("GET", "pages/home.html");
	x.onreadystatechange =funct;
	x.send();
}

function fhome(){
	x.abort();
	x.open("GET", "pages/home.html");
	x.onreadystatechange =funct;
	x.send();
}

function fabout(){
	x.abort();
	x.open("GET", "pages/about.html");
	x.onreadystatechange =funct;
	x.send();
}

function fchildhood(){
	x.abort();
	x.open("GET", "pages/childhood.html");
	x.onreadystatechange =funct;
	x.send();
}

function fcollege(){
	x.abort();
	x.open("GET", "pages/college.html");
	x.onreadystatechange =funct;
	x.send();
}

function fnss(){
	x.abort();
	x.open("GET", "pages/nss.html");
	x.onreadystatechange =funct;
	x.send();
}

function flove(){
	x.abort();
	x.open("GET", "pages/love.html");
	x.onreadystatechange =funct;
	x.send();
}

function fstep(){
	x.abort();
	x.open("GET", "pages/step.html");
	x.onreadystatechange =funct;
	x.send();
}

function fdad(){
	x.abort();
	x.open("GET", "pages/dad.html");
	x.onreadystatechange =funct;
	x.send();
}

function fcontact(){
	x.abort();
	x.open("GET", "pages/contact.html");
	x.onreadystatechange =funct;
	x.send();
}

function ffeedback(){
	x.abort();
	x.open("GET", "pages/feedback.html");
	x.onreadystatechange =funct;
	x.send();
}

window.onload=func;

if(vhome.addEventListener)
	vhome.addEventListener("click", fhome, false);
else if(vhome.attachEvent)
	vhome.attachEvent('onclick', fhome);

if(vabout.addEventListener)
	vabout.addEventListener("click", fabout, false);
else if(vabout.attachEvent)
	vabout.attachEvent('onclick', fabout);

if(vchild.addEventListener)
	vchild.addEventListener("click", fchildhood, false);
else if(vchild.attachEvent)
	vchild.attachEvent('onclick', fchildhood);

if(vcollege.addEventListener)
	vcollege.addEventListener("click", fcollege, false);
else if(vcollege.attachEvent)
	vcollege.attachEvent('onclick', fcollege);

if(vnss.addEventListener)
	vnss.addEventListener("click", fnss, false);
else if(vnss.attachEvent)
	vnss.attachEvent('onclick', fnss);

if(vlove.addEventListener)
	vlove.addEventListener("click", flove, false);
else if(vlove.attachEvent)
	vlove.attachEvent('onclick', flove);

if(vstep.addEventListener)
	vstep.addEventListener("click", fstep, false);
else if(vstep.attachEvent)
	vstep.attachEvent('onclick', fstep);

if(vdad.addEventListener)
	vdad.addEventListener("click", fdad, false);
else if(vdad.attachEvent)
	vdad.attachEvent('onclick', fdad);

if(vcontact.addEventListener)
	vcontact.addEventListener("click", fcontact, false);
else if(vcontact.attachEvent)
	vcontact.attachEvent('onclick', fcontact);

if(vfeedback.addEventListener)
	vfeedback.addEventListener("click", ffeedback, false);
else if(vfeedback.attachEvent)
	vfeedback.attachEvent('onclick', ffeedback);
<commit_msg>Update ajaxed.js<commit_after>var vhome = document.getElementById("ihome");
var vabout = document.getElementById("iabout");
var vchildhood = document.getElementById("ichildhood");
var vcollege = document.getElementById("icollege");
var vnss = document.getElementById("inss");
var vlove = document.getElementById("ilove");
var vstep = document.getElementById("istep");
var vdad = document.getElementById("idad");
var vcontact = document.getElementById("icontact");
var vfeedback = document.getElementById("ifeedback");

var ta = document.getElementById('contentdiv');
var x = new XMLHttpRequest;
function funct(){
	ta.innerHTML = x.responseText;
}

function func(){
	x.open("GET", "pages/home.html");
	x.onreadystatechange =funct;
	x.send();
}

function fhome(){
	x.abort();
	x.open("GET", "pages/home.html");
	x.onreadystatechange =funct;
	x.send();
}

function fabout(){
	x.abort();
	x.open("GET", "pages/about.html");
	x.onreadystatechange =funct;
	x.send();
}

function fchildhood(){
	x.abort();
	x.open("GET", "pages/childhood.html");
	x.onreadystatechange =funct;
	x.send();
}

function fcollege(){
	x.abort();
	x.open("GET", "pages/college.html");
	x.onreadystatechange =funct;
	x.send();
}

function fnss(){
	x.abort();
	x.open("GET", "pages/nss.html");
	x.onreadystatechange =funct;
	x.send();
}

function flove(){
	x.abort();
	x.open("GET", "pages/love.html");
	x.onreadystatechange =funct;
	x.send();
}

function fstep(){
	x.abort();
	x.open("GET", "pages/step.html");
	x.onreadystatechange =funct;
	x.send();
}

function fdad(){
	x.abort();
	x.open("GET", "pages/dad.html");
	x.onreadystatechange =funct;
	x.send();
}

function fcontact(){
	x.abort();
	x.open("GET", "pages/contact.html");
	x.onreadystatechange =funct;
	x.send();
}

function ffeedback(){
	x.abort();
	x.open("GET", "pages/feedback.html");
	x.onreadystatechange =funct;
	x.send();
}

window.onload=func;

if(vhome.addEventListener)
	vhome.addEventListener("click", fhome, false);
else if(vhome.attachEvent)
	vhome.attachEvent('onclick', fhome);

if(vabout.addEventListener)
	vabout.addEventListener("click", fabout, false);
else if(vabout.attachEvent)
	vabout.attachEvent('onclick', fabout);

if(vchildhood.addEventListener)
	vchildhood.addEventListener("click", fchildhood, false);
else if(vchildhood.attachEvent)
	vchildhood.attachEvent('onclick', fchildhood);

if(vcollege.addEventListener)
	vcollege.addEventListener("click", fcollege, false);
else if(vcollege.attachEvent)
	vcollege.attachEvent('onclick', fcollege);

if(vnss.addEventListener)
	vnss.addEventListener("click", fnss, false);
else if(vnss.attachEvent)
	vnss.attachEvent('onclick', fnss);

if(vlove.addEventListener)
	vlove.addEventListener("click", flove, false);
else if(vlove.attachEvent)
	vlove.attachEvent('onclick', flove);

if(vstep.addEventListener)
	vstep.addEventListener("click", fstep, false);
else if(vstep.attachEvent)
	vstep.attachEvent('onclick', fstep);

if(vdad.addEventListener)
	vdad.addEventListener("click", fdad, false);
else if(vdad.attachEvent)
	vdad.attachEvent('onclick', fdad);

if(vcontact.addEventListener)
	vcontact.addEventListener("click", fcontact, false);
else if(vcontact.attachEvent)
	vcontact.attachEvent('onclick', fcontact);

if(vfeedback.addEventListener)
	vfeedback.addEventListener("click", ffeedback, false);
else if(vfeedback.attachEvent)
	vfeedback.attachEvent('onclick', ffeedback);
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 Jesse van den Kieboom. All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above
 *      copyright notice, this list of conditions and the following disclaimer
 *      in the documentation and/or other materials provided with the
 *      distribution.
 *    * Neither the name of Google Inc. nor the names of its
 *      contributors may be used to endorse or promote products derived from
 *      this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

var ui = require('../ui/ui');

function grid(props) {
    return new ui.Grid(props);
}

function label(props) {
    if (typeof props === 'string') {
        props = {
            value: props
        };
    }

    return new ui.Label(props);
}

function onoff(props) {
    return new ui.OnOff(props);
}

function slider(props) {
    return new ui.Slider(props);
}

exports.grid = grid;
exports.label = label;
exports.onoff = onoff;
exports.slider = slider;
<commit_msg>Add modeline<commit_after>/*
 * Copyright (c) 2014 Jesse van den Kieboom. All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above
 *      copyright notice, this list of conditions and the following disclaimer
 *      in the documentation and/or other materials provided with the
 *      distribution.
 *    * Neither the name of Google Inc. nor the names of its
 *      contributors may be used to endorse or promote products derived from
 *      this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

var ui = require('../ui/ui');

function grid(props) {
    return new ui.Grid(props);
}

function label(props) {
    if (typeof props === 'string') {
        props = {
            value: props
        };
    }

    return new ui.Label(props);
}

function onoff(props) {
    return new ui.OnOff(props);
}

function slider(props) {
    return new ui.Slider(props);
}

exports.grid = grid;
exports.label = label;
exports.onoff = onoff;
exports.slider = slider;

// vi:ts=4:et
<|endoftext|>