<commit_before>'use strict';

var _    = require('lodash');
var d3   = require('d3');

var browser = require('util/browser');
var label   = require('chart/renderer/label');
var color   = require('util/color');

var defaults = {
	margin    : {
		top    : 12,
		right  : 0,
		bottom : 12,
		left   : 0
	},
	name      : _.partial(_.get, _, 'name', ''),
	padding   : 0.1,
	values    : _.property('values'),
	x         : _.property('x'),
	xFormat   : String,
	y         : _.property('y'),
	y0        : _.partial(_.get, _, 'y0', 0),
	yFormat   : String,
	yScale    : d3.scale.linear
};

function ColumnChart() {}

_.extend(ColumnChart.prototype, {
	classNames : 'chart stacked-column',
	defaults   : defaults,

	initialize : function (el, data, options) {
		options = this._options = _.defaults({}, options, this.defaults);

		var aspect   = _.get(options, 'aspect', 1);
		this._width  = _.get(options, 'width', el.clientWidth);
		this._height = _.get(options, 'height', this._width / aspect);

		var svg = this._svg = d3.select(el).append('svg')
			.attr({
				'viewBox' : '0 0 ' + this._width + ' ' + this._height,
				'class'   :  this.classNames
			});

		if (browser.isIE()) {
			svg.attr({
				'width'  : this._width,
				'height' : this._height
			});
		}

		var h = this._height - options.margin.top - options.margin.bottom;

		svg.append('rect').attr({
			'class'  : 'bg',
			'height' : h + options.margin.top,
			'width'  : this._width - options.margin.left - options.margin.right,
			'x'      : options.margin.left,
		});

		var g = svg.append('g')
			.attr('transform', 'translate(' + options.margin.left + ',' +
				options.margin.top + ')');

		g.append('g').attr('class', 'data');

		g.append('g').attr('class', 'y axis');
		g.append('g').attr({
			'class'     : 'x axis',
			'transform' : 'translate(0,' + h + ')'
		});
		g.append('g').attr('class', 'legend');
		g.append('g').attr('class', 'annotation');

		this.update(data, options);
	},

	update : function (data, options) {
		var options = _.assign(this._options, options);
		var margin  = options.margin;

		var h = this._height - margin.top - margin.bottom;
		var w = this._width - margin.left - margin.right;

		var domain;

		if (_.isFunction(options.domain)) {
			domain = options.domain(data);
		} else {
			domain = _(data).map(options.values).flatten().map(options.x).value();
		}

		var xScale = d3.scale.ordinal()
			.domain(domain)
			.rangeBands([0, w], options.padding);

		var x = _.flow(options.x, xScale)

		var range;
		if (_.isFunction(options.range)) {
			range = options.range(data);
		} else {
			range = d3.extent(_(data).map(options.values).flatten().value(), function (d) {
				return options.y0(d) + options.y(d);
			});

			// Make sure we always have at least a 0 baseline
			range[0] = Math.min(0, range[0]);
		}

		var yScale = options.yScale()
			.domain(range)
			.range([h, 0]);

		var y = function (d) { return yScale(options.y0(d) + options.y(d)); };

		var height = function (d) {
			var y0 = options.y0(d);
			var y  = options.y(d);

			return yScale(y0) - yScale(y0 + y);
		};

		var svg    = this._svg;
		var g      = svg.select('.data');
		var series = g.selectAll('.bar').data(data);

		svg.select('.bg')
			.attr({
				'height': h + margin.top,
				'width' : w,
				'x'     : margin.left
			});

		series.enter().append('g')
			.attr('class', 'bar');

    var fill = options.hasOwnProperty('color') ?
      options.color :
      _.flow(options.name, color.scale(_.map(data, options.name)));

		series.style('fill', fill);

		series.exit()
			.transition()
			.duration(500)
			.style('opacity', 0)
			.remove();

		var hover = d3.dispatch('over', 'out');

		var column = series.selectAll('rect').data(options.values);

		column.enter()
			.append('rect')
			.style('fill', 'inherit');

		column.attr({
				'height' : height,
				'width'  : xScale.rangeBand(),
				'x'      : x,
				'y'      : y,
			})
			.on('mouseover', hover.over)
			.on('mouseout', hover.out);

		column.exit().remove();

		svg.select('.x.axis')
			.call(d3.svg.axis()
				.orient('bottom')
				.tickSize(0)
				.tickPadding(4)
				.tickValues(_.filter(xScale.domain(), function (d, i, domain) {
					// Include every fourth tick value unless that tick is within three
					// ticks of the last value. Always include the last tick. We have to
					// do this manually because D3 ignores the ticks() value for
					// ordinal scales
					return (i % 4 === 0 && i + 3 < domain.length) || (i + 1) === domain.length;
				}))
				.tickFormat(options.xFormat)
				.scale(xScale));

		var svgBox = this._svg.node().getBoundingClientRect();
		svg.selectAll('.x.axis text')
			.attr('dx', function () {
				var bbox = this.getBoundingClientRect();
				var dx   = null;

				if (bbox.right > svgBox.right) {
					dx = svgBox.right - bbox.right;
				}

				if (bbox.left < svgBox.left) {
					dx = svgBox.left - bbox.left;
				}

				return dx;
			});

		svg.select('.y.axis')
			.call(d3.svg.axis()
				.orient('right')
				.tickFormat(options.yFormat)
				.tickSize(w)
				.ticks(3)
				.scale(yScale));

		svg.selectAll('.y.axis text')
			.attr({
				'dx' : -w,
				'dy' : -4
			});

		var fmt = _.flow(options.y, options.yFormat);
		var labels = _(data)
			.map(function (s) {
				return _.assign({},
					_.max(options.values(s), options.x),
					{ name : options.name(s) }
				);
			})
			.map(function (d) {
				return {
					text    : d.name + ' ' + fmt(d),
					x       : x(d),
					y       : y(d),
					defined : _.isFinite(d.value)
				};
			})
			.reverse()
			.value();

		var seriesLabel = label()
			.addClass('series')
			.width(w)
			.height(h)
			.align(false);

		svg.select('.annotation').selectAll('.series.label')
			.data(labels)
			.call(seriesLabel);

		var timeout = null;

		hover.on('out', function () {
			timeout = window.setTimeout(function () {
				timeout = null;

				g.selectAll('rect')
					.transition()
					.duration(300)
					.style('opacity', 1);

				svg.selectAll('.x.axis text').style('opacity', 1);
				svg.select('.annotation').selectAll('.series.label')
					.data(labels)
					.call(seriesLabel.align(false));

				svg.selectAll('.annotation .axis.label').remove();
			}, 200);
		});

		hover.on('over', function (d) {
			if (_.isNumber(timeout)) {
				window.clearTimeout(timeout);
				timeout = null;
			}

			g.selectAll('rect')
				.transition()
				.duration(500)
				.style('opacity', function (e) {
					return options.x(d) === options.x(e) ? 1 : 0.5;
				});

			svg.selectAll('.x.axis text').style('opacity', 0);

			var annotations = _(data)
				.map(function (s) {
					return _.assign({},
						_.find(options.values(s), function (e) {
							return options.x(d) === options.x(e);
						}),
						{ name : options.name(s) }
					);
				})
				.map(function (d) {
					return {
						text    : d.name + ' ' + fmt(d),
						x       : x(d),
						y       : y(d),
						defined : _.isFinite(d.value)
					};
				})
				.reverse()
				.value();

			svg.select('.annotation').selectAll('.series.label')
				.data(annotations)
				.call(seriesLabel.align(true));

			var axisLabel = svg.select('.annotation')
				.selectAll('.axis.label')
				.data([options.x(d)]);

			axisLabel.enter()
				.append('text')
				.attr('class', 'axis label')
				.style('text-anchor', 'middle');

			axisLabel
				.attr({
					'transform' : 'translate(' + x(d) + ',' + (h + margin.bottom) + ')',
					'dx'        : xScale.rangeBand() / 2
				})
				.text(options.xFormat);
		});
	}

});

module.exports = ColumnChart;
<commit_msg>fix the RP #292 RP-Bug-2002 Mouseover tooltip on chart preview is unreadable.<commit_after>'use strict';

var _ = require('lodash');
var d3 = require('d3');

var browser = require('util/browser');
var label = require('chart/renderer/label');
var color = require('util/color');

var defaults = {
  margin: {
    top: 12,
    right: 0,
    bottom: 12,
    left: 0
  },
  name: _.partial(_.get, _, 'name', ''),
  padding: 0.1,
  values: _.property('values'),
  x: _.property('x'),
  xFormat: String,
  y: _.property('y'),
  y0: _.partial(_.get, _, 'y0', 0),
  yFormat: String,
  yScale: d3.scale.linear
};

function ColumnChart() {
}

