<commit_before>/**
 * Dispatcher - the communication / app nexus / pub-sub extension
 *
 * Taken from: Facebook Dispatcher and Alex MacCaw - JavaScript Web Applications - Pag.28
 *
 * The Flux dispatcher is different from pub-sub in two ways
 * 1) Callbacks are not subscribed to particular events. Every payload is
 *      dispatched to every registered callback.
 * 2) Callbacks can be deferred in whole or part until other callbacks have
 *      been executed.
 * But since we need to support both, if we're using actions then we use the channel as 'ACTION'
 * so all participants in Flux can listen
 *
 * @check https://facebook.github.io/flux/docs/dispatcher.html
 * @usage:
 * // creating the callback
 * var fn = function(payload) { alert('wem!'); }
 *
 * // subscribing
 * PubSub.subscribe('wem', fn);
 *
 * // publishing
 * PubSub.publish('wem');
 *
 * // unsubscribing
 * PubSub.unsubscrube('wem', fn);
 */
F.Core.dispatcher = (function(){
	"use strict";

	var _prefix = 'ID_';
	var ACTION = 'ACTION';

	var
		_isDispatching = false,
		_isHandled = {},
		_isPending = {},
		_lastID = 1,
		_pendingPayload = null
	;

	return {
		/**
		* Registers a callback to be called when an event is published.
		* returns a token that can be used with `waitfFor()`
		* @method
		* @public
		*
		* @param {String} channel - event / channel / action
		* @param {Function} callback - the callback to be registered
		* @param {Object} context - the object under whiches context the callback is to be called
		*/
		subscribe: function (channel, callback, context) {
			// Create _callbacks object, unless it already exists
			var calls = this._callbacks || (this._callbacks = {});

			// Create an array for the given event key, unless it exists, then
			// append the callback to the array
			var id = _prefix + _lastID++;
			(this._callbacks[channel] || (this._callbacks[channel] = [])).push({ callback: callback, context: context, id: id });
			return id;
		},

		/**
		* Deregisters a callback for an event
		* @method
		* @public
		*
		* @param {String} channel
		* @param {Function} callcack - the callback to be unregistered
		*/
		unsubscribe: function (channel, callback) {

			// Return if there isn't a _callbacks object, or
			// if it doesn't contain an array for the given event
			var list, calls, i, l;
			if (!(calls = this._callbacks[channel])) return this;
			if (!(list = this._callbacks[channel])) return this;

			// remove callback
			for (i = 0, l = list.length; i < l; i++) {
				var handler = list[i];
				if (handler === callback) {
					list.splice(i);
				}
			}
		},

		/**
		* Publishes an event and callsback all subscribers to that event
		* @method
		* @public
		*
		* @param {String} eventName - the event / channel / action name
		* @param {Object} payload - the data to be published for the event / channel / action
		*/
		publish: function () {
			// Turn arguments object into a real array
			var args = Array.prototype.slice.call(arguments, 0);
			// Extract the first argument, the event name
			var ev = args.shift();

			if (ev === ACTION) {

				/*
				if(!this._isDispatching){
					throw new Error('dispatcher.publish(...): Cannot dispatch in the middle of a dispatch');
				}
				*/
				this._start(args);

				try {
					var list, calls, i, l;
					if (!(calls = this._callbacks)) return;
					if (!(list = this._callbacks[ACTION])) return;

					for (i = 0, l = list.length; i < l; i++) {
						var handler = list[i];
						if (_isPending[handler.id]) {
							continue;
						}
						handler.callback.apply(handler.context || null, args);
					}
				} finally {
					this._stop();
				}

				return;
			}

			// Return if there isn't a _callbacks object, or
			// if it doesn't contain an array for the given event
			var list1, calls1, i1, l1;
			if (!(calls1 = this._callbacks)) return;
			if (!(list1 = this._callbacks[ev])) return;

			// Invoke the callbacks
			for (i1 = 0, l1 = list1.length; i1 < l1; i1++) {
				var handler1 = list1[i1];
				handler1.callback.apply(handler1.context || null, args);
			}

			return;
		},

		/**
		* Helper method to publish an action
		* @param {Object} payload - the action to be published
		* Payload : {
		*   type : 'action-name',
		*   data : {}
		* }
		*/
		publishAction: function (payload) {
			this.publish(ACTION, payload);
		},

		/**
		* Waits for the callbacks specified to be invoked before continuing execution
		* of the current callback. This method should only be used by a callback in
		* response to a dispatched payload.
		*
		* When `waitFor()` is encountered in a callback, it tells the Dispatcher to invoke the callbacks for the required stores.
		* After these callbacks complete, the original callback can continue to execute.
		* Thus the store that is invoking `waitFor()` can depend on the state of another store to inform how it should update its own state.
		*
		* A problem arises if we create circular dependencies.
		* If Store A waits for Store B, and B waits for A, then we could wind up in an endless loop.
		* The Dispatcher will flag these circular dependencies with console errors.
		*
		* @param {Array} dispatchTokens - an array of dipatcher registry indexes, which we refer to here as each store's dispatchToken
		* @usage:
		* case 'TODO_CREATE':
		*   dispatcher.waitFor([
		*     PrependedTextStore.dispatchToken,
		*     YeatAnotherstore.dispatchToken
		*   ]);
		* 	 TodoStore.create(PrependedTextStore.getText() + '' + action.text);
		*   TodoStore.emit('chage');
		*   break;
		*/
		waitFor: function (dispatchTokens) {
			/*
			if (!this.isDispatching) {
				throw new Error('dispatcher.waitFor(...): Must be invoked while dispatching');
			}
			*/
			var _handlerFn = function (handler) {
				if (handler.id === token) {
					_handler = handler;
				}
			};

			for (var i = 0; i < dispatchTokens.length; i++) {
				var token = dispatchTokens[i];
				if (_isPending[token]) {
					if (!_isHandled[token]) {
						throw new Error('dispatcher.waitFor(...): Circular dependency detected while waiting for ' + token);
					}
					continue;
				}

				var _handler = null;

				this._callbacks[ACTION].forEach(_handlerFn(handler));

				if (!_handler) {
					throw new Error('dispatcher.waitFor(...):' + token + ' does not map to a registered callback.');
				}

				_isPending[token] = true;
				_handler.callback.apply(_handler.context || null);
				_isHandled[token] = true;
			}
		},

		/**
		* Setup booking used for dispatching
		*/
		_start: function (payload) {
			// Return if there isn't a _callbacks object, or
			// if it doesn't contain an array for the given event
			var list, calls, i, l;
			if (!(calls = this._callbacks)) return;
			if (!(list = this._callbacks[ACTION])) return;

			// Invoke the callbacks
			for (i = 0, l = list.length; i < l; i++) {
				var handler = list[i];
				_isPending[handler.id] = false;
				_isHandled[handler.id] = false;
			}
			_pendingPayload = payload;
			_isDispatching = true;
		},

		/**
		* Clear booking used for dispatching
		*/
		_stop: function () {
			_pendingPayload = null;
			_isDispatching = false;
		}
	};
}());<commit_msg>change dispatcher name space and make action dispatch method more idiomatic<commit_after>/**
 * Dispatcher - the communication / app nexus / pub-sub extension
 *
 * Taken from: Facebook Dispatcher and Alex MacCaw - JavaScript Web Applications - Pag.28
 *
 * The Flux dispatcher is different from pub-sub in two ways
 * 1) Callbacks are not subscribed to particular events. Every payload is
 *      dispatched to every registered callback.
 * 2) Callbacks can be deferred in whole or part until other callbacks have
 *      been executed.
 * But since we need to support both, if we're using actions then we use the channel as 'ACTION'
 * so all participants in Flux can listen
 *
 * @check https://facebook.github.io/flux/docs/dispatcher.html
 * @usage:
 * // creating the callback
 * var fn = function(payload) { alert('wem!'); }
 *
 * // subscribing
 * PubSub.subscribe('wem', fn);
 *
 * // publishing
 * PubSub.publish('wem');
 *
 * // unsubscribing
 * PubSub.unsubscrube('wem', fn);
 */
F.dispatcher = (function(){
	"use strict";

	var _prefix = 'ID_';
	var ACTION = 'ACTION';

	var
		_isDispatching = false,
		_isHandled = {},
		_isPending = {},
		_lastID = 1,
		_pendingPayload = null
	;

	return {
		/**
		* Registers a callback to be called when an event is published.
		* returns a token that can be used with `waitfFor()`
		* @method
		* @public
		*
		* @param {String} channel - event / channel / action
		* @param {Function} callback - the callback to be registered
		* @param {Object} context - the object under whiches context the callback is to be called
		*/
		subscribe: function (channel, callback, context) {
			// Create _callbacks object, unless it already exists
			var calls = this._callbacks || (this._callbacks = {});

			// Create an array for the given event key, unless it exists, then
			// append the callback to the array
			var id = _prefix + _lastID++;
			(this._callbacks[channel] || (this._callbacks[channel] = [])).push({ callback: callback, context: context, id: id });
			return id;
		},

		/**
		* Deregisters a callback for an event
		* @method
		* @public
		*
		* @param {String} channel
		* @param {Function} callcack - the callback to be unregistered
		*/
		unsubscribe: function (channel, callback) {

			// Return if there isn't a _callbacks object, or
			// if it doesn't contain an array for the given event
			var list, calls, i, l;
			if (!(calls = this._callbacks[channel])) return this;
			if (!(list = this._callbacks[channel])) return this;

			// remove callback
			for (i = 0, l = list.length; i < l; i++) {
				var handler = list[i];
				if (handler === callback) {
					list.splice(i);
				}
			}
		},

		/**
		* Publishes an event and callsback all subscribers to that event
		* @method
		* @public
		*
		* @param {String} eventName - the event / channel / action name
		* @param {Object} payload - the data to be published for the event / channel / action
		*/
		publish: function () {
			// Turn arguments object into a real array
			var args = Array.prototype.slice.call(arguments, 0);
			// Extract the first argument, the event name
			var ev = args.shift();

			if (ev === ACTION) {

				/*
				if(!this._isDispatching){
					throw new Error('dispatcher.publish(...): Cannot dispatch in the middle of a dispatch');
				}
				*/
				this._start(args);

				try {
					var list, calls, i, l;
					if (!(calls = this._callbacks)) return;
					if (!(list = this._callbacks[ACTION])) return;

					for (i = 0, l = list.length; i < l; i++) {
						var handler = list[i];
						if (_isPending[handler.id]) {
							continue;
						}
						handler.callback.apply(handler.context || null, args);
					}
				} finally {
					this._stop();
				}

				return;
			}

			// Return if there isn't a _callbacks object, or
			// if it doesn't contain an array for the given event
			var list1, calls1, i1, l1;
			if (!(calls1 = this._callbacks)) return;
			if (!(list1 = this._callbacks[ev])) return;

			// Invoke the callbacks
			for (i1 = 0, l1 = list1.length; i1 < l1; i1++) {
				var handler1 = list1[i1];
				handler1.callback.apply(handler1.context || null, args);
			}

			return;
		},

		/**
		* Helper method to publish an action
		* @param {Object} payload - the action to be published
		* Payload : {
		*   type : 'action-name',
		*   data : {}
		* }
		*/
		dispatch: function (payload) {
			this.publish(ACTION, payload);
		},

		/**
		* Waits for the callbacks specified to be invoked before continuing execution
		* of the current callback. This method should only be used by a callback in
		* response to a dispatched payload.
		*
		* When `waitFor()` is encountered in a callback, it tells the Dispatcher to invoke the callbacks for the required stores.
		* After these callbacks complete, the original callback can continue to execute.
		* Thus the store that is invoking `waitFor()` can depend on the state of another store to inform how it should update its own state.
		*
		* A problem arises if we create circular dependencies.
		* If Store A waits for Store B, and B waits for A, then we could wind up in an endless loop.
		* The Dispatcher will flag these circular dependencies with console errors.
		*
		* @param {Array} dispatchTokens - an array of dipatcher registry indexes, which we refer to here as each store's dispatchToken
		* @usage:
		* case 'TODO_CREATE':
		*   dispatcher.waitFor([
		*     PrependedTextStore.dispatchToken,
		*     YeatAnotherstore.dispatchToken
		*   ]);
		* 	 TodoStore.create(PrependedTextStore.getText() + '' + action.text);
		*   TodoStore.emit('chage');
		*   break;
		*/
		waitFor: function (dispatchTokens) {
			/*
			if (!this.isDispatching) {
				throw new Error('dispatcher.waitFor(...): Must be invoked while dispatching');
			}
			*/
			var _handlerFn = function (handler) {
				if (handler.id === token) {
					_handler = handler;
				}
			};

			for (var i = 0; i < dispatchTokens.length; i++) {
				var token = dispatchTokens[i];
				if (_isPending[token]) {
					if (!_isHandled[token]) {
						throw new Error('dispatcher.waitFor(...): Circular dependency detected while waiting for ' + token);
					}
					continue;
				}

				var _handler = null;

				this._callbacks[ACTION].forEach(_handlerFn(handler));

				if (!_handler) {
					throw new Error('dispatcher.waitFor(...):' + token + ' does not map to a registered callback.');
				}

				_isPending[token] = true;
				_handler.callback.apply(_handler.context || null);
				_isHandled[token] = true;
			}
		},

		/**
		* Setup booking used for dispatching
		*/
		_start: function (payload) {
			// Return if there isn't a _callbacks object, or
			// if it doesn't contain an array for the given event
			var list, calls, i, l;
			if (!(calls = this._callbacks)) return;
			if (!(list = this._callbacks[ACTION])) return;

			// Invoke the callbacks
			for (i = 0, l = list.length; i < l; i++) {
				var handler = list[i];
				_isPending[handler.id] = false;
				_isHandled[handler.id] = false;
			}
			_pendingPayload = payload;
			_isDispatching = true;
		},

		/**
		* Clear booking used for dispatching
		*/
		_stop: function () {
			_pendingPayload = null;
			_isDispatching = false;
		}
	};
}());<|endoftext|>


