<commit_before>'use strict';

(function () {
  angular.module('google-maps').

  /**
   * Directive controller which is owned by the googleMap directive and shared
   * among all other google maps directives.
   */
  factory('googleMapControllerFactory', ['googleMapsUtils', 'googleMapsDefaults', 'googleMapsContainer',
    function (googleMapsUtils, googleMapsDefaults, googleMapsContainer) {

    /** aliases */
    var latLngEqual = googleMapsUtils.latLngEqual;
    var boundsEqual = googleMapsUtils.boundsEqual;
    var latLngToObj = googleMapsUtils.latLngToObj;
    var hasNaN = googleMapsUtils.hasNaN;
    var gMDefaults = googleMapsDefaults;
    var gMContainer = googleMapsContainer;

    /** MapController class **/

    /*
     * Construct a new controller for the googleMap directive.
     * @param {angular.Scope} $scope
     * @param {angular.element} $element
     * @param {angular.Attributes} $attrs
     * @constructor
     */
    var MapController = function($scope, $element, $attrs) {

      var mapId = $attrs.mapId;
      if (!mapId) { throw 'googleMap must have non-empty mapId attribute'; }

      var mapDiv = $element.find('[id]');
      mapDiv.attr('id', mapId);

      var config = this._getConfig($scope, gMDefaults);

      // 'private' properties
      this._map = this._createMap(mapId, mapDiv, config, gMContainer);
      this._markers = {};

      // 'public' properties
      this.dragging = false;

      Object.defineProperty(this, 'precision', {
        value: 3,
        writeable: false,
      });

      Object.defineProperty(this, 'center', {
        get: function() {
               return this._map.getCenter();
             },
        set: function(center) {
               if (hasNaN(center))
                 throw 'center contains null or NaN';
               var changed = !latLngEqual(this.center, center);
               if (changed) {
                 this._map.panTo(center);
               }
             }
      });

      Object.defineProperty(this, 'zoom', {
        get: function() {
               return this._map.getZoom();
             },
        set: function(zoom) {
               if (!(zoom != null && !isNaN(zoom)))
                 throw 'zoom was null or NaN';
               var changed = this.zoom !== zoom;
               if (changed) {
                this._map.setZoom(self.zoom);
               }
             }
      });

      Object.defineProperty(this, 'bounds', {
        get: function() {
               return this._map.getBounds();
             },
        set: function(bounds) {
               var numbers = !hasNaN(bounds.getSouthWest()) &&
                             !hasNaN(bounds.getNorthEast());
               if (!numbers)
                 throw 'bounds contains null or NaN';

               var changed = !(boundsEqual(this.bounds, bounds));
               if (changed) {
                 this._map.fitBounds(bounds);
               }
             }
      });

      this._initDragListeners();
    };

    // Retrieve google.maps.MapOptions
    MapController.prototype._getConfig = function($scope, gMDefaults) {
      // Get config or defaults
      var defaults = gMDefaults.mapOptions;
      var config = {};
      angular.extend(config, defaults, $scope.mapOptions());
      return config;
    };

    // Create the map and add to googleMapsContainer
    MapController.prototype._createMap = function(id, element, config, gMContainer) {
      var map = gMContainer.getMap(id);
      if (!map) {
        map = new google.maps.Map(element[0], config);
        gMContainer.addMap(id, map);
      } else {
        throw 'A map with id ' + id + ' already exists. You must use' +
          ' different ids for each instance of the googleMap directive.';
      }
      return map;
    };

    // Set up listeners to update this.dragging
    MapController.prototype._initDragListeners = function() {
      var self = this;
      this.addMapListener('dragstart', function () {
        self.dragging = true;
      });

      this.addMapListener('idle', function () {
        self.dragging = false;
      });

      this.addMapListener('drag', function() {
        self.dragging = true;
      });
    };

    /**
     * Alias for google.maps.event.addListener(map, event, handler)
     * @param {string} event an event defined on google.maps.Map
     * @param {function} a handler for the event
     */
    MapController.prototype.addMapListener = function(event, handler) {
      google.maps.event.addListener(this._map,
          event, handler);
    };

    /**
     * Alias for google.maps.event.addListenerOnce(map, event, handler)
     * @param {string} event an event defined on google.maps.Map
     * @param {function} a handler for the event
     */
    MapController.prototype.addMapListenerOnce = function(event, handler) {
      google.maps.event.addListenerOnce(this._map,
          event, handler);
    };

    /**
     * Alias for google.maps.event.addListener(object, event, handler)
     */
    MapController.prototype.addListener = function(object, event, handler) {
      google.maps.event.addListener(object, event, handler);
    };

    /**
     * Alias for google.maps.event.addListenerOnce(object, event, handler)
     */
    MapController.prototype.addListenerOnce = function(object, event, handler) {
      google.maps.event.addListenerOnce(object, event, handler);
    };

    /**
     * Adds a new marker to the map.
     * @param {google.maps.MarkerOptions} markerOptions
     * @return {boolean} true if a marker was added, false if there was already
     *   a marker at this position. 'at this position' means delta_lat and
     *   delta_lng are < 0.0005
     * @throw if markerOptions does not have all required options (i.e. position)
     */
    MapController.prototype.addMarker = function(markerOptions) {
      var opts = {};
      angular.extend(opts, markerOptions);

      if (!(opts.position instanceof google.maps.LatLng)) {
        throw 'markerOptions did not contain a position';
      }

      var marker = new google.maps.Marker(opts);
      var position = marker.getPosition();
      if (this.hasMarker(position.lat(), position.lng())) {
        return false;
      }

      var hash = position.toUrlValue(this.precision);
      this._markers[hash] = marker;
      marker.setMap(this._map);
      return true;
    };

    /**
     * @param {number} lat
     * @param {number} lng
     * @return {boolean} true if there is a marker with the given lat and lng
     */
    MapController.prototype.hasMarker = function(lat, lng) {
      return (this.getMarker(lat, lng) instanceof google.maps.Marker);
    };

    /**
     * @param {number} lat
     * @param {number} lng
     * @return {google.maps.Marker} the marker at given lat and lng, or null if
     *   no such marker exists
     */
    MapController.prototype.getMarker = function (lat, lng) {
      if (lat == null || lng == null)
        throw 'lat or lng was null';

      var latLng = new google.maps.LatLng(lat, lng);
      var hash = latLng.toUrlValue(this.precision);
      if (hash in this._markers) {
        return this._markers[hash];
      } else {
        return null;
      }
    };

    /**
     * @param {number} lat
     * @param {number} lng
     * @return {boolean} true if a marker was removed, false if nothing
     *   happened
     */
    MapController.prototype.removeMarker = function(lat, lng) {
      if (lat == null || lng == null)
        throw 'lat or lng was null';

      var latLng = new google.maps.LatLng(lat, lng);

      var removed = false;
      var hash = latLng.toUrlValue(this.precision);
      var marker = this._markers[hash];
      if (marker) {
        marker.setMap(null);
        removed = true;
      }
      this._markers[hash] = null;
      return removed;
    };

    /**
     * Changes bounds of map to view all markers.
     *
     * Note: after calling this function, this.bounds, this.center, and
     * this.zoom may temporarily be null as the map moves. Therefore, use
     * this.addMapListenerOnce if you need to access these values immediately
     * after calling fitToMarkers.
     */
    MapController.prototype.fitToMarkers = function () {
      var bounds = new google.maps.LatLngBounds();

      this.forEachMarker(function(marker) {
        bounds.extend(marker.getPosition());
      });

      this._map.fitBounds(bounds);
    };

    /**
     * Applies a function to each marker.
     * @param {function} fn will called with marker as first argument
     * @throw if fn is null or undefined
     */
    MapController.prototype.forEachMarker = function(fn) {
      if (fn == null) { throw 'fn was null or undefined'; };
      angular.forEach(this._markers, function(marker, hash) {
        fn(marker);
      });
    };

    return {
      MapController: MapController
    };

  }]);
})();

<commit_msg>Re-added MapController.precision so tests can access.<commit_after>'use strict';

(function () {
  angular.module('google-maps').

  /**
   * Directive controller which is owned by the googleMap directive and shared
   * among all other google maps directives.
   */
  factory('googleMapControllerFactory', ['googleMapsUtils', 'googleMapsDefaults', 'googleMapsContainer',
    function (googleMapsUtils, googleMapsDefaults, googleMapsContainer) {

    /** aliases */
    var latLngEqual = googleMapsUtils.latLngEqual;
    var boundsEqual = googleMapsUtils.boundsEqual;
    var latLngToObj = googleMapsUtils.latLngToObj;
    var hasNaN = googleMapsUtils.hasNaN;
    var gMDefaults = googleMapsDefaults;
    var gMContainer = googleMapsContainer;

    /** MapController class **/

    /*
     * Construct a new controller for the googleMap directive.
     * @param {angular.Scope} $scope
     * @param {angular.element} $element
     * @param {angular.Attributes} $attrs
     * @constructor
     */
    var MapController = function($scope, $element, $attrs) {

      var mapId = $attrs.mapId;
      if (!mapId) { throw 'googleMap must have non-empty mapId attribute'; }

      var mapDiv = $element.find('[id]');
      mapDiv.attr('id', mapId);

      var config = this._getConfig($scope, gMDefaults);

      // 'private' properties
      this._map = this._createMap(mapId, mapDiv, config, gMContainer);
      this._markers = {};

      // 'public' properties
      this.dragging = false;

      Object.defineProperty(this, 'precision', {
        value: MapController.precision,
        writeable: false,
      });

      Object.defineProperty(this, 'center', {
        get: function() {
               return this._map.getCenter();
             },
        set: function(center) {
               if (hasNaN(center))
                 throw 'center contains null or NaN';
               var changed = !latLngEqual(this.center, center);
               if (changed) {
                 // TODO: change to panTo
                 this._map.setCenter(center);
               }
             }
      });

      Object.defineProperty(this, 'zoom', {
        get: function() {
               return this._map.getZoom();
             },
        set: function(zoom) {
               if (!(zoom != null && !isNaN(zoom)))
                 throw 'zoom was null or NaN';
               var changed = this.zoom !== zoom;
               if (changed) {
                 this._map.setZoom(zoom);
               }
             }
      });

      Object.defineProperty(this, 'bounds', {
        get: function() {
               return this._map.getBounds();
             },
        set: function(bounds) {
               var numbers = !hasNaN(bounds.getSouthWest()) &&
                             !hasNaN(bounds.getNorthEast());
               if (!numbers)
                 throw 'bounds contains null or NaN';

               var changed = !(boundsEqual(this.bounds, bounds));
               if (changed) {
                 this._map.fitBounds(bounds);
               }
             }
      });

      this._initDragListeners();
    };

    // used for hashing marker objects
    MapController.precision = 3;

    // Retrieve google.maps.MapOptions
    MapController.prototype._getConfig = function($scope, gMDefaults) {
      // Get config or defaults
      var defaults = gMDefaults.mapOptions;
      var config = {};
      angular.extend(config, defaults, $scope.mapOptions());
      return config;
    };

    // Create the map and add to googleMapsContainer
    MapController.prototype._createMap = function(id, element, config, gMContainer) {
      var map = gMContainer.getMap(id);
      if (!map) {
        map = new google.maps.Map(element[0], config);
        gMContainer.addMap(id, map);
      } else {
        throw 'A map with id ' + id + ' already exists. You must use' +
          ' different ids for each instance of the googleMap directive.';
      }
      return map;
    };

    // Set up listeners to update this.dragging
    MapController.prototype._initDragListeners = function() {
      var self = this;
      this.addMapListener('dragstart', function () {
        self.dragging = true;
      });

      this.addMapListener('idle', function () {
        self.dragging = false;
      });

      this.addMapListener('drag', function() {
        self.dragging = true;
      });
    };

    /**
     * Alias for google.maps.event.addListener(map, event, handler)
     * @param {string} event an event defined on google.maps.Map
     * @param {function} a handler for the event
     */
    MapController.prototype.addMapListener = function(event, handler) {
      google.maps.event.addListener(this._map,
          event, handler);
    };

    /**
     * Alias for google.maps.event.addListenerOnce(map, event, handler)
     * @param {string} event an event defined on google.maps.Map
     * @param {function} a handler for the event
     */
    MapController.prototype.addMapListenerOnce = function(event, handler) {
      google.maps.event.addListenerOnce(this._map,
          event, handler);
    };

    /**
     * Alias for google.maps.event.addListener(object, event, handler)
     */
    MapController.prototype.addListener = function(object, event, handler) {
      google.maps.event.addListener(object, event, handler);
    };

    /**
     * Alias for google.maps.event.addListenerOnce(object, event, handler)
     */
    MapController.prototype.addListenerOnce = function(object, event, handler) {
      google.maps.event.addListenerOnce(object, event, handler);
    };

    /**
     * Adds a new marker to the map.
     * @param {google.maps.MarkerOptions} markerOptions
     * @return {boolean} true if a marker was added, false if there was already
     *   a marker at this position. 'at this position' means delta_lat and
     *   delta_lng are < 0.0005
     * @throw if markerOptions does not have all required options (i.e. position)
     */
    MapController.prototype.addMarker = function(markerOptions) {
      var opts = {};
      angular.extend(opts, markerOptions);

      if (!(opts.position instanceof google.maps.LatLng)) {
        throw 'markerOptions did not contain a position';
      }

      var marker = new google.maps.Marker(opts);
      var position = marker.getPosition();
      if (this.hasMarker(position.lat(), position.lng())) {
        return false;
      }

      var hash = position.toUrlValue(this.precision);
      this._markers[hash] = marker;
      marker.setMap(this._map);
      return true;
    };

    /**
     * @param {number} lat
     * @param {number} lng
     * @return {boolean} true if there is a marker with the given lat and lng
     */
    MapController.prototype.hasMarker = function(lat, lng) {
      return (this.getMarker(lat, lng) instanceof google.maps.Marker);
    };

    /**
     * @param {number} lat
     * @param {number} lng
     * @return {google.maps.Marker} the marker at given lat and lng, or null if
     *   no such marker exists
     */
    MapController.prototype.getMarker = function (lat, lng) {
      if (lat == null || lng == null)
        throw 'lat or lng was null';

      var latLng = new google.maps.LatLng(lat, lng);
      var hash = latLng.toUrlValue(this.precision);
      if (hash in this._markers) {
        return this._markers[hash];
      } else {
        return null;
      }
    };

    /**
     * @param {number} lat
     * @param {number} lng
     * @return {boolean} true if a marker was removed, false if nothing
     *   happened
     */
    MapController.prototype.removeMarker = function(lat, lng) {
      if (lat == null || lng == null)
        throw 'lat or lng was null';

      var latLng = new google.maps.LatLng(lat, lng);

      var removed = false;
      var hash = latLng.toUrlValue(this.precision);
      var marker = this._markers[hash];
      if (marker) {
        marker.setMap(null);
        removed = true;
      }
      this._markers[hash] = null;
      return removed;
    };

    /**
     * Changes bounds of map to view all markers.
     *
     * Note: after calling this function, this.bounds, this.center, and
     * this.zoom may temporarily be null as the map moves. Therefore, use
     * this.addMapListenerOnce if you need to access these values immediately
     * after calling fitToMarkers.
     */
    MapController.prototype.fitToMarkers = function () {
      var bounds = new google.maps.LatLngBounds();

      this.forEachMarker(function(marker) {
        bounds.extend(marker.getPosition());
      });

      this._map.fitBounds(bounds);
    };

    /**
     * Applies a function to each marker.
     * @param {function} fn will called with marker as first argument
     * @throw if fn is null or undefined
     */
    MapController.prototype.forEachMarker = function(fn) {
      if (fn == null) { throw 'fn was null or undefined'; };
      angular.forEach(this._markers, function(marker, hash) {
        fn(marker);
      });
    };

    return {
      MapController: MapController
    };

  }]);
})();

