<commit_before>import MetadataItem from './MetadataItem';

let DEFAULT_INTERPRETATIONS = {
  'undefined': 'categorical',
  'null': 'categorical',
  boolean: 'categorical',
  integer: 'ordinal',
  number: 'ordinal',
  date: 'categorical',
  string: 'categorical',
  object: 'categorical'
};

let ATTRIBUTE_GENERALITY = [
  'object',
  'string',
  'number',
  'integer'
];

let FILTER_STATES = {
  NO_FILTERS: 0,
  FILTERED: 1,
  EXCLUDED: 2
};

class DatasetCache {
  constructor (model) {
    this.model = model;
  }
  get cachedPromises () {
    if (!this._cachedPromises) {
      this._cachedPromises = {};
    }
    return this._cachedPromises;
  }
  set cachedPromises (value) {
    this._cachedPromises = value;
  }
  get filter () {
    if (!this._filter) {
      this._filter = {};
    }
    return this._filter;
  }
  set filter (value) {
    this._filter = value;
    // Invalidate filteredHistogram, pageHistogram, and currentDataPage
    delete this.cachedPromises.filteredHistogram;
    delete this.cachedPromises.pageHistogram;
    delete this.cachedPromises.currentDataPage;
    this.model.trigger('rl:updatePage');
  }
  get page () {
    if (!this._page) {
      this.page = {
        offset: 0,
        limit: 100
      };
    }
    return this._page;
  }
  set page (value) {
    // We have to show at least one data item
    value.limit = Math.max(1, value.limit);
    // Don't let the offset go lower than zero
    value.offset = Math.max(0, value.offset);
    // Align offset to limit-defined pages
    value.offset = value.limit * Math.floor(value.offset / value.limit);

    if (!this._page || value.offset !== this._page.offset || value.limit !== this._page.limit) {
      // Tentatively set the new page until we can
      // validate that offset doesn't exceed the
      // number of items that we have
      this._page = value;
      // Invalidate pageHistogram and currentDataPage
      delete this.cachedPromises.pageHistogram;
      delete this.cachedPromises.currentDataPage;
      this.model.trigger('rl:updatePage');

      if (this._cachedPromises && this._cachedPromises.filteredHistogram) {
        this._cachedPromises.filteredHistogram.then(filteredHistogram => {
          let maxItems = filteredHistogram.__passedFilters__[0].count;
          if (value.offset >= maxItems) {
            // Move back to the top page
            value.offset = value.limit * Math.floor(maxItems / value.limit);
            this.page = value;
          }
        });
      }
    }
  }
  get schema () {
    // Do we have the schema already in our metadata,
    // and TODO: is it current (check the file's updated flag
    // in girder, or check the last time the mongodb was modified)
    /* let meta = this.model.getMeta();
    let girderUpdate = this.model.get('updated');
    if (!meta || !meta.lastUpdated || !girderUpdate ||
      new Date(meta.lastUpdated) < new Date(girderUpdate)) {
      // With an out-of-date schema, we should trash any cached
      // histograms, and re-run schema inference
      delete meta['schema'];
      delete this.cachedPromises.schema;
    }*/

    if (!this.cachedPromises.schema) {
      let metaSchema = this.model.getMeta('schema');
      if (metaSchema) {
        // We already have up-to-date schema information in the metadata
        this.cachedPromises.schema = Promise.resolve(metaSchema);
      } else {
        // Actually hit the endpoint that does a pass to infer
        // the (potentially new) schema. This invalidates any histograms
        // or data that we have
        this.cachedPromises = {};
        this.cachedPromises.schema = this.restRequest({
          path: 'dataset/inferSchema',
          type: 'POST'
        }).then(newSchema => {
          // Inferring a new schema will update a few things;
          // we want to fetch our model as well
          return this.model.fetch().then(() => {
            this.model.trigger('rl:updatedSchema');
            return newSchema;
          });
        });
      }
    }
    return this.cachedPromises.schema;
  }
  get overviewHistogram () {
    if (!this.cachedPromises.overviewHistogram) {
      this.cachedPromises.overviewHistogram = this.schema.then(schema => {
        return this.restRequest({
          path: 'dataset/getHistograms',
          type: 'POST',
          data: {
            binSettings: JSON.stringify(this.model.getBinSettings(schema))
            // cache: true
          }
        }, 'rl:loadedHistogram');
      });
    }
    return this.cachedPromises.overviewHistogram;
  }
  get filteredHistogram () {
    if (!this.cachedPromises.filteredHistogram) {
      this.cachedPromises.filteredHistogram = this.schema.then(schema => {
        return this.restRequest({
          path: 'dataset/getHistograms',
          type: 'POST',
          data: {
            binSettings: JSON.stringify(this.model.getBinSettings(schema)),
            filter: this.filter
            // cache: true
          }
        }, 'rl:loadedHistogram');
      });
    }
    return this.cachedPromises.filteredHistogram;
  }
  get pageHistogram () {
    if (!this.cachedPromises.pageHistogram) {
      this.cachedPromises.pageHistogram = this.schema.then(schema => {
        return this.restRequest({
          path: 'dataset/getHistograms',
          type: 'POST',
          data: {
            binSettings: JSON.stringify(this.model.getBinSettings(schema)),
            filter: this.filter,
            limit: this.page.limit,
            offset: this.page.offset
            // Don't cache the page histograms on the server
          }
        }, 'rl:loadedHistogram');
      });
    }
    return this.cachedPromises.pageHistogram;
  }
  get currentDataPage () {
    if (!this.cachedPromises.currentDataPage) {
      this.cachedPromises.currentDataPage = this.schema.then(schema => {
        return this.restRequest({
          path: 'download',
          type: 'GET',
          data: {
            extraParameters: JSON.stringify({
              fileType: this.model.getMeta('format'),
              outputType: 'json',
              offset: this.page.offset,
              limit: this.page.limit
            })
          }
        }, 'rl:loadedData');
      });
    }
    return this.cachedPromises.currentDataPage;
  }
  restRequest (parameters, successEvent) {
    if (!this.model.getId()) {
      // We still haven't synced our basic info with the
      // server yet... so leave the value as null
      return null;
    } else {
      let promise = this.model.restRequest(parameters);
      if (successEvent) {
        promise.then(() => {
          this.model.trigger(successEvent);
        });
      }
      return promise;
    }
  }
}

let Dataset = MetadataItem.extend({
  initialize: function () {
    // Backbone.extend doesn't respect
    // getters and setters, so we split
    // all the cached information out into
    // its own non-Backbone cache class
    this.cache = new DatasetCache(this);
    this.dropped = false;
  },
  save: function () {
    // It's possible for a dataset to be dropped from the project
    // but someone is still hanging on to a reference to this
    // object. In this case, we want to prevent any future
    // attempts to save any changes
    if (this.dropped) {
      return Promise.resolve();
    } else {
      return MetadataItem.prototype.save.apply(this);
    }
  },
  autoDetectAttributeInterpretation: function (schema, attrName) {
    // Go with the default interpretation for the attribute type
    return DEFAULT_INTERPRETATIONS[this.getAttributeType(schema, attrName)];
  },
  getAttributeInterpretation: function (schema, attrName) {
    let attrSpec = schema[attrName];
    if (attrSpec.interpretation) {
      // The user has specified an interpretation
      return attrSpec.interpretation;
    } else {
      // auto-detect the interpretation
      return this.autoDetectAttributeInterpretation(schema, attrName);
    }
  },
  autoDetectAttributeType: function (schema, attrName) {
    let attrSpec = schema[attrName];
    // Find the most specific type that can accomodate all the values
    let attrType = 'object';
    let count = 0;
    for (let dataType of ATTRIBUTE_GENERALITY) {
      if (dataType in attrSpec && attrSpec[dataType].count >= count) {
        attrType = dataType;
        count = attrSpec[dataType].count;
      }
    }
    // TODO: if the histograms are available, use them to infer
    // whether to jump further into booleans (e.g. everything is
    // 0/1, y/n, true/false, etc) - this will require sending
    // (and storing) custom falsey strings in place of the
    // FALSEY_STRINGS list in general_purpose/binUtils.js,
    // with any dependent server-side logic
    return attrType;
  },
  getAttributeType: function (schema, attrName) {
    let attrSpec = schema[attrName];
    if (attrSpec.coerceToType) {
      // The user has specified a data type
      return attrSpec.coerceToType;
    } else {
      // auto-detect the data type
      return this.autoDetectAttributeType(schema, attrName);
    }
  },
  getBinSettings: function (schema) {
    let binSettings = {};
    // Assemble the parameters for how we want to see each attribute.
    // For now, other than attempting to auto-infer type and interpretation,
    // we rely on the default behavior
    Object.keys(schema).forEach(attrName => {
      binSettings[attrName] = {
        coerceToType: this.getAttributeType(schema, attrName),
        interpretation: this.getAttributeInterpretation(schema, attrName)
      };
    });
    return binSettings;
  },
  getTypeSpec: function () {
    let schema = this.getMeta('schema') || {};
    let result = {
      name: this.get('name'),
      attributes: {}
    };
    Object.keys(schema).forEach(attrName => {
      result.attributes[attrName] = this.getAttributeType(schema, attrName);
    });
    return result;
  },
  setAttributeType: function (attrName, dataType) {
    return this.cache.schema.then(schema => {
      if (dataType === null) {
        delete schema[attrName].coerceToType;
      } else {
        schema[attrName].coerceToType = dataType;
      }
      this.setMeta('schema', schema);
      let savePromise = this.save();
      this.cache.cachedPromises = {};
      this.trigger('rl:updatedSchema');
      return savePromise;
    });
  },
  setAttributeInterpretation: function (attrName, interpretation) {
    return this.cache.schema.then(schema => {
      if (interpretation === null) {
        delete schema[attrName].interpretation;
      } else {
        schema[attrName].interpretation = interpretation;
      }
      this.setMeta('schema', schema);
      let savePromise = this.save();
      this.cache.cachedPromises = {};
      this.trigger('rl:updatedSchema');
      return savePromise;
    });
  },
  getFilteredState: function (attrName) {
    // TODO
    return FILTER_STATES.NO_FILTERS;
  },
  setPage: function (offset, limit) {
    this.cache.page = {
      offset,
      limit
    };
  },
  setOffset: function (offset) {
    this.setPage(offset, this.cache.page.limit);
  },
  setLimit: function (limit) {
    this.setPage(this.cache.page.offset, limit);
  },
  seekNext: function () {
    this.setPage(this.cache.page.offset + this.cache.page.limit,
                 this.cache.page.limit);
  },
  seekPrev: function () {
    this.setPage(this.cache.page.offset - this.cache.page.limit,
                 this.cache.page.limit);
  },
  seekFirst: function () {
    this.setPage(0, this.cache.page.limit);
  },
  seekLast: function () {
    this.cache.filteredHistogram.then(filteredHistogram => {
      let lastItem = filteredHistogram.__passedFilters__[0].count;
      this.setPage(lastItem, this.cache.page.limit);
    });
  }
});

Dataset.DEFAULT_INTERPRETATIONS = DEFAULT_INTERPRETATIONS;
Dataset.FILTER_STATES = FILTER_STATES;
export default Dataset;
<commit_msg>Point dataset download from the client to the old select endpoint<commit_after>import MetadataItem from './MetadataItem';

let DEFAULT_INTERPRETATIONS = {
  'undefined': 'categorical',
  'null': 'categorical',
  boolean: 'categorical',
  integer: 'ordinal',
  number: 'ordinal',
  date: 'categorical',
  string: 'categorical',
  object: 'categorical'
};

let ATTRIBUTE_GENERALITY = [
  'object',
  'string',
  'number',
  'integer'
];

let FILTER_STATES = {
  NO_FILTERS: 0,
  FILTERED: 1,
  EXCLUDED: 2
};

