<commit_before>/* jshint node: true, unused: false */
/* global __dirname: false, describe: false, before: false, it: false, browser: false,
          element: false, expect: false, by: false, protractor: false */
'use strict';
var path = require('path');
var projectRoot = path.resolve(__dirname, '../../../../');
var pkg = require(path.join(projectRoot, 'package.json'));
var pageUrl = 'http://localhost:' + pkg.gruntConfig.connectPort + '/lib/widgets/variable/test/cam-widget-variable.spec.html';

var page = require('./cam-widget-variable.page.js');

describe('Variable', function() {
  var variable;
  describe('editing', function() {
    before(function () {
      browser.get(pageUrl + '#example-1');
    });

    describe('when empty', function () {
      before(function () {
        variable = page.variable('#example-1', 0);
      });

      it('has a dropdown', function () {
        expect(variable.typeDropdownText()).to.eventually.eql('Type');
      });

      it('has a name input', function () {
        expect(variable.nameValue()).to.eventually.eql('');
      });

      it('has a value input', function () {
        expect(variable.valueValue()).to.eventually.eql('');
      });

      it('is not valid', function () {
        expect(variable
          .editingGroup()
          .getAttribute('class')).to.eventually.match(/invalid/);
      });
    });

    describe('validation', function () {
      before(function () {
        // the integer variable
        variable = page.variable('#example-1', 5);
      });

      it('adds the invalid CSS class when value is not of the correct type', function () {
        variable.value().sendKeys('leet').then(function () {
          expect(variable.editingGroupClass())
            .to.eventually.match(/invalid/);
        });
      });

      it('removes the invalid CSS class when is of the correct type', function () {
        variable.value().clear().sendKeys('1337');
        expect(variable.editingGroupClass())
          .not.to.eventually.match(/invalid/);
      });

      it('adds the invalid CSS class when no name is given', function () {
        variable.name().clear();

        expect(variable.nameValue()).to.eventually.eql('');

        expect(variable.editingGroupClass())
          .to.eventually.match(/invalid/);
      });

      it('removes the invalid CSS class when a name is given', function () {
        variable.name().sendKeys('integerVar');

        expect(variable.nameValue()).to.eventually.eql('integerVar');

        expect(variable.editingGroupClass())
          .not.to.eventually.match(/invalid/);
      });
    });

    describe('"null" support', function () {
      before(function () {
        // the empty variable
        variable = page.variable('#example-1', 0);

        variable.typeSelect('String');
        variable.name().sendKeys('aName');
        variable.value().sendKeys('a value');
      });

      it('allows to set a variable value to "null"', function () {
        expect(variable.setNullBtn().isPresent())
          .to.eventually.eql(true);
        expect(variable.setNonNullBtn().isPresent())
          .to.eventually.eql(false);
      });

      it('allows to revert a variable value to its previous value', function () {
        variable.setNullBtn().click();

        expect(variable.setNullBtn().isPresent())
          .to.eventually.eql(false);
        expect(variable.setNonNullBtn().isPresent())
          .to.eventually.eql(true);

        variable.setNonNullBtn().click();
        expect(variable.valueValue()).to.eventually.eql('a value');
      });
    });

    describe('Boolean variable', function () {
      before(function () {
        variable = page.variable('#example-1', 1);
      });

      it('has a dropdown', function () {
        expect(variable.typeDropdownText()).to.eventually.eql('Boolean');
      });

      it('has a name input', function () {
        expect(variable.nameValue()).to.eventually.eql('booleanVar');
      });

      describe('value input', function () {
        it('is a checkbox input', function () {
          expect(variable.valueValue()).to.eventually.eql('on');
          expect(variable.valueType()).to.eventually.eql('checkbox');
        });
      });
    });

    xdescribe('Bytes variable', function () {
      before(function () {
        variable = page.variable('#example-1', 2);
      });

      it('has a dropdown', function () {
        expect(variable.typeDropdownText()).to.eventually.eql('Bytes');
      });

      it('has a name input', function () {
        expect(variable.nameValue()).to.eventually.eql('bytesVar');
      });

      xdescribe('value input', function () {
        it('is disabled', function () {
          expect(variable.value().getAttribute('disabled')).to.eventually.eql('disabled');
        });

        it('shows the object type', function () {
          expect(variable.valueValue()).to.eventually.eql('');
        });
      });
    });

    xdescribe('Date variable', function () {
      before(function () {
        variable = page.variable('#example-1', 3);
      });

      it('has a dropdown', function () {
        expect(variable.typeDropdownText()).to.eventually.eql('Date');
      });

      it('has a name input', function () {
        expect(variable.nameValue()).to.eventually.eql('dateVar');
      });

      it('has a value input', function () {
        expect(variable.valueValue()).to.eventually.eql('2015-03-23T13:14:06.340Z');
      });

      describe('value input', function () {
        it('has a datepicker button', function () {
          expect(variable.value().element(by.css('.btn')).isPresent()).to.eventually.eql(true);
        });
      });
    });

    describe('Double variable', function () {
      before(function () {
        variable = page.variable('#example-1', 4);
      });

      it('has a dropdown', function () {
        expect(variable.typeDropdownText()).to.eventually.eql('Double');
      });

      it('has a name input', function () {
        expect(variable.nameValue()).to.eventually.eql('doubleVar');
      });

      it('has a value input', function () {
        expect(variable.valueValue()).to.eventually.eql('12.34');
      });
    });

    describe('Integer variable', function () {
      before(function () {
        variable = page.variable('#example-1', 5);
      });

      it('has a dropdown', function () {
        expect(variable.typeDropdownText()).to.eventually.eql('Integer');
      });

      it('has a name input', function () {
        expect(variable.nameValue()).to.eventually.eql('integerVar');
      });

      it('has a value input', function () {
        expect(variable.valueValue()).to.eventually.eql('1337');
      });
    });

    describe('Long variable', function () {
      before(function () {
        variable = page.variable('#example-1', 6);
      });

      it('has a dropdown', function () {
        expect(variable.typeDropdownText()).to.eventually.eql('Long');
      });

      it('has a name input', function () {
        expect(variable.nameValue()).to.eventually.eql('longVar');
      });

      it('has a value input', function () {
        expect(variable.valueValue()).to.eventually.eql('-100000000');
      });
    });

    describe('Null variable', function () {
      before(function () {
        variable = page.variable('#example-1', 7);
      });

      it('has a dropdown', function () {
        expect(variable.typeDropdownText()).to.eventually.eql('Null');
      });

      it('has a name input', function () {
        expect(variable.nameValue()).to.eventually.eql('nullVar');
      });

      xit('has a value input', function () {
        expect(variable.valueValue()).to.eventually.eql('null');
      });
    });

    xdescribe('Object variable', function () {
      before(function () {
        variable = page.variable('#example-1', 8);
      });

      it('has a dropdown', function () {
        expect(variable.typeDropdownText()).to.eventually.eql('Object');
      });

      it('has a name input', function () {
        expect(variable.nameValue()).to.eventually.eql('objectVar');
      });

      describe('value input', function () {
        it('has a button to open a dialog', function () {
          expect(variable.name().element(by.css('.btn')).isPresent()).to.eventually.eql(true);
        });
      });
    });

    describe('Short variable', function () {
      before(function () {
        variable = page.variable('#example-1', 9);
      });

      it('has a dropdown', function () {
        expect(variable.typeDropdownText()).to.eventually.eql('Short');
      });

      it('has a name input', function () {
        expect(variable.nameValue()).to.eventually.eql('shortVar');
      });

      it('has a value input', function () {
        expect(variable.valueValue()).to.eventually.eql('-32768');
      });
    });

    describe('String variable', function () {
      before(function () {
        variable = page.variable('#example-1', 10);
      });

      it('has a dropdown', function () {
        expect(variable.typeDropdownText()).to.eventually.eql('String');
      });

      it('has a name input', function () {
        expect(variable.nameValue()).to.eventually.eql('stringVar');
      });

      it('has a value input', function () {
        expect(variable.valueValue()).to.eventually.eql('Some string value');
      });
    });
  });

  xdescribe('display', function () {
    describe('when value is set', function () {
      before(function () {
        browser.get(pageUrl + '#example-2');
        variable = page.variable('#example-2', 1);
      });
    });
  });

  describe('partially shown', function () {
    describe('when value is set', function () {
      before(function () {
        browser.get(pageUrl + '#example-3');
      });

      it('shows the name and value', function () {
        variable = page.variable('#example-3', 0);
        expect(variable.nameValue()).to.eventually.eql('stringVar');
        expect(variable.valueValue()).to.eventually.eql('Some string value');
      });

      it('shows the type and value', function () {
        variable = page.variable('#example-3', 1);
        expect(variable.typeDropdownText()).to.eventually.eql('String');
        expect(variable.valueValue()).to.eventually.eql('Some string value');
      });

      it('shows the type and name', function () {
        variable = page.variable('#example-3', 2);
        expect(variable.typeDropdownText()).to.eventually.eql('String');
        expect(variable.nameValue()).to.eventually.eql('stringVar');
      });
    });
  });
});
<commit_msg>chore(variable.spec): simplify css matcher<commit_after>/* jshint node: true, unused: false */
/* global __dirname: false, describe: false, before: false, it: false, browser: false,
          element: false, expect: false, by: false, protractor: false */
'use strict';
var path = require('path');
var projectRoot = path.resolve(__dirname, '../../../../');
var pkg = require(path.join(projectRoot, 'package.json'));
var pageUrl = 'http://localhost:' + pkg.gruntConfig.connectPort + '/lib/widgets/variable/test/cam-widget-variable.spec.html';

var page = require('./cam-widget-variable.page.js');

