<commit_before>(function () {

  /**
    Display a list of cloaked items

    @class CloakedCollectionView
    @extends Ember.CollectionView
    @namespace Ember
  **/
  Ember.CloakedCollectionView = Ember.CollectionView.extend({
    topVisible: null,
    bottomVisible: null,
    offsetFixedElement: null,

    init: function() {
      var cloakView = this.get('cloakView'),
          idProperty = this.get('idProperty'),
          uncloakDefault = !!this.get('uncloakDefault');

      // Set the slack ratio differently to allow for more or less slack in preloading
      var slackRatio = parseFloat(this.get('slackRatio'));
      if (!slackRatio) { this.set('slackRatio', 1.0); }

      this.set('itemViewClass', Ember.CloakedView.extend({
        classNames: [cloakView + '-cloak'],
        cloaks: cloakView,
        preservesContext: this.get('preservesContext') === "true",
        cloaksController: this.get('itemController'),
        defaultHeight: this.get('defaultHeight'),

        init: function() {
          this._super();

          if (idProperty) {
            this.set('elementId', cloakView + '-cloak-' + this.get('content.' + idProperty));
          }
          if (uncloakDefault) {
            this.uncloak();
          } else {
            this.cloak();
          }
        }
      }));

      this._super();
      Ember.run.next(this, 'scrolled');
    },

    /**
      If the topmost visible view changed, we will notify the controller if it has an appropriate hook.

      @method _topVisibleChanged
      @observes topVisible
    **/
    _topVisibleChanged: function() {
      var controller = this.get('controller');
      if (controller.topVisibleChanged) { controller.topVisibleChanged(this.get('topVisible')); }
    }.observes('topVisible'),

    /**
      If the bottommost visible view changed, we will notify the controller if it has an appropriate hook.

      @method _bottomVisible
      @observes bottomVisible
    **/
    _bottomVisible: function() {
      var controller = this.get('controller');
      if (controller.bottomVisibleChanged) { controller.bottomVisibleChanged(this.get('bottomVisible')); }
    }.observes('bottomVisible'),

    /**
      Binary search for finding the topmost view on screen.

      @method findTopView
      @param {Array} childViews the childViews to search through
      @param {Number} windowTop The top of the viewport to search against
      @param {Number} min The minimum index to search through of the child views
      @param {Number} max The max index to search through of the child views
      @returns {Number} the index into childViews of the topmost view
    **/
    findTopView: function(childViews, viewportTop, min, max) {
      if (max < min) { return min; }

      var mid = Math.floor((min + max) / 2),
          // in case of not full-window scrolling
          scrollOffset = this.get('wrapperTop') >> 0,
          $view = childViews[mid].$(),
          viewBottom = $view.position().top + scrollOffset + $view.height();

      if (viewBottom > viewportTop) {
        return this.findTopView(childViews, viewportTop, min, mid-1);
      } else {
        return this.findTopView(childViews, viewportTop, mid+1, max);
      }
    },

    /**
      Determine what views are onscreen and cloak/uncloak them as necessary.

      @method scrolled
    **/
    scrolled: function() {
      if (!this.get('scrollingEnabled')) { return; }

      var childViews = this.get('childViews');
      if ((!childViews) || (childViews.length === 0)) { return; }

      var toUncloak = [],
          onscreen = [],
          // calculating viewport edges
          $w = $(window),
          windowHeight = this.get('wrapperHeight') || ( window.innerHeight ? window.innerHeight : $w.height() ),
          windowTop = this.get('wrapperTop') || $w.scrollTop(),
          slack = Math.round(windowHeight * this.get('slackRatio')),
          viewportTop = windowTop - slack,
          windowBottom = windowTop + windowHeight,
          viewportBottom = windowBottom + slack,
          topView = this.findTopView(childViews, viewportTop, 0, childViews.length-1),
          bodyHeight = this.get('wrapperHeight') ? this.$().height() : $('body').height(),
          bottomView = topView,
          offsetFixedElement = this.get('offsetFixedElement');

      if (windowBottom > bodyHeight) { windowBottom = bodyHeight; }
      if (viewportBottom > bodyHeight) { viewportBottom = bodyHeight; }

      if (offsetFixedElement) {
        windowTop += (offsetFixedElement.outerHeight(true) || 0);
      }
      // Find the bottom view and what's onscreen
      while (bottomView < childViews.length) {
        var view = childViews[bottomView],
          $view = view.$(),
          // in case of not full-window scrolling
          scrollOffset = this.get('wrapperTop') >> 0,
          viewTop = $view.position().top + scrollOffset,
          viewBottom = viewTop + $view.height();

        if (viewTop > viewportBottom) { break; }
        toUncloak.push(view);

        if (viewBottom > windowTop && viewTop <= windowBottom) {
          onscreen.push(view.get('content'));
        }

        bottomView++;
      }
      if (bottomView >= childViews.length) { bottomView = childViews.length - 1; }

      // If our controller has a `sawObjects` method, pass the on screen objects to it.
      var controller = this.get('controller');
      if (onscreen.length) {
        this.setProperties({topVisible: onscreen[0], bottomVisible: onscreen[onscreen.length-1]});
        if (controller && controller.sawObjects) {
          Em.run.schedule('afterRender', function() {
            controller.sawObjects(onscreen);
          });
        }
      } else {
        this.setProperties({topVisible: null, bottomVisible: null});
      }

      var toCloak = childViews.slice(0, topView).concat(childViews.slice(bottomView+1));
      Em.run.schedule('afterRender', function() {
        toUncloak.forEach(function (v) { v.uncloak(); });
        toCloak.forEach(function (v) { v.cloak(); });
      });

      for (var j=bottomView; j<childViews.length; j++) {
        var checkView = childViews[j];
        if (!checkView._containedView) {
          if (!checkView.get('loading')) {
            checkView.$().html(this.get('loadingHTML') || "Loading...");
          }
          return;
        }
      }

    },

    scrollTriggered: function() {
      Em.run.scheduleOnce('afterRender', this, 'scrolled');
    },

    _startEvents: function() {
      var self = this,
          offsetFixed = this.get('offsetFixed'),
          onScrollMethod = function() {
            Ember.run.debounce(self, 'scrollTriggered', 10);
          };

      if (offsetFixed) {
        this.set('offsetFixedElement', $(offsetFixed));
      }

      $(document).bind('touchmove.ember-cloak', onScrollMethod);
      $(window).bind('scroll.ember-cloak', onScrollMethod);
      this.addObserver('wrapperTop', self, onScrollMethod);
      this.addObserver('wrapperHeight', self, onScrollMethod);
      this.addObserver('content.@each', self, onScrollMethod);
      this.scrollTriggered();

      this.set('scrollingEnabled', true);
    }.on('didInsertElement'),

    cleanUp: function() {
      $(document).unbind('touchmove.ember-cloak');
      $(window).unbind('scroll.ember-cloak');
      this.set('scrollingEnabled', false);
    },

    _endEvents: function() {
      this.cleanUp();
    }.on('willDestroyElement')
  });

  /**
    A cloaked view is one that removes its content when scrolled off the screen

    @class CloakedView
    @extends Ember.View
    @namespace Ember
  **/
  Ember.CloakedView = Ember.View.extend({
    attributeBindings: ['style'],

    /**
      Triggers the set up for rendering a view that is cloaked.

      @method uncloak
    */
    uncloak: function() {
      if (!this._containedView) {
        var model = this.get('content'),
            controller = null,
            container = this.get('container');

        // Wire up the itemController if necessary
        var controllerName = this.get('cloaksController');
        if (controllerName) {
          var controllerFullName = 'controller:' + controllerName,
              factory = container.lookupFactory(controllerFullName),
              parentController = this.get('controller');

          // let ember generate controller if needed
          if (factory === undefined) {
            factory = Ember.generateControllerFactory(container, controllerName, model);

            // inform developer about typo
            Ember.Logger.warn('ember-cloaking: can\'t lookup controller by name "' + controllerFullName + '".');
            Ember.Logger.warn('ember-cloaking: using ' + factory.toString() + '.');
          }

          controller = factory.create({
            model: model,
            parentController: parentController,
            target: parentController
          });
        }

        var createArgs = {},
            target = controller || model;

        if (this.get('preservesContext')) {
          createArgs.content = target;
        } else {
          createArgs.context = target;
        }
        if (controller) { createArgs.controller = controller; }
        this.setProperties({
          style: null,
          loading: false
        });

        this._containedView = this.createChildView(this.get('cloaks'), createArgs);
        this.rerender();
      }
    },

    /**
      Removes the view from the DOM and tears down all observers.

      @method cloak
    */
    cloak: function() {
      var self = this;

      if (this._containedView && (this._state || this.state) === 'inDOM') {
        var style = 'height: ' + this.$().height() + 'px;';
        this.set('style', style);
        this.$().prop('style', style);

        // We need to remove the container after the height of the element has taken
        // effect.
        Ember.run.schedule('afterRender', function() {
          if(self._containedView){
            self._containedView.remove();
            self._containedView = null;
          }
        });
      }
    },

    willDestroyElement: function(){
      if(this._containedView){
        this._containedView.remove();
        this._containedView = null;
      }
      this._super();
    },

    didInsertElement: function(){
      if (!this._containedView) {
        // setting default height
        // but do not touch if height already defined
        if(!this.$().height()){
          var defaultHeight = 100;
          if(this.get('defaultHeight')) {
            defaultHeight = this.get('defaultHeight');
          }

          this.$().css('height', defaultHeight);
        }
      }
     },

    /**
      Render the cloaked view if applicable.

      @method render
    */
    render: function(buffer) {
      var containedView = this._containedView, self = this;

      if (containedView && (containedView._state || containedView.state) !== 'inDOM') {
        containedView.triggerRecursively('willInsertElement');
        containedView.renderToBuffer(buffer);
        containedView.transitionTo('inDOM');
        Em.run.schedule('afterRender', function() {
          if(self._containedView) {
            self._containedView.triggerRecursively('didInsertElement');
          }
        });
      }
    }

  });

  Ember.Handlebars.registerHelper('cloaked-collection', function(options) {
    var hash = options.hash,
        types = options.hashTypes;

    for (var prop in hash) {
      if (types[prop] === 'ID') {
        hash[prop + 'Binding'] = hash[prop];
        delete hash[prop];
      }
    }
    return Ember.Handlebars.helpers.view.call(this, Ember.CloakedCollectionView, options);
  });

})();
<commit_msg>FEATURE: add support for `offsetFixedBottom` element<commit_after>(function () {

  /**
    Display a list of cloaked items

    @class CloakedCollectionView
    @extends Ember.CollectionView
    @namespace Ember
  **/
  Ember.CloakedCollectionView = Ember.CollectionView.extend({
    topVisible: null,
    bottomVisible: null,
    offsetFixedTopElement: null,
    offsetFixedBottomElement: null,

    init: function() {
      var cloakView = this.get('cloakView'),
          idProperty = this.get('idProperty'),
          uncloakDefault = !!this.get('uncloakDefault');

      // Set the slack ratio differently to allow for more or less slack in preloading
      var slackRatio = parseFloat(this.get('slackRatio'));
      if (!slackRatio) { this.set('slackRatio', 1.0); }

      this.set('itemViewClass', Ember.CloakedView.extend({
        classNames: [cloakView + '-cloak'],
        cloaks: cloakView,
        preservesContext: this.get('preservesContext') === "true",
        cloaksController: this.get('itemController'),
        defaultHeight: this.get('defaultHeight'),

        init: function() {
          this._super();

          if (idProperty) {
            this.set('elementId', cloakView + '-cloak-' + this.get('content.' + idProperty));
          }
          if (uncloakDefault) {
            this.uncloak();
          } else {
            this.cloak();
          }
        }
      }));

      this._super();
      Ember.run.next(this, 'scrolled');
    },

    /**
      If the topmost visible view changed, we will notify the controller if it has an appropriate hook.

      @method _topVisibleChanged
      @observes topVisible
    **/
    _topVisibleChanged: function() {
      var controller = this.get('controller');
      if (controller.topVisibleChanged) { controller.topVisibleChanged(this.get('topVisible')); }
    }.observes('topVisible'),

    /**
      If the bottommost visible view changed, we will notify the controller if it has an appropriate hook.

      @method _bottomVisible
      @observes bottomVisible
    **/
    _bottomVisible: function() {
      var controller = this.get('controller');
      if (controller.bottomVisibleChanged) { controller.bottomVisibleChanged(this.get('bottomVisible')); }
    }.observes('bottomVisible'),

    /**
      Binary search for finding the topmost view on screen.

      @method findTopView
      @param {Array} childViews the childViews to search through
      @param {Number} windowTop The top of the viewport to search against
      @param {Number} min The minimum index to search through of the child views
      @param {Number} max The max index to search through of the child views
      @returns {Number} the index into childViews of the topmost view
    **/
    findTopView: function(childViews, viewportTop, min, max) {
      if (max < min) { return min; }

      var mid = Math.floor((min + max) / 2),
          // in case of not full-window scrolling
          scrollOffset = this.get('wrapperTop') >> 0,
          $view = childViews[mid].$(),
          viewBottom = $view.position().top + scrollOffset + $view.height();

      if (viewBottom > viewportTop) {
        return this.findTopView(childViews, viewportTop, min, mid-1);
      } else {
        return this.findTopView(childViews, viewportTop, mid+1, max);
      }
    },

    /**
      Determine what views are onscreen and cloak/uncloak them as necessary.

      @method scrolled
    **/
    scrolled: function() {
      if (!this.get('scrollingEnabled')) { return; }

      var childViews = this.get('childViews');
      if ((!childViews) || (childViews.length === 0)) { return; }

      var toUncloak = [],
          onscreen = [],
          // calculating viewport edges
          $w = $(window),
          windowHeight = this.get('wrapperHeight') || ( window.innerHeight ? window.innerHeight : $w.height() ),
          windowTop = this.get('wrapperTop') || $w.scrollTop(),
          slack = Math.round(windowHeight * this.get('slackRatio')),
          viewportTop = windowTop - slack,
          windowBottom = windowTop + windowHeight,
          viewportBottom = windowBottom + slack,
          topView = this.findTopView(childViews, viewportTop, 0, childViews.length-1),
          bodyHeight = this.get('wrapperHeight') ? this.$().height() : $('body').height(),
          bottomView = topView,
          offsetFixedTopElement = this.get('offsetFixedTopElement'),
          offsetFixedBottomElement = this.get('offsetFixedBottomElement');

      if (windowBottom > bodyHeight) { windowBottom = bodyHeight; }
      if (viewportBottom > bodyHeight) { viewportBottom = bodyHeight; }

      if (offsetFixedTopElement) {
        windowTop += (offsetFixedTopElement.outerHeight(true) || 0);
      }

      if (offsetFixedBottomElement) {
        windowBottom -= (offsetFixedBottomElement.outerHeight(true) || 0);
      }

      // Find the bottom view and what's onscreen
      while (bottomView < childViews.length) {
        var view = childViews[bottomView],
          $view = view.$(),
          // in case of not full-window scrolling
          scrollOffset = this.get('wrapperTop') || 0,
          viewTop = $view.offset().top + scrollOffset,
          viewBottom = viewTop + $view.height();

        if (viewTop > viewportBottom) { break; }
        toUncloak.push(view);

        if (viewBottom > windowTop && viewTop <= windowBottom) {
          onscreen.push(view.get('content'));
        }

        bottomView++;
      }
      if (bottomView >= childViews.length) { bottomView = childViews.length - 1; }

      // If our controller has a `sawObjects` method, pass the on screen objects to it.
      var controller = this.get('controller');
      if (onscreen.length) {
        this.setProperties({topVisible: onscreen[0], bottomVisible: onscreen[onscreen.length-1]});
        if (controller && controller.sawObjects) {
          Em.run.schedule('afterRender', function() {
            controller.sawObjects(onscreen);
          });
        }
      } else {
        this.setProperties({topVisible: null, bottomVisible: null});
      }

      var toCloak = childViews.slice(0, topView).concat(childViews.slice(bottomView+1));
      Em.run.schedule('afterRender', function() {
        toUncloak.forEach(function (v) { v.uncloak(); });
        toCloak.forEach(function (v) { v.cloak(); });
      });

      for (var j=bottomView; j<childViews.length; j++) {
        var checkView = childViews[j];
        if (!checkView._containedView) {
          if (!checkView.get('loading')) {
            checkView.$().html(this.get('loadingHTML') || "Loading...");
          }
          return;
        }
      }

    },

    scrollTriggered: function() {
      Em.run.scheduleOnce('afterRender', this, 'scrolled');
    },

    _startEvents: function() {
      if (this.get('offsetFixed')) {
        Em.warn("Cloaked-collection's `offsetFixed` is deprecated. Use `offsetFixedTop` instead.");
      }

      var self = this,
          offsetFixedTop = this.get('offsetFixedTop') || this.get('offsetFixed'),
          offsetFixedBottom = this.get('offsetFixedBottom'),
          onScrollMethod = function() {
            Ember.run.debounce(self, 'scrollTriggered', 10);
          };

      if (offsetFixedTop) {
        this.set('offsetFixedTopElement', $(offsetFixedTop));
      }

      if (offsetFixedBottom) {
        this.set('offsetFixedBottomElement', $(offsetFixedBottom));
      }

      $(document).bind('touchmove.ember-cloak', onScrollMethod);
      $(window).bind('scroll.ember-cloak', onScrollMethod);
      this.addObserver('wrapperTop', self, onScrollMethod);
      this.addObserver('wrapperHeight', self, onScrollMethod);
      this.addObserver('content.@each', self, onScrollMethod);
      this.scrollTriggered();

      this.set('scrollingEnabled', true);
    }.on('didInsertElement'),

    cleanUp: function() {
      $(document).unbind('touchmove.ember-cloak');
      $(window).unbind('scroll.ember-cloak');
      this.set('scrollingEnabled', false);
    },

    _endEvents: function() {
      this.cleanUp();
    }.on('willDestroyElement')
  });

  /**
    A cloaked view is one that removes its content when scrolled off the screen

    @class CloakedView
    @extends Ember.View
    @namespace Ember
  **/
  Ember.CloakedView = Ember.View.extend({
    attributeBindings: ['style'],

    /**
      Triggers the set up for rendering a view that is cloaked.

      @method uncloak
    */
    uncloak: function() {
      if (!this._containedView) {
        var model = this.get('content'),
            controller = null,
            container = this.get('container');

        // Wire up the itemController if necessary
        var controllerName = this.get('cloaksController');
        if (controllerName) {
          var controllerFullName = 'controller:' + controllerName,
              factory = container.lookupFactory(controllerFullName),
              parentController = this.get('controller');

          // let ember generate controller if needed
          if (factory === undefined) {
            factory = Ember.generateControllerFactory(container, controllerName, model);

            // inform developer about typo
            Ember.Logger.warn('ember-cloaking: can\'t lookup controller by name "' + controllerFullName + '".');
            Ember.Logger.warn('ember-cloaking: using ' + factory.toString() + '.');
          }

          controller = factory.create({
            model: model,
            parentController: parentController,
            target: parentController
          });
        }

        var createArgs = {},
            target = controller || model;

        if (this.get('preservesContext')) {
          createArgs.content = target;
        } else {
          createArgs.context = target;
        }
        if (controller) { createArgs.controller = controller; }
        this.setProperties({
          style: null,
          loading: false
        });

        this._containedView = this.createChildView(this.get('cloaks'), createArgs);
        this.rerender();
      }
    },

    /**
      Removes the view from the DOM and tears down all observers.

      @method cloak
    */
    cloak: function() {
      var self = this;

      if (this._containedView && (this._state || this.state) === 'inDOM') {
        var style = 'height: ' + this.$().height() + 'px;';
        this.set('style', style);
        this.$().prop('style', style);

        // We need to remove the container after the height of the element has taken
        // effect.
        Ember.run.schedule('afterRender', function() {
          if(self._containedView){
            self._containedView.remove();
            self._containedView = null;
          }
        });
      }
    },

    willDestroyElement: function(){
      if(this._containedView){
        this._containedView.remove();
        this._containedView = null;
      }
      this._super();
    },

    didInsertElement: function(){
      if (!this._containedView) {
        // setting default height
        // but do not touch if height already defined
        if(!this.$().height()){
          var defaultHeight = 100;
          if(this.get('defaultHeight')) {
            defaultHeight = this.get('defaultHeight');
          }

          this.$().css('height', defaultHeight);
        }
      }
     },

    /**
      Render the cloaked view if applicable.

      @method render
    */
    render: function(buffer) {
      var containedView = this._containedView, self = this;

      if (containedView && (containedView._state || containedView.state) !== 'inDOM') {
        containedView.triggerRecursively('willInsertElement');
        containedView.renderToBuffer(buffer);
        containedView.transitionTo('inDOM');
        Em.run.schedule('afterRender', function() {
          if(self._containedView) {
            self._containedView.triggerRecursively('didInsertElement');
          }
        });
      }
    }

  });

  Ember.Handlebars.registerHelper('cloaked-collection', function(options) {
    var hash = options.hash,
        types = options.hashTypes;

    for (var prop in hash) {
      if (types[prop] === 'ID') {
        hash[prop + 'Binding'] = hash[prop];
        delete hash[prop];
      }
    }
    return Ember.Handlebars.helpers.view.call(this, Ember.CloakedCollectionView, options);
  });

})();
<|endoftext|>