_.extend(ColumnChart.prototype, {
  classNames: 'chart stacked-column',
  defaults: defaults,

  initialize: function (el, data, options) {
    options = this._options = _.defaults({}, options, this.defaults);

    var aspect = _.get(options, 'aspect', 1);
    this._width = _.get(options, 'width', el.clientWidth);
    this._height = _.get(options, 'height', this._width / aspect);

    var svg = this._svg = d3.select(el).append('svg')
      .attr({
        'viewBox': '0 0 ' + this._width + ' ' + this._height,
        'class': this.classNames
      });

    if (browser.isIE()) {
      svg.attr({
        'width': this._width,
        'height': this._height
      });
    }

    var h = this._height - options.margin.top - options.margin.bottom;

    svg.append('rect').attr({
      'class': 'bg',
      'height': h + options.margin.top,
      'width': this._width - options.margin.left - options.margin.right,
      'x': options.margin.left,
    });

    var g = svg.append('g')
      .attr('transform', 'translate(' + options.margin.left + ',' +
      options.margin.top + ')');

    g.append('g').attr('class', 'data');

    g.append('g').attr('class', 'y axis');
    g.append('g').attr({
      'class': 'x axis',
      'transform': 'translate(0,' + h + ')'
    });
    g.append('g').attr('class', 'legend');
    g.append('g').attr('class', 'annotation');

    this.update(data, options);
  },

  update: function (data, options) {
    var options = _.assign(this._options, options);
    var margin = options.margin;

    var h = this._height - margin.top - margin.bottom;
    var w = this._width - margin.left - margin.right;

    var domain;

    if (_.isFunction(options.domain)) {
      domain = options.domain(data);
    } else {
      domain = _(data).map(options.values).flatten().map(options.x).value();
    }

    var xScale = d3.scale.ordinal()
      .domain(domain)
      .rangeBands([0, w], options.padding);

    var x = _.flow(options.x, xScale)

    var range;
    if (_.isFunction(options.range)) {
      range = options.range(data);
    } else {
      range = d3.extent(_(data).map(options.values).flatten().value(), function (d) {
        return options.y0(d) + options.y(d);
      });

      // Make sure we always have at least a 0 baseline
      range[0] = Math.min(0, range[0]);
    }

    var yScale = options.yScale()
      .domain(range)
      .range([h, 0]);

    var y = function (d) {
      return yScale(options.y0(d) + options.y(d));
    };

    var height = function (d) {
      var y0 = options.y0(d);
      var y = options.y(d);

      return yScale(y0) - yScale(y0 + y);
    };

    var svg = this._svg;
    var g = svg.select('.data');
    var series = g.selectAll('.bar').data(data);

    svg.select('.bg')
      .attr({
        'height': h + margin.top,
        'width': w,
        'x': margin.left
      });

    series.enter().append('g')
      .attr('class', 'bar');

    var fill = options.hasOwnProperty('color') ?
      options.color :
      _.flow(options.name, color.scale(_.map(data, options.name)));

    series.style('fill', fill);

    series.exit()
      .transition()
      .duration(500)
      .style('opacity', 0)
      .remove();

    var hover = d3.dispatch('over', 'out');

    var column = series.selectAll('rect').data(options.values);

    column.enter()
      .append('rect')
      .style('fill', 'inherit');

    column.attr({
      'height': height,
      'width': xScale.rangeBand(),
      'x': x,
      'y': y,
    })
      .on('mouseover', hover.over)
      .on('mouseout', hover.out);

    column.exit().remove();

    svg.select('.x.axis')
      .call(d3.svg.axis()
        .orient('bottom')
        .tickSize(0)
        .tickPadding(4)
        .tickValues(_.filter(xScale.domain(), function (d, i, domain) {
          // Include every fourth tick value unless that tick is within three
          // ticks of the last value. Always include the last tick. We have to
          // do this manually because D3 ignores the ticks() value for
          // ordinal scales
          return (i % 4 === 0 && i + 3 < domain.length) || (i + 1) === domain.length;
        }))
        .tickFormat(options.xFormat)
        .scale(xScale));

    var svgBox = this._svg.node().getBoundingClientRect();
    svg.selectAll('.x.axis text')
      .attr('dx', function () {
        var bbox = this.getBoundingClientRect();
        var dx = null;

        if (bbox.right > svgBox.right) {
          dx = svgBox.right - bbox.right;
        }

        if (bbox.left < svgBox.left) {
          dx = svgBox.left - bbox.left;
        }

        return dx;
      });

    svg.select('.y.axis')
      .call(d3.svg.axis()
        .orient('right')
        .tickFormat(options.yFormat)
        .tickSize(w)
        .ticks(3)
        .scale(yScale));

    svg.selectAll('.y.axis text')
      .attr({
        'dx': -w,
        'dy': -4
      });

    var fmt = _.flow(options.y, options.yFormat);
    var labels = _(data)
      .map(function (s) {
        return _.assign({},
          _.max(options.values(s), options.x),
          {name: options.name(s)}
        );
      })
      .map(function (d) {
        return {
          text: d.name + ' ' + fmt(d),
          x: x(d),
          y: y(d),
          defined: _.isFinite(d.value)
        };
      })
      .reverse()
      .value();

    var seriesLabel = label()
      .addClass('series')
      .width(w)
      .height(h)
      .align(false);

    svg.select('.annotation').selectAll('.series.label')
      .data(labels)
			.call(seriesLabel);

    var timeout = null;

    hover.on('out', function () {
      timeout = window.setTimeout(function () {
        timeout = null;

        g.selectAll('rect')
          .transition()
          .duration(300)
          .style('opacity', 1);

        svg.selectAll('.x.axis text').style('opacity', 1);
        svg.select('.annotation').selectAll('.series.label')
          .data(labels)
					.call(seriesLabel.align(false));

        svg.selectAll('.annotation .axis.label').remove();
      }, 200);
    });

    hover.on('over', function (d) {
      if (_.isNumber(timeout)) {
        window.clearTimeout(timeout);
        timeout = null;
      }

      g.selectAll('rect')
        .transition()
        .duration(500)
        .style('opacity', function (e) {
          return options.x(d) === options.x(e) ? 1 : 0.5;
        });

      svg.selectAll('.x.axis text').style('opacity', 0);

      var annotations = _(data)
        .map(function (s) {
          return _.assign({},
            _.find(options.values(s), function (e) {
              return options.x(d) === options.x(e);
            }),
            {name: options.name(s)}
          );
        })
        .map(function (d) {
          return {
            text: d.name + ' ' + fmt(d),
            x: x(d),
            y: y(d),
            defined: _.isFinite(d.value)
          };
        })
        .tap(list => {
          if (_(list).some(item => (item.y >= h || item.y < 0)))
            list.forEach(item => {
              item.y = 0;
            })
        })
        .each(item => {item.y = 0; })
        .reverse()
        .value();

      svg.select('.annotation').selectAll('.series.label')
        .data(annotations)
        .call(seriesLabel.align(true));

      var axisLabel = svg.select('.annotation')
        .selectAll('.axis.label')
        .data([options.x(d)]);

      axisLabel.enter()
        .append('text')
        .attr('class', 'axis label')
        .style('text-anchor', 'middle');

      axisLabel
        .attr({
          'transform': 'translate(' + x(d) + ',' + (h + margin.bottom) + ')',
          'dx': xScale.rangeBand() / 2
        })
        .text(options.xFormat);
    });
  }

});

module.exports = ColumnChart;
<|endoftext|>


<commit_before>import {Utility} from '../../../tungstenjs/src/utility';
import {Model} from '../../../tungstenjs/src/model';

/**
 * @class LocalStorageModel
 * @author Andrew Odri andrew@affirmix.com
 *
 * This class is extends the base model class with functionality for interacting with browser storage.
 *
 * In order to track model instances before and after serialization, as well as before and after changea are committed, two registries have been added to the instance: The memory registry for uncomitted changes, and the stroage registry that reads and writes to and from browser storage.
 *
 * All the standard functions of a typical model have been implemented, such as `updateOrCreate`, `findOrFail`, `hydrate`, etc., to make dealing with local storage as simple as possible, and to easily migrate from other model implementations if needed.
 */
export class LocalStorageModel extends Model {

  static get memoryRegistry(){
    if(!this.hasOwnProperty("__memoryRegistry__")){
      this.__memoryRegistry__ = this.storageRegistry;
    }

    return this.__memoryRegistry__;
  }

  static set memoryRegistry(data){
    if(data instanceof Array){
      this.__memoryRegistry__ = data;
    }else{
      throw new Error('Cannot write to memoryRegistry because it is not an Array in class LocalStorageModel');
    }
  }

  static get storageRegistry(){
    let storageJson = window.localStorage.getItem("LocalStorageModel");

    if(storageJson !== null){
      let storageData = JSON.parse(storageJson);

      if(storageData instanceof Array){
        this.__storageRegistry__ = storageData;
      }else{
        throw new Error('Cannot read from storageRegistry because it is not an Array in class LocalStorageModel');
      }
    }else{
      this.__storageRegistry__ = [];
    }

    return this.__storageRegistry__;
  }

  static set storageRegistry(data){
    if(data instanceof Array){
      window.localStorage.setItem("LocalStorageModel", JSON.stringify(data));

      this.__storageRegistry__ = data;
    }else{
      throw new Error('Cannot write to storageRegistry because it is not an Array in class LocalStorageModel');
    }
  }

  /**
   * @static
   * @param {Object} attributes Attributes that will be used to hydrate a new model instance. See `hydrate` for more information
   * @returns {Model} Deferred instance of the newly created model
   *
   * Creates a new instance of the model, and performs a save operation.
   */
  static create(attributes){
    console.log('LocalStorageModel.create()');

    // Inspiration from Backbone.js; not sure if I like it, but lets see how it goes...
    //let four = () => {return (((1+Math.random())*0x10000)|0).toString(16).substring(1);}
    //attributes.guid = (four()+four()+"-"+four()+"-"+four()+"-"+four()+"-"+four()+four()+four());

    //$(this).trigger('create');

    return this.hydrate(attributes).save();
  }

  /**
   * @static
   * @param {Array} items Model instances to be deleted
   * @returns {Boolean} Boolean expressing whether the operation was successful
   *
   * Destroys the model instances provided, and performs a delete operation.
   */
  static destroy(items){
    console.log('LocalStorageModel.destroy()');

    for(let item in items){
      if(item instanceof LocalStorageModel){
        // Remove item from array based on guid; throw error if no guid
      }
    }

    return true;
  }

  /**
   * @static
   * @param {Object} attributes Attributes used to return the models that need to be updated
   * @param {Object} properties Properties that model instances will be updated with
   * @returns {Array} Deferred instance of the updated or created model(s)
   *
   * Create or update a model matching the attributes, and fill it with values.
   */
  static updateOrCreate(attributes, properties){
    console.log('LocalStorageModel.updateOrCreate()');

    let result = this.__find__(attributes, false, properties);

    if(result instanceof Array && result.length == 1){
      return result[0];
    }else if (result instanceof Array && result.length > 1){
      return result;
    }else{
      return this.create(
        Object.assign({}, attributes, properties)
      );
    }
  }

  /**
   * @static
   * @param {Array|Object} data Data needed to instantiate new model instances
   * @returns {Array|Model} Newly instantiated model/models
   *
   * Instantiates a model/models based on the data provided. This is called immediately after `filter`.
   */
  static hydrate(data) {
    console.log('LocalStorageModel.hydrate()');

    let result = false;

    if(data instanceof Array){
      result = [];

      for(let item of data){
        if(item instanceof Object){
          result.push(new this.classReference(item));
        }
      }
    }else if(data instanceof Object){
      result = new this.classReference(data);
    }else{
      throw new Error('Cannot hydrate model from a non-object in class LocalStorageModel');
    }

    return result;
  }

  /**
   * @static
   * @param {Object} attributes An object containing properties that correspond to the attributes in the templated RESTful URL, if not overriden by custom functionality
   * @param {Boolean} isSingle An optional boolean that defines whether one or many models are returned. Defaults to false.
   * @param {Object} properties An optional object containing properties that need to be be updated in the model(s) returned. Defaults to {}.
   * @returns {Array|Model} Deferred instance of the Models that are found
   *
   * Internal function that finds and returns any available instances of the model.
   */
  static __find__(attributes, isSingle = false, properties = {}) {
    console.log('LocalStorageModel.__find__()');

    this.memoryRegistry;

    // This seems like the perfect task for Array.fliter(), however there is bigger fish to fry at this point...
    let filtered = []
    if(Object.keys(attributes).length > 0){
      this.__memoryRegistry__.forEach((currentValue, index, array) => {
        let isMatch = true;

        for(let key in attributes){
          if(currentValue[key] !== attributes[key]){
            isMatch = false;
          }
        }

        if(isMatch){
          array[index] = Object.assign(currentValue, properties);
          filtered.push(currentValue);
        }
      });
    }else{
      filtered = this.__memoryRegistry__;
    }

    if(Object.keys(properties).length > 0){
      this.storageRegistry = this.__memoryRegistry__;
    }

    if(filtered !== null){
      if(isSingle) {
        return this.hydrate(filtered[0]);
      }else{
        return this.hydrate(filtered);
      }
    }else{
      return null;
    }
  }

  /**
   * @constructor
   * @param {Object} attributes This provides properties and objects that are to be merged with the model instance.
   * @returns {Model} Instance of the saved model
   *
   * Constructs the model instance by merging the attributes with the new model instance.
   *
   * It then generates a GUID if one is not already present, as this is essential for identifing local storage model instances before and after serialization.
   *
   * The memoryRegistry is then populated by ensuring that the getter is called, and the newly created instance either overwrites it's match in memoryRegistry, or is pushed onto the memoryRegistry array.
   */
  constructor(attributes) {
    console.log('localStorageModel.constructor()');

    Object.assign(this, attributes);

    if(!this.hasOwnProperty("guid")){
      this.guid = Utility.generateGuid();
    }

    this.classReference.memoryRegistry

    let index = this.classReference.__memoryRegistry__.findIndex((item) => {
      return (item.guid === this.guid);
    });

    this.classReference.memoryRegistry;

    if(index < 0){
      this.classReference.__memoryRegistry__.push(this);
    }else{
      this.classReference.__memoryRegistry__[index] = this;
    }
  }

  /**
   * @returns {Model} Instance of the saved model
   *
   * Performs a save operation.
   */
  save() {
    console.log('localStorageModel.save()');

    let index = this.classReference.memoryRegistry.findIndex((item) => {
        return (item.guid === this.guid);
    });

    this.classReference.storageRegistry = this.classReference.__memoryRegistry__;

    // Overwrite object with matching guid in storage registry; get it first

    return this;
  }
}
<commit_msg>Started adding delete functionality<commit_after>import {Utility} from '../../../tungstenjs/src/utility';
import {Model} from '../../../tungstenjs/src/model';