describe('Variable', function() {
  var variable;
  describe('editing', function() {
    before(function () {
      browser.get(pageUrl + '#example-1');
    });

    describe('when empty', function () {
      before(function () {
        variable = page.variable('#example-1', 0);
      });

      it('has a dropdown', function () {
        expect(variable.typeDropdownText()).to.eventually.eql('Type');
      });

      it('has a name input', function () {
        expect(variable.nameValue()).to.eventually.eql('');
      });

      it('has a value input', function () {
        expect(variable.valueValue()).to.eventually.eql('');
      });

      it('is not valid', function () {
        expect(variable.editingGroupClass())
            .to.eventually.match(/invalid/);
      });
    });

    describe('validation', function () {
      before(function () {
        // the integer variable
        variable = page.variable('#example-1', 5);
      });

      it('adds the invalid CSS class when value is not of the correct type', function () {
        variable.value().sendKeys('leet').then(function () {
          expect(variable.editingGroupClass())
            .to.eventually.match(/invalid/);
        });
      });

      it('removes the invalid CSS class when is of the correct type', function () {
        variable.value().clear().sendKeys('1337');
        expect(variable.editingGroupClass())
          .not.to.eventually.match(/invalid/);
      });

      it('adds the invalid CSS class when no name is given', function () {
        variable.name().clear();

        expect(variable.nameValue()).to.eventually.eql('');

        expect(variable.editingGroupClass())
          .to.eventually.match(/invalid/);
      });

      it('removes the invalid CSS class when a name is given', function () {
        variable.name().sendKeys('integerVar');

        expect(variable.nameValue()).to.eventually.eql('integerVar');

        expect(variable.editingGroupClass())
          .not.to.eventually.match(/invalid/);
      });
    });

    describe('"null" support', function () {
      before(function () {
        // the empty variable
        variable = page.variable('#example-1', 0);

        variable.typeSelect('String');
        variable.name().sendKeys('aName');
        variable.value().sendKeys('a value');
      });

      it('allows to set a variable value to "null"', function () {
        expect(variable.setNullBtn().isPresent())
          .to.eventually.eql(true);
        expect(variable.setNonNullBtn().isPresent())
          .to.eventually.eql(false);
      });

      it('allows to revert a variable value to its previous value', function () {
        variable.setNullBtn().click();

        expect(variable.setNullBtn().isPresent())
          .to.eventually.eql(false);
        expect(variable.setNonNullBtn().isPresent())
          .to.eventually.eql(true);

        variable.setNonNullBtn().click();
        expect(variable.valueValue()).to.eventually.eql('a value');
      });
    });

    describe('Boolean variable', function () {
      before(function () {
        variable = page.variable('#example-1', 1);
      });

      it('has a dropdown', function () {
        expect(variable.typeDropdownText()).to.eventually.eql('Boolean');
      });

      it('has a name input', function () {
        expect(variable.nameValue()).to.eventually.eql('booleanVar');
      });

      describe('value input', function () {
        it('is a checkbox input', function () {
          expect(variable.valueValue()).to.eventually.eql('on');
          expect(variable.valueType()).to.eventually.eql('checkbox');
        });
      });
    });

    xdescribe('Bytes variable', function () {
      before(function () {
        variable = page.variable('#example-1', 2);
      });

      it('has a dropdown', function () {
        expect(variable.typeDropdownText()).to.eventually.eql('Bytes');
      });

      it('has a name input', function () {
        expect(variable.nameValue()).to.eventually.eql('bytesVar');
      });

      xdescribe('value input', function () {
        it('is disabled', function () {
          expect(variable.value().getAttribute('disabled')).to.eventually.eql('disabled');
        });

        it('shows the object type', function () {
          expect(variable.valueValue()).to.eventually.eql('');
        });
      });
    });

    xdescribe('Date variable', function () {
      before(function () {
        variable = page.variable('#example-1', 3);
      });

      it('has a dropdown', function () {
        expect(variable.typeDropdownText()).to.eventually.eql('Date');
      });

      it('has a name input', function () {
        expect(variable.nameValue()).to.eventually.eql('dateVar');
      });

      it('has a value input', function () {
        expect(variable.valueValue()).to.eventually.eql('2015-03-23T13:14:06.340Z');
      });

      describe('value input', function () {
        it('has a datepicker button', function () {
          expect(variable.value().element(by.css('.btn')).isPresent()).to.eventually.eql(true);
        });
      });
    });

    describe('Double variable', function () {
      before(function () {
        variable = page.variable('#example-1', 4);
      });

      it('has a dropdown', function () {
        expect(variable.typeDropdownText()).to.eventually.eql('Double');
      });

      it('has a name input', function () {
        expect(variable.nameValue()).to.eventually.eql('doubleVar');
      });

      it('has a value input', function () {
        expect(variable.valueValue()).to.eventually.eql('12.34');
      });
    });

    describe('Integer variable', function () {
      before(function () {
        variable = page.variable('#example-1', 5);
      });

      it('has a dropdown', function () {
        expect(variable.typeDropdownText()).to.eventually.eql('Integer');
      });

      it('has a name input', function () {
        expect(variable.nameValue()).to.eventually.eql('integerVar');
      });

      it('has a value input', function () {
        expect(variable.valueValue()).to.eventually.eql('1337');
      });
    });

    describe('Long variable', function () {
      before(function () {
        variable = page.variable('#example-1', 6);
      });

      it('has a dropdown', function () {
        expect(variable.typeDropdownText()).to.eventually.eql('Long');
      });

      it('has a name input', function () {
        expect(variable.nameValue()).to.eventually.eql('longVar');
      });

      it('has a value input', function () {
        expect(variable.valueValue()).to.eventually.eql('-100000000');
      });
    });

    describe('Null variable', function () {
      before(function () {
        variable = page.variable('#example-1', 7);
      });

      it('has a dropdown', function () {
        expect(variable.typeDropdownText()).to.eventually.eql('Null');
      });

      it('has a name input', function () {
        expect(variable.nameValue()).to.eventually.eql('nullVar');
      });

      xit('has a value input', function () {
        expect(variable.valueValue()).to.eventually.eql('null');
      });
    });

    xdescribe('Object variable', function () {
      before(function () {
        variable = page.variable('#example-1', 8);
      });

      it('has a dropdown', function () {
        expect(variable.typeDropdownText()).to.eventually.eql('Object');
      });

      it('has a name input', function () {
        expect(variable.nameValue()).to.eventually.eql('objectVar');
      });

      describe('value input', function () {
        it('has a button to open a dialog', function () {
          expect(variable.name().element(by.css('.btn')).isPresent()).to.eventually.eql(true);
        });
      });
    });

    describe('Short variable', function () {
      before(function () {
        variable = page.variable('#example-1', 9);
      });

      it('has a dropdown', function () {
        expect(variable.typeDropdownText()).to.eventually.eql('Short');
      });

      it('has a name input', function () {
        expect(variable.nameValue()).to.eventually.eql('shortVar');
      });

      it('has a value input', function () {
        expect(variable.valueValue()).to.eventually.eql('-32768');
      });
    });

    describe('String variable', function () {
      before(function () {
        variable = page.variable('#example-1', 10);
      });

      it('has a dropdown', function () {
        expect(variable.typeDropdownText()).to.eventually.eql('String');
      });

      it('has a name input', function () {
        expect(variable.nameValue()).to.eventually.eql('stringVar');
      });

      it('has a value input', function () {
        expect(variable.valueValue()).to.eventually.eql('Some string value');
      });
    });
  });

  xdescribe('display', function () {
    describe('when value is set', function () {
      before(function () {
        browser.get(pageUrl + '#example-2');
        variable = page.variable('#example-2', 1);
      });
    });
  });

  describe('partially shown', function () {
    describe('when value is set', function () {
      before(function () {
        browser.get(pageUrl + '#example-3');
      });

      it('shows the name and value', function () {
        variable = page.variable('#example-3', 0);
        expect(variable.nameValue()).to.eventually.eql('stringVar');
        expect(variable.valueValue()).to.eventually.eql('Some string value');
      });

      it('shows the type and value', function () {
        variable = page.variable('#example-3', 1);
        expect(variable.typeDropdownText()).to.eventually.eql('String');
        expect(variable.valueValue()).to.eventually.eql('Some string value');
      });

      it('shows the type and name', function () {
        variable = page.variable('#example-3', 2);
        expect(variable.typeDropdownText()).to.eventually.eql('String');
        expect(variable.nameValue()).to.eventually.eql('stringVar');
      });
    });
  });
});
<|endoftext|>


<commit_before>/**
 * The Cartodb map layer module.
 * @return CartoDBLayerClass (extends LayerClass).
 */