<commit_before>//
// required packages
//

var fs = require('fs');

KMLFileToJSONFile('uac/uac.kml','uac/uac.json','uac','http://utahavalanchecenter.org/advisory/');
// KMLFileToJSONFile('nwac_regions.kml','test_nwac_regions.json','nwac','http://www.nwac.us/forecast/avalanche/current/zone/');
// KMLFileToJSONFile('canada_regions.kml','canada_regions.json','canada','');

function KMLFileToJSONFile(KMLFileName, JSONFileName, regionPrefix, URLPrefix) {
    var JSONString = KMLStringToJSONString(fs.readFileSync(KMLFileName, 'utf8'), regionPrefix, URLPrefix);
    if (JSONString) {
        fs.writeFileSync(JSONFileName, JSONString, 'utf8');
    }
}

function KMLStringToJSONString(KML, regionPrefix, URLPrefix) {

    var JSONString = null;

    // grab all the placemarks from the KML
    var placemarkBlocks = KML.match(/<Placemark>[\S\s]*?<\/Placemark>/g);
    if (placemarkBlocks) {

        var data = [placemarkBlocks.length];

        for (var i = 0; i < placemarkBlocks.length; i++) {
            //console.log('placemarkBlocks[' + i + ']: ' + placemarkBlocks[i]);

            // for each placemark, grab the data we need

            var nameMatch = placemarkBlocks[i].match(/<name>([\S\s]*?)<\/name>/);
            var name = (nameMatch && nameMatch.length > 1) ? nameMatch[1] : 'TBD';
            //console.log('name: ' + name);

            var oneBasedIndex = i + 1;
            data[i] = {'regionId': regionPrefix + '_' + oneBasedIndex, 'displayName': name, 'URL' : URLPrefix, 'points':[]};

            var coordinatesMatch = placemarkBlocks[i].match(/<coordinates>\s*([\S\s]*?)\s*<\/coordinates>/);
            var coordinatesList = (coordinatesMatch && coordinatesMatch.length > 1) ? coordinatesMatch[1] : '';
            //console.log('coordinatesList: ' + coordinatesList);

            var coordinates = coordinatesList.match(/\s*(\S+)\s*/g);
            if (coordinates) {
                for (var j = 0; j < coordinates.length; j++) {
                    //console.log('coordinates[' + j + ']: ' + coordinates[j]);

                    var components = coordinates[j].match(/[-+]?[0-9]*\.[0-9]*/g);
                    if (components && components.length >= 2) {
                        // NOTE latitude comes after longitude in KML ... weird
                        var lat = components[1];
                        var lon = components[0];
                        //console.log('lat: ' + lat + '; lon: ' + lon);

                        data[i].points[j] = {'lat': lat, 'lon': lon};
                    }
                }
            }
        }

        JSONString = JSON.stringify(data, null, 4);
        //console.log(JSONString);
    }

    return JSONString;
}
<commit_msg>add SAC<commit_after>//
// required packages
//