<commit_before>import {Plugin} from "prosemirror-state"
import {dropPoint} from "prosemirror-transform"

export function dropCursor(options = {}) {
  return new Plugin({
    view(editorView) { return new DropCursorView(editorView, options) }
  })
}

class DropCursorView {
  constructor(editorView, options) {
    this.editorView = editorView
    this.width = options.width || 1
    this.color = options.color || "black"
    this.cursorPos = null
    this.element = null
    this.timeout = null

    this.handlers = ["dragover", "dragend", "drop", "dragleave"].map(name => {
      let handler = e => this[name](e)
      editorView.dom.addEventListener(name, handler)
      return {name, handler}
    })
  }

  destroy() {
    this.handlers.forEach(({name, handler}) => this.editorView.dom.removeEventListener(name, handler))
  }

  update(editorView, prevState) {
    if (this.cursorPos != null && prevState.doc != editorView.state.doc) this.updateOverlay()
  }

  setCursor(pos) {
    if (pos == this.cursorPos) return
    this.cursorPos = pos
    if (pos == null) {
      this.element.parentNode.removeChild(this.element)
      this.element = null
    } else {
      this.updateOverlay()
    }
  }

  updateOverlay() {
    let $pos = this.editorView.state.doc.resolve(this.cursorPos), rect
    if (!$pos.parent.inlineContent) {
      let before = $pos.nodeBefore, after = $pos.nodeAfter
      if (before || after) {
        let nodeRect = this.editorView.nodeDOM(this.cursorPos - (before ?  before.nodeSize : 0)).getBoundingClientRect()
        let top = before ? nodeRect.bottom : nodeRect.top
        if (before && after)
          top = (top + this.editorView.nodeDOM(this.cursorPos).getBoundingClientRect().top) / 2
        rect = {left: nodeRect.left, right: nodeRect.right, top: top - this.width / 2, bottom: top + this.width / 2}
      }
    }
    if (!rect) {
      let coords = this.editorView.coordsAtPos(this.cursorPos)
      rect = {left: coords.left - this.width / 2, right: coords.left + this.width / 2, top: coords.top, bottom: coords.bottom}
    }

    let parent = this.editorView.dom.offsetParent
    if (!this.element) {
      this.element = parent.appendChild(document.createElement("div"))
      this.element.style.cssText = "position: absolute; z-index: 50; pointer-events: none; background-color: " + this.color
    }
    let parentRect = parent == document.body && getComputedStyle(parent).position == "static"
        ? {left: -pageXOffset, top: -pageYOffset} : parent.getBoundingClientRect()
    this.element.style.left = (rect.left - parentRect.left) + "px"
    this.element.style.top = (rect.top - parentRect.top) + "px"
    this.element.style.width = (rect.right - rect.left) + "px"
    this.element.style.height = (rect.bottom - rect.top) + "px"
  }

  scheduleRemoval(timeout) {
    clearTimeout(this.timeout)
    this.timeout = setTimeout(() => this.setCursor(null), timeout)
  }

  dragover(event) {
    let pos = this.editorView.posAtCoords({left: event.clientX, top: event.clientY})
    if (pos) {
      let target = pos.pos
      if (this.editorView.dragging && this.editorView.dragging.slice) {
        target = dropPoint(this.editorView.state.doc, target, this.editorView.dragging.slice)
        if (target == null) target = pos.pos
      }
      this.setCursor(target)
      this.scheduleRemoval(5000)
    }
  }

  dragend() {
    this.scheduleRemoval(20)
  }

  drop() {
    this.scheduleRemoval(20)
  }

  dragleave(event) {
    if (event.target == this.editorView.dom || !this.editorView.dom.contains(event.relatedTarget))
      this.setCursor(null)
  }
}
<commit_msg>Don't show a drop cursor when the view isn't editable<commit_after>import {Plugin} from "prosemirror-state"
import {dropPoint} from "prosemirror-transform"

export function dropCursor(options = {}) {
  return new Plugin({
    view(editorView) { return new DropCursorView(editorView, options) }
  })
}

class DropCursorView {
  constructor(editorView, options) {
    this.editorView = editorView
    this.width = options.width || 1
    this.color = options.color || "black"
    this.cursorPos = null
    this.element = null
    this.timeout = null

    this.handlers = ["dragover", "dragend", "drop", "dragleave"].map(name => {
      let handler = e => this[name](e)
      editorView.dom.addEventListener(name, handler)
      return {name, handler}
    })
  }

  destroy() {
    this.handlers.forEach(({name, handler}) => this.editorView.dom.removeEventListener(name, handler))
  }

  update(editorView, prevState) {
    if (this.cursorPos != null && prevState.doc != editorView.state.doc) this.updateOverlay()
  }

  setCursor(pos) {
    if (pos == this.cursorPos) return
    this.cursorPos = pos
    if (pos == null) {
      this.element.parentNode.removeChild(this.element)
      this.element = null
    } else {
      this.updateOverlay()
    }
  }

  updateOverlay() {
    let $pos = this.editorView.state.doc.resolve(this.cursorPos), rect
    if (!$pos.parent.inlineContent) {
      let before = $pos.nodeBefore, after = $pos.nodeAfter
      if (before || after) {
        let nodeRect = this.editorView.nodeDOM(this.cursorPos - (before ?  before.nodeSize : 0)).getBoundingClientRect()
        let top = before ? nodeRect.bottom : nodeRect.top
        if (before && after)
          top = (top + this.editorView.nodeDOM(this.cursorPos).getBoundingClientRect().top) / 2
        rect = {left: nodeRect.left, right: nodeRect.right, top: top - this.width / 2, bottom: top + this.width / 2}
      }
    }
    if (!rect) {
      let coords = this.editorView.coordsAtPos(this.cursorPos)
      rect = {left: coords.left - this.width / 2, right: coords.left + this.width / 2, top: coords.top, bottom: coords.bottom}
    }

    let parent = this.editorView.dom.offsetParent
    if (!this.element) {
      this.element = parent.appendChild(document.createElement("div"))
      this.element.style.cssText = "position: absolute; z-index: 50; pointer-events: none; background-color: " + this.color
    }
    let parentRect = parent == document.body && getComputedStyle(parent).position == "static"
        ? {left: -pageXOffset, top: -pageYOffset} : parent.getBoundingClientRect()
    this.element.style.left = (rect.left - parentRect.left) + "px"
    this.element.style.top = (rect.top - parentRect.top) + "px"
    this.element.style.width = (rect.right - rect.left) + "px"
    this.element.style.height = (rect.bottom - rect.top) + "px"
  }

  scheduleRemoval(timeout) {
    clearTimeout(this.timeout)
    this.timeout = setTimeout(() => this.setCursor(null), timeout)
  }

  dragover(event) {
    if (!this.editorView.editable) return
    let pos = this.editorView.posAtCoords({left: event.clientX, top: event.clientY})
    if (pos) {
      let target = pos.pos
      if (this.editorView.dragging && this.editorView.dragging.slice) {
        target = dropPoint(this.editorView.state.doc, target, this.editorView.dragging.slice)
        if (target == null) target = pos.pos
      }
      this.setCursor(target)
      this.scheduleRemoval(5000)
    }
  }

  dragend() {
    this.scheduleRemoval(20)
  }

  drop() {
    this.scheduleRemoval(20)
  }

  dragleave(event) {
    if (event.target == this.editorView.dom || !this.editorView.dom.contains(event.relatedTarget))
      this.setCursor(null)
  }
}
<|endoftext|>


<commit_before>/**
 * echarts-gl
 * Extension pack of ECharts providing 3d plots and globe visualization
 *
 * Copyright (c) 2014, echarts-gl
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * @module echarts-gl
 * @author Yi Shen(http://github.com/pissang)
 */

// PENDING Use a single canvas as layer or use image element?
var echartsGl = {
    version: '1.0.0',
    dependencies: {
        echarts: '3.4.0',
        qtek: '0.3.0'
    }
};
var echarts = require('echarts/lib/echarts');
var qtekVersion = require('qtek/lib/version');
var LayerGL = require('./core/LayerGL');

// Version checking
var deps = echartsGl.dependencies;
function versionTooOldMsg(name) {
    throw new Error(
        name + ' version is too old, needs ' + deps[name] + ' or higher'
    );
}
function checkVersion(version, name) {
    if ((version.replace('.', '') - 0) < (deps[name].replace('.', '') - 0)) {
        versionTooOldMsg(name);
    }
    console.log('Loaded ' + name + ', version ' + version);
}
checkVersion(qtekVersion, 'qtek');
checkVersion(echarts.version, 'echarts');

function EChartsGL (zr) {
    this._layers = {};

    this._zr = zr;
}

EChartsGL.prototype.update = function (ecModel, api) {
    var self = this;
    var zr = api.getZr();

    function getLayerGL(model) {
        var zlevel = model.get('zlevel');
        var layers = self._layers;
        var layerGL = layers[zlevel];
        if (!layerGL) {
            layerGL = layers[zlevel] = new LayerGL('gl-' + zlevel, zr);

            if (zr.painter.isSingleCanvas()) {
                layerGL.virtual = true;
                // If container is canvas, use image to represent LayerGL
                // FIXME Performance
                var img = new echarts.graphic.Image({
                    z: 1e4,
                    style: {
                        image: layerGL.renderer.canvas
                    },
                    silent: true
                });
                layerGL.__hostImage = img;

                zr.add(img);
            }

            zr.painter.insertLayer(zlevel, layerGL);
        }
        if (layerGL.__hostImage) {
            layerGL.__hostImage.setStyle({
                width: layerGL.renderer.getWidth(),
                height: layerGL.renderer.getHeight()
            });
        }

        return layerGL;
    }

    for (var zlevel in this._layers) {
        this._layers[zlevel].removeViewsAll();
    }

    ecModel.eachComponent(function (componentType, componentModel) {
        if (componentType !== 'series') {
            var view = api.getViewOfComponentModel(componentModel);
            var coordSys = componentModel.coordinateSystem;
            // View with __ecgl__ flag is a echarts-gl component.
            if (view.__ecgl__) {
                var viewGL;
                if (coordSys) {
                    if (!coordSys.viewGL) {
                        console.error('Can\'t find viewGL in coordinateSystem of component ' + componentModel.id);
                        return;
                    }
                    viewGL = coordSys.viewGL;
                }
                else {
                    if (!componentModel.viewGL) {
                        console.error('Can\'t find viewGL of component ' + componentModel.id);
                        return;
                    }
                    viewGL = coordSys.viewGL;
                }

                var viewGL = coordSys.viewGL;
                var layerGL = getLayerGL(componentModel);

                layerGL.addView(viewGL);

                view.afterRender && view.afterRender(
                    componentModel, ecModel, api, layerGL
                );
            }
        }
    });

    ecModel.eachSeries(function (seriesModel) {
        var chartView = api.getViewOfSeriesModel(seriesModel);
        var coordSys = seriesModel.coordinateSystem;
        if (chartView.__ecgl__) {
            if ((coordSys && !coordSys.viewGL) && !chartView.viewGL) {
                console.error('Can\'t find viewGL of series ' + chartView.id);
                return;
            }
            var viewGL = (coordSys && coordSys.viewGL) || chartView.viewGL;
            // TODO Check zlevel not same with component of coordinate system ?
            var layerGL = getLayerGL(seriesModel);
            layerGL.addView(viewGL);

            chartView.afterRender && chartView.afterRender(
                seriesModel, ecModel, api, layerGL
            );
        }
    });
};

