UNPKG

18.4 kBJavaScriptView Raw
1(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'use strict';
3
4var snabbdom = require('../../snabbdom.js');
5var patch = snabbdom.init([require('../../modules/class'), require('../../modules/props'), require('../../modules/style'), require('../../modules/eventlisteners')]);
6var h = require('../../h.js');
7
8var vnode;
9
10var nextKey = 11;
11var margin = 8;
12var sortBy = 'rank';
13var totalHeight = 0;
14var originalData = [{ rank: 1, title: 'The Shawshank Redemption', desc: 'Two imprisoned men bond over a number of years, finding solace and eventual redemption through acts of common decency.', elmHeight: 0 }, { rank: 2, title: 'The Godfather', desc: 'The aging patriarch of an organized crime dynasty transfers control of his clandestine empire to his reluctant son.', elmHeight: 0 }, { rank: 3, title: 'The Godfather: Part II', desc: 'The early life and career of Vito Corleone in 1920s New York is portrayed while his son, Michael, expands and tightens his grip on his crime syndicate stretching from Lake Tahoe, Nevada to pre-revolution 1958 Cuba.', elmHeight: 0 }, { rank: 4, title: 'The Dark Knight', desc: 'When the menace known as the Joker wreaks havoc and chaos on the people of Gotham, the caped crusader must come to terms with one of the greatest psychological tests of his ability to fight injustice.', elmHeight: 0 }, { rank: 5, title: 'Pulp Fiction', desc: 'The lives of two mob hit men, a boxer, a gangster\'s wife, and a pair of diner bandits intertwine in four tales of violence and redemption.', elmHeight: 0 }, { rank: 6, title: 'Schindler\'s List', desc: 'In Poland during World War II, Oskar Schindler gradually becomes concerned for his Jewish workforce after witnessing their persecution by the Nazis.', elmHeight: 0 }, { rank: 7, title: '12 Angry Men', desc: 'A dissenting juror in a murder trial slowly manages to convince the others that the case is not as obviously clear as it seemed in court.', elmHeight: 0 }, { rank: 8, title: 'The Good, the Bad and the Ugly', desc: 'A bounty hunting scam joins two men in an uneasy alliance against a third in a race to find a fortune in gold buried in a remote cemetery.', elmHeight: 0 }, { rank: 9, title: 'The Lord of the Rings: The Return of the King', desc: 'Gandalf and Aragorn lead the World of Men against Sauron\'s army to draw his gaze from Frodo and Sam as they approach Mount Doom with the One Ring.', elmHeight: 0 }, { rank: 10, title: 'Fight Club', desc: 'An insomniac office worker looking for a way to change his life crosses paths with a devil-may-care soap maker and they form an underground fight club that evolves into something much, much more...', elmHeight: 0 }];
15var data = [originalData[0], originalData[1], originalData[2], originalData[3], originalData[4], originalData[5], originalData[6], originalData[7], originalData[8], originalData[9]];
16
17function changeSort(prop) {
18 sortBy = prop;
19 data.sort(function (a, b) {
20 if (a[prop] > b[prop]) {
21 return 1;
22 }
23 if (a[prop] < b[prop]) {
24 return -1;
25 }
26 return 0;
27 });
28 render();
29}
30
31function add() {
32 var n = originalData[Math.floor(Math.random() * 10)];
33 data = [{ rank: nextKey++, title: n.title, desc: n.desc, elmHeight: 0 }].concat(data);
34 render();
35 render();
36}
37
38function remove(movie) {
39 data = data.filter(function (m) {
40 return m !== movie;
41 });
42 render();
43}
44
45function movieView(movie) {
46 return h('div.row', {
47 key: movie.rank,
48 style: { opacity: '0', transform: 'translate(-200px)',
49 delayed: { transform: 'translateY(' + movie.offset + 'px)', opacity: '1' },
50 remove: { opacity: '0', transform: 'translateY(' + movie.offset + 'px) translateX(200px)' } },
51 hook: { insert: function insert(vnode) {
52 movie.elmHeight = vnode.elm.offsetHeight;
53 } } }, [h('div', { style: { fontWeight: 'bold' } }, movie.rank), h('div', movie.title), h('div', movie.desc), h('div.btn.rm-btn', { on: { click: [remove, movie] } }, 'x')]);
54}
55
56function render() {
57 data = data.reduce(function (acc, m) {
58 var last = acc[acc.length - 1];
59 m.offset = last ? last.offset + last.elmHeight + margin : margin;
60 return acc.concat(m);
61 }, []);
62 totalHeight = data[data.length - 1].offset + data[data.length - 1].elmHeight;
63 vnode = patch(vnode, view(data));
64}
65
66function view(data) {
67 return h('div', [h('h1', 'Top 10 movies'), h('div', [h('a.btn.add', { on: { click: add } }, 'Add'), 'Sort by: ', h('span.btn-group', [h('a.btn.rank', { 'class': { active: sortBy === 'rank' }, on: { click: [changeSort, 'rank'] } }, 'Rank'), h('a.btn.title', { 'class': { active: sortBy === 'title' }, on: { click: [changeSort, 'title'] } }, 'Title'), h('a.btn.desc', { 'class': { active: sortBy === 'desc' }, on: { click: [changeSort, 'desc'] } }, 'Description')])]), h('div.list', { style: { height: totalHeight + 'px' } }, data.map(movieView))]);
68}
69
70window.addEventListener('DOMContentLoaded', function () {
71 var container = document.getElementById('container');
72 vnode = patch(container, view(data));
73 render();
74});
75
76},{"../../h.js":2,"../../modules/class":4,"../../modules/eventlisteners":5,"../../modules/props":6,"../../modules/style":7,"../../snabbdom.js":8}],2:[function(require,module,exports){
77'use strict';
78
79var VNode = require('./vnode');
80var is = require('./is');
81
82module.exports = function h(sel, b, c) {
83 var data = {},
84 children,
85 text,
86 i;
87 if (arguments.length === 3) {
88 data = b;
89 if (is.array(c)) {
90 children = c;
91 } else if (is.primitive(c)) {
92 text = c;
93 }
94 } else if (arguments.length === 2) {
95 if (is.array(b)) {
96 children = b;
97 } else if (is.primitive(b)) {
98 text = b;
99 } else {
100 data = b;
101 }
102 }
103 if (is.array(children)) {
104 for (i = 0; i < children.length; ++i) {
105 if (is.primitive(children[i])) children[i] = VNode(undefined, undefined, undefined, children[i]);
106 }
107 }
108 return VNode(sel, data, children, text, undefined);
109};
110
111},{"./is":3,"./vnode":9}],3:[function(require,module,exports){
112'use strict';
113
114module.exports = {
115 array: Array.isArray,
116 primitive: function primitive(s) {
117 return typeof s === 'string' || typeof s === 'number';
118 } };
119
120},{}],4:[function(require,module,exports){
121'use strict';
122
123function updateClass(oldVnode, vnode) {
124 var cur,
125 name,
126 elm = vnode.elm,
127 oldClass = oldVnode.data['class'] || {},
128 klass = vnode.data['class'] || {};
129 for (name in klass) {
130 cur = klass[name];
131 if (cur !== oldClass[name]) {
132 elm.classList[cur ? 'add' : 'remove'](name);
133 }
134 }
135}
136
137module.exports = { create: updateClass, update: updateClass };
138
139},{}],5:[function(require,module,exports){
140'use strict';
141
142var is = require('../is');
143
144function arrInvoker(arr) {
145 return function () {
146 arr[0](arr[1]);
147 };
148}
149
150function updateEventListeners(oldVnode, vnode) {
151 var name,
152 cur,
153 old,
154 elm = vnode.elm,
155 oldOn = oldVnode.data.on || {},
156 on = vnode.data.on;
157 if (!on) return;
158 for (name in on) {
159 cur = on[name];
160 old = oldOn[name];
161 if (old === undefined) {
162 elm.addEventListener(name, is.array(cur) ? arrInvoker(cur) : cur);
163 } else if (is.array(old)) {
164 old[0] = cur[0]; // Deliberately modify old array since it's
165 old[1] = cur[1]; // captured in closure created with `arrInvoker`
166 }
167 }
168}
169
170module.exports = { create: updateEventListeners, update: updateEventListeners };
171
172},{"../is":3}],6:[function(require,module,exports){
173"use strict";
174
175function updateProps(oldVnode, vnode) {
176 var key,
177 cur,
178 old,
179 elm = vnode.elm,
180 oldProps = oldVnode.data.props || {},
181 props = vnode.data.props || {};
182 for (key in props) {
183 cur = props[key];
184 old = oldProps[key];
185 if (old !== cur) {
186 elm[key] = cur;
187 }
188 }
189}
190
191module.exports = { create: updateProps, update: updateProps };
192
193},{}],7:[function(require,module,exports){
194'use strict';
195
196var raf = requestAnimationFrame || setTimeout;
197var nextFrame = function nextFrame(fn) {
198 raf(function () {
199 raf(fn);
200 });
201};
202
203function setNextFrame(obj, prop, val) {
204 nextFrame(function () {
205 obj[prop] = val;
206 });
207}
208
209function updateStyle(oldVnode, vnode) {
210 var cur,
211 name,
212 elm = vnode.elm,
213 oldStyle = oldVnode.data.style || {},
214 style = vnode.data.style || {},
215 oldHasDel = ('delayed' in oldStyle);
216 for (name in style) {
217 cur = style[name];
218 if (name === 'delayed') {
219 for (name in style.delayed) {
220 cur = style.delayed[name];
221 if (!oldHasDel || cur !== oldStyle.delayed[name]) {
222 setNextFrame(elm.style, name, cur);
223 }
224 }
225 } else if (name !== 'remove' && cur !== oldStyle[name]) {
226 elm.style[name] = cur;
227 }
228 }
229}
230
231function applyDestroyStyle(vnode) {
232 var style,
233 name,
234 elm = vnode.elm,
235 s = vnode.data.style;
236 if (!s || !(style = s.destroy)) return;
237 for (name in style) {
238 elm.style[name] = style[name];
239 }
240}
241
242function applyRemoveStyle(vnode, rm) {
243 var s = vnode.data.style;
244 if (!s || !s.remove) {
245 rm();
246 return;
247 }
248 var name,
249 elm = vnode.elm,
250 idx,
251 i = 0,
252 maxDur = 0,
253 compStyle,
254 style = s.remove,
255 amount = 0;
256 var applied = [];
257 for (name in style) {
258 applied.push(name);
259 elm.style[name] = style[name];
260 }
261 compStyle = getComputedStyle(elm);
262 var props = compStyle['transition-property'].split(', ');
263 for (; i < props.length; ++i) {
264 if (applied.indexOf(props[i]) !== -1) amount++;
265 }
266 elm.addEventListener('transitionend', function (ev) {
267 if (ev.target === elm) --amount;
268 if (amount === 0) rm();
269 });
270}
271
272module.exports = { create: updateStyle, update: updateStyle, destroy: applyDestroyStyle, remove: applyRemoveStyle };
273
274},{}],8:[function(require,module,exports){
275// jshint newcap: false
276'use strict';
277
278var VNode = require('./vnode');
279var is = require('./is');
280
281function isUndef(s) {
282 return s === undefined;
283}
284
285function emptyNodeAt(elm) {
286 return VNode(elm.tagName, {}, [], undefined, elm);
287}
288
289var emptyNode = VNode('', {}, [], undefined, undefined);
290
291var insertedVnodeQueue;
292
293function sameVnode(vnode1, vnode2) {
294 return vnode1.key === vnode2.key && vnode1.sel === vnode2.sel;
295}
296
297function createKeyToOldIdx(children, beginIdx, endIdx) {
298 var i,
299 map = {},
300 key;
301 for (i = beginIdx; i <= endIdx; ++i) {
302 key = children[i].key;
303 if (!isUndef(key)) map[key] = i;
304 }
305 return map;
306}
307
308function createRmCb(parentElm, childElm, listeners) {
309 return function () {
310 if (--listeners === 0) parentElm.removeChild(childElm);
311 };
312}
313
314var hooks = ['create', 'update', 'remove', 'destroy', 'pre', 'post'];
315
316function init(modules) {
317 var i,
318 j,
319 cbs = {};
320 for (i = 0; i < hooks.length; ++i) {
321 cbs[hooks[i]] = [];
322 for (j = 0; j < modules.length; ++j) {
323 if (modules[j][hooks[i]] !== undefined) cbs[hooks[i]].push(modules[j][hooks[i]]);
324 }
325 }
326
327 function createElm(vnode) {
328 var i;
329 if (!isUndef(i = vnode.data) && !isUndef(i = i.hook) && !isUndef(i = i.init)) {
330 i(vnode);
331 }
332 if (!isUndef(i = vnode.data) && !isUndef(i = i.vnode)) vnode = i;
333 var elm,
334 children = vnode.children,
335 sel = vnode.sel;
336 if (!isUndef(sel)) {
337 // Parse selector
338 var hashIdx = sel.indexOf('#');
339 var dotIdx = sel.indexOf('.', hashIdx);
340 var hash = hashIdx > 0 ? hashIdx : sel.length;
341 var dot = dotIdx > 0 ? dotIdx : sel.length;
342 var tag = hashIdx !== -1 || dotIdx !== -1 ? sel.slice(0, Math.min(hash, dot)) : sel;
343 elm = vnode.elm = document.createElement(tag);
344 if (hash < dot) elm.id = sel.slice(hash + 1, dot);
345 if (dotIdx > 0) elm.className = sel.slice(dot + 1).replace(/\./g, ' ');
346 if (is.array(children)) {
347 for (i = 0; i < children.length; ++i) {
348 elm.appendChild(createElm(children[i]));
349 }
350 } else if (is.primitive(vnode.text)) {
351 elm.appendChild(document.createTextNode(vnode.text));
352 }
353 for (i = 0; i < cbs.create.length; ++i) cbs.create[i](emptyNode, vnode);
354 i = vnode.data.hook; // Reuse variable
355 if (!isUndef(i)) {
356 if (i.create) i.create(vnode);
357 if (i.insert) insertedVnodeQueue.push(vnode);
358 }
359 } else {
360 elm = vnode.elm = document.createTextNode(vnode.text);
361 }
362 return elm;
363 }
364
365 function addVnodes(parentElm, before, vnodes, startIdx, endIdx) {
366 if (isUndef(before)) {
367 for (; startIdx <= endIdx; ++startIdx) {
368 parentElm.appendChild(createElm(vnodes[startIdx]));
369 }
370 } else {
371 var elm = before.elm;
372 for (; startIdx <= endIdx; ++startIdx) {
373 parentElm.insertBefore(createElm(vnodes[startIdx]), elm);
374 }
375 }
376 }
377
378 function invokeDestroyHook(vnode) {
379 var i = vnode.data.hook,
380 j;
381 if (!isUndef(i) && !isUndef(j = i.destroy)) j(vnode);
382 for (i = 0; i < cbs.destroy.length; ++i) cbs.destroy[i](vnode);
383 if (!isUndef(vnode.children)) {
384 for (j = 0; j < vnode.children.length; ++j) {
385 invokeDestroyHook(vnode.children[j]);
386 }
387 }
388 }
389
390 function removeVnodes(parentElm, vnodes, startIdx, endIdx) {
391 for (; startIdx <= endIdx; ++startIdx) {
392 var i,
393 listeners,
394 rm,
395 ch = vnodes[startIdx];
396 if (!isUndef(ch)) {
397 listeners = cbs.remove.length + 1;
398 rm = createRmCb(parentElm, ch.elm, listeners);
399 for (i = 0; i < cbs.remove.length; ++i) cbs.remove[i](ch, rm);
400 invokeDestroyHook(ch);
401 if (ch.data.hook && ch.data.hook.remove) {
402 ch.data.hook.remove(ch, rm);
403 } else {
404 rm();
405 }
406 }
407 }
408 }
409
410 function updateChildren(parentElm, oldCh, newCh) {
411 var oldStartIdx = 0,
412 newStartIdx = 0;
413 var oldEndIdx = oldCh.length - 1;
414 var oldStartVnode = oldCh[0];
415 var oldEndVnode = oldCh[oldEndIdx];
416 var newEndIdx = newCh.length - 1;
417 var newStartVnode = newCh[0];
418 var newEndVnode = newCh[newEndIdx];
419 var oldKeyToIdx, idxInOld, elmToMove;
420
421 while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
422 if (isUndef(oldStartVnode)) {
423 oldStartVnode = oldCh[++oldStartIdx]; // Vnode has been moved left
424 } else if (isUndef(oldEndVnode)) {
425 oldEndVnode = oldCh[--oldEndIdx];
426 } else if (sameVnode(oldStartVnode, newStartVnode)) {
427 patchVnode(oldStartVnode, newStartVnode);
428 oldStartVnode = oldCh[++oldStartIdx];
429 newStartVnode = newCh[++newStartIdx];
430 } else if (sameVnode(oldEndVnode, newEndVnode)) {
431 patchVnode(oldEndVnode, newEndVnode);
432 oldEndVnode = oldCh[--oldEndIdx];
433 newEndVnode = newCh[--newEndIdx];
434 } else if (sameVnode(oldStartVnode, newEndVnode)) {
435 // Vnode moved right
436 patchVnode(oldStartVnode, newEndVnode);
437 parentElm.insertBefore(oldStartVnode.elm, oldEndVnode.elm.nextSibling);
438 oldStartVnode = oldCh[++oldStartIdx];
439 newEndVnode = newCh[--newEndIdx];
440 } else if (sameVnode(oldEndVnode, newStartVnode)) {
441 // Vnode moved left
442 patchVnode(oldEndVnode, newStartVnode);
443 parentElm.insertBefore(oldEndVnode.elm, oldStartVnode.elm);
444 oldEndVnode = oldCh[--oldEndIdx];
445 newStartVnode = newCh[++newStartIdx];
446 } else {
447 if (isUndef(oldKeyToIdx)) oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx);
448 idxInOld = oldKeyToIdx[newStartVnode.key];
449 if (isUndef(idxInOld)) {
450 // New element
451 parentElm.insertBefore(createElm(newStartVnode), oldStartVnode.elm);
452 newStartVnode = newCh[++newStartIdx];
453 } else {
454 elmToMove = oldCh[idxInOld];
455 patchVnode(elmToMove, newStartVnode);
456 oldCh[idxInOld] = undefined;
457 parentElm.insertBefore(elmToMove.elm, oldStartVnode.elm);
458 newStartVnode = newCh[++newStartIdx];
459 }
460 }
461 }
462 if (oldStartIdx > oldEndIdx) addVnodes(parentElm, oldStartVnode, newCh, newStartIdx, newEndIdx);else if (newStartIdx > newEndIdx) removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx);
463 }
464
465 function patchVnode(oldVnode, vnode) {
466 var i;
467 if (!isUndef(i = vnode.data) && !isUndef(i = i.hook) && !isUndef(i = i.patch)) {
468 i = i(oldVnode, vnode);
469 }
470 if (!isUndef(i = oldVnode.data) && !isUndef(i = i.vnode)) oldVnode = i;
471 if (!isUndef(i = vnode.data) && !isUndef(i = i.vnode)) vnode = i;
472 var elm = vnode.elm = oldVnode.elm,
473 oldCh = oldVnode.children,
474 ch = vnode.children;
475 if (oldVnode === vnode) return;
476 if (!isUndef(vnode.data)) {
477 for (i = 0; i < cbs.update.length; ++i) cbs.update[i](oldVnode, vnode);
478 i = vnode.data.hook;
479 if (!isUndef(i) && !isUndef(i = i.update)) i(vnode);
480 }
481 if (isUndef(vnode.text)) {
482 if (!isUndef(oldCh) && !isUndef(ch)) {
483 if (oldCh !== ch) updateChildren(elm, oldCh, ch);
484 } else if (!isUndef(ch)) {
485 addVnodes(elm, undefined, ch, 0, ch.length - 1);
486 } else if (!isUndef(oldCh)) {
487 removeVnodes(elm, oldCh, 0, oldCh.length - 1);
488 }
489 } else if (oldVnode.text !== vnode.text) {
490 elm.childNodes[0].nodeValue = vnode.text;
491 }
492 return vnode;
493 }
494
495 return function (oldVnode, vnode) {
496 var i;
497 insertedVnodeQueue = [];
498 if (oldVnode instanceof Element) {
499 oldVnode = emptyNodeAt(oldVnode);
500 }
501 for (i = 0; i < cbs.pre.length; ++i) cbs.pre[i]();
502 patchVnode(oldVnode, vnode);
503 for (i = 0; i < insertedVnodeQueue.length; ++i) {
504 insertedVnodeQueue[i].data.hook.insert(insertedVnodeQueue[i]);
505 }
506 insertedVnodeQueue = undefined;
507 for (i = 0; i < cbs.post.length; ++i) cbs.post[i]();
508 return vnode;
509 };
510}
511
512module.exports = { init: init };
513
514},{"./is":3,"./vnode":9}],9:[function(require,module,exports){
515"use strict";
516
517module.exports = function (sel, data, children, text, elm) {
518 var key = data === undefined ? undefined : data.key;
519 return { sel: sel, data: data, children: children,
520 text: text, elm: elm, key: key };
521};
522
523},{}]},{},[1]);