var fs = require('fs');

KMLFileToJSONFile('sac/SACForecastArea.kml','sac/sac.json','sac','http://www.sierraavalanchecenter.org/advisory');
//KMLFileToJSONFile('uac/uac.kml','uac/uac.json','uac','http://utahavalanchecenter.org/advisory/');
// KMLFileToJSONFile('nwac_regions.kml','test_nwac_regions.json','nwac','http://www.nwac.us/forecast/avalanche/current/zone/');
// KMLFileToJSONFile('canada_regions.kml','canada_regions.json','canada','');

function KMLFileToJSONFile(KMLFileName, JSONFileName, regionPrefix, URLPrefix) {
    var JSONString = KMLStringToJSONString(fs.readFileSync(KMLFileName, 'utf8'), regionPrefix, URLPrefix);
    if (JSONString) {
        fs.writeFileSync(JSONFileName, JSONString, 'utf8');
    }
}

function KMLStringToJSONString(KML, regionPrefix, URLPrefix) {

    var JSONString = null;

    // grab all the placemarks from the KML
    var placemarkBlocks = KML.match(/<Placemark>[\S\s]*?<\/Placemark>/g);
    if (placemarkBlocks) {

        var data = [placemarkBlocks.length];

        for (var i = 0; i < placemarkBlocks.length; i++) {
            //console.log('placemarkBlocks[' + i + ']: ' + placemarkBlocks[i]);

            // for each placemark, grab the data we need

            var nameMatch = placemarkBlocks[i].match(/<name>([\S\s]*?)<\/name>/);
            var name = (nameMatch && nameMatch.length > 1) ? nameMatch[1] : 'TBD';
            //console.log('name: ' + name);

            var oneBasedIndex = i + 1;
            data[i] = {'regionId': regionPrefix + '_' + oneBasedIndex, 'displayName': name, 'URL' : URLPrefix, 'points':[]};

            var coordinatesMatch = placemarkBlocks[i].match(/<coordinates>\s*([\S\s]*?)\s*<\/coordinates>/);
            var coordinatesList = (coordinatesMatch && coordinatesMatch.length > 1) ? coordinatesMatch[1] : '';
            //console.log('coordinatesList: ' + coordinatesList);

            var coordinates = coordinatesList.match(/\s*(\S+)\s*/g);
            if (coordinates) {
                for (var j = 0; j < coordinates.length; j++) {
                    //console.log('coordinates[' + j + ']: ' + coordinates[j]);

                    var components = coordinates[j].match(/[-+]?[0-9]*\.[0-9]*/g);
                    if (components && components.length >= 2) {
                        // NOTE latitude comes after longitude in KML ... weird
                        var lat = components[1];
                        var lon = components[0];
                        //console.log('lat: ' + lat + '; lon: ' + lon);

                        data[i].points[j] = {'lat': lat, 'lon': lon};
                    }
                }
            }
        }

        JSONString = JSON.stringify(data, null, 4);
        //console.log(JSONString);
    }

    return JSONString;
}
<|endoftext|>


<commit_before>'use strict';