echarts.registerPostUpdate(function (ecModel, api) {
    var zr = api.getZr();

    var egl = zr.__egl = zr.__egl || new EChartsGL(zr);

    egl.update(ecModel, api);
});

var Shader = require('qtek/lib/Shader');

module.exports = EChartsGL;<commit_msg>Support silent configuration<commit_after>/**
 * echarts-gl
 * Extension pack of ECharts providing 3d plots and globe visualization
 *
 * Copyright (c) 2014, echarts-gl
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * @module echarts-gl
 * @author Yi Shen(http://github.com/pissang)
 */

// PENDING Use a single canvas as layer or use image element?
var echartsGl = {
    version: '1.0.0',
    dependencies: {
        echarts: '3.4.0',
        qtek: '0.3.0'
    }
};
var echarts = require('echarts/lib/echarts');
var qtekVersion = require('qtek/lib/version');
var LayerGL = require('./core/LayerGL');

// Version checking
var deps = echartsGl.dependencies;
function versionTooOldMsg(name) {
    throw new Error(
        name + ' version is too old, needs ' + deps[name] + ' or higher'
    );
}
function checkVersion(version, name) {
    if ((version.replace('.', '') - 0) < (deps[name].replace('.', '') - 0)) {
        versionTooOldMsg(name);
    }
    console.log('Loaded ' + name + ', version ' + version);
}
checkVersion(qtekVersion, 'qtek');
checkVersion(echarts.version, 'echarts');

function EChartsGL (zr) {
    this._layers = {};

    this._zr = zr;
}

EChartsGL.prototype.update = function (ecModel, api) {
    var self = this;
    var zr = api.getZr();

    function getLayerGL(model) {
        var zlevel = model.get('zlevel');
        var layers = self._layers;
        var layerGL = layers[zlevel];
        if (!layerGL) {
            layerGL = layers[zlevel] = new LayerGL('gl-' + zlevel, zr);

            if (zr.painter.isSingleCanvas()) {
                layerGL.virtual = true;
                // If container is canvas, use image to represent LayerGL
                // FIXME Performance
                var img = new echarts.graphic.Image({
                    z: 1e4,
                    style: {
                        image: layerGL.renderer.canvas
                    },
                    silent: true
                });
                layerGL.__hostImage = img;

                zr.add(img);
            }

            zr.painter.insertLayer(zlevel, layerGL);
        }
        if (layerGL.__hostImage) {
            layerGL.__hostImage.setStyle({
                width: layerGL.renderer.getWidth(),
                height: layerGL.renderer.getHeight()
            });
        }

        return layerGL;
    }

    for (var zlevel in this._layers) {
        this._layers[zlevel].removeViewsAll();
    }

    ecModel.eachComponent(function (componentType, componentModel) {
        if (componentType !== 'series') {
            var view = api.getViewOfComponentModel(componentModel);
            var coordSys = componentModel.coordinateSystem;
            // View with __ecgl__ flag is a echarts-gl component.
            if (view.__ecgl__) {
                var viewGL;
                if (coordSys) {
                    if (!coordSys.viewGL) {
                        console.error('Can\'t find viewGL in coordinateSystem of component ' + componentModel.id);
                        return;
                    }
                    viewGL = coordSys.viewGL;
                }
                else {
                    if (!componentModel.viewGL) {
                        console.error('Can\'t find viewGL of component ' + componentModel.id);
                        return;
                    }
                    viewGL = coordSys.viewGL;
                }

                var viewGL = coordSys.viewGL;
                var layerGL = getLayerGL(componentModel);

                layerGL.addView(viewGL);

                view.afterRender && view.afterRender(
                    componentModel, ecModel, api, layerGL
                );
            }
        }
    });

    ecModel.eachSeries(function (seriesModel) {
        var chartView = api.getViewOfSeriesModel(seriesModel);
        var coordSys = seriesModel.coordinateSystem;
        if (chartView.__ecgl__) {
            if ((coordSys && !coordSys.viewGL) && !chartView.viewGL) {
                console.error('Can\'t find viewGL of series ' + chartView.id);
                return;
            }
            var viewGL = (coordSys && coordSys.viewGL) || chartView.viewGL;
            // TODO Check zlevel not same with component of coordinate system ?
            var layerGL = getLayerGL(seriesModel);
            layerGL.addView(viewGL);

            chartView.afterRender && chartView.afterRender(
                seriesModel, ecModel, api, layerGL
            );

            var silent = seriesModel.get('silent');
            chartView.groupGL && chartView.groupGL.traverse(function (node) {
                node.ignorePicking = silent;
            });
        }
    });
};

echarts.registerPostUpdate(function (ecModel, api) {
    var zr = api.getZr();

    var egl = zr.__egl = zr.__egl || new EChartsGL(zr);

    egl.update(ecModel, api);
});

var Shader = require('qtek/lib/Shader');

module.exports = EChartsGL;<|endoftext|>


<commit_before>import {Pos} from "../model"

import {fromHTML} from "../parse/dom"
import {fromText} from "../parse/text"
import {elt} from "../dom"
import {toHTML} from "../serialize/dom"
import {toText} from "../serialize/text"
import {knownSource, parseFrom} from "../parse"

import {isModifierKey, keyName} from "./keys"
import {captureKeys} from "./capturekeys"
import {browser, addClass, rmClass} from "../dom"
import {applyDOMChange, textContext, textInContext} from "./domchange"
import {TextSelection, coordsAtPos, rangeFromDOMLoose, selectableNodeAbove,
        findSelectionAtStart, findSelectionAtEnd} from "./selection"

let stopSeq = null

/**
 * A collection of DOM events that occur within the editor, and callback functions
 * to invoke when the event fires.
 */
const handlers = {}

export class Input {
  constructor(pm) {
    this.pm = pm

    this.keySeq = null

    // When the user is creating a composed character,
    // this is set to a Composing instance.
    this.composing = null
    this.shiftKey = this.updatingComposition = false
    this.skipInput = 0

    this.draggingFrom = false

    this.keymaps = []

    this.storedMarks = null

    this.dropTarget = pm.wrapper.appendChild(elt("div", {class: "ProseMirror-drop-target"}))

    for (let event in handlers) {
      let handler = handlers[event]
      pm.content.addEventListener(event, e => handler(pm, e))
    }

    pm.on("selectionChange", () => this.storedMarks = null)
  }

  maybeAbortComposition() {
    if (this.composing && !this.updatingComposition) {
      if (this.composing.finished) {
        finishComposing(this.pm)
      } else { // Toggle selection to force end of composition
        this.composing = null
        this.skipInput++
        let sel = getSelection()
        if (sel.rangeCount) {
          let range = sel.getRangeAt(0)
          sel.removeAllRanges()
          sel.addRange(range)
        }
      }
      return true
    }
  }
}

/**
 * Dispatch a key press to the internal keymaps, which will override the default
 * DOM behavior.
 *
 * @param  {ProseMirror}   pm The editor instance.
 * @param  {string}        name The name of the key pressed.
 * @param  {KeyboardEvent} e
 * @return {string} If the key name has a mapping and the callback is invoked ("handled"),
 *                  if the key name needs to be combined in sequence with the next key ("multi"),
 *                  if there is no mapping ("nothing").
 */
export function dispatchKey(pm, name, e) {
  let seq = pm.input.keySeq
  // If the previous key should be used in sequence with this one, modify the name accordingly.
  if (seq) {
    if (isModifierKey(name)) return true
    clearTimeout(stopSeq)
    stopSeq = setTimeout(function() {
      if (pm.input.keySeq == seq)
        pm.input.keySeq = null
    }, 50)
    name = seq + " " + name
  }

  let handle = function(bound) {
    if (bound === false) return "nothing"
    if (bound == "...") return "multi"
    if (bound == null) return false

    let result = false
    if (Array.isArray(bound)) {
      for (let i = 0; result === false && i < bound.length; i++)
        result = handle(bound[i])
    } else if (typeof bound == "string") {
      result = pm.execCommand(bound)
    } else {
      result = bound(pm)
    }
    return result
  }

  let result
  for (let i = 0; !result && i < pm.input.keymaps.length; i++)
    result = handle(pm.input.keymaps[i].map.lookup(name, pm))
  if (!result)
    result = handle(pm.options.keymap.lookup(name, pm))

  // If the key should be used in sequence with the next key, store the keyname internally.
  if (result == "multi")
    pm.input.keySeq = name

  if (result == "handled" || result == "multi")
    e.preventDefault()

  if (seq && !result && /\'$/.test(name)) {
    e.preventDefault()
    return true
  }
  return !!result
}

handlers.keydown = (pm, e) => {
  if (e.keyCode == 16) pm.input.shiftKey = true
  if (pm.input.composing) return
  let name = keyName(e)
  if (name && dispatchKey(pm, name, e)) return
  pm.sel.pollForUpdate()
}

handlers.keyup = (pm, e) => {
  if (e.keyCode == 16) pm.input.shiftKey = false
}

function inputText(pm, range, text) {
  if (range.empty && !text) return false
  let marks = pm.input.storedMarks || pm.doc.marksAt(range.from)
  let tr = pm.tr
  tr.replaceWith(range.from, range.to, pm.schema.text(text, marks)).apply()
  pm.scrollIntoView()
  // :: () #path=ProseMirror#events#textInput
  // Fired when the user types text into the editor.
  pm.signal("textInput", text)
}

handlers.keypress = (pm, e) => {
  if (pm.input.composing || !e.charCode || e.ctrlKey && !e.altKey || browser.mac && e.metaKey) return
  let ch = String.fromCharCode(e.charCode)
  if (dispatchKey(pm, "'" + ch + "'", e)) return
  let sel = pm.selection
  if (sel.node && sel.node.contains == null) {
    pm.tr.delete(sel.from, sel.to).apply()
    sel = pm.selection
  }
  inputText(pm, sel, ch)
  e.preventDefault()
}

function selectClickedNode(pm, e) {
  let pos = selectableNodeAbove(pm, e.target, {left: e.clientX, top: e.clientY}, true)
  if (!pos) return pm.sel.pollForUpdate()

  let {node, from} = pm.selection
  if (node && pos.depth >= from.depth && pos.shorten(from.depth).cmp(from) == 0) {
    if (from.depth == 0) return pm.sel.pollForUpdate()
    pos = from.shorten()
  }

  pm.setNodeSelection(pos)
  pm.focus()
  e.preventDefault()
}

let lastClick = 0

handlers.mousedown = (pm, e) => {
  if (e.ctrlKey)
    return selectClickedNode(pm, e)

  pm.sel.pollForUpdate()

  let now = Date.now(), multi = now - lastClick < 500
  lastClick = now
  if (pm.input.shiftKey || multi) return

  let x = e.clientX, y = e.clientY
  let done = () => {
    removeEventListener("mouseup", up)
    removeEventListener("mousemove", move)
  }
  let up = () => {
    done()
    let pos = selectableNodeAbove(pm, e.target, {left: e.clientX, top: e.clientY})
    if (pos) {
      pm.setNodeSelection(pos)
      pm.focus()
    }
  }
  let move = e => {
    if (Math.abs(x - e.clientX) > 4 || Math.abs(y - e.clientY) > 4) done()
  }
  addEventListener("mouseup", up)
  addEventListener("mousemove", move)
}