class DatasetCache {
  constructor (model) {
    this.model = model;
  }
  get cachedPromises () {
    if (!this._cachedPromises) {
      this._cachedPromises = {};
    }
    return this._cachedPromises;
  }
  set cachedPromises (value) {
    this._cachedPromises = value;
  }
  get filter () {
    if (!this._filter) {
      this._filter = {};
    }
    return this._filter;
  }
  set filter (value) {
    this._filter = value;
    // Invalidate filteredHistogram, pageHistogram, and currentDataPage
    delete this.cachedPromises.filteredHistogram;
    delete this.cachedPromises.pageHistogram;
    delete this.cachedPromises.currentDataPage;
    this.model.trigger('rl:updatePage');
  }
  get page () {
    if (!this._page) {
      this.page = {
        offset: 0,
        limit: 100
      };
    }
    return this._page;
  }
  set page (value) {
    // We have to show at least one data item
    value.limit = Math.max(1, value.limit);
    // Don't let the offset go lower than zero
    value.offset = Math.max(0, value.offset);
    // Align offset to limit-defined pages
    value.offset = value.limit * Math.floor(value.offset / value.limit);

    if (!this._page || value.offset !== this._page.offset || value.limit !== this._page.limit) {
      // Tentatively set the new page until we can
      // validate that offset doesn't exceed the
      // number of items that we have
      this._page = value;
      // Invalidate pageHistogram and currentDataPage
      delete this.cachedPromises.pageHistogram;
      delete this.cachedPromises.currentDataPage;
      this.model.trigger('rl:updatePage');

      if (this._cachedPromises && this._cachedPromises.filteredHistogram) {
        this._cachedPromises.filteredHistogram.then(filteredHistogram => {
          let maxItems = filteredHistogram.__passedFilters__[0].count;
          if (value.offset >= maxItems) {
            // Move back to the top page
            value.offset = value.limit * Math.floor(maxItems / value.limit);
            this.page = value;
          }
        });
      }
    }
  }
  get schema () {
    // Do we have the schema already in our metadata,
    // and TODO: is it current (check the file's updated flag
    // in girder, or check the last time the mongodb was modified)
    /* let meta = this.model.getMeta();
    let girderUpdate = this.model.get('updated');
    if (!meta || !meta.lastUpdated || !girderUpdate ||
      new Date(meta.lastUpdated) < new Date(girderUpdate)) {
      // With an out-of-date schema, we should trash any cached
      // histograms, and re-run schema inference
      delete meta['schema'];
      delete this.cachedPromises.schema;
    }*/

    if (!this.cachedPromises.schema) {
      let metaSchema = this.model.getMeta('schema');
      if (metaSchema) {
        // We already have up-to-date schema information in the metadata
        this.cachedPromises.schema = Promise.resolve(metaSchema);
      } else {
        // Actually hit the endpoint that does a pass to infer
        // the (potentially new) schema. This invalidates any histograms
        // or data that we have
        this.cachedPromises = {};
        this.cachedPromises.schema = this.restRequest({
          path: 'dataset/inferSchema',
          type: 'POST'
        }).then(newSchema => {
          // Inferring a new schema will update a few things;
          // we want to fetch our model as well
          return this.model.fetch().then(() => {
            this.model.trigger('rl:updatedSchema');
            return newSchema;
          });
        });
      }
    }
    return this.cachedPromises.schema;
  }
  get overviewHistogram () {
    if (!this.cachedPromises.overviewHistogram) {
      this.cachedPromises.overviewHistogram = this.schema.then(schema => {
        return this.restRequest({
          path: 'dataset/getHistograms',
          type: 'POST',
          data: {
            binSettings: JSON.stringify(this.model.getBinSettings(schema))
            // cache: true
          }
        }, 'rl:loadedHistogram');
      });
    }
    return this.cachedPromises.overviewHistogram;
  }
  get filteredHistogram () {
    if (!this.cachedPromises.filteredHistogram) {
      this.cachedPromises.filteredHistogram = this.schema.then(schema => {
        return this.restRequest({
          path: 'dataset/getHistograms',
          type: 'POST',
          data: {
            binSettings: JSON.stringify(this.model.getBinSettings(schema)),
            filter: this.filter
            // cache: true
          }
        }, 'rl:loadedHistogram');
      });
    }
    return this.cachedPromises.filteredHistogram;
  }
  get pageHistogram () {
    if (!this.cachedPromises.pageHistogram) {
      this.cachedPromises.pageHistogram = this.schema.then(schema => {
        return this.restRequest({
          path: 'dataset/getHistograms',
          type: 'POST',
          data: {
            binSettings: JSON.stringify(this.model.getBinSettings(schema)),
            filter: this.filter,
            limit: this.page.limit,
            offset: this.page.offset
            // Don't cache the page histograms on the server
          }
        }, 'rl:loadedHistogram');
      });
    }
    return this.cachedPromises.pageHistogram;
  }
  get currentDataPage () {
    if (!this.cachedPromises.currentDataPage) {
      this.cachedPromises.currentDataPage = this.schema.then(schema => {
        if (this.model.getMeta('format') === 'mongodb.collection') {
          return this.restRequest({
            path: 'database/select',
            type: 'GET',
            data: {
              format: 'dict',
              offset: this.page.offset,
              limit: this.page.limit
            }
          }, 'rl:loadedData').then(resp => resp.data);
        } else {
          return this.restRequest({
            path: 'download',
            type: 'GET',
            data: {
              extraParameters: JSON.stringify({
                fileType: this.model.getMeta('format'),
                outputType: 'json',
                offset: this.page.offset,
                limit: this.page.limit
              })
            }
          }, 'rl:loadedData');
        }
      });
    }
    return this.cachedPromises.currentDataPage;
  }
  restRequest (parameters, successEvent) {
    if (!this.model.getId()) {
      // We still haven't synced our basic info with the
      // server yet... so leave the value as null
      return null;
    } else {
      let promise = this.model.restRequest(parameters);
      if (successEvent) {
        promise.then(() => {
          this.model.trigger(successEvent);
        });
      }
      return promise;
    }
  }
}

let Dataset = MetadataItem.extend({
  initialize: function () {
    // Backbone.extend doesn't respect
    // getters and setters, so we split
    // all the cached information out into
    // its own non-Backbone cache class
    this.cache = new DatasetCache(this);
    this.dropped = false;
  },
  save: function () {
    // It's possible for a dataset to be dropped from the project
    // but someone is still hanging on to a reference to this
    // object. In this case, we want to prevent any future
    // attempts to save any changes
    if (this.dropped) {
      return Promise.resolve();
    } else {
      return MetadataItem.prototype.save.apply(this);
    }
  },
  autoDetectAttributeInterpretation: function (schema, attrName) {
    // Go with the default interpretation for the attribute type
    return DEFAULT_INTERPRETATIONS[this.getAttributeType(schema, attrName)];
  },
  getAttributeInterpretation: function (schema, attrName) {
    let attrSpec = schema[attrName];
    if (attrSpec.interpretation) {
      // The user has specified an interpretation
      return attrSpec.interpretation;
    } else {
      // auto-detect the interpretation
      return this.autoDetectAttributeInterpretation(schema, attrName);
    }
  },
  autoDetectAttributeType: function (schema, attrName) {
    let attrSpec = schema[attrName];
    // Find the most specific type that can accomodate all the values
    let attrType = 'object';
    let count = 0;
    for (let dataType of ATTRIBUTE_GENERALITY) {
      if (dataType in attrSpec && attrSpec[dataType].count >= count) {
        attrType = dataType;
        count = attrSpec[dataType].count;
      }
    }
    // TODO: if the histograms are available, use them to infer
    // whether to jump further into booleans (e.g. everything is
    // 0/1, y/n, true/false, etc) - this will require sending
    // (and storing) custom falsey strings in place of the
    // FALSEY_STRINGS list in general_purpose/binUtils.js,
    // with any dependent server-side logic
    return attrType;
  },
  getAttributeType: function (schema, attrName) {
    let attrSpec = schema[attrName];
    if (attrSpec.coerceToType) {
      // The user has specified a data type
      return attrSpec.coerceToType;
    } else {
      // auto-detect the data type
      return this.autoDetectAttributeType(schema, attrName);
    }
  },
  getBinSettings: function (schema) {
    let binSettings = {};
    // Assemble the parameters for how we want to see each attribute.
    // For now, other than attempting to auto-infer type and interpretation,
    // we rely on the default behavior
    Object.keys(schema).forEach(attrName => {
      binSettings[attrName] = {
        coerceToType: this.getAttributeType(schema, attrName),
        interpretation: this.getAttributeInterpretation(schema, attrName)
      };
    });
    return binSettings;
  },
  getTypeSpec: function () {
    let schema = this.getMeta('schema') || {};
    let result = {
      name: this.get('name'),
      attributes: {}
    };
    Object.keys(schema).forEach(attrName => {
      result.attributes[attrName] = this.getAttributeType(schema, attrName);
    });
    return result;
  },
  setAttributeType: function (attrName, dataType) {
    return this.cache.schema.then(schema => {
      if (dataType === null) {
        delete schema[attrName].coerceToType;
      } else {
        schema[attrName].coerceToType = dataType;
      }
      this.setMeta('schema', schema);
      let savePromise = this.save();
      this.cache.cachedPromises = {};
      this.trigger('rl:updatedSchema');
      return savePromise;
    });
  },
  setAttributeInterpretation: function (attrName, interpretation) {
    return this.cache.schema.then(schema => {
      if (interpretation === null) {
        delete schema[attrName].interpretation;
      } else {
        schema[attrName].interpretation = interpretation;
      }
      this.setMeta('schema', schema);
      let savePromise = this.save();
      this.cache.cachedPromises = {};
      this.trigger('rl:updatedSchema');
      return savePromise;
    });
  },
  getFilteredState: function (attrName) {
    // TODO
    return FILTER_STATES.NO_FILTERS;
  },
  setPage: function (offset, limit) {
    this.cache.page = {
      offset,
      limit
    };
  },
  setOffset: function (offset) {
    this.setPage(offset, this.cache.page.limit);
  },
  setLimit: function (limit) {
    this.setPage(this.cache.page.offset, limit);
  },
  seekNext: function () {
    this.setPage(this.cache.page.offset + this.cache.page.limit,
                 this.cache.page.limit);
  },
  seekPrev: function () {
    this.setPage(this.cache.page.offset - this.cache.page.limit,
                 this.cache.page.limit);
  },
  seekFirst: function () {
    this.setPage(0, this.cache.page.limit);
  },
  seekLast: function () {
    this.cache.filteredHistogram.then(filteredHistogram => {
      let lastItem = filteredHistogram.__passedFilters__[0].count;
      this.setPage(lastItem, this.cache.page.limit);
    });
  }
});

Dataset.DEFAULT_INTERPRETATIONS = DEFAULT_INTERPRETATIONS;
Dataset.FILTER_STATES = FILTER_STATES;
export default Dataset;
<|endoftext|>


<commit_before>
var margin = {top: 20, right: 20, bottom: 30, left: 50},
    width = 860 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;

var x = d3.scale.ordinal()
    .range([0, width]);

var y = d3.scale.linear()
    .range([height, 0]);

var color = d3.scale.category20();

var xAxis = d3.svg.axis()
    .scale(x)
    .orient("bottom");

var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left");

var area = d3.svg.area()
    .x(function(d) { return x(d.yearCol); })
    .y0(function(d) { return y(d.y0); })
    .y1(function(d) { return y(d.y0 + d.y); });

var stack = d3.layout.stack()
    .values(function(d) { return d.values; });

var svg = d3.select("div#chart").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