define([
  'underscore',
  'uri',
  'abstract/layer/OverlayLayerClass',
  'text!map/cartocss/style.cartocss',
  'text!map/templates/infowindow.handlebars'
], function(_, UriTemplate, OverlayLayerClass, CARTOCSS, TPL) {

  'use strict';

  var CartoDBLayerClass = OverlayLayerClass.extend({

    defaults: {
      user_name: 'wri-01',
      type: 'cartodb',
      sql: null,
      cartocss: CARTOCSS,
      interactivity: 'cartodb_id, name',
      infowindow: false,
      cartodb_logo: false,
      analysis: false
    },

    queryTemplate: 'SELECT cartodb_id||\':\' ||\'{tableName}\' as cartodb_id, the_geom_webmercator,' +
      '\'{tableName}\' AS layer, {analysis} AS analysis, name FROM {tableName}',

    _getLayer: function() {
      var deferred = new $.Deferred();

      var cartodbOptions = {
        name: this.name,
        type: this.options.type,
        cartodb_logo: this.options.cartodb_logo,
        user_name: this.options.user_name,
        sublayers: [{
          sql: this.getQuery(),
          cartocss: this.options.cartocss,
          interactivity: this.options.interactivity
        }]
      };

      cartodb.createLayer(this.map, cartodbOptions)
        .on('done',
          _.bind(function(layer) {
            this.cdbLayer = layer;
            deferred.resolve(this.cdbLayer);
          }, this)
        );

      return deferred.promise();
    },

    updateTiles: function() {
      this.cdbLayer.setQuery(this.getQuery());
    },

    /**
     * Create a CartodDB infowindow object
     * and add to CartoDB layer
     *
     * @return {object}
     */
    setInfowindow: function() {
      this.infowindow = cdb.vis.Vis.addInfowindow(this.map, this.cdbLayer.getSubLayer(0), this.options.interactivity, {
        infowindowTemplate: TPL,
        templateType: 'handlebars',
      });
      this.infowindow.model.on('change:visibility', function(model) {
        if (model.get('visibility')) {
          $('.cartodb-popup').toggleClass('dont_analyze', $('#analysis').hasClass('disabled'));
        }
      });
    },

    removeInfowindow: function() {
      if (this.infowindow) {
        this.infowindow.remove();
      }
    },

    /**
     * Get the CartoDB query. If it isn't set on this.options,
     * it gets the default query from this._queryTemplate.
     *
     * @return {string} CartoDB query
     */
    getQuery: function() {
      return new UriTemplate(this.options.sql || this.queryTemplate)
        .fillFromObject({tableName: this.layer.table_name, analysis: this.options.analysis});
    }

  });

  return CartoDBLayerClass;
});
<commit_msg>Map: make sure that cartodblayer exist before set query<commit_after>/**
 * The Cartodb map layer module.
 * @return CartoDBLayerClass (extends LayerClass).
 */
define([
  'underscore',
  'uri',
  'abstract/layer/OverlayLayerClass',
  'text!map/cartocss/style.cartocss',
  'text!map/templates/infowindow.handlebars'
], function(_, UriTemplate, OverlayLayerClass, CARTOCSS, TPL) {

  'use strict';

  var CartoDBLayerClass = OverlayLayerClass.extend({

    defaults: {
      user_name: 'wri-01',
      type: 'cartodb',
      sql: null,
      cartocss: CARTOCSS,
      interactivity: 'cartodb_id, name',
      infowindow: false,
      cartodb_logo: false,
      analysis: false
    },

    queryTemplate: 'SELECT cartodb_id||\':\' ||\'{tableName}\' as cartodb_id, the_geom_webmercator,' +
      '\'{tableName}\' AS layer, {analysis} AS analysis, name FROM {tableName}',

    _getLayer: function() {
      var deferred = new $.Deferred();

      var cartodbOptions = {
        name: this.name,
        type: this.options.type,
        cartodb_logo: this.options.cartodb_logo,
        user_name: this.options.user_name,
        sublayers: [{
          sql: this.getQuery(),
          cartocss: this.options.cartocss,
          interactivity: this.options.interactivity
        }]
      };

      cartodb.createLayer(this.map, cartodbOptions)
        .on('done',
          _.bind(function(layer) {
            this.cdbLayer = layer;
            deferred.resolve(this.cdbLayer);
          }, this)
        );

      return deferred.promise();
    },

    updateTiles: function() {
      if (this.cdbLayer) {
        this.cdbLayer.setQuery(this.getQuery());
      }
    },

    /**
     * Create a CartodDB infowindow object
     * and add to CartoDB layer
     *
     * @return {object}
     */
    setInfowindow: function() {
      this.infowindow = cdb.vis.Vis.addInfowindow(this.map, this.cdbLayer.getSubLayer(0), this.options.interactivity, {
        infowindowTemplate: TPL,
        templateType: 'handlebars',
      });
      this.infowindow.model.on('change:visibility', function(model) {
        if (model.get('visibility')) {
          $('.cartodb-popup').toggleClass('dont_analyze', $('#analysis').hasClass('disabled'));
        }
      });
    },

    removeInfowindow: function() {
      if (this.infowindow) {
        this.infowindow.remove();
      }
    },

    /**
     * Get the CartoDB query. If it isn't set on this.options,
     * it gets the default query from this._queryTemplate.
     *
     * @return {string} CartoDB query
     */
    getQuery: function() {
      return new UriTemplate(this.options.sql || this.queryTemplate)
        .fillFromObject({tableName: this.layer.table_name, analysis: this.options.analysis});
    }

  });

  return CartoDBLayerClass;
});
<|endoftext|>


<commit_before>/**
 * The LayerSelectionView view.
 *
 * @return LayerSelectionView view (extends Backbone.View)
 */
define([
  'underscore',
  'handlebars',
  'mps',
  'core/View',
  'map/services/LayerSpecService',
  'map/services/CountryService',
  'text!connect/templates/countrySelection.handlebars',
  'text!connect/templates/layerSelection.handlebars',
], function(_, Handlebars, mps, View, LayerSpecService, CountryService, countryTpl, layerTpl) {

  'use strict';

  var LayerSelectionView = View.extend({
    model: new (Backbone.Model.extend({
      country: null,
      layers: null,
      layerSelectId: null
    })),

    el: '#layer-selection',

    templateCountries: Handlebars.compile(countryTpl),
    templateLayers: Handlebars.compile(layerTpl),

    events: {
      'change .js-select-country' : 'onChangeCountry',
      'change .js-select-layer' : 'onChangeLayer',
    },

    initialize: function(map) {
      if (!this.$el.length) {
        return;
      }

      View.prototype.initialize.apply(this);

      this.map = map;
      this.cache();
      this.listeners();

      // Load global layers
      LayerSpecService._getAllLayers(
        // Filter
        function(layer){
          return !layer.iso && !!layer.analyzable;
        }.bind(this),

        // Success
        function(layers){
          this.layers = _.groupBy(_.sortBy(layers, 'title'), 'category_name');
          this.renderLayers();
        }.bind(this),

        // Error
        function(error){
          console.log(error);
        }.bind(this)
      );

      // Load countries
      CountryService.get()
        .then(function(results) {
          this.countries = results.countries;
          this.renderCountries();
          this.renderCountryLayers();
        }.bind(this))

        .error(function(error) {
          console.log(error);
        }.bind(this))
    },

    listeners: function() {
      this.listenTo(this.model, 'change:country', this.changeCountry.bind(this));
      this.listenTo(this.model, 'change:layers', this.changeLayers.bind(this));
      this.listenTo(this.model, 'change:layerSelectId', this.changeLayerSelectId.bind(this));
    },

    cache: function() {
      this.$layersField = this.$el.find('#layers-field');
      this.$layersCountryField = this.$el.find('#layers-country-field');
      this.$countryField = this.$el.find('#country-field');
    },

    /**
     * CHANGE EVENTS
    */
    changeCountry: function() {
      var country = this.model.get('country');

      LayerSpecService._getAllLayers(
        // Filter
        function(layer){
          return layer.iso == country && !!layer.analyzable;
        }.bind(this),

        // Success
        function(layers){
          this.countryLayers = _.groupBy(_.sortBy(layers, 'title'), 'category_name');
          this.renderCountryLayers();
        }.bind(this),

        // Error
        function(error){
          console.log(error);
        }.bind(this)
      );

    },

    changeLayers: function() {
      var layers = this.model.get('layers');
      var where = [{ slug: layers[0] }];

      LayerSpecService._removeAllLayers();

      LayerSpecService.toggle(where,
        function(layerSpec) {
          mps.publish('LayerNav/change', [layerSpec]);
          mps.publish('Place/update', [{go: false}]);
        }.bind(this));
    },

    changeLayerSelectId: function() {
      var layerSelectId = this.model.get('layerSelectId');
      _.each(this.$el.find('select.js-select-layer'), function(select){
        var id = $(select).attr('id');

        if (id != layerSelectId) {
          $(select).val('').trigger('chosen:updated');
        }
      }.bind(this));
    },

    /**
     * RENDERS
    */
    renderCountries: function() {
      // Filter to show only the countries that have layers
      LayerSpecService._getAllLayers(
        // Filter
        function(layer){
          return !!layer.iso && !!layer.analyzable;
        }.bind(this),

        // Success
        function(layers){
          var isos = _.uniq(_.pluck(layers, 'iso'));

          this.$countryField.html(this.templateCountries({
            name: 'Select an area from a country-specific data set',
            placeholder: 'Select a country...',
            countries: _.filter(this.countries, function(country) {
              return (isos.indexOf(country.iso) != -1)
            })
          }));
          this.renderChosen();

        }.bind(this),

        // Error
        function(error){
          console.log(error);
        }.bind(this)
      );
    },

    renderLayers: function() {
      this.$layersField.html(this.templateLayers({
        id: 'select-layers',
        name: 'Select an area from a global data set',
        placeholder: 'Select a data set...',
        layers: this.layers,
        hint: 'Select an area by clicking a shape on the map'
      }));
      this.renderChosen();
    },

    renderCountryLayers: function() {
      this.$layersCountryField.html(this.templateLayers({
        id: 'select-country-layers',
        name: '',
        placeholder: 'Select a data set...',
        layers: (!_.isEmpty(this.countryLayers)) ? this.countryLayers : null,
        hint: ''
      }));
      this.renderChosen();
    },

    renderChosen: function() {
      _.each(this.$el.find('select'), function(select){
        var $select = $(select);
        if (! !!$select.data('chosen')) {
          $select.chosen({
            width: '100%',
            disable_search: true,
            allow_single_deselect: true,
            inherit_select_classes: true,
            no_results_text: "Oops, nothing found!"
          });
        }
      });
    },

    /**
     * UI EVENTS
     * - onChangeCountry
     * - onChangeLayer
    */
    onChangeCountry: function(e) {
      e && e.preventDefault();
      var country = $(e.currentTarget).val();
      this.model.set({
        country: country,
      });
    },

    onChangeLayer: function(e) {
      e && e.preventDefault();
      var layers = [$(e.currentTarget).val()];
      var id = $(e.currentTarget).attr('id');

      this.model.set({
        layers: _.clone(layers),
        layerSelectId: id
      });
    }
  });

  return LayerSelectionView;

});
<commit_msg>Subscriptions: only one layer selected at a time<commit_after>/**
 * The LayerSelectionView view.
 *
 * @return LayerSelectionView view (extends Backbone.View)
 */
