<commit_before>/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
 * Licensed under the MIT License
 */
'use strict';

var d = require('../lib/dom')
  , defaultSettings = require('./default-setting')
  , EventManager = require('../lib/event-manager')
  , guid = require('../lib/guid')
  , h = require('../lib/helper');

var instances = {};

function Instance(element) {
  var i = this;

  i.settings = h.clone(defaultSettings);
  i.containerWidth = null;
  i.containerHeight = null;
  i.contentWidth = null;
  i.contentHeight = null;

  i.isRtl = d.css(element, 'direction') === "rtl";
  i.isNegativeScroll = (function () {
    var originalScrollLeft = element.scrollLeft;
    var result = null;
    element.scrollLeft = -1;
    result = element.scrollLeft < 0;
    element.scrollLeft = originalScrollLeft;
    return result;
  })();
  i.negativeScrollAdjustment = i.isNegativeScroll ? element.scrollWidth - element.clientWidth : 0;
  i.event = new EventManager();
  i.ownerDocument = element.ownerDocument || document;

  i.scrollbarXRail = d.appendTo(d.e('div', 'ps-scrollbar-x-rail'), element);
  i.scrollbarX = d.appendTo(d.e('div', 'ps-scrollbar-x'), i.scrollbarXRail);
  i.scrollbarXActive = null;
  i.scrollbarXWidth = null;
  i.scrollbarXLeft = null;
  i.scrollbarXBottom = h.toInt(d.css(i.scrollbarXRail, 'bottom'));
  i.isScrollbarXUsingBottom = i.scrollbarXBottom === i.scrollbarXBottom; // !isNaN
  i.scrollbarXTop = i.isScrollbarXUsingBottom ? null : h.toInt(d.css(i.scrollbarXRail, 'top'));
  i.railBorderXWidth = h.toInt(d.css(i.scrollbarXRail, 'borderLeftWidth')) + h.toInt(d.css(i.scrollbarXRail, 'borderRightWidth'));
  // Set rail to display:block to calculate margins
  d.css(i.scrollbarXRail, 'display', 'block');
  i.railXMarginWidth = h.toInt(d.css(i.scrollbarXRail, 'marginLeft')) + h.toInt(d.css(i.scrollbarXRail, 'marginRight'));
  d.css(i.scrollbarXRail, 'display', '');
  i.railXWidth = null;
  i.railXRatio = null;

  i.scrollbarYRail = d.appendTo(d.e('div', 'ps-scrollbar-y-rail'), element);
  i.scrollbarY = d.appendTo(d.e('div', 'ps-scrollbar-y'), i.scrollbarYRail);
  i.scrollbarYActive = null;
  i.scrollbarYHeight = null;
  i.scrollbarYTop = null;
  i.scrollbarYRight = h.toInt(d.css(i.scrollbarYRail, 'right'));
  i.isScrollbarYUsingRight = i.scrollbarYRight === i.scrollbarYRight; // !isNaN
  i.scrollbarYLeft = i.isScrollbarYUsingRight ? null : h.toInt(d.css(i.scrollbarYRail, 'left'));
  i.scrollbarYOuterWidth = i.isRtl ? h.outerWidth(i.scrollbarY) : null;
  i.railBorderYWidth = h.toInt(d.css(i.scrollbarYRail, 'borderTopWidth')) + h.toInt(d.css(i.scrollbarYRail, 'borderBottomWidth'));
  d.css(i.scrollbarYRail, 'display', 'block');
  i.railYMarginHeight = h.toInt(d.css(i.scrollbarYRail, 'marginTop')) + h.toInt(d.css(i.scrollbarYRail, 'marginBottom'));
  d.css(i.scrollbarYRail, 'display', '');
  i.railYHeight = null;
  i.railYRatio = null;
}

function getId(element) {
  if (typeof element.dataset === 'undefined') {
    return element.getAttribute('data-ps-id');
  } else {
    return element.dataset.psId;
  }
}

function setId(element, id) {
  if (typeof element.dataset === 'undefined') {
    element.setAttribute('data-ps-id', id);
  } else {
    element.dataset.psId = id;
  }
}

function removeId(element) {
  if (typeof element.dataset === 'undefined') {
    element.removeAttribute('data-ps-id');
  } else {
    delete element.dataset.psId;
  }
}

exports.add = function (element) {
  var newId = guid();
  setId(element, newId);
  instances[newId] = new Instance(element);
  return instances[newId];
};

exports.remove = function (element) {
  delete instances[getId(element)];
  removeId(element);
};

exports.get = function (element) {
  return instances[getId(element)];
};
<commit_msg>Add tabindex properties to scrollbars<commit_after>/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
 * Licensed under the MIT License
 */
'use strict';

var d = require('../lib/dom')
  , defaultSettings = require('./default-setting')
  , EventManager = require('../lib/event-manager')
  , guid = require('../lib/guid')
  , h = require('../lib/helper');

var instances = {};

function Instance(element) {
  var i = this;

  i.settings = h.clone(defaultSettings);
  i.containerWidth = null;
  i.containerHeight = null;
  i.contentWidth = null;
  i.contentHeight = null;

  i.isRtl = d.css(element, 'direction') === "rtl";
  i.isNegativeScroll = (function () {
    var originalScrollLeft = element.scrollLeft;
    var result = null;
    element.scrollLeft = -1;
    result = element.scrollLeft < 0;
    element.scrollLeft = originalScrollLeft;
    return result;
  })();
  i.negativeScrollAdjustment = i.isNegativeScroll ? element.scrollWidth - element.clientWidth : 0;
  i.event = new EventManager();
  i.ownerDocument = element.ownerDocument || document;

  i.scrollbarXRail = d.appendTo(d.e('div', 'ps-scrollbar-x-rail'), element);
  i.scrollbarX = d.appendTo(d.e('div', 'ps-scrollbar-x'), i.scrollbarXRail);
  i.scrollbarX.setAttribute('tabindex', 0);
  i.scrollbarXActive = null;
  i.scrollbarXWidth = null;
  i.scrollbarXLeft = null;
  i.scrollbarXBottom = h.toInt(d.css(i.scrollbarXRail, 'bottom'));
  i.isScrollbarXUsingBottom = i.scrollbarXBottom === i.scrollbarXBottom; // !isNaN
  i.scrollbarXTop = i.isScrollbarXUsingBottom ? null : h.toInt(d.css(i.scrollbarXRail, 'top'));
  i.railBorderXWidth = h.toInt(d.css(i.scrollbarXRail, 'borderLeftWidth')) + h.toInt(d.css(i.scrollbarXRail, 'borderRightWidth'));
  // Set rail to display:block to calculate margins
  d.css(i.scrollbarXRail, 'display', 'block');
  i.railXMarginWidth = h.toInt(d.css(i.scrollbarXRail, 'marginLeft')) + h.toInt(d.css(i.scrollbarXRail, 'marginRight'));
  d.css(i.scrollbarXRail, 'display', '');
  i.railXWidth = null;
  i.railXRatio = null;

  i.scrollbarYRail = d.appendTo(d.e('div', 'ps-scrollbar-y-rail'), element);
  i.scrollbarY = d.appendTo(d.e('div', 'ps-scrollbar-y'), i.scrollbarYRail);
  i.scrollbarY.setAttribute('tabindex', 0);
  i.scrollbarYActive = null;
  i.scrollbarYHeight = null;
  i.scrollbarYTop = null;
  i.scrollbarYRight = h.toInt(d.css(i.scrollbarYRail, 'right'));
  i.isScrollbarYUsingRight = i.scrollbarYRight === i.scrollbarYRight; // !isNaN
  i.scrollbarYLeft = i.isScrollbarYUsingRight ? null : h.toInt(d.css(i.scrollbarYRail, 'left'));
  i.scrollbarYOuterWidth = i.isRtl ? h.outerWidth(i.scrollbarY) : null;
  i.railBorderYWidth = h.toInt(d.css(i.scrollbarYRail, 'borderTopWidth')) + h.toInt(d.css(i.scrollbarYRail, 'borderBottomWidth'));
  d.css(i.scrollbarYRail, 'display', 'block');
  i.railYMarginHeight = h.toInt(d.css(i.scrollbarYRail, 'marginTop')) + h.toInt(d.css(i.scrollbarYRail, 'marginBottom'));
  d.css(i.scrollbarYRail, 'display', '');
  i.railYHeight = null;
  i.railYRatio = null;
}

function getId(element) {
  if (typeof element.dataset === 'undefined') {
    return element.getAttribute('data-ps-id');
  } else {
    return element.dataset.psId;
  }
}

function setId(element, id) {
  if (typeof element.dataset === 'undefined') {
    element.setAttribute('data-ps-id', id);
  } else {
    element.dataset.psId = id;
  }
}

function removeId(element) {
  if (typeof element.dataset === 'undefined') {
    element.removeAttribute('data-ps-id');
  } else {
    delete element.dataset.psId;
  }
}

exports.add = function (element) {
  var newId = guid();
  setId(element, newId);
  instances[newId] = new Instance(element);
  return instances[newId];
};

exports.remove = function (element) {
  delete instances[getId(element)];
  removeId(element);
};

exports.get = function (element) {
  return instances[getId(element)];
};
<|endoftext|>


<commit_before>'use strict';

module.exports = function(shariff) {
    var url = encodeURIComponent(shariff.getURL());
    return {
        popup: true,
        shareText: 'tweet',
        name: 'twitter',
        faName: 'fa-twitter',
        title: {
            'de': 'Bei Twitter teilen',
            'en': 'Share on Twitter',
            'es': 'Compartir en Twitter'
        },
        shareUrl: 'https://twitter.com/intent/tweet?text='+ url + '&url=' + shariff.getURL() + shariff.getReferrerTrack()
    };
};
<commit_msg>fix last fix :-)<commit_after>'use strict';

module.exports = function(shariff) {
    var url = encodeURIComponent(shariff.getURL());
    return {
        popup: true,
        shareText: 'tweet',
        name: 'twitter',
        faName: 'fa-twitter',
        title: {
            'de': 'Bei Twitter teilen',
            'en': 'Share on Twitter',
            'es': 'Compartir en Twitter'
        },
        shareUrl: 'https://twitter.com/intent/tweet?text='+ shariff.getShareText() + '&url=' + url + shariff.getReferrerTrack()
    };
};
<|endoftext|>


<commit_before>import TodoActions from 'actions/TodoActions';
import {List, Map} from 'immutable';
import KEYS from 'js/constants';
import alt from 'js/alt';

//- Crappy UUID Generator, but it works for this demo
let uuid = 0;
let uuidGenerator = () => (++uuid).toString();

class TodoStore {

  constructor () {
    // Set store defaults
    this.todos = new List();
    this.filter = '';

    // Bind events for this.emit from the actions
    this.bindListeners({
      undo: TodoActions.undo,
      redo: TodoActions.redo,
      addTodo: TodoActions.addTodo,
      editTodo: TodoActions.editTodo,
      setFilter: TodoActions.setFilter,
      removeTodo: TodoActions.removeTodo,
      clearCompleted: TodoActions.clearCompleted,
      toggleComplete: TodoActions.toggleComplete,
      toggleAllComplete: TodoActions.toggleAllComplete
    });
  }

  undo () {

  }

  redo () {

  }

  addTodo (text) {
    let todo = {};
    todo[KEYS.TODO_ID] = uuidGenerator();
    todo[KEYS.TODO_COMPLETE] = false;
    todo[KEYS.TODO_TEXT] = text;

    this.todos = this.todos.push(new Map(todo));
  }

  editTodo (payload) {
    let index = this.todos.findIndex(todo => todo.get(KEYS.TODO_ID) === payload.id);
    //- Update the todo if found
    if (index > -1) {
      this.todos = this.todos.update(0, todoItem => {
        return todoItem.set(KEYS.TODO_TEXT, payload.text);
      });
    }
  }

