mirror of
				https://github.com/flynx/ImageGrid.git
				synced 2025-10-30 19:00:09 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			1668 lines
		
	
	
		
			45 KiB
		
	
	
	
		
			JavaScript
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1668 lines
		
	
	
		
			45 KiB
		
	
	
	
		
			JavaScript
		
	
	
		
			Executable File
		
	
	
	
	
| !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.virtualDom=e()}}(function(){var define,module,exports;return (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 createElement = require("./vdom/create-element.js")
 | |
| 
 | |
| module.exports = createElement
 | |
| 
 | |
| },{"./vdom/create-element.js":15}],2:[function(require,module,exports){
 | |
| var diff = require("./vtree/diff.js")
 | |
| 
 | |
| module.exports = diff
 | |
| 
 | |
| },{"./vtree/diff.js":35}],3:[function(require,module,exports){
 | |
| var h = require("./virtual-hyperscript/index.js")
 | |
| 
 | |
| module.exports = h
 | |
| 
 | |
| },{"./virtual-hyperscript/index.js":22}],4:[function(require,module,exports){
 | |
| var diff = require("./diff.js")
 | |
| var patch = require("./patch.js")
 | |
| var h = require("./h.js")
 | |
| var create = require("./create-element.js")
 | |
| var VNode = require('./vnode/vnode.js')
 | |
| var VText = require('./vnode/vtext.js')
 | |
| 
 | |
| module.exports = {
 | |
|     diff: diff,
 | |
|     patch: patch,
 | |
|     h: h,
 | |
|     create: create,
 | |
|     VNode: VNode,
 | |
|     VText: VText
 | |
| }
 | |
| 
 | |
| },{"./create-element.js":1,"./diff.js":2,"./h.js":3,"./patch.js":13,"./vnode/vnode.js":31,"./vnode/vtext.js":33}],5:[function(require,module,exports){
 | |
| /*!
 | |
|  * Cross-Browser Split 1.1.1
 | |
|  * Copyright 2007-2012 Steven Levithan <stevenlevithan.com>
 | |
|  * Available under the MIT License
 | |
|  * ECMAScript compliant, uniform cross-browser split method
 | |
|  */
 | |
| 
 | |
| /**
 | |
|  * Splits a string into an array of strings using a regex or string separator. Matches of the
 | |
|  * separator are not included in the result array. However, if `separator` is a regex that contains
 | |
|  * capturing groups, backreferences are spliced into the result each time `separator` is matched.
 | |
|  * Fixes browser bugs compared to the native `String.prototype.split` and can be used reliably
 | |
|  * cross-browser.
 | |
|  * @param {String} str String to split.
 | |
|  * @param {RegExp|String} separator Regex or string to use for separating the string.
 | |
|  * @param {Number} [limit] Maximum number of items to include in the result array.
 | |
|  * @returns {Array} Array of substrings.
 | |
|  * @example
 | |
|  *
 | |
|  * // Basic use
 | |
|  * split('a b c d', ' ');
 | |
|  * // -> ['a', 'b', 'c', 'd']
 | |
|  *
 | |
|  * // With limit
 | |
|  * split('a b c d', ' ', 2);
 | |
|  * // -> ['a', 'b']
 | |
|  *
 | |
|  * // Backreferences in result array
 | |
|  * split('..word1 word2..', /([a-z]+)(\d+)/i);
 | |
|  * // -> ['..', 'word', '1', ' ', 'word', '2', '..']
 | |
|  */
 | |
| module.exports = (function split(undef) {
 | |
| 
 | |
|   var nativeSplit = String.prototype.split,
 | |
|     compliantExecNpcg = /()??/.exec("")[1] === undef,
 | |
|     // NPCG: nonparticipating capturing group
 | |
|     self;
 | |
| 
 | |
|   self = function(str, separator, limit) {
 | |
|     // If `separator` is not a regex, use `nativeSplit`
 | |
|     if (Object.prototype.toString.call(separator) !== "[object RegExp]") {
 | |
|       return nativeSplit.call(str, separator, limit);
 | |
|     }
 | |
|     var output = [],
 | |
|       flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.extended ? "x" : "") + // Proposed for ES6
 | |
|       (separator.sticky ? "y" : ""),
 | |
|       // Firefox 3+
 | |
|       lastLastIndex = 0,
 | |
|       // Make `global` and avoid `lastIndex` issues by working with a copy
 | |
|       separator = new RegExp(separator.source, flags + "g"),
 | |
|       separator2, match, lastIndex, lastLength;
 | |
|     str += ""; // Type-convert
 | |
|     if (!compliantExecNpcg) {
 | |
|       // Doesn't need flags gy, but they don't hurt
 | |
|       separator2 = new RegExp("^" + separator.source + "$(?!\\s)", flags);
 | |
|     }
 | |
|     /* Values for `limit`, per the spec:
 | |
|      * If undefined: 4294967295 // Math.pow(2, 32) - 1
 | |
|      * If 0, Infinity, or NaN: 0
 | |
|      * If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296;
 | |
|      * If negative number: 4294967296 - Math.floor(Math.abs(limit))
 | |
|      * If other: Type-convert, then use the above rules
 | |
|      */
 | |
|     limit = limit === undef ? -1 >>> 0 : // Math.pow(2, 32) - 1
 | |
|     limit >>> 0; // ToUint32(limit)
 | |
|     while (match = separator.exec(str)) {
 | |
|       // `separator.lastIndex` is not reliable cross-browser
 | |
|       lastIndex = match.index + match[0].length;
 | |
|       if (lastIndex > lastLastIndex) {
 | |
|         output.push(str.slice(lastLastIndex, match.index));
 | |
|         // Fix browsers whose `exec` methods don't consistently return `undefined` for
 | |
|         // nonparticipating capturing groups
 | |
|         if (!compliantExecNpcg && match.length > 1) {
 | |
|           match[0].replace(separator2, function() {
 | |
|             for (var i = 1; i < arguments.length - 2; i++) {
 | |
|               if (arguments[i] === undef) {
 | |
|                 match[i] = undef;
 | |
|               }
 | |
|             }
 | |
|           });
 | |
|         }
 | |
|         if (match.length > 1 && match.index < str.length) {
 | |
|           Array.prototype.push.apply(output, match.slice(1));
 | |
|         }
 | |
|         lastLength = match[0].length;
 | |
|         lastLastIndex = lastIndex;
 | |
|         if (output.length >= limit) {
 | |
|           break;
 | |
|         }
 | |
|       }
 | |
|       if (separator.lastIndex === match.index) {
 | |
|         separator.lastIndex++; // Avoid an infinite loop
 | |
|       }
 | |
|     }
 | |
|     if (lastLastIndex === str.length) {
 | |
|       if (lastLength || !separator.test("")) {
 | |
|         output.push("");
 | |
|       }
 | |
|     } else {
 | |
|       output.push(str.slice(lastLastIndex));
 | |
|     }
 | |
|     return output.length > limit ? output.slice(0, limit) : output;
 | |
|   };
 | |
| 
 | |
|   return self;
 | |
| })();
 | |
| 
 | |
| },{}],6:[function(require,module,exports){
 | |
| 
 | |
| },{}],7:[function(require,module,exports){
 | |
| 'use strict';
 | |
| 
 | |
| var OneVersionConstraint = require('individual/one-version');
 | |
| 
 | |
| var MY_VERSION = '7';
 | |
| OneVersionConstraint('ev-store', MY_VERSION);
 | |
| 
 | |
| var hashKey = '__EV_STORE_KEY@' + MY_VERSION;
 | |
| 
 | |
| module.exports = EvStore;
 | |
| 
 | |
| function EvStore(elem) {
 | |
|     var hash = elem[hashKey];
 | |
| 
 | |
|     if (!hash) {
 | |
|         hash = elem[hashKey] = {};
 | |
|     }
 | |
| 
 | |
|     return hash;
 | |
| }
 | |
| 
 | |
| },{"individual/one-version":9}],8:[function(require,module,exports){
 | |
| (function (global){
 | |
| 'use strict';
 | |
| 
 | |
| /*global window, global*/
 | |
| 
 | |
| var root = typeof window !== 'undefined' ?
 | |
|     window : typeof global !== 'undefined' ?
 | |
|     global : {};
 | |
| 
 | |
| module.exports = Individual;
 | |
| 
 | |
| function Individual(key, value) {
 | |
|     if (key in root) {
 | |
|         return root[key];
 | |
|     }
 | |
| 
 | |
|     root[key] = value;
 | |
| 
 | |
|     return value;
 | |
| }
 | |
| 
 | |
| }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
 | |
| },{}],9:[function(require,module,exports){
 | |
| 'use strict';
 | |
| 
 | |
| var Individual = require('./index.js');
 | |
| 
 | |
| module.exports = OneVersion;
 | |
| 
 | |
| function OneVersion(moduleName, version, defaultValue) {
 | |
|     var key = '__INDIVIDUAL_ONE_VERSION_' + moduleName;
 | |
|     var enforceKey = key + '_ENFORCE_SINGLETON';
 | |
| 
 | |
|     var versionValue = Individual(enforceKey, version);
 | |
| 
 | |
|     if (versionValue !== version) {
 | |
|         throw new Error('Can only have one copy of ' +
 | |
|             moduleName + '.\n' +
 | |
|             'You already have version ' + versionValue +
 | |
|             ' installed.\n' +
 | |
|             'This means you cannot install version ' + version);
 | |
|     }
 | |
| 
 | |
|     return Individual(key, defaultValue);
 | |
| }
 | |
| 
 | |
| },{"./index.js":8}],10:[function(require,module,exports){
 | |
| (function (global){
 | |
| var topLevel = typeof global !== 'undefined' ? global :
 | |
|     typeof window !== 'undefined' ? window : {}
 | |
| var minDoc = require('min-document');
 | |
| 
 | |
| if (typeof document !== 'undefined') {
 | |
|     module.exports = document;
 | |
| } else {
 | |
|     var doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'];
 | |
| 
 | |
|     if (!doccy) {
 | |
|         doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'] = minDoc;
 | |
|     }
 | |
| 
 | |
|     module.exports = doccy;
 | |
| }
 | |
| 
 | |
| }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
 | |
| },{"min-document":6}],11:[function(require,module,exports){
 | |
| "use strict";
 | |
| 
 | |
| module.exports = function isObject(x) {
 | |
| 	return typeof x === "object" && x !== null;
 | |
| };
 | |
| 
 | |
| },{}],12:[function(require,module,exports){
 | |
| var nativeIsArray = Array.isArray
 | |
| var toString = Object.prototype.toString
 | |
| 
 | |
| module.exports = nativeIsArray || isArray
 | |
| 
 | |
| function isArray(obj) {
 | |
|     return toString.call(obj) === "[object Array]"
 | |
| }
 | |
| 
 | |
| },{}],13:[function(require,module,exports){
 | |
| var patch = require("./vdom/patch.js")
 | |
| 
 | |
| module.exports = patch
 | |
| 
 | |
| },{"./vdom/patch.js":18}],14:[function(require,module,exports){
 | |
| var isObject = require("is-object")
 | |
| var isHook = require("../vnode/is-vhook.js")
 | |
| 
 | |
| module.exports = applyProperties
 | |
| 
 | |
| function applyProperties(node, props, previous) {
 | |
|     for (var propName in props) {
 | |
|         var propValue = props[propName]
 | |
| 
 | |
|         if (propValue === undefined) {
 | |
|             removeProperty(node, propName, propValue, previous);
 | |
|         } else if (isHook(propValue)) {
 | |
|             removeProperty(node, propName, propValue, previous)
 | |
|             if (propValue.hook) {
 | |
|                 propValue.hook(node,
 | |
|                     propName,
 | |
|                     previous ? previous[propName] : undefined)
 | |
|             }
 | |
|         } else {
 | |
|             if (isObject(propValue)) {
 | |
|                 patchObject(node, props, previous, propName, propValue);
 | |
|             } else {
 | |
|                 node[propName] = propValue
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| function removeProperty(node, propName, propValue, previous) {
 | |
|     if (previous) {
 | |
|         var previousValue = previous[propName]
 | |
| 
 | |
|         if (!isHook(previousValue)) {
 | |
|             if (propName === "attributes") {
 | |
|                 for (var attrName in previousValue) {
 | |
|                     node.removeAttribute(attrName)
 | |
|                 }
 | |
|             } else if (propName === "style") {
 | |
|                 for (var i in previousValue) {
 | |
|                     node.style[i] = ""
 | |
|                 }
 | |
|             } else if (typeof previousValue === "string") {
 | |
|                 node[propName] = ""
 | |
|             } else {
 | |
|                 node[propName] = null
 | |
|             }
 | |
|         } else if (previousValue.unhook) {
 | |
|             previousValue.unhook(node, propName, propValue)
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| function patchObject(node, props, previous, propName, propValue) {
 | |
|     var previousValue = previous ? previous[propName] : undefined
 | |
| 
 | |
|     // Set attributes
 | |
|     if (propName === "attributes") {
 | |
|         for (var attrName in propValue) {
 | |
|             var attrValue = propValue[attrName]
 | |
| 
 | |
|             if (attrValue === undefined) {
 | |
|                 node.removeAttribute(attrName)
 | |
|             } else {
 | |
|                 node.setAttribute(attrName, attrValue)
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         return
 | |
|     }
 | |
| 
 | |
|     if(previousValue && isObject(previousValue) &&
 | |
|         getPrototype(previousValue) !== getPrototype(propValue)) {
 | |
|         node[propName] = propValue
 | |
|         return
 | |
|     }
 | |
| 
 | |
|     if (!isObject(node[propName])) {
 | |
|         node[propName] = {}
 | |
|     }
 | |
| 
 | |
|     var replacer = propName === "style" ? "" : undefined
 | |
| 
 | |
|     for (var k in propValue) {
 | |
|         var value = propValue[k]
 | |
|         node[propName][k] = (value === undefined) ? replacer : value
 | |
|     }
 | |
| }
 | |
| 
 | |
| function getPrototype(value) {
 | |
|     if (Object.getPrototypeOf) {
 | |
|         return Object.getPrototypeOf(value)
 | |
|     } else if (value.__proto__) {
 | |
|         return value.__proto__
 | |
|     } else if (value.constructor) {
 | |
|         return value.constructor.prototype
 | |
|     }
 | |
| }
 | |
| 
 | |
| },{"../vnode/is-vhook.js":26,"is-object":11}],15:[function(require,module,exports){
 | |
| var document = require("global/document")
 | |
| 
 | |
| var applyProperties = require("./apply-properties")
 | |
| 
 | |
| var isVNode = require("../vnode/is-vnode.js")
 | |
| var isVText = require("../vnode/is-vtext.js")
 | |
| var isWidget = require("../vnode/is-widget.js")
 | |
| var handleThunk = require("../vnode/handle-thunk.js")
 | |
| 
 | |
| module.exports = createElement
 | |
| 
 | |
| function createElement(vnode, opts) {
 | |
|     var doc = opts ? opts.document || document : document
 | |
|     var warn = opts ? opts.warn : null
 | |
| 
 | |
|     vnode = handleThunk(vnode).a
 | |
| 
 | |
|     if (isWidget(vnode)) {
 | |
|         return vnode.init()
 | |
|     } else if (isVText(vnode)) {
 | |
|         return doc.createTextNode(vnode.text)
 | |
|     } else if (!isVNode(vnode)) {
 | |
|         if (warn) {
 | |
|             warn("Item is not a valid virtual dom node", vnode)
 | |
|         }
 | |
|         return null
 | |
|     }
 | |
| 
 | |
|     var node = (vnode.namespace === null) ?
 | |
|         doc.createElement(vnode.tagName) :
 | |
|         doc.createElementNS(vnode.namespace, vnode.tagName)
 | |
| 
 | |
|     var props = vnode.properties
 | |
|     applyProperties(node, props)
 | |
| 
 | |
|     var children = vnode.children
 | |
| 
 | |
|     for (var i = 0; i < children.length; i++) {
 | |
|         var childNode = createElement(children[i], opts)
 | |
|         if (childNode) {
 | |
|             node.appendChild(childNode)
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return node
 | |
| }
 | |
| 
 | |
| },{"../vnode/handle-thunk.js":24,"../vnode/is-vnode.js":27,"../vnode/is-vtext.js":28,"../vnode/is-widget.js":29,"./apply-properties":14,"global/document":10}],16:[function(require,module,exports){
 | |
| // Maps a virtual DOM tree onto a real DOM tree in an efficient manner.
 | |
| // We don't want to read all of the DOM nodes in the tree so we use
 | |
| // the in-order tree indexing to eliminate recursion down certain branches.
 | |
| // We only recurse into a DOM node if we know that it contains a child of
 | |
| // interest.
 | |
| 
 | |
| var noChild = {}
 | |
| 
 | |
| module.exports = domIndex
 | |
| 
 | |
| function domIndex(rootNode, tree, indices, nodes) {
 | |
|     if (!indices || indices.length === 0) {
 | |
|         return {}
 | |
|     } else {
 | |
|         indices.sort(ascending)
 | |
|         return recurse(rootNode, tree, indices, nodes, 0)
 | |
|     }
 | |
| }
 | |
| 
 | |
| function recurse(rootNode, tree, indices, nodes, rootIndex) {
 | |
|     nodes = nodes || {}
 | |
| 
 | |
| 
 | |
|     if (rootNode) {
 | |
|         if (indexInRange(indices, rootIndex, rootIndex)) {
 | |
|             nodes[rootIndex] = rootNode
 | |
|         }
 | |
| 
 | |
|         var vChildren = tree.children
 | |
| 
 | |
|         if (vChildren) {
 | |
| 
 | |
|             var childNodes = rootNode.childNodes
 | |
| 
 | |
|             for (var i = 0; i < tree.children.length; i++) {
 | |
|                 rootIndex += 1
 | |
| 
 | |
|                 var vChild = vChildren[i] || noChild
 | |
|                 var nextIndex = rootIndex + (vChild.count || 0)
 | |
| 
 | |
|                 // skip recursion down the tree if there are no nodes down here
 | |
|                 if (indexInRange(indices, rootIndex, nextIndex)) {
 | |
|                     recurse(childNodes[i], vChild, indices, nodes, rootIndex)
 | |
|                 }
 | |
| 
 | |
|                 rootIndex = nextIndex
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return nodes
 | |
| }
 | |
| 
 | |
| // Binary search for an index in the interval [left, right]
 | |
| function indexInRange(indices, left, right) {
 | |
|     if (indices.length === 0) {
 | |
|         return false
 | |
|     }
 | |
| 
 | |
|     var minIndex = 0
 | |
|     var maxIndex = indices.length - 1
 | |
|     var currentIndex
 | |
|     var currentItem
 | |
| 
 | |
|     while (minIndex <= maxIndex) {
 | |
|         currentIndex = ((maxIndex + minIndex) / 2) >> 0
 | |
|         currentItem = indices[currentIndex]
 | |
| 
 | |
|         if (minIndex === maxIndex) {
 | |
|             return currentItem >= left && currentItem <= right
 | |
|         } else if (currentItem < left) {
 | |
|             minIndex = currentIndex + 1
 | |
|         } else  if (currentItem > right) {
 | |
|             maxIndex = currentIndex - 1
 | |
|         } else {
 | |
|             return true
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return false;
 | |
| }
 | |
| 
 | |
| function ascending(a, b) {
 | |
|     return a > b ? 1 : -1
 | |
| }
 | |
| 
 | |
| },{}],17:[function(require,module,exports){
 | |
| var applyProperties = require("./apply-properties")
 | |
| 
 | |
| var isWidget = require("../vnode/is-widget.js")
 | |
| var VPatch = require("../vnode/vpatch.js")
 | |
| 
 | |
| var updateWidget = require("./update-widget")
 | |
| 
 | |
| module.exports = applyPatch
 | |
| 
 | |
| function applyPatch(vpatch, domNode, renderOptions) {
 | |
|     var type = vpatch.type
 | |
|     var vNode = vpatch.vNode
 | |
|     var patch = vpatch.patch
 | |
| 
 | |
|     switch (type) {
 | |
|         case VPatch.REMOVE:
 | |
|             return removeNode(domNode, vNode)
 | |
|         case VPatch.INSERT:
 | |
|             return insertNode(domNode, patch, renderOptions)
 | |
|         case VPatch.VTEXT:
 | |
|             return stringPatch(domNode, vNode, patch, renderOptions)
 | |
|         case VPatch.WIDGET:
 | |
|             return widgetPatch(domNode, vNode, patch, renderOptions)
 | |
|         case VPatch.VNODE:
 | |
|             return vNodePatch(domNode, vNode, patch, renderOptions)
 | |
|         case VPatch.ORDER:
 | |
|             reorderChildren(domNode, patch)
 | |
|             return domNode
 | |
|         case VPatch.PROPS:
 | |
|             applyProperties(domNode, patch, vNode.properties)
 | |
|             return domNode
 | |
|         case VPatch.THUNK:
 | |
|             return replaceRoot(domNode,
 | |
|                 renderOptions.patch(domNode, patch, renderOptions))
 | |
|         default:
 | |
|             return domNode
 | |
|     }
 | |
| }
 | |
| 
 | |
| function removeNode(domNode, vNode) {
 | |
|     var parentNode = domNode.parentNode
 | |
| 
 | |
|     if (parentNode) {
 | |
|         parentNode.removeChild(domNode)
 | |
|     }
 | |
| 
 | |
|     destroyWidget(domNode, vNode);
 | |
| 
 | |
|     return null
 | |
| }
 | |
| 
 | |
| function insertNode(parentNode, vNode, renderOptions) {
 | |
|     var newNode = renderOptions.render(vNode, renderOptions)
 | |
| 
 | |
|     if (parentNode) {
 | |
|         parentNode.appendChild(newNode)
 | |
|     }
 | |
| 
 | |
|     return parentNode
 | |
| }
 | |
| 
 | |
| function stringPatch(domNode, leftVNode, vText, renderOptions) {
 | |
|     var newNode
 | |
| 
 | |
|     if (domNode.nodeType === 3) {
 | |
|         domNode.replaceData(0, domNode.length, vText.text)
 | |
|         newNode = domNode
 | |
|     } else {
 | |
|         var parentNode = domNode.parentNode
 | |
|         newNode = renderOptions.render(vText, renderOptions)
 | |
| 
 | |
|         if (parentNode && newNode !== domNode) {
 | |
|             parentNode.replaceChild(newNode, domNode)
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return newNode
 | |
| }
 | |
| 
 | |
| function widgetPatch(domNode, leftVNode, widget, renderOptions) {
 | |
|     var updating = updateWidget(leftVNode, widget)
 | |
|     var newNode
 | |
| 
 | |
|     if (updating) {
 | |
|         newNode = widget.update(leftVNode, domNode) || domNode
 | |
|     } else {
 | |
|         newNode = renderOptions.render(widget, renderOptions)
 | |
|     }
 | |
| 
 | |
|     var parentNode = domNode.parentNode
 | |
| 
 | |
|     if (parentNode && newNode !== domNode) {
 | |
|         parentNode.replaceChild(newNode, domNode)
 | |
|     }
 | |
| 
 | |
|     if (!updating) {
 | |
|         destroyWidget(domNode, leftVNode)
 | |
|     }
 | |
| 
 | |
|     return newNode
 | |
| }
 | |
| 
 | |
| function vNodePatch(domNode, leftVNode, vNode, renderOptions) {
 | |
|     var parentNode = domNode.parentNode
 | |
|     var newNode = renderOptions.render(vNode, renderOptions)
 | |
| 
 | |
|     if (parentNode && newNode !== domNode) {
 | |
|         parentNode.replaceChild(newNode, domNode)
 | |
|     }
 | |
| 
 | |
|     return newNode
 | |
| }
 | |
| 
 | |
| function destroyWidget(domNode, w) {
 | |
|     if (typeof w.destroy === "function" && isWidget(w)) {
 | |
|         w.destroy(domNode)
 | |
|     }
 | |
| }
 | |
| 
 | |
| function reorderChildren(domNode, moves) {
 | |
|     var childNodes = domNode.childNodes
 | |
|     var keyMap = {}
 | |
|     var node
 | |
|     var remove
 | |
|     var insert
 | |
| 
 | |
|     for (var i = 0; i < moves.removes.length; i++) {
 | |
|         remove = moves.removes[i]
 | |
|         node = childNodes[remove.from]
 | |
|         if (remove.key) {
 | |
|             keyMap[remove.key] = node
 | |
|         }
 | |
|         domNode.removeChild(node)
 | |
|     }
 | |
| 
 | |
|     var length = childNodes.length
 | |
|     for (var j = 0; j < moves.inserts.length; j++) {
 | |
|         insert = moves.inserts[j]
 | |
|         node = keyMap[insert.key]
 | |
|         // this is the weirdest bug i've ever seen in webkit
 | |
|         domNode.insertBefore(node, insert.to >= length++ ? null : childNodes[insert.to])
 | |
|     }
 | |
| }
 | |
| 
 | |
| function replaceRoot(oldRoot, newRoot) {
 | |
|     if (oldRoot && newRoot && oldRoot !== newRoot && oldRoot.parentNode) {
 | |
|         oldRoot.parentNode.replaceChild(newRoot, oldRoot)
 | |
|     }
 | |
| 
 | |
|     return newRoot;
 | |
| }
 | |
| 
 | |
| },{"../vnode/is-widget.js":29,"../vnode/vpatch.js":32,"./apply-properties":14,"./update-widget":19}],18:[function(require,module,exports){
 | |
| var document = require("global/document")
 | |
| var isArray = require("x-is-array")
 | |
| 
 | |
| var render = require("./create-element")
 | |
| var domIndex = require("./dom-index")
 | |
| var patchOp = require("./patch-op")
 | |
| module.exports = patch
 | |
| 
 | |
| function patch(rootNode, patches, renderOptions) {
 | |
|     renderOptions = renderOptions || {}
 | |
|     renderOptions.patch = renderOptions.patch && renderOptions.patch !== patch
 | |
|         ? renderOptions.patch
 | |
|         : patchRecursive
 | |
|     renderOptions.render = renderOptions.render || render
 | |
| 
 | |
|     return renderOptions.patch(rootNode, patches, renderOptions)
 | |
| }
 | |
| 
 | |
| function patchRecursive(rootNode, patches, renderOptions) {
 | |
|     var indices = patchIndices(patches)
 | |
| 
 | |
|     if (indices.length === 0) {
 | |
|         return rootNode
 | |
|     }
 | |
| 
 | |
|     var index = domIndex(rootNode, patches.a, indices)
 | |
|     var ownerDocument = rootNode.ownerDocument
 | |
| 
 | |
|     if (!renderOptions.document && ownerDocument !== document) {
 | |
|         renderOptions.document = ownerDocument
 | |
|     }
 | |
| 
 | |
|     for (var i = 0; i < indices.length; i++) {
 | |
|         var nodeIndex = indices[i]
 | |
|         rootNode = applyPatch(rootNode,
 | |
|             index[nodeIndex],
 | |
|             patches[nodeIndex],
 | |
|             renderOptions)
 | |
|     }
 | |
| 
 | |
|     return rootNode
 | |
| }
 | |
| 
 | |
| function applyPatch(rootNode, domNode, patchList, renderOptions) {
 | |
|     if (!domNode) {
 | |
|         return rootNode
 | |
|     }
 | |
| 
 | |
|     var newNode
 | |
| 
 | |
|     if (isArray(patchList)) {
 | |
|         for (var i = 0; i < patchList.length; i++) {
 | |
|             newNode = patchOp(patchList[i], domNode, renderOptions)
 | |
| 
 | |
|             if (domNode === rootNode) {
 | |
|                 rootNode = newNode
 | |
|             }
 | |
|         }
 | |
|     } else {
 | |
|         newNode = patchOp(patchList, domNode, renderOptions)
 | |
| 
 | |
|         if (domNode === rootNode) {
 | |
|             rootNode = newNode
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return rootNode
 | |
| }
 | |
| 
 | |
| function patchIndices(patches) {
 | |
|     var indices = []
 | |
| 
 | |
|     for (var key in patches) {
 | |
|         if (key !== "a") {
 | |
|             indices.push(Number(key))
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return indices
 | |
| }
 | |
| 
 | |
| },{"./create-element":15,"./dom-index":16,"./patch-op":17,"global/document":10,"x-is-array":12}],19:[function(require,module,exports){
 | |
| var isWidget = require("../vnode/is-widget.js")
 | |
| 
 | |
| module.exports = updateWidget
 | |
| 
 | |
| function updateWidget(a, b) {
 | |
|     if (isWidget(a) && isWidget(b)) {
 | |
|         if ("name" in a && "name" in b) {
 | |
|             return a.id === b.id
 | |
|         } else {
 | |
|             return a.init === b.init
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return false
 | |
| }
 | |
| 
 | |
| },{"../vnode/is-widget.js":29}],20:[function(require,module,exports){
 | |
| 'use strict';
 | |
| 
 | |
| var EvStore = require('ev-store');
 | |
| 
 | |
| module.exports = EvHook;
 | |
| 
 | |
| function EvHook(value) {
 | |
|     if (!(this instanceof EvHook)) {
 | |
|         return new EvHook(value);
 | |
|     }
 | |
| 
 | |
|     this.value = value;
 | |
| }
 | |
| 
 | |
| EvHook.prototype.hook = function (node, propertyName) {
 | |
|     var es = EvStore(node);
 | |
|     var propName = propertyName.substr(3);
 | |
| 
 | |
|     es[propName] = this.value;
 | |
| };
 | |
| 
 | |
| EvHook.prototype.unhook = function(node, propertyName) {
 | |
|     var es = EvStore(node);
 | |
|     var propName = propertyName.substr(3);
 | |
| 
 | |
|     es[propName] = undefined;
 | |
| };
 | |
| 
 | |
| },{"ev-store":7}],21:[function(require,module,exports){
 | |
| 'use strict';
 | |
| 
 | |
| module.exports = SoftSetHook;
 | |
| 
 | |
| function SoftSetHook(value) {
 | |
|     if (!(this instanceof SoftSetHook)) {
 | |
|         return new SoftSetHook(value);
 | |
|     }
 | |
| 
 | |
|     this.value = value;
 | |
| }
 | |
| 
 | |
| SoftSetHook.prototype.hook = function (node, propertyName) {
 | |
|     if (node[propertyName] !== this.value) {
 | |
|         node[propertyName] = this.value;
 | |
|     }
 | |
| };
 | |
| 
 | |
| },{}],22:[function(require,module,exports){
 | |
| 'use strict';
 | |
| 
 | |
| var isArray = require('x-is-array');
 | |
| 
 | |
| var VNode = require('../vnode/vnode.js');
 | |
| var VText = require('../vnode/vtext.js');
 | |
| var isVNode = require('../vnode/is-vnode');
 | |
| var isVText = require('../vnode/is-vtext');
 | |
| var isWidget = require('../vnode/is-widget');
 | |
| var isHook = require('../vnode/is-vhook');
 | |
| var isVThunk = require('../vnode/is-thunk');
 | |
| 
 | |
| var parseTag = require('./parse-tag.js');
 | |
| var softSetHook = require('./hooks/soft-set-hook.js');
 | |
| var evHook = require('./hooks/ev-hook.js');
 | |
| 
 | |
| module.exports = h;
 | |
| 
 | |
| function h(tagName, properties, children) {
 | |
|     var childNodes = [];
 | |
|     var tag, props, key, namespace;
 | |
| 
 | |
|     if (!children && isChildren(properties)) {
 | |
|         children = properties;
 | |
|         props = {};
 | |
|     }
 | |
| 
 | |
|     props = props || properties || {};
 | |
|     tag = parseTag(tagName, props);
 | |
| 
 | |
|     // support keys
 | |
|     if (props.hasOwnProperty('key')) {
 | |
|         key = props.key;
 | |
|         props.key = undefined;
 | |
|     }
 | |
| 
 | |
|     // support namespace
 | |
|     if (props.hasOwnProperty('namespace')) {
 | |
|         namespace = props.namespace;
 | |
|         props.namespace = undefined;
 | |
|     }
 | |
| 
 | |
|     // fix cursor bug
 | |
|     if (tag === 'INPUT' &&
 | |
|         !namespace &&
 | |
|         props.hasOwnProperty('value') &&
 | |
|         props.value !== undefined &&
 | |
|         !isHook(props.value)
 | |
|     ) {
 | |
|         props.value = softSetHook(props.value);
 | |
|     }
 | |
| 
 | |
|     transformProperties(props);
 | |
| 
 | |
|     if (children !== undefined && children !== null) {
 | |
|         addChild(children, childNodes, tag, props);
 | |
|     }
 | |
| 
 | |
| 
 | |
|     return new VNode(tag, props, childNodes, key, namespace);
 | |
| }
 | |
| 
 | |
| function addChild(c, childNodes, tag, props) {
 | |
|     if (typeof c === 'string') {
 | |
|         childNodes.push(new VText(c));
 | |
|     } else if (typeof c === 'number') {
 | |
|         childNodes.push(new VText(String(c)));
 | |
|     } else if (isChild(c)) {
 | |
|         childNodes.push(c);
 | |
|     } else if (isArray(c)) {
 | |
|         for (var i = 0; i < c.length; i++) {
 | |
|             addChild(c[i], childNodes, tag, props);
 | |
|         }
 | |
|     } else if (c === null || c === undefined) {
 | |
|         return;
 | |
|     } else {
 | |
|         throw UnexpectedVirtualElement({
 | |
|             foreignObject: c,
 | |
|             parentVnode: {
 | |
|                 tagName: tag,
 | |
|                 properties: props
 | |
|             }
 | |
|         });
 | |
|     }
 | |
| }
 | |
| 
 | |
| function transformProperties(props) {
 | |
|     for (var propName in props) {
 | |
|         if (props.hasOwnProperty(propName)) {
 | |
|             var value = props[propName];
 | |
| 
 | |
|             if (isHook(value)) {
 | |
|                 continue;
 | |
|             }
 | |
| 
 | |
|             if (propName.substr(0, 3) === 'ev-') {
 | |
|                 // add ev-foo support
 | |
|                 props[propName] = evHook(value);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| function isChild(x) {
 | |
|     return isVNode(x) || isVText(x) || isWidget(x) || isVThunk(x);
 | |
| }
 | |
| 
 | |
| function isChildren(x) {
 | |
|     return typeof x === 'string' || isArray(x) || isChild(x);
 | |
| }
 | |
| 
 | |
| function UnexpectedVirtualElement(data) {
 | |
|     var err = new Error();
 | |
| 
 | |
|     err.type = 'virtual-hyperscript.unexpected.virtual-element';
 | |
|     err.message = 'Unexpected virtual child passed to h().\n' +
 | |
|         'Expected a VNode / Vthunk / VWidget / string but:\n' +
 | |
|         'got:\n' +
 | |
|         errorString(data.foreignObject) +
 | |
|         '.\n' +
 | |
|         'The parent vnode is:\n' +
 | |
|         errorString(data.parentVnode)
 | |
|         '\n' +
 | |
|         'Suggested fix: change your `h(..., [ ... ])` callsite.';
 | |
|     err.foreignObject = data.foreignObject;
 | |
|     err.parentVnode = data.parentVnode;
 | |
| 
 | |
|     return err;
 | |
| }
 | |
| 
 | |
| function errorString(obj) {
 | |
|     try {
 | |
|         return JSON.stringify(obj, null, '    ');
 | |
|     } catch (e) {
 | |
|         return String(obj);
 | |
|     }
 | |
| }
 | |
| 
 | |
| },{"../vnode/is-thunk":25,"../vnode/is-vhook":26,"../vnode/is-vnode":27,"../vnode/is-vtext":28,"../vnode/is-widget":29,"../vnode/vnode.js":31,"../vnode/vtext.js":33,"./hooks/ev-hook.js":20,"./hooks/soft-set-hook.js":21,"./parse-tag.js":23,"x-is-array":12}],23:[function(require,module,exports){
 | |
| 'use strict';
 | |
| 
 | |
| var split = require('browser-split');
 | |
| 
 | |
| var classIdSplit = /([\.#]?[a-zA-Z0-9\u007F-\uFFFF_:-]+)/;
 | |
| var notClassId = /^\.|#/;
 | |
| 
 | |
| module.exports = parseTag;
 | |
| 
 | |
| function parseTag(tag, props) {
 | |
|     if (!tag) {
 | |
|         return 'DIV';
 | |
|     }
 | |
| 
 | |
|     var noId = !(props.hasOwnProperty('id'));
 | |
| 
 | |
|     var tagParts = split(tag, classIdSplit);
 | |
|     var tagName = null;
 | |
| 
 | |
|     if (notClassId.test(tagParts[1])) {
 | |
|         tagName = 'DIV';
 | |
|     }
 | |
| 
 | |
|     var classes, part, type, i;
 | |
| 
 | |
|     for (i = 0; i < tagParts.length; i++) {
 | |
|         part = tagParts[i];
 | |
| 
 | |
|         if (!part) {
 | |
|             continue;
 | |
|         }
 | |
| 
 | |
|         type = part.charAt(0);
 | |
| 
 | |
|         if (!tagName) {
 | |
|             tagName = part;
 | |
|         } else if (type === '.') {
 | |
|             classes = classes || [];
 | |
|             classes.push(part.substring(1, part.length));
 | |
|         } else if (type === '#' && noId) {
 | |
|             props.id = part.substring(1, part.length);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (classes) {
 | |
|         if (props.className) {
 | |
|             classes.push(props.className);
 | |
|         }
 | |
| 
 | |
|         props.className = classes.join(' ');
 | |
|     }
 | |
| 
 | |
|     return props.namespace ? tagName : tagName.toUpperCase();
 | |
| }
 | |
| 
 | |
| },{"browser-split":5}],24:[function(require,module,exports){
 | |
| var isVNode = require("./is-vnode")
 | |
| var isVText = require("./is-vtext")
 | |
| var isWidget = require("./is-widget")
 | |
| var isThunk = require("./is-thunk")
 | |
| 
 | |
| module.exports = handleThunk
 | |
| 
 | |
| function handleThunk(a, b) {
 | |
|     var renderedA = a
 | |
|     var renderedB = b
 | |
| 
 | |
|     if (isThunk(b)) {
 | |
|         renderedB = renderThunk(b, a)
 | |
|     }
 | |
| 
 | |
|     if (isThunk(a)) {
 | |
|         renderedA = renderThunk(a, null)
 | |
|     }
 | |
| 
 | |
|     return {
 | |
|         a: renderedA,
 | |
|         b: renderedB
 | |
|     }
 | |
| }
 | |
| 
 | |
| function renderThunk(thunk, previous) {
 | |
|     var renderedThunk = thunk.vnode
 | |
| 
 | |
|     if (!renderedThunk) {
 | |
|         renderedThunk = thunk.vnode = thunk.render(previous)
 | |
|     }
 | |
| 
 | |
|     if (!(isVNode(renderedThunk) ||
 | |
|             isVText(renderedThunk) ||
 | |
|             isWidget(renderedThunk))) {
 | |
|         throw new Error("thunk did not return a valid node");
 | |
|     }
 | |
| 
 | |
|     return renderedThunk
 | |
| }
 | |
| 
 | |
| },{"./is-thunk":25,"./is-vnode":27,"./is-vtext":28,"./is-widget":29}],25:[function(require,module,exports){
 | |
| module.exports = isThunk
 | |
| 
 | |
| function isThunk(t) {
 | |
|     return t && t.type === "Thunk"
 | |
| }
 | |
| 
 | |
| },{}],26:[function(require,module,exports){
 | |
| module.exports = isHook
 | |
| 
 | |
| function isHook(hook) {
 | |
|     return hook &&
 | |
|       (typeof hook.hook === "function" && !hook.hasOwnProperty("hook") ||
 | |
|        typeof hook.unhook === "function" && !hook.hasOwnProperty("unhook"))
 | |
| }
 | |
| 
 | |
| },{}],27:[function(require,module,exports){
 | |
| var version = require("./version")
 | |
| 
 | |
| module.exports = isVirtualNode
 | |
| 
 | |
| function isVirtualNode(x) {
 | |
|     return x && x.type === "VirtualNode" && x.version === version
 | |
| }
 | |
| 
 | |
| },{"./version":30}],28:[function(require,module,exports){
 | |
| var version = require("./version")
 | |
| 
 | |
| module.exports = isVirtualText
 | |
| 
 | |
| function isVirtualText(x) {
 | |
|     return x && x.type === "VirtualText" && x.version === version
 | |
| }
 | |
| 
 | |
| },{"./version":30}],29:[function(require,module,exports){
 | |
| module.exports = isWidget
 | |
| 
 | |
| function isWidget(w) {
 | |
|     return w && w.type === "Widget"
 | |
| }
 | |
| 
 | |
| },{}],30:[function(require,module,exports){
 | |
| module.exports = "2"
 | |
| 
 | |
| },{}],31:[function(require,module,exports){
 | |
| var version = require("./version")
 | |
| var isVNode = require("./is-vnode")
 | |
| var isWidget = require("./is-widget")
 | |
| var isThunk = require("./is-thunk")
 | |
| var isVHook = require("./is-vhook")
 | |
| 
 | |
| module.exports = VirtualNode
 | |
| 
 | |
| var noProperties = {}
 | |
| var noChildren = []
 | |
| 
 | |
| function VirtualNode(tagName, properties, children, key, namespace) {
 | |
|     this.tagName = tagName
 | |
|     this.properties = properties || noProperties
 | |
|     this.children = children || noChildren
 | |
|     this.key = key != null ? String(key) : undefined
 | |
|     this.namespace = (typeof namespace === "string") ? namespace : null
 | |
| 
 | |
|     var count = (children && children.length) || 0
 | |
|     var descendants = 0
 | |
|     var hasWidgets = false
 | |
|     var hasThunks = false
 | |
|     var descendantHooks = false
 | |
|     var hooks
 | |
| 
 | |
|     for (var propName in properties) {
 | |
|         if (properties.hasOwnProperty(propName)) {
 | |
|             var property = properties[propName]
 | |
|             if (isVHook(property) && property.unhook) {
 | |
|                 if (!hooks) {
 | |
|                     hooks = {}
 | |
|                 }
 | |
| 
 | |
|                 hooks[propName] = property
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     for (var i = 0; i < count; i++) {
 | |
|         var child = children[i]
 | |
|         if (isVNode(child)) {
 | |
|             descendants += child.count || 0
 | |
| 
 | |
|             if (!hasWidgets && child.hasWidgets) {
 | |
|                 hasWidgets = true
 | |
|             }
 | |
| 
 | |
|             if (!hasThunks && child.hasThunks) {
 | |
|                 hasThunks = true
 | |
|             }
 | |
| 
 | |
|             if (!descendantHooks && (child.hooks || child.descendantHooks)) {
 | |
|                 descendantHooks = true
 | |
|             }
 | |
|         } else if (!hasWidgets && isWidget(child)) {
 | |
|             if (typeof child.destroy === "function") {
 | |
|                 hasWidgets = true
 | |
|             }
 | |
|         } else if (!hasThunks && isThunk(child)) {
 | |
|             hasThunks = true;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     this.count = count + descendants
 | |
|     this.hasWidgets = hasWidgets
 | |
|     this.hasThunks = hasThunks
 | |
|     this.hooks = hooks
 | |
|     this.descendantHooks = descendantHooks
 | |
| }
 | |
| 
 | |
| VirtualNode.prototype.version = version
 | |
| VirtualNode.prototype.type = "VirtualNode"
 | |
| 
 | |
| },{"./is-thunk":25,"./is-vhook":26,"./is-vnode":27,"./is-widget":29,"./version":30}],32:[function(require,module,exports){
 | |
| var version = require("./version")
 | |
| 
 | |
| VirtualPatch.NONE = 0
 | |
| VirtualPatch.VTEXT = 1
 | |
| VirtualPatch.VNODE = 2
 | |
| VirtualPatch.WIDGET = 3
 | |
| VirtualPatch.PROPS = 4
 | |
| VirtualPatch.ORDER = 5
 | |
| VirtualPatch.INSERT = 6
 | |
| VirtualPatch.REMOVE = 7
 | |
| VirtualPatch.THUNK = 8
 | |
| 
 | |
| module.exports = VirtualPatch
 | |
| 
 | |
| function VirtualPatch(type, vNode, patch) {
 | |
|     this.type = Number(type)
 | |
|     this.vNode = vNode
 | |
|     this.patch = patch
 | |
| }
 | |
| 
 | |
| VirtualPatch.prototype.version = version
 | |
| VirtualPatch.prototype.type = "VirtualPatch"
 | |
| 
 | |
| },{"./version":30}],33:[function(require,module,exports){
 | |
| var version = require("./version")
 | |
| 
 | |
| module.exports = VirtualText
 | |
| 
 | |
| function VirtualText(text) {
 | |
|     this.text = String(text)
 | |
| }
 | |
| 
 | |
| VirtualText.prototype.version = version
 | |
| VirtualText.prototype.type = "VirtualText"
 | |
| 
 | |
| },{"./version":30}],34:[function(require,module,exports){
 | |
| var isObject = require("is-object")
 | |
| var isHook = require("../vnode/is-vhook")
 | |
| 
 | |
| module.exports = diffProps
 | |
| 
 | |
| function diffProps(a, b) {
 | |
|     var diff
 | |
| 
 | |
|     for (var aKey in a) {
 | |
|         if (!(aKey in b)) {
 | |
|             diff = diff || {}
 | |
|             diff[aKey] = undefined
 | |
|         }
 | |
| 
 | |
|         var aValue = a[aKey]
 | |
|         var bValue = b[aKey]
 | |
| 
 | |
|         if (aValue === bValue) {
 | |
|             continue
 | |
|         } else if (isObject(aValue) && isObject(bValue)) {
 | |
|             if (getPrototype(bValue) !== getPrototype(aValue)) {
 | |
|                 diff = diff || {}
 | |
|                 diff[aKey] = bValue
 | |
|             } else if (isHook(bValue)) {
 | |
|                  diff = diff || {}
 | |
|                  diff[aKey] = bValue
 | |
|             } else {
 | |
|                 var objectDiff = diffProps(aValue, bValue)
 | |
|                 if (objectDiff) {
 | |
|                     diff = diff || {}
 | |
|                     diff[aKey] = objectDiff
 | |
|                 }
 | |
|             }
 | |
|         } else {
 | |
|             diff = diff || {}
 | |
|             diff[aKey] = bValue
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     for (var bKey in b) {
 | |
|         if (!(bKey in a)) {
 | |
|             diff = diff || {}
 | |
|             diff[bKey] = b[bKey]
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return diff
 | |
| }
 | |
| 
 | |
| function getPrototype(value) {
 | |
|   if (Object.getPrototypeOf) {
 | |
|     return Object.getPrototypeOf(value)
 | |
|   } else if (value.__proto__) {
 | |
|     return value.__proto__
 | |
|   } else if (value.constructor) {
 | |
|     return value.constructor.prototype
 | |
|   }
 | |
| }
 | |
| 
 | |
| },{"../vnode/is-vhook":26,"is-object":11}],35:[function(require,module,exports){
 | |
| var isArray = require("x-is-array")
 | |
| 
 | |
| var VPatch = require("../vnode/vpatch")
 | |
| var isVNode = require("../vnode/is-vnode")
 | |
| var isVText = require("../vnode/is-vtext")
 | |
| var isWidget = require("../vnode/is-widget")
 | |
| var isThunk = require("../vnode/is-thunk")
 | |
| var handleThunk = require("../vnode/handle-thunk")
 | |
| 
 | |
| var diffProps = require("./diff-props")
 | |
| 
 | |
| module.exports = diff
 | |
| 
 | |
| function diff(a, b) {
 | |
|     var patch = { a: a }
 | |
|     walk(a, b, patch, 0)
 | |
|     return patch
 | |
| }
 | |
| 
 | |
| function walk(a, b, patch, index) {
 | |
|     if (a === b) {
 | |
|         return
 | |
|     }
 | |
| 
 | |
|     var apply = patch[index]
 | |
|     var applyClear = false
 | |
| 
 | |
|     if (isThunk(a) || isThunk(b)) {
 | |
|         thunks(a, b, patch, index)
 | |
|     } else if (b == null) {
 | |
| 
 | |
|         // If a is a widget we will add a remove patch for it
 | |
|         // Otherwise any child widgets/hooks must be destroyed.
 | |
|         // This prevents adding two remove patches for a widget.
 | |
|         if (!isWidget(a)) {
 | |
|             clearState(a, patch, index)
 | |
|             apply = patch[index]
 | |
|         }
 | |
| 
 | |
|         apply = appendPatch(apply, new VPatch(VPatch.REMOVE, a, b))
 | |
|     } else if (isVNode(b)) {
 | |
|         if (isVNode(a)) {
 | |
|             if (a.tagName === b.tagName &&
 | |
|                 a.namespace === b.namespace &&
 | |
|                 a.key === b.key) {
 | |
|                 var propsPatch = diffProps(a.properties, b.properties)
 | |
|                 if (propsPatch) {
 | |
|                     apply = appendPatch(apply,
 | |
|                         new VPatch(VPatch.PROPS, a, propsPatch))
 | |
|                 }
 | |
|                 apply = diffChildren(a, b, patch, apply, index)
 | |
|             } else {
 | |
|                 apply = appendPatch(apply, new VPatch(VPatch.VNODE, a, b))
 | |
|                 applyClear = true
 | |
|             }
 | |
|         } else {
 | |
|             apply = appendPatch(apply, new VPatch(VPatch.VNODE, a, b))
 | |
|             applyClear = true
 | |
|         }
 | |
|     } else if (isVText(b)) {
 | |
|         if (!isVText(a)) {
 | |
|             apply = appendPatch(apply, new VPatch(VPatch.VTEXT, a, b))
 | |
|             applyClear = true
 | |
|         } else if (a.text !== b.text) {
 | |
|             apply = appendPatch(apply, new VPatch(VPatch.VTEXT, a, b))
 | |
|         }
 | |
|     } else if (isWidget(b)) {
 | |
|         if (!isWidget(a)) {
 | |
|             applyClear = true
 | |
|         }
 | |
| 
 | |
|         apply = appendPatch(apply, new VPatch(VPatch.WIDGET, a, b))
 | |
|     }
 | |
| 
 | |
|     if (apply) {
 | |
|         patch[index] = apply
 | |
|     }
 | |
| 
 | |
|     if (applyClear) {
 | |
|         clearState(a, patch, index)
 | |
|     }
 | |
| }
 | |
| 
 | |
| function diffChildren(a, b, patch, apply, index) {
 | |
|     var aChildren = a.children
 | |
|     var orderedSet = reorder(aChildren, b.children)
 | |
|     var bChildren = orderedSet.children
 | |
| 
 | |
|     var aLen = aChildren.length
 | |
|     var bLen = bChildren.length
 | |
|     var len = aLen > bLen ? aLen : bLen
 | |
| 
 | |
|     for (var i = 0; i < len; i++) {
 | |
|         var leftNode = aChildren[i]
 | |
|         var rightNode = bChildren[i]
 | |
|         index += 1
 | |
| 
 | |
|         if (!leftNode) {
 | |
|             if (rightNode) {
 | |
|                 // Excess nodes in b need to be added
 | |
|                 apply = appendPatch(apply,
 | |
|                     new VPatch(VPatch.INSERT, null, rightNode))
 | |
|             }
 | |
|         } else {
 | |
|             walk(leftNode, rightNode, patch, index)
 | |
|         }
 | |
| 
 | |
|         if (isVNode(leftNode) && leftNode.count) {
 | |
|             index += leftNode.count
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (orderedSet.moves) {
 | |
|         // Reorder nodes last
 | |
|         apply = appendPatch(apply, new VPatch(
 | |
|             VPatch.ORDER,
 | |
|             a,
 | |
|             orderedSet.moves
 | |
|         ))
 | |
|     }
 | |
| 
 | |
|     return apply
 | |
| }
 | |
| 
 | |
| function clearState(vNode, patch, index) {
 | |
|     // TODO: Make this a single walk, not two
 | |
|     unhook(vNode, patch, index)
 | |
|     destroyWidgets(vNode, patch, index)
 | |
| }
 | |
| 
 | |
| // Patch records for all destroyed widgets must be added because we need
 | |
| // a DOM node reference for the destroy function
 | |
| function destroyWidgets(vNode, patch, index) {
 | |
|     if (isWidget(vNode)) {
 | |
|         if (typeof vNode.destroy === "function") {
 | |
|             patch[index] = appendPatch(
 | |
|                 patch[index],
 | |
|                 new VPatch(VPatch.REMOVE, vNode, null)
 | |
|             )
 | |
|         }
 | |
|     } else if (isVNode(vNode) && (vNode.hasWidgets || vNode.hasThunks)) {
 | |
|         var children = vNode.children
 | |
|         var len = children.length
 | |
|         for (var i = 0; i < len; i++) {
 | |
|             var child = children[i]
 | |
|             index += 1
 | |
| 
 | |
|             destroyWidgets(child, patch, index)
 | |
| 
 | |
|             if (isVNode(child) && child.count) {
 | |
|                 index += child.count
 | |
|             }
 | |
|         }
 | |
|     } else if (isThunk(vNode)) {
 | |
|         thunks(vNode, null, patch, index)
 | |
|     }
 | |
| }
 | |
| 
 | |
| // Create a sub-patch for thunks
 | |
| function thunks(a, b, patch, index) {
 | |
|     var nodes = handleThunk(a, b)
 | |
|     var thunkPatch = diff(nodes.a, nodes.b)
 | |
|     if (hasPatches(thunkPatch)) {
 | |
|         patch[index] = new VPatch(VPatch.THUNK, null, thunkPatch)
 | |
|     }
 | |
| }
 | |
| 
 | |
| function hasPatches(patch) {
 | |
|     for (var index in patch) {
 | |
|         if (index !== "a") {
 | |
|             return true
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return false
 | |
| }
 | |
| 
 | |
| // Execute hooks when two nodes are identical
 | |
| function unhook(vNode, patch, index) {
 | |
|     if (isVNode(vNode)) {
 | |
|         if (vNode.hooks) {
 | |
|             patch[index] = appendPatch(
 | |
|                 patch[index],
 | |
|                 new VPatch(
 | |
|                     VPatch.PROPS,
 | |
|                     vNode,
 | |
|                     undefinedKeys(vNode.hooks)
 | |
|                 )
 | |
|             )
 | |
|         }
 | |
| 
 | |
|         if (vNode.descendantHooks || vNode.hasThunks) {
 | |
|             var children = vNode.children
 | |
|             var len = children.length
 | |
|             for (var i = 0; i < len; i++) {
 | |
|                 var child = children[i]
 | |
|                 index += 1
 | |
| 
 | |
|                 unhook(child, patch, index)
 | |
| 
 | |
|                 if (isVNode(child) && child.count) {
 | |
|                     index += child.count
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     } else if (isThunk(vNode)) {
 | |
|         thunks(vNode, null, patch, index)
 | |
|     }
 | |
| }
 | |
| 
 | |
| function undefinedKeys(obj) {
 | |
|     var result = {}
 | |
| 
 | |
|     for (var key in obj) {
 | |
|         result[key] = undefined
 | |
|     }
 | |
| 
 | |
|     return result
 | |
| }
 | |
| 
 | |
| // List diff, naive left to right reordering
 | |
| function reorder(aChildren, bChildren) {
 | |
|     // O(M) time, O(M) memory
 | |
|     var bChildIndex = keyIndex(bChildren)
 | |
|     var bKeys = bChildIndex.keys
 | |
|     var bFree = bChildIndex.free
 | |
| 
 | |
|     if (bFree.length === bChildren.length) {
 | |
|         return {
 | |
|             children: bChildren,
 | |
|             moves: null
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     // O(N) time, O(N) memory
 | |
|     var aChildIndex = keyIndex(aChildren)
 | |
|     var aKeys = aChildIndex.keys
 | |
|     var aFree = aChildIndex.free
 | |
| 
 | |
|     if (aFree.length === aChildren.length) {
 | |
|         return {
 | |
|             children: bChildren,
 | |
|             moves: null
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     // O(MAX(N, M)) memory
 | |
|     var newChildren = []
 | |
| 
 | |
|     var freeIndex = 0
 | |
|     var freeCount = bFree.length
 | |
|     var deletedItems = 0
 | |
| 
 | |
|     // Iterate through a and match a node in b
 | |
|     // O(N) time,
 | |
|     for (var i = 0 ; i < aChildren.length; i++) {
 | |
|         var aItem = aChildren[i]
 | |
|         var itemIndex
 | |
| 
 | |
|         if (aItem.key) {
 | |
|             if (bKeys.hasOwnProperty(aItem.key)) {
 | |
|                 // Match up the old keys
 | |
|                 itemIndex = bKeys[aItem.key]
 | |
|                 newChildren.push(bChildren[itemIndex])
 | |
| 
 | |
|             } else {
 | |
|                 // Remove old keyed items
 | |
|                 itemIndex = i - deletedItems++
 | |
|                 newChildren.push(null)
 | |
|             }
 | |
|         } else {
 | |
|             // Match the item in a with the next free item in b
 | |
|             if (freeIndex < freeCount) {
 | |
|                 itemIndex = bFree[freeIndex++]
 | |
|                 newChildren.push(bChildren[itemIndex])
 | |
|             } else {
 | |
|                 // There are no free items in b to match with
 | |
|                 // the free items in a, so the extra free nodes
 | |
|                 // are deleted.
 | |
|                 itemIndex = i - deletedItems++
 | |
|                 newChildren.push(null)
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     var lastFreeIndex = freeIndex >= bFree.length ?
 | |
|         bChildren.length :
 | |
|         bFree[freeIndex]
 | |
| 
 | |
|     // Iterate through b and append any new keys
 | |
|     // O(M) time
 | |
|     for (var j = 0; j < bChildren.length; j++) {
 | |
|         var newItem = bChildren[j]
 | |
| 
 | |
|         if (newItem.key) {
 | |
|             if (!aKeys.hasOwnProperty(newItem.key)) {
 | |
|                 // Add any new keyed items
 | |
|                 // We are adding new items to the end and then sorting them
 | |
|                 // in place. In future we should insert new items in place.
 | |
|                 newChildren.push(newItem)
 | |
|             }
 | |
|         } else if (j >= lastFreeIndex) {
 | |
|             // Add any leftover non-keyed items
 | |
|             newChildren.push(newItem)
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     var simulate = newChildren.slice()
 | |
|     var simulateIndex = 0
 | |
|     var removes = []
 | |
|     var inserts = []
 | |
|     var simulateItem
 | |
| 
 | |
|     for (var k = 0; k < bChildren.length;) {
 | |
|         var wantedItem = bChildren[k]
 | |
|         simulateItem = simulate[simulateIndex]
 | |
| 
 | |
|         // remove items
 | |
|         while (simulateItem === null && simulate.length) {
 | |
|             removes.push(remove(simulate, simulateIndex, null))
 | |
|             simulateItem = simulate[simulateIndex]
 | |
|         }
 | |
| 
 | |
|         if (!simulateItem || simulateItem.key !== wantedItem.key) {
 | |
|             // if we need a key in this position...
 | |
|             if (wantedItem.key) {
 | |
|                 if (simulateItem && simulateItem.key) {
 | |
|                     // if an insert doesn't put this key in place, it needs to move
 | |
|                     if (bKeys[simulateItem.key] !== k + 1) {
 | |
|                         removes.push(remove(simulate, simulateIndex, simulateItem.key))
 | |
|                         simulateItem = simulate[simulateIndex]
 | |
|                         // if the remove didn't put the wanted item in place, we need to insert it
 | |
|                         if (!simulateItem || simulateItem.key !== wantedItem.key) {
 | |
|                             inserts.push({key: wantedItem.key, to: k})
 | |
|                         }
 | |
|                         // items are matching, so skip ahead
 | |
|                         else {
 | |
|                             simulateIndex++
 | |
|                         }
 | |
|                     }
 | |
|                     else {
 | |
|                         inserts.push({key: wantedItem.key, to: k})
 | |
|                     }
 | |
|                 }
 | |
|                 else {
 | |
|                     inserts.push({key: wantedItem.key, to: k})
 | |
|                 }
 | |
|                 k++
 | |
|             }
 | |
|             // a key in simulate has no matching wanted key, remove it
 | |
|             else if (simulateItem && simulateItem.key) {
 | |
|                 removes.push(remove(simulate, simulateIndex, simulateItem.key))
 | |
|             }
 | |
|         }
 | |
|         else {
 | |
|             simulateIndex++
 | |
|             k++
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     // remove all the remaining nodes from simulate
 | |
|     while(simulateIndex < simulate.length) {
 | |
|         simulateItem = simulate[simulateIndex]
 | |
|         removes.push(remove(simulate, simulateIndex, simulateItem && simulateItem.key))
 | |
|     }
 | |
| 
 | |
|     // If the only moves we have are deletes then we can just
 | |
|     // let the delete patch remove these items.
 | |
|     if (removes.length === deletedItems && !inserts.length) {
 | |
|         return {
 | |
|             children: newChildren,
 | |
|             moves: null
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return {
 | |
|         children: newChildren,
 | |
|         moves: {
 | |
|             removes: removes,
 | |
|             inserts: inserts
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| function remove(arr, index, key) {
 | |
|     arr.splice(index, 1)
 | |
| 
 | |
|     return {
 | |
|         from: index,
 | |
|         key: key
 | |
|     }
 | |
| }
 | |
| 
 | |
| function keyIndex(children) {
 | |
|     var keys = {}
 | |
|     var free = []
 | |
|     var length = children.length
 | |
| 
 | |
|     for (var i = 0; i < length; i++) {
 | |
|         var child = children[i]
 | |
| 
 | |
|         if (child.key) {
 | |
|             keys[child.key] = i
 | |
|         } else {
 | |
|             free.push(i)
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return {
 | |
|         keys: keys,     // A hash of key name to index
 | |
|         free: free      // An array of unkeyed item indices
 | |
|     }
 | |
| }
 | |
| 
 | |
| function appendPatch(apply, patch) {
 | |
|     if (apply) {
 | |
|         if (isArray(apply)) {
 | |
|             apply.push(patch)
 | |
|         } else {
 | |
|             apply = [apply, patch]
 | |
|         }
 | |
| 
 | |
|         return apply
 | |
|     } else {
 | |
|         return patch
 | |
|     }
 | |
| }
 | |
| 
 | |
| },{"../vnode/handle-thunk":24,"../vnode/is-thunk":25,"../vnode/is-vnode":27,"../vnode/is-vtext":28,"../vnode/is-widget":29,"../vnode/vpatch":32,"./diff-props":34,"x-is-array":12}]},{},[4])(4)
 | |
| }); |