d3.csv('Words_allyears_26oct.csv', function(error, data){

  var list = ['war', 'bomb', 'blast'];
  color.domain(list);
  console.log(color);

  var data = $.map(data, function(element){
    return ($.inArray(element.wordCol,list)>-1?element:null)
  });

  data.forEach(function(d){
    d.countCol = +d.countCol;
    d.yearCol = +d.yearCol;
  });

  function complete(x, key){
    for (i=0; i<key.length; i++){
      tempdata = x.filter(function(d){ return d.wordCol == key[i]; });
      yearsPresent = []
      years = [];

      for (year=1955; year<2010; year++){
        years.push(year)
        for (row=0; row<tempdata.length; row++){
          if (tempdata[row].yearCol === year){
            yearsPresent.push(year);
          }
        }
      }

      for (year=0; year<years.length; year++){
        if (yearsPresent.indexOf(years[year]) < 0){
          dict = {}
          dict['countCol'] = 0;
          dict['wordCol'] = tempdata[0].wordCol;
          dict['yearCol'] = years[year];
          data.push(dict);
        }
      }
    }

  };
  complete(data, list);

  var words = stack(color.domain().map(function(name) {
    return {
      name: name,
      values: data.map(function(d) {
        return {yearCol: d.yearCol, y: d.countCol };
      })
    };
  }));

  x.domain(d3.extent(data, function(d){ return d.yearCol; }));

  var word = svg.selectAll('.word')
      .data(words)
    .enter().append('g')
      .attr('class', 'word');

  word.append('path')
      .attr('class', 'area')
      .attr('d', function(d){ return area(d.values); })
      .style('fill', function(d){ return color(d.name); });

  word.append('text')
    .datum(function(d){ return {name: d.name, value: d.values[d.values.length - 1]}; })
    .attr('transform', function(d){ return "translate(" + x(d.value.yearCol) + "," + y(d.value.y0 + d.value.y / 2) + ")"; })
    .attr('x', -6)
    .attr('dy', '.35em')
    .text(function(d){ return d.name; });

  svg.append('g')
    .attr('class', 'x axis')
    .attr('transform', 'translate(0,' + height + ')')
    .call(xAxis);

  svg.append('g')
    .attr('class', 'y axis')
    .call(yAxis);
  /*
  data = d3.nest()
            .key(function(d){ return d.wordCol; })
            .entries(data);
  */

});

  <commit_msg>update data<commit_after>
var margin = {top: 20, right: 20, bottom: 30, left: 50},
    width = 860 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;

var x = d3.scale.ordinal()
    .range([0, width]);

var y = d3.scale.linear()
    .range([height, 0]);

var color = d3.scale.category20();

var xAxis = d3.svg.axis()
    .scale(x)
    .orient("bottom");

var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left");

var area = d3.svg.area()
    .x(function(d) { return x(d.yearCol); })
    .y0(function(d) { return y(d.y0); })
    .y1(function(d) { return y(d.y0 + d.y); });

var stack = d3.layout.stack()
    .values(function(d) { return d.values; });

var svg = d3.select("div#chart").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

d3.csv('Words_allyears_26oct.csv', function(error, data){

  var list = ['war', 'bomb', 'blast'];
  color.domain(list);

  var data = $.map(data, function(element){
    return ($.inArray(element.wordCol,list)>-1?element:null)
  });

  data.forEach(function(d){
    d.countCol = +d.countCol;
    d.yearCol = +d.yearCol;
  });

  function complete(x, key){
    for (i=0; i<key.length; i++){
      tempdata = x.filter(function(d){ return d.wordCol == key[i]; });
      yearsPresent = []
      years = [];

      for (year=1955; year<2010; year++){
        years.push(year)
        for (row=0; row<tempdata.length; row++){
          if (tempdata[row].yearCol === year){
            yearsPresent.push(year);
          }
        }
      }

      for (year=0; year<years.length; year++){
        if (yearsPresent.indexOf(years[year]) < 0){
          dict = {}
          dict['countCol'] = 0;
          dict['wordCol'] = tempdata[0].wordCol;
          dict['yearCol'] = years[year];
          data.push(dict);
        }
      }
    }

  };
  complete(data, list);

  var words = stack(color.domain().map(function(name) {
    return {
      name: name,
      values: data.map(function(d) {
        return {yearCol: d.yearCol, y: d.countCol };
      })
    };
  }));
  console.log(words);

  x.domain(d3.extent(data, function(d){ return d.yearCol; }));

  var word = svg.selectAll('.word')
      .data(words)
    .enter().append('g')
      .attr('class', 'word');

  word.append('path')
      .attr('class', 'area')
      .attr('d', function(d){ return area(d.values); })
      .style('fill', function(d){ return color(d.name); });

  word.append('text')
    .datum(function(d){ return {name: d.name, value: d.values[d.values.length - 1]}; })
    .attr('transform', function(d){ return "translate(" + x(d.value.yearCol) + "," + y(d.value.y0 + d.value.y / 2) + ")"; })
    .attr('x', -6)
    .attr('dy', '.35em')
    .text(function(d){ return d.name; });

  svg.append('g')
    .attr('class', 'x axis')
    .attr('transform', 'translate(0,' + height + ')')
    .call(xAxis);

  svg.append('g')
    .attr('class', 'y axis')
    .call(yAxis);
  /*
  data = d3.nest()
            .key(function(d){ return d.wordCol; })
            .entries(data);
  */

});

  <|endoftext|>


<commit_before>import boxIntersect from 'box-intersect';
import { scaleLinear } from 'd3-scale';
import * as PIXI from 'pixi.js';

import { PixiTrack } from './PixiTrack';
import { ChromosomeInfo } from './ChromosomeInfo';
import { SearchField } from './search_field';

import { pubSub } from './services';

import { absToChr, hexStrToInt, pixiTextToSvg, svgLine } from './utils';

const TICK_WIDTH = 200;
const TICK_HEIGHT = 6;
const TICK_TEXT_SEPARATION = 2;
const TICK_COLOR = 0x777777;
const MOUSE_POSITION_COLOR = 0xaaaaaa;

class HorizontalChromosomeLabels extends PixiTrack {
  constructor(scene, dataConfig, handleTilesetInfoReceived, options, animate, chromInfoPath) {
    super(scene, dataConfig, handleTilesetInfoReceived, options, animate);

    this.searchField = null;
    this.chromInfo = null;

    this.gTicks = {};
    this.tickTexts = {};

    this.textFontSize = '12px';
    this.textFontFamily = 'Arial';
    this.textFontColor = '#777777';
    this.pixiTextConfig = {
      fontSize: this.textFontSize,
      fontFamily: this.textFontFamily,
      fill: this.textFontColor
    };

    this.animate = animate;

    this.pubSubs = [];

    this.options = options;
    this.options.mousePositionColor = this.options.mousePositionColor
      ? hexStrToInt(this.options.mousePositionColor)
      : MOUSE_POSITION_COLOR;

    if (this.options.showMousePosition) {
      // Graphics for cursor position
      this.cursor = new PIXI.Graphics();

      this.pMain.addChild(this.cursor);

      this.pubSubs.push(
        pubSub.subscribe('app.mouseMove', this.mouseMoveHandler.bind(this))
      );
    }

    let chromSizesPath = chromInfoPath;

    if (!chromSizesPath) {
      chromSizesPath = `${dataConfig.server}/chrom-sizes/?id=${dataConfig.tilesetUid}`;
    }

    ChromosomeInfo(chromSizesPath, (newChromInfo) => {
      this.chromInfo = newChromInfo;

      this.searchField = new SearchField(this.chromInfo);

      this.texts = [];

      for (let i = 0; i < this.chromInfo.cumPositions.length; i++) {
        const textStr = this.chromInfo.cumPositions[i].chr;
        this.gTicks[textStr] = new PIXI.Graphics();

        // create the array that will store tick TEXT objects
        if (!this.tickTexts[textStr]) { this.tickTexts[textStr] = []; }

        const text = new PIXI.Text(textStr, this.pixiTextConfig);

        text.anchor.x = 0.5;
        text.anchor.y = 0.5;
        text.visible = false;

        // give each string a random hash so that some get hidden
        // when there's overlaps
        text.hashValue = Math.random();

        this.pMain.addChild(text);
        this.pMain.addChild(this.gTicks[textStr]);

        this.texts.push(text);
      }

      this.draw();
      this.animate();
    });
  }

  /**
   * Mouse move handler
   *
   * @param  {Object}  e  Event object.
   */
  mouseMoveHandler(e) {
    this.mouseX = e.x - this.position[0];
    this.drawMousePosition();
  }

  drawMousePosition(x = this.mouseX) {
    this.cursor.clear();
    this.cursor.lineStyle(1, this.options.mousePositionColor);
    this.cursor.moveTo(x, 0);
    this.cursor.lineTo(x, this.dimensions[1]);
    this.animate();
  }

  drawTicks(cumPos) {
    const graphics = this.gTicks[cumPos.chr];

    this.gTicks[cumPos.chr].visible = true;
    this.gTicks[cumPos.chr].clear();

    const chromLen = +this.chromInfo.chromLengths[cumPos.chr];

    const vpLeft = Math.max(this._xScale(cumPos.pos), 0);
    const vpRight = Math.min(
      this._xScale(cumPos.pos + chromLen), this.dimensions[0]
    );

    const numTicks = (vpRight - vpLeft) / TICK_WIDTH;

    // what is the domain of this chromosome that is visible?
    const xScale = scaleLinear()
      .domain([
        Math.max(1, this._xScale.invert(0) - cumPos.pos),
        Math.min(chromLen, this._xScale.invert(this.dimensions[0]) - cumPos.pos)
      ])
      .range(vpLeft, vpRight);

    // calculate a certain number of ticks
    const ticks = xScale.ticks(numTicks);
    const tickFormat = xScale.tickFormat(numTicks);
    const tickTexts = this.tickTexts[cumPos.chr];

    while (tickTexts.length <= ticks.length) {
      const newText = new PIXI.Text('', this.pixiTextConfig);
      tickTexts.push(newText);
      this.gTicks[cumPos.chr].addChild(newText);
    }

    let i = 0;
    while (i < ticks.length) {
      tickTexts[i].visible = true;
      tickTexts[i].anchor.x = 0.5;
      tickTexts[i].anchor.y = 1;

      if (this.flipText) tickTexts[i].scale.x = -1;

      // draw the tick labels
      tickTexts[i].x = this._xScale(cumPos.pos + ticks[i]);
      tickTexts[i].y = this.dimensions[1] - (TICK_HEIGHT + TICK_TEXT_SEPARATION);

      tickTexts[i].text = ticks[i] === 0
        ? `${cumPos.chr}:1`
        : `${cumPos.chr}:${tickFormat(ticks[i])}`;

      graphics.lineStyle(6, TICK_COLOR);

      // draw the tick lines
      graphics.moveTo(this._xScale(cumPos.pos + ticks[i]), this.dimensions[1]);
      graphics.lineTo(this._xScale(cumPos.pos + ticks[i]), this.dimensions[1] - TICK_HEIGHT);

      i += 1;
    }

    while (i < tickTexts.length) {
      // we don't need this text so we'll turn it off for now
      tickTexts[i].visible = false;

      i += 1;
    }

    return ticks.length;
  }

  draw() {
    this.allTexts = [];

    if (!this.texts) { return; }

    if (!this.searchField) { return; }

    const x1 = absToChr(this._xScale.domain()[0], this.chromInfo);
    const x2 = absToChr(this._xScale.domain()[1], this.chromInfo);

    for (let i = 0; i < this.texts.length; i++) {
      this.texts[i].visible = false;
      this.gTicks[this.chromInfo.cumPositions[i].chr].visible = false;
    }

    for (let i = x1[3]; i <= x2[3]; i++) {
      const xCumPos = this.chromInfo.cumPositions[i];

      const midX = xCumPos.pos + (this.chromInfo.chromLengths[xCumPos.chr] / 2);

      const viewportMidX = this._xScale(midX);

      const text = this.texts[i];

      text.anchor.y = 1;
      text.x = viewportMidX;
      text.y = this.dimensions[1] - TICK_TEXT_SEPARATION - TICK_HEIGHT;
      text.updateTransform();

      if (this.flipText) { text.scale.x = -1; }

      // const bbox = text.getBounds();
      // text.y -= bbox.height;

      // make sure the chrosome label fits in the x range
      /* Not necessary because chromosome labels only get drawn
            if (viewportMidX + bbox.width / 2  > this.dimensions[0]) {
                text.x -= (viewportMidX + bbox.width / 2) - this.dimensions[0];
            } else if (viewportMidX - bbox.width / 2 < 0) {
                //
                text.x -= (viewportMidX - bbox.width / 2);
            }
            */

      const numTicksDrawn = this.drawTicks(xCumPos);

      // only show chromsome labels if there's no ticks drawn
      text.visible = numTicksDrawn <= 0;

      this.allTexts.push({
        importance: this.texts[i].hashValue,
        text: this.texts[i],
        caption: null
      });
    }

    // define the edge chromosome which are visible
    this.hideOverlaps(this.allTexts);
  }