<|endoftext|>


<commit_before>'use strict';

require('dotenv').load();

var pkg = require('./package.json'),
    path = require('path');

var gulp = require('gulp'),
    gutil = require('gulp-util'),
    inject = require('gulp-inject'),
    plumber = require('gulp-plumber'),
    pgbuild = require('gulp-phonegap-build'),
    bowerFiles = require('main-bower-files');

var dir = {
    out: path.join(__dirname, './out'),
    dist: path.join(__dirname, './dist'),
    assets: path.join(__dirname, './public'),
};

gulp.task('default', ['inject', 'build'], function () {
    gutil.log('Building... This might take a while.');
});

gulp.task('build', function () {
    gulp.src(dir.assets + '/**')
        .pipe(plumber())
        .pipe(pgbuild({
            appId: process.env.PG_BUILD_APP_ID,
            download: {
                android: dir.out + '/onesquare-' + pkg.version + '.apk'
            },
            user: {
                token: process.env.PG_BUILD_AUTH_TOKEN
            }
        }));
});

gulp.task('inject', function () {
    var sources = [
        dir.assets + '/lib/**/*.html'
    ];

    return gulp.src(dir.assets + '/index.html')
        .pipe(inject(gulp.src(sources, {read: false})))
        .pipe(inject(gulp.src(bowerFiles(), {read: false}), {name: 'bower'}))
        .pipe(gulp.dest(dir.dist));
});
<commit_msg>Fix injected file path pointing to root.<commit_after>'use strict';

require('dotenv').load();

var pkg = require('./package.json'),
    path = require('path');

var gulp = require('gulp'),
    gutil = require('gulp-util'),
    inject = require('gulp-inject'),
    plumber = require('gulp-plumber'),
    pgbuild = require('gulp-phonegap-build'),
    bowerFiles = require('main-bower-files');

var dir = {
    out: path.join(__dirname, './out'),
    dist: path.join(__dirname, './dist'),
    assets: path.join(__dirname, './public'),
};

gulp.task('default', ['inject', 'build'], function () {
    gutil.log('Building... This might take a while.');
});

gulp.task('build', function () {
    gulp.src(dir.assets + '/**')
        .pipe(plumber())
        .pipe(pgbuild({
            appId: process.env.PG_BUILD_APP_ID,
            download: {
                android: dir.out + '/onesquare-' + pkg.version + '.apk'
            },
            user: {
                token: process.env.PG_BUILD_AUTH_TOKEN
            }
        }));
});

gulp.task('inject', function () {
    var sources = [
        dir.assets + '/lib/**/*.html'
    ];

    return gulp.src(dir.assets + '/index.html')
        .pipe(inject(gulp.src(sources, {read: false}), {addRootSlash: false}))
        .pipe(inject(gulp.src(bowerFiles(), {read: false}), {name: 'bower', addRootSlash: false}))
        .pipe(gulp.dest(dir.dist));
});
<|endoftext|>


<commit_before>// Instantiate objects based on a JSON "record". The record must be a statement
// array in the following form:
//
//     [ "{verb} {subject}", arg0, arg1, arg2, ... argn ]
//
// Each record is processed from a passed `context` which starts from the
// global (ie. `window`) context if unspecified.
//
// - `@literal` Evaluate `subject` and return its value as a scalar. Useful for
//   referencing API constants, object properties or other values.
// - `@new` Call `subject` as a constructor with args `arg0 - argn`. The
//   newly created object will be the new context.
// - `@call` Call `subject` as a function with args `arg0 - argn` in the
//   global namespace. The return value will be the new context.
// - `@chain` Call `subject` as a method of the current context with args `arg0
//   - argn`. The return value will be the new context.
// - `@inject` Call `subject` as a method of the current context with args
//   `arg0 - argn`. The return value will *not* affect the context.
// - `@group` Treat `arg0 - argn` as a series of statement arrays that share a
//   context. Each statement will be called in serial and affect the context
//   for the next statement.
//
// Requirements:
//
// - Underscore.js
// - jQuery @TODO: only used for $.browser check. Could probably be removed.
//
// Usage:
//
//     var gmap = ['@new google.maps.Map',
//         ['@call document.getElementById', 'gmap'],
//         {
//             center: [ '@new google.maps.LatLng', 0, 0 ],
//             zoom: 2,
//             mapTypeId: [ '@literal google.maps.MapTypeId.ROADMAP' ]
//         }
//     ];
//     wax.Record(gmap);
var wax = wax || {};
wax.Record = function(obj, context) {
    var getFunction = function(head, cur) {
        var ret = _.reduce(head.split('.'), function(part, segment) {
            return [part[1] || part[0], part[1] ? part[1][segment] : part[0][segment]];
        }, [cur || window, null]);
        return ret;
    };
    var makeObject = function(fn_name, args) {
        var fn_obj = getFunction(fn_name),
            obj;
        args = args.length ? wax.Record(args) : [];

        // real browsers
        if (!$.browser.msie) {
            obj = Object.create(fn_obj[1].prototype);
            fn_obj[1].apply(obj, args);
        // lord have mercy on your soul.
        } else {
            switch(args.length) {
                case 0: obj = new fn_obj[1](); break;
                case 1: obj = new fn_obj[1](args[0]); break;
                case 2: obj = new fn_obj[1](args[0], args[1]); break;
                case 3: obj = new fn_obj[1](args[0], args[1], args[2]); break;
                case 4: obj = new fn_obj[1](args[0], args[1], args[2], args[3]); break;
                case 5: obj = new fn_obj[1](args[0], args[1], args[2], args[3], args[4]); break;
                default: break;
            }
        }
        return obj;
    };
    var runFunction = function(fn_name, args, cur) {
        var fn_obj = getFunction(fn_name, cur);
        var fn_args = args.length ? wax.Record(args) : [];
        // @TODO: This is currently a stopgap measure that calls methods like
        // `foo.bar()` in the context of `foo`. It will probably be necessary
        // in the future to be able to call `foo.bar()` from other contexts.
        if (cur && fn_name.indexOf('.') === -1) {
            return fn_obj[1].apply(cur, fn_args);
        } else {
            return fn_obj[1].apply(fn_obj[0], fn_args);
        }
    };
    var isKeyword = function(string) {
        return _.isString(string) && (_.indexOf([
            '@new',
            '@call',
            '@literal',
            '@chain',
            '@inject',
            '@group'
        ], string.split(' ')[0]) !== -1);
    };
    var altersContext = function(string) {
        return _.isString(string) && (_.indexOf([
            '@new',
            '@call',
            '@chain'
        ], string.split(' ')[0]) !== -1);
    };
    var getStatement = function(obj) {
        if (_.isArray(obj) && obj[0] && isKeyword(obj[0])) {
            return {
                verb: obj[0].split(' ')[0],
                subject: obj[0].split(' ')[1],
                object: obj.slice(1)
            };
        }
        return false;
    };

    var i,
        fn = false,
        ret = null,
        child = null,
        statement = getStatement(obj);
    if (statement) {
        switch (statement.verb) {
        case '@group':
            for (i = 0; i < statement.object.length; i++) {
                ret = wax.Record(statement.object[i], context);
                child = getStatement(statement.object[i]);
                if (child && altersContext(child.verb)) {
                    context = ret;
                }
            }
            return context;
        case '@new':
            return makeObject(statement.subject, statement.object);
        case '@literal':
            fn = getFunction(statement.subject);
            return fn ? fn[1] : null;
        case '@inject':
            return runFunction(statement.subject, statement.object, context);
        case '@chain':
            return runFunction(statement.subject, statement.object, context);
        case '@call':
            return runFunction(statement.subject, statement.object, null);
        }
    } else {
        // Reify object/arrays.
        try {
            var keys = _.keys(obj);
            for (i = 0; i < keys.length; i++) {
                var key = keys[i];
                obj[key] = wax.Record(obj[key], context);
            }
            return obj;
        // Unwrapped scalars
        } catch(e) {
            return obj;
        }
    }
};
<commit_msg>Firefox 3 fixes.<commit_after>// Instantiate objects based on a JSON "record". The record must be a statement
// array in the following form:
//
//     [ "{verb} {subject}", arg0, arg1, arg2, ... argn ]
//
// Each record is processed from a passed `context` which starts from the
// global (ie. `window`) context if unspecified.
//
// - `@literal` Evaluate `subject` and return its value as a scalar. Useful for
//   referencing API constants, object properties or other values.
// - `@new` Call `subject` as a constructor with args `arg0 - argn`. The
//   newly created object will be the new context.
// - `@call` Call `subject` as a function with args `arg0 - argn` in the
//   global namespace. The return value will be the new context.
// - `@chain` Call `subject` as a method of the current context with args `arg0
//   - argn`. The return value will be the new context.
// - `@inject` Call `subject` as a method of the current context with args
//   `arg0 - argn`. The return value will *not* affect the context.
// - `@group` Treat `arg0 - argn` as a series of statement arrays that share a
//   context. Each statement will be called in serial and affect the context
//   for the next statement.
//
// Requirements:
//
// - Underscore.js
// - jQuery @TODO: only used for $.browser check. Could probably be removed.
//
// Usage:
//
//     var gmap = ['@new google.maps.Map',
//         ['@call document.getElementById', 'gmap'],
//         {
//             center: [ '@new google.maps.LatLng', 0, 0 ],
//             zoom: 2,
//             mapTypeId: [ '@literal google.maps.MapTypeId.ROADMAP' ]
//         }
//     ];
//     wax.Record(gmap);
var wax = wax || {};
wax.Record = function(obj, context) {
    var getFunction = function(head, cur) {
        var ret = _.reduce(head.split('.'), function(part, segment) {
            return [part[1] || part[0], part[1] ? part[1][segment] : part[0][segment]];
        }, [cur || window, null]);
        return ret;
    };
    var makeObject = function(fn_name, args) {
        var fn_obj = getFunction(fn_name),
            obj;
        args = args.length ? wax.Record(args) : [];

        // real browsers
        if (Object.create) {
            obj = Object.create(fn_obj[1].prototype);
            fn_obj[1].apply(obj, args);
        // lord have mercy on your soul.
        } else {
            switch(args.length) {
                case 0: obj = new fn_obj[1](); break;
                case 1: obj = new fn_obj[1](args[0]); break;
                case 2: obj = new fn_obj[1](args[0], args[1]); break;
                case 3: obj = new fn_obj[1](args[0], args[1], args[2]); break;
                case 4: obj = new fn_obj[1](args[0], args[1], args[2], args[3]); break;
                case 5: obj = new fn_obj[1](args[0], args[1], args[2], args[3], args[4]); break;
                default: break;
            }
        }
        return obj;
    };
    var runFunction = function(fn_name, args, cur) {
        var fn_obj = getFunction(fn_name, cur);
        var fn_args = args.length ? wax.Record(args) : [];
        // @TODO: This is currently a stopgap measure that calls methods like
        // `foo.bar()` in the context of `foo`. It will probably be necessary
        // in the future to be able to call `foo.bar()` from other contexts.
        if (cur && fn_name.indexOf('.') === -1) {
            return fn_obj[1].apply(cur, fn_args);
        } else {
            return fn_obj[1].apply(fn_obj[0], fn_args);
        }
    };
    var isKeyword = function(string) {
        return _.isString(string) && (_.indexOf([
            '@new',
            '@call',
            '@literal',
            '@chain',
            '@inject',
            '@group'
        ], string.split(' ')[0]) !== -1);
    };
    var altersContext = function(string) {
        return _.isString(string) && (_.indexOf([
            '@new',
            '@call',
            '@chain'
        ], string.split(' ')[0]) !== -1);
    };
    var getStatement = function(obj) {
        if (_.isArray(obj) && obj[0] && isKeyword(obj[0])) {
            return {
                verb: obj[0].split(' ')[0],
                subject: obj[0].split(' ')[1],
                object: obj.slice(1)
            };
        }
        return false;
    };

    var i,
        fn = false,
        ret = null,
        child = null,
        statement = getStatement(obj);
    if (statement) {
        switch (statement.verb) {
        case '@group':
            for (i = 0; i < statement.object.length; i++) {
                ret = wax.Record(statement.object[i], context);
                child = getStatement(statement.object[i]);
                if (child && altersContext(child.verb)) {
                    context = ret;
                }
            }
            return context;
        case '@new':
            return makeObject(statement.subject, statement.object);
        case '@literal':
            fn = getFunction(statement.subject);
            return fn ? fn[1] : null;
        case '@inject':
            return runFunction(statement.subject, statement.object, context);
        case '@chain':
            return runFunction(statement.subject, statement.object, context);
        case '@call':
            return runFunction(statement.subject, statement.object, null);
        }
    } else if (typeof obj === 'object') {
        var keys = _.keys(obj);
        for (i = 0; i < keys.length; i++) {
            var key = keys[i];
            obj[key] = wax.Record(obj[key], context);
        }
        return obj;
    } else {
        return obj;
    }
};
<|endoftext|>