module.exports = {
  extends: ['ash-nazg/sauron-node'],
  parserOptions: {
    sourceType: 'module'
  },
  env: {
    browser: true
  },
  settings: {
    polyfills: [
    ],
    jsdoc: {
      additionalTagNames: {
        // In case we need to extend
        customTags: []
      },
      augmentsExtendsReplacesDocs: true
      // Todo: Figure out why this is not working and why seem to have to
      //    disable for all Markdown:
      /*
      baseConfig: {
        rules: {
          'no-multi-spaces': 'off'
        }
      }
      */
    }
  },
  overrides: [
    // Locales have no need for importing outside of SVG-Edit
    {
      files: [
        'editor/locale/lang.*.js', 'editor/extensions/ext-locale/**',
        'docs/tutorials/ExtensionDocs.md'
      ],
      rules: {
        'import/no-anonymous-default-export': ['off']
      }
    },
    // These browser files don't do importing or requiring
    {
      files: [
        'editor/svgpathseg.js', 'editor/touch.js', 'editor/typedefs.js',
        'editor/redirect-on-no-module-support.js',
        'editor/extensions/imagelib/index.js',
        'editor/external/dom-polyfill/dom-polyfill.js',
        'screencasts/svgopen2010/script.js'
      ],
      rules: {
        'import/unambiguous': ['off']
      }
    },
    {
      files: ['**/*.html', 'screencasts/**'],
      globals: {
        root: 'off'
      },
      settings: {
        polyfills: [
          'document.querySelector',
          'history',
          'history.pushState',
          'history.replaceState',
          'location.hash',
          'navigator',
          'Number.parseFloat',
          'Number.parseInt',
          'Number.isNaN'
        ]
      },
      rules: {
        'import/unambiguous': 'off'
      }
    },
    {
      files: ['.eslintrc.js', '.ncurc.js', 'tools/mochawesome-cli.js'],
      extends: [
        'ash-nazg/sauron-node-script'
      ]
    },
    // Our Markdown rules (and used for JSDoc examples as well, by way of
    //   our use of `jsdoc/check-examples` within `ash-nazg`)
    {
      files: ['**/*.md'],
      settings: {
        polyfills: [
          // Tutorials
          'console',
          'location.href'
        ]
      },
      rules: {
        // Todo: Figure out why this is not enough to disable warning
        //  for examples in my environment (but it is in others')
        // Used in examples of assert-close.js plugin
        'mocha-cleanup/no-assertions-outside-it': 'off',
        'eslint-comments/no-unused-disable': 'warn',

        'eol-last': ['off'],
        'no-console': ['off'],
        'no-undef': ['off'],
        'no-unused-vars': ['warn'],
        'padded-blocks': ['off'],
        'import/unambiguous': ['off'],
        'import/no-unresolved': ['off'],
        'node/no-missing-import': ['off'],
        'no-multi-spaces': 'off',
        'sonarjs/no-all-duplicated-branches': 'off',
        'node/no-unpublished-import': ['error', {
          allowModules: ['@cypress/fiddle']
        }],
        'no-alert': 'off',
        // Disable until may fix https://github.com/gajus/eslint-plugin-jsdoc/issues/211
        indent: 'off'
      }
    },
    // Dis-apply Node rules mistakenly giving errors with browser files,
    //  and treating Node global `root` as being present for shadowing
    {
      files: ['editor/**'],
      globals: {
        root: 'off'
      },
      settings: {
        polyfills: [
          // These are the primary polyfills needed by regular users if
          //  not present, e.g., with core-js-bundle; also those under
          //  extensions
          'Array.isArray',
          'Blob',
          'console',
          'CustomEvent',
          'document.body',
          'document.createElementNS',
          'document.evaluate',
          'document.head',
          'document.importNode',
          'document.querySelector',
          'document.querySelectorAll',
          'DOMParser',
          'Error',
          'FileReader',
          'JSON',
          'KeyboardEvent',
          'location.href',
          'location.origin',
          'MouseEvent',
          'MutationObserver',
          'navigator',
          'Number.isNaN',
          'Number.parseFloat',
          'Number.parseInt',
          'Object.assign',
          'Object.defineProperty',
          'Object.defineProperties',
          'Object.entries',
          'Object.getOwnPropertyDescriptor',
          'Object.keys',
          'Object.values',
          'Promise',
          'Promise.all',
          'Set',
          'Uint8Array',
          'URL',
          'URL.createObjectURL',
          'XMLSerializer',
          'XMLHttpRequest',
          'window.getComputedStyle',
          'window.parent',
          'window.scrollX',
          'window.scrollY'
        ]
      },
      rules: {
        // Should probably add this rule to ash-nazg as facilitates tree-shaking
        'import/no-namespace': ['error'],

        'node/no-unsupported-features/node-builtins': 'off'
      }
    },
    // For extensions, `this` is generally assigned to be the more
    //   descriptive `svgEditor`; they also have no need for importing outside
    //   of SVG-Edit
    {
      files: ['editor/extensions/**'],
      settings: {
        polyfills: [
          'console',
          'fetch',
          'location.origin',
          'Number.isNaN',
          'Number.parseFloat',
          'Number.parseInt',
          'window.postMessage'
        ]
      },
      rules: {
        'consistent-this': ['error', 'svgEditor'],
        'import/no-anonymous-default-export': ['off']
      }
    },
    {
      // Node files
      files: [
        'docs/jsdoc-config.js',
        'build/build-html.js',
        'rollup.config.js', 'rollup-config.config.js'
      ],
      env: {
        node: true
      },
      settings: {
        polyfills: [
          'console',
          'Promise.resolve'
        ]
      },
      globals: {
        require: true
      },
      rules: {
        // We can't put Rollup in npmignore or user can't get access,
        //  and we have too many modules to add to `peerDependencies`
        //  so this rule can know them to be available, so we instead
        //  disable
        'node/no-unpublished-import': 'off'
      }
    },
    {
      // As consumed by jsdoc, cannot be expressed as ESM
      files: ['docs/jsdoc-config.js'],
      parserOptions: {
        sourceType: 'script'
      },
      globals: {
        module: false
      },
      rules: {
        'import/no-commonjs': 'off',
        strict: 'off'
      }
    },
    {
      // Should probably have as external, but should still check
      files: ['canvg/rgbcolor.js'],
      settings: {
        polyfills: [
          'Number.isNaN',
          'Number.parseInt',
          'Object.assign',
          'Object.keys'
        ]
      }
    },
    {
      files: ['cypress/plugins/index.js'],
      extends: [
        'ash-nazg/sauron-node-script'
      ]
    },
    {
      files: ['cypress/**'],
      extends: [
        'plugin:cypress/recommended',
        'plugin:mocha/recommended',
        'plugin:mocha-cleanup/recommended-no-limits',
        'plugin:@fintechstudios/chai-as-promised/recommended',
        'plugin:chai-expect-keywords/recommended',
        'plugin:chai-expect/recommended',
        'plugin:chai-friendly/recommended'
      ],
      env: {
        node: true
      },
      settings: {
        polyfills: [
          'console',
          'Date.now',
          'document.body',
          'document.createElementNS',
          'document.head',
          'DOMParser',
          'Number.isNaN',
          'Object.keys',
          'Object.entries',
          'Promise'
        ]
      },
      rules: {
        // These errors are caused in Cypress files if user has not
        //  yet instrumented code; need to reinvestigate why we had to
        //  instrument separately from nyc mocha
        'import/no-unresolved': 'warn',
        'node/no-missing-import': 'warn',

        'chai-expect-keywords/no-unsupported-keywords': [
          'error', {
            allowChaiDOM: true
          }
        ],
        // Would be good but seems necessary due to some bugs in Cypress
        //  in detecting visibility
        // 'cypress/no-force': 0,
        // Good but would be difficult to enforce (and data-* may not be less
        //   brittle than IDs/classes anyways)
        // 'cypress/require-data-selectors': 0,
        'cypress/assertion-before-screenshot': 2,

        // Conflicts with Cypress `should`
        'mocha-cleanup/invalid-assertions': 0,

        // Might see about working around to avoid the option limitation,
        //  but convenient
        'mocha-cleanup/no-expressions-in-assertions': ['error', {
          replacementsOnly: true
        }],

        // Too oppressive when planning to extend a section
        'mocha/no-hooks-for-single-case': 0,

        // Would be good to enable but needs some refactoring
        'mocha/no-setup-in-describe': 0,
        'mocha-cleanup/no-outside-declaration': 0,

        // Useful to ensure allowing `this.timeout()`, etc., but a
        //  little oppressive
        'mocha/no-mocha-arrows': 0,
        // Useful if enabling the regular `prefer-arrow-callback`
        // 'mocha/prefer-arrow-callback': 2

        'jsdoc/require-jsdoc': 0,
        'no-console': 0,
        'import/unambiguous': 0
      }
    }
  ],
  rules: {
    // check-examples is not picking up eslint config properly in some
    //  environments; see also discussion above
    //  `mocha-cleanup/no-assertions-outside-it`
    'jsdoc/check-examples': ['warn', {
      rejectExampleCodeRegex: '^`'
    }],

    // https://github.com/sindresorhus/eslint-plugin-unicorn/issues/453
    'unicorn/regex-shorthand': 0,
    // The Babel transform seems to have a problem converting these
    'prefer-named-capture-group': 'off',
    // Override these `ash-nazg/sauron` rules which are difficult for us
    //   to apply at this time
    'unicorn/prefer-string-slice': 'off',
    'default-case': 'off',
    'require-unicode-regexp': 'off',
    'max-len': 'off', /* , {
      ignoreUrls: true,
      ignoreRegExpLiterals: true
    } */
    'unicorn/prefer-query-selector': 'off',
    'unicorn/prefer-node-append': 'off',
    'unicorn/no-zero-fractions': 'off',
    'unicorn/prefer-number-properties': 'off',
    'jsdoc/require-file-overview': ['error', {
      tags: {
        file: {
          initialCommentsOnly: true,
          preventDuplicates: true
        },
        license: {
          initialCommentsOnly: true,
          preventDuplicates: true
        },
        copyright: {
          initialCommentsOnly: true,
          preventDuplicates: true
        },
        author: {
          initialCommentsOnly: true,
          preventDuplicates: true
        },
        module: {
          initialCommentsOnly: true,
          preventDuplicates: true
        },
        exports: {
          initialCommentsOnly: true,
          preventDuplicates: true
        }
      }
    }],

    // Disable for now
    'eslint-comments/require-description': 0
  }
};
<commit_msg>- Linting: Avoid warnings for instrumented files (currently test files depend on instrumentation step, so we don't want CI checking the paths if not created there)<commit_after>'use strict';

module.exports = {
  extends: ['ash-nazg/sauron-node'],
  parserOptions: {
    sourceType: 'module'
  },
  env: {
    browser: true
  },
  settings: {
    polyfills: [
    ],
    jsdoc: {
      additionalTagNames: {
        // In case we need to extend
        customTags: []
      },
      augmentsExtendsReplacesDocs: true
      // Todo: Figure out why this is not working and why seem to have to
      //    disable for all Markdown:
      /*
      baseConfig: {
        rules: {
          'no-multi-spaces': 'off'
        }
      }
      */
    }
  },
  overrides: [
    // Locales have no need for importing outside of SVG-Edit
    {
      files: [
        'editor/locale/lang.*.js', 'editor/extensions/ext-locale/**',
        'docs/tutorials/ExtensionDocs.md'
      ],
      rules: {
        'import/no-anonymous-default-export': ['off']
      }
    },
    // These browser files don't do importing or requiring
    {
      files: [
        'editor/svgpathseg.js', 'editor/touch.js', 'editor/typedefs.js',
        'editor/redirect-on-no-module-support.js',
        'editor/extensions/imagelib/index.js',
        'editor/external/dom-polyfill/dom-polyfill.js',
        'screencasts/svgopen2010/script.js'
      ],
      rules: {
        'import/unambiguous': ['off']
      }
    },
    {
      files: ['**/*.html', 'screencasts/**'],
      globals: {
        root: 'off'
      },
      settings: {
        polyfills: [
          'document.querySelector',
          'history',
          'history.pushState',
          'history.replaceState',
          'location.hash',
          'navigator',
          'Number.parseFloat',
          'Number.parseInt',
          'Number.isNaN'
        ]
      },
      rules: {
        'import/unambiguous': 'off'
      }
    },
    {
      files: ['.eslintrc.js', '.ncurc.js', 'tools/mochawesome-cli.js'],
      extends: [
        'ash-nazg/sauron-node-script'
      ]
    },
    // Our Markdown rules (and used for JSDoc examples as well, by way of
    //   our use of `jsdoc/check-examples` within `ash-nazg`)
    {
      files: ['**/*.md'],
      settings: {
        polyfills: [
          // Tutorials
          'console',
          'location.href'
        ]
      },
      rules: {
        // Todo: Figure out why this is not enough to disable warning
        //  for examples in my environment (but it is in others')
        // Used in examples of assert-close.js plugin
        'mocha-cleanup/no-assertions-outside-it': 'off',
        'eslint-comments/no-unused-disable': 'warn',

        'eol-last': ['off'],
        'no-console': ['off'],
        'no-undef': ['off'],
        'no-unused-vars': ['warn'],
        'padded-blocks': ['off'],
        'import/unambiguous': ['off'],
        'import/no-unresolved': ['off'],
        'node/no-missing-import': ['off'],
        'no-multi-spaces': 'off',
        'sonarjs/no-all-duplicated-branches': 'off',
        'node/no-unpublished-import': ['error', {
          allowModules: ['@cypress/fiddle']
        }],
        'no-alert': 'off',
        // Disable until may fix https://github.com/gajus/eslint-plugin-jsdoc/issues/211
        indent: 'off'
      }
    },
    // Dis-apply Node rules mistakenly giving errors with browser files,
    //  and treating Node global `root` as being present for shadowing
    {
      files: ['editor/**'],
      globals: {
        root: 'off'
      },
      settings: {
        polyfills: [
          // These are the primary polyfills needed by regular users if
          //  not present, e.g., with core-js-bundle; also those under
          //  extensions
          'Array.isArray',
          'Blob',
          'console',
          'CustomEvent',
          'document.body',
          'document.createElementNS',
          'document.evaluate',
          'document.head',
          'document.importNode',
          'document.querySelector',
          'document.querySelectorAll',
          'DOMParser',
          'Error',
          'FileReader',
          'JSON',
          'KeyboardEvent',
          'location.href',
          'location.origin',
          'MouseEvent',
          'MutationObserver',
          'navigator',
          'Number.isNaN',
          'Number.parseFloat',
          'Number.parseInt',
          'Object.assign',
          'Object.defineProperty',
          'Object.defineProperties',
          'Object.entries',
          'Object.getOwnPropertyDescriptor',
          'Object.keys',
          'Object.values',
          'Promise',
          'Promise.all',
          'Set',
          'Uint8Array',
          'URL',
          'URL.createObjectURL',
          'XMLSerializer',
          'XMLHttpRequest',
          'window.getComputedStyle',
          'window.parent',
          'window.scrollX',
          'window.scrollY'
        ]
      },
      rules: {
        // Should probably add this rule to ash-nazg as facilitates tree-shaking
        'import/no-namespace': ['error'],

        'node/no-unsupported-features/node-builtins': 'off'
      }
    },
    // For extensions, `this` is generally assigned to be the more
    //   descriptive `svgEditor`; they also have no need for importing outside
    //   of SVG-Edit
    {
      files: ['editor/extensions/**'],
      settings: {
        polyfills: [
          'console',
          'fetch',
          'location.origin',
          'Number.isNaN',
          'Number.parseFloat',
          'Number.parseInt',
          'window.postMessage'
        ]
      },
      rules: {
        'consistent-this': ['error', 'svgEditor'],
        'import/no-anonymous-default-export': ['off']
      }
    },
    {
      // Node files
      files: [
        'docs/jsdoc-config.js',
        'build/build-html.js',
        'rollup.config.js', 'rollup-config.config.js'
      ],
      env: {
        node: true
      },
      settings: {
        polyfills: [
          'console',
          'Promise.resolve'
        ]
      },
      globals: {
        require: true
      },
      rules: {
        // We can't put Rollup in npmignore or user can't get access,
        //  and we have too many modules to add to `peerDependencies`
        //  so this rule can know them to be available, so we instead
        //  disable
        'node/no-unpublished-import': 'off'
      }
    },
    {
      // As consumed by jsdoc, cannot be expressed as ESM
      files: ['docs/jsdoc-config.js'],
      parserOptions: {
        sourceType: 'script'
      },
      globals: {
        module: false
      },
      rules: {
        'import/no-commonjs': 'off',
        strict: 'off'
      }
    },
    {
      // Should probably have as external, but should still check
      files: ['canvg/rgbcolor.js'],
      settings: {
        polyfills: [
          'Number.isNaN',
          'Number.parseInt',
          'Object.assign',
          'Object.keys'
        ]
      }
    },
    {
      files: ['cypress/plugins/index.js'],
      extends: [
        'ash-nazg/sauron-node-script'
      ]
    },
    {
      files: ['cypress/**'],
      extends: [
        'plugin:cypress/recommended',
        'plugin:mocha/recommended',
        'plugin:mocha-cleanup/recommended-no-limits',
        'plugin:@fintechstudios/chai-as-promised/recommended',
        'plugin:chai-expect-keywords/recommended',
        'plugin:chai-expect/recommended',
        'plugin:chai-friendly/recommended'
      ],
      env: {
        node: true
      },
      settings: {
        polyfills: [
          'console',
          'Date.now',
          'document.body',
          'document.createElementNS',
          'document.head',
          'DOMParser',
          'Number.isNaN',
          'Object.keys',
          'Object.entries',
          'Promise'
        ]
      },
      rules: {
        // These errors are caused in Cypress files if user has not
        //  yet instrumented code; need to reinvestigate why we had to
        //  instrument separately from nyc mocha
        'import/no-unresolved': ['error', {ignore: ['/instrumented/']}],
        'node/no-missing-import': 'off',

        'chai-expect-keywords/no-unsupported-keywords': [
          'error', {
            allowChaiDOM: true
          }
        ],
        // Would be good but seems necessary due to some bugs in Cypress
        //  in detecting visibility
        // 'cypress/no-force': 0,
        // Good but would be difficult to enforce (and data-* may not be less
        //   brittle than IDs/classes anyways)
        // 'cypress/require-data-selectors': 0,
        'cypress/assertion-before-screenshot': 2,

        // Conflicts with Cypress `should`
        'mocha-cleanup/invalid-assertions': 0,

        // Might see about working around to avoid the option limitation,
        //  but convenient
        'mocha-cleanup/no-expressions-in-assertions': ['error', {
          replacementsOnly: true
        }],

        // Too oppressive when planning to extend a section
        'mocha/no-hooks-for-single-case': 0,

        // Would be good to enable but needs some refactoring
        'mocha/no-setup-in-describe': 0,
        'mocha-cleanup/no-outside-declaration': 0,

        // Useful to ensure allowing `this.timeout()`, etc., but a
        //  little oppressive
        'mocha/no-mocha-arrows': 0,
        // Useful if enabling the regular `prefer-arrow-callback`
        // 'mocha/prefer-arrow-callback': 2

        'jsdoc/require-jsdoc': 0,
        'no-console': 0,
        'import/unambiguous': 0
      }
    }
  ],
  rules: {
    // check-examples is not picking up eslint config properly in some
    //  environments; see also discussion above
    //  `mocha-cleanup/no-assertions-outside-it`
    'jsdoc/check-examples': ['warn', {
      rejectExampleCodeRegex: '^`'
    }],

    // https://github.com/sindresorhus/eslint-plugin-unicorn/issues/453
    'unicorn/regex-shorthand': 0,
    // The Babel transform seems to have a problem converting these
    'prefer-named-capture-group': 'off',
    // Override these `ash-nazg/sauron` rules which are difficult for us
    //   to apply at this time
    'unicorn/prefer-string-slice': 'off',
    'default-case': 'off',
    'require-unicode-regexp': 'off',
    'max-len': 'off', /* , {
      ignoreUrls: true,
      ignoreRegExpLiterals: true
    } */
    'unicorn/prefer-query-selector': 'off',
    'unicorn/prefer-node-append': 'off',
    'unicorn/no-zero-fractions': 'off',
    'unicorn/prefer-number-properties': 'off',
    'jsdoc/require-file-overview': ['error', {
      tags: {
        file: {
          initialCommentsOnly: true,
          preventDuplicates: true
        },
        license: {
          initialCommentsOnly: true,
          preventDuplicates: true
        },
        copyright: {
          initialCommentsOnly: true,
          preventDuplicates: true
        },
        author: {
          initialCommentsOnly: true,
          preventDuplicates: true
        },
        module: {
          initialCommentsOnly: true,
          preventDuplicates: true
        },
        exports: {
          initialCommentsOnly: true,
          preventDuplicates: true
        }
      }
    }],

    // Disable for now
    'eslint-comments/require-description': 0
  }
};
<|endoftext|>


<commit_before>// -------------------------------------------------------------------------- \\
// File: ListItemView.js                                                      \\
// Module: CollectionViews                                                    \\
// Requires: Core, Foundation, View                                           \\
// Author: Neil Jenkins                                                       \\
// License: © 2010-2014 FastMail Pty Ltd. All rights reserved.                \\
// -------------------------------------------------------------------------- \\

"use strict";

( function ( NS ) {

var ListItemView = NS.Class({

    Extends: NS.View,

    content: null,

    index: 0,
    itemHeight: 32,

    selection: null,
    isSelected: false,

    init: function ( mixin ) {
        var selection = mixin.selection,
            content = mixin.content;
        if ( selection && content ) {
            this.isSelected = selection.isIdSelected(
                content.get( 'id' )
            );
        }
        ListItemView.parent.init.call( this, mixin );
    },

    className: function () {
        return 'ListItemView' +
            ( this.get( 'isSelected' ) ? ' selected' : '' );
    }.property( 'isSelected' ),

    positioning: 'absolute',

    layout: ( NS.UA.cssProps.transform3d ? function () {
        var index = this.get( 'index' ),
            itemHeight = this.get( 'itemHeight' );
        return {
            transform: 'translate3d(0,' + ( index * itemHeight ) + 'px,0)'
        };
    } : function () {
        var index = this.get( 'index' ),
            itemHeight = this.get( 'itemHeight' );
        return {
            top: index * itemHeight
        };
    }).property( 'index', 'itemHeight' )
});

NS.ListItemView = ListItemView;

}( this.O ) );
<commit_msg>Remove className property from ListItemView class.<commit_after>// -------------------------------------------------------------------------- \\
// File: ListItemView.js                                                      \\
// Module: CollectionViews                                                    \\
// Requires: Core, Foundation, View                                           \\
// Author: Neil Jenkins                                                       \\
// License: © 2010-2014 FastMail Pty Ltd. All rights reserved.                \\
// -------------------------------------------------------------------------- \\

"use strict";

( function ( NS ) {

var ListItemView = NS.Class({

    Extends: NS.View,

    content: null,

    index: 0,
    itemHeight: 32,

    selection: null,
    isSelected: false,

    init: function ( mixin ) {
        var selection = mixin.selection,
            content = mixin.content;
        if ( selection && content ) {
            this.isSelected = selection.isIdSelected(
                content.get( 'id' )
            );
        }
        ListItemView.parent.init.call( this, mixin );
    },

    positioning: 'absolute',

    layout: ( NS.UA.cssProps.transform3d ? function () {
        var index = this.get( 'index' ),
            itemHeight = this.get( 'itemHeight' );
        return {
            transform: 'translate3d(0,' + ( index * itemHeight ) + 'px,0)'
        };
    } : function () {
        var index = this.get( 'index' ),
            itemHeight = this.get( 'itemHeight' );
        return {
            top: index * itemHeight
        };
    }).property( 'index', 'itemHeight' )
});

NS.ListItemView = ListItemView;

}( this.O ) );
<|endoftext|>


<commit_before>'use strict';

/**
 * A utility class that obtains user location from browser and plots it on the
 * map.
 */
angular.module('atlasApp').factory('LocationProvider', function() {
  /**
   * Instantiates a LocationProvider.
   * Parameters:
   *   map{google.maps.Map}: The map to plot user location on
   */
  function LocationProvider(map) {
    console.log("Location Provider instantiated");
    this._map = map;
  }

  LocationProvider.prototype = {

    getUserLocation: function() {
      // Use lazy instantiation to avoid asking the user for location permissions
      // if this function never gets called
      if (this._userLocation == null) {
        console.log("userLocation instantiated");
        this._userLocation = new GeolocationMarker();  // Asks browser for location
        this._userLocation.setMap(this._map);
      }
      return this._userLocation;
    },

    _startWatchingUserLocation: function() {
      // TODO: Implement this
    },

    _stopWatchingUserLocation: function() {
      // TODO: Implement this
    },

    showUserLocation: function() {
      this.getUserLocation().setMarkerOptions({visible: true});
      this.getUserLocation().setCircleOptions({visible: true});
    },

    hideUserLocation: function() {
      this.getUserLocation().setMarkerOptions({visible: false});
      this.getUserLocation().setCircleOptions({visible: false});
    }
  }

  return LocationProvider;
});<commit_msg>Implemented location watching<commit_after>'use strict';

/**
 * A utility class that obtains user location from browser and plots it on the
 * map.
 */
angular.module('atlasApp').factory('LocationProvider', function() {
  /**
   * Instantiates a LocationProvider.
   * Parameters:
   *   map{google.maps.Map}: The map to plot user location on
   */
  function LocationProvider(map) {
    console.log("Location Provider instantiated");
    this._map = map;
  }

  LocationProvider.prototype = {

    getUserLocation: function() {
      // Use lazy instantiation to avoid asking the user for location permissions
      // if this function never gets called
      if (this._userLocation == null) {
        console.log("userLocation instantiated");
        this._userLocation = new GeolocationMarker();  // Asks browser for location
        this._userLocation.setMap(this._map);
      }
      return this._userLocation;
    },

    _startWatchingUserLocation: function() {
      var self = this;
      if (!navigator.geolocation) {
        return;   // Geolocation not supported
      }
      if (this._watchId != null) {
        return;   // Already watching
      }
      this._watchId = navigator.geolocation.watchPosition(function(position) {
        var coordinates = new google.maps.LatLng(
            position.coords.latitude,
            position.coords.longitude);
        self._map.panTo(coordinates);
      }, function(error) {
        console.log(error);
      }, this.getUserLocation().getPositionOptions());
    },

    _stopWatchingUserLocation: function() {
      // TODO: Implement this
    },

    showUserLocation: function() {
      this.getUserLocation().setMarkerOptions({visible: true});
      this.getUserLocation().setCircleOptions({visible: true});
      this._startWatchingUserLocation();
    },

    hideUserLocation: function() {
      this.getUserLocation().setMarkerOptions({visible: false});
      this.getUserLocation().setCircleOptions({visible: false});
      this._stopWatchingUserLocation();
    }
  }

  return LocationProvider;
});<|endoftext|>


<commit_before>import getItemModelName from 'appkit/utils/model';

export default Ember.CollectionView.extend({

  limit: 3,

  content: function () {
    return this.get('relationKeys').slice(0, this.get('limit'));
  }.property('relationKeys'),

  itemViewClass: Ember.View.extend({
    tagName: 'span',
    willInsertElement: function () {

      if (!this.get('content')) {
        Ember.Logger.error('No relationKey');
        return;
      }

      var relationNameItem = this;
      var collectionView = this.get('parentView');
      var store = this.get('controller.store');

      var content = this.get('content');
      var keyParts = content.split(' ');
      var contentTypeId = keyParts[0];
      var itemId = keyParts[1];

      Ember.Logger.info('Looking up item for relation name', contentTypeId, itemId);

      store.find('contentType', contentTypeId).then(function (contentType) {
        var modelName = getItemModelName(contentType);

        store.find(modelName, itemId).then(function (relation) {
          Ember.Logger.info('Found item for relation', relation.get('data.name'));
          if (content === collectionView.get('content.lastObject')) {
            relationNameItem.set('last', true);
            if (collectionView.get('relationKeys.length') > collectionView.get('limit')) {
              relationNameItem.set('more', collectionView.get('relationKeys.length') - collectionView.get('limit'));
            }
          }
          relationNameItem.set('relation', relation);
        });
      });

    }
  })
});
<commit_msg>handle no relations<commit_after>import getItemModelName from 'appkit/utils/model';

export default Ember.CollectionView.extend({

  limit: 3,

  content: function () {
    if (!this.get('relationKeys')) {
      return Ember.A([]);
    }
    return this.get('relationKeys').slice(0, this.get('limit'));
  }.property('relationKeys'),

  itemViewClass: Ember.View.extend({
    tagName: 'span',
    willInsertElement: function () {

      if (!this.get('content')) {
        Ember.Logger.error('No relationKey');
        return;
      }

      var relationNameItem = this;
      var collectionView = this.get('parentView');
      var store = this.get('controller.store');

      var content = this.get('content');
      var keyParts = content.split(' ');
      var contentTypeId = keyParts[0];
      var itemId = keyParts[1];

      Ember.Logger.info('Looking up item for relation name', contentTypeId, itemId);

      store.find('contentType', contentTypeId).then(function (contentType) {
        var modelName = getItemModelName(contentType);

        store.find(modelName, itemId).then(function (relation) {
          Ember.Logger.info('Found item for relation', relation.get('data.name'));
          if (content === collectionView.get('content.lastObject')) {
            relationNameItem.set('last', true);
            if (collectionView.get('relationKeys.length') > collectionView.get('limit')) {
              relationNameItem.set('more', collectionView.get('relationKeys.length') - collectionView.get('limit'));
            }
          }
          relationNameItem.set('relation', relation);
        });
      });

    }
  })
});
<|endoftext|>


<commit_before>import ComponentView from 'dom_components/view/ComponentView';
import Component from 'dom_components/model/Component';
import DomComponents from 'dom_components';
import Editor from 'editor/model/Editor';

describe('ComponentView', () => {
  var fixtures;
  var model;
  var view;
  var hClass = 'hc-state';
  var dcomp;
  var compOpts;
  let em;

  beforeEach(() => {
    em = new Editor({});
    dcomp = new DomComponents();
    compOpts = {
      em,
      componentTypes: dcomp.componentTypes
    };
    model = new Component({}, compOpts);
    view = new ComponentView({
      model
    });
    document.body.innerHTML = '

';
    fixtures = document.body.querySelector('#fixtures');
    fixtures.appendChild(view.render().el);
  });

  afterEach(() => {
    view.remove();
  });

  test('Component empty', () => {
    expect(fixtures.innerHTML).toEqual(
      '

'
    );
  });

  test('Add helper class on update of state', () => {
    em.setSelected(model);
    em.setState('test');
    expect(fixtures.innerHTML).toEqual(
      `<div data-gjs-type="default" data-highlightable="1" class="selected ${hClass}"></div>`
    );
  });

  test('Clean form helper state', () => {
    em.setSelected(model);
    em.setState('test');
    em.setState();
    expect(fixtures.innerHTML).toEqual(
      '

'
    );
  });

  test('Add helper class on status update', () => {
    model.set('status', 'selected');
    expect(fixtures.innerHTML).toEqual(
      '

'
    );
  });

  test('Get string of classes', () => {
    model.set('attributes', { class: ['test', 'test2'] });
    expect(view.getClasses()).toEqual('test test2');
  });

  test('Update attributes', () => {
    model.set('attributes', {
      title: 'value',
      'data-test': 'value2'
    });
    expect(view.el.getAttribute('title')).toEqual('value');
    expect(view.el.getAttribute('data-test')).toEqual('value2');
  });

  test('Update style', () => {
    model.set('style', {
      color: 'red',
      float: 'left'
    });
    expect(view.el.getAttribute('style')).toEqual('color:red;float:left;');
  });

  test('Clean style', () => {
    model.set('style', { color: 'red' });
    model.set('style', {});
    expect(view.el.getAttribute('style')).toEqual(null);
  });

  test('Add class', () => {
    model.get('classes').add({ name: 'test' });
    expect(view.el.getAttribute('class')).toEqual('test');
  });

  test('Add classes', () => {
    model.get('classes').add([{ name: 'test' }, { name: 'test2' }]);
    expect(view.el.getAttribute('class')).toEqual('test test2');
  });

  test('Update on remove of some class', () => {
    var cls1 = model.get('classes').add({ name: 'test' });
    var cls12 = model.get('classes').add({ name: 'test2' });
    model.get('classes').remove(cls1);
    expect(view.el.getAttribute('class')).toEqual('test2');
  });

  test('Init with different tag', () => {
    model = new Component({ tagName: 'span' });
    view = new ComponentView({ model });
    fixtures.innerHTML = '';
    fixtures.appendChild(view.render().el);
    expect(view.render().el.tagName).toEqual('SPAN');
  });

  test('Init with nested components', () => {
    model = new Component(
      {
        components: [{ tagName: 'span' }, { attributes: { title: 'test' } }]
      },
      compOpts
    );
    view = new ComponentView({
      model,
      componentTypes: dcomp.componentTypes
    });
    fixtures.innerHTML = '';
    fixtures.appendChild(view.render().el);
    expect(view.$el.html()).toEqual(
      '

'
    );
  });

  test('removeClass removes classes from attributes', () => {
    model.addClass('class1');
    model.removeClass('class1');
    const result = model.getAttributes();
    expect(result.class).toEqual(undefined);
  });
});
<commit_msg>Update ComponentView tests<commit_after>import ComponentView from 'dom_components/view/ComponentView';
import Component from 'dom_components/model/Component';
import DomComponents from 'dom_components';
import Editor from 'editor/model/Editor';

describe('ComponentView', () => {
  var fixtures;
  var model;
  var view;
  var hClass = 'hc-state';
  var dcomp;
  var compOpts;
  let em;

  beforeEach(() => {
    em = new Editor({});
    dcomp = new DomComponents();
    compOpts = {
      em,
      componentTypes: dcomp.componentTypes
    };
    model = new Component({}, compOpts);
    view = new ComponentView({
      model
    });
    em.get('StyleManager').render(); // Enable to listen em.setState
    document.body.innerHTML = '

';
    fixtures = document.body.querySelector('#fixtures');
    fixtures.appendChild(view.render().el);
  });

  afterEach(() => {
    view.remove();
  });

  test('Component empty', () => {
    expect(fixtures.innerHTML).toEqual(
      '

'
    );
  });

  test('Add helper class on update of state', () => {
    em.setSelected(model);
    em.setState('test');
    expect(fixtures.innerHTML).toEqual(
      `<div data-gjs-type="default" data-highlightable="1" class="selected ${hClass}"></div>`
    );
  });

  test('Clean form helper state', () => {
    em.setSelected(model);
    em.setState('test');
    em.setState();
    expect(fixtures.innerHTML).toEqual(
      '

'
    );
  });

  test('Add helper class on status update', () => {
    model.set('status', 'selected');
    expect(fixtures.innerHTML).toEqual(
      '

'
    );
  });

  test('Get string of classes', () => {
    model.set('attributes', { class: ['test', 'test2'] });
    expect(view.getClasses()).toEqual('test test2');
  });

  test('Update attributes', () => {
    model.set('attributes', {
      title: 'value',
      'data-test': 'value2'
    });
    expect(view.el.getAttribute('title')).toEqual('value');
    expect(view.el.getAttribute('data-test')).toEqual('value2');
  });

  test('Update style', () => {
    model.set('style', {
      color: 'red',
      float: 'left'
    });
    expect(view.el.getAttribute('style')).toEqual('color:red;float:left;');
  });

  test('Clean style', () => {
    model.set('style', { color: 'red' });
    model.set('style', {});
    expect(view.el.getAttribute('style')).toEqual(null);
  });

  test('Add class', () => {
    model.get('classes').add({ name: 'test' });
    expect(view.el.getAttribute('class')).toEqual('test');
  });

  test('Add classes', () => {
    model.get('classes').add([{ name: 'test' }, { name: 'test2' }]);
    expect(view.el.getAttribute('class')).toEqual('test test2');
  });

  test('Update on remove of some class', () => {
    var cls1 = model.get('classes').add({ name: 'test' });
    var cls12 = model.get('classes').add({ name: 'test2' });
    model.get('classes').remove(cls1);
    expect(view.el.getAttribute('class')).toEqual('test2');
  });

  test('Init with different tag', () => {
    model = new Component({ tagName: 'span' });
    view = new ComponentView({ model });
    fixtures.innerHTML = '';
    fixtures.appendChild(view.render().el);
    expect(view.render().el.tagName).toEqual('SPAN');
  });

  test('Init with nested components', () => {
    model = new Component(
      {
        components: [{ tagName: 'span' }, { attributes: { title: 'test' } }]
      },
      compOpts
    );
    view = new ComponentView({
      model,
      componentTypes: dcomp.componentTypes
    });
    fixtures.innerHTML = '';
    fixtures.appendChild(view.render().el);
    expect(view.$el.html()).toEqual(
      '

'
    );
  });

  test('removeClass removes classes from attributes', () => {
    model.addClass('class1');
    model.removeClass('class1');
    const result = model.getAttributes();
    expect(result.class).toEqual(undefined);
  });
});
<|endoftext|>


<commit_before>module.exports = {
    'env': {
        'browser': true,
        'commonjs': true,
        'es6': true,
        'jasmine': true
    },
    'extends': [
        'eslint:recommended',
        'plugin:flowtype/recommended'
    ],
    'globals': {
        // The globals that (1) are accessed but not defined within many of our
        // files, (2) are certainly defined, and (3) we would like to use
        // without explicitly specifying them (using a comment) inside of our
        // files.
        '__filename': false
    },
    'parser': 'babel-eslint',
    'parserOptions': {
        'ecmaFeatures': {
            'experimentalObjectRestSpread': true
        },
        'sourceType': 'module'
    },
    'plugins': [
        'flowtype',

        // ESLint's rule no-duplicate-imports does not understand Flow's import
        // type. Fortunately, eslint-plugin-import understands Flow's import
        // type.
        'import'
    ],
    'rules': {
        'new-cap': 2,
        'no-console': 0,
        'semi': [ 'error', 'always' ],

        // Possible Errors group
        'no-cond-assign': 2,
        'no-constant-condition': 2,
        'no-control-regex': 2,
        'no-debugger': 2,
        'no-dupe-args': 2,
        'no-duplicate-case': 2,
        'no-empty': 2,
        'no-empty-character-class': 2,
        'no-ex-assign': 2,
        'no-extra-boolean-cast': 2,
        'no-extra-parens': [
            'error',
            'all',
            { 'nestedBinaryExpressions': false }
        ],
        'no-extra-semi': 2,
        'no-func-assign': 2,
        'no-inner-declarations': 2,
        'no-invalid-regexp': 2,
        'no-irregular-whitespace': 2,
        'no-negated-in-lhs': 2,
        'no-obj-calls': 2,
        'no-prototype-builtins': 0,
        'no-regex-spaces': 2,
        'no-sparse-arrays': 2,
        'no-unexpected-multiline': 2,
        'no-unreachable': 2,
        'no-unsafe-finally': 2,
        'use-isnan': 2,

        'valid-typeof': 2,

        // Best Practices group
        'accessor-pairs': 0,
        'array-callback-return': 2,
        'block-scoped-var': 0,
        'complexity': 0,

        'prefer-const': 2,
        'prefer-reflect': 0,
        'prefer-spread': 2,
        'require-yield': 2,
        'rest-spread-spacing': 2,
        'sort-imports': 0,
        'template-curly-spacing': 2,
        'yield-star-spacing': 2,

        'import/no-duplicates': 2
    }
};
<commit_msg>chore(eslint): Add consistent-return rule<commit_after>module.exports = {
    'env': {
        'browser': true,
        'commonjs': true,
        'es6': true,
        'jasmine': true
    },
    'extends': [
        'eslint:recommended',
        'plugin:flowtype/recommended'
    ],
    'globals': {
        // The globals that (1) are accessed but not defined within many of our
        // files, (2) are certainly defined, and (3) we would like to use
        // without explicitly specifying them (using a comment) inside of our
        // files.
        '__filename': false
    },
    'parser': 'babel-eslint',
    'parserOptions': {
        'ecmaFeatures': {
            'experimentalObjectRestSpread': true
        },
        'sourceType': 'module'
    },
    'plugins': [
        'flowtype',

        // ESLint's rule no-duplicate-imports does not understand Flow's import
        // type. Fortunately, eslint-plugin-import understands Flow's import
        // type.
        'import'
    ],
    'rules': {
        'new-cap': 2,
        'no-console': 0,
        'semi': [ 'error', 'always' ],

        // Possible Errors group
        'no-cond-assign': 2,
        'no-constant-condition': 2,
        'no-control-regex': 2,
        'no-debugger': 2,
        'no-dupe-args': 2,
        'no-duplicate-case': 2,
        'no-empty': 2,
        'no-empty-character-class': 2,
        'no-ex-assign': 2,
        'no-extra-boolean-cast': 2,
        'no-extra-parens': [
            'error',
            'all',
            { 'nestedBinaryExpressions': false }
        ],
        'no-extra-semi': 2,
        'no-func-assign': 2,
        'no-inner-declarations': 2,
        'no-invalid-regexp': 2,
        'no-irregular-whitespace': 2,
        'no-negated-in-lhs': 2,
        'no-obj-calls': 2,
        'no-prototype-builtins': 0,
        'no-regex-spaces': 2,
        'no-sparse-arrays': 2,
        'no-unexpected-multiline': 2,
        'no-unreachable': 2,
        'no-unsafe-finally': 2,
        'use-isnan': 2,

        'valid-typeof': 2,

        // Best Practices group
        'accessor-pairs': 0,
        'array-callback-return': 2,
        'block-scoped-var': 0,
        'complexity': 0,
        'consistent-return': 0,

        'prefer-const': 2,
        'prefer-reflect': 0,
        'prefer-spread': 2,
        'require-yield': 2,
        'rest-spread-spacing': 2,
        'sort-imports': 0,
        'template-curly-spacing': 2,
        'yield-star-spacing': 2,

        'import/no-duplicates': 2
    }
};
<|endoftext|>


<commit_before>/**
 * Created by Sanchez
 */
'use strict';

window.game = new Phaser.Game('100', '100', Phaser.AUTO, 'canvas-wrapper', null, true);
window.game.state.add('Boot', require('../states/boot'));
window.game.state.add('Preloader', require('../states/preloader'));
window.game.state.add('State1', require('../states/state1'));
window.game.state.start('Boot');

//Can Use ES6
const use_e6 = true;

window.h5 = {
    isPc: function() {
        var userAgentInfo = navigator.userAgent;
        var Agents = new Array("Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod");
        var flag = true;
        for (var v = 0; v < Agents.length; v++) {
            if (userAgentInfo.indexOf(Agents[v]) > 0) { flag = false; break; }
        }
        return flag;
    },
    rootResize: function() {
        //orientation portrait width=750px height=1334px / WeChat width=750px height=1206px
        var wFsize;
        //screen.width screen.height  bug !!!
        // var wWidth = (screen.width > 0) ? (window.innerWidth >= screen.width || window.innerWidth == 0) ? screen.width :
        //     window.innerWidth : window.innerWidth;
        // var wHeight = (screen.height > 0) ? (window.innerHeight >= screen.height || window.innerHeight == 0) ?
        //     screen.height : window.innerHeight : window.innerHeight;
        var wWidth = window.innerWidth;
        var wHeight = window.innerHeight;
        if (wWidth > wHeight) {
            wHeight = wWidth;
        }
        wFsize = wHeight / 7.5;
        document.getElementsByTagName('html')[0].style.fontSize = wFsize + 'px';
    },
    eventInit: function() {
        var that = this;
        document.addEventListener('touchstart', function(e) {}, false);
        document.addEventListener('touchmove', function(e) {
            e.preventDefault();
        }, false);
        return that;
    },
    cssInit: function() {
        var that = this;
        var noChangeCountToEnd = 100,
            noEndTimeout = 1000;
        that.rootResize();
        window.addEventListener("onorientationchange" in window ? "orientationchange" : "resize", function() {
            var interval,
                timeout,
                end,
                lastInnerWidth,
                lastInnerHeight,
                noChangeCount;
            end = function() {
                // "orientationchangeend"
                clearInterval(interval);
                clearTimeout(timeout);
                interval = null;
                timeout = null;
                that.rootResize();
            };
            interval = setInterval(function() {
                if (window.innerWidth === lastInnerWidth && window.innerHeight === lastInnerHeight) {
                    noChangeCount++;
                    if (noChangeCount === noChangeCountToEnd) {
                        // The interval resolved the issue first.
                        end();
                    }
                } else {
                    lastInnerWidth = window.innerWidth;
                    lastInnerHeight = window.innerHeight;
                    noChangeCount = 0;
                }
            });
            timeout = setTimeout(function() {
                // The timeout happened first.
                end();
            }, noEndTimeout);
        });

        return that;
    },
    init: function() {
        var that = this;
        that.cssInit().eventInit();
    }
};

window.onload = function() {
    window.h5.init();
    showStats();
};

function showStats() {
    var stats = new Stats();
    stats.showPanel(0); // 0: fps, 1: ms, 2: mb, 3+: custom
    var fs = document.createElement('div');
    fs.style.position = 'absolute';
    fs.style.left = 0;
    fs.style.top = 0;
    fs.style.zIndex = 999;
    fs.appendChild(stats.domElement);
    document.body.appendChild(fs);

    function animate() {
        stats.begin();
        // monitored code goes here
        stats.end();
        requestAnimationFrame(animate);
    }
    requestAnimationFrame(animate);
}<commit_msg>:art: Just Use ' instead of "<commit_after>/**
 * Created by Sanchez
 */
'use strict';

window.game = new Phaser.Game('100', '100', Phaser.AUTO, 'canvas-wrapper', null, true);
window.game.state.add('Boot', require('../states/boot'));
window.game.state.add('Preloader', require('../states/preloader'));
window.game.state.add('State1', require('../states/state1'));
window.game.state.start('Boot');

//Can Use ES6
const use_e6 = true;

window.h5 = {
    isPc: function() {
        var userAgentInfo = navigator.userAgent;
        var Agents = new Array('Android', 'iPhone', 'SymbianOS', 'Windows Phone', 'iPad', 'iPod');
        var flag = true;
        for (var v = 0; v < Agents.length; v++) {
            if (userAgentInfo.indexOf(Agents[v]) > 0) { flag = false; break; }
        }
        return flag;
    },
    rootResize: function() {
        //orientation portrait width=750px height=1334px / WeChat width=750px height=1206px
        var wFsize;
        //screen.width screen.height  bug !!!
        // var wWidth = (screen.width > 0) ? (window.innerWidth >= screen.width || window.innerWidth == 0) ? screen.width :
        //     window.innerWidth : window.innerWidth;
        // var wHeight = (screen.height > 0) ? (window.innerHeight >= screen.height || window.innerHeight == 0) ?
        //     screen.height : window.innerHeight : window.innerHeight;
        var wWidth = window.innerWidth;
        var wHeight = window.innerHeight;
        if (wWidth > wHeight) {
            wHeight = wWidth;
        }
        wFsize = wHeight / 7.5;
        document.getElementsByTagName('html')[0].style.fontSize = wFsize + 'px';
    },
    eventInit: function() {
        var that = this;
        document.addEventListener('touchstart', function(e) {}, false);
        document.addEventListener('touchmove', function(e) {
            e.preventDefault();
        }, false);
        return that;
    },
    cssInit: function() {
        var that = this;
        var noChangeCountToEnd = 100,
            noEndTimeout = 1000;
        that.rootResize();
        window.addEventListener('onorientationchange' in window ? 'orientationchange' : 'resize', function() {
            var interval,
                timeout,
                end,
                lastInnerWidth,
                lastInnerHeight,
                noChangeCount;
            end = function() {
                // 'orientationchangeend'
                clearInterval(interval);
                clearTimeout(timeout);
                interval = null;
                timeout = null;
                that.rootResize();
            };
            interval = setInterval(function() {
                if (window.innerWidth === lastInnerWidth && window.innerHeight === lastInnerHeight) {
                    noChangeCount++;
                    if (noChangeCount === noChangeCountToEnd) {
                        // The interval resolved the issue first.
                        end();
                    }
                } else {
                    lastInnerWidth = window.innerWidth;
                    lastInnerHeight = window.innerHeight;
                    noChangeCount = 0;
                }
            });
            timeout = setTimeout(function() {
                // The timeout happened first.
                end();
            }, noEndTimeout);
        });

        return that;
    },
    init: function() {
        var that = this;
        that.cssInit().eventInit();
    }
};

window.onload = function() {
    window.h5.init();
    showStats();
};

function showStats() {
    var stats = new Stats();
    stats.showPanel(0); // 0: fps, 1: ms, 2: mb, 3+: custom
    var fs = document.createElement('div');
    fs.style.position = 'absolute';
    fs.style.left = 0;
    fs.style.top = 0;
    fs.style.zIndex = 999;
    fs.appendChild(stats.domElement);
    document.body.appendChild(fs);

    function animate() {
        stats.begin();
        // monitored code goes here
        stats.end();
        requestAnimationFrame(animate);
    }
    requestAnimationFrame(animate);
}<|endoftext|>


<commit_before>'use strict';

module.exports = {
  root: true,
  parserOptions: {
    ecmaVersion: 6,
    sourceType: 'module',
    ecmaFeatures: {
      jsx: true,
    },
  },
  env: {
    browser: true,
    mocha: true,
    node: true,
    es6: true,
  },
  plugins: ['react'],
  extends: ['eslint:recommended', 'plugin:react/recommended'],
  rules: {
    // Other rules
    'no-console': 'off',
    'valid-jsdoc': ['error', {requireReturn: false}],
    eqeqeq: 'error',
    // The following rules can be used in some cases. See the README for more
    // information. (These are marked with `0` instead of `"off"` so that a
    // script can distinguish them.)
    curly: 0,
    'max-len': 0,
    'no-mixed-operators': 0,
    quotes: 0,
    // The rest are rules that you never need to enable when using Prettier.
    'array-bracket-spacing': 'off',
    'arrow-parens': 'off',
    'arrow-spacing': 'off',
    'block-spacing': 'off',
    'brace-style': 'off',
    'comma-dangle': 'off',
    'comma-spacing': 'off',
    'comma-style': 'off',
    'computed-property-spacing': 'off',
    'dot-location': 'off',
    'eol-last': 'off',
    'func-call-spacing': 'off',
    'generator-star': 'off',
    'generator-star-spacing': 'off',
    indent: 'off',
    'jsx-quotes': 'off',
    'key-spacing': 'off',
    'keyword-spacing': 'off',
    'multiline-ternary': 'off',
    'newline-per-chained-call': 'off',
    'new-parens': 'off',
    'no-arrow-condition': 'off',
    'no-comma-dangle': 'off',
    'no-confusing-arrow': 'off',
    'no-extra-parens': 'off',
    'no-extra-semi': 'off',
    'no-mixed-spaces-and-tabs': 'off',
    'no-multi-spaces': 'off',
    'no-multiple-empty-lines': 'off',
    'no-reserved-keys': 'off',
    'no-space-before-semi': 'off',
    'no-spaced-func': 'off',
    'no-trailing-spaces': 'off',
    'no-whitespace-before-property': 'off',
    'no-wrap-func': 'off',
    'nonblock-statement-body-position': 'off',
    'object-curly-newline': 'off',
    'object-curly-spacing': 'off',
    'object-property-newline': 'off',
    'one-var-declaration-per-line': 'off',
    'operator-linebreak': 'off',
    'padded-blocks': 'off',
    'quote-props': 'off',
    'rest-spread-spacing': 'off',
    semi: 'off',
    'semi-spacing': 'off',
    'space-after-function-name': 'off',
    'space-after-keywords': 'off',
    'space-before-blocks': 'off',
    'space-before-function-paren': 'off',
    'space-before-function-parentheses': 'off',
    'space-before-keywords': 'off',
    'space-in-brackets': 'off',
    'space-in-parens': 'off',
    'space-infix-ops': 'off',
    'space-return-throw-case': 'off',
    'space-unary-ops': 'off',
    'space-unary-word-ops': 'off',
    'template-curly-spacing': 'off',
    'template-tag-spacing': 'off',
    'unicode-bom': 'off',
    'wrap-iife': 'off',
    'wrap-regex': 'off',
    'yield-star-spacing': 'off',
  },
};
<commit_msg>Update linter file<commit_after>'use strict';

module.exports = {
  root: true,
  parserOptions: {
    ecmaVersion: 6,
    sourceType: 'module',
    ecmaFeatures: {
      jsx: true,
    },
  },
  env: {
    browser: true,
    mocha: true,
    node: true,
    es6: true,
  },
  parser: 'babel-eslint',
  plugins: ['react', 'babel'],
  extends: ['eslint:recommended', 'plugin:react/recommended'],
  rules: {
    // Other rules
    'no-console': 'off',
    'valid-jsdoc': ['error', {requireReturn: false}],
    eqeqeq: 'error',
    // The following rules can be used in some cases. See the README for more
    // information. (These are marked with `0` instead of `"off"` so that a
    // script can distinguish them.)
    curly: 0,
    'max-len': 0,
    'no-mixed-operators': 0,
    quotes: 0,
    // The rest are rules that you never need to enable when using Prettier.
    'array-bracket-spacing': 'off',
    'arrow-parens': 'off',
    'arrow-spacing': 'off',
    'block-spacing': 'off',
    'brace-style': 'off',
    'comma-dangle': 'off',
    'comma-spacing': 'off',
    'comma-style': 'off',
    'computed-property-spacing': 'off',
    'dot-location': 'off',
    'eol-last': 'off',
    'func-call-spacing': 'off',
    'generator-star': 'off',
    'generator-star-spacing': 'off',
    indent: 'off',
    'jsx-quotes': 'off',
    'key-spacing': 'off',
    'keyword-spacing': 'off',
    'multiline-ternary': 'off',
    'newline-per-chained-call': 'off',
    'new-parens': 'off',
    'no-arrow-condition': 'off',
    'no-comma-dangle': 'off',
    'no-confusing-arrow': 'off',
    'no-extra-parens': 'off',
    'no-extra-semi': 'off',
    'no-mixed-spaces-and-tabs': 'off',
    'no-multi-spaces': 'off',
    'no-multiple-empty-lines': 'off',
    'no-reserved-keys': 'off',
    'no-space-before-semi': 'off',
    'no-spaced-func': 'off',
    'no-trailing-spaces': 'off',
    'no-whitespace-before-property': 'off',
    'no-wrap-func': 'off',
    'nonblock-statement-body-position': 'off',
    'object-curly-newline': 'off',
    'object-curly-spacing': 'off',
    'object-property-newline': 'off',
    'one-var-declaration-per-line': 'off',
    'operator-linebreak': 'off',
    'padded-blocks': 'off',
    'quote-props': 'off',
    'rest-spread-spacing': 'off',
    semi: 'off',
    'semi-spacing': 'off',
    'space-after-function-name': 'off',
    'space-after-keywords': 'off',
    'space-before-blocks': 'off',
    'space-before-function-paren': 'off',
    'space-before-function-parentheses': 'off',
    'space-before-keywords': 'off',
    'space-in-brackets': 'off',
    'space-in-parens': 'off',
    'space-infix-ops': 'off',
    'space-return-throw-case': 'off',
    'space-unary-ops': 'off',
    'space-unary-word-ops': 'off',
    'template-curly-spacing': 'off',
    'template-tag-spacing': 'off',
    'unicode-bom': 'off',
    'wrap-iife': 'off',
    'wrap-regex': 'off',
    'yield-star-spacing': 'off',
  },
};
<|endoftext|>


<commit_before>module.exports = TorrentList

var h = require('virtual-dom/h')
var hyperx = require('hyperx')
var hx = hyperx(h)
var prettyBytes = require('pretty-bytes')

function TorrentList (state, dispatch) {
  var torrents = state.view.client
    ? state.view.client.torrents
    : []

  var list = torrents.map((torrent) => renderTorrent(state, dispatch, torrent))
  return hx`<div className="torrent-list">${list}</div>`
}

// Renders a torrent in the torrent list
// Includes name, download status, play button, background image
// May be expanded for additional info, including the list of files inside
function renderTorrent (state, dispatch, torrent) {
  // Background image: show some nice visuals, like a frame from the movie, if possible
  var style = {}
  if (torrent.posterURL) {
    style['background-image'] = `linear-gradient(to bottom, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0) 100%), url("${torrent.posterURL}")`
  }

  // Foreground: name of the torrent, basic info like size, play button,
  // cast buttons if available, and delete
  var elements = [
    renderTorrentMetadata(torrent),
    hx`
       dispatch('deleteTorrent', torrent)}>
        close

    `,
    hx`
       dispatch('openPlayer', torrent)}>
        play_arrow

    `
  ]

  if (state.view.chromecast) {
    elements.push(hx`
       dispatch('openChromecast', torrent)}>
        cast

    `)
  }

  if (state.view.devices.airplay) {
    elements.push(hx`
       dispatch('openAirplay', torrent)}>
        airplay

    `)
  }

  return hx`<div className='torrent' style=${style}>${elements}</div>`
}

// Renders the torrent name and download progress
function renderTorrentMetadata (torrent) {
  return hx`

${torrent.name || 'Loading torrent...'}

        ${Math.floor(100 * torrent.progress)}%

      ${getFilesLength()}
      ${getPeers()}
      ${prettyBytes(torrent.downloadSpeed)}/s
      ${prettyBytes(torrent.uploadSpeed)}/s

  `

  function getPeers () {
    var count = torrent.numPeers === 1 ? 'peer' : 'peers'
    return `${torrent.numPeers} ${count}`
  }

  function getFilesLength () {
    if (torrent.ready && torrent.files.length > 1) {
      return hx`<span className="files">${torrent.files.length} files</span>`
    }
  }
}
<commit_msg>update class notation<commit_after>module.exports = TorrentList

var h = require('virtual-dom/h')
var hyperx = require('hyperx')
var hx = hyperx(h)
var prettyBytes = require('pretty-bytes')

function TorrentList (state, dispatch) {
  var torrents = state.view.client
    ? state.view.client.torrents
    : []

  var list = torrents.map((torrent) => renderTorrent(state, dispatch, torrent))
  return hx`<div className="torrent-list">${list}</div>`
}

// Renders a torrent in the torrent list
// Includes name, download status, play button, background image
// May be expanded for additional info, including the list of files inside
function renderTorrent (state, dispatch, torrent) {
  // Background image: show some nice visuals, like a frame from the movie, if possible
  var style = {}
  if (torrent.posterURL) {
    style['background-image'] = `linear-gradient(to bottom, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0) 100%), url("${torrent.posterURL}")`
  }

  // Foreground: name of the torrent, basic info like size, play button,
  // cast buttons if available, and delete
  var elements = [
    renderTorrentMetadata(torrent),
    hx`
       dispatch('deleteTorrent', torrent)}>
        close

    `,
    hx`
       dispatch('openPlayer', torrent)}>
        play_arrow

    `
  ]

  if (state.view.chromecast) {
    elements.push(hx`
       dispatch('openChromecast', torrent)}>
        cast

    `)
  }

  if (state.view.devices.airplay) {
    elements.push(hx`
       dispatch('openAirplay', torrent)}>
        airplay

    `)
  }

  return hx`<div className='torrent' style=${style}>${elements}</div>`
}

// Renders the torrent name and download progress
function renderTorrentMetadata (torrent) {
  return hx`

${torrent.name || 'Loading torrent...'}

        ${Math.floor(100 * torrent.progress)}%

      ${getFilesLength()}
      ${getPeers()}
      ${prettyBytes(torrent.downloadSpeed)}/s
      ${prettyBytes(torrent.uploadSpeed)}/s

  `

  function getPeers () {
    var count = torrent.numPeers === 1 ? 'peer' : 'peers'
    return `${torrent.numPeers} ${count}`
  }

  function getFilesLength () {
    if (torrent.ready && torrent.files.length > 1) {
      return hx`<span className="files">${torrent.files.length} files</span>`
    }
  }
}
<|endoftext|>


<commit_before>// Copyright (C) 2016 Goom Inc. All rights reserved.

import React, { PropTypes } from 'react';

import SellerBox from './CartSellerBox';

export default React.createClass({
  propTypes: {
    order: PropTypes.object.isRequired,
    addressFields: PropTypes.array,
    activeAddress: PropTypes.object,
    addresses: PropTypes.object,
    saveAddress: PropTypes.func,
  },
  getInitialState() {
    return {};
  },
  render() {
    const { order, addressFields, activeAddress } = this.props;

    const renderFormField = (obj) => {
      return (

{`${obj.text}: `}

          <input type="text"
                 value={_.get(activeAddress, obj.key)}
                 onChange={(e) => { _.set(activeAddress, obj.key, e.target.value ); this.setState({ activeAddress }) } } />

      );
    };
    const handleSubmitAddress = (e) => {
      e.preventDefault();
      let activeAddressInState = this.state.activeAddress;
      if (!activeAddressInState) {
        // Did not changed
        return;
      }
      this.props.saveAddress(activeAddressInState);
      this.setState({ editMode: false });
    };
    let editMode = !!this.state.editMode;
    if (!activeAddress || !activeAddress.id) {
      editMode = true;
    }
    const renderAddress = () => {
      if (editMode) {
        return (
          <form onSubmit={handleSubmitAddress}>
            {addressFields.map((field) => renderFormField(field))}
            <button type="submit">저장하고 사용하기</button>
          </form>
        );
      }
      return (

name

{activeAddress.detail.name}

C.C.

{activeAddress.countryCode}

A.D.

{activeAddress.detail.streetAddress}

{activeAddress.detail.city}

 this.setState({ editMode: true })}>Edit

      );
    };
    const cartVariants = order.orderProducts.map((orderProduct) => {
      return _.assign({}, orderProduct.productVariant, { count: orderProduct.orderedCount });
    });
    return (

1. Please fill in your shipping address.

        {renderAddress()}

2. Review and confirm your order (3 items):

        <SellerBox productVariants={cartVariants} />

          All Total:
          {150000}

          <button className="place-order-button">Place Order</button>

    );
  },
});
<commit_msg>next step when click 'place order'<commit_after>// Copyright (C) 2016 Goom Inc. All rights reserved.