  setFilter () {

  }

  removeTodo () {

  }

  clearCompleted () {

  }

  toggleComplete (payload) {
    let index = this.todos.findIndex(todo => todo.get(KEYS.TODO_ID) === payload.id);
    //- Update the todo if found
    if (index > -1) {
      this.todos = this.todos.update(0, todoItem => {
        return todoItem.set(KEYS.TODO_COMPLETE, payload.complete);
      });
    }
  }

  toggleAllComplete () {

  }

}

const todoStore = alt.createStore(TodoStore, 'TodoStore');
export { todoStore as default };
<commit_msg>added todo<commit_after>import TodoActions from 'actions/TodoActions';
//- TODO: Use OrderedMap, and Record, check here:
//- https://github.com/MandarinConLaBarba/flux-immutable-todomvc/blob/master/js/stores/TodoStore.js
import {List, Map} from 'immutable';
import KEYS from 'js/constants';
import alt from 'js/alt';

//- Crappy UUID Generator, but it works for this demo
let uuid = 0;
let uuidGenerator = () => (++uuid).toString();

class TodoStore {

  constructor () {
    // Set store defaults
    this.todos = new List();
    this.filter = '';

    // Bind events for this.emit from the actions
    this.bindListeners({
      undo: TodoActions.undo,
      redo: TodoActions.redo,
      addTodo: TodoActions.addTodo,
      editTodo: TodoActions.editTodo,
      setFilter: TodoActions.setFilter,
      removeTodo: TodoActions.removeTodo,
      clearCompleted: TodoActions.clearCompleted,
      toggleComplete: TodoActions.toggleComplete,
      toggleAllComplete: TodoActions.toggleAllComplete
    });
  }

  undo () {

  }

  redo () {

  }

  addTodo (text) {
    let todo = {};
    todo[KEYS.TODO_ID] = uuidGenerator();
    todo[KEYS.TODO_COMPLETE] = false;
    todo[KEYS.TODO_TEXT] = text;

    this.todos = this.todos.push(new Map(todo));
  }

  editTodo (payload) {
    let index = this.todos.findIndex(todo => todo.get(KEYS.TODO_ID) === payload.id);
    //- Update the todo if found
    if (index > -1) {
      this.todos = this.todos.update(0, todoItem => {
        return todoItem.set(KEYS.TODO_TEXT, payload.text);
      });
    }
  }

  setFilter () {

  }

  removeTodo () {

  }

  clearCompleted () {

  }

  toggleComplete (payload) {
    let index = this.todos.findIndex(todo => todo.get(KEYS.TODO_ID) === payload.id);
    //- Update the todo if found
    if (index > -1) {
      this.todos = this.todos.update(0, todoItem => {
        return todoItem.set(KEYS.TODO_COMPLETE, payload.complete);
      });
    }
  }

  toggleAllComplete () {

  }

}

const todoStore = alt.createStore(TodoStore, 'TodoStore');
export { todoStore as default };
<|endoftext|>


<commit_before>'use strict';

module.exports = function (initClass, ExtraClass) {
  var classes = initClass,
      typeInitClass = typeof initClass,
      typeExtraClass = typeof ExtraClass;

  if (typeExtraClass !== "undefined") {
    var initClasses = (typeInitClass === "object") ? initClass : initClass.split(" "),
        extraClasses = (typeExtraClass === "object") ? ExtraClass : ExtraClass.split(" ");

    extraClasses.map(function (s) {
      initClasses[s] = true;
    });

    classes = initClasses;
  }

  return classes;
};
<commit_msg>fixed bug where component state was directly modified<commit_after>'use strict';

module.exports = function (initClass, ExtraClass) {
  var typeInitClass = typeof initClass,
      typeExtraClass = typeof ExtraClass;

  /**
   * Instead of assigning the reference of `initClass` to `classes` this for loop copies all the
   * values of `initClass` to `classes` preserving the original `initClass` object.
   */
  for (var key in initClass) {
    classes[key] = initClass[key];
  }

  if (typeExtraClass !== "undefined") {
    var initClasses = (typeInitClass === "object") ? initClass : initClass.split(" "),
        extraClasses = (typeExtraClass === "object") ? ExtraClass : ExtraClass.split(" ");

    extraClasses.map(function (s) {
      initClasses[s] = true;
    });

    classes = initClasses;
  }

  return classes;
};
<|endoftext|>


<commit_before>import React from 'react';
import {Grid, Row, Col, Panel, PanelGroup, Glyphicon, ListGroup, ButtonToolbar} from 'react-bootstrap';
import {withRouter} from 'react-router';
import AppActions from '../actions/AppActions';
import Transaction from './Transaction';

class Home extends React.Component {
  flipOrder(event) {
    event.preventDefault();
    AppActions.flipOrder();
  }

  renderTransactions(transactions) {
    var transactionsElements;
    if (transactions.length) {
      transactionsElements = [
        Transactions:
      ,
        <ListGroup className="transactions">
          {
            transactions.map((item) => {
              return (
                <Transaction key={item.Hash} transaction={item} />
              );
            })
          }
        </ListGroup>
      ]
    }
    else {
      transactionsElements = (
        No transactions
      )
    }
    return transactionsElements;
  }

  render() {
    var blocks = this.props.blocks;
    if (!this.props.sortDown) {
      blocks = blocks.slice().reverse();
    }
    return (
      <Grid>
        <Row>
          <Col sm={12}>
            <Panel header={(
Blockchain<Glyphicon glyph="sort" className='pull-right order-button' onClick={this.flipOrder.bind(this)} />
)}>
              <PanelGroup accordion>
                {
                  blocks.map((item) => {
                    var transactions = item.Links[0].Content.Links.filter((link) => {
                      return link.Name === "transaction"
                    });

                    return (
                      <Panel key={item.Hash} eventKey={item.Hash} header={(
{item.Hash} ({transactions.length} transactions) {item.Data.Time}
)}>
                        <ButtonToolbar className="pull-right">
                          Block Get
                          Block Stat
                          Payload Get
                          Payload Stat
                        </ButtonToolbar>
                        Luck: {item.Data.Luck}

                        Miner: {item.Data.MinerId}

                        {this.renderTransactions(transactions)}
                      </Panel>
                    );
                  })
                }
              </PanelGroup>
            </Panel>
          </Col>
        </Row>
      </Grid>
    );
  }
}

export default withRouter(Home);<commit_msg>Improve the count.<commit_after>import React from 'react';
import {Grid, Row, Col, Panel, PanelGroup, Glyphicon, ListGroup, ButtonToolbar} from 'react-bootstrap';
import {withRouter} from 'react-router';
import AppActions from '../actions/AppActions';
import Transaction from './Transaction';

class Home extends React.Component {
  flipOrder(event) {
    event.preventDefault();
    AppActions.flipOrder();
  }

  renderTransactions(transactions) {
    var transactionsElements;
    if (transactions.length) {
      transactionsElements = [
        Transactions:
      ,
        <ListGroup className="transactions">
          {
            transactions.map((item) => {
              return (
                <Transaction key={item.Hash} transaction={item} />
              );
            })
          }
        </ListGroup>
      ]
    }
    else {
      transactionsElements = (
        No transactions
      )
    }
    return transactionsElements;
  }

  render() {
    var blocks = this.props.blocks;
    if (!this.props.sortDown) {
      blocks = blocks.slice().reverse();
    }
    return (
      <Grid>
        <Row>
          <Col sm={12}>
            <Panel header={(
Blockchain<Glyphicon glyph="sort" className='pull-right order-button' onClick={this.flipOrder.bind(this)} />
)}>
              <PanelGroup accordion>
                {
                  blocks.map((item) => {
                    var transactions = item.Links[0].Content.Links.filter((link) => {
                      return link.Name === "transaction"
                    });

                    var transactionsCount = transactions.length === 1 ? "1 transaction" : `${transactions.length} transactions`;

                    return (
                      <Panel key={item.Hash} eventKey={item.Hash} header={(
{item.Hash} ({transactionsCount}) {item.Data.Time}
)}>
                        <ButtonToolbar className="pull-right">
                          Block Get
                          Block Stat
                          Payload Get
                          Payload Stat
                        </ButtonToolbar>
                        Luck: {item.Data.Luck}

                        Miner: {item.Data.MinerId}

                        {this.renderTransactions(transactions)}
                      </Panel>
                    );
                  })
                }
              </PanelGroup>
            </Panel>
          </Col>
        </Row>
      </Grid>
    );
  }
}

export default withRouter(Home);<|endoftext|>


<commit_before>/*
 * L.ActiveOverlay sets an independent SVG universe over the map, handling the
 * panning and scaling without any modifications within the SVG universe required
 * (i.e. ActiveOverlay adjusts the svg viewbox appropriately).
 *
 * In practice, this is akin to 'L.ImageOverlay' but the contents can move, be
 * animated and be interactive.
 *
 * Since the technique doesn't touch the internals of the SVG at all, any SVG library
 * (such as SnapSVG, D3 or svg.js) can be used.
 *
 * Pros:
 *    - any SVG library can be used (such as SnapSVG, D3 or svg.js)
 *    - anything is possible (that SVG itself supports)
 *
 * Cons:
 *    - not tiled; if you have a lot of polylines, or your data covers a wide
 *      geographic area, it may be best to use the normal Leaflet vector elements
 *      for drawing those (you can of course do a hybrid of vectors + activeOverlay).
 *
 * Developer note:
 *    - If this code were to be taken to Leaflet proper, one day, it may be useful
 *      to create a common base class for 'L.ImageOverlay' and this; common code
 *      could then live in that base class.
 */