define([
  'underscore',
  'handlebars',
  'mps',
  'core/View',
  'map/services/LayerSpecService',
  'map/services/CountryService',
  'text!connect/templates/countrySelection.handlebars',
  'text!connect/templates/layerSelection.handlebars',
], function(_, Handlebars, mps, View, LayerSpecService, CountryService, countryTpl, layerTpl) {

  'use strict';

  var LayerSelectionView = View.extend({
    model: new (Backbone.Model.extend({
      country: null,
      layers: null,
      layerSelectId: null
    })),

    el: '#layer-selection',

    templateCountries: Handlebars.compile(countryTpl),
    templateLayers: Handlebars.compile(layerTpl),

    events: {
      'change .js-select-country' : 'onChangeCountry',
      'change .js-select-layer' : 'onChangeLayer',
    },

    initialize: function(map) {
      if (!this.$el.length) {
        return;
      }

      View.prototype.initialize.apply(this);

      this.map = map;
      this.cache();
      this.listeners();

      // Load global layers
      LayerSpecService._getAllLayers(
        // Filter
        function(layer){
          return !layer.iso && !!layer.analyzable;
        }.bind(this),

        // Success
        function(layers){
          this.layers = _.groupBy(_.sortBy(layers, 'title'), 'category_name');
          this.renderLayers();
        }.bind(this),

        // Error
        function(error){
          console.log(error);
        }.bind(this)
      );

      // Load countries
      CountryService.get()
        .then(function(results) {
          this.countries = results.countries;
          this.renderCountries();
          this.renderCountryLayers();
        }.bind(this))

        .error(function(error) {
          console.log(error);
        }.bind(this))
    },

    listeners: function() {
      this.listenTo(this.model, 'change:country', this.changeCountry.bind(this));
      this.listenTo(this.model, 'change:layers', this.changeLayers.bind(this));
      this.listenTo(this.model, 'change:layerSelectId', this.changeLayerSelectId.bind(this));
    },

    cache: function() {
      this.$layersField = this.$el.find('#layers-field');
      this.$layersCountryField = this.$el.find('#layers-country-field');
      this.$countryField = this.$el.find('#country-field');
    },

    /**
     * CHANGE EVENTS
    */
    changeCountry: function() {
      var country = this.model.get('country');

      LayerSpecService._getAllLayers(
        // Filter
        function(layer){
          return layer.iso == country && !!layer.analyzable;
        }.bind(this),

        // Success
        function(layers){
          this.countryLayers = _.groupBy(_.sortBy(layers, 'title'), 'category_name');
          this.renderCountryLayers();
        }.bind(this),

        // Error
        function(error){
          console.log(error);
        }.bind(this)
      );

    },

    changeLayers: function() {
      var layers = this.model.get('layers');
      var where = [{ slug: layers[0] }];

      LayerSpecService._removeAllLayers();

      LayerSpecService.toggle(where,
        function(layerSpec) {
          mps.publish('LayerNav/change', [layerSpec]);
          mps.publish('Place/update', [{go: false}]);
        }.bind(this));
    },

    changeLayerSelectId: function() {
      var layerSelectId = this.model.get('layerSelectId');
      _.each(this.$el.find('select.js-select-layer'), function(select){
        var id = $(select).attr('id');

        if (id != layerSelectId) {
          $(select).val('').trigger('chosen:updated');
        }
      }.bind(this));
    },

    /**
     * RENDERS
    */
    renderCountries: function() {
      // Filter to show only the countries that have layers
      LayerSpecService._getAllLayers(
        // Filter
        function(layer){
          return !!layer.iso && !!layer.analyzable;
        }.bind(this),

        // Success
        function(layers){
          var isos = _.uniq(_.pluck(layers, 'iso'));

          this.$countryField.html(this.templateCountries({
            name: 'Select an area from a country-specific data set',
            placeholder: 'Select a country...',
            countries: _.filter(this.countries, function(country) {
              return (isos.indexOf(country.iso) != -1)
            })
          }));
          this.renderChosen();

        }.bind(this),

        // Error
        function(error){
          console.log(error);
        }.bind(this)
      );
    },

    renderLayers: function() {
      this.$layersField.html(this.templateLayers({
        id: 'select-layers',
        name: 'Select an area from a global data set',
        placeholder: 'Select a data set...',
        layers: this.layers,
        hint: 'Select an area by clicking a shape on the map'
      }));
      this.renderChosen();
    },

    renderCountryLayers: function() {
      this.$layersCountryField.html(this.templateLayers({
        id: 'select-country-layers',
        name: '',
        placeholder: 'Select a data set...',
        layers: (!_.isEmpty(this.countryLayers)) ? this.countryLayers : null,
        hint: ''
      }));
      this.renderChosen();
    },

    renderChosen: function() {
      _.each(this.$el.find('select'), function(select){
        var $select = $(select);
        if (! !!$select.data('chosen')) {
          $select.chosen({
            width: '100%',
            disable_search: true,
            allow_single_deselect: true,
            inherit_select_classes: true,
            no_results_text: "Oops, nothing found!"
          });
        }
      });
    },

    /**
     * UI EVENTS
     * - onChangeCountry
     * - onChangeLayer
    */
    onChangeCountry: function(e) {
      e && e.preventDefault();
      var country = $(e.currentTarget).val();
      this.model.set({
        country: country,
        layers: (! !!country) ? [] : this.model.get('layers')
        // layers: [],
      });
    },

    onChangeLayer: function(e) {
      e && e.preventDefault();
      var layers = [$(e.currentTarget).val()];
      var id = $(e.currentTarget).attr('id');

      this.model.set({
        layers: _.clone(layers),
        layerSelectId: id
      });
    }
  });

  return LayerSelectionView;

});
<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import GenericLoader from '../components/GenericLoader';
import {apiFetchJson} from '../helpers/apiFetchJson';
import moment from 'moment';
import _ from 'lodash';
import {toMomentFromTimestamp} from '../helpers/toMoment';
import SectionHeading from '../components/SectionHeading';

export default class LoginActivityPage extends React.Component {
  constructor(props) {
    super(props);

    this.fetchLoginActivities = this.fetchLoginActivities.bind(this);
    this.renderPage = this.renderPage.bind(this);
    this.pastThirtyDaysArray = this.pastThirtyDaysArray.bind(this);
    this.structureLoginActivityJson = this.structureLoginActivityJson.bind(this);
    this.renderCellForDay = this.renderCellForDay.bind(this);
    this.renderEmptyCellForDay = this.renderEmptyCellForDay.bind(this);
    this.renderSuccessfulLoginListItem = this.renderSuccessfulLoginListItem.bind(this);
    this.renderFailedAttemptListItem = this.renderFailedAttemptListItem.bind(this);
  }

  fetchLoginActivities() {
    const {queryStartTimestamp, queryEndTimestamp} = this.props;

    const endpoint = '/api/login_activity';
    const params = `?created_at_or_before=${queryEndTimestamp}&created_after=${queryStartTimestamp}`;
    const url = endpoint + params;

    return apiFetchJson(url);
  }

  structureLoginActivityJson(loginActivityJson) {
    const toMoment = loginActivityJson.map((activity) => {
      return {...activity, ...{created_at: toMomentFromTimestamp(activity.created_at)}};
    });

    // Group activities by email identity
    const byEmail = _.groupBy(toMoment, 'identity');

    // Iterate through each identity and group login activity by day
    _.forOwn(byEmail, (value, key, collection) => {
      collection[key] = _.groupBy(value, (activity) => {
        return activity.created_at.clone().startOf('day').format();
      });
    });

    return byEmail;
  }

  pastThirtyDaysArray() {
    const emptyArray = new Array(30);
    emptyArray.fill(0);

    const pastThirtyDays = emptyArray.map((value, index) => {
      return moment.utc().subtract(index, 'days').startOf('day').format();
    });

    return pastThirtyDays;
  }

  render() {
    return (
      <GenericLoader
        promiseFn={this.fetchLoginActivities}
        render={this.renderPage} />
    );
  }

  renderPage(loginActivityJson) {
    // Shape of the data:
    // {
    //   "uri@demo.studentinsights.org": {
    //     "Thu Jul 19 2018 00:00:00 GMT+0000": {
    //       "fail": 4,
    //       "success": 2
    //     }
    //   },
    //   "vivian@demo.studentinsights.org": {
    //     "Thu Jul 19 2018 00:00:00 GMT+0000": {
    //       "fail": 2,
    //       "success": 1
    //     }
    //   }
    // }

    const structuredData = this.structureLoginActivityJson(loginActivityJson);
    const emails = Object.keys(structuredData);
    const pastThirtyDaysArray = this.pastThirtyDaysArray();

    return (

        <SectionHeading>Login Attempts, Past 30 days</SectionHeading>

          {this.renderHeaderRow()}
          {emails.map((email, index) => {
            return this.renderRow(email, index, structuredData[email], pastThirtyDaysArray);
          })}

    );
  }

  renderHeaderRow() {
    const pastThirtyDaysArray = this.pastThirtyDaysArray();

    return (

        {pastThirtyDaysArray.map((day, index) => {
          return (

              {moment(day).utc().format('D/M')}

          );
        })}

    );
  }