import React, { PropTypes } from 'react';

import SellerBox from './CartSellerBox';

export default React.createClass({
  propTypes: {
    order: PropTypes.object.isRequired,
    addressFields: PropTypes.array,
    activeAddress: PropTypes.object,
    addresses: PropTypes.object,
    saveAddress: PropTypes.func,
    setCheckoutStep: PropTypes.func,
  },
  getInitialState() {
    return {};
  },
  render() {
    const { order, addressFields, activeAddress, setCheckoutStep } = this.props;

    const renderFormField = (obj) => {
      return (

{`${obj.text}: `}

          <input type="text"
                 value={_.get(activeAddress, obj.key)}
                 onChange={(e) => { _.set(activeAddress, obj.key, e.target.value ); this.setState({ activeAddress }) } } />

      );
    };
    const handleSubmitAddress = (e) => {
      e.preventDefault();
      let activeAddressInState = this.state.activeAddress;
      if (!activeAddressInState) {
        // Did not changed
        return;
      }
      this.props.saveAddress(activeAddressInState);
      this.setState({ editMode: false });
    };
    let editMode = !!this.state.editMode;
    if (!activeAddress || !activeAddress.id) {
      editMode = true;
    }
    const renderAddress = () => {
      if (editMode) {
        return (
          <form onSubmit={handleSubmitAddress}>
            {addressFields.map((field) => renderFormField(field))}
            <button type="submit">저장하고 사용하기</button>
          </form>
        );
      }
      return (

name

{activeAddress.detail.name}

C.C.

{activeAddress.countryCode}

A.D.

{activeAddress.detail.streetAddress}

{activeAddress.detail.city}

 this.setState({ editMode: true })}>Edit

      );
    };
    const cartVariants = order.orderProducts.map((orderProduct) => {
      return _.assign({}, orderProduct.productVariant, { count: orderProduct.orderedCount });
    });
    return (

1. Please fill in your shipping address.

        {renderAddress()}

2. Review and confirm your order (3 items):

        <SellerBox productVariants={cartVariants} />

          All Total:
          {150000}

          <button className="place-order-button" onClick={() => setCheckoutStep(2)}>Place Order</button>

    );
  },
});
<|endoftext|>