  hideOverlaps(allTexts) {
    let allBoxes = []; // store the bounding boxes of the text objects so we can
    // calculate overlaps
    allBoxes = allTexts.map((val) => {
      const text = val.text;
      text.updateTransform();
      const b = text.getBounds();
      const box = [b.x, b.y, b.x + b.width, b.y + b.height];

      return box;
    });

    boxIntersect(allBoxes, (i, j) => {
      if (allTexts[i].importance > allTexts[j].importance) {
        allTexts[j].text.visible = 0;
      } else {
        allTexts[i].text.visible = 0;
      }
    });
  }

  setPosition(newPosition) {
    super.setPosition(newPosition);

    this.pMain.position.y = this.position[1];
    this.pMain.position.x = this.position[0];
  }

  zoomed(newXScale, newYScale) {
    this.xScale(newXScale);
    this.yScale(newYScale);

    this.draw();
  }

  refreshTiles() {
    // dummy function that is called by LeftTrackModifier
  }

  exportSVG() {
    let track = null,
      base = null;

    if (super.exportSVG) {
      [base, track] = super.exportSVG();
    } else {
      base = document.createElement('g');
      track = base;
    }
    base.setAttribute('class', 'chromosome-labels');

    const output = document.createElement('g');
    track.appendChild(output);

    output.setAttribute('transform',
      `translate(${this.position[0]},${this.position[1]})`);

    for (const text of this.allTexts) {
      if (!text.text.visible) continue;

      const g = pixiTextToSvg(text.text);
      output.appendChild(g);
    }

    for (let key in this.tickTexts) {
      for (let text of this.tickTexts[key]) {
        let g = pixiTextToSvg(text);
        output.appendChild(g);

        g = svgLine(
          text.x,
          this.dimensions[1],
          text.x,
          this.dimensions[1] - TICK_HEIGHT,
          1,
          TICK_COLOR,
        );

        output.appendChild(g);
      }
    }

    return [base, track];
  }
}

export default HorizontalChromosomeLabels;
<commit_msg>Make left-modifiable<commit_after>import boxIntersect from 'box-intersect';
import { scaleLinear } from 'd3-scale';
import * as PIXI from 'pixi.js';

import { PixiTrack } from './PixiTrack';
import { ChromosomeInfo } from './ChromosomeInfo';
import { SearchField } from './search_field';

import { pubSub } from './services';

import { absToChr, hexStrToInt, pixiTextToSvg, svgLine } from './utils';

const TICK_WIDTH = 200;
const TICK_HEIGHT = 6;
const TICK_TEXT_SEPARATION = 2;
const TICK_COLOR = 0x777777;
const MOUSE_POSITION_COLOR = 0xaaaaaa;

class HorizontalChromosomeLabels extends PixiTrack {
  constructor(scene, dataConfig, handleTilesetInfoReceived, options, animate, chromInfoPath) {
    super(scene, dataConfig, handleTilesetInfoReceived, options, animate);

    this.searchField = null;
    this.chromInfo = null;

    this.gTicks = {};
    this.tickTexts = {};

    this.textFontSize = '12px';
    this.textFontFamily = 'Arial';
    this.textFontColor = '#777777';
    this.pixiTextConfig = {
      fontSize: this.textFontSize,
      fontFamily: this.textFontFamily,
      fill: this.textFontColor
    };

    this.animate = animate;

    this.pubSubs = [];

    this.options = options;
    this.options.mousePositionColor = this.options.mousePositionColor
      ? hexStrToInt(this.options.mousePositionColor)
      : MOUSE_POSITION_COLOR;

    if (this.options.showMousePosition) {
      // Graphics for cursor position
      this.cursor = new PIXI.Graphics();

      this.pMain.addChild(this.cursor);

      this.pubSubs.push(
        pubSub.subscribe('app.mouseMove', this.mouseMoveHandler.bind(this))
      );
    }

    let chromSizesPath = chromInfoPath;

    if (!chromSizesPath) {
      chromSizesPath = `${dataConfig.server}/chrom-sizes/?id=${dataConfig.tilesetUid}`;
    }

    ChromosomeInfo(chromSizesPath, (newChromInfo) => {
      this.chromInfo = newChromInfo;

      this.searchField = new SearchField(this.chromInfo);

      this.texts = [];

      for (let i = 0; i < this.chromInfo.cumPositions.length; i++) {
        const textStr = this.chromInfo.cumPositions[i].chr;
        this.gTicks[textStr] = new PIXI.Graphics();

        // create the array that will store tick TEXT objects
        if (!this.tickTexts[textStr]) { this.tickTexts[textStr] = []; }

        const text = new PIXI.Text(textStr, this.pixiTextConfig);

        text.anchor.x = 0.5;
        text.anchor.y = 0.5;
        text.visible = false;

        // give each string a random hash so that some get hidden
        // when there's overlaps
        text.hashValue = Math.random();

        this.pMain.addChild(text);
        this.pMain.addChild(this.gTicks[textStr]);

        this.texts.push(text);
      }

      this.draw();
      this.animate();
    });
  }

  /**
   * Mouse move handler
   *
   * @param  {Object}  e  Event object.
   */
  mouseMoveHandler(e) {
    this.mousePos = this.flipText
      ? e.y - this.position[1]
      : e.x - this.position[0];
    this.drawMousePosition();
  }

  drawMousePosition(mousePos = this.mousePos) {
    this.cursor.clear();
    this.cursor.lineStyle(1, this.options.mousePositionColor);
    this.cursor.moveTo(mousePos, 0);
    this.cursor.lineTo(mousePos, this.dimensions[1]);
    this.animate();
  }

  drawTicks(cumPos) {
    const graphics = this.gTicks[cumPos.chr];

    this.gTicks[cumPos.chr].visible = true;
    this.gTicks[cumPos.chr].clear();

    const chromLen = +this.chromInfo.chromLengths[cumPos.chr];

    const vpLeft = Math.max(this._xScale(cumPos.pos), 0);
    const vpRight = Math.min(
      this._xScale(cumPos.pos + chromLen), this.dimensions[0]
    );

    const numTicks = (vpRight - vpLeft) / TICK_WIDTH;

    // what is the domain of this chromosome that is visible?
    const xScale = scaleLinear()
      .domain([
        Math.max(1, this._xScale.invert(0) - cumPos.pos),
        Math.min(chromLen, this._xScale.invert(this.dimensions[0]) - cumPos.pos)
      ])
      .range(vpLeft, vpRight);

    // calculate a certain number of ticks
    const ticks = xScale.ticks(numTicks);
    const tickFormat = xScale.tickFormat(numTicks);
    const tickTexts = this.tickTexts[cumPos.chr];

    while (tickTexts.length <= ticks.length) {
      const newText = new PIXI.Text('', this.pixiTextConfig);
      tickTexts.push(newText);
      this.gTicks[cumPos.chr].addChild(newText);
    }

    let i = 0;
    while (i < ticks.length) {
      tickTexts[i].visible = true;
      tickTexts[i].anchor.x = 0.5;
      tickTexts[i].anchor.y = 1;

      if (this.flipText) tickTexts[i].scale.x = -1;

      // draw the tick labels
      tickTexts[i].x = this._xScale(cumPos.pos + ticks[i]);
      tickTexts[i].y = this.dimensions[1] - (TICK_HEIGHT + TICK_TEXT_SEPARATION);

      tickTexts[i].text = ticks[i] === 0
        ? `${cumPos.chr}:1`
        : `${cumPos.chr}:${tickFormat(ticks[i])}`;

      graphics.lineStyle(6, TICK_COLOR);

      // draw the tick lines
      graphics.moveTo(this._xScale(cumPos.pos + ticks[i]), this.dimensions[1]);
      graphics.lineTo(this._xScale(cumPos.pos + ticks[i]), this.dimensions[1] - TICK_HEIGHT);

      i += 1;
    }

    while (i < tickTexts.length) {
      // we don't need this text so we'll turn it off for now
      tickTexts[i].visible = false;

      i += 1;
    }

    return ticks.length;
  }

  draw() {
    this.allTexts = [];

    if (!this.texts) { return; }

    if (!this.searchField) { return; }

    const x1 = absToChr(this._xScale.domain()[0], this.chromInfo);
    const x2 = absToChr(this._xScale.domain()[1], this.chromInfo);

    for (let i = 0; i < this.texts.length; i++) {
      this.texts[i].visible = false;
      this.gTicks[this.chromInfo.cumPositions[i].chr].visible = false;
    }

    for (let i = x1[3]; i <= x2[3]; i++) {
      const xCumPos = this.chromInfo.cumPositions[i];

      const midX = xCumPos.pos + (this.chromInfo.chromLengths[xCumPos.chr] / 2);

      const viewportMidX = this._xScale(midX);

      const text = this.texts[i];

      text.anchor.y = 1;
      text.x = viewportMidX;
      text.y = this.dimensions[1] - TICK_TEXT_SEPARATION - TICK_HEIGHT;
      text.updateTransform();

      if (this.flipText) { text.scale.x = -1; }

      // const bbox = text.getBounds();
      // text.y -= bbox.height;

      // make sure the chrosome label fits in the x range
      /* Not necessary because chromosome labels only get drawn
            if (viewportMidX + bbox.width / 2  > this.dimensions[0]) {
                text.x -= (viewportMidX + bbox.width / 2) - this.dimensions[0];
            } else if (viewportMidX - bbox.width / 2 < 0) {
                //
                text.x -= (viewportMidX - bbox.width / 2);
            }
            */

      const numTicksDrawn = this.drawTicks(xCumPos);

      // only show chromsome labels if there's no ticks drawn
      text.visible = numTicksDrawn <= 0;

      this.allTexts.push({
        importance: this.texts[i].hashValue,
        text: this.texts[i],
        caption: null
      });
    }

    // define the edge chromosome which are visible
    this.hideOverlaps(this.allTexts);
  }

  hideOverlaps(allTexts) {
    let allBoxes = []; // store the bounding boxes of the text objects so we can
    // calculate overlaps
    allBoxes = allTexts.map((val) => {
      const text = val.text;
      text.updateTransform();
      const b = text.getBounds();
      const box = [b.x, b.y, b.x + b.width, b.y + b.height];

      return box;
    });

    boxIntersect(allBoxes, (i, j) => {
      if (allTexts[i].importance > allTexts[j].importance) {
        allTexts[j].text.visible = 0;
      } else {
        allTexts[i].text.visible = 0;
      }
    });
  }

  setPosition(newPosition) {
    super.setPosition(newPosition);

    this.pMain.position.y = this.position[1];
    this.pMain.position.x = this.position[0];
  }

  zoomed(newXScale, newYScale) {
    this.xScale(newXScale);
    this.yScale(newYScale);

    this.draw();
  }

  refreshTiles() {
    // dummy function that is called by LeftTrackModifier
  }

  exportSVG() {
    let track = null,
      base = null;

    if (super.exportSVG) {
      [base, track] = super.exportSVG();
    } else {
      base = document.createElement('g');
      track = base;
    }
    base.setAttribute('class', 'chromosome-labels');

    const output = document.createElement('g');
    track.appendChild(output);

    output.setAttribute('transform',
      `translate(${this.position[0]},${this.position[1]})`);

    for (const text of this.allTexts) {
      if (!text.text.visible) continue;

      const g = pixiTextToSvg(text.text);
      output.appendChild(g);
    }

    for (let key in this.tickTexts) {
      for (let text of this.tickTexts[key]) {
        let g = pixiTextToSvg(text);
        output.appendChild(g);

        g = svgLine(
          text.x,
          this.dimensions[1],
          text.x,
          this.dimensions[1] - TICK_HEIGHT,
          1,
          TICK_COLOR,
        );

        output.appendChild(g);
      }
    }

    return [base, track];
  }
}