  renderRow(email, index, loginData, pastThirtyDaysArray) {
    const emailDisplay = (email === 'null') /* null cast to string by _.groupBy */
      ? 'No email (often means user timeout)'
      : email.substring(0, 35);

    return (

{emailDisplay}

        {pastThirtyDaysArray.map((day, index) => {
          return (loginData[day])
            ? this.renderCellForDay(email, index, loginData[day], day)
            : this.renderEmptyCellForDay(index);
        })}

    );
  }

  renderCellForDay(email, index, data, day) {
    const successfulAttempts = data.filter(d => d.success);
    const failedAttempts = data.filter(d => d.success);

    return (

        {this.renderTooltipText(email, successfulAttempts, failedAttempts, day)}
        {this.renderSuccessLoginSegment(successfulAttempts)}
        {this.renderFailLoginSegment(failedAttempts)}

    );
  }

  renderTooltipText(email, successfulAttempts, failedAttempts, day) {
    const emailDisplay = (email === 'null') /* null cast to string by _.groupBy */
      ? 'No email'
      : email.split('@')[0];

    return (

{[emailDisplay, moment(day).utc().format('D/M')].join(', ')}

        {this.renderSuccessfulLoginList(successfulAttempts)}
        {this.renderFailedAttemptList(failedAttempts)}

    );
  }

  renderSuccessfulLoginList(successfulAttempts) {
    if (successfulAttempts.length === 0) return null;

    return (

Successful login activity:

        {successfulAttempts.map((item, index) => {
          return this.renderSuccessfulLoginListItem(item, index);
        }, this)}

    );
  }

  renderFailedAttemptList(failedAttempts) {
    if (failedAttempts.length === 0) return null;

    return (

Failed login activity:

        {failedAttempts.map((item, index) => {
          return this.renderFailedAttemptListItem(item, index);
        }, this)}

    );
  }

  renderSuccessfulLoginListItem (item, index) {
    return (

        {item.created_at.local().format('h:mm A')}

    );
  }

  renderFailedAttemptListItem (item, index) {
    return (

        {item.created_at.local().format('h:mm A')} – {item.failure_reason}

    );
  }

  renderSuccessLoginSegment(successfulAttempts) {
    const count = successfulAttempts.length;
    const baseHex = '#329fff';
    const divStyle = {
      ...style.cellSegment, ...{backgroundColor: baseHex, opacity: count / 10},
    };

    return (

    );
  }

  renderFailLoginSegment(failedAttempts) {
    const count = failedAttempts.length;
    const baseHex = '#CD6000';
    const divStyle = {
      ...style.cellSegment, ...{backgroundColor: baseHex, opacity: count / 10},
    };

    return (

    );
  }

  renderEmptyCellForDay(index) {
    return (

);
  }
}

LoginActivityPage.propTypes = {
  queryStartTimestamp: PropTypes.string.isRequired,
  queryEndTimestamp: PropTypes.string.isRequired,
};

const style = {
  wrapper: {
    padding: '20px 40px',
  },
  container: {
    marginTop: 50,
    marginLeft: 10,
    minWidth: 1060,
  },
  row: {
    clear: 'both',
  },
  headerDateCell: {
    transform: 'rotate(-45deg)',
    border: 'none',
    fontSize: 12,
  },
  cell: {
    height: 25,
    border: '1px solid #ccc',
    margin: '-1px 0 0 -1px',
    float: 'left',
    display: 'flex',
  },
  cellSegment: {
    flex: 1,
  },
  emailCell: {
    float: 'left',
    padding: 2,
    width: 340,
  },
  squareCell: {
    width: 25,
    float: 'left',
  },
  li: {
    listStyleType: 'none',
  }
};

<commit_msg>Fix failed filter<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import GenericLoader from '../components/GenericLoader';
import {apiFetchJson} from '../helpers/apiFetchJson';
import moment from 'moment';
import _ from 'lodash';
import {toMomentFromTimestamp} from '../helpers/toMoment';
import SectionHeading from '../components/SectionHeading';

export default class LoginActivityPage extends React.Component {
  constructor(props) {
    super(props);

    this.fetchLoginActivities = this.fetchLoginActivities.bind(this);
    this.renderPage = this.renderPage.bind(this);
    this.pastThirtyDaysArray = this.pastThirtyDaysArray.bind(this);
    this.structureLoginActivityJson = this.structureLoginActivityJson.bind(this);
    this.renderCellForDay = this.renderCellForDay.bind(this);
    this.renderEmptyCellForDay = this.renderEmptyCellForDay.bind(this);
    this.renderSuccessfulLoginListItem = this.renderSuccessfulLoginListItem.bind(this);
    this.renderFailedAttemptListItem = this.renderFailedAttemptListItem.bind(this);
  }

  fetchLoginActivities() {
    const {queryStartTimestamp, queryEndTimestamp} = this.props;

    const endpoint = '/api/login_activity';
    const params = `?created_at_or_before=${queryEndTimestamp}&created_after=${queryStartTimestamp}`;
    const url = endpoint + params;

    return apiFetchJson(url);
  }

  structureLoginActivityJson(loginActivityJson) {
    const toMoment = loginActivityJson.map((activity) => {
      return {...activity, ...{created_at: toMomentFromTimestamp(activity.created_at)}};
    });

    // Group activities by email identity
    const byEmail = _.groupBy(toMoment, 'identity');

    // Iterate through each identity and group login activity by day
    _.forOwn(byEmail, (value, key, collection) => {
      collection[key] = _.groupBy(value, (activity) => {
        return activity.created_at.clone().startOf('day').format();
      });
    });

    return byEmail;
  }

  pastThirtyDaysArray() {
    const emptyArray = new Array(30);
    emptyArray.fill(0);

    const pastThirtyDays = emptyArray.map((value, index) => {
      return moment.utc().subtract(index, 'days').startOf('day').format();
    });

    return pastThirtyDays;
  }

  render() {
    return (
      <GenericLoader
        promiseFn={this.fetchLoginActivities}
        render={this.renderPage} />
    );
  }

  renderPage(loginActivityJson) {
    // Shape of the data:
    // {
    //   "uri@demo.studentinsights.org": {
    //     "Thu Jul 19 2018 00:00:00 GMT+0000": {
    //       "fail": 4,
    //       "success": 2
    //     }
    //   },
    //   "vivian@demo.studentinsights.org": {
    //     "Thu Jul 19 2018 00:00:00 GMT+0000": {
    //       "fail": 2,
    //       "success": 1
    //     }
    //   }
    // }

    const structuredData = this.structureLoginActivityJson(loginActivityJson);
    const emails = Object.keys(structuredData);
    const pastThirtyDaysArray = this.pastThirtyDaysArray();

    return (

        <SectionHeading>Login Attempts, Past 30 days</SectionHeading>

          {this.renderHeaderRow()}
          {emails.map((email, index) => {
            return this.renderRow(email, index, structuredData[email], pastThirtyDaysArray);
          })}

    );
  }

  renderHeaderRow() {
    const pastThirtyDaysArray = this.pastThirtyDaysArray();

    return (

        {pastThirtyDaysArray.map((day, index) => {
          return (

              {moment(day).utc().format('D/M')}

          );
        })}

    );
  }

  renderRow(email, index, loginData, pastThirtyDaysArray) {
    const emailDisplay = (email === 'null') /* null cast to string by _.groupBy */
      ? 'No email (often means user timeout)'
      : email.substring(0, 35);

    return (

{emailDisplay}

        {pastThirtyDaysArray.map((day, index) => {
          return (loginData[day])
            ? this.renderCellForDay(email, index, loginData[day], day)
            : this.renderEmptyCellForDay(index);
        })}

    );
  }

  renderCellForDay(email, index, data, day) {
    const successfulAttempts = data.filter(d => d.success);
    const failedAttempts = data.filter(d => !d.success);

    return (

        {this.renderTooltipText(email, successfulAttempts, failedAttempts, day)}
        {this.renderSuccessLoginSegment(successfulAttempts)}
        {this.renderFailLoginSegment(failedAttempts)}

    );
  }

  renderTooltipText(email, successfulAttempts, failedAttempts, day) {
    const emailDisplay = (email === 'null') /* null cast to string by _.groupBy */
      ? 'No email'
      : email.split('@')[0];

    return (

{[emailDisplay, moment(day).utc().format('D/M')].join(', ')}

        {this.renderSuccessfulLoginList(successfulAttempts)}
        {this.renderFailedAttemptList(failedAttempts)}

    );
  }

  renderSuccessfulLoginList(successfulAttempts) {
    if (successfulAttempts.length === 0) return null;

    return (

Successful login activity:

        {successfulAttempts.map((item, index) => {
          return this.renderSuccessfulLoginListItem(item, index);
        }, this)}

    );
  }

  renderFailedAttemptList(failedAttempts) {
    if (failedAttempts.length === 0) return null;

    return (

Failed login activity:

        {failedAttempts.map((item, index) => {
          return this.renderFailedAttemptListItem(item, index);
        }, this)}

    );
  }

  renderSuccessfulLoginListItem (item, index) {
    return (

        {item.created_at.local().format('h:mm A')}

    );
  }

  renderFailedAttemptListItem (item, index) {
    return (

        {item.created_at.local().format('h:mm A')} – {item.failure_reason}

    );
  }

  renderSuccessLoginSegment(successfulAttempts) {
    const count = successfulAttempts.length;
    const baseHex = '#329fff';
    const divStyle = {
      ...style.cellSegment, ...{backgroundColor: baseHex, opacity: count / 10},
    };

    return (

    );
  }