/**
 * @class LocalStorageModel
 * @author Andrew Odri andrew@affirmix.com
 *
 * This class is extends the base model class with functionality for interacting with browser storage.
 *
 * In order to track model instances before and after serialization, as well as before and after changea are committed, two registries have been added to the instance: The memory registry for uncomitted changes, and the stroage registry that reads and writes to and from browser storage.
 *
 * All the standard functions of a typical model have been implemented, such as `updateOrCreate`, `findOrFail`, `hydrate`, etc., to make dealing with local storage as simple as possible, and to easily migrate from other model implementations if needed.
 */
export class LocalStorageModel extends Model {

  static get memoryRegistry(){
    if(!this.hasOwnProperty("__memoryRegistry__")){
      this.__memoryRegistry__ = this.storageRegistry;
    }

    return this.__memoryRegistry__;
  }

  static set memoryRegistry(data){
    if(data instanceof Array){
      this.__memoryRegistry__ = data;
    }else{
      throw new Error('Cannot write to memoryRegistry because it is not an Array in class LocalStorageModel');
    }
  }

  static get storageRegistry(){
    let storageJson = window.localStorage.getItem("LocalStorageModel");

    if(storageJson !== null){
      let storageData = JSON.parse(storageJson);

      if(storageData instanceof Array){
        this.__storageRegistry__ = storageData;
      }else{
        throw new Error('Cannot read from storageRegistry because it is not an Array in class LocalStorageModel');
      }
    }else{
      this.__storageRegistry__ = [];
    }

    return this.__storageRegistry__;
  }

  static set storageRegistry(data){
    if(data instanceof Array){
      window.localStorage.setItem("LocalStorageModel", JSON.stringify(data));

      this.__storageRegistry__ = data;
    }else{
      throw new Error('Cannot write to storageRegistry because it is not an Array in class LocalStorageModel');
    }
  }

  /**
   * @static
   * @param {Object} attributes Attributes that will be used to hydrate a new model instance. See `hydrate` for more information
   * @returns {Model} Deferred instance of the newly created model
   *
   * Creates a new instance of the model, and performs a save operation.
   */
  static create(attributes){
    console.log('LocalStorageModel.create()');

    return this.hydrate(attributes).save();
  }

  /**
   * @static
   * @param {Array} items Model instances to be deleted
   * @returns {Boolean} Boolean expressing whether the operation was successful
   *
   * Destroys the model instances provided, and performs a delete operation.
   */
  static destroy(items){
    console.log('LocalStorageModel.destroy()');

    for(let item in items){
      if(item instanceof this.classReference){
        item.delete();
      }
    }

    return true;
  }

  /**
   * @static
   * @param {Object} attributes Attributes used to return the models that need to be updated
   * @param {Object} properties Properties that model instances will be updated with
   * @returns {Array} Deferred instance of the updated or created model(s)
   *
   * Create or update a model matching the attributes, and fill it with values.
   */
  static updateOrCreate(attributes, properties){
    console.log('LocalStorageModel.updateOrCreate()');

    let result = this.__find__(attributes, false, properties);

    if(result instanceof Array && result.length == 1){
      return result[0];
    }else if (result instanceof Array && result.length > 1){
      return result;
    }else{
      return this.create(
        Object.assign({}, attributes, properties)
      );
    }
  }

  /**
   * @static
   * @param {Array|Object} data Data needed to instantiate new model instances
   * @returns {Array|Model} Newly instantiated model/models
   *
   * Instantiates a model/models based on the data provided. This is called immediately after `filter`.
   */
  static hydrate(data) {
    console.log('LocalStorageModel.hydrate()');

    let result = false;

    if(data instanceof Array){
      result = [];

      for(let item of data){
        if(item instanceof Object){
          result.push(new this.classReference(item));
        }
      }
    }else if(data instanceof Object){
      result = new this.classReference(data);
    }else{
      throw new Error('Cannot hydrate model from a non-object in class LocalStorageModel');
    }

    return result;
  }

  /**
   * @static
   * @param {Object} attributes An object containing properties that correspond to the attributes in the templated RESTful URL, if not overriden by custom functionality
   * @param {Boolean} isSingle An optional boolean that defines whether one or many models are returned. Defaults to false.
   * @param {Object} properties An optional object containing properties that need to be be updated in the model(s) returned. Defaults to {}.
   * @returns {Array|Model} Deferred instance of the Models that are found
   *
   * Internal function that finds and returns any available instances of the model.
   */
  static __find__(attributes, isSingle = false, properties = {}) {
    console.log('LocalStorageModel.__find__()');

    this.memoryRegistry;

    // This seems like the perfect task for Array.fliter(), however there is bigger fish to fry at this point...
    let filtered = []
    if(Object.keys(attributes).length > 0){
      this.__memoryRegistry__.forEach((currentValue, index, array) => {
        let isMatch = true;

        for(let key in attributes){
          if(currentValue[key] !== attributes[key]){
            isMatch = false;
          }
        }

        if(isMatch){
          array[index] = Object.assign(currentValue, properties);
          filtered.push(currentValue);
        }
      });
    }else{
      filtered = this.__memoryRegistry__;
    }

    if(Object.keys(properties).length > 0){
      this.storageRegistry = this.__memoryRegistry__;
    }

    if(filtered !== null){
      if(isSingle) {
        return this.hydrate(filtered[0]);
      }else{
        return this.hydrate(filtered);
      }
    }else{
      return null;
    }
  }

  /**
   * @constructor
   * @param {Object} attributes This provides properties and objects that are to be merged with the model instance.
   * @returns {Model} Instance of the saved model
   *
   * Constructs the model instance by merging the attributes with the new model instance.
   *
   * It then generates a GUID if one is not already present, as this is essential for identifing local storage model instances before and after serialization.
   *
   * The memoryRegistry is then populated by ensuring that the getter is called, and the newly created instance either overwrites it's match in memoryRegistry, or is pushed onto the memoryRegistry array.
   */
  constructor(attributes) {
    console.log('localStorageModel.constructor()');

    Object.assign(this, attributes);

    if(!this.hasOwnProperty("guid")){
      this.guid = Utility.generateGuid();
    }

    this.classReference.memoryRegistry

    let index = this.classReference.__memoryRegistry__.findIndex((item) => {
      return (item.guid === this.guid);
    });

    this.classReference.memoryRegistry;

    if(index < 0){
      this.classReference.__memoryRegistry__.push(this);
    }else{
      this.classReference.__memoryRegistry__[index] = this;
    }
  }

  /**
   * @returns {Model} Instance of the saved model
   *
   * Performs a save operation.
   */
  save() {
    console.log('localStorageModel.save()');

    let index = this.classReference.memoryRegistry.findIndex((item) => {
      return (item.guid === this.guid);
    });

    this.classReference.storageRegistry = this.classReference.__memoryRegistry__;

    // Overwrite object with matching guid in storage registry; get it first

    return this;
  }

  /**
   * @returns {Model} Instance of the model to be deleted
   *
   * Performs a delete operation.
   */
  delete() {
    console.log('localStorageModel.save()');

    let index = this.classReference.memoryRegistry.findIndex((item) => {
      return (item.guid === this.guid);
    });

    this.classReference.__memoryRegistry__.splice(index, 1);

    this.classReference.storageRegistry = this.classReference.__memoryRegistry__;

    return this;
  }
}
<|endoftext|>


<commit_before>angular.module('anol.map')

/**
 * @ngdoc directive
 * @name anol.map.directive:anolMap
 *
 * @requires $timeout
 * @requires anol.DefaultMapName
 * @requires anol.map.MapService
 *
 * @description
 * The anol-map directive adds the map defined in MapService to the dom.
 *
 * It also add the DefaultMapName as id and class to the map element.
 */
.directive('anolMap', ['$timeout', 'DefaultMapName', 'MapService', 'LayersService', 'ControlsService', 'InteractionsService',
    function($timeout, DefaultMapName, MapService, LayersService, ControlsService, InteractionsService) {
    return {
        scope: {},
        link: {
            pre: function(scope, element, attrs) {
                scope.mapName = DefaultMapName;
                scope.map = MapService.getMap();
                element
                    .attr('id', scope.mapName)
                    .addClass(scope.mapName);

                scope.map.setTarget(document.getElementById(scope.mapName));
            },
            post: function(scope, element, attrs) {
                $timeout(function() {
                    scope.map.updateSize();
                    // add layers after map has correct size to prevent
                    // loading layer twice (before and after resize)
                    angular.forEach(LayersService.backgroundLayers, function(layer) {
                        scope.map.addLayer(layer.olLayer);
                    });
                    angular.forEach(LayersService.overlayLayers.slice().reverse(), function(layer) {
                        if(layer instanceof anol.layer.Group) {
                            angular.forEach(layer.layers.slice().reverse(), function(grouppedLayer) {
                                scope.map.addLayer(grouppedLayer.olLayer);
                            });
                        } else {
                            scope.map.addLayer(grouppedLayer.olLayer);
                        }
                    });
                    LayersService.registerMap(scope.map);
                    // add registered controls and interactions
                    angular.forEach(ControlsService.olControls, function(control) {
                        scope.map.addControl(control);
                    });
                    ControlsService.registerMap(scope.map);
                    angular.forEach(InteractionsService.interactions, function(interaction) {
                        scope.map.addInteraction(interaction);
                    });
                    InteractionsService.registerMap(scope.map);
                });
            }
        },
        controller: function($scope, $element, $attrs) {
            this.getMap = function() {
                return $scope.map;
            };
        }
    };
}]);
<commit_msg>Used correct variable<commit_after>angular.module('anol.map')

/**
 * @ngdoc directive
 * @name anol.map.directive:anolMap
 *
 * @requires $timeout
 * @requires anol.DefaultMapName
 * @requires anol.map.MapService
 *
 * @description
 * The anol-map directive adds the map defined in MapService to the dom.
 *
 * It also add the DefaultMapName as id and class to the map element.
 */
.directive('anolMap', ['$timeout', 'DefaultMapName', 'MapService', 'LayersService', 'ControlsService', 'InteractionsService',
    function($timeout, DefaultMapName, MapService, LayersService, ControlsService, InteractionsService) {
    return {
        scope: {},
        link: {
            pre: function(scope, element, attrs) {
                scope.mapName = DefaultMapName;
                scope.map = MapService.getMap();
                element
                    .attr('id', scope.mapName)
                    .addClass(scope.mapName);

                scope.map.setTarget(document.getElementById(scope.mapName));
            },
            post: function(scope, element, attrs) {
                $timeout(function() {
                    scope.map.updateSize();
                    // add layers after map has correct size to prevent
                    // loading layer twice (before and after resize)
                    angular.forEach(LayersService.backgroundLayers, function(layer) {
                        scope.map.addLayer(layer.olLayer);
                    });
                    angular.forEach(LayersService.overlayLayers.slice().reverse(), function(layer) {
                        if(layer instanceof anol.layer.Group) {
                            angular.forEach(layer.layers.slice().reverse(), function(grouppedLayer) {
                                scope.map.addLayer(grouppedLayer.olLayer);
                            });
                        } else {
                            scope.map.addLayer(layer.olLayer);
                        }
                    });
                    LayersService.registerMap(scope.map);
                    // add registered controls and interactions
                    angular.forEach(ControlsService.olControls, function(control) {
                        scope.map.addControl(control);
                    });
                    ControlsService.registerMap(scope.map);
                    angular.forEach(InteractionsService.interactions, function(interaction) {
                        scope.map.addInteraction(interaction);
                    });
                    InteractionsService.registerMap(scope.map);
                });
            }
        },
        controller: function($scope, $element, $attrs) {
            this.getMap = function() {
                return $scope.map;
            };
        }
    };
}]);
<|endoftext|>