handlers.touchdown = pm => {
  pm.sel.pollForUpdate()
}

handlers.mousemove = (pm, e) => {
  if (e.which || e.button) pm.sel.pollForUpdate()
}

/**
 * A class to track state while creating a composed character.
 */
class Composing {
  constructor(pm, data) {
    this.finished = false
    this.context = textContext(data)
    this.data = data
    this.endData = null
    let range = pm.selection
    if (data) {
      let path = range.head.path, line = pm.doc.path(path).textContent
      let found = line.indexOf(data, range.head.offset - data.length)
      if (found > -1 && found <= range.head.offset + data.length)
        range = new TextSelection(new Pos(path, found), new Pos(path, found + data.length))
    }
    this.range = range
  }
}

handlers.compositionstart = (pm, e) => {
  if (pm.input.maybeAbortComposition()) return

  pm.flush()
  pm.input.composing = new Composing(pm, e.data)
  let above = pm.selection.head.shorten()
  pm.markRangeDirty({from: above, to: above.move(1)})
}

handlers.compositionupdate = (pm, e) => {
  let info = pm.input.composing
  if (info && info.data != e.data) {
    info.data = e.data
    pm.input.updatingComposition = true
    inputText(pm, info.range, info.data)
    pm.input.updatingComposition = false
    info.range = new TextSelection(info.range.from, info.range.from.move(info.data.length))
  }
}

handlers.compositionend = (pm, e) => {
  let info = pm.input.composing
  if (info) {
    pm.input.composing.finished = true
    pm.input.composing.endData = e.data
    setTimeout(() => {if (pm.input.composing == info) finishComposing(pm)}, 20)
  }
}

function finishComposing(pm) {
  let info = pm.input.composing
  let text = textInContext(info.context, info.endData)
  let range = rangeFromDOMLoose(pm)
  pm.ensureOperation()
  pm.input.composing = null
  if (text != info.data) inputText(pm, info.range, text)
  if (range && !range.eq(pm.sel.range)) pm.setSelectionDirect(range)
}

handlers.input = (pm) => {
  if (pm.input.skipInput) return --pm.input.skipInput

  if (pm.input.composing) {
    if (pm.input.composing.finished) finishComposing(pm)
    return
  }

  applyDOMChange(pm)
  pm.scrollIntoView()
}

let lastCopied = null

handlers.copy = handlers.cut = (pm, e) => {
  let {from, to, empty} = pm.selection
  if (empty) return
  let fragment = pm.selectedDoc
  lastCopied = {doc: pm.doc, from, to,
                html: toHTML(fragment),
                text: toText(fragment)}

  if (e.clipboardData) {
    e.preventDefault()
    e.clipboardData.clearData()
    e.clipboardData.setData("text/html", lastCopied.html)
    e.clipboardData.setData("text/plain", lastCopied.text)
    if (e.type == "cut" && !empty)
      pm.tr.delete(from, to).apply()
  }
}

handlers.paste = (pm, e) => {
  if (!e.clipboardData) return
  let sel = pm.selection
  let txt = e.clipboardData.getData("text/plain")
  let html = e.clipboardData.getData("text/html")
  if (html || txt) {
    e.preventDefault()
    let doc, from, to
    if (pm.input.shiftKey && txt) {
      doc = fromText(pm.schema, txt)
    } else if (lastCopied && (lastCopied.html == html || lastCopied.text == txt)) {
      ;({doc, from, to} = lastCopied)
    } else if (html) {
      doc = fromHTML(pm.schema, html)
    } else {
      doc = parseFrom(pm.schema, txt, knownSource("markdown") ? "markdown" : "text")
    }
    pm.tr.replace(sel.from, sel.to, doc, from || findSelectionAtStart(doc).from,
                  to || findSelectionAtEnd(doc).to).apply()
    pm.scrollIntoView()
  }
}

handlers.dragstart = (pm, e) => {
  if (!e.dataTransfer) return

  let fragment = pm.selectedDoc

  e.dataTransfer.setData("text/html", toHTML(fragment))
  e.dataTransfer.setData("text/plain", toText(fragment))
  pm.input.draggingFrom = true
}

handlers.dragend = pm => window.setTimeout(() => pm.input.dragginFrom = false, 50)

handlers.dragover = handlers.dragenter = (pm, e) => {
  e.preventDefault()
  let cursorPos = pm.posAtCoords({left: e.clientX, top: e.clientY})
  if (!cursorPos) return
  let coords = coordsAtPos(pm, cursorPos)
  let rect = pm.wrapper.getBoundingClientRect()
  coords.top -= rect.top
  coords.right -= rect.left
  coords.bottom -= rect.top
  coords.left -= rect.left
  let target = pm.input.dropTarget
  target.style.display = "block"
  target.style.left = (coords.left - 1) + "px"
  target.style.top = coords.top + "px"
  target.style.height = (coords.bottom - coords.top) + "px"
}

handlers.dragleave = pm => pm.input.dropTarget.style.display = ""

handlers.drop = (pm, e) => {
  pm.input.dropTarget.style.display = ""

  if (!e.dataTransfer) return

  let html, txt, doc
  if (html = e.dataTransfer.getData("text/html"))
    doc = fromHTML(pm.schema, html, {document})
  else if (txt = e.dataTransfer.getData("text/plain"))
    doc = parseFrom(pm.schema, txt, knownSource("markdown") ? "markdown" : "text")

  if (doc) {
    e.preventDefault()
    let insertPos = pm.posAtCoords({left: e.clientX, top: e.clientY})
    if (!insertPos) return
    let tr = pm.tr
    if (pm.input.draggingFrom && !e.ctrlKey) {
      tr.deleteSelection()
      insertPos = tr.map(insertPos).pos
    }
    tr.replace(insertPos, insertPos, doc, findSelectionAtStart(doc).from, findSelectionAtEnd(doc).to).apply()
    pm.setTextSelection(insertPos, tr.map(insertPos).pos)
    pm.focus()
  }
}

handlers.focus = pm => {
  addClass(pm.wrapper, "ProseMirror-focused")
  // :: () #path=ProseMirror#events#focus
  // Fired when the editor gains focus.
  pm.signal("focus")
}

handlers.blur = pm => {
  rmClass(pm.wrapper, "ProseMirror-focused")
  // :: () #path=ProseMirror#events#blur
  // Fired when the editor loses focus.
  pm.signal("blur")
}
<commit_msg>Fix capturing of dangerous keys<commit_after>import {Pos} from "../model"

import {fromHTML} from "../parse/dom"
import {fromText} from "../parse/text"
import {elt} from "../dom"
import {toHTML} from "../serialize/dom"
import {toText} from "../serialize/text"
import {knownSource, parseFrom} from "../parse"

import {isModifierKey, keyName} from "./keys"
import {captureKeys} from "./capturekeys"
import {browser, addClass, rmClass} from "../dom"
import {applyDOMChange, textContext, textInContext} from "./domchange"
import {TextSelection, coordsAtPos, rangeFromDOMLoose, selectableNodeAbove,
        findSelectionAtStart, findSelectionAtEnd} from "./selection"

let stopSeq = null

/**
 * A collection of DOM events that occur within the editor, and callback functions
 * to invoke when the event fires.
 */
const handlers = {}

export class Input {
  constructor(pm) {
    this.pm = pm

    this.keySeq = null

    // When the user is creating a composed character,
    // this is set to a Composing instance.
    this.composing = null
    this.shiftKey = this.updatingComposition = false
    this.skipInput = 0

    this.draggingFrom = false

    this.keymaps = []

    this.storedMarks = null

    this.dropTarget = pm.wrapper.appendChild(elt("div", {class: "ProseMirror-drop-target"}))

    for (let event in handlers) {
      let handler = handlers[event]
      pm.content.addEventListener(event, e => handler(pm, e))
    }

    pm.on("selectionChange", () => this.storedMarks = null)
  }

  maybeAbortComposition() {
    if (this.composing && !this.updatingComposition) {
      if (this.composing.finished) {
        finishComposing(this.pm)
      } else { // Toggle selection to force end of composition
        this.composing = null
        this.skipInput++
        let sel = getSelection()
        if (sel.rangeCount) {
          let range = sel.getRangeAt(0)
          sel.removeAllRanges()
          sel.addRange(range)
        }
      }
      return true
    }
  }
}

/**
 * Dispatch a key press to the internal keymaps, which will override the default
 * DOM behavior.
 *
 * @param  {ProseMirror}   pm The editor instance.
 * @param  {string}        name The name of the key pressed.
 * @param  {KeyboardEvent} e
 * @return {string} If the key name has a mapping and the callback is invoked ("handled"),
 *                  if the key name needs to be combined in sequence with the next key ("multi"),
 *                  if there is no mapping ("nothing").
 */
export function dispatchKey(pm, name, e) {
  let seq = pm.input.keySeq
  // If the previous key should be used in sequence with this one, modify the name accordingly.
  if (seq) {
    if (isModifierKey(name)) return true
    clearTimeout(stopSeq)
    stopSeq = setTimeout(function() {
      if (pm.input.keySeq == seq)
        pm.input.keySeq = null
    }, 50)
    name = seq + " " + name
  }

  let handle = function(bound) {
    if (bound === false) return "nothing"
    if (bound == "...") return "multi"
    if (bound == null) return false

    let result = false
    if (Array.isArray(bound)) {
      for (let i = 0; result === false && i < bound.length; i++)
        result = handle(bound[i])
    } else if (typeof bound == "string") {
      result = pm.execCommand(bound)
    } else {
      result = bound(pm)
    }
    return result
  }

  let result
  for (let i = 0; !result && i < pm.input.keymaps.length; i++)
    result = handle(pm.input.keymaps[i].map.lookup(name, pm))
  if (!result)
    result = handle(pm.options.keymap.lookup(name, pm)) || handle(captureKeys.lookup(name))

  // If the key should be used in sequence with the next key, store the keyname internally.
  if (result == "multi")
    pm.input.keySeq = name

  if (result == "handled" || result == "multi")
    e.preventDefault()

  if (seq && !result && /\'$/.test(name)) {
    e.preventDefault()
    return true
  }
  return !!result
}

handlers.keydown = (pm, e) => {
  if (e.keyCode == 16) pm.input.shiftKey = true
  if (pm.input.composing) return
  let name = keyName(e)
  if (name && dispatchKey(pm, name, e)) return
  pm.sel.pollForUpdate()
}

handlers.keyup = (pm, e) => {
  if (e.keyCode == 16) pm.input.shiftKey = false
}

function inputText(pm, range, text) {
  if (range.empty && !text) return false
  let marks = pm.input.storedMarks || pm.doc.marksAt(range.from)
  let tr = pm.tr
  tr.replaceWith(range.from, range.to, pm.schema.text(text, marks)).apply()
  pm.scrollIntoView()
  // :: () #path=ProseMirror#events#textInput
  // Fired when the user types text into the editor.
  pm.signal("textInput", text)
}

handlers.keypress = (pm, e) => {
  if (pm.input.composing || !e.charCode || e.ctrlKey && !e.altKey || browser.mac && e.metaKey) return
  let ch = String.fromCharCode(e.charCode)
  if (dispatchKey(pm, "'" + ch + "'", e)) return
  let sel = pm.selection
  if (sel.node && sel.node.contains == null) {
    pm.tr.delete(sel.from, sel.to).apply()
    sel = pm.selection
  }
  inputText(pm, sel, ch)
  e.preventDefault()
}

function selectClickedNode(pm, e) {
  let pos = selectableNodeAbove(pm, e.target, {left: e.clientX, top: e.clientY}, true)
  if (!pos) return pm.sel.pollForUpdate()

  let {node, from} = pm.selection
  if (node && pos.depth >= from.depth && pos.shorten(from.depth).cmp(from) == 0) {
    if (from.depth == 0) return pm.sel.pollForUpdate()
    pos = from.shorten()
  }

  pm.setNodeSelection(pos)
  pm.focus()
  e.preventDefault()
}

