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