<commit_before>import { computed, transaction, action, autorun } from 'mobx'
import { BarQueryDownload } from './barquery.js'
import { config } from '/utils/config.js'

export class BarStatusDownload extends BarQueryDownload {
    name = 'bar status'

    // update bar status every 30s
    cacheInfo = config.defaultRefreshCacheInfo
    periodicRefresh = 30

    @computed get query() {
        return {
            BarStatus: {
                args: {
                    /* NOTE: Use require() to resolve cyclic dependency */
                    barID: this.props.barID,
                },
                result: {
                    bar_status: {
                        qdodger_bar:      'Bool',
                        taking_orders:    'Bool',
                        table_service:    'String',
                        pickup_locations: ['String'],
                    }
                }
            }
        }
    }

    @computed get barStatus() {
        return this.lastValue && this.lastValue.bar_status
    }
}
<commit_msg>Update bar status query download<commit_after>import { computed, transaction, action, autorun } from 'mobx'
import { BarQueryDownload } from './barquery.js'
import { config } from '/utils/config.js'

export class BarStatusDownload extends BarQueryDownload {
    name = 'bar status'

    // update bar status every 30s
    cacheInfo = config.defaultRefreshCacheInfo
    periodicRefresh = 30

    @computed get query() {
        return {
            BarStatus: {
                args: {
                    /* NOTE: Use require() to resolve cyclic dependency */
                    barID: this.props.barID,
                },
                result: {
                    bar_status: {
                        qdodger_bar:      'Bool',
                        taking_orders:    'Bool',
                        table_service:    'String',
                        pickup_locations: [{
                            name: 'String',
                            open: 'Bool',
                        }],
                    }
                }
            }
        }
    }

    @computed get barStatus() {
        return this.lastValue && this.lastValue.bar_status
    }
}
<|endoftext|>


<commit_before>'use strict';

/**
 * @ngdoc directive
 * @name ngTransclude
 * @restrict AC
 *
 * @description
 * Directive that marks the insertion point for the transcluded DOM of the nearest parent directive that uses transclusion.
 *
 * Any existing content of the element that this directive is placed on will be removed before the transcluded content is inserted.
 *
 * @element ANY
 *
 * @example
   <example module="transcludeExample">
     <file name="index.html">

         <input ng-model="title">

         <textarea ng-model="text"></textarea>

         <pane title="{{title}}">{{text}}</pane>

     </file>
     <file name="protractor.js" type="protractor">
        it('should have transcluded', function() {
          var titleElement = element(by.model('title'));
          titleElement.clear();
          titleElement.sendKeys('TITLE');
          var textElement = element(by.model('text'));
          textElement.clear();
          textElement.sendKeys('TEXT');
          expect(element(by.binding('title')).getText()).toEqual('TITLE');
          expect(element(by.binding('text')).getText()).toEqual('TEXT');
        });
     </file>
   </example>
 *
 */
var ngTranscludeDirective = ngDirective({
  link: function($scope, $element, $attrs, controller, $transclude) {
    if (!$transclude) {
      throw minErr('ngTransclude')('orphan',
       'Illegal use of ngTransclude directive in the template! ' +
       'No parent directive that requires a transclusion found. ' +
       'Element: {0}',
       startingTag($element));
    }

    $transclude(function(clone) {
      $element.empty();
      $element.append(clone);
    });
  }
});
<commit_msg>feat(ngTransclude): allow ngTransclude to be used as an element<commit_after>'use strict';

/**
 * @ngdoc directive
 * @name ngTransclude
 * @restrict EAC
 *
 * @description
 * Directive that marks the insertion point for the transcluded DOM of the nearest parent directive that uses transclusion.
 *
 * Any existing content of the element that this directive is placed on will be removed before the transcluded content is inserted.
 *
 * @element ANY
 *
 * @example
   <example module="transcludeExample">
     <file name="index.html">

         <input ng-model="title">

         <textarea ng-model="text"></textarea>

         <pane title="{{title}}">{{text}}</pane>

     </file>
     <file name="protractor.js" type="protractor">
        it('should have transcluded', function() {
          var titleElement = element(by.model('title'));
          titleElement.clear();
          titleElement.sendKeys('TITLE');
          var textElement = element(by.model('text'));
          textElement.clear();
          textElement.sendKeys('TEXT');
          expect(element(by.binding('title')).getText()).toEqual('TITLE');
          expect(element(by.binding('text')).getText()).toEqual('TEXT');
        });
     </file>
   </example>
 *
 */
var ngTranscludeDirective = ngDirective({
  restrict: 'EAC',
  link: function($scope, $element, $attrs, controller, $transclude) {
    if (!$transclude) {
      throw minErr('ngTransclude')('orphan',
       'Illegal use of ngTransclude directive in the template! ' +
       'No parent directive that requires a transclusion found. ' +
       'Element: {0}',
       startingTag($element));
    }

    $transclude(function(clone) {
      $element.empty();
      $element.append(clone);
    });
  }
});
<|endoftext|>


<commit_before>import Vue from "vue";
import Associate from "./templates/Associate.vue";
import Leaderboard from "./templates/Leaderboard.vue";
import Upload from "./templates/Upload.vue";
import UserProfile from "./templates/UserProfile.vue";
import VerifyEmail from "./templates/VerifyEmail.vue";
import Visualizer from "./templates/Visualizer.vue";

import * as api from "./api";

Vue.use(require('vue-moment'));

window.views = {
    Associate: function () {
        new Vue({
            el: "#associate-container",
            render: (h) => h(Associate),
        });
    },
    Leaderboard: function () {
        new Vue({
            el: "#leaderboard-container",
            render: (h) => h(Leaderboard),
        });
    },
    Upload: function () {
        new Vue({
            el: "#upload-container",
            render: (h) => h(Upload),
        });
    },
    UserProfile: function () {
        new Vue({
            el: "#user-profile-container",
            render: (h) => h(UserProfile),
        });
    },
    VerifyEmail: function () {
        new Vue({
            el: "#verify-email-container",
            render: (h) => h(VerifyEmail),
        });
    },
    Visualizer: function () {
        new Vue({
            el: "#visualizer-container",
            render: (h) => h(Visualizer),
        });
    },
};

api.me().then((me) => {
   if (me) {
       $(".logged-in").show();
       $(".not-logged-in").hide();

       if (me.is_new_user && window.location.pathname !== "/associate") {
           window.location.replace("/associate");
       }
   }
});
<commit_msg>Properly include bootstrap JS<commit_after>import Vue from "vue";
import Associate from "./templates/Associate.vue";
import Leaderboard from "./templates/Leaderboard.vue";
import Upload from "./templates/Upload.vue";
import UserProfile from "./templates/UserProfile.vue";
import VerifyEmail from "./templates/VerifyEmail.vue";
import Visualizer from "./templates/Visualizer.vue";

// Include bootstrap.js - do not remove
import _ from "../vendor_assets/bootstrap-sass-3.3.7/assets/javascripts/bootstrap";

import * as api from "./api";

Vue.use(require('vue-moment'));

window.views = {
    Associate: function () {
        new Vue({
            el: "#associate-container",
            render: (h) => h(Associate),
        });
    },
    Leaderboard: function () {
        new Vue({
            el: "#leaderboard-container",
            render: (h) => h(Leaderboard),
        });
    },
    Upload: function () {
        new Vue({
            el: "#upload-container",
            render: (h) => h(Upload),
        });
    },
    UserProfile: function () {
        new Vue({
            el: "#user-profile-container",
            render: (h) => h(UserProfile),
        });
    },
    VerifyEmail: function () {
        new Vue({
            el: "#verify-email-container",
            render: (h) => h(VerifyEmail),
        });
    },
    Visualizer: function () {
        new Vue({
            el: "#visualizer-container",
            render: (h) => h(Visualizer),
        });
    },
};

api.me().then((me) => {
   if (me) {
       $(".logged-in").show();
       $(".not-logged-in").hide();

       if (me.is_new_user && window.location.pathname !== "/associate") {
           window.location.replace("/associate");
       }
   }
});
<|endoftext|>


<commit_before>/**
*
* webconfig-parser
*
* License MIT
*
**/

/*====================================
=            Dependencies            =
====================================*/
var _         = require('lodash');
var DomParser = require('xmldom').DOMParser;
var fs        = require('fs');
var path      = require('path');

var parser    = {};

parser.parse = function (options) {

    if (!_.isObject(options)) return;

    options = _.defaults(options, {
        url: path.join(__dirname, './../../Web.config'),
        encoding: 'utf8',
        tagName: 'add',
        keyAttrName: 'key',
        valueAttrName: 'value',
        readConnectionStrings: false
    });

    var config = {};

    /* Read of the Web.config file */
    var webConfigXML = fs.readFileSync(options.url, {
        encoding: options.encoding
    });

    /* Parse the file */
    var doc = new DomParser().parseFromString(webConfigXML, 'text/xml');

    /* Retrieve all parameters entries */
    var paramsEntries = doc.getElementsByTagName(options.tagName);
    for (var i = paramsEntries.length - 1; i >= 0; i--) {
        var param = paramsEntries.item(i);
        if (param.hasAttribute(options.keyAttrName)) {
            config[param.getAttribute(options.keyAttrName)] = param.getAttribute(options.valueAttrName);
        }
    }

    if (!options.readConnectionStrings) return config;

    config.connectionStrings = {};

    /* Get connection string */
    var connStrNode = doc.getElementsByTagName('connectionStrings');
    var connStrEntries = connStrNode.item(0).getElementsByTagName('add');
    for (var i = connStrEntries.length - 1; i >= 0; i--) {
        var entry = connStrEntries.item(i);
        if (entry.hasAttribute('connectionString')) {
            config.connectionStrings[entry.getAttribute('name')] = entry.getAttribute('connectionString');
        }
    };

    return config;

};

module.exports = parser;
<commit_msg>Return the last occurence of duplicate keys<commit_after>/**
*
* webconfig-parser
*
* License MIT
*
**/

/*====================================
=            Dependencies            =
====================================*/
var _         = require('lodash');
var DomParser = require('xmldom').DOMParser;
var fs        = require('fs');
var path      = require('path');

var parser    = {};

parser.parse = function (options) {

    if (!_.isObject(options)) return;

    options = _.defaults(options, {
        url: path.join(__dirname, './../../Web.config'),
        encoding: 'utf8',
        tagName: 'add',
        keyAttrName: 'key',
        valueAttrName: 'value',
        readConnectionStrings: false
    });

    var config = {};

    /* Read of the Web.config file */
    var webConfigXML = fs.readFileSync(options.url, {
        encoding: options.encoding
    });

    /* Parse the file */
    var doc = new DomParser().parseFromString(webConfigXML, 'text/xml');

    /* Retrieve all parameters entries */
    var paramsEntries = doc.getElementsByTagName(options.tagName);
    for (var i = 0 ; i < paramsEntries.length ; i++) {
        var param = paramsEntries.item(i);
        if (param.hasAttribute(options.keyAttrName)) {
            config[param.getAttribute(options.keyAttrName)] = param.getAttribute(options.valueAttrName);
        }
    }

    if (!options.readConnectionStrings) return config;

    config.connectionStrings = {};

    /* Get connection string */
    var connStrNode = doc.getElementsByTagName('connectionStrings');
    var connStrEntries = connStrNode.item(0).getElementsByTagName('add');
    for (var i = connStrEntries.length - 1; i >= 0; i--) {
        var entry = connStrEntries.item(i);
        if (entry.hasAttribute('connectionString')) {
            config.connectionStrings[entry.getAttribute('name')] = entry.getAttribute('connectionString');
        }
    };

    return config;

};

