clearwater 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,108 @@
1
+ require 'browser'
2
+ require 'clearwater/virtual_dom/js/virtual_dom.js'
3
+
4
+ module StringUtils
5
+ def self.camelize string
6
+ string.gsub(/_(\w)/) { |match| match.gsub(/_/, '').upcase }
7
+ end
8
+ end
9
+
10
+ module HashUtils
11
+ def self.camelize_keys(hash)
12
+ return nil if hash.nil?
13
+
14
+ Hash[hash.map { |k,v|
15
+ key = StringUtils.camelize(k)
16
+ value = if Hash === v
17
+ camelize_keys(v)
18
+ else
19
+ v
20
+ end
21
+
22
+ [key, value]
23
+ }]
24
+ end
25
+ end
26
+
27
+ module VirtualDOM
28
+ def self.node(tag_name, attributes, content)
29
+ content = Array(content).map { |node|
30
+ case node
31
+ when Node
32
+ node.node
33
+ else
34
+ node
35
+ end
36
+ }
37
+ attributes = HashUtils.camelize_keys(attributes).to_n
38
+ Node.new(`virtualDom.h(tag_name, attributes, content)`)
39
+ end
40
+
41
+ def self.create_element node
42
+ `virtualDom.create(node)`
43
+ end
44
+
45
+ class Document
46
+ def initialize(root=$document.create_element('div'))
47
+ @root = root
48
+ @rendered_nodes = {}
49
+ end
50
+
51
+ def render node
52
+ if rendered?
53
+ diff = @node.diff(node)
54
+ @tree = Element.new(@tree.patch(diff))
55
+ @node = node
56
+ else
57
+ @node = node
58
+ @tree = node.to_element
59
+ @root.inner_dom = @tree.to_n
60
+ @rendered = true
61
+ end
62
+ end
63
+
64
+ def rendered?
65
+ @rendered
66
+ end
67
+ end
68
+
69
+ class Node
70
+ attr_reader :node
71
+
72
+ def initialize(node)
73
+ @node = node
74
+ end
75
+
76
+ def method_missing *args, &block
77
+ node.send *args, &block
78
+ end
79
+
80
+ def to_element
81
+ Element.new(VirtualDOM.create_element(node))
82
+ end
83
+
84
+ def diff other
85
+ `virtualDom.diff(self.node, other.node)`
86
+ end
87
+
88
+ def patch diff
89
+ `virtualDom.patch(#{to_element.to_n}, diff)`
90
+ end
91
+ end
92
+
93
+ class Element
94
+ attr_reader :element
95
+
96
+ def initialize(element)
97
+ @element = element
98
+ end
99
+
100
+ def patch(diff)
101
+ `virtualDom.patch(#{element}, diff)`
102
+ end
103
+
104
+ def to_n
105
+ @element
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,1663 @@
1
+ (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.virtualDom = f()}})(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){
2
+ var createElement = require("./vdom/create-element.js")
3
+
4
+ module.exports = createElement
5
+
6
+ },{"./vdom/create-element.js":14}],2:[function(require,module,exports){
7
+ var diff = require("./vtree/diff.js")
8
+
9
+ module.exports = diff
10
+
11
+ },{"./vtree/diff.js":34}],3:[function(require,module,exports){
12
+ var h = require("./virtual-hyperscript/index.js")
13
+
14
+ module.exports = h
15
+
16
+ },{"./virtual-hyperscript/index.js":21}],4:[function(require,module,exports){
17
+ var diff = require("./diff.js")
18
+ var patch = require("./patch.js")
19
+ var h = require("./h.js")
20
+ var create = require("./create-element.js")
21
+ var VNode = require('./vnode/vnode.js')
22
+ var VText = require('./vnode/vtext.js')
23
+
24
+ module.exports = {
25
+ diff: diff,
26
+ patch: patch,
27
+ h: h,
28
+ create: create,
29
+ VNode: VNode,
30
+ VText: VText
31
+ }
32
+
33
+ },{"./create-element.js":1,"./diff.js":2,"./h.js":3,"./patch.js":12,"./vnode/vnode.js":30,"./vnode/vtext.js":32}],5:[function(require,module,exports){
34
+ /*!
35
+ * Cross-Browser Split 1.1.1
36
+ * Copyright 2007-2012 Steven Levithan <stevenlevithan.com>
37
+ * Available under the MIT License
38
+ * ECMAScript compliant, uniform cross-browser split method
39
+ */
40
+
41
+ /**
42
+ * Splits a string into an array of strings using a regex or string separator. Matches of the
43
+ * separator are not included in the result array. However, if `separator` is a regex that contains
44
+ * capturing groups, backreferences are spliced into the result each time `separator` is matched.
45
+ * Fixes browser bugs compared to the native `String.prototype.split` and can be used reliably
46
+ * cross-browser.
47
+ * @param {String} str String to split.
48
+ * @param {RegExp|String} separator Regex or string to use for separating the string.
49
+ * @param {Number} [limit] Maximum number of items to include in the result array.
50
+ * @returns {Array} Array of substrings.
51
+ * @example
52
+ *
53
+ * // Basic use
54
+ * split('a b c d', ' ');
55
+ * // -> ['a', 'b', 'c', 'd']
56
+ *
57
+ * // With limit
58
+ * split('a b c d', ' ', 2);
59
+ * // -> ['a', 'b']
60
+ *
61
+ * // Backreferences in result array
62
+ * split('..word1 word2..', /([a-z]+)(\d+)/i);
63
+ * // -> ['..', 'word', '1', ' ', 'word', '2', '..']
64
+ */
65
+ module.exports = (function split(undef) {
66
+
67
+ var nativeSplit = String.prototype.split,
68
+ compliantExecNpcg = /()??/.exec("")[1] === undef,
69
+ // NPCG: nonparticipating capturing group
70
+ self;
71
+
72
+ self = function(str, separator, limit) {
73
+ // If `separator` is not a regex, use `nativeSplit`
74
+ if (Object.prototype.toString.call(separator) !== "[object RegExp]") {
75
+ return nativeSplit.call(str, separator, limit);
76
+ }
77
+ var output = [],
78
+ flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.extended ? "x" : "") + // Proposed for ES6
79
+ (separator.sticky ? "y" : ""),
80
+ // Firefox 3+
81
+ lastLastIndex = 0,
82
+ // Make `global` and avoid `lastIndex` issues by working with a copy
83
+ separator = new RegExp(separator.source, flags + "g"),
84
+ separator2, match, lastIndex, lastLength;
85
+ str += ""; // Type-convert
86
+ if (!compliantExecNpcg) {
87
+ // Doesn't need flags gy, but they don't hurt
88
+ separator2 = new RegExp("^" + separator.source + "$(?!\\s)", flags);
89
+ }
90
+ /* Values for `limit`, per the spec:
91
+ * If undefined: 4294967295 // Math.pow(2, 32) - 1
92
+ * If 0, Infinity, or NaN: 0
93
+ * If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296;
94
+ * If negative number: 4294967296 - Math.floor(Math.abs(limit))
95
+ * If other: Type-convert, then use the above rules
96
+ */
97
+ limit = limit === undef ? -1 >>> 0 : // Math.pow(2, 32) - 1
98
+ limit >>> 0; // ToUint32(limit)
99
+ while (match = separator.exec(str)) {
100
+ // `separator.lastIndex` is not reliable cross-browser
101
+ lastIndex = match.index + match[0].length;
102
+ if (lastIndex > lastLastIndex) {
103
+ output.push(str.slice(lastLastIndex, match.index));
104
+ // Fix browsers whose `exec` methods don't consistently return `undefined` for
105
+ // nonparticipating capturing groups
106
+ if (!compliantExecNpcg && match.length > 1) {
107
+ match[0].replace(separator2, function() {
108
+ for (var i = 1; i < arguments.length - 2; i++) {
109
+ if (arguments[i] === undef) {
110
+ match[i] = undef;
111
+ }
112
+ }
113
+ });
114
+ }
115
+ if (match.length > 1 && match.index < str.length) {
116
+ Array.prototype.push.apply(output, match.slice(1));
117
+ }
118
+ lastLength = match[0].length;
119
+ lastLastIndex = lastIndex;
120
+ if (output.length >= limit) {
121
+ break;
122
+ }
123
+ }
124
+ if (separator.lastIndex === match.index) {
125
+ separator.lastIndex++; // Avoid an infinite loop
126
+ }
127
+ }
128
+ if (lastLastIndex === str.length) {
129
+ if (lastLength || !separator.test("")) {
130
+ output.push("");
131
+ }
132
+ } else {
133
+ output.push(str.slice(lastLastIndex));
134
+ }
135
+ return output.length > limit ? output.slice(0, limit) : output;
136
+ };
137
+
138
+ return self;
139
+ })();
140
+
141
+ },{}],6:[function(require,module,exports){
142
+ 'use strict';
143
+
144
+ var OneVersionConstraint = require('individual/one-version');
145
+
146
+ var MY_VERSION = '7';
147
+ OneVersionConstraint('ev-store', MY_VERSION);
148
+
149
+ var hashKey = '__EV_STORE_KEY@' + MY_VERSION;
150
+
151
+ module.exports = EvStore;
152
+
153
+ function EvStore(elem) {
154
+ var hash = elem[hashKey];
155
+
156
+ if (!hash) {
157
+ hash = elem[hashKey] = {};
158
+ }
159
+
160
+ return hash;
161
+ }
162
+
163
+ },{"individual/one-version":8}],7:[function(require,module,exports){
164
+ (function (global){
165
+ 'use strict';
166
+
167
+ /*global window, global*/
168
+
169
+ var root = typeof window !== 'undefined' ?
170
+ window : typeof global !== 'undefined' ?
171
+ global : {};
172
+
173
+ module.exports = Individual;
174
+
175
+ function Individual(key, value) {
176
+ if (key in root) {
177
+ return root[key];
178
+ }
179
+
180
+ root[key] = value;
181
+
182
+ return value;
183
+ }
184
+
185
+ }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
186
+ },{}],8:[function(require,module,exports){
187
+ 'use strict';
188
+
189
+ var Individual = require('./index.js');
190
+
191
+ module.exports = OneVersion;
192
+
193
+ function OneVersion(moduleName, version, defaultValue) {
194
+ var key = '__INDIVIDUAL_ONE_VERSION_' + moduleName;
195
+ var enforceKey = key + '_ENFORCE_SINGLETON';
196
+
197
+ var versionValue = Individual(enforceKey, version);
198
+
199
+ if (versionValue !== version) {
200
+ throw new Error('Can only have one copy of ' +
201
+ moduleName + '.\n' +
202
+ 'You already have version ' + versionValue +
203
+ ' installed.\n' +
204
+ 'This means you cannot install version ' + version);
205
+ }
206
+
207
+ return Individual(key, defaultValue);
208
+ }
209
+
210
+ },{"./index.js":7}],9:[function(require,module,exports){
211
+ (function (global){
212
+ var topLevel = typeof global !== 'undefined' ? global :
213
+ typeof window !== 'undefined' ? window : {}
214
+ var minDoc = require('min-document');
215
+
216
+ if (typeof document !== 'undefined') {
217
+ module.exports = document;
218
+ } else {
219
+ var doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'];
220
+
221
+ if (!doccy) {
222
+ doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'] = minDoc;
223
+ }
224
+
225
+ module.exports = doccy;
226
+ }
227
+
228
+ }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
229
+ },{"min-document":35}],10:[function(require,module,exports){
230
+ "use strict";
231
+
232
+ module.exports = function isObject(x) {
233
+ return typeof x === "object" && x !== null;
234
+ };
235
+
236
+ },{}],11:[function(require,module,exports){
237
+ var nativeIsArray = Array.isArray
238
+ var toString = Object.prototype.toString
239
+
240
+ module.exports = nativeIsArray || isArray
241
+
242
+ function isArray(obj) {
243
+ return toString.call(obj) === "[object Array]"
244
+ }
245
+
246
+ },{}],12:[function(require,module,exports){
247
+ var patch = require("./vdom/patch.js")
248
+
249
+ module.exports = patch
250
+
251
+ },{"./vdom/patch.js":17}],13:[function(require,module,exports){
252
+ var isObject = require("is-object")
253
+ var isHook = require("../vnode/is-vhook.js")
254
+
255
+ module.exports = applyProperties
256
+
257
+ function applyProperties(node, props, previous) {
258
+ for (var propName in props) {
259
+ var propValue = props[propName]
260
+
261
+ if (propValue === undefined) {
262
+ removeProperty(node, propName, propValue, previous);
263
+ } else if (isHook(propValue)) {
264
+ removeProperty(node, propName, propValue, previous)
265
+ if (propValue.hook) {
266
+ propValue.hook(node,
267
+ propName,
268
+ previous ? previous[propName] : undefined)
269
+ }
270
+ } else {
271
+ if (isObject(propValue)) {
272
+ patchObject(node, props, previous, propName, propValue);
273
+ } else {
274
+ node[propName] = propValue
275
+ }
276
+ }
277
+ }
278
+ }
279
+
280
+ function removeProperty(node, propName, propValue, previous) {
281
+ if (previous) {
282
+ var previousValue = previous[propName]
283
+
284
+ if (!isHook(previousValue)) {
285
+ if (propName === "attributes") {
286
+ for (var attrName in previousValue) {
287
+ node.removeAttribute(attrName)
288
+ }
289
+ } else if (propName === "style") {
290
+ for (var i in previousValue) {
291
+ node.style[i] = ""
292
+ }
293
+ } else if (typeof previousValue === "string") {
294
+ node[propName] = ""
295
+ } else {
296
+ node[propName] = null
297
+ }
298
+ } else if (previousValue.unhook) {
299
+ previousValue.unhook(node, propName, propValue)
300
+ }
301
+ }
302
+ }
303
+
304
+ function patchObject(node, props, previous, propName, propValue) {
305
+ var previousValue = previous ? previous[propName] : undefined
306
+
307
+ // Set attributes
308
+ if (propName === "attributes") {
309
+ for (var attrName in propValue) {
310
+ var attrValue = propValue[attrName]
311
+
312
+ if (attrValue === undefined) {
313
+ node.removeAttribute(attrName)
314
+ } else {
315
+ node.setAttribute(attrName, attrValue)
316
+ }
317
+ }
318
+
319
+ return
320
+ }
321
+
322
+ if(previousValue && isObject(previousValue) &&
323
+ getPrototype(previousValue) !== getPrototype(propValue)) {
324
+ node[propName] = propValue
325
+ return
326
+ }
327
+
328
+ if (!isObject(node[propName])) {
329
+ node[propName] = {}
330
+ }
331
+
332
+ var replacer = propName === "style" ? "" : undefined
333
+
334
+ for (var k in propValue) {
335
+ var value = propValue[k]
336
+ node[propName][k] = (value === undefined) ? replacer : value
337
+ }
338
+ }
339
+
340
+ function getPrototype(value) {
341
+ if (Object.getPrototypeOf) {
342
+ return Object.getPrototypeOf(value)
343
+ } else if (value.__proto__) {
344
+ return value.__proto__
345
+ } else if (value.constructor) {
346
+ return value.constructor.prototype
347
+ }
348
+ }
349
+
350
+ },{"../vnode/is-vhook.js":25,"is-object":10}],14:[function(require,module,exports){
351
+ var document = require("global/document")
352
+
353
+ var applyProperties = require("./apply-properties")
354
+
355
+ var isVNode = require("../vnode/is-vnode.js")
356
+ var isVText = require("../vnode/is-vtext.js")
357
+ var isWidget = require("../vnode/is-widget.js")
358
+ var handleThunk = require("../vnode/handle-thunk.js")
359
+
360
+ module.exports = createElement
361
+
362
+ function createElement(vnode, opts) {
363
+ var doc = opts ? opts.document || document : document
364
+ var warn = opts ? opts.warn : null
365
+
366
+ vnode = handleThunk(vnode).a
367
+
368
+ if (isWidget(vnode)) {
369
+ return vnode.init()
370
+ } else if (isVText(vnode)) {
371
+ return doc.createTextNode(vnode.text)
372
+ } else if (!isVNode(vnode)) {
373
+ if (warn) {
374
+ warn("Item is not a valid virtual dom node", vnode)
375
+ }
376
+ return null
377
+ }
378
+
379
+ var node = (vnode.namespace === null) ?
380
+ doc.createElement(vnode.tagName) :
381
+ doc.createElementNS(vnode.namespace, vnode.tagName)
382
+
383
+ var props = vnode.properties
384
+ applyProperties(node, props)
385
+
386
+ var children = vnode.children
387
+
388
+ for (var i = 0; i < children.length; i++) {
389
+ var childNode = createElement(children[i], opts)
390
+ if (childNode) {
391
+ node.appendChild(childNode)
392
+ }
393
+ }
394
+
395
+ return node
396
+ }
397
+
398
+ },{"../vnode/handle-thunk.js":23,"../vnode/is-vnode.js":26,"../vnode/is-vtext.js":27,"../vnode/is-widget.js":28,"./apply-properties":13,"global/document":9}],15:[function(require,module,exports){
399
+ // Maps a virtual DOM tree onto a real DOM tree in an efficient manner.
400
+ // We don't want to read all of the DOM nodes in the tree so we use
401
+ // the in-order tree indexing to eliminate recursion down certain branches.
402
+ // We only recurse into a DOM node if we know that it contains a child of
403
+ // interest.
404
+
405
+ var noChild = {}
406
+
407
+ module.exports = domIndex
408
+
409
+ function domIndex(rootNode, tree, indices, nodes) {
410
+ if (!indices || indices.length === 0) {
411
+ return {}
412
+ } else {
413
+ indices.sort(ascending)
414
+ return recurse(rootNode, tree, indices, nodes, 0)
415
+ }
416
+ }
417
+
418
+ function recurse(rootNode, tree, indices, nodes, rootIndex) {
419
+ nodes = nodes || {}
420
+
421
+
422
+ if (rootNode) {
423
+ if (indexInRange(indices, rootIndex, rootIndex)) {
424
+ nodes[rootIndex] = rootNode
425
+ }
426
+
427
+ var vChildren = tree.children
428
+
429
+ if (vChildren) {
430
+
431
+ var childNodes = rootNode.childNodes
432
+
433
+ for (var i = 0; i < tree.children.length; i++) {
434
+ rootIndex += 1
435
+
436
+ var vChild = vChildren[i] || noChild
437
+ var nextIndex = rootIndex + (vChild.count || 0)
438
+
439
+ // skip recursion down the tree if there are no nodes down here
440
+ if (indexInRange(indices, rootIndex, nextIndex)) {
441
+ recurse(childNodes[i], vChild, indices, nodes, rootIndex)
442
+ }
443
+
444
+ rootIndex = nextIndex
445
+ }
446
+ }
447
+ }
448
+
449
+ return nodes
450
+ }
451
+
452
+ // Binary search for an index in the interval [left, right]
453
+ function indexInRange(indices, left, right) {
454
+ if (indices.length === 0) {
455
+ return false
456
+ }
457
+
458
+ var minIndex = 0
459
+ var maxIndex = indices.length - 1
460
+ var currentIndex
461
+ var currentItem
462
+
463
+ while (minIndex <= maxIndex) {
464
+ currentIndex = ((maxIndex + minIndex) / 2) >> 0
465
+ currentItem = indices[currentIndex]
466
+
467
+ if (minIndex === maxIndex) {
468
+ return currentItem >= left && currentItem <= right
469
+ } else if (currentItem < left) {
470
+ minIndex = currentIndex + 1
471
+ } else if (currentItem > right) {
472
+ maxIndex = currentIndex - 1
473
+ } else {
474
+ return true
475
+ }
476
+ }
477
+
478
+ return false;
479
+ }
480
+
481
+ function ascending(a, b) {
482
+ return a > b ? 1 : -1
483
+ }
484
+
485
+ },{}],16:[function(require,module,exports){
486
+ var applyProperties = require("./apply-properties")
487
+
488
+ var isWidget = require("../vnode/is-widget.js")
489
+ var VPatch = require("../vnode/vpatch.js")
490
+
491
+ var render = require("./create-element")
492
+ var updateWidget = require("./update-widget")
493
+
494
+ module.exports = applyPatch
495
+
496
+ function applyPatch(vpatch, domNode, renderOptions) {
497
+ var type = vpatch.type
498
+ var vNode = vpatch.vNode
499
+ var patch = vpatch.patch
500
+
501
+ switch (type) {
502
+ case VPatch.REMOVE:
503
+ return removeNode(domNode, vNode)
504
+ case VPatch.INSERT:
505
+ return insertNode(domNode, patch, renderOptions)
506
+ case VPatch.VTEXT:
507
+ return stringPatch(domNode, vNode, patch, renderOptions)
508
+ case VPatch.WIDGET:
509
+ return widgetPatch(domNode, vNode, patch, renderOptions)
510
+ case VPatch.VNODE:
511
+ return vNodePatch(domNode, vNode, patch, renderOptions)
512
+ case VPatch.ORDER:
513
+ reorderChildren(domNode, patch)
514
+ return domNode
515
+ case VPatch.PROPS:
516
+ applyProperties(domNode, patch, vNode.properties)
517
+ return domNode
518
+ case VPatch.THUNK:
519
+ return replaceRoot(domNode,
520
+ renderOptions.patch(domNode, patch, renderOptions))
521
+ default:
522
+ return domNode
523
+ }
524
+ }
525
+
526
+ function removeNode(domNode, vNode) {
527
+ var parentNode = domNode.parentNode
528
+
529
+ if (parentNode) {
530
+ parentNode.removeChild(domNode)
531
+ }
532
+
533
+ destroyWidget(domNode, vNode);
534
+
535
+ return null
536
+ }
537
+
538
+ function insertNode(parentNode, vNode, renderOptions) {
539
+ var newNode = render(vNode, renderOptions)
540
+
541
+ if (parentNode) {
542
+ parentNode.appendChild(newNode)
543
+ }
544
+
545
+ return parentNode
546
+ }
547
+
548
+ function stringPatch(domNode, leftVNode, vText, renderOptions) {
549
+ var newNode
550
+
551
+ if (domNode.nodeType === 3) {
552
+ domNode.replaceData(0, domNode.length, vText.text)
553
+ newNode = domNode
554
+ } else {
555
+ var parentNode = domNode.parentNode
556
+ newNode = render(vText, renderOptions)
557
+
558
+ if (parentNode && newNode !== domNode) {
559
+ parentNode.replaceChild(newNode, domNode)
560
+ }
561
+ }
562
+
563
+ return newNode
564
+ }
565
+
566
+ function widgetPatch(domNode, leftVNode, widget, renderOptions) {
567
+ var updating = updateWidget(leftVNode, widget)
568
+ var newNode
569
+
570
+ if (updating) {
571
+ newNode = widget.update(leftVNode, domNode) || domNode
572
+ } else {
573
+ newNode = render(widget, renderOptions)
574
+ }
575
+
576
+ var parentNode = domNode.parentNode
577
+
578
+ if (parentNode && newNode !== domNode) {
579
+ parentNode.replaceChild(newNode, domNode)
580
+ }
581
+
582
+ if (!updating) {
583
+ destroyWidget(domNode, leftVNode)
584
+ }
585
+
586
+ return newNode
587
+ }
588
+
589
+ function vNodePatch(domNode, leftVNode, vNode, renderOptions) {
590
+ var parentNode = domNode.parentNode
591
+ var newNode = render(vNode, renderOptions)
592
+
593
+ if (parentNode && newNode !== domNode) {
594
+ parentNode.replaceChild(newNode, domNode)
595
+ }
596
+
597
+ return newNode
598
+ }
599
+
600
+ function destroyWidget(domNode, w) {
601
+ if (typeof w.destroy === "function" && isWidget(w)) {
602
+ w.destroy(domNode)
603
+ }
604
+ }
605
+
606
+ function reorderChildren(domNode, moves) {
607
+ var childNodes = domNode.childNodes
608
+ var keyMap = {}
609
+ var node
610
+ var remove
611
+ var insert
612
+
613
+ for (var i = 0; i < moves.removes.length; i++) {
614
+ remove = moves.removes[i]
615
+ node = childNodes[remove.from]
616
+ if (remove.key) {
617
+ keyMap[remove.key] = node
618
+ }
619
+ domNode.removeChild(node)
620
+ }
621
+
622
+ var length = childNodes.length
623
+ for (var j = 0; j < moves.inserts.length; j++) {
624
+ insert = moves.inserts[j]
625
+ node = keyMap[insert.key]
626
+ // this is the weirdest bug i've ever seen in webkit
627
+ domNode.insertBefore(node, insert.to >= length++ ? null : childNodes[insert.to])
628
+ }
629
+ }
630
+
631
+ function replaceRoot(oldRoot, newRoot) {
632
+ if (oldRoot && newRoot && oldRoot !== newRoot && oldRoot.parentNode) {
633
+ oldRoot.parentNode.replaceChild(newRoot, oldRoot)
634
+ }
635
+
636
+ return newRoot;
637
+ }
638
+
639
+ },{"../vnode/is-widget.js":28,"../vnode/vpatch.js":31,"./apply-properties":13,"./create-element":14,"./update-widget":18}],17:[function(require,module,exports){
640
+ var document = require("global/document")
641
+ var isArray = require("x-is-array")
642
+
643
+ var domIndex = require("./dom-index")
644
+ var patchOp = require("./patch-op")
645
+ module.exports = patch
646
+
647
+ function patch(rootNode, patches) {
648
+ return patchRecursive(rootNode, patches)
649
+ }
650
+
651
+ function patchRecursive(rootNode, patches, renderOptions) {
652
+ var indices = patchIndices(patches)
653
+
654
+ if (indices.length === 0) {
655
+ return rootNode
656
+ }
657
+
658
+ var index = domIndex(rootNode, patches.a, indices)
659
+ var ownerDocument = rootNode.ownerDocument
660
+
661
+ if (!renderOptions) {
662
+ renderOptions = { patch: patchRecursive }
663
+ if (ownerDocument !== document) {
664
+ renderOptions.document = ownerDocument
665
+ }
666
+ }
667
+
668
+ for (var i = 0; i < indices.length; i++) {
669
+ var nodeIndex = indices[i]
670
+ rootNode = applyPatch(rootNode,
671
+ index[nodeIndex],
672
+ patches[nodeIndex],
673
+ renderOptions)
674
+ }
675
+
676
+ return rootNode
677
+ }
678
+
679
+ function applyPatch(rootNode, domNode, patchList, renderOptions) {
680
+ if (!domNode) {
681
+ return rootNode
682
+ }
683
+
684
+ var newNode
685
+
686
+ if (isArray(patchList)) {
687
+ for (var i = 0; i < patchList.length; i++) {
688
+ newNode = patchOp(patchList[i], domNode, renderOptions)
689
+
690
+ if (domNode === rootNode) {
691
+ rootNode = newNode
692
+ }
693
+ }
694
+ } else {
695
+ newNode = patchOp(patchList, domNode, renderOptions)
696
+
697
+ if (domNode === rootNode) {
698
+ rootNode = newNode
699
+ }
700
+ }
701
+
702
+ return rootNode
703
+ }
704
+
705
+ function patchIndices(patches) {
706
+ var indices = []
707
+
708
+ for (var key in patches) {
709
+ if (key !== "a") {
710
+ indices.push(Number(key))
711
+ }
712
+ }
713
+
714
+ return indices
715
+ }
716
+
717
+ },{"./dom-index":15,"./patch-op":16,"global/document":9,"x-is-array":11}],18:[function(require,module,exports){
718
+ var isWidget = require("../vnode/is-widget.js")
719
+
720
+ module.exports = updateWidget
721
+
722
+ function updateWidget(a, b) {
723
+ if (isWidget(a) && isWidget(b)) {
724
+ if ("name" in a && "name" in b) {
725
+ return a.id === b.id
726
+ } else {
727
+ return a.init === b.init
728
+ }
729
+ }
730
+
731
+ return false
732
+ }
733
+
734
+ },{"../vnode/is-widget.js":28}],19:[function(require,module,exports){
735
+ 'use strict';
736
+
737
+ var EvStore = require('ev-store');
738
+
739
+ module.exports = EvHook;
740
+
741
+ function EvHook(value) {
742
+ if (!(this instanceof EvHook)) {
743
+ return new EvHook(value);
744
+ }
745
+
746
+ this.value = value;
747
+ }
748
+
749
+ EvHook.prototype.hook = function (node, propertyName) {
750
+ var es = EvStore(node);
751
+ var propName = propertyName.substr(3);
752
+
753
+ es[propName] = this.value;
754
+ };
755
+
756
+ EvHook.prototype.unhook = function(node, propertyName) {
757
+ var es = EvStore(node);
758
+ var propName = propertyName.substr(3);
759
+
760
+ es[propName] = undefined;
761
+ };
762
+
763
+ },{"ev-store":6}],20:[function(require,module,exports){
764
+ 'use strict';
765
+
766
+ module.exports = SoftSetHook;
767
+
768
+ function SoftSetHook(value) {
769
+ if (!(this instanceof SoftSetHook)) {
770
+ return new SoftSetHook(value);
771
+ }
772
+
773
+ this.value = value;
774
+ }
775
+
776
+ SoftSetHook.prototype.hook = function (node, propertyName) {
777
+ if (node[propertyName] !== this.value) {
778
+ node[propertyName] = this.value;
779
+ }
780
+ };
781
+
782
+ },{}],21:[function(require,module,exports){
783
+ 'use strict';
784
+
785
+ var isArray = require('x-is-array');
786
+
787
+ var VNode = require('../vnode/vnode.js');
788
+ var VText = require('../vnode/vtext.js');
789
+ var isVNode = require('../vnode/is-vnode');
790
+ var isVText = require('../vnode/is-vtext');
791
+ var isWidget = require('../vnode/is-widget');
792
+ var isHook = require('../vnode/is-vhook');
793
+ var isVThunk = require('../vnode/is-thunk');
794
+
795
+ var parseTag = require('./parse-tag.js');
796
+ var softSetHook = require('./hooks/soft-set-hook.js');
797
+ var evHook = require('./hooks/ev-hook.js');
798
+
799
+ module.exports = h;
800
+
801
+ function h(tagName, properties, children) {
802
+ var childNodes = [];
803
+ var tag, props, key, namespace;
804
+
805
+ if (!children && isChildren(properties)) {
806
+ children = properties;
807
+ props = {};
808
+ }
809
+
810
+ props = props || properties || {};
811
+ tag = parseTag(tagName, props);
812
+
813
+ // support keys
814
+ if (props.hasOwnProperty('key')) {
815
+ key = props.key;
816
+ props.key = undefined;
817
+ }
818
+
819
+ // support namespace
820
+ if (props.hasOwnProperty('namespace')) {
821
+ namespace = props.namespace;
822
+ props.namespace = undefined;
823
+ }
824
+
825
+ // fix cursor bug
826
+ if (tag === 'INPUT' &&
827
+ !namespace &&
828
+ props.hasOwnProperty('value') &&
829
+ props.value !== undefined &&
830
+ !isHook(props.value)
831
+ ) {
832
+ props.value = softSetHook(props.value);
833
+ }
834
+
835
+ transformProperties(props);
836
+
837
+ if (children !== undefined && children !== null) {
838
+ addChild(children, childNodes, tag, props);
839
+ }
840
+
841
+
842
+ return new VNode(tag, props, childNodes, key, namespace);
843
+ }
844
+
845
+ function addChild(c, childNodes, tag, props) {
846
+ if (typeof c === 'string') {
847
+ childNodes.push(new VText(c));
848
+ } else if (isChild(c)) {
849
+ childNodes.push(c);
850
+ } else if (isArray(c)) {
851
+ for (var i = 0; i < c.length; i++) {
852
+ addChild(c[i], childNodes, tag, props);
853
+ }
854
+ } else if (c === null || c === undefined) {
855
+ return;
856
+ } else {
857
+ throw UnexpectedVirtualElement({
858
+ foreignObject: c,
859
+ parentVnode: {
860
+ tagName: tag,
861
+ properties: props
862
+ }
863
+ });
864
+ }
865
+ }
866
+
867
+ function transformProperties(props) {
868
+ for (var propName in props) {
869
+ if (props.hasOwnProperty(propName)) {
870
+ var value = props[propName];
871
+
872
+ if (isHook(value)) {
873
+ continue;
874
+ }
875
+
876
+ if (propName.substr(0, 3) === 'ev-') {
877
+ // add ev-foo support
878
+ props[propName] = evHook(value);
879
+ }
880
+ }
881
+ }
882
+ }
883
+
884
+ function isChild(x) {
885
+ return isVNode(x) || isVText(x) || isWidget(x) || isVThunk(x);
886
+ }
887
+
888
+ function isChildren(x) {
889
+ return typeof x === 'string' || isArray(x) || isChild(x);
890
+ }
891
+
892
+ function UnexpectedVirtualElement(data) {
893
+ var err = new Error();
894
+
895
+ err.type = 'virtual-hyperscript.unexpected.virtual-element';
896
+ err.message = 'Unexpected virtual child passed to h().\n' +
897
+ 'Expected a VNode / Vthunk / VWidget / string but:\n' +
898
+ 'got:\n' +
899
+ errorString(data.foreignObject) +
900
+ '.\n' +
901
+ 'The parent vnode is:\n' +
902
+ errorString(data.parentVnode)
903
+ '\n' +
904
+ 'Suggested fix: change your `h(..., [ ... ])` callsite.';
905
+ err.foreignObject = data.foreignObject;
906
+ err.parentVnode = data.parentVnode;
907
+
908
+ return err;
909
+ }
910
+
911
+ function errorString(obj) {
912
+ try {
913
+ return JSON.stringify(obj, null, ' ');
914
+ } catch (e) {
915
+ return String(obj);
916
+ }
917
+ }
918
+
919
+ },{"../vnode/is-thunk":24,"../vnode/is-vhook":25,"../vnode/is-vnode":26,"../vnode/is-vtext":27,"../vnode/is-widget":28,"../vnode/vnode.js":30,"../vnode/vtext.js":32,"./hooks/ev-hook.js":19,"./hooks/soft-set-hook.js":20,"./parse-tag.js":22,"x-is-array":11}],22:[function(require,module,exports){
920
+ 'use strict';
921
+
922
+ var split = require('browser-split');
923
+
924
+ var classIdSplit = /([\.#]?[a-zA-Z0-9_:-]+)/;
925
+ var notClassId = /^\.|#/;
926
+
927
+ module.exports = parseTag;
928
+
929
+ function parseTag(tag, props) {
930
+ if (!tag) {
931
+ return 'DIV';
932
+ }
933
+
934
+ var noId = !(props.hasOwnProperty('id'));
935
+
936
+ var tagParts = split(tag, classIdSplit);
937
+ var tagName = null;
938
+
939
+ if (notClassId.test(tagParts[1])) {
940
+ tagName = 'DIV';
941
+ }
942
+
943
+ var classes, part, type, i;
944
+
945
+ for (i = 0; i < tagParts.length; i++) {
946
+ part = tagParts[i];
947
+
948
+ if (!part) {
949
+ continue;
950
+ }
951
+
952
+ type = part.charAt(0);
953
+
954
+ if (!tagName) {
955
+ tagName = part;
956
+ } else if (type === '.') {
957
+ classes = classes || [];
958
+ classes.push(part.substring(1, part.length));
959
+ } else if (type === '#' && noId) {
960
+ props.id = part.substring(1, part.length);
961
+ }
962
+ }
963
+
964
+ if (classes) {
965
+ if (props.className) {
966
+ classes.push(props.className);
967
+ }
968
+
969
+ props.className = classes.join(' ');
970
+ }
971
+
972
+ return props.namespace ? tagName : tagName.toUpperCase();
973
+ }
974
+
975
+ },{"browser-split":5}],23:[function(require,module,exports){
976
+ var isVNode = require("./is-vnode")
977
+ var isVText = require("./is-vtext")
978
+ var isWidget = require("./is-widget")
979
+ var isThunk = require("./is-thunk")
980
+
981
+ module.exports = handleThunk
982
+
983
+ function handleThunk(a, b) {
984
+ var renderedA = a
985
+ var renderedB = b
986
+
987
+ if (isThunk(b)) {
988
+ renderedB = renderThunk(b, a)
989
+ }
990
+
991
+ if (isThunk(a)) {
992
+ renderedA = renderThunk(a, null)
993
+ }
994
+
995
+ return {
996
+ a: renderedA,
997
+ b: renderedB
998
+ }
999
+ }
1000
+
1001
+ function renderThunk(thunk, previous) {
1002
+ var renderedThunk = thunk.vnode
1003
+
1004
+ if (!renderedThunk) {
1005
+ renderedThunk = thunk.vnode = thunk.render(previous)
1006
+ }
1007
+
1008
+ if (!(isVNode(renderedThunk) ||
1009
+ isVText(renderedThunk) ||
1010
+ isWidget(renderedThunk))) {
1011
+ throw new Error("thunk did not return a valid node");
1012
+ }
1013
+
1014
+ return renderedThunk
1015
+ }
1016
+
1017
+ },{"./is-thunk":24,"./is-vnode":26,"./is-vtext":27,"./is-widget":28}],24:[function(require,module,exports){
1018
+ module.exports = isThunk
1019
+
1020
+ function isThunk(t) {
1021
+ return t && t.type === "Thunk"
1022
+ }
1023
+
1024
+ },{}],25:[function(require,module,exports){
1025
+ module.exports = isHook
1026
+
1027
+ function isHook(hook) {
1028
+ return hook &&
1029
+ (typeof hook.hook === "function" && !hook.hasOwnProperty("hook") ||
1030
+ typeof hook.unhook === "function" && !hook.hasOwnProperty("unhook"))
1031
+ }
1032
+
1033
+ },{}],26:[function(require,module,exports){
1034
+ var version = require("./version")
1035
+
1036
+ module.exports = isVirtualNode
1037
+
1038
+ function isVirtualNode(x) {
1039
+ return x && x.type === "VirtualNode" && x.version === version
1040
+ }
1041
+
1042
+ },{"./version":29}],27:[function(require,module,exports){
1043
+ var version = require("./version")
1044
+
1045
+ module.exports = isVirtualText
1046
+
1047
+ function isVirtualText(x) {
1048
+ return x && x.type === "VirtualText" && x.version === version
1049
+ }
1050
+
1051
+ },{"./version":29}],28:[function(require,module,exports){
1052
+ module.exports = isWidget
1053
+
1054
+ function isWidget(w) {
1055
+ return w && w.type === "Widget"
1056
+ }
1057
+
1058
+ },{}],29:[function(require,module,exports){
1059
+ module.exports = "2"
1060
+
1061
+ },{}],30:[function(require,module,exports){
1062
+ var version = require("./version")
1063
+ var isVNode = require("./is-vnode")
1064
+ var isWidget = require("./is-widget")
1065
+ var isThunk = require("./is-thunk")
1066
+ var isVHook = require("./is-vhook")
1067
+
1068
+ module.exports = VirtualNode
1069
+
1070
+ var noProperties = {}
1071
+ var noChildren = []
1072
+
1073
+ function VirtualNode(tagName, properties, children, key, namespace) {
1074
+ this.tagName = tagName
1075
+ this.properties = properties || noProperties
1076
+ this.children = children || noChildren
1077
+ this.key = key != null ? String(key) : undefined
1078
+ this.namespace = (typeof namespace === "string") ? namespace : null
1079
+
1080
+ var count = (children && children.length) || 0
1081
+ var descendants = 0
1082
+ var hasWidgets = false
1083
+ var hasThunks = false
1084
+ var descendantHooks = false
1085
+ var hooks
1086
+
1087
+ for (var propName in properties) {
1088
+ if (properties.hasOwnProperty(propName)) {
1089
+ var property = properties[propName]
1090
+ if (isVHook(property) && property.unhook) {
1091
+ if (!hooks) {
1092
+ hooks = {}
1093
+ }
1094
+
1095
+ hooks[propName] = property
1096
+ }
1097
+ }
1098
+ }
1099
+
1100
+ for (var i = 0; i < count; i++) {
1101
+ var child = children[i]
1102
+ if (isVNode(child)) {
1103
+ descendants += child.count || 0
1104
+
1105
+ if (!hasWidgets && child.hasWidgets) {
1106
+ hasWidgets = true
1107
+ }
1108
+
1109
+ if (!hasThunks && child.hasThunks) {
1110
+ hasThunks = true
1111
+ }
1112
+
1113
+ if (!descendantHooks && (child.hooks || child.descendantHooks)) {
1114
+ descendantHooks = true
1115
+ }
1116
+ } else if (!hasWidgets && isWidget(child)) {
1117
+ if (typeof child.destroy === "function") {
1118
+ hasWidgets = true
1119
+ }
1120
+ } else if (!hasThunks && isThunk(child)) {
1121
+ hasThunks = true;
1122
+ }
1123
+ }
1124
+
1125
+ this.count = count + descendants
1126
+ this.hasWidgets = hasWidgets
1127
+ this.hasThunks = hasThunks
1128
+ this.hooks = hooks
1129
+ this.descendantHooks = descendantHooks
1130
+ }
1131
+
1132
+ VirtualNode.prototype.version = version
1133
+ VirtualNode.prototype.type = "VirtualNode"
1134
+
1135
+ },{"./is-thunk":24,"./is-vhook":25,"./is-vnode":26,"./is-widget":28,"./version":29}],31:[function(require,module,exports){
1136
+ var version = require("./version")
1137
+
1138
+ VirtualPatch.NONE = 0
1139
+ VirtualPatch.VTEXT = 1
1140
+ VirtualPatch.VNODE = 2
1141
+ VirtualPatch.WIDGET = 3
1142
+ VirtualPatch.PROPS = 4
1143
+ VirtualPatch.ORDER = 5
1144
+ VirtualPatch.INSERT = 6
1145
+ VirtualPatch.REMOVE = 7
1146
+ VirtualPatch.THUNK = 8
1147
+
1148
+ module.exports = VirtualPatch
1149
+
1150
+ function VirtualPatch(type, vNode, patch) {
1151
+ this.type = Number(type)
1152
+ this.vNode = vNode
1153
+ this.patch = patch
1154
+ }
1155
+
1156
+ VirtualPatch.prototype.version = version
1157
+ VirtualPatch.prototype.type = "VirtualPatch"
1158
+
1159
+ },{"./version":29}],32:[function(require,module,exports){
1160
+ var version = require("./version")
1161
+
1162
+ module.exports = VirtualText
1163
+
1164
+ function VirtualText(text) {
1165
+ this.text = String(text)
1166
+ }
1167
+
1168
+ VirtualText.prototype.version = version
1169
+ VirtualText.prototype.type = "VirtualText"
1170
+
1171
+ },{"./version":29}],33:[function(require,module,exports){
1172
+ var isObject = require("is-object")
1173
+ var isHook = require("../vnode/is-vhook")
1174
+
1175
+ module.exports = diffProps
1176
+
1177
+ function diffProps(a, b) {
1178
+ var diff
1179
+
1180
+ for (var aKey in a) {
1181
+ if (!(aKey in b)) {
1182
+ diff = diff || {}
1183
+ diff[aKey] = undefined
1184
+ }
1185
+
1186
+ var aValue = a[aKey]
1187
+ var bValue = b[aKey]
1188
+
1189
+ if (aValue === bValue) {
1190
+ continue
1191
+ } else if (isObject(aValue) && isObject(bValue)) {
1192
+ if (getPrototype(bValue) !== getPrototype(aValue)) {
1193
+ diff = diff || {}
1194
+ diff[aKey] = bValue
1195
+ } else if (isHook(bValue)) {
1196
+ diff = diff || {}
1197
+ diff[aKey] = bValue
1198
+ } else {
1199
+ var objectDiff = diffProps(aValue, bValue)
1200
+ if (objectDiff) {
1201
+ diff = diff || {}
1202
+ diff[aKey] = objectDiff
1203
+ }
1204
+ }
1205
+ } else {
1206
+ diff = diff || {}
1207
+ diff[aKey] = bValue
1208
+ }
1209
+ }
1210
+
1211
+ for (var bKey in b) {
1212
+ if (!(bKey in a)) {
1213
+ diff = diff || {}
1214
+ diff[bKey] = b[bKey]
1215
+ }
1216
+ }
1217
+
1218
+ return diff
1219
+ }
1220
+
1221
+ function getPrototype(value) {
1222
+ if (Object.getPrototypeOf) {
1223
+ return Object.getPrototypeOf(value)
1224
+ } else if (value.__proto__) {
1225
+ return value.__proto__
1226
+ } else if (value.constructor) {
1227
+ return value.constructor.prototype
1228
+ }
1229
+ }
1230
+
1231
+ },{"../vnode/is-vhook":25,"is-object":10}],34:[function(require,module,exports){
1232
+ var isArray = require("x-is-array")
1233
+
1234
+ var VPatch = require("../vnode/vpatch")
1235
+ var isVNode = require("../vnode/is-vnode")
1236
+ var isVText = require("../vnode/is-vtext")
1237
+ var isWidget = require("../vnode/is-widget")
1238
+ var isThunk = require("../vnode/is-thunk")
1239
+ var handleThunk = require("../vnode/handle-thunk")
1240
+
1241
+ var diffProps = require("./diff-props")
1242
+
1243
+ module.exports = diff
1244
+
1245
+ function diff(a, b) {
1246
+ var patch = { a: a }
1247
+ walk(a, b, patch, 0)
1248
+ return patch
1249
+ }
1250
+
1251
+ function walk(a, b, patch, index) {
1252
+ if (a === b) {
1253
+ return
1254
+ }
1255
+
1256
+ var apply = patch[index]
1257
+ var applyClear = false
1258
+
1259
+ if (isThunk(a) || isThunk(b)) {
1260
+ thunks(a, b, patch, index)
1261
+ } else if (b == null) {
1262
+
1263
+ // If a is a widget we will add a remove patch for it
1264
+ // Otherwise any child widgets/hooks must be destroyed.
1265
+ // This prevents adding two remove patches for a widget.
1266
+ if (!isWidget(a)) {
1267
+ clearState(a, patch, index)
1268
+ apply = patch[index]
1269
+ }
1270
+
1271
+ apply = appendPatch(apply, new VPatch(VPatch.REMOVE, a, b))
1272
+ } else if (isVNode(b)) {
1273
+ if (isVNode(a)) {
1274
+ if (a.tagName === b.tagName &&
1275
+ a.namespace === b.namespace &&
1276
+ a.key === b.key) {
1277
+ var propsPatch = diffProps(a.properties, b.properties)
1278
+ if (propsPatch) {
1279
+ apply = appendPatch(apply,
1280
+ new VPatch(VPatch.PROPS, a, propsPatch))
1281
+ }
1282
+ apply = diffChildren(a, b, patch, apply, index)
1283
+ } else {
1284
+ apply = appendPatch(apply, new VPatch(VPatch.VNODE, a, b))
1285
+ applyClear = true
1286
+ }
1287
+ } else {
1288
+ apply = appendPatch(apply, new VPatch(VPatch.VNODE, a, b))
1289
+ applyClear = true
1290
+ }
1291
+ } else if (isVText(b)) {
1292
+ if (!isVText(a)) {
1293
+ apply = appendPatch(apply, new VPatch(VPatch.VTEXT, a, b))
1294
+ applyClear = true
1295
+ } else if (a.text !== b.text) {
1296
+ apply = appendPatch(apply, new VPatch(VPatch.VTEXT, a, b))
1297
+ }
1298
+ } else if (isWidget(b)) {
1299
+ if (!isWidget(a)) {
1300
+ applyClear = true
1301
+ }
1302
+
1303
+ apply = appendPatch(apply, new VPatch(VPatch.WIDGET, a, b))
1304
+ }
1305
+
1306
+ if (apply) {
1307
+ patch[index] = apply
1308
+ }
1309
+
1310
+ if (applyClear) {
1311
+ clearState(a, patch, index)
1312
+ }
1313
+ }
1314
+
1315
+ function diffChildren(a, b, patch, apply, index) {
1316
+ var aChildren = a.children
1317
+ var orderedSet = reorder(aChildren, b.children)
1318
+ var bChildren = orderedSet.children
1319
+
1320
+ var aLen = aChildren.length
1321
+ var bLen = bChildren.length
1322
+ var len = aLen > bLen ? aLen : bLen
1323
+
1324
+ for (var i = 0; i < len; i++) {
1325
+ var leftNode = aChildren[i]
1326
+ var rightNode = bChildren[i]
1327
+ index += 1
1328
+
1329
+ if (!leftNode) {
1330
+ if (rightNode) {
1331
+ // Excess nodes in b need to be added
1332
+ apply = appendPatch(apply,
1333
+ new VPatch(VPatch.INSERT, null, rightNode))
1334
+ }
1335
+ } else {
1336
+ walk(leftNode, rightNode, patch, index)
1337
+ }
1338
+
1339
+ if (isVNode(leftNode) && leftNode.count) {
1340
+ index += leftNode.count
1341
+ }
1342
+ }
1343
+
1344
+ if (orderedSet.moves) {
1345
+ // Reorder nodes last
1346
+ apply = appendPatch(apply, new VPatch(
1347
+ VPatch.ORDER,
1348
+ a,
1349
+ orderedSet.moves
1350
+ ))
1351
+ }
1352
+
1353
+ return apply
1354
+ }
1355
+
1356
+ function clearState(vNode, patch, index) {
1357
+ // TODO: Make this a single walk, not two
1358
+ unhook(vNode, patch, index)
1359
+ destroyWidgets(vNode, patch, index)
1360
+ }
1361
+
1362
+ // Patch records for all destroyed widgets must be added because we need
1363
+ // a DOM node reference for the destroy function
1364
+ function destroyWidgets(vNode, patch, index) {
1365
+ if (isWidget(vNode)) {
1366
+ if (typeof vNode.destroy === "function") {
1367
+ patch[index] = appendPatch(
1368
+ patch[index],
1369
+ new VPatch(VPatch.REMOVE, vNode, null)
1370
+ )
1371
+ }
1372
+ } else if (isVNode(vNode) && (vNode.hasWidgets || vNode.hasThunks)) {
1373
+ var children = vNode.children
1374
+ var len = children.length
1375
+ for (var i = 0; i < len; i++) {
1376
+ var child = children[i]
1377
+ index += 1
1378
+
1379
+ destroyWidgets(child, patch, index)
1380
+
1381
+ if (isVNode(child) && child.count) {
1382
+ index += child.count
1383
+ }
1384
+ }
1385
+ } else if (isThunk(vNode)) {
1386
+ thunks(vNode, null, patch, index)
1387
+ }
1388
+ }
1389
+
1390
+ // Create a sub-patch for thunks
1391
+ function thunks(a, b, patch, index) {
1392
+ var nodes = handleThunk(a, b)
1393
+ var thunkPatch = diff(nodes.a, nodes.b)
1394
+ if (hasPatches(thunkPatch)) {
1395
+ patch[index] = new VPatch(VPatch.THUNK, null, thunkPatch)
1396
+ }
1397
+ }
1398
+
1399
+ function hasPatches(patch) {
1400
+ for (var index in patch) {
1401
+ if (index !== "a") {
1402
+ return true
1403
+ }
1404
+ }
1405
+
1406
+ return false
1407
+ }
1408
+
1409
+ // Execute hooks when two nodes are identical
1410
+ function unhook(vNode, patch, index) {
1411
+ if (isVNode(vNode)) {
1412
+ if (vNode.hooks) {
1413
+ patch[index] = appendPatch(
1414
+ patch[index],
1415
+ new VPatch(
1416
+ VPatch.PROPS,
1417
+ vNode,
1418
+ undefinedKeys(vNode.hooks)
1419
+ )
1420
+ )
1421
+ }
1422
+
1423
+ if (vNode.descendantHooks || vNode.hasThunks) {
1424
+ var children = vNode.children
1425
+ var len = children.length
1426
+ for (var i = 0; i < len; i++) {
1427
+ var child = children[i]
1428
+ index += 1
1429
+
1430
+ unhook(child, patch, index)
1431
+
1432
+ if (isVNode(child) && child.count) {
1433
+ index += child.count
1434
+ }
1435
+ }
1436
+ }
1437
+ } else if (isThunk(vNode)) {
1438
+ thunks(vNode, null, patch, index)
1439
+ }
1440
+ }
1441
+
1442
+ function undefinedKeys(obj) {
1443
+ var result = {}
1444
+
1445
+ for (var key in obj) {
1446
+ result[key] = undefined
1447
+ }
1448
+
1449
+ return result
1450
+ }
1451
+
1452
+ // List diff, naive left to right reordering
1453
+ function reorder(aChildren, bChildren) {
1454
+ // O(M) time, O(M) memory
1455
+ var bChildIndex = keyIndex(bChildren)
1456
+ var bKeys = bChildIndex.keys
1457
+ var bFree = bChildIndex.free
1458
+
1459
+ if (bFree.length === bChildren.length) {
1460
+ return {
1461
+ children: bChildren,
1462
+ moves: null
1463
+ }
1464
+ }
1465
+
1466
+ // O(N) time, O(N) memory
1467
+ var aChildIndex = keyIndex(aChildren)
1468
+ var aKeys = aChildIndex.keys
1469
+ var aFree = aChildIndex.free
1470
+
1471
+ if (aFree.length === aChildren.length) {
1472
+ return {
1473
+ children: bChildren,
1474
+ moves: null
1475
+ }
1476
+ }
1477
+
1478
+ // O(MAX(N, M)) memory
1479
+ var newChildren = []
1480
+
1481
+ var freeIndex = 0
1482
+ var freeCount = bFree.length
1483
+ var deletedItems = 0
1484
+
1485
+ // Iterate through a and match a node in b
1486
+ // O(N) time,
1487
+ for (var i = 0 ; i < aChildren.length; i++) {
1488
+ var aItem = aChildren[i]
1489
+ var itemIndex
1490
+
1491
+ if (aItem.key) {
1492
+ if (bKeys.hasOwnProperty(aItem.key)) {
1493
+ // Match up the old keys
1494
+ itemIndex = bKeys[aItem.key]
1495
+ newChildren.push(bChildren[itemIndex])
1496
+
1497
+ } else {
1498
+ // Remove old keyed items
1499
+ itemIndex = i - deletedItems++
1500
+ newChildren.push(null)
1501
+ }
1502
+ } else {
1503
+ // Match the item in a with the next free item in b
1504
+ if (freeIndex < freeCount) {
1505
+ itemIndex = bFree[freeIndex++]
1506
+ newChildren.push(bChildren[itemIndex])
1507
+ } else {
1508
+ // There are no free items in b to match with
1509
+ // the free items in a, so the extra free nodes
1510
+ // are deleted.
1511
+ itemIndex = i - deletedItems++
1512
+ newChildren.push(null)
1513
+ }
1514
+ }
1515
+ }
1516
+
1517
+ var lastFreeIndex = freeIndex >= bFree.length ?
1518
+ bChildren.length :
1519
+ bFree[freeIndex]
1520
+
1521
+ // Iterate through b and append any new keys
1522
+ // O(M) time
1523
+ for (var j = 0; j < bChildren.length; j++) {
1524
+ var newItem = bChildren[j]
1525
+
1526
+ if (newItem.key) {
1527
+ if (!aKeys.hasOwnProperty(newItem.key)) {
1528
+ // Add any new keyed items
1529
+ // We are adding new items to the end and then sorting them
1530
+ // in place. In future we should insert new items in place.
1531
+ newChildren.push(newItem)
1532
+ }
1533
+ } else if (j >= lastFreeIndex) {
1534
+ // Add any leftover non-keyed items
1535
+ newChildren.push(newItem)
1536
+ }
1537
+ }
1538
+
1539
+ var simulate = newChildren.slice()
1540
+ var simulateIndex = 0
1541
+ var removes = []
1542
+ var inserts = []
1543
+ var simulateItem
1544
+
1545
+ for (var k = 0; k < bChildren.length;) {
1546
+ var wantedItem = bChildren[k]
1547
+ simulateItem = simulate[simulateIndex]
1548
+
1549
+ // remove items
1550
+ while (simulateItem === null && simulate.length) {
1551
+ removes.push(remove(simulate, simulateIndex, null))
1552
+ simulateItem = simulate[simulateIndex]
1553
+ }
1554
+
1555
+ if (!simulateItem || simulateItem.key !== wantedItem.key) {
1556
+ // if we need a key in this position...
1557
+ if (wantedItem.key) {
1558
+ if (simulateItem && simulateItem.key) {
1559
+ // if an insert doesn't put this key in place, it needs to move
1560
+ if (bKeys[simulateItem.key] !== k + 1) {
1561
+ removes.push(remove(simulate, simulateIndex, simulateItem.key))
1562
+ simulateItem = simulate[simulateIndex]
1563
+ // if the remove didn't put the wanted item in place, we need to insert it
1564
+ if (!simulateItem || simulateItem.key !== wantedItem.key) {
1565
+ inserts.push({key: wantedItem.key, to: k})
1566
+ }
1567
+ // items are matching, so skip ahead
1568
+ else {
1569
+ simulateIndex++
1570
+ }
1571
+ }
1572
+ else {
1573
+ inserts.push({key: wantedItem.key, to: k})
1574
+ }
1575
+ }
1576
+ else {
1577
+ inserts.push({key: wantedItem.key, to: k})
1578
+ }
1579
+ k++
1580
+ }
1581
+ // a key in simulate has no matching wanted key, remove it
1582
+ else if (simulateItem && simulateItem.key) {
1583
+ removes.push(remove(simulate, simulateIndex, simulateItem.key))
1584
+ }
1585
+ }
1586
+ else {
1587
+ simulateIndex++
1588
+ k++
1589
+ }
1590
+ }
1591
+
1592
+ // remove all the remaining nodes from simulate
1593
+ while(simulateIndex < simulate.length) {
1594
+ simulateItem = simulate[simulateIndex]
1595
+ removes.push(remove(simulate, simulateIndex, simulateItem && simulateItem.key))
1596
+ }
1597
+
1598
+ // If the only moves we have are deletes then we can just
1599
+ // let the delete patch remove these items.
1600
+ if (removes.length === deletedItems && !inserts.length) {
1601
+ return {
1602
+ children: newChildren,
1603
+ moves: null
1604
+ }
1605
+ }
1606
+
1607
+ return {
1608
+ children: newChildren,
1609
+ moves: {
1610
+ removes: removes,
1611
+ inserts: inserts
1612
+ }
1613
+ }
1614
+ }
1615
+
1616
+ function remove(arr, index, key) {
1617
+ arr.splice(index, 1)
1618
+
1619
+ return {
1620
+ from: index,
1621
+ key: key
1622
+ }
1623
+ }
1624
+
1625
+ function keyIndex(children) {
1626
+ var keys = {}
1627
+ var free = []
1628
+ var length = children.length
1629
+
1630
+ for (var i = 0; i < length; i++) {
1631
+ var child = children[i]
1632
+
1633
+ if (child.key) {
1634
+ keys[child.key] = i
1635
+ } else {
1636
+ free.push(i)
1637
+ }
1638
+ }
1639
+
1640
+ return {
1641
+ keys: keys, // A hash of key name to index
1642
+ free: free // An array of unkeyed item indices
1643
+ }
1644
+ }
1645
+
1646
+ function appendPatch(apply, patch) {
1647
+ if (apply) {
1648
+ if (isArray(apply)) {
1649
+ apply.push(patch)
1650
+ } else {
1651
+ apply = [apply, patch]
1652
+ }
1653
+
1654
+ return apply
1655
+ } else {
1656
+ return patch
1657
+ }
1658
+ }
1659
+
1660
+ },{"../vnode/handle-thunk":23,"../vnode/is-thunk":24,"../vnode/is-vnode":26,"../vnode/is-vtext":27,"../vnode/is-widget":28,"../vnode/vpatch":31,"./diff-props":33,"x-is-array":11}],35:[function(require,module,exports){
1661
+
1662
+ },{}]},{},[4])(4)
1663
+ });