let lastClick = 0

handlers.mousedown = (pm, e) => {
  if (e.ctrlKey)
    return selectClickedNode(pm, e)

  pm.sel.pollForUpdate()

  let now = Date.now(), multi = now - lastClick < 500
  lastClick = now
  if (pm.input.shiftKey || multi) return

  let x = e.clientX, y = e.clientY
  let done = () => {
    removeEventListener("mouseup", up)
    removeEventListener("mousemove", move)
  }
  let up = () => {
    done()
    let pos = selectableNodeAbove(pm, e.target, {left: e.clientX, top: e.clientY})
    if (pos) {
      pm.setNodeSelection(pos)
      pm.focus()
    }
  }
  let move = e => {
    if (Math.abs(x - e.clientX) > 4 || Math.abs(y - e.clientY) > 4) done()
  }
  addEventListener("mouseup", up)
  addEventListener("mousemove", move)
}

handlers.touchdown = pm => {
  pm.sel.pollForUpdate()
}

handlers.mousemove = (pm, e) => {
  if (e.which || e.button) pm.sel.pollForUpdate()
}

/**
 * A class to track state while creating a composed character.
 */
class Composing {
  constructor(pm, data) {
    this.finished = false
    this.context = textContext(data)
    this.data = data
    this.endData = null
    let range = pm.selection
    if (data) {
      let path = range.head.path, line = pm.doc.path(path).textContent
      let found = line.indexOf(data, range.head.offset - data.length)
      if (found > -1 && found <= range.head.offset + data.length)
        range = new TextSelection(new Pos(path, found), new Pos(path, found + data.length))
    }
    this.range = range
  }
}

handlers.compositionstart = (pm, e) => {
  if (pm.input.maybeAbortComposition()) return

  pm.flush()
  pm.input.composing = new Composing(pm, e.data)
  let above = pm.selection.head.shorten()
  pm.markRangeDirty({from: above, to: above.move(1)})
}

handlers.compositionupdate = (pm, e) => {
  let info = pm.input.composing
  if (info && info.data != e.data) {
    info.data = e.data
    pm.input.updatingComposition = true
    inputText(pm, info.range, info.data)
    pm.input.updatingComposition = false
    info.range = new TextSelection(info.range.from, info.range.from.move(info.data.length))
  }
}

handlers.compositionend = (pm, e) => {
  let info = pm.input.composing
  if (info) {
    pm.input.composing.finished = true
    pm.input.composing.endData = e.data
    setTimeout(() => {if (pm.input.composing == info) finishComposing(pm)}, 20)
  }
}

function finishComposing(pm) {
  let info = pm.input.composing
  let text = textInContext(info.context, info.endData)
  let range = rangeFromDOMLoose(pm)
  pm.ensureOperation()
  pm.input.composing = null
  if (text != info.data) inputText(pm, info.range, text)
  if (range && !range.eq(pm.sel.range)) pm.setSelectionDirect(range)
}

handlers.input = (pm) => {
  if (pm.input.skipInput) return --pm.input.skipInput

  if (pm.input.composing) {
    if (pm.input.composing.finished) finishComposing(pm)
    return
  }

  applyDOMChange(pm)
  pm.scrollIntoView()
}

let lastCopied = null

handlers.copy = handlers.cut = (pm, e) => {
  let {from, to, empty} = pm.selection
  if (empty) return
  let fragment = pm.selectedDoc
  lastCopied = {doc: pm.doc, from, to,
                html: toHTML(fragment),
                text: toText(fragment)}

  if (e.clipboardData) {
    e.preventDefault()
    e.clipboardData.clearData()
    e.clipboardData.setData("text/html", lastCopied.html)
    e.clipboardData.setData("text/plain", lastCopied.text)
    if (e.type == "cut" && !empty)
      pm.tr.delete(from, to).apply()
  }
}

handlers.paste = (pm, e) => {
  if (!e.clipboardData) return
  let sel = pm.selection
  let txt = e.clipboardData.getData("text/plain")
  let html = e.clipboardData.getData("text/html")
  if (html || txt) {
    e.preventDefault()
    let doc, from, to
    if (pm.input.shiftKey && txt) {
      doc = fromText(pm.schema, txt)
    } else if (lastCopied && (lastCopied.html == html || lastCopied.text == txt)) {
      ;({doc, from, to} = lastCopied)
    } else if (html) {
      doc = fromHTML(pm.schema, html)
    } else {
      doc = parseFrom(pm.schema, txt, knownSource("markdown") ? "markdown" : "text")
    }
    pm.tr.replace(sel.from, sel.to, doc, from || findSelectionAtStart(doc).from,
                  to || findSelectionAtEnd(doc).to).apply()
    pm.scrollIntoView()
  }
}

handlers.dragstart = (pm, e) => {
  if (!e.dataTransfer) return

  let fragment = pm.selectedDoc

  e.dataTransfer.setData("text/html", toHTML(fragment))
  e.dataTransfer.setData("text/plain", toText(fragment))
  pm.input.draggingFrom = true
}

handlers.dragend = pm => window.setTimeout(() => pm.input.dragginFrom = false, 50)

handlers.dragover = handlers.dragenter = (pm, e) => {
  e.preventDefault()
  let cursorPos = pm.posAtCoords({left: e.clientX, top: e.clientY})
  if (!cursorPos) return
  let coords = coordsAtPos(pm, cursorPos)
  let rect = pm.wrapper.getBoundingClientRect()
  coords.top -= rect.top
  coords.right -= rect.left
  coords.bottom -= rect.top
  coords.left -= rect.left
  let target = pm.input.dropTarget
  target.style.display = "block"
  target.style.left = (coords.left - 1) + "px"
  target.style.top = coords.top + "px"
  target.style.height = (coords.bottom - coords.top) + "px"
}

handlers.dragleave = pm => pm.input.dropTarget.style.display = ""

handlers.drop = (pm, e) => {
  pm.input.dropTarget.style.display = ""

  if (!e.dataTransfer) return

  let html, txt, doc
  if (html = e.dataTransfer.getData("text/html"))
    doc = fromHTML(pm.schema, html, {document})
  else if (txt = e.dataTransfer.getData("text/plain"))
    doc = parseFrom(pm.schema, txt, knownSource("markdown") ? "markdown" : "text")

  if (doc) {
    e.preventDefault()
    let insertPos = pm.posAtCoords({left: e.clientX, top: e.clientY})
    if (!insertPos) return
    let tr = pm.tr
    if (pm.input.draggingFrom && !e.ctrlKey) {
      tr.deleteSelection()
      insertPos = tr.map(insertPos).pos
    }
    tr.replace(insertPos, insertPos, doc, findSelectionAtStart(doc).from, findSelectionAtEnd(doc).to).apply()
    pm.setTextSelection(insertPos, tr.map(insertPos).pos)
    pm.focus()
  }
}

handlers.focus = pm => {
  addClass(pm.wrapper, "ProseMirror-focused")
  // :: () #path=ProseMirror#events#focus
  // Fired when the editor gains focus.
  pm.signal("focus")
}

handlers.blur = pm => {
  rmClass(pm.wrapper, "ProseMirror-focused")
  // :: () #path=ProseMirror#events#blur
  // Fired when the editor loses focus.
  pm.signal("blur")
}
<|endoftext|>


<commit_before>/*
  Ported to JavaScript by Lazar Laszlo 2011

  lazarsoft@gmail.com, www.lazarsoft.info

*/

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

function ErrorCorrectionLevel(ordinal,  bits, name)
{
	this.ordinal_Renamed_Field = ordinal;
	this.bits = bits;
	this.name = name;
	this.__defineGetter__("Bits", function()
	{
		return this.bits;
	});
	this.__defineGetter__("Name", function()
	{
		return this.name;
	});
	this.ordinal=function()
	{
		return this.ordinal_Renamed_Field;
	}
}

ErrorCorrectionLevel.forBits=function( bits)
{
	if (bits < 0 || bits >= FOR_BITS.Length)
	{
		throw "ArgumentException";
	}
	return FOR_BITS[bits];
}

var L = new ErrorCorrectionLevel(0, 0x01, "L");
var M = new ErrorCorrectionLevel(1, 0x00, "M");
var Q = new ErrorCorrectionLevel(2, 0x03, "Q");
var H = new ErrorCorrectionLevel(3, 0x02, "H");
var FOR_BITS = new Array( M, L, H, Q);<commit_msg>corrected Length to length<commit_after>/*
  Ported to JavaScript by Lazar Laszlo 2011

  lazarsoft@gmail.com, www.lazarsoft.info

*/

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

function ErrorCorrectionLevel(ordinal,  bits, name)
{
	this.ordinal_Renamed_Field = ordinal;
	this.bits = bits;
	this.name = name;
	this.__defineGetter__("Bits", function()
	{
		return this.bits;
	});
	this.__defineGetter__("Name", function()
	{
		return this.name;
	});
	this.ordinal=function()
	{
		return this.ordinal_Renamed_Field;
	}
}

ErrorCorrectionLevel.forBits=function( bits)
{
	if (bits < 0 || bits >= FOR_BITS.length)
	{
		throw "ArgumentException";
	}
	return FOR_BITS[bits];
}

var L = new ErrorCorrectionLevel(0, 0x01, "L");
var M = new ErrorCorrectionLevel(1, 0x00, "M");
var Q = new ErrorCorrectionLevel(2, 0x03, "Q");
var H = new ErrorCorrectionLevel(3, 0x02, "H");
var FOR_BITS = new Array( M, L, H, Q);
<|endoftext|>


<commit_before>import sha512 from '../../node_modules/sha512/lib/sha512.js'
var raw = window.location.search,
refined = raw.length ? raw.replace('?',''):false,
[...rawQueryData] = refined ? refined.split('&').map((chunk) => chunk.split('=')):false,
queryParams = false;

if (rawQueryData.length) {
  queryParams = {};
  rawQueryData.map((chunk) => queryParams[chunk[0]] = chunk[1]);
}

const config = {
  debug: !!(queryParams && queryParams.debug) || false,
  wireframe: !!(queryParams && queryParams.wireframe) || false,
  autoRotate: !!(queryParams && queryParams.autoRotate) || false,
  w: queryParams && queryParams.w || 720,
  h: queryParams && queryParams.h || 480,
  fov: queryParams && queryParams.fov || 75,
  near: queryParams && queryParams.near || 0.1,
  far: queryParams && queryParams.far || 1000,
  zoom: queryParams && queryParams.zoom || 2,
  levelMax: queryParams && queryParams.levelMax || 0,
  size: parseInt(queryParams && queryParams.size || 4),
  originalSeed: queryParams && queryParams.seed || 'proc.edu.ria'
}
let maxSeedLength = 512/4
let maxSize = 32
config.size = maxSize < config.size ? maxSize:config.size
config.cubicSize = Math.pow(config.size, 3)
var mkSha = (string) => sha512(string).toString('hex')
config.rawSeed = mkSha(config.originalSeed)
while (config.rawSeed.length < config.cubicSize) {
  let rest = config.cubicSize - config.rawSeed.length
  if (config.debug) console.info(`filling up to ${rest} hex chars with seed generated from rawSeed`)
  config.rawSeed += mkSha(config.rawSeed).substr(0, rest)
}

let sizeToUse = 'cubicSize'
config.seed = config.rawSeed.substr(0, config.cubicSize).substr(0, config[sizeToUse])
if (config.debug) console.info('config:', config)
console.info('size', config.size)
console.info('cubicSize', config.cubicSize)
console.info('rawSeed', config.rawSeed.length, config.rawSeed)
console.info('seed', config.seed.length, config.seed)

export default config
<commit_msg>masking config message for debug mode ON only<commit_after>import sha512 from '../../node_modules/sha512/lib/sha512.js'
var raw = window.location.search,
refined = raw.length ? raw.replace('?',''):false,
[...rawQueryData] = refined ? refined.split('&').map((chunk) => chunk.split('=')):false,
queryParams = false;