<commit_before>// Dependencies that makes this all work! Yay packages!
var gulp = require('gulp'),
    cleanCSS = require('gulp-clean-css'),
    del = require('del'),
    inlineCSS = require('gulp-inline-css'),
    preprocess = require('gulp-preprocess'),
    rename = require('gulp-rename'),
    strip = require('gulp-strip-comments');

// Load in environment variables from .boilerplate.defaults first and then .boilerplate.custom if it exists
var boilerplateConfig = require('dotenv-extended').load(
    {
        encoding: 'utf8',
        silent: true,
        path: '.boilerplate.custom',
        defaults: '.boilerplate.defaults',
        errorOnMissing: false,
        errorOnExtra: false,
        assignToProcessEnv: true,
        overrideProcessEnv: true
    }
);

// We need to check if DOCTYPE_VERSION is using an XHTML value for inline-css purposes later
var currentSetDoctype = process.env.DOCTYPE_VERSION;
if (/XHTML/i.test(currentSetDoctype)) {
    xmlMode = true;
} else {
    xmlMode = false;
}

// Clean out the build directories
gulp.task('clean', function () {
    return del(
        [
            'tmp/css/**',
            'tmp/html-samples/**',
            'dist/boilerplate/**'
        ]
    ).then(paths => {
        console.log('Cleaning directories :\n', paths.join('\n'));
    });
});

// Pre-process CSS files with config values
gulp.task('preprocess-css', function() {
    var stream = gulp.src('./app/css/*.css')
    .pipe(preprocess())
    .pipe(gulp.dest('./tmp/css/'))
    return stream;
});

// Minify processed CSS for inclusion in the email boilerplate
gulp.task('minify-css', ['preprocess-css'], function() {
    var stream = gulp.src('./tmp/css/*.css')
    .pipe(cleanCSS(
        {
            // We don't want to go too crazy when minifying, this is email after all!
            advanced: false,
            aggressiveMerging: false,
            debug: true, // Needed for the size output on before and after min files
            keepBreaks: true,
            keepSpecialComments: 0,
            shorthandCompacting: false,
            // Defensive for less friendly email clients
            compatibility: '*,' +
            '-properties.colors,' +
            '-properties.zeroUnits'
        },
        // Log original size and minified size in gulp output
        function(details) {
            console.log(details.name + ': ' + details.stats.originalSize);
            console.log(details.name + '.min' + ': ' + details.stats.minifiedSize);
        })
    )
    .pipe(rename({ extname: '.css.min' }))
    .pipe(gulp.dest('./tmp/css/'));
    return stream;
});

// Build all HTML samples, inline CSS and strip comments to be included in boilerplate
gulp.task('build-html-samples', function() {
    gulp.src('./app/html-samples/*.html')
    .pipe(preprocess())
    .pipe(inlineCSS(
        {
            applyStyleTags: true,
            removeStyleTags: true,
            removeHtmlSelectors: true,
            applyTableAttributes: true,
            xmlMode: xmlMode
        }
    ))
    .pipe(strip(
        {
            ignore: /<!--\[if(?!\s*(?:\[[^\]]+]|<!|>))(?:(?!-->).)*-->/g,
            safe: true,
            trim: true
        }
    ))
    .pipe(gulp.dest('./tmp/html-samples/'));
});

// Build email boilerplate HTML and put everything together!
gulp.task('preprocess-boilerplate', ['minify-css'], function() {
    // We only want to target this file for HTML processing, the guidelines version is static and legacy
    var stream = gulp.src('app/email-boilerplate.html.preprocess')
    .pipe(preprocess({ extension: 'html' }))
    .pipe(rename('email-boilerplate.html'))
    .pipe(gulp.dest('./dist/boilerplate/'))
    return stream;
});

// Inline CSS to main layout elements after boilerplate is generated and update it
gulp.task('inline-css', ['preprocess-boilerplate'], function() {

    var stream = gulp.src('./dist/boilerplate/email-boilerplate.html')
    .pipe(inlineCSS(
        {
            applyTableAttributes: true,
            applyWidthAttributes: true,
            applyStyleTags: false,
            applyLinkTags: true,
            removeStyleTags: false,
            removeLinkTags: true,
            xmlMode: xmlMode
        }
    ))
    .pipe(gulp.dest('./dist/boilerplate/'));
    return stream;
});

// Detect certain configurations and warn when they are less optimal
gulp.task('check-config', ['inline-css'], function() {

    var isMsoNamespacesEnabled = process.env.ENABLE_VML_NAMESPACES;
    var isXuaCompatMetaTagEnabled = process.env.ENABLE_XUA_COMPATIBLE_META_TAG;
    var xuaCompatValue = process.env.XUA_COMPATIBLE_VALUE;
    var isViewportMetaTagEnabled = process.env.ENABLE_VIEWPORT_META_TAG;
    var viewportValue = process.env.VIEWPORT_META_VALUE;
    var isFormatDetectionEnabled = process.env.ENABLE_FORMAT_DETECTION_META_TAG;
    var formatDetectionValue = process.env.FORMAT_DETECTION_META_VALUE;
    var isYahooShortcutsCSSEnabled = process.env.ENABLE_YAHOO_SHORTCUTS_CSS;
    var isMsoDpiScalingFixEnabled = process.env.ENABLE_MSO_DPI_SCALING_FIX;
    var isWebkitMediaQueryEnabled = process.env.ENABLE_WEBKIT_DETECTION_QUERY;
    var isGeckoMediaQueryEnabled = process.env.ENABLE_GECKO_MEDIA_QUERY;
    var isIEMediaQueryEnabled = process.env.ENABLE_IE_10_11_MEDIA_QUERY;
    var isGmailAndroidFixEnabled = process.env.ENABLE_GMAIL_ANDROID_RESIZE_FIX;
    var isGmailiOSFontFixEnabled = process.env.ENABLE_GMAIL_IOS_FONT_FIX;
    var isTableContainerFixedWidth = process.env.TABLE_CONTAINER_FIXED_WIDTH;

    // Small function to re-use for warnings, because lazy
    function configWarn(configMessage) {
        var label = 'CONFIG WARNING:'
        console.warn(label, configMessage)
    }

    // While they act as booleans, they aren't actually REAL booleans (quacks like a duck etc..)
    if((isMsoNamespacesEnabled === 'false') && (isMsoDpiScalingFixEnabled === 'true')) {
        configWarn('ENABLE_VML_NAMESPACES should be set to true when ENABLE_MSO_DPI_SCALING_FIX is set to true');
    }

    if(isXuaCompatMetaTagEnabled === 'false') {
        configWarn('You should strongly consider setting ENABLE_XUA_COMPATIBLE_META_TAG to true for better Windows Phone/IE compatibility');
    }

    if((isXuaCompatMetaTagEnabled === 'true') && (!/edge/i.test(xuaCompatValue))) {
        configWarn('Using any other value than IE=edge for XAU_COMPATIBLE_VALUE is not recommended');
    }

    if(isViewportMetaTagEnabled === 'false') {
        configWarn('You should strongly consider setting ENABLE_VIEWPORT_META_TAG to true for correct scaling on mobile devices');
    }

    if((isViewportMetaTagEnabled === 'true') && (/user-scalable=no/i.test(viewportValue))) {
        configWarn('You should not disable pinch zooming/resizing gestures, it is bad UX');
    }

    if((isFormatDetectionEnabled === 'true') && (/no/i.test(formatDetectionValue))) {
        configWarn('Disabling auto formatting data also disables any user interaction events i.e. tap to call');
    }

    if(isMsoDpiScalingFixEnabled === 'false') {
        configWarn('You should strongly consider setting ENABLE_MSO_DPI_SCALING_FIX to true for fixing image scaling with DPI values higher than 96');
    }

    if(isYahooShortcutsCSSEnabled === 'true') {
        configWarn('Yahoo Shortcuts is no longer a feature of the Yahoo! Mail webmail client and does not need additional CSS to override');
    }

    if(isWebkitMediaQueryEnabled === 'true') {
        configWarn('The Webkit vendor prefixes return true on some non-webkit clients, do not rely on it for accurate detection');
    }

    if(isGeckoMediaQueryEnabled === 'true') {
        configWarn('The Gecko/Mozilla media query is often mangled in Yahoo! Mail and can cause unexpected CSS issues');
    }

    if(isIEMediaQueryEnabled === 'true') {
        configWarn('The IE 10/11 media query will also return true on IEMobile (Windows Phone 8.0/8.1)');
    }

    if((isGmailAndroidFixEnabled === 'true') && (isTableContainerFixedWidth === 'false')) {
        configWarn('You should set ENABLE_GMAIL_ANDROID_RESIZE_FIX to false when not using a fixed width container table');
    }

    if((isGmailiOSFontFixEnabled === 'true') && (isTableContainerFixedWidth === 'false')) {
        configWarn('You should set ENABLE_GMAIL_IOS_FONT_FIX to false when not using a fixed width container table');
    }

    if((isGmailiOSFontFixEnabled === 'true') || (isGmailAndroidFixEnabled === 'true')) {
        configWarn('Gmail app font/image spacer hacks for iOS and Android should be deprecated due to CSS3 support, see USAGE.md for more info');
    }

    // Check for older .env file
    var fs = require('fs');
    fs.stat('.env', function(err, stat) {
        if(err == null) {
            configWarn('.env is deprecated, please rename your custom settings file to .boilerplate.custom');
        }
    });

});