module.exports = parser;
<|endoftext|>


<commit_before> function main() {
         var map = new L.Map('map', {
             zoomControl: false,
             center: [44.908, -75.83],
             zoom: 15
         });
         L.tileLayer(
             'http://server.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Light_Gray_Base/MapServer/tile/{z}/{y}/{x}', {
                 attribution: 'Tiles © Esri — Esri, DeLorme, NAVTEQ',
                 maxZoom: 16
             }).addTo(map);
         // load 10k course route
         $.getJSON("10k.geojson", function(data) {
             // add GeoJSON layer to the map once the file is loaded
             L.geoJson(data).addTo(map);
         });
         // Define markers
         var startIcon = L.AwesomeMarkers.icon({
             prefix: 'fa',
             icon: 'flag-checkered',
             iconColor: 'white',
             markerColor: 'cadetblue'
         });
         var km1Icon = L.AwesomeMarkers.icon({
             prefix: 'fa',
             icon: '',
             iconColor: 'white',
             markerColor: 'cadetblue',
			 html: "1"
         });
		 var km2Icon = L.AwesomeMarkers.icon({
             prefix: 'fa',
             icon: '',
             iconColor: 'white',
             markerColor: 'cadetblue',
			 html: "2"
         });
		 var km3Icon = L.AwesomeMarkers.icon({
             prefix: 'fa',
             icon: '',
             iconColor: 'white',
             markerColor: 'cadetblue',
			 html: "3"
         });
		 var km4Icon = L.AwesomeMarkers.icon({
             prefix: 'fa',
             icon: '',
             iconColor: 'white',
             markerColor: 'cadetblue',
			 html: "4"
         });
		 var km5Icon = L.AwesomeMarkers.icon({
             prefix: 'fa',
             icon: '',
             iconColor: 'white',
             markerColor: 'cadetblue',
			 html: "5"
         });
		 var km6Icon = L.AwesomeMarkers.icon({
             prefix: 'fa',
             icon: '',
             iconColor: 'white',
             markerColor: 'cadetblue',
			 html: "6"
         });
		 var km7Icon = L.AwesomeMarkers.icon({
             prefix: 'fa',
             icon: '',
             iconColor: 'white',
             markerColor: 'cadetblue',
			 html: "7"
         });
		 var km8Icon = L.AwesomeMarkers.icon({
             prefix: 'fa',
             icon: '',
             iconColor: 'white',
             markerColor: 'cadetblue',
			 html: "8"
         });
		 var km9Icon = L.AwesomeMarkers.icon({
             prefix: 'fa',
             icon: '',
             iconColor: 'white',
             markerColor: 'cadetblue',
			 html: "9"
         });
		 var defaultIcon = L.AwesomeMarkers.icon({
             prefix: 'fa',
             icon: '',
             iconColor: 'white',
             markerColor: 'cadetblue',
			 html: ""
		});
         // load 10k course route features
         $.getJSON("features.geojson", function(data) {
             //add GeoJSON layer to the map once the file is loaded
             L.geoJson(data, {
                 pointToLayer: function(feature, latlng) {
                     if (feature.properties.cng_Meters ==
                         "0.0") {
                         var marker = L.marker(latlng, {
                             icon: startIcon
                         });
					} else if (feature.properties.cng_Meters ==
                         "1000.0") {
                         var marker = L.marker(latlng, {
                             icon: km1Icon
                         });
					} else if (feature.properties.cng_Meters ==
                         "2000.0") {
                         var marker = L.marker(latlng, {
                             icon: km2Icon
                         });
					} else if (feature.properties.cng_Meters ==
                         "3000.0") {
                         var marker = L.marker(latlng, {
                             icon: km3Icon
                         });
					} else if (feature.properties.cng_Meters ==
                         "4000.0") {
                         var marker = L.marker(latlng, {
                             icon: km4Icon
                         });
					} else if (feature.properties.cng_Meters ==
                         "5000.0") {
                         var marker = L.marker(latlng, {
                             icon: km5Icon
                         });
					} else if (feature.properties.cng_Meters ==
                         "6000.0") {
                         var marker = L.marker(latlng, {
                             icon: km6Icon
                         });
					} else if (feature.properties.cng_Meters ==
                         "7000.0") {
                         var marker = L.marker(latlng, {
                             icon: km7Icon
                         });
					} else if (feature.properties.cng_Meters ==
                         "8000.0") {
                         var marker = L.marker(latlng, {
                             icon: km8Icon
                         });
					} else if (feature.properties.cng_Meters ==
                         "9000.0") {
                         var marker = L.marker(latlng, {
                             icon: km9Icon
                         });
                     } else {
                         var marker = L.marker(latlng, {
                             icon: defaultIcon
                         });
                     };
                     return marker;
                     //return new L.marker(latlng, {
                     //icon: startIcon
                     //});
                 },
                 //onEachFeature: function(feature, layer) {
                 //layer.bindPopup(feature.properties.cng_Meters);
                 //}
             }).addTo(map);
         });

// we will be appending the SVG to the Leaflet map pane
    // g (group) element will be inside the svg and it
    svg = d3.select(map.getPanes().overlayPane).append("svg"),

    // if you don't include the leaflet-zoom-hide when a
    // user zooms in or out you will still see the phantom
    // original SVG
    g = svg.append("g").attr("class", "leaflet-zoom-hide");

    //read in the GeoJSON. This function is asynchronous so
    // anything that needs the json file should be within
    d3.json("10k.geojson", function(collection) {

        //stream transform. transforms geometry before passing it to
        // listener. Can be used in conjunction with d3.geo.path
        // to implement the transform. In this case the transform

        var transform = d3.geo.transform({
            point: projectPoint
        });

        //d3.geo.path translates GeoJSON to SVG path codes.
        //essentially a path generator. In this case it's
        // a path generator referencing our custom "projection"
        // which is the Leaflet method latLngToLayerPoint inside
        // our function called projectPoint
        var d3path = d3.geo.path().projection(transform);

        //essentially we're appending our features to the
        // group element. We're adding a class with the line name
        // and we're making them invisible
        var lineFeatures = g.selectAll("path")
            .data(collection.features)
            .enter()
            .append("path")
            .attr("class", function(d) {
                return d.properties.name

            })
            .attr("style", "opacity:0.5");

        // this is going to be the circle that tracks the
        // route, we're appending it to the g element
        var marker = g.append("circle");
        marker.attr("r", 10)
            .attr("id", "marker");

        // for now we're selecting just one of the lines. And
        // on this one line we're invoking (with the selection.call)
        // our transition function. Using callis the same as invoking
        // the function by hand but makes it easier to use method
        // chaining.
        var path = svg.select("path.line0")
            .attr("style", "opacity:1")
            .call(transition);

        // when the user zooms in or out you need to reset
        // the view
        map.on("viewreset", reset);

        // this puts stuff on the map! Without this "path"
        // only exists in theory
        reset();

             var startPoint = pathStartPoint(path);
         marker.attr("transform", "translate(" + startPoint[0] + "," + startPoint[1] + ")");

     // Reposition the SVG to cover the features.
        function reset() {
            var bounds = d3path.bounds(collection),
                topLeft = bounds[0],
                bottomRight = bounds[1];

            // here you're setting some styles, width, heigh etc
            // to the SVG. Note that we're adding a little height and
            // width because otherwise the bounding box would perfectly
            // cover our features BUT... since you might be using a big
            // circle to represent a 1 dimensional point, the circle
            // might get cut off.

        svg.attr("width", bottomRight[0] - topLeft[0] + 100)
            .attr("height", bottomRight[1] - topLeft[1] + 100)
            .style("left", topLeft[0] - 50 + "px")
            .style("top", topLeft[1] - 50 + "px");

        lineFeatures.attr("d", d3path);
        g.attr("transform", "translate(" + (-topLeft[0] + 50) + "," + (-topLeft[1] + 50) + ")"    );

        }// end reset

        function pathStartPoint(path) {

            var d = path.attr('d');
            console.log(d)

            dsplitted = d.split("L")[0].slice(1).split(",");
            var point = []
            point[0] = parseInt(dsplitted[0]);
            point[1] = parseInt(dsplitted[1]);

            return point;
        }//end pathStartPoint

        function transition(path) {
            path.transition()
                .duration(19000)
                .attrTween("stroke-dasharray", tweenDash)
                //if you want to have it repeat the sequence
                 //then uncomment this piece
                .each("end", function() {
                    d3.select(this).call(transition);
                }); // infinite loop
        } //end transition

        function tweenDash() {
            var l = path.node().getTotalLength(); //total length of path
            var i = d3.interpolateString("0," + l, l + "," + l); // interpolation of stroke-dasharray style attr
            console.log(l)
            return function(t) {
                //t is fraction of time 0-1 since transition began
                var marker = d3.select("#marker");
                console.log(t)
                // p is the point on the line (coordinates) at a given length
                // along the line. In this case if l=50 and we're midway through
                // the time then this would 25.
                var p = path.node().getPointAtLength(t * l);

                //Move the marker to that point
                marker.attr("transform", "translate(" + p.x + "," + p.y + ")"); //move marker
                return i(t);
            }
        } //end tweenDash

        // Use Leaflet to implement a D3 geometric transformation.
        // the latLngToLayerPoint is a Leaflet conversion method:
        //Returns the map layer point that corresponds to the given geographical
        // coordinates (useful for placing overlays on the map).
        function projectPoint(x, y) {
            var point = map.latLngToLayerPoint(new L.LatLng(y, x));
            this.stream.point(point.x, point.y);
        }//end projectPoint
    });

     }
     // you could use $(window).load(main);
 window.onload = main;<commit_msg>change basemap<commit_after> function main() {
         var map = new L.Map('map', {
             zoomControl: false,
             center: [44.908, -75.83],
             zoom: 15
         });
		 L.tileLayer('http://{s}.google.com/vt/lyrs=s&x={x}&y={y}&z={z}',{
    maxZoom: 20,
    subdomains:['mt0','mt1','mt2','mt3']
});.addToMap
         //L.tileLayer(
             //'http://server.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Light_Gray_Base/MapServer/tile/{z}/{y}/{x}', {
                 //attribution: 'Tiles © Esri — Esri, DeLorme, NAVTEQ',
                 //maxZoom: 16
             //}).addTo(map);
         // load 10k course route
         $.getJSON("10k.geojson", function(data) {
             // add GeoJSON layer to the map once the file is loaded
             L.geoJson(data).addTo(map);
         });
         // Define markers
         var startIcon = L.AwesomeMarkers.icon({
             prefix: 'fa',
             icon: 'flag-checkered',
             iconColor: 'white',
             markerColor: 'cadetblue'
         });
         var km1Icon = L.AwesomeMarkers.icon({
             prefix: 'fa',
             icon: '',
             iconColor: 'white',
             markerColor: 'cadetblue',
			 html: "1"
         });
		 var km2Icon = L.AwesomeMarkers.icon({
             prefix: 'fa',
             icon: '',
             iconColor: 'white',
             markerColor: 'cadetblue',
			 html: "2"
         });
		 var km3Icon = L.AwesomeMarkers.icon({
             prefix: 'fa',
             icon: '',
             iconColor: 'white',
             markerColor: 'cadetblue',
			 html: "3"
         });
		 var km4Icon = L.AwesomeMarkers.icon({
             prefix: 'fa',
             icon: '',
             iconColor: 'white',
             markerColor: 'cadetblue',
			 html: "4"
         });
		 var km5Icon = L.AwesomeMarkers.icon({
             prefix: 'fa',
             icon: '',
             iconColor: 'white',
             markerColor: 'cadetblue',
			 html: "5"
         });
		 var km6Icon = L.AwesomeMarkers.icon({
             prefix: 'fa',
             icon: '',
             iconColor: 'white',
             markerColor: 'cadetblue',
			 html: "6"
         });
		 var km7Icon = L.AwesomeMarkers.icon({
             prefix: 'fa',
             icon: '',
             iconColor: 'white',
             markerColor: 'cadetblue',
			 html: "7"
         });
		 var km8Icon = L.AwesomeMarkers.icon({
             prefix: 'fa',
             icon: '',
             iconColor: 'white',
             markerColor: 'cadetblue',
			 html: "8"
         });
		 var km9Icon = L.AwesomeMarkers.icon({
             prefix: 'fa',
             icon: '',
             iconColor: 'white',
             markerColor: 'cadetblue',
			 html: "9"
         });
		 var defaultIcon = L.AwesomeMarkers.icon({
             prefix: 'fa',
             icon: '',
             iconColor: 'white',
             markerColor: 'cadetblue',
			 html: ""
		});
         // load 10k course route features
         $.getJSON("features.geojson", function(data) {
             //add GeoJSON layer to the map once the file is loaded
             L.geoJson(data, {
                 pointToLayer: function(feature, latlng) {
                     if (feature.properties.cng_Meters ==
                         "0.0") {
                         var marker = L.marker(latlng, {
                             icon: startIcon
                         });
					} else if (feature.properties.cng_Meters ==
                         "1000.0") {
                         var marker = L.marker(latlng, {
                             icon: km1Icon
                         });
					} else if (feature.properties.cng_Meters ==
                         "2000.0") {
                         var marker = L.marker(latlng, {
                             icon: km2Icon
                         });
					} else if (feature.properties.cng_Meters ==
                         "3000.0") {
                         var marker = L.marker(latlng, {
                             icon: km3Icon
                         });
					} else if (feature.properties.cng_Meters ==
                         "4000.0") {
                         var marker = L.marker(latlng, {
                             icon: km4Icon
                         });
					} else if (feature.properties.cng_Meters ==
                         "5000.0") {
                         var marker = L.marker(latlng, {
                             icon: km5Icon
                         });
					} else if (feature.properties.cng_Meters ==
                         "6000.0") {
                         var marker = L.marker(latlng, {
                             icon: km6Icon
                         });
					} else if (feature.properties.cng_Meters ==
                         "7000.0") {
                         var marker = L.marker(latlng, {
                             icon: km7Icon
                         });
					} else if (feature.properties.cng_Meters ==
                         "8000.0") {
                         var marker = L.marker(latlng, {
                             icon: km8Icon
                         });
					} else if (feature.properties.cng_Meters ==
                         "9000.0") {
                         var marker = L.marker(latlng, {
                             icon: km9Icon
                         });
                     } else {
                         var marker = L.marker(latlng, {
                             icon: defaultIcon
                         });
                     };
                     return marker;
                     //return new L.marker(latlng, {
                     //icon: startIcon
                     //});
                 },
                 //onEachFeature: function(feature, layer) {
                 //layer.bindPopup(feature.properties.cng_Meters);
                 //}
             }).addTo(map);
         });

// we will be appending the SVG to the Leaflet map pane
    // g (group) element will be inside the svg and it
    svg = d3.select(map.getPanes().overlayPane).append("svg"),

    // if you don't include the leaflet-zoom-hide when a
    // user zooms in or out you will still see the phantom
    // original SVG
    g = svg.append("g").attr("class", "leaflet-zoom-hide");

    //read in the GeoJSON. This function is asynchronous so
    // anything that needs the json file should be within
    d3.json("10k.geojson", function(collection) {

        //stream transform. transforms geometry before passing it to
        // listener. Can be used in conjunction with d3.geo.path
        // to implement the transform. In this case the transform

        var transform = d3.geo.transform({
            point: projectPoint
        });

        //d3.geo.path translates GeoJSON to SVG path codes.
        //essentially a path generator. In this case it's
        // a path generator referencing our custom "projection"
        // which is the Leaflet method latLngToLayerPoint inside
        // our function called projectPoint
        var d3path = d3.geo.path().projection(transform);

        //essentially we're appending our features to the
        // group element. We're adding a class with the line name
        // and we're making them invisible
        var lineFeatures = g.selectAll("path")
            .data(collection.features)
            .enter()
            .append("path")
            .attr("class", function(d) {
                return d.properties.name

            })
            .attr("style", "opacity:0.5");

        // this is going to be the circle that tracks the
        // route, we're appending it to the g element
        var marker = g.append("circle");
        marker.attr("r", 10)
            .attr("id", "marker");

        // for now we're selecting just one of the lines. And
        // on this one line we're invoking (with the selection.call)
        // our transition function. Using callis the same as invoking
        // the function by hand but makes it easier to use method
        // chaining.
        var path = svg.select("path.line0")
            .attr("style", "opacity:1")
            .call(transition);

        // when the user zooms in or out you need to reset
        // the view
        map.on("viewreset", reset);

        // this puts stuff on the map! Without this "path"
        // only exists in theory
        reset();

             var startPoint = pathStartPoint(path);
         marker.attr("transform", "translate(" + startPoint[0] + "," + startPoint[1] + ")");

     // Reposition the SVG to cover the features.
        function reset() {
            var bounds = d3path.bounds(collection),
                topLeft = bounds[0],
                bottomRight = bounds[1];

            // here you're setting some styles, width, heigh etc
            // to the SVG. Note that we're adding a little height and
            // width because otherwise the bounding box would perfectly
            // cover our features BUT... since you might be using a big
            // circle to represent a 1 dimensional point, the circle
            // might get cut off.

        svg.attr("width", bottomRight[0] - topLeft[0] + 100)
            .attr("height", bottomRight[1] - topLeft[1] + 100)
            .style("left", topLeft[0] - 50 + "px")
            .style("top", topLeft[1] - 50 + "px");

        lineFeatures.attr("d", d3path);
        g.attr("transform", "translate(" + (-topLeft[0] + 50) + "," + (-topLeft[1] + 50) + ")"    );

        }// end reset

        function pathStartPoint(path) {

            var d = path.attr('d');
            console.log(d)

            dsplitted = d.split("L")[0].slice(1).split(",");
            var point = []
            point[0] = parseInt(dsplitted[0]);
            point[1] = parseInt(dsplitted[1]);

            return point;
        }//end pathStartPoint

        function transition(path) {
            path.transition()
                .duration(19000)
                .attrTween("stroke-dasharray", tweenDash)
                //if you want to have it repeat the sequence
                 //then uncomment this piece
                .each("end", function() {
                    d3.select(this).call(transition);
                }); // infinite loop
        } //end transition

        function tweenDash() {
            var l = path.node().getTotalLength(); //total length of path
            var i = d3.interpolateString("0," + l, l + "," + l); // interpolation of stroke-dasharray style attr
            console.log(l)
            return function(t) {
                //t is fraction of time 0-1 since transition began
                var marker = d3.select("#marker");
                console.log(t)
                // p is the point on the line (coordinates) at a given length
                // along the line. In this case if l=50 and we're midway through
                // the time then this would 25.
                var p = path.node().getPointAtLength(t * l);

                //Move the marker to that point
                marker.attr("transform", "translate(" + p.x + "," + p.y + ")"); //move marker
                return i(t);
            }
        } //end tweenDash

        // Use Leaflet to implement a D3 geometric transformation.
        // the latLngToLayerPoint is a Leaflet conversion method:
        //Returns the map layer point that corresponds to the given geographical
        // coordinates (useful for placing overlays on the map).
        function projectPoint(x, y) {
            var point = map.latLngToLayerPoint(new L.LatLng(y, x));
            this.stream.point(point.x, point.y);
        }//end projectPoint
    });

     }
     // you could use $(window).load(main);
 window.onload = main;<|endoftext|>