L.ActiveOverlay = L.Layer.extend({

	/* Design note: there does not seem to be a way to apply opacity to an 'svg' HTML tag,
	 *       so it's left out of options, compared to 'L.ImageOverlay'. To get the
	 *       same effect, one can set a group ('<g>') within the SVG and control its opacity instead.
	 */
	options: {
		unit: 1.0,            // SVG units (meters)
		interactive: false    // like 'L.ImageOverlay' has interactive 'false' by default
	},

	/* Design note: either the caller or us could create the 'svgElem' (now we do it).
	 */
	initialize: function (bounds, options) { // (LatLngBounds [, Object])
		this._bounds = bounds;
		this._zoomAnimated = true;
		this._initSvg();    // sets 'this._svgElem'

		// Set elsewhere:
		//
		// this._initialized: boolean   (true)
		// this._svgSize: Point         (constant)
		// this._factor: number         (varies by the zoom level)

		L.Util.setOptions(this, options);
	},

	onAdd: function () {
		var el = this._svgElem;

		/*** REMOVE
		// tbd: do we need to update both '.className' and '.classList' this way? AKa270815
		//
		el.className = 'leaflet-active-layer ' + (this._zoomAnimated ? 'leaflet-zoom-animated' : '');

		el.classList.add('leaflet-active-layer');
		if (this._zoomAnimated) {
			el.classList.add('leaflet-zoom-animated');
		}
		***/

		if (this.options.interactive) {
			L.DomUtil.addClass(el, 'leaflet-interactive');
			this.addInteractiveTarget(el);
		}

		this.getPane().appendChild(el);
		this._reset();
	},

	onRemove: function () {
		L.DomUtil.remove(this._svgElem);
		if (this.options.interactive) {
			this.removeInteractiveTarget(this._image);
		}
	},

	bringToFront: function () {
		if (this._map) {
			L.DomUtil.toFront(this._svgElem);
		}
		return this;
	},

	bringToBack: function () {
		if (this._map) {
			L.DomUtil.toBack(this._svgElem);
		}
		return this;
	},

	getEvents: function () {
		var events = {
		  zoom: this._reset,
			viewreset: this._reset
		};

		if (this._zoomAnimated) {
			events.zoomanim = this._animateZoom;
		}

		return events;
	},

	getBounds: function () {
		return this._bounds;
	},

	getElement: function () {
		return this._svgElem;
	},

	_initSvg: function () {
		this._svgElem = L.DomUtil.create('svg',
				'leaflet-active-layer ' + (this._zoomAnimated ? 'leaflet-zoom-animated' : ''));

		var el = this._svgElem;
		el.onselectstart = L.Util.falseFn;
		el.onmousemove = L.Util.falseFn;
	},

	_animateZoom: function (e) {
		var scale = this._map.getZoomScale(e.zoom),
			offset = this._map._latLngToNewLayerPoint(this._bounds.getNorthWest(), e.zoom, e.center);

		L.DomUtil.setTransform(this._svgElem, offset, scale);
	},

	_reset: function () {      // ([Event]) ->
		var el = this._svgElem;

		if (!this._initial) {
			this._initial = true;

			// Find the width and height of the bounding box, in meters.
			//
			var nw = this._bounds.getNorthWest();

			var mWidth = nw.distanceTo(this._bounds.getNorthEast());    // width (m)
			var mHeight = nw.distanceTo(this._bounds.getSouthWest());   // height (m)

			var svgSize = L.point(mWidth, mHeight)._divideBy(this.options.unit);

			// The actual dimensions (in meters) get anchored in the SVG 'viewBox' properties
			// (and don't change by zooming or panning). These are the SVG coordinate dimensions
			// of the bounding box.
			//
			el.setAttribute('viewBox', [0, 0, svgSize.x, svgSize.y].join(' '));

			this._svgSize = svgSize;
		}

		// Pixels from the top left of the map, if the map hasn't been panned
		//
		var pBounds = L.bounds(
			this._map.latLngToLayerPoint(this._bounds.getNorthWest()),
			this._map.latLngToLayerPoint(this._bounds.getSouthEast())
	  );

		var size = pBounds.getSize();    // size in screen pixels

		// Note: We're currently only considering the 'x' factor in latLngToSvgPoint
		//      calculations. To be more precise, we could consider both (they are
		//      close to each other but not completely the same).
		//
		//console.log('X factor: ' + (size.x / this._svgSize.x));
		//console.log('Y factor: ' + (size.y / this._svgSize.y));

		this._factor = size.x / this._svgSize.x;      // pixels / m

		L.DomUtil.setPosition(el, pBounds.min);

		el.style.width  = size.x + 'px';
		el.style.height = size.y + 'px';
	},

	/*
	* Conversion of LatLng coordinates to/from SVG coordinates.
	*
	* Note: For a normal image, this would mean conversion from/to pixel coordinates
	*      (which feature is not in the 'ImageOverlay' API but could be).
	*/
	latLngToSvgPoint: function(latLng) {  // (LatLng) -> Point
		var offset = L.DomUtil.getPosition(this._svgElem);    // offset in screen pixels, without panning

		var p = this._map.latLngToLayerPoint(latLng)._subtract(offset)._divideBy(this._factor);
		return p;
	},

	// Note: This has not been tested!!
	//
	svgPointToLatLng: function(p) {   // (Point) -> LatLng
		var offset = L.DomUtil.getPosition(this._svgElem);

		var latlng = this._map.layerPointToLatLng(p.multiplyBy(this._factor)._add(offset));
		return latlng;
	},

	/*
	* Size of a screen pixel in SVG dimensions.
	*
	* Note: Returning a 'Point' though it's a dimension, not a coordinate.
	*
	* Note: The API is ready for storing separate x and y factors, though currently we don't.
	*/
	pixelToSvg: function() {    // () -> Point
		var tmp = 1.0 / this._factor;
		return L.point(tmp, tmp);
	}
});

L.activeOverlay = function (bounds, options) {   // (LatLngBounds [, Object])
	return new L.ActiveOverlay(bounds, options);
};
<commit_msg>Zooming works<commit_after>/*
 * L.ActiveOverlay sets an independent SVG universe over the map, handling the
 * panning and scaling without any modifications within the SVG universe required
 * (i.e. ActiveOverlay adjusts the svg viewbox appropriately).
 *
 * In practice, this is akin to 'L.ImageOverlay' but the contents can move, be
 * animated and be interactive.
 *
 * Since the technique doesn't touch the internals of the SVG at all, any SVG library
 * (such as SnapSVG, D3 or svg.js) can be used.
 *
 * Pros:
 *    - any SVG library can be used (such as SnapSVG, D3 or svg.js)
 *    - anything is possible (that SVG itself supports)
 *
 * Cons:
 *    - not tiled; if you have a lot of polylines, or your data covers a wide
 *      geographic area, it may be best to use the normal Leaflet vector elements
 *      for drawing those (you can of course do a hybrid of vectors + activeOverlay).
 *
 * Developer note:
 *    - If this code were to be taken to Leaflet proper, one day, it may be useful
 *      to create a common base class for 'L.ImageOverlay' and this; common code
 *      could then live in that base class.
 */

L.ActiveOverlay = L.Layer.extend({

	/* Design note: there does not seem to be a way to apply opacity to an 'svg' HTML tag,
	 *       so it's left out of options, compared to 'L.ImageOverlay'. To get the
	 *       same effect, one can set a group ('<g>') within the SVG and control its opacity instead.
	 */
	options: {
		unit: 1.0,            // SVG units (meters)
		interactive: false    // like 'L.ImageOverlay' has interactive 'false' by default
	},

	/* Design note: either the caller or us could create the 'svgElem' (now we do it).
	 */
	initialize: function (bounds, options) { // (LatLngBounds [, Object])
		this._bounds = bounds;
		this._zoomAnimated = true;
		this._initSvg();    // sets 'this._svgElem'

		// Set elsewhere:
		//
		// this._initialized: boolean   (true)
		// this._svgSize: Point         (constant)
		// this._factor: number         (varies by the zoom level)

		L.Util.setOptions(this, options);
	},

	onAdd: function () {
		var el = this._svgElem;

		// Note: The below '.classList' setting is vital for zooming to be performed smoothly.
		//      '.className' does not seem to matter.
		//
		/*** REMOVE
		//el.className = 'leaflet-active-layer ' + (this._zoomAnimated ? 'leaflet-zoom-animated' : '');

		el.classList.add('leaflet-active-layer');
		if (this._zoomAnimated) {
			el.classList.add('leaflet-zoom-animated');
		}
		***/

		L.DomUtil.addClass(el, 'leaflet-active-layer');
		if (this._zoomAnimated) {
			L.DomUtil.addClass(el, 'leaflet-zoom-animated');
		}

		// Note: The contents behave interactive (i.e. get mouse events) even when 'interactive' option
		//    is false. We probably need something else to ban mouse events from flying into the SVG,
		//    or simply take away the "interactive" option completely. AKa270815
		//
		if (this.options.interactive) {
			L.DomUtil.addClass(el, 'leaflet-interactive');
			this.addInteractiveTarget(el);
		}

		this.getPane().appendChild(el);
		this._reset();
	},

	onRemove: function () {
		L.DomUtil.remove(this._svgElem);
		if (this.options.interactive) {
			this.removeInteractiveTarget(this._image);
		}
	},

	bringToFront: function () {
		if (this._map) {
			L.DomUtil.toFront(this._svgElem);
		}
		return this;
	},

	bringToBack: function () {
		if (this._map) {
			L.DomUtil.toBack(this._svgElem);
		}
		return this;
	},

	getEvents: function () {
		var events = {
		  zoom: this._reset,
			viewreset: this._reset
		};

		if (this._zoomAnimated) {
			events.zoomanim = this._animateZoom;
		}

		return events;
	},

	getBounds: function () {
		return this._bounds;
	},

	getElement: function () {
		return this._svgElem;
	},

	_initSvg: function () {
		this._svgElem = L.DomUtil.create('svg',
				'leaflet-active-layer ' + (this._zoomAnimated ? 'leaflet-zoom-animated' : ''));

		var el = this._svgElem;
		el.onselectstart = L.Util.falseFn;
		el.onmousemove = L.Util.falseFn;
	},

	_animateZoom: function (e) {
		var scale = this._map.getZoomScale(e.zoom),
			offset = this._map._latLngToNewLayerPoint(this._bounds.getNorthWest(), e.zoom, e.center);

		L.DomUtil.setTransform(this._svgElem, offset, scale);
	},

	_reset: function () {      // ([Event]) ->
		var el = this._svgElem;

		if (!this._initial) {
			this._initial = true;

			// Find the width and height of the bounding box, in meters.
			//
			var nw = this._bounds.getNorthWest();

			var mWidth = nw.distanceTo(this._bounds.getNorthEast());    // width (m)
			var mHeight = nw.distanceTo(this._bounds.getSouthWest());   // height (m)

			var svgSize = L.point(mWidth, mHeight)._divideBy(this.options.unit);

			// The actual dimensions (in meters) get anchored in the SVG 'viewBox' properties
			// (and don't change by zooming or panning). These are the SVG coordinate dimensions
			// of the bounding box.
			//
			el.setAttribute('viewBox', [0, 0, svgSize.x, svgSize.y].join(' '));

			this._svgSize = svgSize;
		}

		// Pixels from the top left of the map, if the map hasn't been panned
		//
		var pBounds = L.bounds(
			this._map.latLngToLayerPoint(this._bounds.getNorthWest()),
			this._map.latLngToLayerPoint(this._bounds.getSouthEast())
	  );

		var size = pBounds.getSize();    // size in screen pixels

		// Note: We're currently only considering the 'x' factor in latLngToSvgPoint
		//      calculations. To be more precise, we could consider both (they are
		//      close to each other but not completely the same).
		//
		//console.log('X factor: ' + (size.x / this._svgSize.x));
		//console.log('Y factor: ' + (size.y / this._svgSize.y));

		this._factor = size.x / this._svgSize.x;      // pixels / m

		L.DomUtil.setPosition(el, pBounds.min);

		el.style.width  = size.x + 'px';
		el.style.height = size.y + 'px';
	},

	/*
	* Conversion of LatLng coordinates to/from SVG coordinates.
	*
	* Note: For a normal image, this would mean conversion from/to pixel coordinates
	*      (which feature is not in the 'ImageOverlay' API but could be).
	*/
	latLngToSvgPoint: function(latLng) {  // (LatLng) -> Point
		var offset = L.DomUtil.getPosition(this._svgElem);    // offset in screen pixels, without panning

		var p = this._map.latLngToLayerPoint(latLng)._subtract(offset)._divideBy(this._factor);
		return p;
	},

	// Note: This has not been tested!!
	//
	svgPointToLatLng: function(p) {   // (Point) -> LatLng
		var offset = L.DomUtil.getPosition(this._svgElem);

		var latlng = this._map.layerPointToLatLng(p.multiplyBy(this._factor)._add(offset));
		return latlng;
	},

	/*
	* Size of a screen pixel in SVG dimensions.
	*
	* Note: Returning a 'Point' though it's a dimension, not a coordinate.
	*
	* Note: The API is ready for storing separate x and y factors, though currently we don't.
	*/
	pixelToSvg: function() {    // () -> Point
		var tmp = 1.0 / this._factor;
		return L.point(tmp, tmp);
	}
});

L.activeOverlay = function (bounds, options) {   // (LatLngBounds [, Object])
	return new L.ActiveOverlay(bounds, options);
};
<|endoftext|>


<commit_before>import {Layer} from '../Layer';
import {IconDefault} from './Icon.Default';
import * as Util from '../../core/Util';
import {toLatLng as latLng} from '../../geo/LatLng';
import * as DomUtil from '../../dom/DomUtil';
import {MarkerDrag} from './Marker.Drag';