// The order is important! The CSS pre-process stuff must happen first otherwise minify will break everything!
gulp.task('default',
    [
        'clean',
        'preprocess-css',
        'minify-css',
        'build-html-samples',
        'preprocess-boilerplate',
        'inline-css',
        'check-config'
    ]
);
<commit_msg>Fix IE Edge config test<commit_after>// Dependencies that makes this all work! Yay packages!
var gulp = require('gulp'),
    cleanCSS = require('gulp-clean-css'),
    del = require('del'),
    inlineCSS = require('gulp-inline-css'),
    preprocess = require('gulp-preprocess'),
    rename = require('gulp-rename'),
    strip = require('gulp-strip-comments');

// Load in environment variables from .boilerplate.defaults first and then .boilerplate.custom if it exists
var boilerplateConfig = require('dotenv-extended').load(
    {
        encoding: 'utf8',
        silent: true,
        path: '.boilerplate.custom',
        defaults: '.boilerplate.defaults',
        errorOnMissing: false,
        errorOnExtra: false,
        assignToProcessEnv: true,
        overrideProcessEnv: true
    }
);

// We need to check if DOCTYPE_VERSION is using an XHTML value for inline-css purposes later
var currentSetDoctype = process.env.DOCTYPE_VERSION;
if (/XHTML/i.test(currentSetDoctype)) {
    xmlMode = true;
} else {
    xmlMode = false;
}

// Clean out the build directories
gulp.task('clean', function () {
    return del(
        [
            'tmp/css/**',
            'tmp/html-samples/**',
            'dist/boilerplate/**'
        ]
    ).then(paths => {
        console.log('Cleaning directories :\n', paths.join('\n'));
    });
});

// Pre-process CSS files with config values
gulp.task('preprocess-css', function() {
    var stream = gulp.src('./app/css/*.css')
    .pipe(preprocess())
    .pipe(gulp.dest('./tmp/css/'))
    return stream;
});

// Minify processed CSS for inclusion in the email boilerplate
gulp.task('minify-css', ['preprocess-css'], function() {
    var stream = gulp.src('./tmp/css/*.css')
    .pipe(cleanCSS(
        {
            // We don't want to go too crazy when minifying, this is email after all!
            advanced: false,
            aggressiveMerging: false,
            debug: true, // Needed for the size output on before and after min files
            keepBreaks: true,
            keepSpecialComments: 0,
            shorthandCompacting: false,
            // Defensive for less friendly email clients
            compatibility: '*,' +
            '-properties.colors,' +
            '-properties.zeroUnits'
        },
        // Log original size and minified size in gulp output
        function(details) {
            console.log(details.name + ': ' + details.stats.originalSize);
            console.log(details.name + '.min' + ': ' + details.stats.minifiedSize);
        })
    )
    .pipe(rename({ extname: '.css.min' }))
    .pipe(gulp.dest('./tmp/css/'));
    return stream;
});

// Build all HTML samples, inline CSS and strip comments to be included in boilerplate
gulp.task('build-html-samples', function() {
    gulp.src('./app/html-samples/*.html')
    .pipe(preprocess())
    .pipe(inlineCSS(
        {
            applyStyleTags: true,
            removeStyleTags: true,
            removeHtmlSelectors: true,
            applyTableAttributes: true,
            xmlMode: xmlMode
        }
    ))
    .pipe(strip(
        {
            ignore: /<!--\[if(?!\s*(?:\[[^\]]+]|<!|>))(?:(?!-->).)*-->/g,
            safe: true,
            trim: true
        }
    ))
    .pipe(gulp.dest('./tmp/html-samples/'));
});

// Build email boilerplate HTML and put everything together!
gulp.task('preprocess-boilerplate', ['minify-css'], function() {
    // We only want to target this file for HTML processing, the guidelines version is static and legacy
    var stream = gulp.src('app/email-boilerplate.html.preprocess')
    .pipe(preprocess({ extension: 'html' }))
    .pipe(rename('email-boilerplate.html'))
    .pipe(gulp.dest('./dist/boilerplate/'))
    return stream;
});

// Inline CSS to main layout elements after boilerplate is generated and update it
gulp.task('inline-css', ['preprocess-boilerplate'], function() {

    var stream = gulp.src('./dist/boilerplate/email-boilerplate.html')
    .pipe(inlineCSS(
        {
            applyTableAttributes: true,
            applyWidthAttributes: true,
            applyStyleTags: false,
            applyLinkTags: true,
            removeStyleTags: false,
            removeLinkTags: true,
            xmlMode: xmlMode
        }
    ))
    .pipe(gulp.dest('./dist/boilerplate/'));
    return stream;
});

// Detect certain configurations and warn when they are less optimal
gulp.task('check-config', ['inline-css'], function() {

    var isMsoNamespacesEnabled = process.env.ENABLE_VML_NAMESPACES;
    var isXuaCompatMetaTagEnabled = process.env.ENABLE_XUA_COMPATIBLE_META_TAG;
    var xuaCompatValue = process.env.XUA_COMPATIBLE_VALUE;
    var isViewportMetaTagEnabled = process.env.ENABLE_VIEWPORT_META_TAG;
    var viewportValue = process.env.VIEWPORT_META_VALUE;
    var isFormatDetectionEnabled = process.env.ENABLE_FORMAT_DETECTION_META_TAG;
    var formatDetectionValue = process.env.FORMAT_DETECTION_META_VALUE;
    var isYahooShortcutsCSSEnabled = process.env.ENABLE_YAHOO_SHORTCUTS_CSS;
    var isMsoDpiScalingFixEnabled = process.env.ENABLE_MSO_DPI_SCALING_FIX;
    var isWebkitMediaQueryEnabled = process.env.ENABLE_WEBKIT_DETECTION_QUERY;
    var isGeckoMediaQueryEnabled = process.env.ENABLE_GECKO_MEDIA_QUERY;
    var isIEMediaQueryEnabled = process.env.ENABLE_IE_10_11_MEDIA_QUERY;
    var isGmailAndroidFixEnabled = process.env.ENABLE_GMAIL_ANDROID_RESIZE_FIX;
    var isGmailiOSFontFixEnabled = process.env.ENABLE_GMAIL_IOS_FONT_FIX;
    var isTableContainerFixedWidth = process.env.TABLE_CONTAINER_FIXED_WIDTH;

    // Small function to re-use for warnings, because lazy
    function configWarn(configMessage) {
        var label = 'CONFIG WARNING:'
        console.warn(label, configMessage)
    }

    // While they act as booleans, they aren't actually REAL booleans (quacks like a duck etc..)
    if((isMsoNamespacesEnabled === 'false') && (isMsoDpiScalingFixEnabled === 'true')) {
        configWarn('ENABLE_VML_NAMESPACES should be set to true when ENABLE_MSO_DPI_SCALING_FIX is set to true');
    }

    if(isXuaCompatMetaTagEnabled === 'false') {
        configWarn('You should strongly consider setting ENABLE_XUA_COMPATIBLE_META_TAG to true for better Windows Phone/IE compatibility');
    }

    if((isXuaCompatMetaTagEnabled === 'true') && (!/IE=edge/i.test(xuaCompatValue))) {
        configWarn('Using any other value than IE=edge for XAU_COMPATIBLE_VALUE is not recommended');
    }

    if(isViewportMetaTagEnabled === 'false') {
        configWarn('You should strongly consider setting ENABLE_VIEWPORT_META_TAG to true for correct scaling on mobile devices');
    }

    if((isViewportMetaTagEnabled === 'true') && (/user-scalable=no/i.test(viewportValue))) {
        configWarn('You should not disable pinch zooming/resizing gestures, it is bad UX');
    }

    if((isFormatDetectionEnabled === 'true') && (/no/i.test(formatDetectionValue))) {
        configWarn('Disabling auto formatting data also disables any user interaction events i.e. tap to call');
    }

    if(isMsoDpiScalingFixEnabled === 'false') {
        configWarn('You should strongly consider setting ENABLE_MSO_DPI_SCALING_FIX to true for fixing image scaling with DPI values higher than 96');
    }

    if(isYahooShortcutsCSSEnabled === 'true') {
        configWarn('Yahoo Shortcuts is no longer a feature of the Yahoo! Mail webmail client and does not need additional CSS to override');
    }

    if(isWebkitMediaQueryEnabled === 'true') {
        configWarn('The Webkit vendor prefixes return true on some non-webkit clients, do not rely on it for accurate detection');
    }

    if(isGeckoMediaQueryEnabled === 'true') {
        configWarn('The Gecko/Mozilla media query is often mangled in Yahoo! Mail and can cause unexpected CSS issues');
    }

    if(isIEMediaQueryEnabled === 'true') {
        configWarn('The IE 10/11 media query will also return true on IEMobile (Windows Phone 8.0/8.1)');
    }

    if((isGmailAndroidFixEnabled === 'true') && (isTableContainerFixedWidth === 'false')) {
        configWarn('You should set ENABLE_GMAIL_ANDROID_RESIZE_FIX to false when not using a fixed width container table');
    }

    if((isGmailiOSFontFixEnabled === 'true') && (isTableContainerFixedWidth === 'false')) {
        configWarn('You should set ENABLE_GMAIL_IOS_FONT_FIX to false when not using a fixed width container table');
    }

    if((isGmailiOSFontFixEnabled === 'true') || (isGmailAndroidFixEnabled === 'true')) {
        configWarn('Gmail app font/image spacer hacks for iOS and Android should be deprecated due to CSS3 support, see USAGE.md for more info');
    }

    // Check for older .env file
    var fs = require('fs');
    fs.stat('.env', function(err, stat) {
        if(err == null) {
            configWarn('.env is deprecated, please rename your custom settings file to .boilerplate.custom');
        }
    });

});

// The order is important! The CSS pre-process stuff must happen first otherwise minify will break everything!
gulp.task('default',
    [
        'clean',
        'preprocess-css',
        'minify-css',
        'build-html-samples',
        'preprocess-boilerplate',
        'inline-css',
        'check-config'
    ]
);
<|endoftext|>


<commit_before>var ApiService = require("services/ApiService");

Vue.directive("logout", function()
{
    /**
     * Logout the current user
     */
    $(this.el).click(
        function(event)
        {
            $(this.el).addClass("disabled");

            ApiService.post("/rest/io/customer/logout")
                .done(
                    function()
                    {
                        window.location.assign(window.location.origin);
                    })
                .fail(function()
                {
                    $(this.el).removeClass("disabled");
                }.bind(this));

            event.preventDefault();
        }.bind(this));
});
<commit_msg>elastic_search: - cleaning code<commit_after>var ApiService = require("services/ApiService");

Vue.directive("logout", function()
{
    /**
     * Logout the current user
     */
    $(this.el).click(
        function(event)
        {
            $(this.el).addClass("disabled");

            ApiService.post("/rest/io/customer/logout")
                .done(
                    function()
                    {
                        window.location.assign(window.location.origin);
                    })
                .fail(
                    function()
                    {
                        $(this.el).removeClass("disabled");
                    }.bind(this));

            event.preventDefault();
        }.bind(this));
});
<|endoftext|>


<commit_before>/**
 * @author humbletim / https://github.com/humbletim
 * @author TristanVALCKE / https://github.com/Itee
 */
/* global QUnit */

import { _Math as ThreeMath } from '../../../../src/math/Math';