<commit_before>module.exports = function() {
	'use strict';
	var tasks = {
		'build': [
			'clean',
			'shell:bower',
			'build:fonts',
			'build:css',
			'build:images',
			'build:js',
			'clean:bowercomponents',
			'build:i18n'
		],
		'build:dependencies': [
			'build:dependencies:css',
			'build:dependencies:fonts',
			'build:dependencies:js'
		],
		'build:i18n': [
			'clean:languages',
			'addtextdomain',
			'makepot',
			'newer:copy:languages'
		],
		'newplugin': [
			'copy:rename',
			'replace:packagename',
			'readpkg',
			'build'
		],
		'release': [
			'build',
			'copy:release'
		],
		'release:major': [
			'version::major',
			'release'
		],
		'release:minor': [
			'version::minor',
			'release'
		],
		'release:patch': [
			'version::patch',
			'release'
		],
		'default': [
			'watch'
		]
	};

	return tasks;
};
<commit_msg>Run readpkg before build<commit_after>module.exports = function() {
	'use strict';
	var tasks = {
		'build': [
			'readpkg',
			'clean',
			'shell:bower',
			'build:fonts',
			'build:css',
			'build:images',
			'build:js',
			'clean:bowercomponents',
			'build:i18n'
		],
		'build:dependencies': [
			'build:dependencies:css',
			'build:dependencies:fonts',
			'build:dependencies:js'
		],
		'build:i18n': [
			'clean:languages',
			'addtextdomain',
			'makepot',
			'newer:copy:languages'
		],
		'newplugin': [
			'copy:rename',
			'replace:packagename',
			'readpkg',
			'build'
		],
		'release': [
			'build',
			'copy:release'
		],
		'release:major': [
			'version::major',
			'release'
		],
		'release:minor': [
			'version::minor',
			'release'
		],
		'release:patch': [
			'version::patch',
			'release'
		],
		'default': [
			'watch'
		]
	};

	return tasks;
};
<|endoftext|>


<commit_before>goog.provide('ol.render.webgl.Immediate');

goog.require('ol');
goog.require('ol.extent');
goog.require('ol.geom.GeometryType');
goog.require('ol.render.ReplayType');
goog.require('ol.render.VectorContext');
goog.require('ol.render.webgl.ReplayGroup');