if (rawQueryData.length) {
  queryParams = {};
  rawQueryData.map((chunk) => queryParams[chunk[0]] = chunk[1]);
}

const config = {
  debug: !!(queryParams && queryParams.debug) || false,
  wireframe: !!(queryParams && queryParams.wireframe) || false,
  autoRotate: !!(queryParams && queryParams.autoRotate) || false,
  w: queryParams && queryParams.w || 720,
  h: queryParams && queryParams.h || 480,
  fov: queryParams && queryParams.fov || 75,
  near: queryParams && queryParams.near || 0.1,
  far: queryParams && queryParams.far || 1000,
  zoom: queryParams && queryParams.zoom || 2,
  levelMax: queryParams && queryParams.levelMax || 0,
  size: parseInt(queryParams && queryParams.size || 4),
  originalSeed: queryParams && queryParams.seed || 'proc.edu.ria'
}
let maxSeedLength = 512/4
let maxSize = 32
config.size = maxSize < config.size ? maxSize:config.size
config.cubicSize = Math.pow(config.size, 3)
var mkSha = (string) => sha512(string).toString('hex')
config.rawSeed = mkSha(config.originalSeed)
while (config.rawSeed.length < config.cubicSize) {
  let rest = config.cubicSize - config.rawSeed.length
  if (config.debug) console.info(`filling up to ${rest} hex chars with seed generated from rawSeed`)
  config.rawSeed += mkSha(config.rawSeed).substr(0, rest)
}

let sizeToUse = 'cubicSize'
config.seed = config.rawSeed.substr(0, config.cubicSize).substr(0, config[sizeToUse])
if (config.debug) {
  console.info('config:', config)
  console.info('size', config.size)
  console.info('cubicSize', config.cubicSize)
  console.info('rawSeed', config.rawSeed.length, config.rawSeed)
  console.info('seed', config.seed.length, config.seed)
}

export default config
<|endoftext|>


<commit_before>/**
 * a form verfiy tool
 *
 * Author by robinma
 *
 *formFilter([form jQObj | seletor],fieldConfig)
 *
 *fieldConfig:
 *require:[false|true] imperactive
 */

(function(root, factory) {
  //set up formFilter appropriately for the enviroment.
  if (typeof define === 'function' && (define.cmd || define.amd)) {
    define(function() {
      return factory();
    });
  } else {
    //as a browser global
    root.formFilter = factory();
  }

})(this, function() {

  var objproto = Object.prototype;
  var tostring = objproto.toString;

  var pubsub = {
    _handlers: '',
    on: function(etype, handler) {
      if (typeof this._handlers !== 'object') {
        this._handlers = [];
      }
      if (!this._handlers[etype]) {
        this._handlers[etype] = []
      }
      if (typeof handler === 'function') {
        this._handlers[etype].push(handler)
      }
      return this;
    },
    emit: function(etype) {
      var args = Array.prototype.slice.call(arguments, 1)
      var handlers = this._handlers[etype] || [];
      for (var i = 0, l = handlers.length; i < l; i++) {
        handlers[i].apply(null, args)
      }
      return this;
    }
  };

  //formFilter constracter
  var formFilter = function() {
    var arg = arguments;
    var argLen = arg.length;
    var params;
    var el;
    if (argLen >= 2) {
      el = arg[0];
      params = arg[1];
    } else if (argLen == 1) {
      el = 'body';
      params = arg[0];
    }
    this.$el = (typeof el === 'object' ? el : $(el));
    params = params || {};
    //field array
    this.fieldArr = [];
    this.fieldObj = {};
    this._init(params);

  };

  //extend method
  $.extend(formFilter.prototype, pubsub, {
    //formFilter version Number
    version: '0.0.1',
    //formFilter init
    _init: function(params) {
      if (typeof params === 'object') {
        this._traversal(params);
      }
    },
    //traversal user config and push field object to fieldArr
    _traversal: function(params) {
      var __ = this,
        _paramLen = 0;
      $.each(params, function(k, v) {
        //new a field object
        var field = new Field({
            el: k.replace(/^\s*|\s*$/ig, ''),
            $el: __.get$Obj(k),
            config: v,
            groupField: __.fieldObj,
            parent:__
          })
          //push field Object to field array
        __.fieldObj[k] = field;

        __.fieldArr.push(field);

        _paramLen++;
      })
      //record field length
      __.fieldLength = _paramLen;
    },
    //get form input jquery Obj
    get$Obj: function(seletor) {
      return this.$el.find(seletor);
    },
    check: function(callback) {
      var __ = this,
        returnVal = 0;
      $.each(__.fieldObj, function(key, fobj) {
        if (!fobj.checked) {
          returnVal++;
        }
      });
      return !returnVal;
    },
    serialize: function() {
      var __ = this,
        returnVal = [];
      $.each(__.fieldObj, function(key, fobj) {
        var temp = {};
        temp[fobj.getFieldName()] = fobj.getData();
        returnVal.push(temp)
      });
      return returnVal;
    },
    submit: function(callback) {
      var __ = this,
        inx = 0;
      // final call it
      var finish = function() {
        if(typeof callback === 'function')callback(!__.check(), __.serialize());
      };

      var traverseFields = function(index) {
        var feild = __.fieldArr[index];
        feild.todoRule(true,function() {
          inx++;
          if (inx >= __.fieldLength) {
            finish()
            return;
          }
          traverseFields(inx);
        });
      };
      traverseFields(inx);
    }
  });

  var ruleStr = ['ff_length', 'ff_exp', 'ff_equal', '_require','ff_remote'];
  /**
   *  field function prototype
   */
  function Field(params) {
    $.extend({
      require: false, //imperative
    }, params);
    //cache params
    this.params = params;
    this.config = params.config;
    //cache seletor
    this.el = params.el;
    //cache field jqueryObj
    this.$el = params.$el;
    this.parent = params.parent;

    this.callback = this.config.callback || function() {};

    this.ruleStatus = {};

    this.checked = false;
    this._interrupt = false;
    this._init();
  }

  //extend method of Field
  $.extend(Field.prototype, {}, {
    //init field
    _init: function() {
      if(this.config.require){
        this.config[ruleStr[3]] = [/\S+/i,1];
      }
      this.rules = this._extRule();
      this.emitEvn()
      this.todoRule('')
    },
    //extraction ruler string
    _extRule: function() {
      var __ = this;
      var rules = [];
      //get dom attr and config of rule
      $.each(ruleStr, function(inx, val) {
        var ruleTemp = {};
        var rule = __.$el.attr(val);
        rule = $.trim(rule);
        //dom rule isn't empty
        if (rule.length > 0) {
          ruleTemp[val] = rule;
        }
        //config rule isn't empty
        var crule = __.config[val];
        if (crule) {
          ruleTemp[val] = crule;
        }
        if ($.isEmptyObject(ruleTemp)) return;
        for (var i in ruleTemp) {
          rules.push([i, ruleTemp[i]])
        }
      })
      return rules;
    },
    getData: function() {
      return this.$el.val().replace(/$\s*|\s*$/gi, '');
    },
    getFieldName: function() {
      return this.$el.attr('name');
    },
    //tigger events
    emitEvn: function() {
      var __ = this;
      this.$el.on('blur', function() {
        __.todoRule(true)
      }).on('focus', function() {
        __._focus();
        __.parent.emit('focus',__.$el,__);
      }).on('keyup', function(e) {
        __._keyup()
        __.parent.emit('keyup',__.$el,__);
      })
    },
    _focus: function() {
      if(typeof this.config.focus === 'function'){
        this.config.focus();
      }
    },
    _keyup:function(){
      if(typeof this.config.keyup === 'function'){
        this.config.keyup();
      }
    },
    //traverse rule
    //param {boolean} runcb, to run define callback
    todoRule: function(runcb,callback) {
      var __ = this,
        rules = __.rules,
        len = rules.length,
        inx = 0;

      //递归
      var todorule = function(index) {
        var rule = rules[index];
        if (!rule) {
          callback && callback();
          return;
        }
        //test each rule and go on next
        __.distRule(rule[0], rule[1], function(err, verClass, verObj) {
          //test the rule is end and ok
          var status = __.fieldVerify(err, verClass, verObj,runcb);
          if (++inx >= len) {
            callback && callback();
            return;
          }
          if (status) {
            todorule(inx);
          } else {
            if (inx < len) {
              callback && callback();
            }
          }

        });
      };

      todorule(inx);
    },
    //set gobel feild status
    fieldVerify: function(err, verfiyClass, verfiyObj, runcb) {
      var __ = this;
      var rules = __.rules;
      var finished = 0,
        notFinished = 0;
      //rule Status
      __.ruleStatus[verfiyClass] = err;
      if (err) {
        if(runcb)
        __.callback(true, verfiyObj.tips, __);
        __.checked = false;
        return false;
      }
      //check finish info
      for (var i = 0, l = rules.length; i < l; i++) {
        var cstatus = __.ruleStatus[rules[i][0]];
        if (!(typeof cstatus === 'boolean' && cstatus === false)) {
          notFinished += 1;
        } else {
          finished += 1;
        }
      }
      //verfiy finished,to do it
      if (finished == rules.length || !__._interrupt) {
        if(runcb)
        __.callback(false, verfiyObj.tips, __);
        __.checked = true;
      }

      return true;

    },
    //dispatch verify rule
    distRule: function(k, v, callback) {
      var __ = this,
        valiData;
      //require verfiy
      if(k == ruleStr[3]){
        valiData = new verRepExp(v);
      }
      //字符长度验证
      else if (k == ruleStr[0]) {
        valiData = new lengthVer(v)
      }
      //正则验证
      else if (k == ruleStr[1]) {
        valiData = new verRepExp(v);
      }
      //是否相等
      else if (k == ruleStr[2]) {
        valiData = new verEqual(v, __);
      }
      //远程验证
      else if (k == ruleStr[4]) {
        valiData = new verRemote(v, __);
      }
      __.set_callback(valiData, k, callback);

    },
    //set verfiy plugin callback method
    set_callback: function(valiObj, verfiyClass, callback) {
      var __ = this;
      //set validata object callback method
      //when callback params err is true,
      //then verfiy plugin test result is error
      valiObj.callback = function(err,data) {
        if (err) {
          __._interrupt = true;
          callback.call(__, true, verfiyClass, valiObj,data);
        } else {
          __._interrupt = false;
          callback.call(__, false, verfiyClass, valiObj,data);

        }
      }
      //to do validata with input text
      return valiObj.valiData(__.getData())

    }
  });

  //verfiy string length
  var lengthVer = function(lenstr) {
    var strType = $.type(lenstr);
    var regArr;
    if (strType == 'array') {
      regArr = lenstr;
    } else if (strType == 'string') {
      regArr = lenstr.split(',');
    }
    this.tips = '';
    this.valArr = regArr;
    this.callback = null;

  }
  lengthVer.prototype.valiData = function(itxt) {
    var valArr = this.valArr;
    if (valArr.length >= 2) {
      this.tips = valArr[2] ? valArr[2] : '';
    } else if (valArr.length == 1) {
      valArr[1] = valArr[0];
    }
    var exp = new RegExp('^\.{' + valArr[0] + ',' + valArr[1] + '}$');

    if (!exp.test(itxt)) {
      //exp not ok
      this.callback(true)
      return false;
    }
    //exp is ok
    this.callback(false)
    return true;

  }

  //verify regExp
  var verRepExp = function(regStr) {
    var strType = $.type(regStr);
    var regArr = null;

    if (strType == 'array') {
      regArr = regStr;
    } else if (strType == 'string') {
      regArr = eval('(' + regStr + ')');
    }
    this.tips= '';
   // this.callback = null;
   this.regArr = regArr;
  }
  verRepExp.prototype.valiData = function(itxt) {
    var self = this,testval;
     function testReg(exp,itxt){
      console.log(exp,itxt,exp.test(itxt));

      if(!exp.test(itxt)){
       // self.callback(true);
        return false;
      }
      //self.callback(false);
      return true;
    };

    if(tostring.call(self.regArr[0]) === '[object RegExp]'){
      self.tips = self.regArr[1];
      testval = testReg(self.regArr[0],itxt);
    }else{
      for(var i = 0,l = self.regArr.length;i<l;i++){
        var regexp = self.regArr[i].regexp;
        self.tips = self.regArr[i].label;
        testval = testReg(regexp,itxt);
        if(!testval){
         // return testval;
         break;
        }
      }
    }
    if(testval){
      self.callback(false);
    }else{
      self.callback(true)
    }
    return testval;

  };

  // verfiy equal field
  var verEqual = function(regStr, field) {
    var strType = $.type(regStr),
      regArr = null;

    if (strType == 'array') {
      regArr = regStr;
    } else if (strType == 'string') {
      regArr = eval('(' + regStr + ')');
    }
    var groups = field.params.groupField;
    this.relFeld = groups[regArr[0]];
    this.tips = regArr[1] ? regArr[1] : '';
    this.callback = null;
  };
  verEqual.prototype.valiData = function(itxt) {
    var inpVal = this.relFeld.getData();
    if (inpVal !== itxt) {
      this.callback(true)
      return false
    }
    this.callback(false)
    return true
  }

  //async verfiy module
  var verRemote = function(remoteparam, field) {
    var strType = $.type(remoteparam),
      regArr = null;

    if (strType == 'array') {
      regArr = remoteparam;
    } else if (strType == 'string') {
      regArr = eval('(' + remoteparam + ')');
    }
    this.remote = regArr[0];
    this.verFn = regArr[1];
    this.tips = regArr[2];
    this.htxType =  regArr[3] || 'get';
    this.pdata = regArr[4] || {};
    this.datatype = regArr[5] || 'json';
    this.filedName = regArr[6]||field.$el.attr('name');
    this.callback = null;
  }
  verRemote.prototype.valiData = function(itxt) {
    var __ = this;
    var params = {};
    params[__.filedName] = itxt;
    $.extend(params,this.pdata);
    // $[this.htxType](this.remote, params, function(data) {
    //   if (!__.verFn(data)) {
    //     __.callback(true);
    //   } else {
    //     __.callback(false);
    //   }
    // }, 'json');

    $.ajax({
      type:this.htxType,
      url:this.remote,
      data:params,
      dataType:this.datatype,
      success:function(data){
        if (!__.verFn(data)) {
        __.callback(true,data);
      } else {
        __.callback(false,data);
      }
      },
      error:function(xhr,type){
        console && console.log(xhr,type);
      }
    })

  }

  return function() {
    var argLen = arguments.length;
    if (argLen == 0) {
      return new formFilter({})
    } else if (argLen == 1) {
      return new formFilter(arguments[0])
    } else {
      return new formFilter(arguments[0], arguments[1])
    }
  }
});<commit_msg>Update formFilter.js<commit_after>/**
 * a form verfiy tool
 *
 * Author by robinma
 *
 *formFilter([form jQObj | seletor],fieldConfig)
 *
 *fieldConfig:
 *require:[false|true] imperactive
 */