export default QUnit.module( 'Maths', () => {

	QUnit.module( 'Math', () => {

		// PUBLIC STUFF
		QUnit.test( "generateUUID", ( assert ) => {

			var a = ThreeMath.generateUUID();
			var regex = /[A-Z0-9]{8}-[A-Z0-9]{4}-4[A-Z0-9]{3}-[A-Z0-9]{4}-[A-Z0-9]{12}/i;
			// note the fixed '4' here ----------^

			assert.ok( regex.test( a ), "Generated UUID matches the expected pattern" );

		} );

		QUnit.test( "clamp", ( assert ) => {

			assert.strictEqual( ThreeMath.clamp( 0.5, 0, 1 ), 0.5, "Value already within limits" );
			assert.strictEqual( ThreeMath.clamp( 0, 0, 1 ), 0, "Value equal to one limit" );
			assert.strictEqual( ThreeMath.clamp( - 0.1, 0, 1 ), 0, "Value too low" );
			assert.strictEqual( ThreeMath.clamp( 1.1, 0, 1 ), 1, "Value too high" );

		} );

		QUnit.test( "euclideanModulo", ( assert ) => {

			assert.ok( isNaN( ThreeMath.euclideanModulo( 6, 0 ) ), "Division by zero returns NaN" );
			assert.strictEqual( ThreeMath.euclideanModulo( 6, 1 ), 0, "Divison by trivial divisor" );
			assert.strictEqual( ThreeMath.euclideanModulo( 6, 2 ), 0, "Divison by non-trivial divisor" );
			assert.strictEqual( ThreeMath.euclideanModulo( 6, 5 ), 1, "Divison by itself - 1" );
			assert.strictEqual( ThreeMath.euclideanModulo( 6, 6 ), 0, "Divison by itself" );
			assert.strictEqual( ThreeMath.euclideanModulo( 6, 7 ), 6, "Divison by itself + 1" );

		} );

		QUnit.test( "mapLinear", ( assert ) => {

			assert.strictEqual( ThreeMath.mapLinear( 0.5, 0, 1, 0, 10 ), 5, "Value within range" );
			assert.strictEqual( ThreeMath.mapLinear( 0.0, 0, 1, 0, 10 ), 0, "Value equal to lower boundary" );
			assert.strictEqual( ThreeMath.mapLinear( 1.0, 0, 1, 0, 10 ), 10, "Value equal to upper boundary" );

		} );

		QUnit.test( "lerp", ( assert ) => {

			assert.strictEqual(ThreeMath.lerp(1, 2, 0), 1, "Value equal to lower boundary");
			assert.strictEqual(ThreeMath.lerp(1, 2, 1), 2, "Value equal to upper boundary");
			assert.strictEqual(ThreeMath.lerp(1, 2, 0.4), 1.4, "Value within range");

		} );

		QUnit.test( "smoothstep", ( assert ) => {

			assert.strictEqual( ThreeMath.smoothstep( - 1, 0, 2 ), 0, "Value lower than minimum" );
			assert.strictEqual( ThreeMath.smoothstep( 0, 0, 2 ), 0, "Value equal to minimum" );
			assert.strictEqual( ThreeMath.smoothstep( 0.5, 0, 2 ), 0.15625, "Value within limits" );
			assert.strictEqual( ThreeMath.smoothstep( 1, 0, 2 ), 0.5, "Value within limits" );
			assert.strictEqual( ThreeMath.smoothstep( 1.5, 0, 2 ), 0.84375, "Value within limits" );
			assert.strictEqual( ThreeMath.smoothstep( 2, 0, 2 ), 1, "Value equal to maximum" );
			assert.strictEqual( ThreeMath.smoothstep( 3, 0, 2 ), 1, "Value highter than maximum" );

		} );

		QUnit.test( "smootherstep", ( assert ) => {

			assert.strictEqual(ThreeMath.smootherstep(- 1, 0, 2), 0, "Value lower than minimum");
			assert.strictEqual(ThreeMath.smootherstep(0, 0, 2), 0, "Value equal to minimum");
			assert.strictEqual(ThreeMath.smootherstep(0.5, 0, 2), 0.103515625, "Value within limits");
			assert.strictEqual(ThreeMath.smootherstep(1, 0, 2), 0.5, "Value within limits");
			assert.strictEqual(ThreeMath.smootherstep(1.5, 0, 2), 0.896484375, "Value within limits");
			assert.strictEqual(ThreeMath.smootherstep(2, 0, 2), 1, "Value equal to maximum");
			assert.strictEqual(ThreeMath.smootherstep(3, 0, 2), 1, "Value highter than maximum");

		} );

		QUnit.test( "randInt", ( assert ) => {

			var low = 1, high = 3;
			var a = ThreeMath.randInt( low, high );

			assert.ok( a >= low, "Value equal to or higher than lower limit" );
			assert.ok( a <= high, "Value equal to or lower than upper limit" );

		} );

		QUnit.test( "randFloat", ( assert ) => {

			var low = 1, high = 3;
			var a = ThreeMath.randFloat( low, high );

			assert.ok( a >= low, "Value equal to or higher than lower limit" );
			assert.ok( a <= high, "Value equal to or lower than upper limit" );

		} );

		QUnit.test( "randFloatSpread", ( assert ) => {

			var a = ThreeMath.randFloatSpread( 3 );

			assert.ok( a > - 3 / 2, "Value higher than lower limit" );
			assert.ok( a < 3 / 2, "Value lower than upper limit" );

		} );

		QUnit.test( "degToRad", ( assert ) => {

			assert.strictEqual( ThreeMath.degToRad( 0 ), 0, "0 degrees" );
			assert.strictEqual( ThreeMath.degToRad( 90 ), Math.PI / 2, "90 degrees" );
			assert.strictEqual( ThreeMath.degToRad( 180 ), Math.PI, "180 degrees" );
			assert.strictEqual( ThreeMath.degToRad( 360 ), Math.PI * 2, "360 degrees" );

		} );

		QUnit.test( "radToDeg", ( assert ) => {

			assert.strictEqual( ThreeMath.radToDeg( 0 ), 0, "0 radians" );
			assert.strictEqual( ThreeMath.radToDeg( Math.PI / 2 ), 90, "Math.PI / 2 radians" );
			assert.strictEqual( ThreeMath.radToDeg( Math.PI ), 180, "Math.PI radians" );
			assert.strictEqual( ThreeMath.radToDeg( Math.PI * 2 ), 360, "Math.PI * 2 radians" );

		} );

		QUnit.test( "isPowerOfTwo", ( assert ) => {

			assert.strictEqual( ThreeMath.isPowerOfTwo( 0 ), false, "0 is not a PoT" );
			assert.strictEqual( ThreeMath.isPowerOfTwo( 1 ), true, "1 is a PoT" );
			assert.strictEqual( ThreeMath.isPowerOfTwo( 2 ), true, "2 is a PoT" );
			assert.strictEqual( ThreeMath.isPowerOfTwo( 3 ), false, "3 is not a PoT" );
			assert.strictEqual( ThreeMath.isPowerOfTwo( 4 ), true, "4 is a PoT" );

		} );

		QUnit.test( "ceilPowerOfTwo", ( assert ) => {

			assert.strictEqual( ThreeMath.ceilPowerOfTwo( 1 ), 1, "Closest higher PoT to 1 is 1" );
			assert.strictEqual( ThreeMath.ceilPowerOfTwo( 3 ), 4, "Closest higher PoT to 3 is 4" );
			assert.strictEqual( ThreeMath.ceilPowerOfTwo( 4 ), 4, "Closest higher PoT to 4 is 4" );

		} );

		QUnit.test( "floorPowerOfTwo", ( assert ) => {

			assert.strictEqual( ThreeMath.floorPowerOfTwo( 1 ), 1, "Closest lower PoT to 1 is 1" );
			assert.strictEqual( ThreeMath.floorPowerOfTwo( 3 ), 2, "Closest lower PoT to 3 is 2" );
			assert.strictEqual( ThreeMath.floorPowerOfTwo( 4 ), 4, "Closest lower PoT to 4 is 4" );

		} );

	} );

} );
<commit_msg>lint the code<commit_after>/**
 * @author humbletim / https://github.com/humbletim
 * @author TristanVALCKE / https://github.com/Itee
 */
/* global QUnit */

import { _Math as ThreeMath } from '../../../../src/math/Math';

export default QUnit.module( 'Maths', () => {

	QUnit.module( 'Math', () => {

		// PUBLIC STUFF
		QUnit.test( "generateUUID", ( assert ) => {

			var a = ThreeMath.generateUUID();
			var regex = /[A-Z0-9]{8}-[A-Z0-9]{4}-4[A-Z0-9]{3}-[A-Z0-9]{4}-[A-Z0-9]{12}/i;
			// note the fixed '4' here ----------^

			assert.ok( regex.test( a ), "Generated UUID matches the expected pattern" );

		} );

		QUnit.test( "clamp", ( assert ) => {

			assert.strictEqual( ThreeMath.clamp( 0.5, 0, 1 ), 0.5, "Value already within limits" );
			assert.strictEqual( ThreeMath.clamp( 0, 0, 1 ), 0, "Value equal to one limit" );
			assert.strictEqual( ThreeMath.clamp( - 0.1, 0, 1 ), 0, "Value too low" );
			assert.strictEqual( ThreeMath.clamp( 1.1, 0, 1 ), 1, "Value too high" );

		} );

		QUnit.test( "euclideanModulo", ( assert ) => {

			assert.ok( isNaN( ThreeMath.euclideanModulo( 6, 0 ) ), "Division by zero returns NaN" );
			assert.strictEqual( ThreeMath.euclideanModulo( 6, 1 ), 0, "Divison by trivial divisor" );
			assert.strictEqual( ThreeMath.euclideanModulo( 6, 2 ), 0, "Divison by non-trivial divisor" );
			assert.strictEqual( ThreeMath.euclideanModulo( 6, 5 ), 1, "Divison by itself - 1" );
			assert.strictEqual( ThreeMath.euclideanModulo( 6, 6 ), 0, "Divison by itself" );
			assert.strictEqual( ThreeMath.euclideanModulo( 6, 7 ), 6, "Divison by itself + 1" );

		} );

		QUnit.test( "mapLinear", ( assert ) => {

			assert.strictEqual( ThreeMath.mapLinear( 0.5, 0, 1, 0, 10 ), 5, "Value within range" );
			assert.strictEqual( ThreeMath.mapLinear( 0.0, 0, 1, 0, 10 ), 0, "Value equal to lower boundary" );
			assert.strictEqual( ThreeMath.mapLinear( 1.0, 0, 1, 0, 10 ), 10, "Value equal to upper boundary" );

		} );

		QUnit.test( "lerp", ( assert ) => {

			assert.strictEqual( ThreeMath.lerp( 1, 2, 0 ), 1, "Value equal to lower boundary" );
			assert.strictEqual( ThreeMath.lerp( 1, 2, 1 ), 2, "Value equal to upper boundary" );
			assert.strictEqual( ThreeMath.lerp( 1, 2, 0.4 ), 1.4, "Value within range" );

		} );

		QUnit.test( "smoothstep", ( assert ) => {

			assert.strictEqual( ThreeMath.smoothstep( - 1, 0, 2 ), 0, "Value lower than minimum" );
			assert.strictEqual( ThreeMath.smoothstep( 0, 0, 2 ), 0, "Value equal to minimum" );
			assert.strictEqual( ThreeMath.smoothstep( 0.5, 0, 2 ), 0.15625, "Value within limits" );
			assert.strictEqual( ThreeMath.smoothstep( 1, 0, 2 ), 0.5, "Value within limits" );
			assert.strictEqual( ThreeMath.smoothstep( 1.5, 0, 2 ), 0.84375, "Value within limits" );
			assert.strictEqual( ThreeMath.smoothstep( 2, 0, 2 ), 1, "Value equal to maximum" );
			assert.strictEqual( ThreeMath.smoothstep( 3, 0, 2 ), 1, "Value highter than maximum" );

		} );

		QUnit.test( "smootherstep", ( assert ) => {

			assert.strictEqual( ThreeMath.smootherstep( - 1, 0, 2 ), 0, "Value lower than minimum" );
			assert.strictEqual( ThreeMath.smootherstep( 0, 0, 2 ), 0, "Value equal to minimum" );
			assert.strictEqual( ThreeMath.smootherstep( 0.5, 0, 2 ), 0.103515625, "Value within limits" );
			assert.strictEqual( ThreeMath.smootherstep( 1, 0, 2 ), 0.5, "Value within limits" );
			assert.strictEqual( ThreeMath.smootherstep( 1.5, 0, 2 ), 0.896484375, "Value within limits" );
			assert.strictEqual( ThreeMath.smootherstep( 2, 0, 2 ), 1, "Value equal to maximum" );
			assert.strictEqual( ThreeMath.smootherstep( 3, 0, 2 ), 1, "Value highter than maximum" );

		} );

		QUnit.test( "randInt", ( assert ) => {

			var low = 1, high = 3;
			var a = ThreeMath.randInt( low, high );

			assert.ok( a >= low, "Value equal to or higher than lower limit" );
			assert.ok( a <= high, "Value equal to or lower than upper limit" );

		} );

		QUnit.test( "randFloat", ( assert ) => {

			var low = 1, high = 3;
			var a = ThreeMath.randFloat( low, high );

			assert.ok( a >= low, "Value equal to or higher than lower limit" );
			assert.ok( a <= high, "Value equal to or lower than upper limit" );

		} );

		QUnit.test( "randFloatSpread", ( assert ) => {

			var a = ThreeMath.randFloatSpread( 3 );

			assert.ok( a > - 3 / 2, "Value higher than lower limit" );
			assert.ok( a < 3 / 2, "Value lower than upper limit" );

		} );

		QUnit.test( "degToRad", ( assert ) => {

			assert.strictEqual( ThreeMath.degToRad( 0 ), 0, "0 degrees" );
			assert.strictEqual( ThreeMath.degToRad( 90 ), Math.PI / 2, "90 degrees" );
			assert.strictEqual( ThreeMath.degToRad( 180 ), Math.PI, "180 degrees" );
			assert.strictEqual( ThreeMath.degToRad( 360 ), Math.PI * 2, "360 degrees" );

		} );

		QUnit.test( "radToDeg", ( assert ) => {

			assert.strictEqual( ThreeMath.radToDeg( 0 ), 0, "0 radians" );
			assert.strictEqual( ThreeMath.radToDeg( Math.PI / 2 ), 90, "Math.PI / 2 radians" );
			assert.strictEqual( ThreeMath.radToDeg( Math.PI ), 180, "Math.PI radians" );
			assert.strictEqual( ThreeMath.radToDeg( Math.PI * 2 ), 360, "Math.PI * 2 radians" );

		} );

		QUnit.test( "isPowerOfTwo", ( assert ) => {

			assert.strictEqual( ThreeMath.isPowerOfTwo( 0 ), false, "0 is not a PoT" );
			assert.strictEqual( ThreeMath.isPowerOfTwo( 1 ), true, "1 is a PoT" );
			assert.strictEqual( ThreeMath.isPowerOfTwo( 2 ), true, "2 is a PoT" );
			assert.strictEqual( ThreeMath.isPowerOfTwo( 3 ), false, "3 is not a PoT" );
			assert.strictEqual( ThreeMath.isPowerOfTwo( 4 ), true, "4 is a PoT" );

		} );

		QUnit.test( "ceilPowerOfTwo", ( assert ) => {

			assert.strictEqual( ThreeMath.ceilPowerOfTwo( 1 ), 1, "Closest higher PoT to 1 is 1" );
			assert.strictEqual( ThreeMath.ceilPowerOfTwo( 3 ), 4, "Closest higher PoT to 3 is 4" );
			assert.strictEqual( ThreeMath.ceilPowerOfTwo( 4 ), 4, "Closest higher PoT to 4 is 4" );

		} );

		QUnit.test( "floorPowerOfTwo", ( assert ) => {

			assert.strictEqual( ThreeMath.floorPowerOfTwo( 1 ), 1, "Closest lower PoT to 1 is 1" );
			assert.strictEqual( ThreeMath.floorPowerOfTwo( 3 ), 2, "Closest lower PoT to 3 is 2" );
			assert.strictEqual( ThreeMath.floorPowerOfTwo( 4 ), 4, "Closest lower PoT to 4 is 4" );

		} );

	} );

} );
<|endoftext|>


