UNPKG

react-tree-menu

Version:
1,559 lines (1,295 loc) 1.33 MB
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ var React = require('react'), TreeMenu = require('../index'), TreeNode = require('../index').TreeNode, TreeMenuUtils = require('../index').Utils, Immutable = require('immutable'), _ = require('lodash'); var CSSTransitionGroup = require('react-addons-css-transition-group'); var App = React.createClass({displayName: "App", getInitialState: function() { return { lastAction1: null, lastAction2: null, lastAction3: null, staticTreeData: { "option_2.a" : { checked: false }, "option_2.b" : { checked: false } }, dynamicTreeData: [ { label : "Option 1" }, { label : "Option 2", children : [ { checkbox: true, label: "Sub Option A", children: [ { label: "Third Level Option 1", checkbox : true }, { label: "Third Level Option 2", checkbox : true } ] }, { checkbox: true, label: "Sub Option B" } ] } ], dynamicTreeDataMap: { "Option 1" : { checked: true, checkbox: true, children: { "Sub Option 1" : { checked: false }, "Sub Option 2" : { checked: false, checkbox: true, children: { "Sub-Sub Option 1" : { checked: false, checkbox: true }, "Sub-Sub Option 2" : { checked: false, checkbox: true } } } } }, "Option 2" : { checked: false, checkbox: true } }, dynamicTreeDataMap2: { "Option 1" : { checkbox: false, children: { "Sub Option 1" : { checkbox: false }, "Sub Option 2" : { checkbox: false, children: { "Sub-Sub Option 1" : { selected: true, checkbox: false }, "Sub-Sub Option 2" : { checkbox: false } } } } }, "Option 2" : { checkbox: false } } }; }, render: function() { var dynamicExample1 = this._getExamplePanel("Dynamic", this._getDynamicTreeExample()), declarativeExample = this._getExamplePanel("Declarative", this._getDeclarativeTreeExample()), unboundExample = this._getExamplePanel("Unbound", this._getUnboundTreeExample()), statefulExample = this._getExamplePanel("Stateful", this._getStatefulTreeExample()), dynamicExample2 = this._getExamplePanel("Dynamic (Object)", this._getDynamicTreeExample2()), dynamicExample3 = this._getExamplePanel("Selection w/o Checkboxes", this._getDynamicTreeExample3()), labelFilterExample = this._getExamplePanel("Label Filter", this._getLabelFilterExample()), rendererExample = this._getExamplePanel("Label/Checkbox Renderers", this._getRendererExample()); return React.createElement("div", {className: "container"}, React.createElement("div", {className: "row"}, React.createElement("div", {className: "col-lg-12 hero"}, React.createElement("h1", null, React.createElement("code", null, "<TreeMenu/>")) ) ), React.createElement("div", {className: "row"}, React.createElement("div", {className: "col-lg-12 hero"}, React.createElement("h3", null, "Check out the code for this demo ", React.createElement("a", {href: "https://github.com/MandarinConLaBarba/react-tree-menu/blob/master/example/App.jsx"}, "here"), ".") ) ), React.createElement("div", {className: "row"}, React.createElement("div", {className: "col-lg-3"}, React.createElement("h2", null, "Dynamic (Array)"), React.createElement("ul", null, React.createElement("li", null, "This menu is built dynamically using the data prop (array)"), React.createElement("li", null, "It is collapsible (the default), so expand/collapse icons show"), React.createElement("li", null, "It has no identifier prop for the TreeMenu, so it uses the array index when emitting events") ) ), React.createElement("div", {className: "col-lg-3"}, React.createElement("h2", null, "Declarative"), React.createElement("ul", null, React.createElement("li", null, "This menu is built w/ nested TreeNode components"), React.createElement("li", null, "It has collapsible=false, so no expand/collapse icons show"), React.createElement("li", null, "It has identifier=\"id\", so it uses the 'id' prop when emitting events") ) ), React.createElement("div", {className: "col-lg-3"}, React.createElement("h2", null, "Unbound: Won't Update UI State"), React.createElement("ul", null, React.createElement("li", null, "This menu doesn't have any handlers applied that update UI state, so it's static.") ) ), React.createElement("div", {className: "col-lg-3"}, React.createElement("h2", null, "Stateful, manages its own UI state"), React.createElement("ul", null, React.createElement("li", null, "This menu has stateful=true, so it manages its own state w/o help from the Controller-View.") ) ) ), React.createElement("div", {className: "row"}, React.createElement("div", {className: "col-lg-3"}, dynamicExample1 ), React.createElement("div", {className: "col-lg-3"}, declarativeExample ), React.createElement("div", {className: "col-lg-3"}, unboundExample ), React.createElement("div", {className: "col-lg-3"}, statefulExample ) ), React.createElement("div", {className: "row"}, React.createElement("div", {className: "col-lg-3"}, React.createElement(CSSTransitionGroup, { transitionEnterTimeout: 500, transitionName: "last-action", transitionLeave: false}, this._getLastActionNode("1") ) ), React.createElement("div", {className: "col-lg-3"}, React.createElement(CSSTransitionGroup, {transitionEnterTimeout: 500, transitionName: "last-action", transitionLeave: false}, this._getLastActionNode("2") ) ), React.createElement("div", {className: "col-lg-3"}, React.createElement(CSSTransitionGroup, {transitionEnterTimeout: 500, transitionName: "last-action", transitionLeave: false}, this._getLastActionNode("3") ) ), React.createElement("div", {className: "col-lg-3"}, React.createElement(CSSTransitionGroup, {transitionEnterTimeout: 500, transitionName: "last-action", transitionLeave: false}, this._getLastActionNode("4") ) ) ), React.createElement("div", {className: "row"}, React.createElement("div", {className: "col-lg-3"}, React.createElement("h2", null, "Dynamic (Object)"), React.createElement("ul", null, React.createElement("li", null, "This menu is built dynamically using the data prop (object)"), React.createElement("li", null, "It is collapsible (the default), so expand/collapse icons show"), React.createElement("li", null, "It has no identifier prop for the TreeMenu, so it uses the object key when emitting events") ) ), React.createElement("div", {className: "col-lg-3"}, React.createElement("h2", null, "Dynamic - No Checkboxes"), React.createElement("ul", null, React.createElement("li", null, "This menu is built dynamically using the data prop (object)"), React.createElement("li", null, "It doesn't have checkboxes, but does have selection state") ) ), React.createElement("div", {className: "col-lg-3"}, React.createElement("h2", null, "Label Filter"), React.createElement("ul", null, React.createElement("li", null, "This menu has a labelFilter prop that truncates the displayed label") ) ), React.createElement("div", {className: "col-lg-3"}, React.createElement("h2", null, "Renderers"), React.createElement("ul", null, React.createElement("li", null, "Using renderer (node factory) methods as arguments") ) ) ), React.createElement("div", {className: "row"}, React.createElement("div", {className: "col-lg-3"}, dynamicExample2 ), React.createElement("div", {className: "col-lg-3"}, dynamicExample3 ), React.createElement("div", {className: "col-lg-3"}, labelFilterExample ), React.createElement("div", {className: "col-lg-3"}, rendererExample ) ), React.createElement("div", {className: "row"}, React.createElement("div", {className: "col-lg-3"}, React.createElement(CSSTransitionGroup, {transitionEnterTimeout: 500, transitionName: "last-action", transitionLeave: false}, this._getLastActionNode("5") ) ), React.createElement("div", {className: "col-lg-3"}, React.createElement(CSSTransitionGroup, {transitionEnterTimeout: 500, transitionName: "last-action", transitionLeave: false}, this._getLastActionNode("6") ) ) ) ); }, _getLastActionNode: function (col) { var lastActionNode = React.createElement("div", {className: "text-center alert alert-success tree-event-alert"}, "Waiting for interaction"), key = "lastAction" + col; var action = this.state[key]; if (action) { lastActionNode = ( React.createElement("div", {className: "text-center alert alert-success tree-event-alert", key: "lastAction_" + col + "_" + action.time}, React.createElement("h3", null, "Event Received:"), React.createElement("div", null, React.createElement("strong", null, action.event)), React.createElement("h3", null, React.createElement("code", null, "<TreeNode/>"), " Affected: "), React.createElement("div", null, React.createElement("strong", null, action.node)) )); } else { } return lastActionNode; }, _getStatefulTreeExample: function () { return ( React.createElement(TreeMenu, { identifier: "id", stateful: true, onTreeNodeClick: this._setLastActionState.bind(this, "clicked", "4"), onTreeNodeCollapseChange: this._setLastActionState.bind(this, "collapsed", "4"), onTreeNodeCheckChange: this._setLastActionState.bind(this, "checked", "4"), expandIconClass: "fa fa-chevron-right", collapseIconClass: "fa fa-chevron-down"}, React.createElement(TreeNode, {label: "Option 1", checkbox: true, id: "option_1"}), React.createElement(TreeNode, {label: "Option 2", checkbox: true, id: "option_2"}, React.createElement(TreeNode, {label: "Option A", checkbox: true, id: "option_2.a"}), React.createElement(TreeNode, {label: "Option B", checkbox: true, id: "option_2.b"}, React.createElement(TreeNode, {label: "Option B.x", checkbox: true, id: "option_2.b.x"}), React.createElement(TreeNode, {label: "Option B.y", checkbox: true, id: "option_2.b.y"}) ) ) ) ); }, _getUnboundTreeExample: function () { return ( React.createElement(TreeMenu, { identifier: "id", onTreeNodeClick: this._setLastActionState.bind(this, "clicked", "3"), onTreeNodeCollapseChange: this._setLastActionState.bind(this, "collapsed", "3"), onTreeNodeCheckChange: this._setLastActionState.bind(this, "checked", "3"), expandIconClass: "fa fa-chevron-right", collapseIconClass: "fa fa-chevron-down"}, React.createElement(TreeNode, {label: "Option 1", checkbox: true, id: "option_1"}), React.createElement(TreeNode, {label: "Option 2", checkbox: true, id: "option_2"}, React.createElement(TreeNode, {label: "Option A", checkbox: true, checked: true, id: "option_2.a"}), React.createElement(TreeNode, {label: "Option B", checkbox: true, id: "option_2.b"}) ), React.createElement(TreeNode, {label: "Option 3", checkbox: true, id: "option_3"}), React.createElement(TreeNode, {label: "Option 3", checkbox: true, id: "option_3"}) ) ); }, _getDeclarativeTreeExample: function () { return ( React.createElement(TreeMenu, { sort: true, identifier: "id", onTreeNodeClick: this._setLastActionState.bind(this, "clicked", "2"), onTreeNodeCollapseChange: this._handleDeclarativeTreeNodePropChange.bind(this, "collapsed"), onTreeNodeCheckChange: this._handleDeclarativeTreeNodePropChange.bind(this, "checked"), collapsible: false, expandIconClass: "fa fa-chevron-right", collapseIconClass: "fa fa-chevron-down"}, React.createElement(TreeNode, {label: "Option 1", id: "option_1"}), React.createElement(TreeNode, {label: "Option 2", id: "option_2"}, React.createElement(TreeNode, {label: "Option B", checkbox: true, checked: this.state.staticTreeData["option_2.b"].checked, id: "option_2.b"}), React.createElement(TreeNode, {label: "Option A", checkbox: true, checked: this.state.staticTreeData["option_2.a"].checked, id: "option_2.a"}) ), React.createElement(TreeNode, {label: "Option 3", id: "option_3"}), React.createElement(TreeNode, {label: "Option 4", id: "option_4"}) ) ); }, _getLabelFilterExample: function () { return ( React.createElement(TreeMenu, { identifier: "id", onTreeNodeClick: function() {}, onTreeNodeCollapseChange: function() {}, onTreeNodeCheckChange: function() {}, collapsible: false, labelFilter: function(label) { var max = 10; if (label.length <= max) return label; return label.substring(label, max).concat("..."); }, expandIconClass: "fa fa-chevron-right", collapseIconClass: "fa fa-chevron-down"}, React.createElement(TreeNode, {label: "Option 1 with a long name", id: "option_1"}), React.createElement(TreeNode, {label: "Option 2 also has a long name", id: "option_2"}, React.createElement(TreeNode, {label: "Option A with a long name", checkbox: true, id: "option_2.a"}), React.createElement(TreeNode, {label: "Option B with a long name", checkbox: true, id: "option_2.b"}) ), React.createElement(TreeNode, {label: "Option 3 with a long name", id: "option_3"}), React.createElement(TreeNode, {label: "Option 4 with a long name", id: "option_4"}) ) ); }, _getRendererExample: function () { return ( React.createElement(TreeMenu, { identifier: "id", onTreeNodeClick: function() {}, onTreeNodeCollapseChange: function() {}, onTreeNodeCheckChange: function() {}, collapsible: false, labelFilter: function(label) { var max = 10; if (label.length <= max) return label; return label.substring(label, max).concat("..."); }, labelFactory: function(labelClassName, displayLabel) { return React.createElement("span", {className: labelClassName}, displayLabel, " ", "<span/>"); }, checkboxFactory: function(checkboxClassName, isChecked) { return React.createElement("span", {className: checkboxClassName + " fa " + (isChecked ? "fa-check-circle" : "fa-circle-o")}); }, expandIconClass: "fa fa-chevron-right", collapseIconClass: "fa fa-chevron-down"}, React.createElement(TreeNode, {label: "Option 1 with a long name", id: "option_1"}), React.createElement(TreeNode, {label: "Option 2 also has a long name", id: "option_2", checkbox: true, checked: false}, React.createElement(TreeNode, {label: "Option A with a long name", checkbox: true, id: "option_2.a"}), React.createElement(TreeNode, {label: "Option B with a long name", checkbox: true, checked: true, id: "option_2.b"}) ), React.createElement(TreeNode, {label: "Option 3 with a long name", id: "option_3"}), React.createElement(TreeNode, {label: "Option 4 with a long name", id: "option_4"}) ) ); }, _getDynamicTreeExample: function () { return ( React.createElement(TreeMenu, { expandIconClass: "fa fa-chevron-right", collapseIconClass: "fa fa-chevron-down", onTreeNodeClick: this._setLastActionState.bind(this, "clicked", "1"), onTreeNodeCollapseChange: this._handleDynamicTreeNodePropChange.bind(this, "collapsed"), onTreeNodeCheckChange: this._handleDynamicTreeNodePropChange.bind(this, "checked"), data: this.state.dynamicTreeData}) ); }, _getDynamicTreeExample2: function () { return ( React.createElement(TreeMenu, { expandIconClass: "fa fa-chevron-right", collapseIconClass: "fa fa-chevron-down", onTreeNodeClick: this._setLastActionState.bind(this, "clicked", "5"), onTreeNodeCollapseChange: this._handleDynamicObjectTreeNodePropChange.bind(this, 5, "dynamicTreeDataMap","collapsed"), onTreeNodeCheckChange: this._handleDynamicObjectTreeNodePropChange.bind(this, 5, "dynamicTreeDataMap","checked"), data: this.state.dynamicTreeDataMap}) ); }, _getDynamicTreeExample3: function () { return ( React.createElement(TreeMenu, { expandIconClass: "fa fa-chevron-right", collapseIconClass: "fa fa-chevron-down", onTreeNodeCollapseChange: this._handleDynamicObjectTreeNodePropChange.bind(this, 6, "dynamicTreeDataMap2", "collapsed"), onTreeNodeCheckChange: this._handleDynamicObjectTreeNodePropChange.bind(this, 6, "dynamicTreeDataMap2","checked"), onTreeNodeSelectChange: this._handleDynamicObjectTreeNodePropChange.bind(this, 6, "dynamicTreeDataMap2","selected"), data: this.state.dynamicTreeDataMap2}) ); }, _getExamplePanel: function (title, treeMenuNode) { return React.createElement("div", null, React.createElement("div", {className: "panel panel-default"}, React.createElement("div", {className: "panel-heading"}, title + " Menu"), React.createElement("div", {className: "panel-body"}, treeMenuNode ) ) ); }, _handleDeclarativeTreeNodePropChange: function (propName, lineage) { this._setLastActionState(propName, "2", lineage); var nodeId = lineage.pop(); var treeState = this.state.staticTreeData; treeState[nodeId][propName] = !treeState[nodeId][propName]; this.setState({ staticTreeData : treeState }); }, _handleDynamicTreeNodePropChange: function (propName, lineage) { this._setLastActionState(propName, "1", lineage); this.setState(TreeMenuUtils.getNewTreeState(lineage, this.state.dynamicTreeData, propName)); }, _handleDynamicObjectTreeNodePropChange: function (messageWindowKey, stateKey, propName, lineage) { this._setLastActionState(propName, messageWindowKey, lineage); //Get a node path that includes children, given a key function getNodePath(nodeKey) { if (nodeKey.length === 1) return nodeKey; return _(nodeKey).zip(nodeKey.map(function () { return "children"; })).flatten().initial().value(); } var oldState = Immutable.fromJS(this.state[stateKey]); var nodePath = getNodePath(lineage), keyPaths = [nodePath.concat([propName])]; //Build a list of key paths for all children function addChildKeys(state, parentPath) { var childrenPath = parentPath.concat('children'), children = state.getIn(childrenPath); if (!children || children.size === 0) return; children.map(function (value, key) { keyPaths.push(childrenPath.concat([key, propName])) addChildKeys(state, childrenPath.concat([key])); }); } addChildKeys(oldState, nodePath); //Get the new prop state var newPropState = !oldState.getIn(keyPaths[0]); //Now create a new map w/ all the changes var newState = oldState.withMutations(function(state) { keyPaths.forEach(function (keyPath) { state.setIn(keyPath, newPropState); }) }); var mutation = {}; mutation[stateKey] = newState.toJS(); this.setState(mutation); }, _setLastActionState: function (action, col, node) { var toggleEvents = ["collapsed", "checked", "selected"]; if (toggleEvents.indexOf(action) >= 0) { action += "Changed"; } console.log("Controller View received tree menu " + action + " action: " + node.join(" > ")); var key = "lastAction" + col; var mutation = {}; mutation[key] = { event: action, node: node.join(" > "), time: new Date().getTime() }; this.setState(mutation) } }); module.exports = App; },{"../index":3,"immutable":5,"lodash":9,"react":240,"react-addons-css-transition-group":78}],2:[function(require,module,exports){ var React = require('react'); var ReactDOM = require('react-dom'); var App = require('./App.jsx'); ReactDOM.render(React.createElement(App, null), document.getElementById('appContainer')); },{"./App.jsx":1,"react":240,"react-dom":79}],3:[function(require,module,exports){ var api = require('./src/TreeMenu.jsx'); api.TreeMenu = require('./src/TreeMenu.jsx'); api.TreeNode = require('./src/TreeNode.jsx'); api.Utils = require('./src/TreeMenuUtils'); module.exports = api; },{"./src/TreeMenu.jsx":241,"./src/TreeMenuUtils":242,"./src/TreeNode.jsx":243}],4:[function(require,module,exports){ // shim for using process in browser var process = module.exports = {}; var queue = []; var draining = false; function drainQueue() { if (draining) { return; } draining = true; var currentQueue; var len = queue.length; while(len) { currentQueue = queue; queue = []; var i = -1; while (++i < len) { currentQueue[i](); } len = queue.length; } draining = false; } process.nextTick = function (fun) { queue.push(fun); if (!draining) { setTimeout(drainQueue, 0); } }; process.title = 'browser'; process.browser = true; process.env = {}; process.argv = []; process.version = ''; // empty string to avoid regexp issues function noop() {} process.on = noop; process.addListener = noop; process.once = noop; process.off = noop; process.removeListener = noop; process.removeAllListeners = noop; process.emit = noop; process.binding = function (name) { throw new Error('process.binding is not supported'); }; // TODO(shtylman) process.cwd = function () { return '/' }; process.chdir = function (dir) { throw new Error('process.chdir is not supported'); }; process.umask = function() { return 0; }; },{}],5:[function(require,module,exports){ /** * Copyright (c) 2014, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : global.Immutable = factory() }(this, function () { 'use strict';var SLICE$0 = Array.prototype.slice; function createClass(ctor, superClass) { if (superClass) { ctor.prototype = Object.create(superClass.prototype); } ctor.prototype.constructor = ctor; } // Used for setting prototype methods that IE8 chokes on. var DELETE = 'delete'; // Constants describing the size of trie nodes. var SHIFT = 5; // Resulted in best performance after ______? var SIZE = 1 << SHIFT; var MASK = SIZE - 1; // A consistent shared value representing "not set" which equals nothing other // than itself, and nothing that could be provided externally. var NOT_SET = {}; // Boolean references, Rough equivalent of `bool &`. var CHANGE_LENGTH = { value: false }; var DID_ALTER = { value: false }; function MakeRef(ref) { ref.value = false; return ref; } function SetRef(ref) { ref && (ref.value = true); } // A function which returns a value representing an "owner" for transient writes // to tries. The return value will only ever equal itself, and will not equal // the return of any subsequent call of this function. function OwnerID() {} // http://jsperf.com/copy-array-inline function arrCopy(arr, offset) { offset = offset || 0; var len = Math.max(0, arr.length - offset); var newArr = new Array(len); for (var ii = 0; ii < len; ii++) { newArr[ii] = arr[ii + offset]; } return newArr; } function ensureSize(iter) { if (iter.size === undefined) { iter.size = iter.__iterate(returnTrue); } return iter.size; } function wrapIndex(iter, index) { return index >= 0 ? (+index) : ensureSize(iter) + (+index); } function returnTrue() { return true; } function wholeSlice(begin, end, size) { return (begin === 0 || (size !== undefined && begin <= -size)) && (end === undefined || (size !== undefined && end >= size)); } function resolveBegin(begin, size) { return resolveIndex(begin, size, 0); } function resolveEnd(end, size) { return resolveIndex(end, size, size); } function resolveIndex(index, size, defaultIndex) { return index === undefined ? defaultIndex : index < 0 ? Math.max(0, size + index) : size === undefined ? index : Math.min(size, index); } function Iterable(value) { return isIterable(value) ? value : Seq(value); } createClass(KeyedIterable, Iterable); function KeyedIterable(value) { return isKeyed(value) ? value : KeyedSeq(value); } createClass(IndexedIterable, Iterable); function IndexedIterable(value) { return isIndexed(value) ? value : IndexedSeq(value); } createClass(SetIterable, Iterable); function SetIterable(value) { return isIterable(value) && !isAssociative(value) ? value : SetSeq(value); } function isIterable(maybeIterable) { return !!(maybeIterable && maybeIterable[IS_ITERABLE_SENTINEL]); } function isKeyed(maybeKeyed) { return !!(maybeKeyed && maybeKeyed[IS_KEYED_SENTINEL]); } function isIndexed(maybeIndexed) { return !!(maybeIndexed && maybeIndexed[IS_INDEXED_SENTINEL]); } function isAssociative(maybeAssociative) { return isKeyed(maybeAssociative) || isIndexed(maybeAssociative); } function isOrdered(maybeOrdered) { return !!(maybeOrdered && maybeOrdered[IS_ORDERED_SENTINEL]); } Iterable.isIterable = isIterable; Iterable.isKeyed = isKeyed; Iterable.isIndexed = isIndexed; Iterable.isAssociative = isAssociative; Iterable.isOrdered = isOrdered; Iterable.Keyed = KeyedIterable; Iterable.Indexed = IndexedIterable; Iterable.Set = SetIterable; var IS_ITERABLE_SENTINEL = '@@__IMMUTABLE_ITERABLE__@@'; var IS_KEYED_SENTINEL = '@@__IMMUTABLE_KEYED__@@'; var IS_INDEXED_SENTINEL = '@@__IMMUTABLE_INDEXED__@@'; var IS_ORDERED_SENTINEL = '@@__IMMUTABLE_ORDERED__@@'; /* global Symbol */ var ITERATE_KEYS = 0; var ITERATE_VALUES = 1; var ITERATE_ENTRIES = 2; var REAL_ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator; var FAUX_ITERATOR_SYMBOL = '@@iterator'; var ITERATOR_SYMBOL = REAL_ITERATOR_SYMBOL || FAUX_ITERATOR_SYMBOL; function Iterator(next) { this.next = next; } Iterator.prototype.toString = function() { return '[Iterator]'; }; Iterator.KEYS = ITERATE_KEYS; Iterator.VALUES = ITERATE_VALUES; Iterator.ENTRIES = ITERATE_ENTRIES; Iterator.prototype.inspect = Iterator.prototype.toSource = function () { return this.toString(); } Iterator.prototype[ITERATOR_SYMBOL] = function () { return this; }; function iteratorValue(type, k, v, iteratorResult) { var value = type === 0 ? k : type === 1 ? v : [k, v]; iteratorResult ? (iteratorResult.value = value) : (iteratorResult = { value: value, done: false }); return iteratorResult; } function iteratorDone() { return { value: undefined, done: true }; } function hasIterator(maybeIterable) { return !!getIteratorFn(maybeIterable); } function isIterator(maybeIterator) { return maybeIterator && typeof maybeIterator.next === 'function'; } function getIterator(iterable) { var iteratorFn = getIteratorFn(iterable); return iteratorFn && iteratorFn.call(iterable); } function getIteratorFn(iterable) { var iteratorFn = iterable && ( (REAL_ITERATOR_SYMBOL && iterable[REAL_ITERATOR_SYMBOL]) || iterable[FAUX_ITERATOR_SYMBOL] ); if (typeof iteratorFn === 'function') { return iteratorFn; } } function isArrayLike(value) { return value && typeof value.length === 'number'; } createClass(Seq, Iterable); function Seq(value) { return value === null || value === undefined ? emptySequence() : isIterable(value) ? value.toSeq() : seqFromValue(value); } Seq.of = function(/*...values*/) { return Seq(arguments); }; Seq.prototype.toSeq = function() { return this; }; Seq.prototype.toString = function() { return this.__toString('Seq {', '}'); }; Seq.prototype.cacheResult = function() { if (!this._cache && this.__iterateUncached) { this._cache = this.entrySeq().toArray(); this.size = this._cache.length; } return this; }; // abstract __iterateUncached(fn, reverse) Seq.prototype.__iterate = function(fn, reverse) { return seqIterate(this, fn, reverse, true); }; // abstract __iteratorUncached(type, reverse) Seq.prototype.__iterator = function(type, reverse) { return seqIterator(this, type, reverse, true); }; createClass(KeyedSeq, Seq); function KeyedSeq(value) { return value === null || value === undefined ? emptySequence().toKeyedSeq() : isIterable(value) ? (isKeyed(value) ? value.toSeq() : value.fromEntrySeq()) : keyedSeqFromValue(value); } KeyedSeq.of = function(/*...values*/) { return KeyedSeq(arguments); }; KeyedSeq.prototype.toKeyedSeq = function() { return this; }; KeyedSeq.prototype.toSeq = function() { return this; }; createClass(IndexedSeq, Seq); function IndexedSeq(value) { return value === null || value === undefined ? emptySequence() : !isIterable(value) ? indexedSeqFromValue(value) : isKeyed(value) ? value.entrySeq() : value.toIndexedSeq(); } IndexedSeq.of = function(/*...values*/) { return IndexedSeq(arguments); }; IndexedSeq.prototype.toIndexedSeq = function() { return this; }; IndexedSeq.prototype.toString = function() { return this.__toString('Seq [', ']'); }; IndexedSeq.prototype.__iterate = function(fn, reverse) { return seqIterate(this, fn, reverse, false); }; IndexedSeq.prototype.__iterator = function(type, reverse) { return seqIterator(this, type, reverse, false); }; createClass(SetSeq, Seq); function SetSeq(value) { return ( value === null || value === undefined ? emptySequence() : !isIterable(value) ? indexedSeqFromValue(value) : isKeyed(value) ? value.entrySeq() : value ).toSetSeq(); } SetSeq.of = function(/*...values*/) { return SetSeq(arguments); }; SetSeq.prototype.toSetSeq = function() { return this; }; Seq.isSeq = isSeq; Seq.Keyed = KeyedSeq; Seq.Set = SetSeq; Seq.Indexed = IndexedSeq; var IS_SEQ_SENTINEL = '@@__IMMUTABLE_SEQ__@@'; Seq.prototype[IS_SEQ_SENTINEL] = true; // #pragma Root Sequences createClass(ArraySeq, IndexedSeq); function ArraySeq(array) { this._array = array; this.size = array.length; } ArraySeq.prototype.get = function(index, notSetValue) { return this.has(index) ? this._array[wrapIndex(this, index)] : notSetValue; }; ArraySeq.prototype.__iterate = function(fn, reverse) { var array = this._array; var maxIndex = array.length - 1; for (var ii = 0; ii <= maxIndex; ii++) { if (fn(array[reverse ? maxIndex - ii : ii], ii, this) === false) { return ii + 1; } } return ii; }; ArraySeq.prototype.__iterator = function(type, reverse) { var array = this._array; var maxIndex = array.length - 1; var ii = 0; return new Iterator(function() {return ii > maxIndex ? iteratorDone() : iteratorValue(type, ii, array[reverse ? maxIndex - ii++ : ii++])} ); }; createClass(ObjectSeq, KeyedSeq); function ObjectSeq(object) { var keys = Object.keys(object); this._object = object; this._keys = keys; this.size = keys.length; } ObjectSeq.prototype.get = function(key, notSetValue) { if (notSetValue !== undefined && !this.has(key)) { return notSetValue; } return this._object[key]; }; ObjectSeq.prototype.has = function(key) { return this._object.hasOwnProperty(key); }; ObjectSeq.prototype.__iterate = function(fn, reverse) { var object = this._object; var keys = this._keys; var maxIndex = keys.length - 1; for (var ii = 0; ii <= maxIndex; ii++) { var key = keys[reverse ? maxIndex - ii : ii]; if (fn(object[key], key, this) === false) { return ii + 1; } } return ii; }; ObjectSeq.prototype.__iterator = function(type, reverse) { var object = this._object; var keys = this._keys; var maxIndex = keys.length - 1; var ii = 0; return new Iterator(function() { var key = keys[reverse ? maxIndex - ii : ii]; return ii++ > maxIndex ? iteratorDone() : iteratorValue(type, key, object[key]); }); }; ObjectSeq.prototype[IS_ORDERED_SENTINEL] = true; createClass(IterableSeq, IndexedSeq); function IterableSeq(iterable) { this._iterable = iterable; this.size = iterable.length || iterable.size; } IterableSeq.prototype.__iterateUncached = function(fn, reverse) { if (reverse) { return this.cacheResult().__iterate(fn, reverse); } var iterable = this._iterable; var iterator = getIterator(iterable); var iterations = 0; if (isIterator(iterator)) { var step; while (!(step = iterator.next()).done) { if (fn(step.value, iterations++, this) === false) { break; } } } return iterations; }; IterableSeq.prototype.__iteratorUncached = function(type, reverse) { if (reverse) { return this.cacheResult().__iterator(type, reverse); } var iterable = this._iterable; var iterator = getIterator(iterable); if (!isIterator(iterator)) { return new Iterator(iteratorDone); } var iterations = 0; return new Iterator(function() { var step = iterator.next(); return step.done ? step : iteratorValue(type, iterations++, step.value); }); }; createClass(IteratorSeq, IndexedSeq); function IteratorSeq(iterator) { this._iterator = iterator; this._iteratorCache = []; } IteratorSeq.prototype.__iterateUncached = function(fn, reverse) { if (reverse) { return this.cacheResult().__iterate(fn, reverse); } var iterator = this._iterator; var cache = this._iteratorCache; var iterations = 0; while (iterations < cache.length) { if (fn(cache[iterations], iterations++, this) === false) { return iterations; } } var step; while (!(step = iterator.next()).done) { var val = step.value; cache[iterations] = val; if (fn(val, iterations++, this) === false) { break; } } return iterations; }; IteratorSeq.prototype.__iteratorUncached = function(type, reverse) { if (reverse) { return this.cacheResult().__iterator(type, reverse); } var iterator = this._iterator; var cache = this._iteratorCache; var iterations = 0; return new Iterator(function() { if (iterations >= cache.length) { var step = iterator.next(); if (step.done) { return step; } cache[iterations] = step.value; } return iteratorValue(type, iterations, cache[iterations++]); }); }; // # pragma Helper functions function isSeq(maybeSeq) { return !!(maybeSeq && maybeSeq[IS_SEQ_SENTINEL]); } var EMPTY_SEQ; function emptySequence() { return EMPTY_SEQ || (EMPTY_SEQ = new ArraySeq([])); } function keyedSeqFromValue(value) { var seq = Array.isArray(value) ? new ArraySeq(value).fromEntrySeq() : isIterator(value) ? new IteratorSeq(value).fromEntrySeq() : hasIterator(value) ? new IterableSeq(value).fromEntrySeq() : typeof value === 'object' ? new ObjectSeq(value) : undefined; if (!seq) { throw new TypeError( 'Expected Array or iterable object of [k, v] entries, '+ 'or keyed object: ' + value ); } return seq; } function indexedSeqFromValue(value) { var seq = maybeIndexedSeqFromValue(value); if (!seq) { throw new TypeError( 'Expected Array or iterable object of values: ' + value ); } return seq; } function seqFromValue(value) { var seq = maybeIndexedSeqFromValue(value) || (typeof value === 'object' && new ObjectSeq(value)); if (!seq) { throw new TypeError( 'Expected Array or iterable object of values, or keyed object: ' + value ); } return seq; } function maybeIndexedSeqFromValue(value) { return ( isArrayLike(value) ? new ArraySeq(value) : isIterator(value) ? new IteratorSeq(value) : hasIterator(value) ? new IterableSeq(value) : undefined ); } function seqIterate(seq, fn, reverse, useKeys) { var cache = seq._cache; if (cache) { var maxIndex = cache.length - 1; for (var ii = 0; ii <= maxIndex; ii++) { var entry = cache[reverse ? maxIndex - ii : ii]; if (fn(entry[1], useKeys ? entry[0] : ii, seq) === false) { return ii + 1; } } return ii; } return seq.__iterateUncached(fn, reverse); } function seqIterator(seq, type, reverse, useKeys) { var cache = seq._cache; if (cache) { var maxIndex = cache.length - 1; var ii = 0; return new Iterator(function() { var entry = cache[reverse ? maxIndex - ii : ii]; return ii++ > maxIndex ? iteratorDone() : iteratorValue(type, useKeys ? entry[0] : ii - 1, entry[1]); }); } return seq.__iteratorUncached(type, reverse); } createClass(Collection, Iterable); function Collection() { throw TypeError('Abstract'); } createClass(KeyedCollection, Collection);function KeyedCollection() {} createClass(IndexedCollection, Collection);function IndexedCollection() {} createClass(SetCollection, Collection);function SetCollection() {} Collection.Keyed = KeyedCollection; Collection.Indexed = IndexedCollection; Collection.Set = SetCollection; /** * An extension of the "same-value" algorithm as [described for use by ES6 Map * and Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map#Key_equality) * * NaN is considered the same as NaN, however -0 and 0 are considered the same * value, which is different from the algorithm described by * [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is). * * This is extended further to allow Objects to describe the values they * represent, by way of `valueOf` or `equals` (and `hashCode`). * * Note: because of this extension, the key equality of Immutable.Map and the * value equality of Immutable.Set will differ from ES6 Map and Set. * * ### Defining custom values * * The easiest way to describe the value an object represents is by implementing * `valueOf`. For example, `Date` represents a value by returning a unix * timestamp for `valueOf`: * * var date1 = new Date(1234567890000); // Fri Feb 13 2009 ... * var date2 = new Date(1234567890000); * date1.valueOf(); // 1234567890000 * assert( date1 !== date2 ); * assert( Immutable.is( date1, date2 ) ); * * Note: overriding `valueOf` may have other implications if you use this object * where JavaScript expects a primitive, such as implicit string coercion. * * For more complex types, especially collections, implementing `valueOf` may * not be performant. An alternative is to implement `equals` and `hashCode`. * * `equals` takes another object, presumably of similar type, and returns true * if the it is equal. Equality is symmetrical, so the same result should be * returned if this and the argument are flipped. * * assert( a.equals(b) === b.equals(a) ); * * `hashCode` returns a 32bit integer number representing the object which will * be used to determine how to store the value object in a Map or Set. You must * provide both or neither methods, one must not exist without the other. * * Also, an important relationship between these methods must be upheld: if two * values are equal, they *must* return the same hashCode. If the values are not * equal, they might have the same hashCode; this is called a hash collision, * and while undesirable for performance reasons, it is acceptable. * * if (a.equals(b)) { * assert( a.hashCode() === b.hashCode() ); * } * * All Immutable collections implement `equals` and `hashCode`. * */ function is(valueA, valueB) { if (valueA === valueB || (valueA !== valueA && valueB !== valueB)) { return true; } if (!valueA || !valueB) { return false; } if (typeof valueA.valueOf === 'function' && typeof valueB.valueOf === 'function') { valueA = valueA.valueOf(); valueB = valueB.valueOf(); } return typeof valueA.equals === 'function' && typeof valueB.equals === 'function' ? valueA.equals(valueB) : valueA === valueB || (valueA !== valueA && valueB !== valueB); } function fromJS(json, converter) { return converter ? fromJSWith(converter, json, '', {'': json}) : fromJSDefault(json); } function fromJSWith(converter, json, key, parentJSON) { if (Array.isArray(json)) { return converter.call(parentJSON, key, IndexedSeq(json).map(function(v, k) {return fromJSWith(converter, v, k, json)})); } if (isPlainObj(json)) { return converter.call(parentJSON, key, KeyedSeq(json).map(function(v, k) {return fromJSWith(converter, v, k, json)})); } return json; } function fromJSDefault(json) { if (Array.isArray(json)) { return IndexedSeq(json).map(fromJSDefault).toList(); } if (isPlainObj(json)) { return KeyedSeq(json).map(fromJSDefault).toMap(); } return json; } function isPlainObj(value) { return value && value.constructor === Object; } var Math__imul = typeof Math.imul === 'function' && Math.imul(0xffffffff, 2) === -2 ? Math.imul : function Math__imul(a, b) { a = a | 0; // int b = b | 0; // int var c = a & 0xffff; var d = b & 0xffff; // Shift by 0 fixes the sign on the high part. return (c * d) + ((((a >>> 16) * d + c * (b >>> 16)) << 16) >>> 0) | 0; // int }; // v8 has an optimization for storing 31-bit signed numbers. // Values which have either 00 or 11 as the high order bits qualify. // This function drops the highest order bit in a signed number, maintaining // the sign bit. function smi(i32) { return ((i32 >>> 1) & 0x40000000) | (i32 & 0xBFFFFFFF); } function hash(o) { if (o === false || o === null || o === undefined) { return 0; } if (typeof o.valueOf === 'function') { o = o.valueOf(); if (o === false || o === null || o === undefined) { return 0; } } if (o === true) { return 1; } var type = typeof o; if (type === 'number') { var h = o | 0; if (h !== o) { h ^= o * 0xFFFFFFFF; } while (o > 0xFFFFFFFF) { o /= 0xFFFFFFFF; h ^= o; } return smi(h); } if (type === 'string') { return o.length > STRING_HASH_CACHE_MIN_STRLEN ? cachedHashString(o) : hashString(o); } if (typeof o.hashCode === 'function') { return o.hashCode(); } return hashJSObj(o); } function cachedHashString(string) { var hash = stringHashCache[string]; if (hash === undefined) { hash = hashString(string); if (STRING_HASH_CACHE_SIZE === STRING_HASH_CACHE_MAX_SIZE) { STRING_HASH_CACHE_SIZE = 0; stringHashCache = {}; } STRING_HASH_CACHE_SIZE++; stringHashCache[string] = hash; } return hash; } // http://jsperf.com/hashing-strings function hashString(string) { // This is the hash from JVM // The hash code for a string is computed as // s[0] * 31 ^ (n - 1) + s[1] * 31 ^ (n - 2) + ... + s[n - 1], // where s[i] is the ith character of the string and n is the length of // the string. We "mod" the result to make it between 0 (inclusive) and 2^31 // (exclusive) by dropping high bits. var hash = 0; for (var ii = 0; ii < string.length; ii++) { hash = 31 * hash + string.charCodeAt(ii) | 0; } return smi(hash); } function hashJSObj(obj) { var hash = weakMap && weakMap.get(obj); if (hash) return hash; hash = obj[UID_HASH_KEY]; if (hash) return hash; if (!canDefineProperty) { hash = obj.propertyIsEnumerable && obj.propertyIsEnumerable[UID_HASH_KEY]; if (hash) return hash; hash = getIENodeHash(obj); if (hash) return hash; } if (Object.isExtensible && !Object.isExtensible(obj)) { throw new Error('Non-extensible objects are not allowed as keys.'); } hash = ++objHashUID; if (objHashUID & 0x40000000) { objHashUID = 0; } if (weakMap) { weakMap.set(obj, hash); } else if (canDefineProperty) { Object.defineProperty(obj, UID_HASH_KEY, { 'enumerable': false, 'configurable': false, 'writable': false, 'value': hash }); } else if (obj.propertyIsEnumerable && obj.propertyIsEnumerable === obj.constructor.prototype.propertyIsEnumerable) { // Since we can't define a non-enumerable property on the object // we'll hijack one of the less-used non-enumerable properties to // save our hash on it. Since this is a function it will not show up in // `JSON.stringify` which is what we want. obj.propertyIsEnumerable = function() { return this.constructor.prototype.propertyIsEnumerable.apply(this, arguments); }; obj.propertyIsEnumerable[UID_HASH_KEY] = hash; } else if (obj.nodeType) { // At this point we couldn't get the IE `uniqueID` to use as a hash // and we couldn't use a non-enumerable property to exploit the // dontEnum bug so we simply add the `UID_HASH_KEY` on the node // itself. obj[UID_HASH_KEY] = hash; } else { throw new Error('Unable to set a non-enumerable property on object.'); } return hash; } // True if Object.defineProperty works as expected. IE8 fails this test. var canDefineProperty = (function() { try { Object.defineProperty({}, 'x', {}); return true; } catch (e) { return false; } }()); // IE has a `uniqueID` property on DOM nodes. We can construct the hash from it // and avoid memory leaks from the IE cloneNode bug. function getIENode