export default HorizontalChromosomeLabels;
<|endoftext|>


<commit_before>function streamVideo(videoElement)
{
	//use getUserMedia() to stream the webcam video
	if (getUserMedia)
	{
		console.log("Calling getUserMedia()...");
		getUserMedia(
			{'audio':false, 'video':true},
			function(localMediaStream)
			{
				console.log("User has granted access to local media.");

				var localMediaStreamUrl = URL.createObjectURL(localMediaStream);
				console.log('Local media stream URL: ' + localMediaStreamUrl);

				//call wrapper to attach the media stream to the video element
				console.log('Attaching local media stream...');
				attachMediaStream(videoElement, localMediaStream);
				console.log('Done.');
			},
			function(error)
			{
				errorMsg = 'ERROR: getUserMedia(): ' + JSON.stringify(error);
				console.log(errorMsg);
				alert(errorMsg);
			}
		);
	} else {
		errorMsg = 'ERROR: Your browser does not support getUserMedia()';
		console.log(errorMsg);
		alert(errorMsg);
	}
}<commit_msg>Using console.error() when getUserMedia() fails<commit_after>function streamVideo(videoElement)
{
	//use getUserMedia() to stream the webcam video
	if (getUserMedia)
	{
		console.log("Calling getUserMedia()...");
		getUserMedia(
			{'audio':false, 'video':true},
			function(localMediaStream)
			{
				console.log("User has granted access to local media.");

				var localMediaStreamUrl = URL.createObjectURL(localMediaStream);
				console.log('Local media stream URL: ' + localMediaStreamUrl);

				//call wrapper to attach the media stream to the video element
				console.log('Attaching local media stream...');
				attachMediaStream(videoElement, localMediaStream);
				console.log('Done.');
			},
			function(error)
			{
				errorMsg = 'ERROR: getUserMedia(): ' + JSON.stringify(error);
				console.error(errorMsg);
				alert(errorMsg);
			}
		);
	} else {
		errorMsg = 'ERROR: Your browser does not support getUserMedia()';
		console.error(errorMsg);
		alert(errorMsg);
	}
}<|endoftext|>


<commit_before>// Tic-Tac-Toe with Log
// March 5, 2016 by James Savard

// set needed variables
var selected;
var winningCombinations;
var counter = 0;
var squaresFilled = 0;
var gameOver = false;
var content = [];
var player = "X"; // initial player is always X
var otherplayer = "O"; // initial other player is O (for blocking purposes initially)
var isGameOver = false;
var chosenSquare = false;

// on load, set up the arrays
window.onload = function() {
	selected = [];
	document.getElementById("textMessage").innerHTML = "";

	// set the winning combinations array
	winningCombinations = [[0,1,2],[3,4,5],[6,7,8],[0,3,6],[1,4,7],[2,5,8],[0,4,8],[2,4,6]];

	// deselect all squares
	for(var l = 0; l <= 8; l++) {
		selected[l] = false;
		content[l] = '';
	}

	// choose a move for the current player
	var i = 0;
	do {
		chooseMove(player);
		i++;
	}
	while (i < 9 && gameOver === false);

};

// choose a move to make
function chooseMove(player) {
	"use strict";
	if (isGameOver === false) {
		if (chosenSquare === false) {
			chosenSquare = winCheck(player);
		}
		if (chosenSquare === false) {
			chosenSquare = blockCheck(player,otherplayer);
		}
		if (chosenSquare === false) {
			chosenSquare = otherCheck();
		}
		isGameOver = squareClicked(chosenSquare);
		chosenSquare = false;
	}
}

function wait(msecs)
{
var start = new Date().getTime();
var cur = start
while(cur - start < msecs)
{
cur = new Date().getTime();
}
}

// game functions
function squareClicked(squareNumber) {
	"use strict";
	var verbosePositions = [['Top Left'],['Top Centre'],['Top Right'],['Middle Left'],['Middle Centre'],['Middle Right'],['Bottom Left'],['Bottom Middle'],['Bottom Right']];
	var theSquare = "square" + (squareNumber+1); // + 1 because the HTML board is 1-9 instead of 0-8
	var currentSquare;
	var entry;
	var entryText;
	var c = document.getElementById(theSquare);
	var xlist = document.getElementById('xlist');
	var olist = document.getElementById('olist');
	var cxt = c.getContext("2d");

	// if this square is not already selected and the game is not over, proceed
	if (((selected[squareNumber]) === false) && (gameOver === false)) {
		if (counter%2 === 0) {
			cxt.beginPath();
			cxt.moveTo(5,5);
			cxt.lineTo(35,35);
			cxt.moveTo(35,5);
			cxt.lineTo(5,35);
			cxt.stroke();
			cxt.closePath();
			content[squareNumber] = 'X';
		} else {
			cxt.beginPath();
			cxt.arc(20,20,15,0,Math.PI*2,true);
			cxt.stroke();
			cxt.closePath();
			content[squareNumber] = 'O';
		}
		counter++;
		alert('Click for Next Move');
		document.getElementById("textMessage").innerHTML = "";
		selected[squareNumber] = true;

		// add moves to the log
		if (content[squareNumber] === 'X') {
			currentSquare = squareNumber;
			entryText = 'X takes square ' + verbosePositions[currentSquare];
			entry = document.createElement('li');
			entry.appendChild(document.createTextNode(entryText));
			xlist.appendChild(entry);
		} else {
			currentSquare = squareNumber;
			entryText = 'O takes square ' + verbosePositions[currentSquare];
			entry = document.createElement('li');
			entry.appendChild(document.createTextNode(entryText));
			olist.appendChild(entry);
		}
		squaresFilled++;

		// switch to the other player
		if (player === "X") {
			player = "O";
			otherplayer = "X";
		} else {
			player = "X";
			otherplayer = "O";
		}

		// check for a winner
		checkForAWinner(content[squareNumber]);
		if (squaresFilled === 9) {
			document.getElementById("textMessage").innerHTML = "This game is a draw.
Click here to play again!";
			gameOver = true;
			return true;
		}
		return false;

	}
}

function checkForAWinner(symbol) {
	"use strict";
	var a;
	for(a = 0; a < winningCombinations.length; a++) {
		if (content[winningCombinations[a][0]] === symbol && content[winningCombinations[a][1]] === symbol && content[winningCombinations[a][2]] === symbol) {
			document.getElementById("textMessage").innerHTML= symbol + " is the winner!
Click here to play again!";
			gameOver = true;
		}
	}
}

// check for a win opportunity
function winCheck(player) {
	"use strict";
    if(content[0] === player && content[1] === player && content[2] === "") {
        return 2;
    }
    else if(content[1] === player && content[2] === player && content[0] === "") {
        return 0;
    }
    else if(content[3] === player && content[4] === player && content[5] === "") {
        return 5;
    }
    else if(content[4] === player && content[5] === player && content[3] === "") {
        return 3;
    }
    else if(content[6] === player && content[7] === player && content[8] === "") {
        return 8;
    }
    else if(content[7] === player && content[8] === player && content[6] === "") {
        return 6;
    }
    else if(content[0] === player && content[4] === player && content[8] === "") {
        return 8;
    }
    else if(content[4] === player && content[8] === player && content[0] === "") {
        return 0;
    }
    else if(content[2] === player && content[4] === player && content[6] === "") {
        return 6;
    }
    else if(content[6] === player && content[4] === player && content[2] === "") {
        return 2;
    }
    else if(content[0] === player && content[2] === player && content[1] === "") {
        return 1;
    }
    else if(content[3] === player && content[5] === player && content[4] === "") {
        return 4;
    }
    else if(content[6] === player && content[8] === player && content[7] === "") {
        return 7;
    }
    else if(content[0] === player && content[6] === player && content[3] === "") {
        return 3;
    }
    else if(content[1] === player && content[7] === player && content[4] === "") {
        return 4;
    }
    else if(content[2] === player && content[8] === player && content[5] === "") {
        return 5;
    }
    else if(content[0] === player && content[4] === player && content[8] === "") {
        return 8;
    }
    else if(content[3] === player && content[6] === player && content[0] === "") {
        return 0;
    }
    else if(content[4] === player && content[7] === player && content[1] === "") {
        return 1;
    }
    else if(content[5] === player && content[8] === player && content[2] === "") {
        return 2;
    }
    else if(content[0] === player && content[3] === player && content[6] === "") {
        return 6;
    }
    else if(content[1] === player && content[4] === player && content[7] === "") {
        return 7;
    }
    else if(content[2] === player && content[5] === player && content[8] === "") {
        return 8;
    }
    else if(content[0] === player && content[8] === player && content[4] === "") {
        return 4;
    }
    else if(content[2] === player && content[6] === player && content[4] === "") {
        return 4;
    } else {
		return false;
	}
}

// check for a block opportunity
function blockCheck(player,otherplayer) {
	"use strict";
    if(content[0] === otherplayer && content[1] === otherplayer && content[2] === "") {
        return 2;
    }
    else if(content[1] === otherplayer && content[2] === otherplayer && content[0] === "") {
        return 0;
    }
    else if(content[3] === otherplayer && content[4] === otherplayer && content[5] === "") {
        return 5;
    }
    else if(content[4] === otherplayer && content[5] === otherplayer && content[3] === "") {
        return 3;
    }
    else if(content[6] === otherplayer && content[7] === otherplayer && content[8] === "") {
        return 8;
    }
    else if(content[7] === otherplayer && content[8] === otherplayer && content[6] === "") {
        return 6;
    }
    else if(content[0] === otherplayer && content[4] === otherplayer && content[8] === "") {
        return 8;
    }
    else if(content[4] === otherplayer && content[8] === otherplayer && content[0] === "") {
        return 0;
    }
    else if(content[2] === otherplayer && content[4] === otherplayer && content[6] === "") {
        return 6;
    }
    else if(content[6] === otherplayer && content[4] === otherplayer && content[2] === "") {
        return 2;
    }
    else if(content[0] === otherplayer && content[2] === otherplayer && content[1] === "") {
        return 1;
    }
    else if(content[3] === otherplayer && content[5] === otherplayer && content[4] === "") {
        return 4;
    }
    else if(content[6] === otherplayer && content[8] === otherplayer && content[7] === "") {
        return 7;
    }
    else if(content[0] === otherplayer && content[6] === otherplayer && content[3] === "") {
        return 3;
    }
    else if(content[1] === otherplayer && content[7] === otherplayer && content[4] === "") {
        return 4;
    }
    else if(content[2] === otherplayer && content[8] === otherplayer && content[5] === "") {
        return 5;
    }
    else if(content[0] === otherplayer && content[4] === otherplayer && content[8] === "") {
        return 8;
    }
    else if(content[3] === otherplayer && content[6] === otherplayer && content[0] === "") {
        return 0;
    }
    else if(content[4] === otherplayer && content[7] === otherplayer && content[1] === "") {
        return 1;
    }
    else if(content[5] === otherplayer && content[8] === otherplayer && content[2] === "") {
        return 2;
    }
    else if(content[0] === otherplayer && content[3] === otherplayer && content[6] === "") {
        return 6;
    }
    else if(content[1] === otherplayer && content[4] === otherplayer && content[7] === "") {
        return 7;
    }
    else if(content[2] === otherplayer && content[5] === otherplayer && content[8] === "") {
        return 8;
    }
    else if(content[0] === otherplayer && content[8] === otherplayer && content[4] === "") {
        return 4;
    }
    else if(content[2] === otherplayer && content[6] === otherplayer && content[4] === "") {
        return 4;
    } else {
		return false;
	}
}

// check next best opportunity other than winning or blocking
function otherCheck() {
	"use strict";
	if(content[4] === "") {
		return 4;
	}
	else if(content[0] === "") {
		return 0;
	}
	else if(content[8] === "") {
		return 8;
	}
	else if(content[5] === "") {
		return 5;
	}
	else if(content[1] === "") {
		return 1;
	}
	else if(content[7] === "") {
		return 7;
	}
	else if(content[2] === "") {
		return 2;
	}
	else if(content[6] === "") {
		return 6;
	}
	else if(content[3] === "") {
		return 3;
	} else {
		return false;
	}
}<commit_msg>Added files via upload<commit_after>// Tic-Tac-Toe with Log
// March 6, 2016 by James Savard