<commit_before>var data        = require('data'),
    eventData   = data.get('eventData');

exports.add = function (label, items, onClick, navigationWindow, backgroundColor, openerWindow) {

    function init(label, items, onClick, navigationWindow, openerWindow) {
        createWindow(
            label,
            backgroundColor,
            createListView(items, onClick, navigationWindow),
            openerWindow
        );
    }

    function addCalendar(label, items, onClick, navigationWindow) {
        var window = createWindow(
            label,
            backgroundColor,
            createListView(items, onClick, navigationWindow)
        );

        return window;
    }

    function addCalendarTime(label, items, onClick, navigationWindow) {
        items = addTimeLabels(items);

        return createWindow(
            label,
            backgroundColor,
            createMultipleTitleListView(items, onClick, navigationWindow)
        );
    }

    function createWindow(title, backgroundColor, viewChildren, localOpenerWindow) {
        var window = null;

        if (localOpenerWindow) {
            window = localOpenerWindow;

            window.setBackgroundColor(backgroundColor);
            window.setTitle(title);
        } else {
            window = Titanium.UI.createWindow({
                backgroundColor: backgroundColor,
                title: title
            });
        }

        var view = Titanium.UI.createView({
           layout: 'vertical',
           backgroundColor: backgroundColor,
           width: '100%',
           height: Ti.UI.FILL
        });

        view.add(viewChildren);

        window.add(view);

        return window;
    }

    function createListView(items, onClick, navigationWindow)
    {
        var isFinalList = false;

        var sectionParameters = {};

        if (items.headerTitle) {
            sectionParameters = { headerTitle: items.headerTitle};
        } else {
            isFinalList = true;
        }

        var listView = Ti.UI.createListView({
            backgroundColor: eventData.styles.button_background
        });
        var sections = [];

        var section = Ti.UI.createListSection(sectionParameters);
        var dataSet = [];

        var title = '';

        var hasChildren = true;

        var itemId = null;

        for (var i in items) {
            if (i === 'headerTitle') {
                continue;
            }

            if (! isNaN(parseInt(i))) {
                title = items[i].title;
            } else {
                title = i;
            }

            if (typeof items[i][0] != 'undefined'){
                hasChildren = false;
            }

            if (typeof items[i].id != 'undefined') {
                itemId = items[i].id;
            } else {
                itemId = i;
            }

            dataSet.push({
                properties: {
                    title: title,
                    id: itemId,
                    color: eventData.styles.button_foreground,
                    backgroundColor: eventData.styles.button_background
                }
            });
        }

        section.setItems(dataSet);
        sections.push(section);

        listView.setSections(sections);

        if (isFinalList) {
            listView.addEventListener('itemclick', function (e) {
                var item = section.getItemAt(e.itemIndex);

                var id      = item.properties.id;
                var title   = item.properties.title;

                onClick(id, title);
            });
        }
        else if (hasChildren) {
            listView.addEventListener('itemclick', function (e) {
                var item = section.getItemAt(e.itemIndex);

                var id      = item.properties.id;
                var title   = item.properties.title;

                var subWindow = addCalendar(title, items[id], onClick, navigationWindow);

                if (navigationWindow == null) {
                    subWindow.open({
                        modal: true
                    });
                } else {
                    navigationWindow.openWindow(subWindow, {animated:true});
                }
            });
        } else {
            listView.addEventListener('itemclick', function (e) {
                var item = section.getItemAt(e.itemIndex);

                var id      = item.properties.id;
                var title   = item.properties.title;

                var subWindow = addCalendarTime(title, items[id], onClick, navigationWindow);

                if (navigationWindow == null) {
                    subWindow.open({
                        modal: true
                    });
                } else {
                    navigationWindow.openWindow(subWindow, {animated:true});
                }
            });
        }

        return listView;
    }

    function createMultipleTitleListView(items, onClick, navigationWindow)
    {
        var listView = Ti.UI.createListView({
            backgroundColor: eventData.styles.button_background
        });

        var sections = [];

        var section = null;
        var dataSet = [];

        for (var title in items) {
            section = Ti.UI.createListSection({ headerTitle: title });

            for (var i in items[title]) {
                dataSet.push({
                    properties: {
                        title: items[title][i].title,
                        id: items[title][i].id,
                        color: eventData.styles.button_foreground,
                        backgroundColor: eventData.styles.button_background
                    }
                });
            }

            section.setItems(dataSet);
            sections.push(section);
        }

        listView.setSections(sections);

        listView.addEventListener('itemclick', function (e) {
            var item = section.getItemAt(e.itemIndex);

            var id      = item.properties.id;
            var title   = item.properties.title;

            onClick(id, title);
        });

        return listView;
    }

    function addTimeLabels(items) {
        var timeItems = {},
            timelabel = null,
            item = null;

        for(var i in items) {
            timeLabel = items[i].endTime ? items[i].startTime + ' - ' + items[i].endTime : items[i].startTime;

            if (typeof timeItems[timeLabel] == 'undefined') {
                timeItems[timeLabel] = [];
            }

            timeItems[timeLabel].push(items[i]);
        }

        return timeItems;
    }

    return init(label, items, onClick, navigationWindow, openerWindow);
};
<commit_msg>Debug list navigation. DataSet wasn't being cleared.<commit_after>var data        = require('data'),
    eventData   = data.get('eventData');

exports.add = function (label, items, onClick, navigationWindow, backgroundColor, openerWindow) {

    function init(label, items, onClick, navigationWindow, openerWindow) {
        createWindow(
            label,
            backgroundColor,
            createListView(items, onClick, navigationWindow),
            openerWindow
        );
    }

    function addCalendar(label, items, onClick, navigationWindow) {
        var window = createWindow(
            label,
            backgroundColor,
            createListView(items, onClick, navigationWindow)
        );

        return window;
    }

    function addCalendarTime(label, items, onClick, navigationWindow) {
        items = addTimeLabels(items);

        return createWindow(
            label,
            backgroundColor,
            createMultipleTitleListView(items, onClick, navigationWindow)
        );
    }

    function createWindow(title, backgroundColor, viewChildren, localOpenerWindow) {
        var window = null;

        if (localOpenerWindow) {
            window = localOpenerWindow;

            window.setBackgroundColor(backgroundColor);
            window.setTitle(title);
        } else {
            window = Titanium.UI.createWindow({
                backgroundColor: backgroundColor,
                title: title
            });
        }

        var view = Titanium.UI.createView({
           layout: 'vertical',
           backgroundColor: backgroundColor,
           width: '100%',
           height: Ti.UI.FILL
        });

        view.add(viewChildren);

        window.add(view);

        return window;
    }

    function createListView(items, onClick, navigationWindow)
    {
        var isFinalList = false;

        var sectionParameters = {};

        if (items.headerTitle) {
            sectionParameters = { headerTitle: items.headerTitle};
        } else {
            isFinalList = true;
        }

        var listView = Ti.UI.createListView({
            backgroundColor: eventData.styles.button_background,
            font: {
                fontSize: 15
            }
        });
        var sections = [];

        var section = Ti.UI.createListSection(sectionParameters);
        var dataSet = [];

        var title = '';

        var hasChildren = true;

        var itemId = null;

        for (var i in items) {
            if (i === 'headerTitle') {
                continue;
            }

            if (! isNaN(parseInt(i))) {
                title = items[i].title;
            } else {
                title = i;
            }

            if (typeof items[i][0] != 'undefined'){
                hasChildren = false;
            }

            if (typeof items[i].id != 'undefined') {
                itemId = items[i].id;
            } else {
                itemId = i;
            }

            dataSet.push({
                properties: {
                    title: title,
                    id: itemId,
                    color: eventData.styles.button_foreground,
                    backgroundColor: eventData.styles.button_background,
                    font: {
                        fontSize: 15
                    }
                }
            });
        }

        section.setItems(dataSet);
        sections.push(section);

        listView.setSections(sections);

        if (isFinalList) {
            listView.addEventListener('itemclick', function (e) {
                var item = section.getItemAt(e.itemIndex);

                var id      = item.properties.id;
                var title   = item.properties.title;

                onClick(id, title);
            });
        }
        else if (hasChildren) {
            listView.addEventListener('itemclick', function (e) {
                var item = section.getItemAt(e.itemIndex);

                var id      = item.properties.id;
                var title   = item.properties.title;

                var subWindow = addCalendar(title, items[id], onClick, navigationWindow);

                if (navigationWindow == null) {
                    subWindow.open({
                        modal: true
                    });
                } else {
                    navigationWindow.openWindow(subWindow, {animated:true});
                }
            });
        } else {
            listView.addEventListener('itemclick', function (e) {
                var item = section.getItemAt(e.itemIndex);

                var id      = item.properties.id;
                var title   = item.properties.title;

                var subWindow = addCalendarTime(title, items[id], onClick, navigationWindow);

                if (navigationWindow == null) {
                    subWindow.open({
                        modal: true
                    });
                } else {
                    navigationWindow.openWindow(subWindow, {animated:true});
                }
            });
        }

        return listView;
    }

    function createMultipleTitleListView(items, onClick, navigationWindow)
    {
        var listView = Ti.UI.createListView({
            backgroundColor: eventData.styles.button_background
        });

        var sections = [];

        var section = null;
        var dataSet;

        for (var title in items) {
            section = Ti.UI.createListSection({ headerTitle: title });

            dataSet = [];

            for (var i in items[title]) {
                dataSet.push({
                    properties: {
                        title: items[title][i].title,
                        id: items[title][i].id,
                        color: eventData.styles.button_foreground,
                        backgroundColor: eventData.styles.button_background
                    }
                });
            }

            section.setItems(dataSet);
            sections.push(section);
        }

        listView.setSections(sections);

        listView.addEventListener('itemclick', function (e) {
            var item = section.getItemAt(e.itemIndex);

            var id      = item.properties.id;
            var title   = item.properties.title;

            onClick(id, title);
        });

        return listView;
    }

    function addTimeLabels(items) {
        var timeItems = {},
            timelabel = null,
            item = null;

        for(var i in items) {
            timeLabel = items[i].endTime ? items[i].startTime + ' - ' + items[i].endTime : items[i].startTime;

            if (typeof timeItems[timeLabel] == 'undefined') {
                timeItems[timeLabel] = [];
            }

            timeItems[timeLabel].push(items[i]);
        }

        console.log(timeItems);

        return timeItems;
    }

    return init(label, items, onClick, navigationWindow, openerWindow);
};
<|endoftext|>