  renderFailLoginSegment(failedAttempts) {
    const count = failedAttempts.length;
    const baseHex = '#CD6000';
    const divStyle = {
      ...style.cellSegment, ...{backgroundColor: baseHex, opacity: count / 10},
    };

    return (

    );
  }

  renderEmptyCellForDay(index) {
    return (

);
  }
}

LoginActivityPage.propTypes = {
  queryStartTimestamp: PropTypes.string.isRequired,
  queryEndTimestamp: PropTypes.string.isRequired,
};

const style = {
  wrapper: {
    padding: '20px 40px',
  },
  container: {
    marginTop: 50,
    marginLeft: 10,
    minWidth: 1060,
  },
  row: {
    clear: 'both',
  },
  headerDateCell: {
    transform: 'rotate(-45deg)',
    border: 'none',
    fontSize: 12,
  },
  cell: {
    height: 25,
    border: '1px solid #ccc',
    margin: '-1px 0 0 -1px',
    float: 'left',
    display: 'flex',
  },
  cellSegment: {
    flex: 1,
  },
  emailCell: {
    float: 'left',
    padding: 2,
    width: 340,
  },
  squareCell: {
    width: 25,
    float: 'left',
  },
  li: {
    listStyleType: 'none',
  }
};

<|endoftext|>


<commit_before>jQuery.widget('pageflow.playerControls', {
  _create: function() {
    var player = this.options.player;

    var playButton = this.element.find('.vjs-play-control');
    var progressHolder = this.element.find('.vjs-progress-holder');
    var playProgress = this.element.find('.vjs-play-progress');
    var currentTimeDisplay = this.element.find('.vjs-current-time-display');
    var durationDisplay = this.element.find('.vjs-duration-display');
    var progressHandler = this.element.find('.vjs-slider-handle');
    var seeking = false;
    var smallTimestamp = durationDisplay.html().length === 5 && durationDisplay.html().charAt(0) === "0";

    if(smallTimestamp) {
      durationDisplay.html("0:00");
      currentTimeDisplay.html(currentTimeDisplay.html().substr(1));
    }
    else {
      durationDisplay.html("00:00");
    }

    player.on('timeupdate', function (position, duration) {
      var percent = duration > 0 ? (player.position / player.duration) * 100 : 0;

      if (!isNaN(position)) {
        if (player.duration < 600) {
          $(currentTimeDisplay).html(player.formatTime(position).substr(1));
          $(durationDisplay).html(player.formatTime(duration).substr(1));
        }
        else {
          $(currentTimeDisplay).html(player.formatTime(position));
          $(durationDisplay).html(player.formatTime(duration));
        }
      }

      var handlerLeft = ((progressHolder.width() - progressHandler.width()) * percent / 100);

      progressHandler.css({left: handlerLeft + 'px'});
      playProgress.css({width: percent + "%"});
    });

    player.on('play', function (position, duration) {
      $(playButton).removeClass('vjs-play');
      $(playButton).addClass('vjs-pause vjs-playing');
    });

    player.on('pause', function (position, duration) {
      $(playButton).removeClass('vjs-pause vjs-playing');
      $(playButton).addClass('vjs-play');
    });

    player.on('ended', function (position, duration) {
      $(playButton).removeClass('vjs-pause vjs-playing');
      $(playButton).addClass('vjs-play');
    });

    function togglePlay() {
      if (player.playing) {
        player.pause();
      }
      else {
        player.play();
      }
    }

    playButton.on({
      'mousedown touchstart': function() {
        $(this).addClass('pressed');
      },
      'mouseup touchend': function() {
        $(this).removeClass('pressed');
      },
      'click': function() {
        togglePlay();
      },
      'keypress': function(e) {
        if (e.which == 13) {
          var that = this;

          togglePlay();
          setTimeout(function() {
            $(that).focus();
          }, 20);
        }
      }
    });

    $(progressHolder).on('mousedown touchstart', function(event) {
      var newProgress = (event.pageX - $(progressHolder).offset().left) / $(progressHolder).width();
      player.seek(newProgress * player.duration);

      $('body').on({
        'mousemove touchmove': onMouseMove,
        'mouseup touchend': onMouseUp
      });

      function onMouseMove(event) {
        var pageX;
        if(event.originalEvent.changedTouches || event.originalEvent.touches) {
          pageX = event.originalEvent.changedTouches[0].pageX || event.originalEvent.touches[0].pageX;
        } else {
          pageX = event.pageX;
        }
        var newProgress = (pageX - $(progressHolder).offset().left) / $(progressHolder).width();

        if (newProgress > 1) { newProgress = 1; }
        if (newProgress < 0) { newProgress = 0; }

        player.seek(newProgress * player.duration);
      }

      function onMouseUp() {
        $('body').off({
          'mousemove touchmove': onMouseMove,
          'mouseup touchend': onMouseUp
        });
      }
    });
  }
});<commit_msg>Fix player controls seek on touch devices<commit_after>jQuery.widget('pageflow.playerControls', {
  _create: function() {
    var player = this.options.player;

    var playButton = this.element.find('.vjs-play-control');
    var progressHolder = this.element.find('.vjs-progress-holder');
    var playProgress = this.element.find('.vjs-play-progress');
    var currentTimeDisplay = this.element.find('.vjs-current-time-display');
    var durationDisplay = this.element.find('.vjs-duration-display');
    var progressHandler = this.element.find('.vjs-slider-handle');
    var seeking = false;
    var smallTimestamp = durationDisplay.html().length === 5 && durationDisplay.html().charAt(0) === "0";

    if(smallTimestamp) {
      durationDisplay.html("0:00");
      currentTimeDisplay.html(currentTimeDisplay.html().substr(1));
    }
    else {
      durationDisplay.html("00:00");
    }

    player.on('timeupdate', function (position, duration) {
      var percent = duration > 0 ? (player.position / player.duration) * 100 : 0;

      if (!isNaN(position)) {
        if (player.duration < 600) {
          $(currentTimeDisplay).html(player.formatTime(position).substr(1));
          $(durationDisplay).html(player.formatTime(duration).substr(1));
        }
        else {
          $(currentTimeDisplay).html(player.formatTime(position));
          $(durationDisplay).html(player.formatTime(duration));
        }
      }

      var handlerLeft = ((progressHolder.width() - progressHandler.width()) * percent / 100);

      progressHandler.css({left: handlerLeft + 'px'});
      playProgress.css({width: percent + "%"});
    });

    player.on('play', function (position, duration) {
      $(playButton).removeClass('vjs-play');
      $(playButton).addClass('vjs-pause vjs-playing');
    });

    player.on('pause', function (position, duration) {
      $(playButton).removeClass('vjs-pause vjs-playing');
      $(playButton).addClass('vjs-play');
    });

    player.on('ended', function (position, duration) {
      $(playButton).removeClass('vjs-pause vjs-playing');
      $(playButton).addClass('vjs-play');
    });

    function togglePlay() {
      if (player.playing) {
        player.pause();
      }
      else {
        player.play();
      }
    }

    playButton.on({
      'mousedown touchstart': function() {
        $(this).addClass('pressed');
      },
      'mouseup touchend': function() {
        $(this).removeClass('pressed');
      },
      'click': function() {
        togglePlay();
      },
      'keypress': function(e) {
        if (e.which == 13) {
          var that = this;

          togglePlay();
          setTimeout(function() {
            $(that).focus();
          }, 20);
        }
      }
    });

    $(progressHolder).on('mousedown touchstart', function(event) {
      player.seek(getSeekPosition(event));

      $('body').on({
        'mousemove touchmove': onMouseMove,
        'mouseup touchend': onMouseUp
      });

      function onMouseMove(event) {
        player.seek(getSeekPosition(event));
      }

      function onMouseUp() {
        $('body').off({
          'mousemove touchmove': onMouseMove,
          'mouseup touchend': onMouseUp
        });
      }

      function getSeekPosition(event) {
        var position = getPointerPageX(event) - $(progressHolder).offset().left;
        var fraction = position / $(progressHolder).width();

        return Math.min(Math.max(fraction, 0), 1) * player.duration;
      }

      function getPointerPageX(event) {
        if (event.originalEvent.changedTouches) {
          return event.originalEvent.changedTouches[0].pageX;
        } else {
          return event.pageX;
        }
      }
    });
  }
});<|endoftext|>


<commit_before>// Representation of one object with its properties

'use strict';

var startsWith     = require('es5-ext/string/#/starts-with')
  , assign         = require('es5-ext/object/assign')
  , copy           = require('es5-ext/object/copy')
  , setPrototypeOf = require('es5-ext/object/set-prototype-of')
  , validValue     = require('es5-ext/object/valid-value')
  , d              = require('d')
  , autoBind       = require('d/auto-bind')
  , allOff         = require('event-emitter/lib/all-off')
  , Set            = require('observable-set/create-read-only')(
	require('observable-set/primitive')
)
  , serialize      = require('dbjs/_setup/serialize/object')

  , defineProperties = Object.defineProperties
  , Fragment, pass;

pass = function (rootObj, obj, sKey, rules) {
	var tree, current, deepPass, pass;
	if (rules['/'] === 2) deepPass = true;
	if (!obj.owner || (obj === rootObj)) {
		pass = rules[sKey];
		if (pass) return true;
		if (pass === 0) return false;
		if (deepPass) return true;
		return false;
	}
	tree = [sKey];
	do {
		tree.unshift(obj.__sKey__);
		obj = obj.owner;
	} while (obj.owner && (obj !== rootObj));
	current = tree.shift();
	while (true) {
		pass = rules[current];
		if (pass) {
			if (pass === 2) deepPass = true;
		} else {
			if (pass === 0) return false;
			if (!deepPass) return false;
		}
		sKey = tree.shift();
		if (!sKey) return true;
		current += '/' + sKey;
	}
};