// set needed variables
var selected;
var winningCombinations;
var counter = 0;
var squaresFilled = 0;
var gameOver = false;
var content = [];
var player = "X"; // initial player is always X
var otherplayer = "O"; // initial other player is O (for blocking purposes initially)
var isGameOver = false;
var chosenSquare = false;

// on load, set up the arrays
window.onload = function() {
	selected = [];
	document.getElementById("textMessage").innerHTML = "";

	// set the winning combinations array
	winningCombinations = [[0,1,2],[3,4,5],[6,7,8],[0,3,6],[1,4,7],[2,5,8],[0,4,8],[2,4,6]];

	// deselect all squares
	for(var l = 0; l <= 8; l++) {
		selected[l] = false;
		content[l] = '';
	}

	// choose a move for the current player
	var i = 0;
	do {
		chooseMove(player);
		i++;
	}
	while (i < 9 && gameOver === false);

};

// choose a move to make
function chooseMove(player) {
	"use strict";
	if (isGameOver === false) {
		if (chosenSquare === false) {
			chosenSquare = winCheck(player);
		}
		if (chosenSquare === false) {
			chosenSquare = blockCheck(player,otherplayer);
		}
		if (chosenSquare === false) {
			chosenSquare = otherCheck();
		}
		isGameOver = squareClicked(chosenSquare);
		chosenSquare = false;
	}
}

function wait(msecs)
{
var start = new Date().getTime();
var cur = start
while(cur - start < msecs)
{
cur = new Date().getTime();
}
}

// game functions
function squareClicked(squareNumber) {
	"use strict";
	var verbosePositions = [['Top Left'],['Top Centre'],['Top Right'],['Middle Left'],['Middle Centre'],['Middle Right'],['Bottom Left'],['Bottom Middle'],['Bottom Right']];
	var theSquare = "square" + (squareNumber+1); // + 1 because the HTML board is 1-9 instead of 0-8
	var currentSquare;
	var entry;
	var entryText;
	var c = document.getElementById(theSquare);
	var xlist = document.getElementById('xlist');
	var olist = document.getElementById('olist');
	var cxt = c.getContext("2d");

	// if this square is not already selected and the game is not over, proceed
	if (((selected[squareNumber]) === false) && (gameOver === false)) {
		if (counter%2 === 0) {
			cxt.beginPath();
			cxt.moveTo(5,5);
			cxt.lineTo(35,35);
			cxt.moveTo(35,5);
			cxt.lineTo(5,35);
			cxt.stroke();
			cxt.closePath();
			content[squareNumber] = 'X';
		} else {
			cxt.beginPath();
			cxt.arc(20,20,15,0,Math.PI*2,true);
			cxt.stroke();
			cxt.closePath();
			content[squareNumber] = 'O';
		}
		counter++;

		document.getElementById("textMessage").innerHTML = "";
		selected[squareNumber] = true;

		// add moves to the log
		if (content[squareNumber] === 'X') {
			currentSquare = squareNumber;
			entryText = 'X takes square ' + verbosePositions[currentSquare];
			entry = document.createElement('li');
			entry.appendChild(document.createTextNode(entryText));
			xlist.appendChild(entry);
		} else {
			currentSquare = squareNumber;
			entryText = 'O takes square ' + verbosePositions[currentSquare];
			entry = document.createElement('li');
			entry.appendChild(document.createTextNode(entryText));
			olist.appendChild(entry);
		}
		squaresFilled++;
		alert(entryText + ' - click for Next Move');
		// switch to the other player
		if (player === "X") {
			player = "O";
			otherplayer = "X";
		} else {
			player = "X";
			otherplayer = "O";
		}

		// check for a winner
		checkForAWinner(content[squareNumber]);
		if (squaresFilled === 9) {
			document.getElementById("textMessage").innerHTML = "This game is a draw.
Click here to play again!";
			gameOver = true;
			return true;
		}
		return false;

	}
}

function checkForAWinner(symbol) {
	"use strict";
	var a;
	for(a = 0; a < winningCombinations.length; a++) {
		if (content[winningCombinations[a][0]] === symbol && content[winningCombinations[a][1]] === symbol && content[winningCombinations[a][2]] === symbol) {
			document.getElementById("textMessage").innerHTML= symbol + " is the winner!
Click here to play again!";
			gameOver = true;
		}
	}
}

// check for a win opportunity
function winCheck(player) {
	"use strict";
    if(content[0] === player && content[1] === player && content[2] === "") {
        return 2;
    }
    else if(content[1] === player && content[2] === player && content[0] === "") {
        return 0;
    }
    else if(content[3] === player && content[4] === player && content[5] === "") {
        return 5;
    }
    else if(content[4] === player && content[5] === player && content[3] === "") {
        return 3;
    }
    else if(content[6] === player && content[7] === player && content[8] === "") {
        return 8;
    }
    else if(content[7] === player && content[8] === player && content[6] === "") {
        return 6;
    }
    else if(content[0] === player && content[4] === player && content[8] === "") {
        return 8;
    }
    else if(content[4] === player && content[8] === player && content[0] === "") {
        return 0;
    }
    else if(content[2] === player && content[4] === player && content[6] === "") {
        return 6;
    }
    else if(content[6] === player && content[4] === player && content[2] === "") {
        return 2;
    }
    else if(content[0] === player && content[2] === player && content[1] === "") {
        return 1;
    }
    else if(content[3] === player && content[5] === player && content[4] === "") {
        return 4;
    }
    else if(content[6] === player && content[8] === player && content[7] === "") {
        return 7;
    }
    else if(content[0] === player && content[6] === player && content[3] === "") {
        return 3;
    }
    else if(content[1] === player && content[7] === player && content[4] === "") {
        return 4;
    }
    else if(content[2] === player && content[8] === player && content[5] === "") {
        return 5;
    }
    else if(content[0] === player && content[4] === player && content[8] === "") {
        return 8;
    }
    else if(content[3] === player && content[6] === player && content[0] === "") {
        return 0;
    }
    else if(content[4] === player && content[7] === player && content[1] === "") {
        return 1;
    }
    else if(content[5] === player && content[8] === player && content[2] === "") {
        return 2;
    }
    else if(content[0] === player && content[3] === player && content[6] === "") {
        return 6;
    }
    else if(content[1] === player && content[4] === player && content[7] === "") {
        return 7;
    }
    else if(content[2] === player && content[5] === player && content[8] === "") {
        return 8;
    }
    else if(content[0] === player && content[8] === player && content[4] === "") {
        return 4;
    }
    else if(content[2] === player && content[6] === player && content[4] === "") {
        return 4;
    } else {
		return false;
	}
}

// check for a block opportunity
function blockCheck(player,otherplayer) {
	"use strict";
    if(content[0] === otherplayer && content[1] === otherplayer && content[2] === "") {
        return 2;
    }
    else if(content[1] === otherplayer && content[2] === otherplayer && content[0] === "") {
        return 0;
    }
    else if(content[3] === otherplayer && content[4] === otherplayer && content[5] === "") {
        return 5;
    }
    else if(content[4] === otherplayer && content[5] === otherplayer && content[3] === "") {
        return 3;
    }
    else if(content[6] === otherplayer && content[7] === otherplayer && content[8] === "") {
        return 8;
    }
    else if(content[7] === otherplayer && content[8] === otherplayer && content[6] === "") {
        return 6;
    }
    else if(content[0] === otherplayer && content[4] === otherplayer && content[8] === "") {
        return 8;
    }
    else if(content[4] === otherplayer && content[8] === otherplayer && content[0] === "") {
        return 0;
    }
    else if(content[2] === otherplayer && content[4] === otherplayer && content[6] === "") {
        return 6;
    }
    else if(content[6] === otherplayer && content[4] === otherplayer && content[2] === "") {
        return 2;
    }
    else if(content[0] === otherplayer && content[2] === otherplayer && content[1] === "") {
        return 1;
    }
    else if(content[3] === otherplayer && content[5] === otherplayer && content[4] === "") {
        return 4;
    }
    else if(content[6] === otherplayer && content[8] === otherplayer && content[7] === "") {
        return 7;
    }
    else if(content[0] === otherplayer && content[6] === otherplayer && content[3] === "") {
        return 3;
    }
    else if(content[1] === otherplayer && content[7] === otherplayer && content[4] === "") {
        return 4;
    }
    else if(content[2] === otherplayer && content[8] === otherplayer && content[5] === "") {
        return 5;
    }
    else if(content[0] === otherplayer && content[4] === otherplayer && content[8] === "") {
        return 8;
    }
    else if(content[3] === otherplayer && content[6] === otherplayer && content[0] === "") {
        return 0;
    }
    else if(content[4] === otherplayer && content[7] === otherplayer && content[1] === "") {
        return 1;
    }
    else if(content[5] === otherplayer && content[8] === otherplayer && content[2] === "") {
        return 2;
    }
    else if(content[0] === otherplayer && content[3] === otherplayer && content[6] === "") {
        return 6;
    }
    else if(content[1] === otherplayer && content[4] === otherplayer && content[7] === "") {
        return 7;
    }
    else if(content[2] === otherplayer && content[5] === otherplayer && content[8] === "") {
        return 8;
    }
    else if(content[0] === otherplayer && content[8] === otherplayer && content[4] === "") {
        return 4;
    }
    else if(content[2] === otherplayer && content[6] === otherplayer && content[4] === "") {
        return 4;
    } else {
		return false;
	}
}

// check next best opportunity other than winning or blocking
function otherCheck() {
	"use strict";
	if(content[4] === "") {
		return 4;
	}
	else if(content[0] === "") {
		return 0;
	}
	else if(content[8] === "") {
		return 8;
	}
	else if(content[5] === "") {
		return 5;
	}
	else if(content[1] === "") {
		return 1;
	}
	else if(content[7] === "") {
		return 7;
	}
	else if(content[2] === "") {
		return 2;
	}
	else if(content[6] === "") {
		return 6;
	}
	else if(content[3] === "") {
		return 3;
	} else {
		return false;
	}
}<|endoftext|>


<commit_before>'use strict';

/**
 * @ngdoc directive
 * @name vnToolboxCommonApp.directive:vnPriceSearch
 * @description
 * # vnPriceSearch
 */
angular.module('Volusion.toolboxCommon')
	.directive('vnPriceSearch', ['vnProductParams', function (vnProductParams) {
		return {
			templateUrl: 'vn-faceted-search/vn-price-search.html',
			restrict   : 'AE',
			scope      : {
				queryProducts: '&'
			},
			link       : function postLink(scope) {

				scope.searchByPrice = function (event) {

					vnProductParams.setMinPrice(scope.minPrice);
					vnProductParams.setMaxPrice(scope.maxPrice);

					scope.$watch(
						function() {
							return vnProductParams.getMinPrice();
						},
						function(min) {
							scope.minPrice = min;
						}
					);

					scope.$watch(
						function() {
							return vnProductParams.getMaxPrice();
						},
						function(min) {
							scope.maxPrice = min;
						}
					);

					vnProductParams.setMinPrice(scope.minPrice);
					vnProductParams.setMaxPrice(scope.maxPrice);

					if (event.which === 13) {
						scope.queryProducts();
					}

				};
			}
		};
	}]);
<commit_msg>Add documentation for vnPriceSearch<commit_after>'use strict';

/**
 * @ngdoc directive
 * @name vnToolboxCommonApp.directive:vnPriceSearch
 * @restrict EA
 * @requires vnProductParams
 * @description
 * - Implewments search by price for a min::max range
 * $watches via vnProductParams.getMinPrice() for resetting the field
 * $watches via vnProductParams.getMaxPrice() for resetting the field
 *
 * Inherits the parent $controller's queryProducts function and calls if enter is keyed
 * The parent controller is responsible for resetting these values to nil as needed.
 *
 */