(function(root, factory) {
  //set up formFilter appropriately for the enviroment.
  if (typeof define === 'function' && (define.cmd || define.amd)) {
    define(function() {
      return factory();
    });
  } else {
    //as a browser global
    root.formFilter = factory();
  }

})(this, function() {

  var objproto = Object.prototype;
  var tostring = objproto.toString;

  var pubsub = {
    _handlers: '',
    on: function(etype, handler) {
      if (typeof this._handlers !== 'object') {
        this._handlers = [];
      }
      if (!this._handlers[etype]) {
        this._handlers[etype] = []
      }
      if (typeof handler === 'function') {
        this._handlers[etype].push(handler)
      }
      return this;
    },
    emit: function(etype) {
      var args = Array.prototype.slice.call(arguments, 1)
      var handlers = this._handlers[etype] || [];
      for (var i = 0, l = handlers.length; i < l; i++) {
        handlers[i].apply(null, args)
      }
      return this;
    }
  };

  //formFilter constracter
  var formFilter = function() {
    var arg = arguments;
    var argLen = arg.length;
    var params;
    var el;
    if (argLen >= 2) {
      el = arg[0];
      params = arg[1];
    } else if (argLen == 1) {
      el = 'body';
      params = arg[0];
    }
    this.$el = (typeof el === 'object' ? el : $(el));
    params = params || {};
    //field array
    this.fieldArr = [];
    this.fieldObj = {};
    this._init(params);

  };

  //extend method
  $.extend(formFilter.prototype, pubsub, {
    //formFilter version Number
    version: '0.0.1',
    //formFilter init
    _init: function(params) {
      if (typeof params === 'object') {
        this._traversal(params);
      }
    },
    //traversal user config and push field object to fieldArr
    _traversal: function(params) {
      var __ = this,
        _paramLen = 0;
      $.each(params, function(k, v) {
        //new a field object
        var field = new Field({
            el: k.replace(/^\s*|\s*$/ig, ''),
            $el: __.get$Obj(k),
            config: v,
            groupField: __.fieldObj,
            parent:__
          })
          //push field Object to field array
        __.fieldObj[k] = field;

        __.fieldArr.push(field);

        _paramLen++;
      })
      //record field length
      __.fieldLength = _paramLen;
    },
    //get form input jquery Obj
    get$Obj: function(seletor) {
      return this.$el.find(seletor);
    },
    check: function(callback) {
      var __ = this,
        returnVal = 0;
      $.each(__.fieldObj, function(key, fobj) {
        if (!fobj.checked) {
          returnVal++;
        }
      });
      return !returnVal;
    },
    serialize: function() {
      var __ = this,
        returnVal = [];
      $.each(__.fieldObj, function(key, fobj) {
        var temp = {};
        temp[fobj.getFieldName()] = fobj.getData();
        returnVal.push(temp)
      });
      return returnVal;
    },
    submit: function(callback) {
      var __ = this,
        inx = 0;
      // final call it
      var finish = function() {
        if(typeof callback === 'function')callback(!__.check(), __.serialize());
      };

      var traverseFields = function(index) {
        var feild = __.fieldArr[index];
        feild.todoRule(true,function() {
          inx++;
          if (inx >= __.fieldLength) {
            finish()
            return;
          }
          traverseFields(inx);
        });
      };
      traverseFields(inx);
    }
  });

  var ruleStr = ['ff_length', 'ff_exp', 'ff_equal', '_require','ff_remote'];
  /**
   *  field function prototype
   */
  function Field(params) {
    $.extend({
      require: false //imperative
    }, params);
    //cache params
    this.params = params;
    this.config = params.config;
    //cache seletor
    this.el = params.el;
    //cache field jqueryObj
    this.$el = params.$el;
    this.parent = params.parent;

    this.callback = this.config.callback || function() {};

    this.ruleStatus = {};

    this.checked = false;
    this._interrupt = false;
    this._init();
  }

  //extend method of Field
  $.extend(Field.prototype, {}, {
    //init field
    _init: function() {
      if(this.config.require){
        this.config[ruleStr[3]] = [/\S+/i,1];
      }
      this.rules = this._extRule();
      this.emitEvn()
      this.todoRule('')
    },
    //extraction ruler string
    _extRule: function() {
      var __ = this;
      var rules = [];
      //get dom attr and config of rule
      $.each(ruleStr, function(inx, val) {
        var ruleTemp = {};
        var rule = __.$el.attr(val);
        rule = $.trim(rule);
        //dom rule isn't empty
        if (rule.length > 0) {
          ruleTemp[val] = rule;
        }
        //config rule isn't empty
        var crule = __.config[val];
        if (crule) {
          ruleTemp[val] = crule;
        }
        if ($.isEmptyObject(ruleTemp)) return;
        for (var i in ruleTemp) {
          rules.push([i, ruleTemp[i]])
        }
      })
      return rules;
    },
    getData: function() {
      return this.$el.val().replace(/$\s*|\s*$/gi, '');
    },
    getFieldName: function() {
      return this.$el.attr('name');
    },
    //tigger events
    emitEvn: function() {
      var __ = this;
      this.$el.on('blur', function() {
        __.todoRule(true)
      }).on('focus', function() {
        __._focus();
        __.parent.emit('focus',__.$el,__);
      }).on('keyup', function(e) {
        __._keyup()
        __.parent.emit('keyup',__.$el,__);
      })
    },
    _focus: function() {
      if(typeof this.config.focus === 'function'){
        this.config.focus();
      }
    },
    _keyup:function(){
      if(typeof this.config.keyup === 'function'){
        this.config.keyup();
      }
    },
    //traverse rule
    //param {boolean} runcb, to run define callback
    todoRule: function(runcb,callback) {
      var __ = this,
        rules = __.rules,
        len = rules.length,
        inx = 0;

      //递归
      var todorule = function(index) {
        var rule = rules[index];
        if (!rule) {
          callback && callback();
          return;
        }
        //test each rule and go on next
        __.distRule(rule[0], rule[1], function(err, verClass, verObj) {
          //test the rule is end and ok
          var status = __.fieldVerify(err, verClass, verObj,runcb);
          if (++inx >= len) {
            callback && callback();
            return;
          }
          if (status) {
            todorule(inx);
          } else {
            if (inx < len) {
              callback && callback();
            }
          }

        });
      };

      todorule(inx);
    },
    //set gobel feild status
    fieldVerify: function(err, verfiyClass, verfiyObj, runcb) {
      var __ = this;
      var rules = __.rules;
      var finished = 0,
        notFinished = 0;
      //rule Status
      __.ruleStatus[verfiyClass] = err;
      if (err) {
        if(runcb)
        __.callback(true, verfiyObj.tips, __);
        __.checked = false;
        return false;
      }
      //check finish info
      for (var i = 0, l = rules.length; i < l; i++) {
        var cstatus = __.ruleStatus[rules[i][0]];
        if (!(typeof cstatus === 'boolean' && cstatus === false)) {
          notFinished += 1;
        } else {
          finished += 1;
        }
      }
      //verfiy finished,to do it
      if (finished == rules.length || !__._interrupt) {
        if(runcb)
        __.callback(false, verfiyObj.tips, __);
        __.checked = true;
      }

      return true;

    },
    //dispatch verify rule
    distRule: function(k, v, callback) {
      var __ = this,
        valiData;
      //require verfiy
      if(k == ruleStr[3]){
        valiData = new verRepExp(v);
      }
      //字符长度验证
      else if (k == ruleStr[0]) {
        valiData = new lengthVer(v)
      }
      //正则验证
      else if (k == ruleStr[1]) {
        valiData = new verRepExp(v);
      }
      //是否相等
      else if (k == ruleStr[2]) {
        valiData = new verEqual(v, __);
      }
      //远程验证
      else if (k == ruleStr[4]) {
        valiData = new verRemote(v, __);
      }
      __.set_callback(valiData, k, callback);

    },
    //set verfiy plugin callback method
    set_callback: function(valiObj, verfiyClass, callback) {
      var __ = this;
      //set validata object callback method
      //when callback params err is true,
      //then verfiy plugin test result is error
      valiObj.callback = function(err,data) {
        if (err) {
          __._interrupt = true;
          callback.call(__, true, verfiyClass, valiObj,data);
        } else {
          __._interrupt = false;
          callback.call(__, false, verfiyClass, valiObj,data);

        }
      }
      //to do validata with input text
      return valiObj.valiData(__.getData())

    }
  });

  //verfiy string length
  var lengthVer = function(lenstr) {
    var strType = $.type(lenstr);
    var regArr;
    if (strType == 'array') {
      regArr = lenstr;
    } else if (strType == 'string') {
      regArr = lenstr.split(',');
    }
    this.tips = '';
    this.valArr = regArr;
    this.callback = null;

  }
  lengthVer.prototype.valiData = function(itxt) {
    var valArr = this.valArr;
    if (valArr.length >= 2) {
      this.tips = valArr[2] ? valArr[2] : '';
    } else if (valArr.length == 1) {
      valArr[1] = valArr[0];
    }
    var exp = new RegExp('^\.{' + valArr[0] + ',' + valArr[1] + '}$');

    if (!exp.test(itxt)) {
      //exp not ok
      this.callback(true)
      return false;
    }
    //exp is ok
    this.callback(false)
    return true;

  }

  //verify regExp
  var verRepExp = function(regStr) {
    var strType = $.type(regStr);
    var regArr = null;

    if (strType == 'array') {
      regArr = regStr;
    } else if (strType == 'string') {
      regArr = eval('(' + regStr + ')');
    }
    this.tips= '';
   // this.callback = null;
   this.regArr = regArr;
  }
  verRepExp.prototype.valiData = function(itxt) {
    var self = this,testval;
     function testReg(exp,itxt){
      // window.console && console.log(exp,itxt,exp.test(itxt));

      if(!exp.test(itxt)){
       // self.callback(true);
        return false;
      }
      //self.callback(false);
      return true;
    };

    if(tostring.call(self.regArr[0]) === '[object RegExp]'){
      self.tips = self.regArr[1];
      testval = testReg(self.regArr[0],itxt);
    }else{
      for(var i = 0,l = self.regArr.length;i<l;i++){
        var regexp = self.regArr[i].regexp;
        self.tips = self.regArr[i].label;
        testval = testReg(regexp,itxt);
        if(!testval){
         // return testval;
         break;
        }
      }
    }
    if(testval){
      self.callback(false);
    }else{
      self.callback(true)
    }
    return testval;

  };

  // verfiy equal field
  var verEqual = function(regStr, field) {
    var strType = $.type(regStr),
      regArr = null;

    if (strType == 'array') {
      regArr = regStr;
    } else if (strType == 'string') {
      regArr = eval('(' + regStr + ')');
    }
    var groups = field.params.groupField;
    this.relFeld = groups[regArr[0]];
    this.tips = regArr[1] ? regArr[1] : '';
    this.callback = null;
  };
  verEqual.prototype.valiData = function(itxt) {
    var inpVal = this.relFeld.getData();
    if (inpVal !== itxt) {
      this.callback(true)
      return false
    }
    this.callback(false)
    return true
  }

  //async verfiy module
  var verRemote = function(remoteparam, field) {
    var strType = $.type(remoteparam),
      regArr = null;

    if (strType == 'array') {
      regArr = remoteparam;
    } else if (strType == 'string') {
      regArr = eval('(' + remoteparam + ')');
    }
    this.remote = regArr[0];
    this.verFn = regArr[1];
    this.tips = regArr[2];
    this.htxType =  regArr[3] || 'get';
    this.pdata = regArr[4] || {};
    this.datatype = regArr[5] || 'json';
    this.filedName = regArr[6]||field.$el.attr('name');
    this.callback = null;
  }
  verRemote.prototype.valiData = function(itxt) {
    var __ = this;
    var params = {};
    params[__.filedName] = itxt;
    $.extend(params,this.pdata);
    // $[this.htxType](this.remote, params, function(data) {
    //   if (!__.verFn(data)) {
    //     __.callback(true);
    //   } else {
    //     __.callback(false);
    //   }
    // }, 'json');

    $.ajax({
      type:this.htxType,
      url:this.remote,
      data:params,
      dataType:this.datatype,
      success:function(data){
        if (!__.verFn(data)) {
        __.callback(true,data);
      } else {
        __.callback(false,data);
      }
      },
      error:function(xhr,type){
        // window.console && console.log(xhr,type);
      }
    })

  }

  return function() {
    var argLen = arguments.length;
    if (argLen == 0) {
      return new formFilter({})
    } else if (argLen == 1) {
      return new formFilter(arguments[0])
    } else {
      return new formFilter(arguments[0], arguments[1])
    }
  }
});
<|endoftext|>