if (ol.ENABLE_WEBGL) {

  /**
   * @constructor
   * @extends {ol.render.VectorContext}
   * @param {ol.webgl.Context} context Context.
   * @param {ol.Coordinate} center Center.
   * @param {number} resolution Resolution.
   * @param {number} rotation Rotation.
   * @param {ol.Size} size Size.
   * @param {ol.Extent} extent Extent.
   * @param {number} pixelRatio Pixel ratio.
   * @struct
   */
  ol.render.webgl.Immediate = function(context, center, resolution, rotation, size, extent, pixelRatio) {
    ol.render.VectorContext.call(this);

    /**
     * @private
     */
    this.context_ = context;

    /**
     * @private
     */
    this.center_ = center;

    /**
     * @private
     */
    this.extent_ = extent;

    /**
     * @private
     */
    this.pixelRatio_ = pixelRatio;

    /**
     * @private
     */
    this.size_ = size;

    /**
     * @private
     */
    this.rotation_ = rotation;

    /**
     * @private
     */
    this.resolution_ = resolution;

    /**
     * @private
     * @type {ol.style.Image}
     */
    this.imageStyle_ = null;

    /**
     * @private
     * @type {ol.style.Fill}
     */
    this.fillStyle_ = null;

    /**
     * @private
     * @type {ol.style.Stroke}
     */
    this.strokeStyle_ = null;

  };
  ol.inherits(ol.render.webgl.Immediate, ol.render.VectorContext);

  /**
   * Set the rendering style.  Note that since this is an immediate rendering API,
   * any `zIndex` on the provided style will be ignored.
   *
   * @param {ol.style.Style} style The rendering style.
   * @override
   * @api
   */
  ol.render.webgl.Immediate.prototype.setStyle = function(style) {
    this.setFillStrokeStyle(style.getFill(), style.getStroke());
    this.setImageStyle(style.getImage());
  };

  /**
   * Render a geometry into the canvas.  Call
   * {@link ol.render.webgl.Immediate#setStyle} first to set the rendering style.
   *
   * @param {ol.geom.Geometry|ol.render.Feature} geometry The geometry to render.
   * @override
   * @api
   */
  ol.render.webgl.Immediate.prototype.drawGeometry = function(geometry) {
    var type = geometry.getType();
    switch (type) {
      case ol.geom.GeometryType.POINT:
        this.drawPoint(/** @type {ol.geom.Point} */ (geometry), null);
        break;
      case ol.geom.GeometryType.LINE_STRING:
        this.drawLineString(/** @type {ol.geom.LineString} */ (geometry), null);
        break;
      case ol.geom.GeometryType.POLYGON:
        this.drawPolygon(/** @type {ol.geom.Polygon} */ (geometry), null);
        break;
      case ol.geom.GeometryType.MULTI_POINT:
        this.drawMultiPoint(/** @type {ol.geom.MultiPoint} */ (geometry), null);
        break;
      case ol.geom.GeometryType.MULTI_LINE_STRING:
        this.drawMultiLineString(/** @type {ol.geom.MultiLineString} */ (geometry), null);
        break;
      case ol.geom.GeometryType.MULTI_POLYGON:
        this.drawMultiPolygon(/** @type {ol.geom.MultiPolygon} */ (geometry), null);
        break;
      case ol.geom.GeometryType.GEOMETRY_COLLECTION:
        this.drawGeometryCollection(/** @type {ol.geom.GeometryCollection} */ (geometry), null);
        break;
      case ol.geom.GeometryType.CIRCLE:
        this.drawCircle(/** @type {ol.geom.Circle} */ (geometry), null);
        break;
      default:
        // pass
    }
  };

  /**
   * @inheritDoc
   * @api
   */
  ol.render.webgl.Immediate.prototype.drawFeature = function(feature, style) {
    var geometry = style.getGeometryFunction()(feature);
    if (!geometry ||
        !ol.extent.intersects(this.extent_, geometry.getExtent())) {
      return;
    }
    this.setStyle(style);
    this.drawGeometry(geometry);
  };

  /**
   * @inheritDoc
   */
  ol.render.webgl.Immediate.prototype.drawGeometryCollection = function(geometry, data) {
    var geometries = geometry.getGeometriesArray();
    var i, ii;
    for (i = 0, ii = geometries.length; i < ii; ++i) {
      this.drawGeometry(geometries[i]);
    }
  };

  /**
   * @inheritDoc
   */
  ol.render.webgl.Immediate.prototype.drawPoint = function(geometry, data) {
    var context = this.context_;
    var replayGroup = new ol.render.webgl.ReplayGroup(1, this.extent_);
    var replay = /** @type {ol.render.webgl.ImageReplay} */ (
      replayGroup.getReplay(0, ol.render.ReplayType.IMAGE));
    replay.setImageStyle(this.imageStyle_);
    replay.drawPoint(geometry, data);
    replay.finish(context);
    // default colors
    var opacity = 1;
    var skippedFeatures = {};
    var featureCallback;
    var oneByOne = false;
    replay.replay(this.context_, this.center_, this.resolution_, this.rotation_,
        this.size_, this.pixelRatio_, opacity, skippedFeatures, featureCallback,
        oneByOne);
    replay.getDeleteResourcesFunction(context)();
  };

  /**
   * @inheritDoc
   */
  ol.render.webgl.Immediate.prototype.drawMultiPoint = function(geometry, data) {
    var context = this.context_;
    var replayGroup = new ol.render.webgl.ReplayGroup(1, this.extent_);
    var replay = /** @type {ol.render.webgl.ImageReplay} */ (
      replayGroup.getReplay(0, ol.render.ReplayType.IMAGE));
    replay.setImageStyle(this.imageStyle_);
    replay.drawMultiPoint(geometry, data);
    replay.finish(context);
    var opacity = 1;
    var skippedFeatures = {};
    var featureCallback;
    var oneByOne = false;
    replay.replay(this.context_, this.center_, this.resolution_, this.rotation_,
        this.size_, this.pixelRatio_, opacity, skippedFeatures, featureCallback,
        oneByOne);
    replay.getDeleteResourcesFunction(context)();
  };

  /**
   * @inheritDoc
   */
  ol.render.webgl.Immediate.prototype.drawLineString = function(geometry, data) {
    var context = this.context_;
    var replayGroup = new ol.render.webgl.ReplayGroup(1, this.extent_);
    var replay = /** @type {ol.render.webgl.LineStringReplay} */ (
      replayGroup.getReplay(0, ol.render.ReplayType.LINE_STRING));
    replay.setFillStrokeStyle(null, this.strokeStyle_);
    replay.drawLineString(geometry, data);
    replay.finish(context);
    var opacity = 1;
    var skippedFeatures = {};
    var featureCallback;
    var oneByOne = false;
    replay.replay(this.context_, this.center_, this.resolution_, this.rotation_,
        this.size_, this.pixelRatio_, opacity, skippedFeatures, featureCallback,
        oneByOne);
    replay.getDeleteResourcesFunction(context)();
  };

  /**
   * @inheritDoc
   */
  ol.render.webgl.Immediate.prototype.drawMultiLineString = function(geometry, data) {
    var context = this.context_;
    var replayGroup = new ol.render.webgl.ReplayGroup(1, this.extent_);
    var replay = /** @type {ol.render.webgl.LineStringReplay} */ (
      replayGroup.getReplay(0, ol.render.ReplayType.LINE_STRING));
    replay.setFillStrokeStyle(null, this.strokeStyle_);
    replay.drawMultiLineString(geometry, data);
    replay.finish(context);
    var opacity = 1;
    var skippedFeatures = {};
    var featureCallback;
    var oneByOne = false;
    replay.replay(this.context_, this.center_, this.resolution_, this.rotation_,
        this.size_, this.pixelRatio_, opacity, skippedFeatures, featureCallback,
        oneByOne);
    replay.getDeleteResourcesFunction(context)();
  };

  /**
   * @inheritDoc
   */
  ol.render.webgl.Immediate.prototype.drawPolygon = function(geometry, data) {
    var context = this.context_;
    var replayGroup = new ol.render.webgl.ReplayGroup(1, this.extent_);
    var replay = /** @type {ol.render.webgl.PolygonReplay} */ (
      replayGroup.getReplay(0, ol.render.ReplayType.POLYGON));
    replay.setFillStrokeStyle(this.fillStyle_, this.strokeStyle_);
    replay.drawPolygon(geometry, data);
    replay.finish(context);
    var opacity = 1;
    var skippedFeatures = {};
    var featureCallback;
    var oneByOne = false;
    replay.replay(this.context_, this.center_, this.resolution_, this.rotation_,
        this.size_, this.pixelRatio_, opacity, skippedFeatures, featureCallback,
        oneByOne);
    replay.getDeleteResourcesFunction(context)();
  };

  /**
   * @inheritDoc
   */
  ol.render.webgl.Immediate.prototype.drawMultiPolygon = function(geometry, data) {
    var context = this.context_;
    var replayGroup = new ol.render.webgl.ReplayGroup(1, this.extent_);
    var replay = /** @type {ol.render.webgl.PolygonReplay} */ (
      replayGroup.getReplay(0, ol.render.ReplayType.POLYGON));
    replay.setFillStrokeStyle(this.fillStyle_, this.strokeStyle_);
    replay.drawMultiPolygon(geometry, data);
    replay.finish(context);
    var opacity = 1;
    var skippedFeatures = {};
    var featureCallback;
    var oneByOne = false;
    replay.replay(this.context_, this.center_, this.resolution_, this.rotation_,
        this.size_, this.pixelRatio_, opacity, skippedFeatures, featureCallback,
        oneByOne);
    replay.getDeleteResourcesFunction(context)();
  };

  /**
   * @inheritDoc
   */
  ol.render.webgl.Immediate.prototype.drawCircle = function(geometry, data) {
    var context = this.context_;
    var replayGroup = new ol.render.webgl.ReplayGroup(1, this.extent_);
    var replay = /** @type {ol.render.webgl.CircleReplay} */ (
      replayGroup.getReplay(0, ol.render.ReplayType.CIRCLE));
    replay.setFillStrokeStyle(this.fillStyle_, this.strokeStyle_);
    replay.drawCircle(geometry, data);
    replay.finish(context);
    var opacity = 1;
    var skippedFeatures = {};
    var featureCallback;
    var oneByOne = false;
    replay.replay(this.context_, this.center_, this.resolution_, this.rotation_,
        this.size_, this.pixelRatio_, opacity, skippedFeatures, featureCallback,
        oneByOne);
    replay.getDeleteResourcesFunction(context)();
  };

  /**
   * @inheritDoc
   */
  ol.render.webgl.Immediate.prototype.setImageStyle = function(imageStyle) {
    this.imageStyle_ = imageStyle;
  };

  /**
   * @inheritDoc
   */
  ol.render.webgl.Immediate.prototype.setFillStrokeStyle = function(fillStyle, strokeStyle) {
    this.fillStyle_ = fillStyle;
    this.strokeStyle_ = strokeStyle;
  };

}
<commit_msg>Add immediate WebGL text renderer<commit_after>goog.provide('ol.render.webgl.Immediate');

goog.require('ol');
goog.require('ol.extent');
goog.require('ol.geom.GeometryType');
goog.require('ol.render.ReplayType');
goog.require('ol.render.VectorContext');
goog.require('ol.render.webgl.ReplayGroup');