angular.module('Volusion.toolboxCommon')
	.directive('vnPriceSearch', ['vnProductParams', function (vnProductParams) {
		return {
			templateUrl: 'vn-faceted-search/vn-price-search.html',
			restrict   : 'AE',
			scope      : {
				queryProducts: '&'
			},
			link       : function postLink(scope) {

				scope.searchByPrice = function (event) {

					vnProductParams.setMinPrice(scope.minPrice);
					vnProductParams.setMaxPrice(scope.maxPrice);

					scope.$watch(
						function() {
							return vnProductParams.getMinPrice();
						},
						function(min) {
							scope.minPrice = min;
						}
					);

					scope.$watch(
						function() {
							return vnProductParams.getMaxPrice();
						},
						function(min) {
							scope.maxPrice = min;
						}
					);

					vnProductParams.setMinPrice(scope.minPrice);
					vnProductParams.setMaxPrice(scope.maxPrice);

					if (event.which === 13) {
						scope.queryProducts();
					}

				};
			}
		};
	}]);
<|endoftext|>


<commit_before>var url = './data/ams_stadhouderskade_5-01-2017.geojson';

map.on('load', function() {
 var filterHour = ['==', 'Hour', 12];
 var filterDay = ['!=', 'Day', 'Bob'];
 var filterPollutant = ['==', 'Pollutant', 'NO2'];

 map.getSource('pollutants').setData(url);
 map.addSource('pollutants', {
            type: 'geojson',
            data: url
          });
 map.addLayer({
                id: 'pollutants',
                type: 'circle',
                filter: ['all', filterHour, filterDay, filterPollutant],
                source: 'pollutants',
                paint: {
                  'circle-radius': {
                    property: 'Concentration',
                    stops: [
                      [0, 3],
                      [150, 15] ]
                  },
                  'circle-color': {
                    property: 'Concentration',
                    stops: [
                      [0, '#2DC4B2'],
                      [25, '#3BB3C3'],
                      [75, '#669EC4'],
                      [100, '#8B88B6'],
                      [125, '#A2719B'],
                      [150, '#AA5E79'] ]
                  },
                  'circle-opacity': 0.8

    }, 'admin-2-boundaries-dispute'}); // place the layer beneath this layer in the basemap

 });

document.getElementById('slider').addEventListener('input', function(e) {
                  // get the current hour as an integer

                  var hour = parseInt(e.target.value); //string argument
                  //hour = hour < 10 ? '0' + '' + hour + ':00:00+02:00': hour;
                  // map.setFilter(layer-name, filter)
                  filterHour = ['==', 'Hour', hour];
                  map.setFilter('pollutants', ['all', filterHour, filterDay]);

                  // converting 0-23 hour to AMPM format
                  var ampm = hour >= 12 ? 'PM' : 'AM';
                  var hour12 = hour % 12 ? hour % 12 : 12;
                  // update text in the UI
                  document.getElementById('active-hour').innerText = hour12 + ampm;
});

document.getElementById('filters').addEventListener('change', function(e) {
                  var day = e.target.value;
                  if (day === 'all') {
                    // `null` would not work for combining filters
                    filterDay = ['!=', 'Day', 'Bob'];
                  } else if (day === 'weekday') {
                    filterDay = ['!in', 'Day', 'Sat', 'Sun'];
                  } else if (day === 'weekend') {
                    filterDay = ['in', 'Day', 'Sat', 'Sun'];
                  } else {
                    console.log('error');
                  }
                  map.setFilter('pollutants', filterHour, filterDay, filterPollutant);
});

/*
map.on('load', function() {
  map.addLayer({
    id: 'collisions',
    type: 'circle',
    filter: ['==', 'Hour', 12],
    source: {
      type: 'geojson',
      data: 'data/stadhouderskade_5-01-2017.geojson'
    },
    paint: {
      'circle-radius': {
        property: 'Casualty',
        stops: [
          [0, 3],
          [5, 15]
        ]
      },
      'circle-color': {
        property: 'Casualty',
        stops: [
          [0, '#2DC4B2'],
          [1, '#3BB3C3'],
          [2, '#669EC4'],
          [3, '#8B88B6'],
          [4, '#A2719B'],
          [5, '#AA5E79']
        ]
      },
      'circle-opacity': 0.8
    }
  }, 'admin-2-boundaries-dispute'); // place the layer beneath this layer in the basemap
});

document.getElementById('slider').addEventListener('input', function(e) {
  // get the current hour as an integer
  var hour = parseInt(e.target.value);
  // map.setFilter(layer-name, filter)
  map.setFilter('collisions', ['==', 'Hour', hour]);

  // converting 0-23 hour to AMPM format
  var ampm = hour >= 12 ? 'PM' : 'AM';
  var hour12 = hour % 12 ? hour % 12 : 12;
  // update text in the UI
  document.getElementById('active-hour').innerText = hour12 + ampm;
});

document.getElementById('filters').addEventListener('change', function(e) {
  var day = e.target.value;
  var filterDay;
  if (day === 'all') {
    filterDay = null;
  } else if (day === 'weekday') {
    filterDay = ['!in', 'Day', 'Sat', 'Sun'];
  } else if (day === 'weekend') {
    filterDay = ['in', 'Day', 'Sat', 'Sun'];
  } else {
    console.log('error');
  }
  map.setFilter('collisions', filterDay);
});
*/

<commit_msg>Update timeFilters.js<commit_after>var url = './data/ams_stadhouderskade_5-01-2017.geojson';

map.on('load', function() {
 var filterHour = ['==', 'Hour', 12];
 var filterDay = ['!=', 'Day', 'Bob'];
 var filterPollutant = ['==', 'Pollutant', 'NO2'];

 map.getSource('pollutants').setData(url);
 map.addSource('pollutants', {
            type: 'geojson',
            data: url
          });
 map.addLayer({
                id: 'pollutants',
                type: 'circle',
                filter: ['all', filterHour, filterDay, filterPollutant],
                source: 'pollutants',
                paint: {
                  'circle-radius': {
                    property: 'Concentration',
                    stops: [
                      [0, 3],
                      [150, 15] ]
                  },
                  'circle-color': {
                    property: 'Concentration',
                    stops: [
                      [0, '#2DC4B2'],
                      [25, '#3BB3C3'],
                      [75, '#669EC4'],
                      [100, '#8B88B6'],
                      [125, '#A2719B'],
                      [150, '#AA5E79'] ]
                  },
                  'circle-opacity': 0.8

    }, 'admin-2-boundaries-dispute'}); // place the layer beneath this layer in the basemap

 });

document.getElementById('slider').addEventListener('input', function(e) {
                  // get the current hour as an integer

                  var hour = parseInt(e.target.value); //string argument
                  //hour = hour < 10 ? '0' + '' + hour + ':00:00+02:00': hour;
                  // map.setFilter(layer-name, filter)
                  filterHour = ['==', 'Hour', hour];
                  //map.setFilter('pollutants', ['all', filterHour, filterDay]);
                  map.setFilter('pollutants', ['==', 'Hour', hour]);

                  // converting 0-23 hour to AMPM format
                  var ampm = hour >= 12 ? 'PM' : 'AM';
                  var hour12 = hour % 12 ? hour % 12 : 12;
                  // update text in the UI
                  document.getElementById('active-hour').innerText = hour12 + ampm;
});

document.getElementById('filters').addEventListener('change', function(e) {
                  var day = e.target.value;
                  if (day === 'all') {
                    // `null` would not work for combining filters
                    filterDay = ['!=', 'Day', 'Bob'];
                  } else if (day === 'weekday') {
                    filterDay = ['!in', 'Day', 'Sat', 'Sun'];
                  } else if (day === 'weekend') {
                    filterDay = ['in', 'Day', 'Sat', 'Sun'];
                  } else {
                    console.log('error');
                  }
                  map.setFilter('pollutants', filterHour, filterDay, filterPollutant);
});

/*
map.on('load', function() {
  map.addLayer({
    id: 'collisions',
    type: 'circle',
    filter: ['==', 'Hour', 12],
    source: {
      type: 'geojson',
      data: 'data/stadhouderskade_5-01-2017.geojson'
    },
    paint: {
      'circle-radius': {
        property: 'Casualty',
        stops: [
          [0, 3],
          [5, 15]
        ]
      },
      'circle-color': {
        property: 'Casualty',
        stops: [
          [0, '#2DC4B2'],
          [1, '#3BB3C3'],
          [2, '#669EC4'],
          [3, '#8B88B6'],
          [4, '#A2719B'],
          [5, '#AA5E79']
        ]
      },
      'circle-opacity': 0.8
    }
  }, 'admin-2-boundaries-dispute'); // place the layer beneath this layer in the basemap
});

document.getElementById('slider').addEventListener('input', function(e) {
  // get the current hour as an integer
  var hour = parseInt(e.target.value);
  // map.setFilter(layer-name, filter)
  map.setFilter('collisions', ['==', 'Hour', hour]);

  // converting 0-23 hour to AMPM format
  var ampm = hour >= 12 ? 'PM' : 'AM';
  var hour12 = hour % 12 ? hour % 12 : 12;
  // update text in the UI
  document.getElementById('active-hour').innerText = hour12 + ampm;
});

document.getElementById('filters').addEventListener('change', function(e) {
  var day = e.target.value;
  var filterDay;
  if (day === 'all') {
    filterDay = null;
  } else if (day === 'weekday') {
    filterDay = ['!in', 'Day', 'Sat', 'Sun'];
  } else if (day === 'weekend') {
    filterDay = ['in', 'Day', 'Sat', 'Sun'];
  } else {
    console.log('error');
  }
  map.setFilter('collisions', filterDay);
});
*/

<|endoftext|>


<commit_before>(function( hx ) {

    var vendorPatch = function( options ) {

        options = $.extend({
            vendors: {
                webkit: 'webkit',
                moz: 'firefox',
                o: 'opera',
                ms: 'msie'
            },
            events: {
                webkit: 'webkitTransitionEnd',
                moz: 'transitionend',
                o: 'oTransitionEnd',
                ms: 'transitionend'
            },
            prefixProps: [ 'transition' , 'transform' ]
        }, (options || {}));

        $.extend( this , options );

        this._init();
    };

    vendorPatch.prototype = {
        _init: function() {
            this._getUserAgent();
        },
        _getUserAgent: function() {
            var uaString = navigator.userAgent;
            for (var key in this.vendors) {
                var re = new RegExp( this.vendors[key] , 'i' );
                if (re.test( uaString )) {
                    this.ua = key;
                    break;
                }
            }
        },
        getEventType: function() {
            return this.events[ this.ua ];
        },
        getPrefixed: function( str ) {
            for (var i = 0; i < this.prefixProps.length; i++) {
                var re = new RegExp( '(?!-)' + this.prefixProps[i] + '(?!-)' , 'g' );
                var match = re.exec( str );
                if (match)
                    str = str.replace( re , ('-' + this.ua + '-' + match[0]) );
            }
            return str;
        },
        createEvent: function( type , detail ) {

            if (!type)
                return;

            detail = detail || {};

            var evt = {};

            try {
                evt = new CustomEvent( type , {
                    bubbles: true,
                    cancelable: true,
                    detail: detail
                });
            } catch( err ) {
                evt = document.createEvent('Event');
                evt.initEvent( type , true , true );
                evt.detail = detail;
            }

            return evt;
        },
        /*addEventListener: function( target , listener ) {
            var evt = this.getEventType();
            target.addEventListener( evt , listener );
        },
        removeEventListener: function( target , listener ) {
            var evt = this.getEventType();
            target.removeEventListener( evt , listener );
        },*/
        getComputedMatrix: function( manager ) {
            var style = window.getComputedStyle( manager.element );
            var transform = this.ua + 'Transform';
            return style[transform] || style.transform;
        }
    };

    $.extend( hx , {vendorPatch: vendorPatch} );

}( hxManager ));