<commit_before>const crypto = require('crypto');
const formatString = require('util').format;
const fs = require('fs');
const http = require('http');
const jws = require('jws');
const mime = require('mime');
const request = require('request');
const url = require('url');
const utils = require('./modelUtils');

function makeUrl (endpoint, path, query) {
  var uri = url.resolve(endpoint, path);
  if (query) {
    uri = url.parse(uri, true);
    uri.query = Object.keys(query).reduce(function (q, key) {
      return (q[key] = query[key], q);
    }, uri.query || {});
    delete uri.search;
    uri = url.format(uri);
  }
  return uri;
}

function errorNameFromStatusCode (code) {
  var status = http.STATUS_CODES[parseInt(code, 10)];

  if (!status)
    return null;

  var name = status.split(/\s+/).reduce(function(name, part) {
    name += part.charAt(0).toUpperCase() + part.slice(1).toLowerCase();
    return name;
  }, '').replace(/\W+/g, '');

  if (!/Error$/.test(name))
    name += 'Error';

  return name;
}

function fixError (res, body) {
  var errName = body.code || (body.error ? body.error.code : '');
  var errMsg = body.message || (body.error ? body.error.message : '') || '';

  if (errName) {
    if (!/Error$/.test(errName))
      errName += 'Error';
  } else {
    errName = errorNameFromStatusCode(res.statusCode) || 'Http' + res.statusCode + 'Error';
  }

  var err = new Error(errMsg);
  Object.defineProperties(err, {
    code: {value: res.statusCode},
    name: {value: errName},
    details: {value: body.details}
  });

  return err;
}

function encodeDataItem (key, value) {
  if (key === 'image' && /^[\/\.]/.test(value)) {
    value = {
      path: value,
      type: mime.lookup(value)
    };
  }

  if (value && value.type && (value.path || value.data)) {
    var data = (value.data || fs.readFileSync(value.path)).toString('base64');
    value = formatString('data:%s;base64,%s', value.type, data);
  }

  return value;
}

function signRequest (req, auth) {
  if (typeof auth === 'string')
    auth = {secret: auth};

  var key = auth.key || 'master';
  var secret = auth.secret;

  var data = {
    header: {typ: 'JWT', alg: 'HS256'},
    payload: {
      key: key,
      exp: Date.now() + (1000 * 60),
      method: req.method.toUpperCase(),
      path: url.parse(req.url).path
    },
    secret: secret
  };

  if (req.body) {
    data.payload.body = {
      alg: 'SHA256',
      hash: crypto.createHash('SHA256').update(req.body).digest('hex')
    }
  }

  req.headers['Authorization'] = 'JWT token="' + jws.sign(data) + '"';

  return req;
}

function Remote (endpoint, auth) {
  if (!(this instanceof Remote))
    return new Remote(endpoint, auth);

  function makeCall (method, meta, cb) {
    if (typeof meta === 'string')
      meta = {path: meta};

    var filter = meta.filter;
    var defaultValue = meta.default;
    var generator = meta.generator;

    var config = {
      url: makeUrl(endpoint, meta.path, meta.query),
      method: method,
      headers: {
        'User-Agent': 'BadgeKit API Client',
        'Content-Type': 'application/json',
        'Accept': 'application/json'
      }
    };

    if (meta.data) {
      config.body = JSON.stringify(meta.data, encodeDataItem);
    }

    var call = request(signRequest(config, meta.auth || auth), function (err, rsp, body) {
      if (typeof cb !== 'function')
        return;

      if (typeof body === 'string') {
        try {
          body = JSON.parse(body);
        } catch (e) {
          // NO-OP - leave body as is
        }
      }

      if (err) {
        if (err.name === 'Error')
          Object.defineProperty(err, 'name', {value: 'HttpError'});
        return cb(err, null);
      }

      if (rsp.statusCode >= 400) {
        cb(fixError(rsp, body), null);
      } else {
        body = generator.preformat(body);

        if (filter)
          body = (body||{})[filter];

        if (typeof body === 'undefined')
          body = defaultValue;

        if (generator)
          body = generator(body);

        cb(null, body);
      }
    });
  }

  ['get', 'head', 'post', 'put', 'delete'].forEach(function (method) {
    Object.defineProperty(this, method, {
      enumerable: true,
      value: makeCall.bind(this, method)
    });
  }.bind(this));

}

exports = module.exports = Remote;
<commit_msg>Fix for parentheses in url<commit_after>const crypto = require('crypto');
const formatString = require('util').format;
const fs = require('fs');
const http = require('http');
const jws = require('jws');
const mime = require('mime');
const request = require('request');
const url = require('url');
const utils = require('./modelUtils');

function makeUrl (endpoint, path, query) {
  var uri = url.resolve(endpoint, path);
  if (query) {
    uri = url.parse(uri, true);
    uri.query = Object.keys(query).reduce(function (q, key) {
      return (q[key] = query[key], q);
    }, uri.query || {});
    delete uri.search;
    uri = url.format(uri);
  }
  return uri.replace(/\(/g, '%28').replace(/\)/g, '%29');
}

function errorNameFromStatusCode (code) {
  var status = http.STATUS_CODES[parseInt(code, 10)];

  if (!status)
    return null;

  var name = status.split(/\s+/).reduce(function(name, part) {
    name += part.charAt(0).toUpperCase() + part.slice(1).toLowerCase();
    return name;
  }, '').replace(/\W+/g, '');

  if (!/Error$/.test(name))
    name += 'Error';

  return name;
}

function fixError (res, body) {
  var errName = body.code || (body.error ? body.error.code : '');
  var errMsg = body.message || (body.error ? body.error.message : '') || '';

  if (errName) {
    if (!/Error$/.test(errName))
      errName += 'Error';
  } else {
    errName = errorNameFromStatusCode(res.statusCode) || 'Http' + res.statusCode + 'Error';
  }

  var err = new Error(errMsg);
  Object.defineProperties(err, {
    code: {value: res.statusCode},
    name: {value: errName},
    details: {value: body.details}
  });

  return err;
}

function encodeDataItem (key, value) {
  if (key === 'image' && /^[\/\.]/.test(value)) {
    value = {
      path: value,
      type: mime.lookup(value)
    };
  }

  if (value && value.type && (value.path || value.data)) {
    var data = (value.data || fs.readFileSync(value.path)).toString('base64');
    value = formatString('data:%s;base64,%s', value.type, data);
  }

  return value;
}

function signRequest (req, auth) {
  if (typeof auth === 'string')
    auth = {secret: auth};

  var key = auth.key || 'master';
  var secret = auth.secret;

  var data = {
    header: {typ: 'JWT', alg: 'HS256'},
    payload: {
      key: key,
      exp: Date.now() + (1000 * 60),
      method: req.method.toUpperCase(),
      path: url.parse(req.url).path
    },
    secret: secret
  };

  if (req.body) {
    data.payload.body = {
      alg: 'SHA256',
      hash: crypto.createHash('SHA256').update(req.body).digest('hex')
    }
  }

  req.headers['Authorization'] = 'JWT token="' + jws.sign(data) + '"';

  return req;
}

function Remote (endpoint, auth) {
  if (!(this instanceof Remote))
    return new Remote(endpoint, auth);

  function makeCall (method, meta, cb) {
    if (typeof meta === 'string')
      meta = {path: meta};

    var filter = meta.filter;
    var defaultValue = meta.default;
    var generator = meta.generator;

    var config = {
      url: makeUrl(endpoint, meta.path, meta.query),
      method: method,
      headers: {
        'User-Agent': 'BadgeKit API Client',
        'Content-Type': 'application/json',
        'Accept': 'application/json'
      }
    };

    if (meta.data) {
      config.body = JSON.stringify(meta.data, encodeDataItem);
    }

    var call = request(signRequest(config, meta.auth || auth), function (err, rsp, body) {
      if (typeof cb !== 'function')
        return;

      if (typeof body === 'string') {
        try {
          body = JSON.parse(body);
        } catch (e) {
          // NO-OP - leave body as is
        }
      }

      if (err) {
        if (err.name === 'Error')
          Object.defineProperty(err, 'name', {value: 'HttpError'});
        return cb(err, null);
      }

      if (rsp.statusCode >= 400) {
        cb(fixError(rsp, body), null);
      } else {
        body = generator.preformat(body);

        if (filter)
          body = (body||{})[filter];

        if (typeof body === 'undefined')
          body = defaultValue;

        if (generator)
          body = generator(body);

        cb(null, body);
      }
    });
  }

  ['get', 'head', 'post', 'put', 'delete'].forEach(function (method) {
    Object.defineProperty(this, method, {
      enumerable: true,
      value: makeCall.bind(this, method)
    });
  }.bind(this));

}

exports = module.exports = Remote;
<|endoftext|>


<commit_before>var gulp        = require('gulp'),
    gutil       = require('gulp-util'),
    path        = require('path'),
    plumber     = require('gulp-plumber'),
    less        = require('gulp-less'),
    uglify      = require('gulp-uglify'),
    jshint      = require('gulp-jshint'),
    concat      = require('gulp-concat'),
    merge       = require('merge-stream'),
    handlebars  = require('gulp-handlebars'),
    wrap        = require('gulp-wrap'),
    declare     = require('gulp-declare'),
    watch       = require('gulp-watch'),
    mocha       = require('gulp-spawn-mocha'),
    options     = {reporter: 'mochawesome', timeout: 30000, slow: 1, 'no-exit': true},
    config      = require('./lib/config');

var watchFiles = [
  path.join(config.srcLessDir, '*.less'),
  path.join(config.srcJsDir, '*.js'),
  path.join('!', config.srcJsDir, 'hbsHelpers.js'),
  path.join(config.srcHbsDir, '*.mu')
];

var lintPaths =  {
  server: './.jshintrc',
  client: './client.jshintrc',
  lint: [
    './lib/*.js',
    '!./lib/templates.js'
  ],
  felint: [
    path.join(config.srcJsDir, '*.js')
  ]
};

function onWatchFileChanged(file) {
  var ext = file.path.slice(file.path.lastIndexOf('.') + 1);
  gutil.log(gutil.colors.yellow('Change detected in ' + file.path.replace(file.cwd, '')));
  if (ext === 'less') {
    return gulp.start('styles');
  }
  if (ext === 'js') {
    return gulp.start('scripts');
  }
  if (ext === 'mu') {
    return gulp.start('templates');
  }
}