<commit_before>// The client ID is obtained from the Google Developers Console
// at https://console.developers.google.com/.
// If you run this code from a server other than http://localhost,
// you need to register your own client ID.
var OAUTH2_CLIENT_ID = '29930055248-1ndkuph87papjlhsk59k7c07p9s911lq.apps.googleusercontent.com';
var OAUTH2_SCOPES = [
  'https://www.googleapis.com/auth/youtube',
  'https://www.googleapis.com/auth/calendar.readonly'
];

// Upon loading, the Google APIs JS client automatically invokes this callback.
googleApiClientReady = function() {
  gapi.auth.init(function() {
    window.setTimeout(checkAuth, 1);
  });
}

// Attempt the immediate OAuth 2.0 client flow as soon as the page loads.
// If the currently logged-in Google Account has previously authorized
// the client specified as the OAUTH2_CLIENT_ID, then the authorization
// succeeds with no user intervention. Otherwise, it fails and the
// user interface that prompts for authorization needs to display.
function checkAuth() {
  gapi.auth.authorize({
    client_id: OAUTH2_CLIENT_ID,
    scope: OAUTH2_SCOPES.join(' '),
    immediate: true
  }, handleAuthResult);
}

// Handle the result of a gapi.auth.authorize() call.
function handleAuthResult(authResult) {
  if (authResult && !authResult.error) {

    // Authorization was successful. Hide authorization prompts and show
    // content that should be visible after authorization succeeds.
    $('.pre-auth').hide();
    $('.post-auth').show();
    loadAPIClientInterfaces();
    loadCalendarApi();
  } else {
    // Make the #login-link clickable. Attempt a non-immediate OAuth 2.0
    // client flow. The current function is called when that flow completes.
    $('#login-link').click(function() {
      gapi.auth.authorize({
        client_id: OAUTH2_CLIENT_ID,
        scope: OAUTH2_SCOPES,
        immediate: false
        }, handleAuthResult);
    });
  }
}

// Load the client interfaces for the YouTube Analytics and Data APIs, which
// are required to use the Google APIs JS client. More info is available at
// http://code.google.com/p/google-api-javascript-client/wiki/GettingStarted#Loading_the_Client
function loadAPIClientInterfaces() {
  gapi.client.load('youtube', 'v3', function() {
    //handleAPILoaded();
  });
}

/**
 * Load Google Calendar client library. List upcoming events
 * once client library is loaded.
 */
function loadCalendarApi() {
  gapi.client.load('calendar', 'v3', listUpcomingEvents);
}

/**
 * Print the summary and start datetime/date of the next ten events in
 * the authorized user's calendar. If no events are found an
 * appropriate message is printed.
 */
function listUpcomingEvents() {
  var request = gapi.client.calendar.events.list({
    'calendarId': 'primary',
    'timeMin': (new Date()).toISOString(),
    'showDeleted': false,
    'singleEvents': true,
    'maxResults': 10,
    'orderBy': 'startTime'
  });

  request.execute(function(resp) {
    console.log(resp);
    var events = resp.items;
    schedule=events;
    //appendPre('Upcoming events:');

    if (events.length > 0) {
      for (i = 0; i < events.length; i++) {
        var event = events[i];
        var when = event.start.dateTime;
        if (!when)
          when = event.start.date;
      }
    }
  });
}<commit_msg>Update auth.js<commit_after>// The client ID is obtained from the Google Developers Console
// at https://console.developers.google.com/.
// If you run this code from a server other than http://localhost,
// you need to register your own client ID.
var OAUTH2_CLIENT_ID = '29930055248-1ndkuph87papjlhsk59k7c07p9s911lq.apps.googleusercontent.com';
var OAUTH2_SCOPES = [
  'https://www.googleapis.com/auth/youtube',
  'https://www.googleapis.com/auth/calendar.readonly'
];

// Upon loading, the Google APIs JS client automatically invokes this callback.
googleApiClientReady = function() {
  gapi.auth.init(function() {
    window.setTimeout(checkAuth, 1);
  });
}

// Attempt the immediate OAuth 2.0 client flow as soon as the page loads.
// If the currently logged-in Google Account has previously authorized
// the client specified as the OAUTH2_CLIENT_ID, then the authorization
// succeeds with no user intervention. Otherwise, it fails and the
// user interface that prompts for authorization needs to display.
function checkAuth() {
  gapi.auth.authorize({
    client_id: OAUTH2_CLIENT_ID,
    scope: OAUTH2_SCOPES.join(' '),
    immediate: false
  }, handleAuthResult);
}

// Handle the result of a gapi.auth.authorize() call.
function handleAuthResult(authResult) {
  if (authResult && !authResult.error) {

    // Authorization was successful. Hide authorization prompts and show
    // content that should be visible after authorization succeeds.
    $('.pre-auth').hide();
    $('.post-auth').show();
    loadAPIClientInterfaces();
    loadCalendarApi();
  } else {
    // Make the #login-link clickable. Attempt a non-immediate OAuth 2.0
    // client flow. The current function is called when that flow completes.
    $('#login-link').click(function() {
      gapi.auth.authorize({
        client_id: OAUTH2_CLIENT_ID,
        scope: OAUTH2_SCOPES,
        immediate: false
        }, handleAuthResult);
    });
  }
}

// Load the client interfaces for the YouTube Analytics and Data APIs, which
// are required to use the Google APIs JS client. More info is available at
// http://code.google.com/p/google-api-javascript-client/wiki/GettingStarted#Loading_the_Client
function loadAPIClientInterfaces() {
  gapi.client.load('youtube', 'v3', function() {
    //handleAPILoaded();
  });
}

/**
 * Load Google Calendar client library. List upcoming events
 * once client library is loaded.
 */
function loadCalendarApi() {
  gapi.client.load('calendar', 'v3', listUpcomingEvents);
}

/**
 * Print the summary and start datetime/date of the next ten events in
 * the authorized user's calendar. If no events are found an
 * appropriate message is printed.
 */
function listUpcomingEvents() {
  var request = gapi.client.calendar.events.list({
    'calendarId': 'primary',
    'timeMin': (new Date()).toISOString(),
    'showDeleted': false,
    'singleEvents': true,
    'maxResults': 10,
    'orderBy': 'startTime'
  });

  request.execute(function(resp) {
    console.log(resp);
    var events = resp.items;
    schedule=events;
    //appendPre('Upcoming events:');

    if (events.length > 0) {
      for (i = 0; i < events.length; i++) {
        var event = events[i];
        var when = event.start.dateTime;
        if (!when)
          when = event.start.date;
      }
    }
  });
}
<|endoftext|>


<commit_before>'use strict';

let util = require('util');
let R = require('ramda');

let internal = exports.internal = {};

exports.formatAddress = R.curry(function(validator, builder, info){
  let validationErrors = validator(info);
  return validationErrors.length > 0 ? validationErrors : builder(info);
});

exports.validateRequired = R.curry(function(requiredFields, info){
  return R.filter(R.complement(R.isNil),
    R.map((requiredField) => {
      return R.has(requiredField, info) ? null : new Error(util.format('Required field [%s] was not found in address info object', requiredField));
    }, requiredFields)
  );
});

let second = R.nth(1);

internal.isValid = R.complement(R.anyPass([R.isEmpty, R.isNil]));

// internal.isValid = function(val){
//   return !(R.isEmpty(val) || R.isNil(val));
// };

exports.trimVals = function(strings, ...values){
  let pairs = R.zip(strings, values);

  let writePairs = R.filter((val) => {
    return internal.isValid(second(val));
  }, pairs);

  return R.reduce((acc, pair) => {
    return acc.concat(R.join('', pair));
  }, '', writePairs);
};
<commit_msg>actually saved file <sadtrombone/><commit_after>'use strict';

let util = require('util');
let R = require('ramda');

let internal = exports.internal = {};

exports.formatAddress = R.curry(function(validator, builder, info){
  let validationErrors = validator(info);
  return validationErrors.length > 0 ? validationErrors : builder(info);
});

exports.validateRequired = R.curry(function(requiredFields, info){
  return R.filter(R.complement(R.isNil),
    R.map((requiredField) => {
      return R.has(requiredField, info) ? null : new Error(util.format('Required field [%s] was not found in address info object', requiredField));
    }, requiredFields)
  );
});

let second = R.nth(1);

let isValid = R.complement(R.anyPass([R.isEmpty, R.isNil]));

exports.trimVals = function(strings, ...values){
  let pairs = R.zip(strings, values);

  let writePairs = R.filter((val) => {
    return isValid(second(val));
  }, pairs);

  return R.reduce((acc, pair) => {
    return acc.concat(R.join('', pair));
  }, '', writePairs);
};
<|endoftext|>