/*
 * @class Marker
 * @inherits Interactive layer
 * @aka L.Marker
 * L.Marker is used to display clickable/draggable icons on the map. Extends `Layer`.
 *
 * @example
 *
 * ```js
 * L.marker([50.5, 30.5]).addTo(map);
 * ```
 */

export var Marker = Layer.extend({

	// @section
	// @aka Marker options
	options: {
		// @option icon: Icon = *
		// Icon class to use for rendering the marker. See [Icon documentation](#L.Icon) for details on how to customize the marker icon. If not specified, a new `L.Icon.Default` is used.
		icon: new IconDefault(),

		// Option inherited from "Interactive layer" abstract class
		interactive: true,

		// @option draggable: Boolean = false
		// Whether the marker is draggable with mouse/touch or not.
		draggable: false,

		// @option keyboard: Boolean = true
		// Whether the marker can be tabbed to with a keyboard and clicked by pressing enter.
		keyboard: true,

		// @option title: String = ''
		// Text for the browser tooltip that appear on marker hover (no tooltip by default).
		title: '',

		// @option alt: String = ''
		// Text for the `alt` attribute of the icon image (useful for accessibility).
		alt: '',

		// @option zIndexOffset: Number = 0
		// By default, marker images zIndex is set automatically based on its latitude. Use this option if you want to put the marker on top of all others (or below), specifying a high value like `1000` (or high negative value, respectively).
		zIndexOffset: 0,

		// @option opacity: Number = 1.0
		// The opacity of the marker.
		opacity: 1,

		// @option riseOnHover: Boolean = false
		// If `true`, the marker will get on top of others when you hover the mouse over it.
		riseOnHover: false,

		// @option riseOffset: Number = 250
		// The z-index offset used for the `riseOnHover` feature.
		riseOffset: 250,

		// @option pane: String = 'markerPane'
		// `Map pane` where the markers icon will be added.
		pane: 'markerPane',

		// @option bubblingMouseEvents: Boolean = false
		// When `true`, a mouse event on this marker will trigger the same event on the map
		// (unless [`L.DomEvent.stopPropagation`](#domevent-stoppropagation) is used).
		bubblingMouseEvents: false
	},

	/* @section
	 *
	 * In addition to [shared layer methods](#Layer) like `addTo()` and `remove()` and [popup methods](#Popup) like bindPopup() you can also use the following methods:
	 */

	initialize: function (latlng, options) {
		Util.setOptions(this, options);
		this._latlng = latLng(latlng);
	},

	onAdd: function (map) {
		this._zoomAnimated = this._zoomAnimated && map.options.markerZoomAnimation;

		if (this._zoomAnimated) {
			map.on('zoomanim', this._animateZoom, this);
		}

		this._initIcon();
		this.update();
	},

	onRemove: function (map) {
		if (this.dragging && this.dragging.enabled()) {
			this.options.draggable = true;
			this.dragging.removeHooks();
		}
		delete this.dragging;

		if (this._zoomAnimated) {
			map.off('zoomanim', this._animateZoom, this);
		}

		this._removeIcon();
		this._removeShadow();
	},

	getEvents: function () {
		return {
			zoom: this.update,
			viewreset: this.update
		};
	},

	// @method getLatLng: LatLng
	// Returns the current geographical position of the marker.
	getLatLng: function () {
		return this._latlng;
	},

	// @method setLatLng(latlng: LatLng): this
	// Changes the marker position to the given point.
	setLatLng: function (latlng) {
		var oldLatLng = this._latlng;
		this._latlng = latLng(latlng);
		this.update();

		// @event move: Event
		// Fired when the marker is moved via [`setLatLng`](#marker-setlatlng) or by [dragging](#marker-dragging). Old and new coordinates are included in event arguments as `oldLatLng`, `latlng`.
		return this.fire('move', {oldLatLng: oldLatLng, latlng: this._latlng});
	},

	// @method setZIndexOffset(offset: Number): this
	// Changes the [zIndex offset](#marker-zindexoffset) of the marker.
	setZIndexOffset: function (offset) {
		this.options.zIndexOffset = offset;
		return this.update();
	},

	// @method setIcon(icon: Icon): this
	// Changes the marker icon.
	setIcon: function (icon) {

		this.options.icon = icon;

		if (this._map) {
			this._initIcon();
			this.update();
		}

		if (this._popup) {
			this.bindPopup(this._popup, this._popup.options);
		}

		return this;
	},

	getElement: function () {
		return this._icon;
	},

	update: function () {

		if (this._icon) {
			var pos = this._map.latLngToLayerPoint(this._latlng).round();
			this._setPos(pos);
		}

		return this;
	},

	_initIcon: function () {
		var options = this.options,
		    classToAdd = 'leaflet-zoom-' + (this._zoomAnimated ? 'animated' : 'hide');

		var icon = options.icon.createIcon(this._icon),
		    addIcon = false;

		// if we're not reusing the icon, remove the old one and init new one
		if (icon !== this._icon) {
			if (this._icon) {
				this._removeIcon();
			}
			addIcon = true;

			if (options.title) {
				icon.title = options.title;
			}
			if (options.alt) {
				icon.alt = options.alt;
			}
		}

		DomUtil.addClass(icon, classToAdd);

		if (options.keyboard) {
			icon.tabIndex = '0';
		}

		this._icon = icon;

		if (options.riseOnHover) {
			this.on({
				mouseover: this._bringToFront,
				mouseout: this._resetZIndex
			});
		}

		var newShadow = options.icon.createShadow(this._shadow),
		    addShadow = false;

		if (newShadow !== this._shadow) {
			this._removeShadow();
			addShadow = true;
		}

		if (newShadow) {
			DomUtil.addClass(newShadow, classToAdd);
			newShadow.alt = '';
		}
		this._shadow = newShadow;

		if (options.opacity < 1) {
			this._updateOpacity();
		}

		if (addIcon) {
			this.getPane().appendChild(this._icon);
		}
		this._initInteraction();
		if (newShadow && addShadow) {
			this.getPane('shadowPane').appendChild(this._shadow);
		}
	},

	_removeIcon: function () {
		if (this.options.riseOnHover) {
			this.off({
				mouseover: this._bringToFront,
				mouseout: this._resetZIndex
			});
		}

		DomUtil.remove(this._icon);
		this.removeInteractiveTarget(this._icon);

		this._icon = null;
	},

	_removeShadow: function () {
		if (this._shadow) {
			DomUtil.remove(this._shadow);
		}
		this._shadow = null;
	},

	_setPos: function (pos) {
		DomUtil.setPosition(this._icon, pos);

		if (this._shadow) {
			DomUtil.setPosition(this._shadow, pos);
		}

		this._zIndex = pos.y + this.options.zIndexOffset;

		this._resetZIndex();
	},

	_updateZIndex: function (offset) {
		this._icon.style.zIndex = this._zIndex + offset;
	},

	_animateZoom: function (opt) {
		var pos = this._map._latLngToNewLayerPoint(this._latlng, opt.zoom, opt.center).round();

		this._setPos(pos);
	},

	_initInteraction: function () {

		if (!this.options.interactive) { return; }

		DomUtil.addClass(this._icon, 'leaflet-interactive');

		this.addInteractiveTarget(this._icon);

		if (MarkerDrag) {
			var draggable = this.options.draggable;
			if (this.dragging) {
				draggable = this.dragging.enabled();
				this.dragging.disable();
			}

			this.dragging = new MarkerDrag(this);

			if (draggable) {
				this.dragging.enable();
			}
		}
	},

	// @method setOpacity(opacity: Number): this
	// Changes the opacity of the marker.
	setOpacity: function (opacity) {
		this.options.opacity = opacity;
		if (this._map) {
			this._updateOpacity();
		}

		return this;
	},

	_updateOpacity: function () {
		var opacity = this.options.opacity;

		DomUtil.setOpacity(this._icon, opacity);

		if (this._shadow) {
			DomUtil.setOpacity(this._shadow, opacity);
		}
	},

	_bringToFront: function () {
		this._updateZIndex(this.options.riseOffset);
	},

	_resetZIndex: function () {
		this._updateZIndex(0);
	},

	_getPopupAnchor: function () {
		return this.options.icon.options.popupAnchor || [0, 0];
	},

	_getTooltipAnchor: function () {
		return this.options.icon.options.tooltipAnchor || [0, 0];
	}
});

// factory L.marker(latlng: LatLng, options? : Marker options)