// Build Tasks
gulp.task('fonts', function () {
  return gulp.src(path.join(config.bsFontsDir, '*'))
    .pipe(gulp.dest(config.buildFontsDir));
});

gulp.task('styles', function () {
  return gulp.src(path.join(config.srcLessDir, '[^_]*.less'))
    .pipe(plumber({errorHandler: gutil.log}))
    .pipe(less({
      paths: [config.srcLessDir, config.bsLessDir],
      compress: true
    }))
    .pipe(gulp.dest(config.buildCssDir));
});

gulp.task('scripts', ['lint'], function () {
  return gulp.src(config.clientJsFiles)
    .pipe(concat('mochawesome.js'))
    .pipe(uglify())
    .pipe(gulp.dest(config.buildJsDir));
});

gulp.task('templates', function () {
  var partials = gulp.src(path.join(config.srcHbsDir, '_*.mu'))
    .pipe(handlebars({
      handlebars: require('handlebars')
    }))
    .pipe(wrap('Handlebars.registerPartial(<%= processPartialName(file.relative) %>, Handlebars.template(<%= contents %>));', {}, {
      imports: {
        processPartialName: function(fileName) {
          // Strip the extension
          // Escape the output with JSON.stringify
          return JSON.stringify(path.basename(fileName, '.js'));
        }
      }
    }));

  var templates = gulp.src(path.join(config.srcHbsDir, '[^_]*.mu'))
    .pipe(handlebars())
    .pipe(wrap('Handlebars.template(<%= contents %>)'))
    .pipe(declare({
      root: 'exports',
      noRedeclare: true, // Avoid duplicate declarations
      processName: function(filePath) {
        return declare.processNameByPath(filePath.replace('src/templates/', ''));
      }
    }));

  var helpers = gulp.src(path.join(config.srcJsDir, 'hbsHelpers.js'));

  return merge(partials, templates, helpers)
    .pipe(concat('templates.js'))
    .pipe(wrap('var Handlebars = require("handlebars");\n <%= contents %>'))
    .pipe(gulp.dest(config.libDir));
});

// Linting
gulp.task('svrlint', function () {
  return gulp.src(lintPaths.lint)
    .pipe(jshint(lintPaths.server))
    .pipe(jshint.reporter('jshint-stylish'))
    .pipe(jshint.reporter('fail'));
});

gulp.task('felint', function () {
  return gulp.src(lintPaths.felint)
    .pipe(jshint(lintPaths.client))
    .pipe(jshint.reporter('jshint-stylish'))
    .pipe(jshint.reporter('fail'));
});

// Watch Tasks
gulp.task('watch', function () {
  watch(watchFiles, onWatchFileChanged);
});

// Test Tasks
gulp.task('fiveby', function () {
  return gulp.src('test/**/*.js', '!test/test.js')
    .pipe(mocha(options))
    .on('error', console.warn.bind(console));
});

gulp.task('test', function () {
  return gulp.src('test/test.js')
    .pipe(mocha(options))
    .on('error', console.warn.bind(console));
});

// Default/Combo Tasks
gulp.task('build', ['lint'], function () {
  return gulp.start('assemble');
});

gulp.task('lint', ['svrlint', 'felint']);

gulp.task('assemble', ['fonts', 'styles', 'scripts', 'templates']);

gulp.task('default', ['test']);<commit_msg>fix test sources<commit_after>var gulp        = require('gulp'),
    gutil       = require('gulp-util'),
    path        = require('path'),
    plumber     = require('gulp-plumber'),
    less        = require('gulp-less'),
    uglify      = require('gulp-uglify'),
    jshint      = require('gulp-jshint'),
    concat      = require('gulp-concat'),
    merge       = require('merge-stream'),
    handlebars  = require('gulp-handlebars'),
    wrap        = require('gulp-wrap'),
    declare     = require('gulp-declare'),
    watch       = require('gulp-watch'),
    mocha       = require('gulp-spawn-mocha'),
    options     = {reporter: 'mochawesome', timeout: 30000, slow: 1, 'no-exit': true},
    config      = require('./lib/config');

var watchFiles = [
  path.join(config.srcLessDir, '*.less'),
  path.join(config.srcJsDir, '*.js'),
  path.join('!', config.srcJsDir, 'hbsHelpers.js'),
  path.join(config.srcHbsDir, '*.mu')
];

var testPaths = {
  basic: ['./test/test.js'],
  fiveby: [
    './test/*.js',
    './test/**/*.js',
    '!./test/test.js'
  ]
}

var lintPaths =  {
  server: './.jshintrc',
  client: './client.jshintrc',
  lint: [
    './lib/*.js',
    '!./lib/templates.js'
  ],
  felint: [
    path.join(config.srcJsDir, '*.js')
  ]
};

function onWatchFileChanged(file) {
  var ext = file.path.slice(file.path.lastIndexOf('.') + 1);
  gutil.log(gutil.colors.yellow('Change detected in ' + file.path.replace(file.cwd, '')));
  if (ext === 'less') {
    return gulp.start('styles');
  }
  if (ext === 'js') {
    return gulp.start('scripts');
  }
  if (ext === 'mu') {
    return gulp.start('templates');
  }
}

// Build Tasks
gulp.task('fonts', function () {
  return gulp.src(path.join(config.bsFontsDir, '*'))
    .pipe(gulp.dest(config.buildFontsDir));
});

gulp.task('styles', function () {
  return gulp.src(path.join(config.srcLessDir, '[^_]*.less'))
    .pipe(plumber({errorHandler: gutil.log}))
    .pipe(less({
      paths: [config.srcLessDir, config.bsLessDir],
      compress: true
    }))
    .pipe(gulp.dest(config.buildCssDir));
});

gulp.task('scripts', ['lint'], function () {
  return gulp.src(config.clientJsFiles)
    .pipe(concat('mochawesome.js'))
    .pipe(uglify())
    .pipe(gulp.dest(config.buildJsDir));
});

gulp.task('templates', function () {
  var partials = gulp.src(path.join(config.srcHbsDir, '_*.mu'))
    .pipe(handlebars({
      handlebars: require('handlebars')
    }))
    .pipe(wrap('Handlebars.registerPartial(<%= processPartialName(file.relative) %>, Handlebars.template(<%= contents %>));', {}, {
      imports: {
        processPartialName: function(fileName) {
          // Strip the extension
          // Escape the output with JSON.stringify
          return JSON.stringify(path.basename(fileName, '.js'));
        }
      }
    }));

  var templates = gulp.src(path.join(config.srcHbsDir, '[^_]*.mu'))
    .pipe(handlebars())
    .pipe(wrap('Handlebars.template(<%= contents %>)'))
    .pipe(declare({
      root: 'exports',
      noRedeclare: true, // Avoid duplicate declarations
      processName: function(filePath) {
        return declare.processNameByPath(filePath.replace('src/templates/', ''));
      }
    }));

  var helpers = gulp.src(path.join(config.srcJsDir, 'hbsHelpers.js'));

  return merge(partials, templates, helpers)
    .pipe(concat('templates.js'))
    .pipe(wrap('var Handlebars = require("handlebars");\n <%= contents %>'))
    .pipe(gulp.dest(config.libDir));
});

// Linting
gulp.task('svrlint', function () {
  return gulp.src(lintPaths.lint)
    .pipe(jshint(lintPaths.server))
    .pipe(jshint.reporter('jshint-stylish'))
    .pipe(jshint.reporter('fail'));
});

gulp.task('felint', function () {
  return gulp.src(lintPaths.felint)
    .pipe(jshint(lintPaths.client))
    .pipe(jshint.reporter('jshint-stylish'))
    .pipe(jshint.reporter('fail'));
});

// Watch Tasks
gulp.task('watch', function () {
  watch(watchFiles, onWatchFileChanged);
});

// Test Tasks
gulp.task('fiveby', function () {
  return gulp.src(testPaths.fiveby)
    .pipe(mocha(options))
    .on('error', console.warn.bind(console));
});

gulp.task('test', function () {
  return gulp.src(testPaths.basic)
    .pipe(mocha(options))
    .on('error', console.warn.bind(console));
});

// Default/Combo Tasks
gulp.task('build', ['lint'], function () {
  return gulp.start('assemble');
});

gulp.task('lint', ['svrlint', 'felint']);

gulp.task('assemble', ['fonts', 'styles', 'scripts', 'templates']);

gulp.task('default', ['test']);<|endoftext|>


<commit_before>var config = require('./dag-lab-config.js'),
	endTaskMsg = config.endTaskMsg,
	fileChangedMsg = config.fileChangedMsg,
	handleError = config.handleError,
	paths;
	if (config.paths) { paths = config.paths;}

var gulp = require('gulp'),
	concat = require('gulp-concat'),
	prefix = require('gulp-autoprefixer'),
	livereload = require('gulp-livereload'),
		connect = require('connect'),
		server = connect(),
		serveStatic = require('serve-static'),
	uglify = require('gulp-uglify'),
	sass = require('gulp-ruby-sass');

gulp.task('index', function(){
	gulp.src(paths.htm)
	.pipe(concat('index.html'))
		.on('error', handleError)
	.pipe(gulp.dest(paths.html));
});

gulp.task('sass', function () {
	gulp.src(paths.sass)
	.pipe(sass({sourcemap: true}))
		.on('error', handleError)
	.pipe(prefix('last 2 versions'))
	.pipe(gulp.dest(paths.css));

	endTaskMsg();
});

gulp.task('server', function(next) {

  server.use(serveStatic('./dist/')).listen(process.env.PORT || 80, next);
});

gulp.task('uglify', function () {
	gulp.src(paths.js)
		.pipe(uglify())
			.on('error', handleError)
		.pipe(gulp.dest(paths.jsmin));
});

gulp.task('uglify-dbug', function () {
	gulp.src(paths.js)
		.pipe(uglify({beautify: true}))
			.on('error', handleError)
		.pipe(gulp.dest(paths.jsmin));
});

gulp.task('watch', ['server'], function() {
  livereload.listen();

	gulp.watch(paths.css + '/*.css').on('change', livereload.changed);

	gulp.watch(paths.htm, ['index']).on('change', function(file){
		fileChangedMsg(file);
	});

	gulp.watch(paths.html + '**/*.html').on('change', livereload.changed);

	gulp.watch(paths.sass, ['sass']).on('change', function(file){
		fileChangedMsg(file);
	});
});

gulp.task('default', ['server', 'watch']);<commit_msg>fixed conflict<commit_after>var config = require('./dag-lab-config.js'),
	endTaskMsg = config.endTaskMsg,
	fileChangedMsg = config.fileChangedMsg,
	handleError = config.handleError,
	paths;
	if (config.paths) { paths = config.paths;}

var gulp = require('gulp'),
	concat = require('gulp-concat'),
	prefix = require('gulp-autoprefixer'),
	livereload = require('gulp-livereload'),
		connect = require('connect'),
		server = connect(),
		serveStatic = require('serve-static'),
	uglify = require('gulp-uglify'),
	sass = require('gulp-ruby-sass');

gulp.task('index', function(){
	gulp.src(paths.htm)
	.pipe(concat('index.html'))
		.on('error', handleError)
	.pipe(gulp.dest(paths.html));
});

gulp.task('sass', function () {
	gulp.src(paths.sass)
	.pipe(sass({sourcemap: true}))
		.on('error', handleError)
	.pipe(prefix('last 2 versions'))
	.pipe(gulp.dest(paths.css));

	endTaskMsg();
});

gulp.task('server', function(next) {

  server.use(serveStatic('./dist/')).listen(process.env.PORT || 80, next);
});

gulp.task('uglify', function () {
	gulp.src(paths.js)
		.pipe(uglify())
			.on('error', handleError)
		.pipe(gulp.dest(paths.jsmin));
});

gulp.task('uglify-dbug', function () {
	gulp.src(paths.js)
		.pipe(gulp.dest(paths.jsmin));
});

gulp.task('watch', ['server'], function() {
  livereload.listen();

	gulp.watch(paths.css + '/*.css').on('change', livereload.changed);

	gulp.watch(paths.htm, ['index']).on('change', function(file){
		fileChangedMsg(file);
	});

	gulp.watch(paths.html + '**/*.html').on('change', livereload.changed);

	gulp.watch(paths.sass, ['sass']).on('change', function(file){
		fileChangedMsg(file);
	});
});

gulp.task('default', ['server', 'watch']);<|endoftext|>