<commit_msg>removed commented lines<commit_after>(function( hx ) {

    var vendorPatch = function( options ) {

        options = $.extend({
            vendors: {
                webkit: 'webkit',
                moz: 'firefox',
                o: 'opera',
                ms: 'msie'
            },
            events: {
                webkit: 'webkitTransitionEnd',
                moz: 'transitionend',
                o: 'oTransitionEnd',
                ms: 'transitionend'
            },
            prefixProps: [ 'transition' , 'transform' ]
        }, (options || {}));

        $.extend( this , options );

        this._init();
    };

    vendorPatch.prototype = {
        _init: function() {
            this._getUserAgent();
        },
        _getUserAgent: function() {
            var uaString = navigator.userAgent;
            for (var key in this.vendors) {
                var re = new RegExp( this.vendors[key] , 'i' );
                if (re.test( uaString )) {
                    this.ua = key;
                    break;
                }
            }
        },
        getEventType: function() {
            return this.events[ this.ua ];
        },
        getPrefixed: function( str ) {
            for (var i = 0; i < this.prefixProps.length; i++) {
                var re = new RegExp( '(?!-)' + this.prefixProps[i] + '(?!-)' , 'g' );
                var match = re.exec( str );
                if (match)
                    str = str.replace( re , ('-' + this.ua + '-' + match[0]) );
            }
            return str;
        },
        createEvent: function( type , detail ) {

            if (!type)
                return;

            detail = detail || {};

            var evt = {};

            try {
                evt = new CustomEvent( type , {
                    bubbles: true,
                    cancelable: true,
                    detail: detail
                });
            } catch( err ) {
                evt = document.createEvent('Event');
                evt.initEvent( type , true , true );
                evt.detail = detail;
            }

            return evt;
        },
        getComputedMatrix: function( manager ) {
            var style = window.getComputedStyle( manager.element );
            var transform = this.ua + 'Transform';
            return style[transform] || style.transform;
        }
    };

    $.extend( hx , {vendorPatch: vendorPatch} );

}( hxManager ));

<|endoftext|>


<commit_before>jsio('from shared.javascript import Class, bind')
jsio('import ui.Component')

exports = Class(ui.Component, function(supr){

	this._domTag = 'span'
	this._className = 'Value'

	this.init = function(jsArgs, viewArgs) {
		supr(this, 'init')

		this._itemIds = jsArgs[0]
		this._property = viewArgs[0]
	}

	this._createContent = function() {
		this.setDependant(this._itemIds, this._property)
	}

	this.setDependant = function(itemIds, property) {
		if (this._item) { logger.warn("TODO unsubscribe from old item") }
		this._propertyChain = property.split('.')
		var itemId = (typeof itemIds == 'string' ? itemIds
				: itemIds.getId ? itemIds.getId()
				: itemIds[this._propertyChain.shift()])
		this._item = fin.getItem(itemId)
		this._item.addDependant(this._propertyChain, bind(this, '_onItemMutation'))
	}

	this._onItemMutation = function(mutation, newValue) {
		this.setValue(newValue)
	}

	this.setValue = function(value) {
		if (typeof value == 'undefined') { return }
		if (typeof value == 'string') {
			value = value.replace(/\n/g, '
')
			value = value.replace(/ $/, ' ')
		}
		this._element.innerHTML = value
		this._element.className = this._className + ' fin-Value-' + this._property + '-' + value
	}
})<commit_msg>Fix a bug with value-sensitive styling where values with spaces would add multiple class names instead of just one<commit_after>jsio('from shared.javascript import Class, bind')
jsio('import ui.Component')

exports = Class(ui.Component, function(supr){

	this._domTag = 'span'
	this._className = 'Value'

	this.init = function(jsArgs, viewArgs) {
		supr(this, 'init')

		this._itemIds = jsArgs[0]
		this._property = viewArgs[0]
	}

	this._createContent = function() {
		this.setDependant(this._itemIds, this._property)
	}

	this.setDependant = function(itemIds, property) {
		if (this._item) { logger.warn("TODO unsubscribe from old item") }
		this._propertyChain = property.split('.')
		var itemId = (typeof itemIds == 'string' ? itemIds
				: itemIds.getId ? itemIds.getId()
				: itemIds[this._propertyChain.shift()])
		this._item = fin.getItem(itemId)
		this._item.addDependant(this._propertyChain, bind(this, '_onItemMutation'))
	}

	this._onItemMutation = function(mutation, newValue) {
		this.setValue(newValue)
	}

	this.setValue = function(value) {
		if (typeof value == 'undefined') { return }
		if (typeof value == 'string') {
			value = value.replace(/\n/g, '
')
			value = value.replace(/ $/, ' ')
		}
		this._element.innerHTML = value
		var valueClassName = typeof value == 'string' ? value.replace(/ /g, '_') : value
		this._element.className = this._className + ' fin-Value-' + this._property + '-' + valueClassName
	}
})<|endoftext|>


<commit_before>import ko from "knockout";
import $ from "jquery";

import api from "../api";
import log from "./log";
import store from "../store";
import user from "./user";

/* Models a single print job and supplies the data bindings for
 * the print.html template. */

export default class PrintJob {
  constructor(cart) {
    this.cart = cart;
    this._depositCount = null;
    this.status = undefined; /* undefined | 'success' | 'error' | 'waiting' */
    this.errorText = '';
    this.printedPercent = null;
    this.selectedPrinter = undefined;
    // select a default printer as soon as they're loaded
    store.ensureLoaded(() => {
        this.selectedPrinter = this.availablePrinters[0];
    });

    ko.track(this);

    // desired behavior: deposit count is automatically calculated from cart
    // contents, but still overrideable
    ko.defineProperty(this, 'depositCount', {
      get: () => {
        if (this._depositCount !== null) {
          return this._depositCount;
        }
        return this.cart.includesOral ? 1 : 0;
      },
      set: (num) => {
        if (num === '') {
          // the user probably erased the field in the UI after it was
          // automatically set; do the right thing for them.
          this._depositCount = 0;
        }
        else {
          this._depositCount = num;
        }
      },
    });

    // reset print state if settings for the current cart change
    ko.getObservable(this.cart, 'documents').subscribe(() => this.reset());
    ko.getObservable(this.cart, 'name').subscribe(() => this.reset());
    ko.getObservable(this, 'selectedPrinter').subscribe(() => this.reset());
  }

  get availablePrinters() {
    return user.officeConfig.printers;
  }

  get printPrice() {
    return this.cart.priceEstimate(0);
  }

  get totalPrice() {
    return this.cart.priceEstimate(this.depositCount);
  }

  reset() {
    this.status = undefined;
  }

  clearDeposit() {
    // reset to automatic behaviour
    this._depositCount = null;
  }

  submit() {
    this.status = 'waiting';
    this.printedPercent = 0;
    let job = {
      cover_text: this.cart.name,
      cash_box: user.officeConfig.cash_boxes[0],
      document_ids: this.cart.documents.map(doc => doc.id),
      deposit_count: parseInt(this.depositCount),
      price: this.totalPrice,
      printer: this.selectedPrinter,
    };

    // We use event streams to prevent connection timeouts on long-running
    // print requests and to show some progress indication.
    // Unfortunately, EventSource doesn't allow us to put the request data
    // in the body, so we use a cookie instead (~4k bytes limit).
    // Web Sockets may be a more appropriate solution, but are non-trivial
    // to set up on the production server and especially local debug servers.
    $.cookie('print_data', JSON.stringify(job), {path: '/'});
    let stream = new EventSource(api.baseUrl + 'print');
    stream.onerror = () => {
      this.status = 'error';
      this.errorText = 'Verbindung zum Server verloren';
      stream.close();
      $.cookie('print_data', '', {path: '/'});
    };
    let printed = 0;
    stream.addEventListener('progress', (msg) => {
      printed++;
      // #events = #docs + 1 (accounting)
      this.printedPercent = (printed*100.0/(job.document_ids.length+1)).toFixed(0);
      console.log(msg);
    });
    stream.addEventListener('error', (msg) => {
      this.status = 'error';
      this.errorText = msg.data;
      stream.close();
      $.cookie('print_data', '', {path: '/'});
    });
    stream.addEventListener('complete', () => {
      this.status = 'success';
      this.errorText = '';
      log.addItem(this.cart.name, this.totalPrice);
      stream.close();
      $.cookie('print_data', '', {path: '/'});
    });
  }

  get buttonGradient() {
    // primary and disabled button colors stolen from Bootstrap
    return `linear-gradient(to right, #337ab7 ${this.printedPercent}%, #79a7ce ${this.printedPercent}%)`;
  }

  get config() { return store.config; }
}
<commit_msg>vm/printjob: Fix error event name<commit_after>import ko from "knockout";
import $ from "jquery";

import api from "../api";
import log from "./log";
import store from "../store";
import user from "./user";

/* Models a single print job and supplies the data bindings for
 * the print.html template. */

export default class PrintJob {
  constructor(cart) {
    this.cart = cart;
    this._depositCount = null;
    this.status = undefined; /* undefined | 'success' | 'error' | 'waiting' */
    this.errorText = '';
    this.printedPercent = null;
    this.selectedPrinter = undefined;
    // select a default printer as soon as they're loaded
    store.ensureLoaded(() => {
        this.selectedPrinter = this.availablePrinters[0];
    });

    ko.track(this);

    // desired behavior: deposit count is automatically calculated from cart
    // contents, but still overrideable
    ko.defineProperty(this, 'depositCount', {
      get: () => {
        if (this._depositCount !== null) {
          return this._depositCount;
        }
        return this.cart.includesOral ? 1 : 0;
      },
      set: (num) => {
        if (num === '') {
          // the user probably erased the field in the UI after it was
          // automatically set; do the right thing for them.
          this._depositCount = 0;
        }
        else {
          this._depositCount = num;
        }
      },
    });

    // reset print state if settings for the current cart change
    ko.getObservable(this.cart, 'documents').subscribe(() => this.reset());
    ko.getObservable(this.cart, 'name').subscribe(() => this.reset());
    ko.getObservable(this, 'selectedPrinter').subscribe(() => this.reset());
  }

  get availablePrinters() {
    return user.officeConfig.printers;
  }

  get printPrice() {
    return this.cart.priceEstimate(0);
  }

  get totalPrice() {
    return this.cart.priceEstimate(this.depositCount);
  }

  reset() {
    this.status = undefined;
  }

  clearDeposit() {
    // reset to automatic behaviour
    this._depositCount = null;
  }

  submit() {
    this.status = 'waiting';
    this.printedPercent = 0;
    let job = {
      cover_text: this.cart.name,
      cash_box: user.officeConfig.cash_boxes[0],
      document_ids: this.cart.documents.map(doc => doc.id),
      deposit_count: parseInt(this.depositCount),
      price: this.totalPrice,
      printer: this.selectedPrinter,
    };

    // We use event streams to prevent connection timeouts on long-running
    // print requests and to show some progress indication.
    // Unfortunately, EventSource doesn't allow us to put the request data
    // in the body, so we use a cookie instead (~4k bytes limit).
    // Web Sockets may be a more appropriate solution, but are non-trivial
    // to set up on the production server and especially local debug servers.
    $.cookie('print_data', JSON.stringify(job), {path: '/'});
    let stream = new EventSource(api.baseUrl + 'print');
    stream.onerror = () => {
      this.status = 'error';
      this.errorText = 'Verbindung zum Server verloren';
      stream.close();
      $.cookie('print_data', '', {path: '/'});
    };
    let printed = 0;
    stream.addEventListener('progress', (msg) => {
      printed++;
      // #events = #docs + 1 (accounting)
      this.printedPercent = (printed*100.0/(job.document_ids.length+1)).toFixed(0);
      console.log(msg);
    });
    stream.addEventListener('stream-error', (msg) => {
      this.status = 'error';
      this.errorText = msg.data;
      stream.close();
      $.cookie('print_data', '', {path: '/'});
    });
    stream.addEventListener('complete', () => {
      this.status = 'success';
      this.errorText = '';
      log.addItem(this.cart.name, this.totalPrice);
      stream.close();
      $.cookie('print_data', '', {path: '/'});
    });
  }

  get buttonGradient() {
    // primary and disabled button colors stolen from Bootstrap
    return `linear-gradient(to right, #337ab7 ${this.printedPercent}%, #79a7ce ${this.printedPercent}%)`;
  }

  get config() { return store.config; }
}
<|endoftext|>