module.exports = Fragment = function (obj, rules) {
	if (!(this instanceof Fragment)) return new Fragment(obj, rules);
	validValue(rules);
	Set.call(this);
	defineProperties(this, {
		__object__: d('', obj),
		__rules__: d('', rules)
	});
	if (obj._lastOwnEvent_) this.__setData__[obj.__id__] = obj;
	obj.master.on('update', this.onUpdate);
	this.onObject(obj);
};
setPrototypeOf(Fragment, Set);

Fragment.prototype = Object.create(Set.prototype, assign({
	_serialize: d(serialize),
	destroy: d(function () {
		var data;
		this.__object__.off('update', this.onUpdate);
		allOff(this);
		data = copy(this.__setData__);
		this._clear();
		return data;
	}),
	onObject: d(function (obj) {
		obj._forEachOwnDescriptor_(this.onDescriptor, this);
		obj._forEachOwnItem_(this.onItem, this);
		obj._forEachOwnNestedObject_(this.onObject, this);
	}),
	onDescriptor: d(function (desc) {
		var event;
		if (!pass(this.__object__, desc.object, desc._sKey_, this.__rules__)) {
			return;
		}
		event = desc._lastOwnEvent_;
		if (event && (event.value !== undefined)) {
			this.__setData__[desc.__id__] = desc;
		}
		desc._forEachOwnDescriptor_(this.onItem, this);
	}),
	onItem: d(function (obj) {
		var event;
		if (!pass(this.__object__, obj.object, obj._pSKey_, this.__rules__)) return;
		event = obj._lastOwnEvent_;
		if (!event) return;
		if (event.value === undefined) return;
		this.__setData__[obj.__id__] = obj;
	})
}, autoBind({
	onUpdate: d(function (event) {
		var obj = event.object, kind = obj._kind_;
		if (!startsWith.call(obj.__valueId__, this.__object__.__valueId__)) return;
		if (kind === 'descriptor') {
			if (!pass(this.__object__, obj.object, obj._sKey_, this.__rules__)) {
				return;
			}
		} else if (kind !== 'object') {
			if (!pass(this.__object__, obj.object, obj._pSKey_, this.__rules__)) {
				return;
			}
		}
		if (event.value === undefined) this._delete(obj);
		else this._add(obj);
		this.emit('update', event);
	})
})));
<commit_msg>Update up to changes in event-emitter package<commit_after>// Representation of one object with its properties

'use strict';

var startsWith     = require('es5-ext/string/#/starts-with')
  , assign         = require('es5-ext/object/assign')
  , copy           = require('es5-ext/object/copy')
  , setPrototypeOf = require('es5-ext/object/set-prototype-of')
  , validValue     = require('es5-ext/object/valid-value')
  , d              = require('d')
  , autoBind       = require('d/auto-bind')
  , allOff         = require('event-emitter/all-off')
  , Set            = require('observable-set/create-read-only')(
	require('observable-set/primitive')
)
  , serialize      = require('dbjs/_setup/serialize/object')

  , defineProperties = Object.defineProperties
  , Fragment, pass;

pass = function (rootObj, obj, sKey, rules) {
	var tree, current, deepPass, pass;
	if (rules['/'] === 2) deepPass = true;
	if (!obj.owner || (obj === rootObj)) {
		pass = rules[sKey];
		if (pass) return true;
		if (pass === 0) return false;
		if (deepPass) return true;
		return false;
	}
	tree = [sKey];
	do {
		tree.unshift(obj.__sKey__);
		obj = obj.owner;
	} while (obj.owner && (obj !== rootObj));
	current = tree.shift();
	while (true) {
		pass = rules[current];
		if (pass) {
			if (pass === 2) deepPass = true;
		} else {
			if (pass === 0) return false;
			if (!deepPass) return false;
		}
		sKey = tree.shift();
		if (!sKey) return true;
		current += '/' + sKey;
	}
};

module.exports = Fragment = function (obj, rules) {
	if (!(this instanceof Fragment)) return new Fragment(obj, rules);
	validValue(rules);
	Set.call(this);
	defineProperties(this, {
		__object__: d('', obj),
		__rules__: d('', rules)
	});
	if (obj._lastOwnEvent_) this.__setData__[obj.__id__] = obj;
	obj.master.on('update', this.onUpdate);
	this.onObject(obj);
};
setPrototypeOf(Fragment, Set);

Fragment.prototype = Object.create(Set.prototype, assign({
	_serialize: d(serialize),
	destroy: d(function () {
		var data;
		this.__object__.off('update', this.onUpdate);
		allOff(this);
		data = copy(this.__setData__);
		this._clear();
		return data;
	}),
	onObject: d(function (obj) {
		obj._forEachOwnDescriptor_(this.onDescriptor, this);
		obj._forEachOwnItem_(this.onItem, this);
		obj._forEachOwnNestedObject_(this.onObject, this);
	}),
	onDescriptor: d(function (desc) {
		var event;
		if (!pass(this.__object__, desc.object, desc._sKey_, this.__rules__)) {
			return;
		}
		event = desc._lastOwnEvent_;
		if (event && (event.value !== undefined)) {
			this.__setData__[desc.__id__] = desc;
		}
		desc._forEachOwnDescriptor_(this.onItem, this);
	}),
	onItem: d(function (obj) {
		var event;
		if (!pass(this.__object__, obj.object, obj._pSKey_, this.__rules__)) return;
		event = obj._lastOwnEvent_;
		if (!event) return;
		if (event.value === undefined) return;
		this.__setData__[obj.__id__] = obj;
	})
}, autoBind({
	onUpdate: d(function (event) {
		var obj = event.object, kind = obj._kind_;
		if (!startsWith.call(obj.__valueId__, this.__object__.__valueId__)) return;
		if (kind === 'descriptor') {
			if (!pass(this.__object__, obj.object, obj._sKey_, this.__rules__)) {
				return;
			}
		} else if (kind !== 'object') {
			if (!pass(this.__object__, obj.object, obj._pSKey_, this.__rules__)) {
				return;
			}
		}
		if (event.value === undefined) this._delete(obj);
		else this._add(obj);
		this.emit('update', event);
	})
})));
<|endoftext|>