if (ol.ENABLE_WEBGL) {

  /**
   * @constructor
   * @extends {ol.render.VectorContext}
   * @param {ol.webgl.Context} context Context.
   * @param {ol.Coordinate} center Center.
   * @param {number} resolution Resolution.
   * @param {number} rotation Rotation.
   * @param {ol.Size} size Size.
   * @param {ol.Extent} extent Extent.
   * @param {number} pixelRatio Pixel ratio.
   * @struct
   */
  ol.render.webgl.Immediate = function(context, center, resolution, rotation, size, extent, pixelRatio) {
    ol.render.VectorContext.call(this);

    /**
     * @private
     */
    this.context_ = context;

    /**
     * @private
     */
    this.center_ = center;

    /**
     * @private
     */
    this.extent_ = extent;

    /**
     * @private
     */
    this.pixelRatio_ = pixelRatio;

    /**
     * @private
     */
    this.size_ = size;

    /**
     * @private
     */
    this.rotation_ = rotation;

    /**
     * @private
     */
    this.resolution_ = resolution;

    /**
     * @private
     * @type {ol.style.Image}
     */
    this.imageStyle_ = null;

    /**
     * @private
     * @type {ol.style.Fill}
     */
    this.fillStyle_ = null;

    /**
     * @private
     * @type {ol.style.Stroke}
     */
    this.strokeStyle_ = null;

    /**
     * @private
     * @type {ol.style.Text}
     */
    this.textStyle_ = null;

  };
  ol.inherits(ol.render.webgl.Immediate, ol.render.VectorContext);

  /**
   * @param {ol.render.webgl.ReplayGroup} replayGroup Replay group.
   * @param {Array.<number>} flatCoordinates Flat coordinates.
   * @param {number} offset Offset.
   * @param {number} end End.
   * @param {number} stride Stride.
   * @private
   */
  ol.render.webgl.Immediate.prototype.drawText_ = function(replayGroup,
      flatCoordinates, offset, end, stride) {
    var context = this.context_;
    var replay = /** @type {ol.render.webgl.TextReplay} */ (
      replayGroup.getReplay(0, ol.render.ReplayType.TEXT));
    replay.setTextStyle(this.textStyle_);
    replay.drawText(flatCoordinates, offset, end, stride, null, null);
    replay.finish(context);
    // default colors
    var opacity = 1;
    var skippedFeatures = {};
    var featureCallback;
    var oneByOne = false;
    replay.replay(this.context_, this.center_, this.resolution_, this.rotation_,
        this.size_, this.pixelRatio_, opacity, skippedFeatures, featureCallback,
        oneByOne);
    replay.getDeleteResourcesFunction(context)();
  };

  /**
   * Set the rendering style.  Note that since this is an immediate rendering API,
   * any `zIndex` on the provided style will be ignored.
   *
   * @param {ol.style.Style} style The rendering style.
   * @override
   * @api
   */
  ol.render.webgl.Immediate.prototype.setStyle = function(style) {
    this.setFillStrokeStyle(style.getFill(), style.getStroke());
    this.setImageStyle(style.getImage());
    this.setTextStyle(style.getText());
  };

  /**
   * Render a geometry into the canvas.  Call
   * {@link ol.render.webgl.Immediate#setStyle} first to set the rendering style.
   *
   * @param {ol.geom.Geometry|ol.render.Feature} geometry The geometry to render.
   * @override
   * @api
   */
  ol.render.webgl.Immediate.prototype.drawGeometry = function(geometry) {
    var type = geometry.getType();
    switch (type) {
      case ol.geom.GeometryType.POINT:
        this.drawPoint(/** @type {ol.geom.Point} */ (geometry), null);
        break;
      case ol.geom.GeometryType.LINE_STRING:
        this.drawLineString(/** @type {ol.geom.LineString} */ (geometry), null);
        break;
      case ol.geom.GeometryType.POLYGON:
        this.drawPolygon(/** @type {ol.geom.Polygon} */ (geometry), null);
        break;
      case ol.geom.GeometryType.MULTI_POINT:
        this.drawMultiPoint(/** @type {ol.geom.MultiPoint} */ (geometry), null);
        break;
      case ol.geom.GeometryType.MULTI_LINE_STRING:
        this.drawMultiLineString(/** @type {ol.geom.MultiLineString} */ (geometry), null);
        break;
      case ol.geom.GeometryType.MULTI_POLYGON:
        this.drawMultiPolygon(/** @type {ol.geom.MultiPolygon} */ (geometry), null);
        break;
      case ol.geom.GeometryType.GEOMETRY_COLLECTION:
        this.drawGeometryCollection(/** @type {ol.geom.GeometryCollection} */ (geometry), null);
        break;
      case ol.geom.GeometryType.CIRCLE:
        this.drawCircle(/** @type {ol.geom.Circle} */ (geometry), null);
        break;
      default:
        // pass
    }
  };

  /**
   * @inheritDoc
   * @api
   */
  ol.render.webgl.Immediate.prototype.drawFeature = function(feature, style) {
    var geometry = style.getGeometryFunction()(feature);
    if (!geometry ||
        !ol.extent.intersects(this.extent_, geometry.getExtent())) {
      return;
    }
    this.setStyle(style);
    this.drawGeometry(geometry);
  };

  /**
   * @inheritDoc
   */
  ol.render.webgl.Immediate.prototype.drawGeometryCollection = function(geometry, data) {
    var geometries = geometry.getGeometriesArray();
    var i, ii;
    for (i = 0, ii = geometries.length; i < ii; ++i) {
      this.drawGeometry(geometries[i]);
    }
  };

  /**
   * @inheritDoc
   */
  ol.render.webgl.Immediate.prototype.drawPoint = function(geometry, data) {
    var context = this.context_;
    var replayGroup = new ol.render.webgl.ReplayGroup(1, this.extent_);
    var replay = /** @type {ol.render.webgl.ImageReplay} */ (
      replayGroup.getReplay(0, ol.render.ReplayType.IMAGE));
    replay.setImageStyle(this.imageStyle_);
    replay.drawPoint(geometry, data);
    replay.finish(context);
    // default colors
    var opacity = 1;
    var skippedFeatures = {};
    var featureCallback;
    var oneByOne = false;
    replay.replay(this.context_, this.center_, this.resolution_, this.rotation_,
        this.size_, this.pixelRatio_, opacity, skippedFeatures, featureCallback,
        oneByOne);
    replay.getDeleteResourcesFunction(context)();

    if (this.textStyle_) {
      var flatCoordinates = geometry.getFlatCoordinates();
      var stride = geometry.getStride();
      this.drawText_(replayGroup, flatCoordinates, 0, flatCoordinates.length, stride);
    }
  };

  /**
   * @inheritDoc
   */
  ol.render.webgl.Immediate.prototype.drawMultiPoint = function(geometry, data) {
    var context = this.context_;
    var replayGroup = new ol.render.webgl.ReplayGroup(1, this.extent_);
    var replay = /** @type {ol.render.webgl.ImageReplay} */ (
      replayGroup.getReplay(0, ol.render.ReplayType.IMAGE));
    replay.setImageStyle(this.imageStyle_);
    replay.drawMultiPoint(geometry, data);
    replay.finish(context);
    var opacity = 1;
    var skippedFeatures = {};
    var featureCallback;
    var oneByOne = false;
    replay.replay(this.context_, this.center_, this.resolution_, this.rotation_,
        this.size_, this.pixelRatio_, opacity, skippedFeatures, featureCallback,
        oneByOne);
    replay.getDeleteResourcesFunction(context)();

    if (this.textStyle_) {
      var flatCoordinates = geometry.getFlatCoordinates();
      var stride = geometry.getStride();
      this.drawText_(replayGroup, flatCoordinates, 0, flatCoordinates.length, stride);
    }
  };

  /**
   * @inheritDoc
   */
  ol.render.webgl.Immediate.prototype.drawLineString = function(geometry, data) {
    var context = this.context_;
    var replayGroup = new ol.render.webgl.ReplayGroup(1, this.extent_);
    var replay = /** @type {ol.render.webgl.LineStringReplay} */ (
      replayGroup.getReplay(0, ol.render.ReplayType.LINE_STRING));
    replay.setFillStrokeStyle(null, this.strokeStyle_);
    replay.drawLineString(geometry, data);
    replay.finish(context);
    var opacity = 1;
    var skippedFeatures = {};
    var featureCallback;
    var oneByOne = false;
    replay.replay(this.context_, this.center_, this.resolution_, this.rotation_,
        this.size_, this.pixelRatio_, opacity, skippedFeatures, featureCallback,
        oneByOne);
    replay.getDeleteResourcesFunction(context)();

    if (this.textStyle_) {
      var flatMidpoint = geometry.getFlatMidpoint();
      this.drawText_(replayGroup, flatMidpoint, 0, 2, 2);
    }
  };

  /**
   * @inheritDoc
   */
  ol.render.webgl.Immediate.prototype.drawMultiLineString = function(geometry, data) {
    var context = this.context_;
    var replayGroup = new ol.render.webgl.ReplayGroup(1, this.extent_);
    var replay = /** @type {ol.render.webgl.LineStringReplay} */ (
      replayGroup.getReplay(0, ol.render.ReplayType.LINE_STRING));
    replay.setFillStrokeStyle(null, this.strokeStyle_);
    replay.drawMultiLineString(geometry, data);
    replay.finish(context);
    var opacity = 1;
    var skippedFeatures = {};
    var featureCallback;
    var oneByOne = false;
    replay.replay(this.context_, this.center_, this.resolution_, this.rotation_,
        this.size_, this.pixelRatio_, opacity, skippedFeatures, featureCallback,
        oneByOne);
    replay.getDeleteResourcesFunction(context)();

    if (this.textStyle_) {
      var flatMidpoints = geometry.getFlatMidpoints();
      this.drawText_(replayGroup, flatMidpoints, 0, flatMidpoints.length, 2);
    }
  };

  /**
   * @inheritDoc
   */
  ol.render.webgl.Immediate.prototype.drawPolygon = function(geometry, data) {
    var context = this.context_;
    var replayGroup = new ol.render.webgl.ReplayGroup(1, this.extent_);
    var replay = /** @type {ol.render.webgl.PolygonReplay} */ (
      replayGroup.getReplay(0, ol.render.ReplayType.POLYGON));
    replay.setFillStrokeStyle(this.fillStyle_, this.strokeStyle_);
    replay.drawPolygon(geometry, data);
    replay.finish(context);
    var opacity = 1;
    var skippedFeatures = {};
    var featureCallback;
    var oneByOne = false;
    replay.replay(this.context_, this.center_, this.resolution_, this.rotation_,
        this.size_, this.pixelRatio_, opacity, skippedFeatures, featureCallback,
        oneByOne);
    replay.getDeleteResourcesFunction(context)();

    if (this.textStyle_) {
      var flatInteriorPoint = geometry.getFlatInteriorPoint();
      this.drawText_(replayGroup, flatInteriorPoint, 0, 2, 2);
    }
  };

  /**
   * @inheritDoc
   */
  ol.render.webgl.Immediate.prototype.drawMultiPolygon = function(geometry, data) {
    var context = this.context_;
    var replayGroup = new ol.render.webgl.ReplayGroup(1, this.extent_);
    var replay = /** @type {ol.render.webgl.PolygonReplay} */ (
      replayGroup.getReplay(0, ol.render.ReplayType.POLYGON));
    replay.setFillStrokeStyle(this.fillStyle_, this.strokeStyle_);
    replay.drawMultiPolygon(geometry, data);
    replay.finish(context);
    var opacity = 1;
    var skippedFeatures = {};
    var featureCallback;
    var oneByOne = false;
    replay.replay(this.context_, this.center_, this.resolution_, this.rotation_,
        this.size_, this.pixelRatio_, opacity, skippedFeatures, featureCallback,
        oneByOne);
    replay.getDeleteResourcesFunction(context)();

    if (this.textStyle_) {
      var flatInteriorPoints = geometry.getFlatInteriorPoints();
      this.drawText_(replayGroup, flatInteriorPoints, 0, flatInteriorPoints.length, 2);
    }
  };

  /**
   * @inheritDoc
   */
  ol.render.webgl.Immediate.prototype.drawCircle = function(geometry, data) {
    var context = this.context_;
    var replayGroup = new ol.render.webgl.ReplayGroup(1, this.extent_);
    var replay = /** @type {ol.render.webgl.CircleReplay} */ (
      replayGroup.getReplay(0, ol.render.ReplayType.CIRCLE));
    replay.setFillStrokeStyle(this.fillStyle_, this.strokeStyle_);
    replay.drawCircle(geometry, data);
    replay.finish(context);
    var opacity = 1;
    var skippedFeatures = {};
    var featureCallback;
    var oneByOne = false;
    replay.replay(this.context_, this.center_, this.resolution_, this.rotation_,
        this.size_, this.pixelRatio_, opacity, skippedFeatures, featureCallback,
        oneByOne);
    replay.getDeleteResourcesFunction(context)();

    if (this.textStyle_) {
      this.drawText_(replayGroup, geometry.getCenter(), 0, 2, 2);
    }
  };

  /**
   * @inheritDoc
   */
  ol.render.webgl.Immediate.prototype.setImageStyle = function(imageStyle) {
    this.imageStyle_ = imageStyle;
  };

  /**
   * @inheritDoc
   */
  ol.render.webgl.Immediate.prototype.setFillStrokeStyle = function(fillStyle, strokeStyle) {
    this.fillStyle_ = fillStyle;
    this.strokeStyle_ = strokeStyle;
  };

  /**
   * @inheritDoc
   */
  ol.render.webgl.Immediate.prototype.setTextStyle = function(textStyle) {
    this.textStyle_ = textStyle;
  };

}
<|endoftext|>