// @factory L.marker(latlng: LatLng, options? : Marker options)
// Instantiates a Marker object given a geographical point and optionally an options object.
export function marker(latlng, options) {
	return new Marker(latlng, options);
}
<commit_msg>Docs(Marker): modify icon option description (#5529)<commit_after>import {Layer} from '../Layer';
import {IconDefault} from './Icon.Default';
import * as Util from '../../core/Util';
import {toLatLng as latLng} from '../../geo/LatLng';
import * as DomUtil from '../../dom/DomUtil';
import {MarkerDrag} from './Marker.Drag';

/*
 * @class Marker
 * @inherits Interactive layer
 * @aka L.Marker
 * L.Marker is used to display clickable/draggable icons on the map. Extends `Layer`.
 *
 * @example
 *
 * ```js
 * L.marker([50.5, 30.5]).addTo(map);
 * ```
 */

export var Marker = Layer.extend({

	// @section
	// @aka Marker options
	options: {
		// @option icon: Icon = *
		// Icon instance to use for rendering the marker.
		// See [Icon documentation](#L.Icon) for details on how to customize the marker icon.
		// If not specified, a common instance of `L.Icon.Default` is used.
		icon: new IconDefault(),

		// Option inherited from "Interactive layer" abstract class
		interactive: true,

		// @option draggable: Boolean = false
		// Whether the marker is draggable with mouse/touch or not.
		draggable: false,

		// @option keyboard: Boolean = true
		// Whether the marker can be tabbed to with a keyboard and clicked by pressing enter.
		keyboard: true,

		// @option title: String = ''
		// Text for the browser tooltip that appear on marker hover (no tooltip by default).
		title: '',

		// @option alt: String = ''
		// Text for the `alt` attribute of the icon image (useful for accessibility).
		alt: '',

		// @option zIndexOffset: Number = 0
		// By default, marker images zIndex is set automatically based on its latitude. Use this option if you want to put the marker on top of all others (or below), specifying a high value like `1000` (or high negative value, respectively).
		zIndexOffset: 0,

		// @option opacity: Number = 1.0
		// The opacity of the marker.
		opacity: 1,

		// @option riseOnHover: Boolean = false
		// If `true`, the marker will get on top of others when you hover the mouse over it.
		riseOnHover: false,

		// @option riseOffset: Number = 250
		// The z-index offset used for the `riseOnHover` feature.
		riseOffset: 250,

		// @option pane: String = 'markerPane'
		// `Map pane` where the markers icon will be added.
		pane: 'markerPane',

		// @option bubblingMouseEvents: Boolean = false
		// When `true`, a mouse event on this marker will trigger the same event on the map
		// (unless [`L.DomEvent.stopPropagation`](#domevent-stoppropagation) is used).
		bubblingMouseEvents: false
	},

	/* @section
	 *
	 * In addition to [shared layer methods](#Layer) like `addTo()` and `remove()` and [popup methods](#Popup) like bindPopup() you can also use the following methods:
	 */

	initialize: function (latlng, options) {
		Util.setOptions(this, options);
		this._latlng = latLng(latlng);
	},

	onAdd: function (map) {
		this._zoomAnimated = this._zoomAnimated && map.options.markerZoomAnimation;

		if (this._zoomAnimated) {
			map.on('zoomanim', this._animateZoom, this);
		}

		this._initIcon();
		this.update();
	},

	onRemove: function (map) {
		if (this.dragging && this.dragging.enabled()) {
			this.options.draggable = true;
			this.dragging.removeHooks();
		}
		delete this.dragging;

		if (this._zoomAnimated) {
			map.off('zoomanim', this._animateZoom, this);
		}

		this._removeIcon();
		this._removeShadow();
	},

	getEvents: function () {
		return {
			zoom: this.update,
			viewreset: this.update
		};
	},

	// @method getLatLng: LatLng
	// Returns the current geographical position of the marker.
	getLatLng: function () {
		return this._latlng;
	},

	// @method setLatLng(latlng: LatLng): this
	// Changes the marker position to the given point.
	setLatLng: function (latlng) {
		var oldLatLng = this._latlng;
		this._latlng = latLng(latlng);
		this.update();

		// @event move: Event
		// Fired when the marker is moved via [`setLatLng`](#marker-setlatlng) or by [dragging](#marker-dragging). Old and new coordinates are included in event arguments as `oldLatLng`, `latlng`.
		return this.fire('move', {oldLatLng: oldLatLng, latlng: this._latlng});
	},

	// @method setZIndexOffset(offset: Number): this
	// Changes the [zIndex offset](#marker-zindexoffset) of the marker.
	setZIndexOffset: function (offset) {
		this.options.zIndexOffset = offset;
		return this.update();
	},

	// @method setIcon(icon: Icon): this
	// Changes the marker icon.
	setIcon: function (icon) {

		this.options.icon = icon;

		if (this._map) {
			this._initIcon();
			this.update();
		}

		if (this._popup) {
			this.bindPopup(this._popup, this._popup.options);
		}

		return this;
	},

	getElement: function () {
		return this._icon;
	},

	update: function () {

		if (this._icon) {
			var pos = this._map.latLngToLayerPoint(this._latlng).round();
			this._setPos(pos);
		}

		return this;
	},

	_initIcon: function () {
		var options = this.options,
		    classToAdd = 'leaflet-zoom-' + (this._zoomAnimated ? 'animated' : 'hide');

		var icon = options.icon.createIcon(this._icon),
		    addIcon = false;

		// if we're not reusing the icon, remove the old one and init new one
		if (icon !== this._icon) {
			if (this._icon) {
				this._removeIcon();
			}
			addIcon = true;

			if (options.title) {
				icon.title = options.title;
			}
			if (options.alt) {
				icon.alt = options.alt;
			}
		}

		DomUtil.addClass(icon, classToAdd);

		if (options.keyboard) {
			icon.tabIndex = '0';
		}

		this._icon = icon;

		if (options.riseOnHover) {
			this.on({
				mouseover: this._bringToFront,
				mouseout: this._resetZIndex
			});
		}

		var newShadow = options.icon.createShadow(this._shadow),
		    addShadow = false;

		if (newShadow !== this._shadow) {
			this._removeShadow();
			addShadow = true;
		}

		if (newShadow) {
			DomUtil.addClass(newShadow, classToAdd);
			newShadow.alt = '';
		}
		this._shadow = newShadow;

		if (options.opacity < 1) {
			this._updateOpacity();
		}

		if (addIcon) {
			this.getPane().appendChild(this._icon);
		}
		this._initInteraction();
		if (newShadow && addShadow) {
			this.getPane('shadowPane').appendChild(this._shadow);
		}
	},

	_removeIcon: function () {
		if (this.options.riseOnHover) {
			this.off({
				mouseover: this._bringToFront,
				mouseout: this._resetZIndex
			});
		}

		DomUtil.remove(this._icon);
		this.removeInteractiveTarget(this._icon);

		this._icon = null;
	},

	_removeShadow: function () {
		if (this._shadow) {
			DomUtil.remove(this._shadow);
		}
		this._shadow = null;
	},

	_setPos: function (pos) {
		DomUtil.setPosition(this._icon, pos);

		if (this._shadow) {
			DomUtil.setPosition(this._shadow, pos);
		}

		this._zIndex = pos.y + this.options.zIndexOffset;

		this._resetZIndex();
	},

	_updateZIndex: function (offset) {
		this._icon.style.zIndex = this._zIndex + offset;
	},

	_animateZoom: function (opt) {
		var pos = this._map._latLngToNewLayerPoint(this._latlng, opt.zoom, opt.center).round();

		this._setPos(pos);
	},

	_initInteraction: function () {

		if (!this.options.interactive) { return; }

		DomUtil.addClass(this._icon, 'leaflet-interactive');

		this.addInteractiveTarget(this._icon);

		if (MarkerDrag) {
			var draggable = this.options.draggable;
			if (this.dragging) {
				draggable = this.dragging.enabled();
				this.dragging.disable();
			}

			this.dragging = new MarkerDrag(this);

			if (draggable) {
				this.dragging.enable();
			}
		}
	},

	// @method setOpacity(opacity: Number): this
	// Changes the opacity of the marker.
	setOpacity: function (opacity) {
		this.options.opacity = opacity;
		if (this._map) {
			this._updateOpacity();
		}

		return this;
	},

	_updateOpacity: function () {
		var opacity = this.options.opacity;

		DomUtil.setOpacity(this._icon, opacity);

		if (this._shadow) {
			DomUtil.setOpacity(this._shadow, opacity);
		}
	},

	_bringToFront: function () {
		this._updateZIndex(this.options.riseOffset);
	},

	_resetZIndex: function () {
		this._updateZIndex(0);
	},

	_getPopupAnchor: function () {
		return this.options.icon.options.popupAnchor || [0, 0];
	},

	_getTooltipAnchor: function () {
		return this.options.icon.options.tooltipAnchor || [0, 0];
	}
});

// factory L.marker(latlng: LatLng, options? : Marker options)

// @factory L.marker(latlng: LatLng, options? : Marker options)
// Instantiates a Marker object given a geographical point and optionally an options object.
export function marker(latlng, options) {
	return new Marker(latlng, options);
}
<|endoftext|>


<commit_before>/* eslint-disable no-console */
import path from 'path';
import minimist from 'minimist';
import Source from '../source.js';
import { fetchFileList } from '../utils.js';

const showUsage = () => {
  console.log(
`word-quiz-generator make --help
word-quiz-generator make --src=<path> --lang=<lang>
word-quiz-generator make --src=<path> [--preprocessor=<path>] [--lemmatizer=<path>]

Generate preprocessed and lemmatized texts from the given sources.

-h, --help
    Show this usage.
-s, --src=<paths>
    Comma-separated path strings to be processed.
-l, --lang=<lang>
    IETF langage tag in which source texts are written.
    This determines which built-in preprocesser and lemmatizer should be used.
    If you want to use your custom ones, please use '--preprocessor' and '--lemmatizer' options.
--preprocessor=<path>
  Path to a custom preprocessor.
--lemmatizer=<path>
  Path to a custom lemmatizer.`);
};

const getPreprocessor = (argv) => {
  try {
    if (argv.preprocessor) {
      const preprocessor = require(argv.preprocessor);
      return preprocessor.default || preprocessor;
    } else if (argv.lang) {
      return require(`../preprocessor/${argv.lang}.js`).default;
    }
  } catch (err) {
    console.error('Unable to load the preprocessor: %c', err.message);
  }

  return null;
};

const getLemmatizer = (argv) => {
  try {
    if (argv.lemmatizer) {
      const lemmatizer = require(argv.lemmatizer);
      return lemmatizer.default || lemmatizer;
    } else if (argv.lang) {
      return require(`../lemmatizer/${argv.lang}.js`).default;
    }
  } catch (err) {
    console.error('Unable to load the lemmatizer: %c', err.message);
  }

  return null;
};

export default async function (args) {
  const argv = minimist(args, {
    string: [
      'src',
      'lang',
      'preprocessor',
      'lemmatizer',
    ],
    boolean: [
      'help',
    ],
    alias: {
      s: 'src',
      l: 'lang',
      h: 'help',
    },
    default: {
      lang: 'en',
      help: false,
    },
  });

  if (argv.help) {
    showUsage();
    process.exit(0);
  }

  if (!argv.src) {
    console.error('ERR: No src is specified.');
    showUsage();
    process.exit(1);
  }

  console.log(`Src: ${path.resolve(argv.src)}`);

  const preprocessor = getPreprocessor(argv);
  const lemmatizer = getLemmatizer(argv);
  const files = await fetchFileList(argv.src, /\.txt$/);

  for (const _path of files) {
    console.log(_path);

    try {
      const source = new Source(_path);

      if (preprocessor) {
        console.log('Preprocessing...');
        await source.preprocess(preprocessor);
      }

      if (lemmatizer) {
        console.log('Lemmatizing...');
        await source.lemmatize(lemmatizer);
      }
    } catch (ex) {
      console.error(ex.stack);
    }
  }
}
<commit_msg>Remove previously preprocessed/lemmatized files<commit_after>/* eslint-disable no-console */
import path from 'path';
import minimist from 'minimist';
import fs from 'fs-extra-promise';
import Source from '../source.js';
import { fetchFileList } from '../utils.js';

const showUsage = () => {
  console.log(
`word-quiz-generator make --help
word-quiz-generator make --src=<path> --lang=<lang>
word-quiz-generator make --src=<path> [--preprocessor=<path>] [--lemmatizer=<path>]

Generate preprocessed and lemmatized texts from the given sources.

-h, --help
    Show this usage.
-s, --src=<paths>
    Comma-separated path strings to be processed.
-l, --lang=<lang>
    IETF langage tag in which source texts are written.
    This determines which built-in preprocesser and lemmatizer should be used.
    If you want to use your custom ones, please use '--preprocessor' and '--lemmatizer' options.
--preprocessor=<path>
  Path to a custom preprocessor.
--lemmatizer=<path>
  Path to a custom lemmatizer.`);
};

function getPreprocessor(argv) {
  try {
    if (argv.preprocessor) {
      const preprocessor = require(argv.preprocessor);
      return preprocessor.default || preprocessor;
    } else if (argv.lang) {
      return require(`../preprocessor/${argv.lang}.js`).default;
    }
  } catch (err) {
    console.error('Unable to load the preprocessor: %c', err.message);
  }

  return null;
}

function getLemmatizer(argv) {
  try {
    if (argv.lemmatizer) {
      const lemmatizer = require(argv.lemmatizer);
      return lemmatizer.default || lemmatizer;
    } else if (argv.lang) {
      return require(`../lemmatizer/${argv.lang}.js`).default;
    }
  } catch (err) {
    console.error('Unable to load the lemmatizer: %c', err.message);
  }

  return null;
}

async function clean(dir) {
  const files = await fetchFileList(dir, /\.(?:preprocessed|lemmatized)$/);

  for (const _path of files) {
    await fs.removeAsync(_path);
  }
}

export default async function (args) {
  const argv = minimist(args, {
    string: [
      'src',
      'lang',
      'preprocessor',
      'lemmatizer',
    ],
    boolean: [
      'help',
    ],
    alias: {
      s: 'src',
      l: 'lang',
      h: 'help',
    },
    default: {
      lang: 'en',
      help: false,
    },
  });

  if (argv.help) {
    showUsage();
    process.exit(0);
  }

  if (!argv.src) {
    console.error('ERR: No src is specified.');
    showUsage();
    process.exit(1);
  }

  console.log(`Src: ${path.resolve(argv.src)}`);

  await clean(argv.src);

  const preprocessor = getPreprocessor(argv);
  const lemmatizer = getLemmatizer(argv);
  const files = await fetchFileList(argv.src, /\.txt$/);

  for (const _path of files) {
    console.log(_path);

    try {
      const source = new Source(_path);

      if (preprocessor) {
        console.log('Preprocessing...');
        await source.preprocess(preprocessor);
      }

      if (lemmatizer) {
        console.log('Lemmatizing...');
        await source.lemmatize(lemmatizer);
      }
    } catch (ex) {
      console.error(ex.stack);
    }
  }
}
<|endoftext|>


<commit_before>import Logger from './logging/Logger';
import FocusOnlyKeyEventStrategy from './strategies/FocusOnlyKeyEventStrategy';
import GlobalKeyEventStrategy from './strategies/GlobalKeyEventStrategy';
import Configuration from './config/Configuration';
import EventResponse from '../const/EventResponse';
import ApplicationKeyMapBuilder from './definitions/ApplicationKeyMapBuilder';
import lazyLoadAttribute from '../utils/object/lazyLoadAttribute';

/**
 * Provides a registry for keyboard sequences and events, and the handlers that should
 * be called when they are detected. Also contains the interface for processing and
 * matching keyboard events against its list of registered actions and handlers.
 * @class
 */
class KeyEventManager {
  /**
   * Creates a new KeyEventManager instance if one does not already exist or returns the
   * instance that already exists.
   * @param {Object} configuration Configuration object
   * @param {Logger} configuration.logger Logger instance
   * @returns {KeyEventManager} The key event manager instance
   */
  static getInstance(configuration = {}) {
    return lazyLoadAttribute(this, 'instance', () => new KeyEventManager(configuration));
  }

  static getFocusOnlyEventStrategy() {
    return this.getInstance().focusOnlyEventStrategy;
  }

  static getGlobalEventStrategy() {
    return this.getInstance().globalEventStrategy
  }

  /**
   * Creates a new KeyEventManager instance. It is expected that only a single instance
   * will be used with a render tree.
   */
  constructor(configuration = {}) {
    const logLevel = Configuration.option('logLevel');

    this.logger = configuration.logger || new Logger(logLevel);

    this.focusOnlyEventStrategy =
      new FocusOnlyKeyEventStrategy({ configuration, logLevel }, this);

    this.globalEventStrategy =
      new GlobalKeyEventStrategy({ configuration, logLevel }, this);

    this.mountedComponentsCount = 0;
  }

  /********************************************************************************
   * Generating key maps
   ********************************************************************************/

  /**
   * Returns a mapping of all of the application's actions and the key sequences
   * needed to trigger them.
   *
   * @type {ApplicationKeyMap} The application's key map
   */
  get applicationKeyMap() {
    return [this.globalEventStrategy, this.focusOnlyEventStrategy].reduce((memo, strategy) => {
      const builder = new ApplicationKeyMapBuilder(strategy.componentTree);
      const keyMap = builder.build();

      return { ...memo, ...keyMap };
    }, {});
  }

  /********************************************************************************
   * Registering key maps
   ********************************************************************************/

  /**
   * Registers that a component has now mounted, and declares its parent HotKeys
   * component id so that actions may be properly resolved
   * @param {ComponentId} componentId - Id of the component that has mounted
   * @param {ComponentId} parentId - Id of the parent HotKeys component
   */
  registerComponentMount(componentId, parentId) {
    this._incrementComponentCount();

    return this.focusOnlyEventStrategy.registerComponentMount(componentId, parentId);
  }

  registerComponentUnmount() {
    this._decrementComponentCount();
  }

  _incrementComponentCount(){
    const preMountedComponentCount = this.mountedComponentsCount;
    this.mountedComponentsCount += 1;

    if (preMountedComponentCount === 0 && this.mountedComponentsCount === 1) {
      window.onblur = () => this._clearKeyHistory();
    }
  }

  _decrementComponentCount(){
    const preMountedComponentCount = this.mountedComponentsCount;
    this.mountedComponentsCount -= 1;

    if (preMountedComponentCount === 1 && this.mountedComponentsCount === 0) {
      delete window.onblur;
    }
  }

  _clearKeyHistory() {
    this.logger.info('HotKeys: Window focused - clearing key history');

    this.focusOnlyEventStrategy.resetKeyHistory({ force: true });
    this.globalEventStrategy.resetKeyHistory({ force: true });
  }

  registerGlobalComponentUnmount() {
    this._decrementComponentCount();
  }

  /**
   * Registers that a component has now mounted, and declares its parent GlobalHotKeys
   * component id so that actions may be properly resolved
   * @param {ComponentId} componentId - Id of the component that has mounted
   * @param {ComponentId} parentId - Id of the parent GlobalHotKeys component
   */
  registerGlobalComponentMount(componentId, parentId) {
    this._incrementComponentCount();

    return this.globalEventStrategy.registerComponentMount(componentId, parentId);
  }

  /********************************************************************************
   * Recording key combination
   ********************************************************************************/

  /**
   * Adds a listener function that will be called the next time a key combination completes
   * @param {keyCombinationListener} callbackFunction Listener function to be called
   * @returns {function} Function to call to cancel listening to the next key combination
   */
  addKeyCombinationListener(callbackFunction) {
    return this.globalEventStrategy.addKeyCombinationListener(callbackFunction);
  }

  /********************************************************************************
   * Global key events
   ********************************************************************************/

  /**
   * Ignores the next keyboard event immediately, rather than waiting for it to
   * match the ignoreEventsCondition
   * @param {SyntheticKeyboardEvent} event keyboard event to ignore
   * @see Configuration.ignoreEventsCondition
   */
  ignoreEvent(event) {
    this.focusOnlyEventStrategy.eventPropagator.ignoreEvent(event);
  }

  /**
   * Forces the observation of the next keyboard event immediately, disregarding whether
   * the event matches the ignoreKeyEventsCondition
   * @param {SyntheticKeyboardEvent} event keyboard event to force the observation of
   * @see Configuration.ignoreEventsCondition
   */
  observeIgnoredEvents(event) {
    this.focusOnlyEventStrategy.eventPropagator.observeIgnoredEvents(event);
  }

  /**
   * Closes any hanging key combinations that have not received the key event indicated
   * by recordIndex.
   * @param {KeyName} keyName The name of the key whose state should be updated if it
   *        is currently set to keydown or keypress.
   * @param {KeyEventType} recordIndex Index of key event to move the key state
   *        up to.
   */
  closeHangingKeyCombination(keyName, recordIndex) {
    this.focusOnlyEventStrategy.closeHangingKeyCombination(keyName, recordIndex);
  }

  reactAppHistoryWithEvent(key, type) {
    const previousPropagation =
      this.focusOnlyEventStrategy.eventPropagator.previousPropagation;

    if (previousPropagation.isForKey(key) && previousPropagation.isForEventType(type)) {
      if (previousPropagation.isHandled()) {
        return EventResponse.handled;
      } else if (previousPropagation.isIgnoringEvent()) {
        return EventResponse.ignored;
      } else {
        return EventResponse.seen;
      }
    } else {
      return EventResponse.unseen;
    }
  }

  simulatePendingKeyPressEvents() {
    this.focusOnlyEventStrategy.simulatePendingKeyPressEvents();
  }

  simulatePendingKeyUpEvents() {
    this.focusOnlyEventStrategy.simulatePendingKeyUpEvents();
  }

  isGlobalListenersBound() {
    return this.globalEventStrategy.isListenersBound();
  }
}

export default KeyEventManager;
<commit_msg>🐛 Use addEventlistener instead of window.onblur (#238)<commit_after>import Logger from './logging/Logger';
import FocusOnlyKeyEventStrategy from './strategies/FocusOnlyKeyEventStrategy';
import GlobalKeyEventStrategy from './strategies/GlobalKeyEventStrategy';
import Configuration from './config/Configuration';
import EventResponse from '../const/EventResponse';
import ApplicationKeyMapBuilder from './definitions/ApplicationKeyMapBuilder';
import lazyLoadAttribute from '../utils/object/lazyLoadAttribute';

/**
 * Provides a registry for keyboard sequences and events, and the handlers that should
 * be called when they are detected. Also contains the interface for processing and
 * matching keyboard events against its list of registered actions and handlers.
 * @class
 */
class KeyEventManager {
  /**
   * Creates a new KeyEventManager instance if one does not already exist or returns the
   * instance that already exists.
   * @param {Object} configuration Configuration object
   * @param {Logger} configuration.logger Logger instance
   * @returns {KeyEventManager} The key event manager instance
   */
  static getInstance(configuration = {}) {
    return lazyLoadAttribute(this, 'instance', () => new KeyEventManager(configuration));
  }

  static getFocusOnlyEventStrategy() {
    return this.getInstance().focusOnlyEventStrategy;
  }

  static getGlobalEventStrategy() {
    return this.getInstance().globalEventStrategy
  }

  /**
   * Creates a new KeyEventManager instance. It is expected that only a single instance
   * will be used with a render tree.
   */
  constructor(configuration = {}) {
    const logLevel = Configuration.option('logLevel');

    this.logger = configuration.logger || new Logger(logLevel);

    this.focusOnlyEventStrategy =
      new FocusOnlyKeyEventStrategy({ configuration, logLevel }, this);

    this.globalEventStrategy =
      new GlobalKeyEventStrategy({ configuration, logLevel }, this);

    this.mountedComponentsCount = 0;

    this._blurHandler = this._clearKeyHistory.bind(this);
  }

  /********************************************************************************
   * Generating key maps
   ********************************************************************************/

  /**
   * Returns a mapping of all of the application's actions and the key sequences
   * needed to trigger them.
   *
   * @type {ApplicationKeyMap} The application's key map
   */
  get applicationKeyMap() {
    return [this.globalEventStrategy, this.focusOnlyEventStrategy].reduce((memo, strategy) => {
      const builder = new ApplicationKeyMapBuilder(strategy.componentTree);
      const keyMap = builder.build();

      return { ...memo, ...keyMap };
    }, {});
  }

  /********************************************************************************
   * Registering key maps
   ********************************************************************************/

  /**
   * Registers that a component has now mounted, and declares its parent HotKeys
   * component id so that actions may be properly resolved
   * @param {ComponentId} componentId - Id of the component that has mounted
   * @param {ComponentId} parentId - Id of the parent HotKeys component
   */
  registerComponentMount(componentId, parentId) {
    this._incrementComponentCount();

    return this.focusOnlyEventStrategy.registerComponentMount(componentId, parentId);
  }

  registerComponentUnmount() {
    this._decrementComponentCount();
  }

  _incrementComponentCount(){
    const preMountedComponentCount = this.mountedComponentsCount;
    this.mountedComponentsCount += 1;

    if (preMountedComponentCount === 0 && this.mountedComponentsCount === 1) {
      window.addEventListener('blur', this._blurHandler);
    }
  }

  _decrementComponentCount(){
    const preMountedComponentCount = this.mountedComponentsCount;
    this.mountedComponentsCount -= 1;

    if (preMountedComponentCount === 1 && this.mountedComponentsCount === 0) {
      window.removeEventListener('blur', this._blurHandler);
    }
  }

  _clearKeyHistory() {
    this.logger.info('HotKeys: Window focused - clearing key history');

    this.focusOnlyEventStrategy.resetKeyHistory({ force: true });
    this.globalEventStrategy.resetKeyHistory({ force: true });
  }

  registerGlobalComponentUnmount() {
    this._decrementComponentCount();
  }

  /**
   * Registers that a component has now mounted, and declares its parent GlobalHotKeys
   * component id so that actions may be properly resolved
   * @param {ComponentId} componentId - Id of the component that has mounted
   * @param {ComponentId} parentId - Id of the parent GlobalHotKeys component
   */
  registerGlobalComponentMount(componentId, parentId) {
    this._incrementComponentCount();

    return this.globalEventStrategy.registerComponentMount(componentId, parentId);
  }

  /********************************************************************************
   * Recording key combination
   ********************************************************************************/

  /**
   * Adds a listener function that will be called the next time a key combination completes
   * @param {keyCombinationListener} callbackFunction Listener function to be called
   * @returns {function} Function to call to cancel listening to the next key combination
   */
  addKeyCombinationListener(callbackFunction) {
    return this.globalEventStrategy.addKeyCombinationListener(callbackFunction);
  }

  /********************************************************************************
   * Global key events
   ********************************************************************************/

  /**
   * Ignores the next keyboard event immediately, rather than waiting for it to
   * match the ignoreEventsCondition
   * @param {SyntheticKeyboardEvent} event keyboard event to ignore
   * @see Configuration.ignoreEventsCondition
   */
  ignoreEvent(event) {
    this.focusOnlyEventStrategy.eventPropagator.ignoreEvent(event);
  }

  /**
   * Forces the observation of the next keyboard event immediately, disregarding whether
   * the event matches the ignoreKeyEventsCondition
   * @param {SyntheticKeyboardEvent} event keyboard event to force the observation of
   * @see Configuration.ignoreEventsCondition
   */
  observeIgnoredEvents(event) {
    this.focusOnlyEventStrategy.eventPropagator.observeIgnoredEvents(event);
  }

  /**
   * Closes any hanging key combinations that have not received the key event indicated
   * by recordIndex.
   * @param {KeyName} keyName The name of the key whose state should be updated if it
   *        is currently set to keydown or keypress.
   * @param {KeyEventType} recordIndex Index of key event to move the key state
   *        up to.
   */
  closeHangingKeyCombination(keyName, recordIndex) {
    this.focusOnlyEventStrategy.closeHangingKeyCombination(keyName, recordIndex);
  }

  reactAppHistoryWithEvent(key, type) {
    const previousPropagation =
      this.focusOnlyEventStrategy.eventPropagator.previousPropagation;

    if (previousPropagation.isForKey(key) && previousPropagation.isForEventType(type)) {
      if (previousPropagation.isHandled()) {
        return EventResponse.handled;
      } else if (previousPropagation.isIgnoringEvent()) {
        return EventResponse.ignored;
      } else {
        return EventResponse.seen;
      }
    } else {
      return EventResponse.unseen;
    }
  }

  simulatePendingKeyPressEvents() {
    this.focusOnlyEventStrategy.simulatePendingKeyPressEvents();
  }

  simulatePendingKeyUpEvents() {
    this.focusOnlyEventStrategy.simulatePendingKeyUpEvents();
  }

  isGlobalListenersBound() {
    return this.globalEventStrategy.isListenersBound();
  }
}

export default KeyEventManager;
<|endoftext|>


<commit_before>import util from '../core/utils';

// dynamic proxy for custom generators
function proxy(gen) {
  return (value, schema, property, rootSchema) => {
    let fn = value;
    let args = [];

    // support for nested object, first-key is the generator
    if (typeof value === 'object') {
      fn = Object.keys(value)[0];

      // treat the given array as arguments,
      if (Array.isArray(value[fn])) {
        // if the generator is expecting arrays they should be nested, e.g. `[[1, 2, 3], true, ...]`
        args = value[fn];
      } else {
        args.push(value[fn]);
      }
    }

    // support for keypaths, e.g. "internet.email"
    const props = fn.split('.');

    // retrieve a fresh dependency
    let ctx = gen();

    while (props.length > 1) {
      ctx = ctx[props.shift()];
    }

    // retrieve last value from context object
    value = typeof ctx === 'object' ? ctx[props[0]] : ctx;

    // invoke dynamic generators
    if (typeof value === 'function') {
      value = value.apply(ctx, args.map(x => util.template(x, rootSchema)));
    }

    // test for pending callbacks
    if (Object.prototype.toString.call(value) === '[object Object]') {
      Object.keys(value).forEach(key => {
        if (typeof value[key] === 'function') {
          throw new Error(`Cannot resolve value for '${property}: ${fn}', given: ${value}`);
        }
      });
    }

    return value;
  };
}

/**
 * Container is used to wrap external generators (faker, chance, casual, etc.) and its dependencies.
 *
 * - `jsf.extend('faker')` will enhance or define the given dependency.
 * - `jsf.define('faker')` will provide the "faker" keyword support.
 *
 * RandExp is not longer considered an "extension".
 */
class Container {
  constructor() {
    // dynamic requires - handle all dependencies
    // they will NOT be included on the bundle
    this.registry = {};
    this.support = {};
  }

  /**
   * Unregister extensions
   * @param name
   */
  reset(name) {
    if (!name) {
      this.registry = {};
      this.support = {};
    } else {
      delete this.registry[name];
      delete this.support[name];
    }
  }

  /**
   * Override dependency given by name
   * @param name
   * @param callback
   */
  extend(name, callback) {
    this.registry[name] = callback(this.registry[name]);

    // built-in proxy (can be overridden)
    if (!this.support[name]) {
      this.support[name] = proxy(() => this.registry[name]);
    }
  }

  /**
   * Set keyword support by name
   * @param name
   * @param callback
   */
  define(name, callback) {
    this.support[name] = callback;
  }

  /**
   * Returns dependency given by name
   * @param name
   * @returns {Dependency}
   */
  get(name) {
    if (typeof this.registry[name] === 'undefined') {
      throw new ReferenceError(`'${name}' dependency doesn't exist.`);
    }
    return this.registry[name];
  }

  /**
   * Apply a custom keyword
   * @param schema
   */
  wrap(schema) {
    const keys = Object.keys(schema);
    const context = {};

    let length = keys.length;

    while (length--) { // eslint-disable-line
      const fn = keys[length].replace(/^x-/, '');
      const gen = this.support[fn];

      if (typeof gen === 'function') {
        Object.defineProperty(schema, 'generate', {
          configurable: false,
          enumerable: false,
          writable: false,
          value: (rootSchema, key) => gen.call(context, schema[keys[length]], schema, keys[length], rootSchema, key.slice()), // eslint-disable-line
        });
        break;
      }
    }

    return schema;
  }
}

export default Container;
<commit_msg>fix: do not reassign generate() if present<commit_after>import util from '../core/utils';

// dynamic proxy for custom generators
function proxy(gen) {
  return (value, schema, property, rootSchema) => {
    let fn = value;
    let args = [];

    // support for nested object, first-key is the generator
    if (typeof value === 'object') {
      fn = Object.keys(value)[0];

      // treat the given array as arguments,
      if (Array.isArray(value[fn])) {
        // if the generator is expecting arrays they should be nested, e.g. `[[1, 2, 3], true, ...]`
        args = value[fn];
      } else {
        args.push(value[fn]);
      }
    }

    // support for keypaths, e.g. "internet.email"
    const props = fn.split('.');

    // retrieve a fresh dependency
    let ctx = gen();

    while (props.length > 1) {
      ctx = ctx[props.shift()];
    }

    // retrieve last value from context object
    value = typeof ctx === 'object' ? ctx[props[0]] : ctx;

    // invoke dynamic generators
    if (typeof value === 'function') {
      value = value.apply(ctx, args.map(x => util.template(x, rootSchema)));
    }

    // test for pending callbacks
    if (Object.prototype.toString.call(value) === '[object Object]') {
      Object.keys(value).forEach(key => {
        if (typeof value[key] === 'function') {
          throw new Error(`Cannot resolve value for '${property}: ${fn}', given: ${value}`);
        }
      });
    }

    return value;
  };
}

/**
 * Container is used to wrap external generators (faker, chance, casual, etc.) and its dependencies.
 *
 * - `jsf.extend('faker')` will enhance or define the given dependency.
 * - `jsf.define('faker')` will provide the "faker" keyword support.
 *
 * RandExp is not longer considered an "extension".
 */
class Container {
  constructor() {
    // dynamic requires - handle all dependencies
    // they will NOT be included on the bundle
    this.registry = {};
    this.support = {};
  }

  /**
   * Unregister extensions
   * @param name
   */
  reset(name) {
    if (!name) {
      this.registry = {};
      this.support = {};
    } else {
      delete this.registry[name];
      delete this.support[name];
    }
  }

  /**
   * Override dependency given by name
   * @param name
   * @param callback
   */
  extend(name, callback) {
    this.registry[name] = callback(this.registry[name]);

    // built-in proxy (can be overridden)
    if (!this.support[name]) {
      this.support[name] = proxy(() => this.registry[name]);
    }
  }

  /**
   * Set keyword support by name
   * @param name
   * @param callback
   */
  define(name, callback) {
    this.support[name] = callback;
  }

  /**
   * Returns dependency given by name
   * @param name
   * @returns {Dependency}
   */
  get(name) {
    if (typeof this.registry[name] === 'undefined') {
      throw new ReferenceError(`'${name}' dependency doesn't exist.`);
    }
    return this.registry[name];
  }

  /**
   * Apply a custom keyword
   * @param schema
   */
  wrap(schema) {
    if (!('generate' in schema)) {
      const keys = Object.keys(schema);
      const context = {};

      let length = keys.length;

      while (length--) { // eslint-disable-line
        const fn = keys[length].replace(/^x-/, '');
        const gen = this.support[fn];

        if (typeof gen === 'function') {
          Object.defineProperty(schema, 'generate', {
            configurable: false,
            enumerable: false,
            writable: false,
            value: (rootSchema, key) => gen.call(context, schema[keys[length]], schema, keys[length], rootSchema, key.slice()), // eslint-disable-line
          });
          break;
        }
      }
    }
    return schema;
  }
}

export default Container;
<|endoftext|>


<commit_before>'use strict';

const _ = require('lodash')
const fs = require('fs')
const moment = require('moment')

class Utils {
    constructor() { }

    static getSingleLineStrings(strings, ...values) {
        let output = ''
        const valuesLength = values.length
        for (let i = 0; i < valuesLength; i++) {
            output += strings[i] + values[i]
        }
        output += strings[valuesLength]
        let lines = output.split(/(?:\r\n|\n|\r)/)

        return lines.map((line) => {
            return line.replace(/^\s+/gm, '')
        }).join(' ').trim()
    }

    // static *getObjectValues(object) {
    // 	const objectKeys = Object.keys(obj)
    // 	for (let prop of objectKeys) {
    // 		yield obj[prop]
    // 	}
    // }

    static getObjectIndex(arrayOfObjects, objectToFind, excludeArrays) {
        return _.findIndex(arrayOfObjects, (obj) => {
            if (excludeArrays) {
                obj = this.removeArraysFromObject(obj)
            }
            return _.isEqual(obj, objectToFind)
        })
    }

    static trimSpacesFromString(stringToTrim) {
        return stringToTrim.replace(/\s+/g, ' ')
    }

    static updateObjectPropsFromNewArray(objectToUpdate, objectsToAppend) {
        objectsToAppend.forEach((object) => {
            Object.keys(object).forEach((key) => {
                objectToUpdate[key] = object[key]
            })
        })
        return objectToUpdate
    }

    static removeStringsFromArray(arrayOfStrings, stringsToRemove) {
        let arrayCopy = _.clone(arrayOfStrings)

        _.remove(arrayCopy, stringFromArray => {
            return stringsToRemove.includes(stringFromArray)
        })
        return arrayCopy
    }

    static removeArraysFromObject(object) {
        let result = {}
        Object.keys(object).forEach((key) => {
            if (!_.isArray(object[key])) {
                result[key] = object[key]
            }
        })
        return result
    }

    static formatDateToCurrentTimezone(date) {
        const currentTimezoneHours = getTimezoneHours()
        const currentTimezoneMinutes = getTimezoneMinutes()
        const newDate = new Date(date)
        newDate.setHours(newDate.getHours() + currentTimezoneHours)
        newDate.setMinutes(newDate.getMinutes() + currentTimezoneMinutes)
        return newDate
    }

    static arrayContainsObject(arrayOfObjects, objectToFind) {
        return _.find(arrayOfObjects, (object) => {
            return _.isEqual(objectToFind, object)
        })
    }

    static readFile(filePath) {
        return new Promise((resolve, reject) => {
            fs.readFile(filePath, 'utf8', (err, data) => {
                if (err) {
                    reject(err)
                } else {
                    resolve(data)
                }
            })
        })
    }

    static writeFile(filePath, fileContent) {
        return new Promise((resolve, reject) => {
            fs.writeFile(filePath, fileContent, (err) => {
                if (err) {
                    reject(err)
                } else {
                    resolve(true)
                }
            })
        })
    }

    static stringContainsAny(stringToCheck, strings) {
        return _.some(strings, (string) => {
            return stringToCheck.toLowerCase()
                .includes(string.toLowerCase())
        })
    }
}

function getTimezoneHours() {
    const date = new Date()
    const offset = -date.getTimezoneOffset()
    const resultSign = offset >= 0 ? '+' : '-'
    return parseInt(resultSign + parseInt(offset / 60))
}

function getTimezoneMinutes() {
    const date = new Date();
    const offset = -date.getTimezoneOffset()
    return parseInt(offset % 60)
}

module.exports = Utils;
<commit_msg>Update utils.js<commit_after>'use strict';

const _ = require('lodash')
const fs = require('fs')

class Utils {
    constructor() { }

    static getSingleLineStrings(strings, ...values) {
        let output = ''
        const valuesLength = values.length
        for (let i = 0; i < valuesLength; i++) {
            output += strings[i] + values[i]
        }
        output += strings[valuesLength]
        let lines = output.split(/(?:\r\n|\n|\r)/)

        return lines.map((line) => {
            return line.replace(/^\s+/gm, '')
        }).join(' ').trim()
    }

    // static *getObjectValues(object) {
    // 	const objectKeys = Object.keys(obj)
    // 	for (let prop of objectKeys) {
    // 		yield obj[prop]
    // 	}
    // }

    static getObjectIndex(arrayOfObjects, objectToFind, excludeArrays) {
        return _.findIndex(arrayOfObjects, (obj) => {
            if (excludeArrays) {
                obj = this.removeArraysFromObject(obj)
            }
            return _.isEqual(obj, objectToFind)
        })
    }

    static trimSpacesFromString(stringToTrim) {
        return stringToTrim.replace(/\s+/g, ' ')
    }

    static updateObjectPropsFromNewArray(objectToUpdate, objectsToAppend) {
        objectsToAppend.forEach((object) => {
            Object.keys(object).forEach((key) => {
                objectToUpdate[key] = object[key]
            })
        })
        return objectToUpdate
    }

    static removeStringsFromArray(arrayOfStrings, stringsToRemove) {
        let arrayCopy = _.clone(arrayOfStrings)

        _.remove(arrayCopy, stringFromArray => {
            return stringsToRemove.includes(stringFromArray)
        })
        return arrayCopy
    }

    static removeArraysFromObject(object) {
        let result = {}
        Object.keys(object).forEach((key) => {
            if (!_.isArray(object[key])) {
                result[key] = object[key]
            }
        })
        return result
    }

    static formatDateToCurrentTimezone(date) {
        const currentTimezoneHours = getTimezoneHours()
        const currentTimezoneMinutes = getTimezoneMinutes()
        const newDate = new Date(date)
        newDate.setHours(newDate.getHours() + currentTimezoneHours)
        newDate.setMinutes(newDate.getMinutes() + currentTimezoneMinutes)
        return newDate
    }

    static arrayContainsObject(arrayOfObjects, objectToFind) {
        return _.find(arrayOfObjects, (object) => {
            return _.isEqual(objectToFind, object)
        })
    }

    static readFile(filePath) {
        return new Promise((resolve, reject) => {
            fs.readFile(filePath, 'utf8', (err, data) => {
                if (err) {
                    reject(err)
                } else {
                    resolve(data)
                }
            })
        })
    }

    static writeFile(filePath, fileContent) {
        return new Promise((resolve, reject) => {
            fs.writeFile(filePath, fileContent, (err) => {
                if (err) {
                    reject(err)
                } else {
                    resolve(true)
                }
            })
        })
    }

    static stringContainsAny(stringToCheck, strings) {
        return _.some(strings, (string) => {
            return stringToCheck.toLowerCase()
                .includes(string.toLowerCase())
        })
    }
}

function getTimezoneHours() {
    const date = new Date()
    const offset = -date.getTimezoneOffset()
    const resultSign = offset >= 0 ? '+' : '-'
    return parseInt(resultSign + parseInt(offset / 60))
}

function getTimezoneMinutes() {
    const date = new Date();
    const offset = -date.getTimezoneOffset()
    return parseInt(offset % 60)
}

module.exports = Utils;
<|endoftext|>


<commit_before>var globals = require('../globals'),
  util = require('../util'),
  setter = util.setter,
  getter = util.getter,
  time = require('./time');

var axis = module.exports = {};

axis.names = function(props) {
  return util.keys(util.keys(props).reduce(function(a, x) {
    var s = props[x].scale;
    if (s === X || s === Y) a[props[x].scale] = 1;
    return a;
  }, {}));
};

axis.defs = function(names, encoding, layout, opt) {
  return names.reduce(function(a, name) {
    a.push(axis.def(name, encoding, layout, opt));
    return a;
  }, []);
};

axis.def = function(name, encoding, layout, opt) {
  var type = name;
  var isCol = name == COL, isRow = name == ROW;
  if (isCol) type = 'x';
  if (isRow) type = 'y';

  var def = {
    type: type,
    scale: name
  };

  if (encoding.axis(name).grid) {
    def.grid = true;
    def.layer = 'back';
  }

  if (encoding.axis(name).title) {
    def = axis_title(def, name, encoding, layout, opt);
  }

  if (isRow || isCol) {
    setter(def, ['properties', 'ticks'], {
      opacity: {value: 0}
    });
    setter(def, ['properties', 'majorTicks'], {
      opacity: {value: 0}
    });
    setter(def, ['properties', 'axis'], {
      opacity: {value: 0}
    });
  }

  if (isCol) {
    def.orient = 'top';
  }

  if (isRow) {
    def.offset = axisTitleOffset(encoding, layout, Y) + 20;
  }

  if (name == X) {
    if (encoding.isOrdinalScale(X) || encoding.isType(X, T)) {
      setter(def, ['properties','labels'], {
        angle: {value: 270},
        align: {value: 'right'},
        baseline: {value: 'middle'}
      });
    } else { // Q
      def.ticks = 5;
    }
  }

  if (encoding.axis(name).format) {
    def.format = encoding.axis(name).format;
  } else if (encoding.isType(name, Q)) {
    def.format = "s";
  } else if (encoding.isType(name, T)) {
    if (!encoding.fn(name)) {
      def.format = "%Y-%m-%d";
    } else {
      def.format = "d";
    }
  }

  var fn;
  // add custom label for time type
  if (encoding.isType(name, T) && (fn = encoding.fn(name)) && (time.hasScale(fn))) {
    setter(def, ['properties','labels','text','scale'], 'time-'+ fn);
  }

  return def;
};

function axis_title(def, name, encoding, layout, opt) {
  var maxLength = null,
    fieldTitle = encoding.fieldTitle(name);
  if (name===X) {
    maxlength = layout.cellWidth / encoding.config('characterWidth');
  } else if (name === Y) {
    maxlength = layout.cellHeight / encoding.config('characterWidth');
  }

  def.title = maxlength ? util.truncate(fieldTitle, maxlength) : fieldTitle;

  if (name === ROW) {
    setter(def, ['properties','title'], {
      angle: {value: 0},
      align: {value: 'right'},
      baseline: {value: 'middle'},
      dy: {value: (-layout.height/2) -20}
    });
  }
  def.titleOffset = axisTitleOffset(encoding, layout, name);
  return def;
}

function axisTitleOffset(encoding, layout, name) {
  var value = encoding.axis(name).titleOffset;
  if (value) {
    return value;
  }
  switch (name) {
    case ROW: return 0;
    case COL: return 35;
  }
  return getter(layout, [name, 'axisTitleOffset']);
}
<commit_msg>fix typo bug<commit_after>var globals = require('../globals'),
  util = require('../util'),
  setter = util.setter,
  getter = util.getter,
  time = require('./time');

var axis = module.exports = {};

axis.names = function(props) {
  return util.keys(util.keys(props).reduce(function(a, x) {
    var s = props[x].scale;
    if (s === X || s === Y) a[props[x].scale] = 1;
    return a;
  }, {}));
};

axis.defs = function(names, encoding, layout, opt) {
  return names.reduce(function(a, name) {
    a.push(axis.def(name, encoding, layout, opt));
    return a;
  }, []);
};

axis.def = function(name, encoding, layout, opt) {
  var type = name;
  var isCol = name == COL, isRow = name == ROW;
  if (isCol) type = 'x';
  if (isRow) type = 'y';

  var def = {
    type: type,
    scale: name
  };

  if (encoding.axis(name).grid) {
    def.grid = true;
    def.layer = 'back';
  }

  if (encoding.axis(name).title) {
    def = axis_title(def, name, encoding, layout, opt);
  }

  if (isRow || isCol) {
    setter(def, ['properties', 'ticks'], {
      opacity: {value: 0}
    });
    setter(def, ['properties', 'majorTicks'], {
      opacity: {value: 0}
    });
    setter(def, ['properties', 'axis'], {
      opacity: {value: 0}
    });
  }

  if (isCol) {
    def.orient = 'top';
  }

  if (isRow) {
    def.offset = axisTitleOffset(encoding, layout, Y) + 20;
  }

  if (name == X) {
    if (encoding.isOrdinalScale(X) || encoding.isType(X, T)) {
      setter(def, ['properties','labels'], {
        angle: {value: 270},
        align: {value: 'right'},
        baseline: {value: 'middle'}
      });
    } else { // Q
      def.ticks = 5;
    }
  }

  if (encoding.axis(name).format) {
    def.format = encoding.axis(name).format;
  } else if (encoding.isType(name, Q)) {
    def.format = "s";
  } else if (encoding.isType(name, T)) {
    if (!encoding.fn(name)) {
      def.format = "%Y-%m-%d";
    } else {
      def.format = "d";
    }
  }

  var fn;
  // add custom label for time type
  if (encoding.isType(name, T) && (fn = encoding.fn(name)) && (time.hasScale(fn))) {
    setter(def, ['properties','labels','text','scale'], 'time-'+ fn);
  }

  return def;
};

function axis_title(def, name, encoding, layout, opt) {
  var maxlength = null,
    fieldTitle = encoding.fieldTitle(name);
  if (name===X) {
    maxlength = layout.cellWidth / encoding.config('characterWidth');
  } else if (name === Y) {
    maxlength = layout.cellHeight / encoding.config('characterWidth');
  }

  def.title = maxlength ? util.truncate(fieldTitle, maxlength) : fieldTitle;

  if (name === ROW) {
    setter(def, ['properties','title'], {
      angle: {value: 0},
      align: {value: 'right'},
      baseline: {value: 'middle'},
      dy: {value: (-layout.height/2) -20}
    });
  }
  def.titleOffset = axisTitleOffset(encoding, layout, name);
  return def;
}

function axisTitleOffset(encoding, layout, name) {
  var value = encoding.axis(name).titleOffset;
  if (value) {
    return value;
  }
  switch (name) {
    case ROW: return 0;
    case COL: return 35;
  }
  return getter(layout, [name, 'axisTitleOffset']);
}
<|endoftext|>


<commit_before>/* eslint-disable
    global-require,
    import/no-unresolved,
*/
// TODO: This file was created by bulk-decaffeinate.
// Fix any style issues and re-enable lint.
const { isBrowser } = require('../Platform');

if (isBrowser()) {
  throw new Error('Generate NoFlo component loader for browsers with noflo-component-loader');
} else {
  module.exports = require('./NodeJs');
}
<commit_msg>Strip decaf notes<commit_after>/* eslint-disable
    global-require,
    import/no-unresolved,
*/
const { isBrowser } = require('../Platform');

if (isBrowser()) {
  throw new Error('Generate NoFlo component loader for browsers with noflo-component-loader');
} else {
  module.exports = require('./NodeJs');
}
<|endoftext|>