<commit_before>/*
 * Copyright 2012-2013 inBloom, Inc. and its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

$(function() {

    $("#files").change(function(evt){
        importedFiles = evt.target.files;
        for (var i = 0,file; file = importedFiles[i]; i++) {

            reader = new FileReader();
            reader.onload = (function(theFile) {

                itemCounter = 0;
                // Uncheck everything when you add a new tag
                jQuery("#multiItemSelector input[type=checkbox]").each(function(i,obj) {
                    obj.checked = false;
                    itemCounter++;
                });

                return function(e) {
                    $("#loadModal").modal("hide");

                    // Uncheck everything when you add a new tag
                    jQuery("#multiItemSelector input[type=checkbox]").each(function(i,obj) {
                        obj.checked = false;
                    });
                    // Update the form
                    updateInputFields();

                    if (itemCounter == 0){
                        jQuery("#multiItemSelector").empty();
                    }

                    // Get all the results
                    var allText = e.target.result;

                    // Parse JSON input
                    if (allText[0] == "{") {

                        var output = JSON.parse(allText);

                        for (i in output) {
                            if (output[i] == undefined || output[i].length == 0) continue;

                            output[i].id = itemCounter;
                            items['itemTag' + itemCounter] = output[i];

                            var itemTitle = (output[i].title!='')? ((output[i].title.length > 25) ? output[i].title.substr(0,25) + '…' : output[i].title) :"New Item " + itemCounter;
                            var itemUrl = output[i].url;

                            for (objHash in output[i].educationalAlignments) {
                                if (alignments[objHash] == undefined) {
                                    $('.noAlignmentsYet').hide();
                                    alignments[objHash] = output[i].educationalAlignments[objHash];
                                    $('#currentAlignmentTable > tbody:last').append('
<input type="checkbox" class="alignment-checkbox" value="'+objHash+'" />'+ output[i].educationalAlignments[objHash].dotNotation +'	'+ capitalize(output[i].educationalAlignments[objHash].alignmentType) +'
');
                                }
                            }
                            $("#multiItemSelector").append($("     <input id='itemTag"+itemCounter+"' type='checkbox' name='tagItem'/>"+itemTitle+""));
                            itemCounter++;

                        }

                    }

                    // parse CSV input
                    if (allText[0] != '{') {

                        var tempItems = [];
                        var output = $.csv2Array(allText);

                        for (var i = 1; i < output.length; i++) {
                            if (fileHasErrors) continue;
                            if (output[i] == undefined || output[i].length == 0) continue;

                            var itemTitle = (output[i][1] != '' && output[i][1] != undefined)? ((output[i][1].length > 25) ? output[i][1].substr(0,25) + '…' : output[i][1]) :"New Item " + itemCounter;
                            var itemUrl = output[i][2];

                            // Parse the education alignments and use them, or create new ones.
                            var tempEducationAlignmentArray = output[i][17].split(",");
                            var tempAlignmentTypeArray = output[i][18].split(",");
                            var tempDotNotationArray = output[i][19].split(",");
                            var tempDescriptionArray = output[i][21].split(",");
                            var tempItemURLArray = output[i][20].split(",");

                            var itemEducationAlignments = {}
                            for (ea = 0; ea < tempEducationAlignmentArray.length; ea++) {
                                if (tempEducationAlignmentArray[ea] == '' ||
                                    tempAlignmentTypeArray[ea] == '' ||
                                    tempDescriptionArray[ea] == '' ||
                                    tempItemURLArray[ea] == '') continue;
                                var object = {
                                    'educationalAlignment' : tempEducationAlignmentArray[ea],
                                    'alignmentType' : tempAlignmentTypeArray[ea],
                                    'dotNotation' : tempDotNotationArray[ea],
                                    'description' : tempDescriptionArray[ea],
                                    'itemURL' : tempItemURLArray[ea]
                                };
                                var objHash = objectToHash(object);
                                if (alignments[objHash] == undefined) {
                                    $('.noAlignmentsYet').hide();
                                    alignments[objHash] = object;
                                    $('#currentAlignmentTable > tbody:last').append('
<input type="checkbox" class="alignment-checkbox" value="'+objHash+'" />'+ tempDotNotationArray[ea] +'	'+ capitalize(tempAlignmentTypeArray[ea]) +'
');
                                }

                                itemEducationAlignments[objHash] = object;
                            }

                            tempItem = {
                                'id'                    : itemCounter,
                                'title'                 : validateImport('title', output[i][1]),
                                'language'              : validateImport('language', output[i][8]),
                                'thumbnail'             : validateImport('thumbnail', output[i][23]),
                                'url'                   : validateImport('url', itemUrl),
                                'tagDescription'        : validateImport('tagDescription', output[i][24]),
                                'createdOn'             : validateImport('createdOn', output[i][5]),
                                'topic'                 : validateImport('topic', output[i][4]),
                                'createdBy'             : validateImport('createdBy', output[i][6]),
                                'usageRightsURL'        : validateImport('usageRightsURL', output[i][10]),
                                'publisher'             : validateImport('publisher', output[i][7]),
                                'isBasedOnURL'          : validateImport('isBasedOnURL', output[i][11]),
                                'endUser'               : validateImport('endUser', output[i][12]),
                                'ageRange'              : validateImport('ageRange', output[i][14]),
                                'educationalUse'        : validateImport('educationalUse', output[i][13]),
                                'interactivityType'     : validateImport('interactivityType', output[i][15]),
                                'learningResourceType'  : validateImport('learningResourceType', output[i][16]),
                                'mediaType'             : validateImport('mediaType', output[i][9]),
                                'groupType'             : validateImport('groupType', output[i][22]),
                                'timeRequired'          : validateImport('timeRequired', output[i][3]),
                                'educationalAlignments' : itemEducationAlignments
                            };

                            // Did anything above generate an error?
                            if (fileHasErrors) {

                                var message = "No data could be imported. It looks like the file you're attempting to import had some column/row errors that Tagger doesn't understand.  Before this data can be imported you'll need to correct the following errors so that we don't import something incorrectly:

" + fileErrors;

                                showMessage(message, "Import Errors! :: Errors found in row #"+i);
                            } else {
                                // Stuff the item
                                items['itemTag' + itemCounter] = tempItem;
                                // Inject the checkbox
                                $("#multiItemSelector").append($("     <input id='itemTag"+itemCounter+"' type='checkbox' name='tagItem'/>"+itemTitle+""));
                                // Increment the counter
                                itemCounter++;

                            }

                        }

                    }

                    updateResourceCount();

                }
            })(file);

            reader.readAsText(file);

            $("#fileForm")[0].reset();

        }
    });

});<commit_msg>Reset errors on each file import attempt<commit_after>/*
 * Copyright 2012-2013 inBloom, Inc. and its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

$(function() {

    $("#files").change(function(evt){
        importedFiles = evt.target.files;
        for (var i = 0,file; file = importedFiles[i]; i++) {

            reader = new FileReader();
            reader.onload = (function(theFile) {

                itemCounter = 0;
                // Uncheck everything when you add a new tag
                jQuery("#multiItemSelector input[type=checkbox]").each(function(i,obj) {
                    obj.checked = false;
                    itemCounter++;
                });

                return function(e) {
                    $("#loadModal").modal("hide");

                    // Reset any previous errors
                    fileHasErrors = false;
                    fileErrors = [];

                    // Uncheck everything when you add a new tag
                    jQuery("#multiItemSelector input[type=checkbox]").each(function(i,obj) {
                        obj.checked = false;
                    });
                    // Update the form
                    updateInputFields();

                    if (itemCounter == 0){
                        jQuery("#multiItemSelector").empty();
                    }

                    // Get all the results
                    var allText = e.target.result;

                    // Parse JSON input
                    if (allText[0] == "{") {

                        var output = JSON.parse(allText);

                        for (i in output) {
                            if (output[i] == undefined || output[i].length == 0) continue;

                            output[i].id = itemCounter;
                            items['itemTag' + itemCounter] = output[i];

                            var itemTitle = (output[i].title!='')? ((output[i].title.length > 25) ? output[i].title.substr(0,25) + '…' : output[i].title) :"New Item " + itemCounter;
                            var itemUrl = output[i].url;

                            for (objHash in output[i].educationalAlignments) {
                                if (alignments[objHash] == undefined) {
                                    $('.noAlignmentsYet').hide();
                                    alignments[objHash] = output[i].educationalAlignments[objHash];
                                    $('#currentAlignmentTable > tbody:last').append('
<input type="checkbox" class="alignment-checkbox" value="'+objHash+'" />'+ output[i].educationalAlignments[objHash].dotNotation +'	'+ capitalize(output[i].educationalAlignments[objHash].alignmentType) +'
');
                                }
                            }
                            $("#multiItemSelector").append($("     <input id='itemTag"+itemCounter+"' type='checkbox' name='tagItem'/>"+itemTitle+""));
                            itemCounter++;

                        }

                    }

                    // parse CSV input
                    if (allText[0] != '{') {

                        var tempItems = [];
                        var output = $.csv2Array(allText);

                        for (var i = 1; i < output.length; i++) {
                            if (fileHasErrors) continue;
                            if (output[i] == undefined || output[i].length == 0) continue;

                            var itemTitle = (output[i][1] != '' && output[i][1] != undefined)? ((output[i][1].length > 25) ? output[i][1].substr(0,25) + '…' : output[i][1]) :"New Item " + itemCounter;
                            var itemUrl = output[i][2];

                            // Parse the education alignments and use them, or create new ones.
                            var tempEducationAlignmentArray = output[i][17].split(",");
                            var tempAlignmentTypeArray = output[i][18].split(",");
                            var tempDotNotationArray = output[i][19].split(",");
                            var tempDescriptionArray = output[i][21].split(",");
                            var tempItemURLArray = output[i][20].split(",");

                            var itemEducationAlignments = {}
                            for (ea = 0; ea < tempEducationAlignmentArray.length; ea++) {
                                if (tempEducationAlignmentArray[ea] == '' ||
                                    tempAlignmentTypeArray[ea] == '' ||
                                    tempDescriptionArray[ea] == '' ||
                                    tempItemURLArray[ea] == '') continue;
                                var object = {
                                    'educationalAlignment' : tempEducationAlignmentArray[ea],
                                    'alignmentType' : tempAlignmentTypeArray[ea],
                                    'dotNotation' : tempDotNotationArray[ea],
                                    'description' : tempDescriptionArray[ea],
                                    'itemURL' : tempItemURLArray[ea]
                                };
                                var objHash = objectToHash(object);
                                if (alignments[objHash] == undefined) {
                                    $('.noAlignmentsYet').hide();
                                    alignments[objHash] = object;
                                    $('#currentAlignmentTable > tbody:last').append('
<input type="checkbox" class="alignment-checkbox" value="'+objHash+'" />'+ tempDotNotationArray[ea] +'	'+ capitalize(tempAlignmentTypeArray[ea]) +'
');
                                }

                                itemEducationAlignments[objHash] = object;
                            }

                            tempItem = {
                                'id'                    : itemCounter,
                                'title'                 : validateImport('title', output[i][1]),
                                'language'              : validateImport('language', output[i][8]),
                                'thumbnail'             : validateImport('thumbnail', output[i][23]),
                                'url'                   : validateImport('url', itemUrl),
                                'tagDescription'        : validateImport('tagDescription', output[i][24]),
                                'createdOn'             : validateImport('createdOn', output[i][5]),
                                'topic'                 : validateImport('topic', output[i][4]),
                                'createdBy'             : validateImport('createdBy', output[i][6]),
                                'usageRightsURL'        : validateImport('usageRightsURL', output[i][10]),
                                'publisher'             : validateImport('publisher', output[i][7]),
                                'isBasedOnURL'          : validateImport('isBasedOnURL', output[i][11]),
                                'endUser'               : validateImport('endUser', output[i][12]),
                                'ageRange'              : validateImport('ageRange', output[i][14]),
                                'educationalUse'        : validateImport('educationalUse', output[i][13]),
                                'interactivityType'     : validateImport('interactivityType', output[i][15]),
                                'learningResourceType'  : validateImport('learningResourceType', output[i][16]),
                                'mediaType'             : validateImport('mediaType', output[i][9]),
                                'groupType'             : validateImport('groupType', output[i][22]),
                                'timeRequired'          : validateImport('timeRequired', output[i][3]),
                                'educationalAlignments' : itemEducationAlignments
                            };

                            // Did anything above generate an error?
                            if (fileHasErrors) {

                                var message = "No data could be imported. It looks like the file you're attempting to import had some column/row errors that Tagger doesn't understand.  Before this data can be imported you'll need to correct the following errors so that we don't import something incorrectly:

" + fileErrors;

                                showMessage(message, "Import Errors! :: Errors found in row #"+i);
                            } else {
                                // Stuff the item
                                items['itemTag' + itemCounter] = tempItem;
                                // Inject the checkbox
                                $("#multiItemSelector").append($("     <input id='itemTag"+itemCounter+"' type='checkbox' name='tagItem'/>"+itemTitle+""));
                                // Increment the counter
                                itemCounter++;

                            }

                        }

                    }

                    updateResourceCount();

                }
            })(file);

            reader.readAsText(file);

            $("#fileForm")[0].reset();

        }
    });

});<|endoftext|>