move snabbdom into libs/

This commit is contained in:
Géry Debongnie
2019-03-14 11:30:49 +01:00
parent f08ff9e5c2
commit 027318bb98
85 changed files with 12 additions and 12 deletions
+19
View File
@@ -0,0 +1,19 @@
This carousel example uses `style transform` and `transition` to rotate a group of SVG triangles.
Also, the color of each triangle changes when you hover or click/tap it.
I built the build.js using npm and browserify.
In my local copy of the snabbdom project root I did these preparations:
```
npm install --save-dev babelify
npm install --save-dev babel-preset-es2015
echo '{ "presets": ["es2015"] }' > .babelrc
```
I then built like this:
```
browserify examples/carousel-svg/script.js -t babelify -o examples/carousel-svg/build.js
```
-- *jk*
+566
View File
@@ -0,0 +1,566 @@
(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){
'use strict';
var VNode = require('./vnode');
var is = require('./is');
function addNS(data, children) {
data.ns = 'http://www.w3.org/2000/svg';
if (children !== undefined) {
for (var i = 0; i < children.length; ++i) {
addNS(children[i].data, children[i].children);
}
}
}
module.exports = function h(sel, b, c) {
var data = {},
children,
text,
i;
if (arguments.length === 3) {
data = b;
if (is.array(c)) {
children = c;
} else if (is.primitive(c)) {
text = c;
}
} else if (arguments.length === 2) {
if (is.array(b)) {
children = b;
} else if (is.primitive(b)) {
text = b;
} else {
data = b;
}
}
if (is.array(children)) {
for (i = 0; i < children.length; ++i) {
if (is.primitive(children[i])) children[i] = VNode(undefined, undefined, undefined, children[i]);
}
}
if (sel[0] === 's' && sel[1] === 'v' && sel[2] === 'g') {
addNS(data, children);
}
return VNode(sel, data, children, text, undefined);
};
},{"./is":2,"./vnode":7}],2:[function(require,module,exports){
'use strict';
module.exports = {
array: Array.isArray,
primitive: function primitive(s) {
return typeof s === 'string' || typeof s === 'number';
}
};
},{}],3:[function(require,module,exports){
"use strict";
var booleanAttrs = ["allowfullscreen", "async", "autofocus", "autoplay", "checked", "compact", "controls", "declare", "default", "defaultchecked", "defaultmuted", "defaultselected", "defer", "disabled", "draggable", "enabled", "formnovalidate", "hidden", "indeterminate", "inert", "ismap", "itemscope", "loop", "multiple", "muted", "nohref", "noresize", "noshade", "novalidate", "nowrap", "open", "pauseonexit", "readonly", "required", "reversed", "scoped", "seamless", "selected", "sortable", "spellcheck", "translate", "truespeed", "typemustmatch", "visible"];
var booleanAttrsDict = {};
for (var i = 0, len = booleanAttrs.length; i < len; i++) {
booleanAttrsDict[booleanAttrs[i]] = true;
}
function updateAttrs(oldVnode, vnode) {
var key,
cur,
old,
elm = vnode.elm,
oldAttrs = oldVnode.data.attrs || {},
attrs = vnode.data.attrs || {};
// update modified attributes, add new attributes
for (key in attrs) {
cur = attrs[key];
old = oldAttrs[key];
if (old !== cur) {
// TODO: add support to namespaced attributes (setAttributeNS)
if (!cur && booleanAttrsDict[key]) elm.removeAttribute(key);else elm.setAttribute(key, cur);
}
}
//remove removed attributes
// use `in` operator since the previous `for` iteration uses it (.i.e. add even attributes with undefined value)
// the other option is to remove all attributes with value == undefined
for (key in oldAttrs) {
if (!(key in attrs)) {
elm.removeAttribute(key);
}
}
}
module.exports = { create: updateAttrs, update: updateAttrs };
},{}],4:[function(require,module,exports){
'use strict';
var is = require('../is');
function arrInvoker(arr) {
return function () {
// Special case when length is two, for performance
arr.length === 2 ? arr[0](arr[1]) : arr[0].apply(undefined, arr.slice(1));
};
}
function fnInvoker(o) {
return function (ev) {
o.fn(ev);
};
}
function updateEventListeners(oldVnode, vnode) {
var name,
cur,
old,
elm = vnode.elm,
oldOn = oldVnode.data.on || {},
on = vnode.data.on;
if (!on) return;
for (name in on) {
cur = on[name];
old = oldOn[name];
if (old === undefined) {
if (is.array(cur)) {
elm.addEventListener(name, arrInvoker(cur));
} else {
cur = { fn: cur };
on[name] = cur;
elm.addEventListener(name, fnInvoker(cur));
}
} else if (is.array(old)) {
// Deliberately modify old array since it's captured in closure created with `arrInvoker`
old.length = cur.length;
for (var i = 0; i < old.length; ++i) {
old[i] = cur[i];
}on[name] = old;
} else {
old.fn = cur;
on[name] = old;
}
}
}
module.exports = { create: updateEventListeners, update: updateEventListeners };
},{"../is":2}],5:[function(require,module,exports){
'use strict';
var raf = window && window.requestAnimationFrame || setTimeout;
var nextFrame = function nextFrame(fn) {
raf(function () {
raf(fn);
});
};
function setNextFrame(obj, prop, val) {
nextFrame(function () {
obj[prop] = val;
});
}
function updateStyle(oldVnode, vnode) {
var cur,
name,
elm = vnode.elm,
oldStyle = oldVnode.data.style || {},
style = vnode.data.style || {},
oldHasDel = 'delayed' in oldStyle;
for (name in oldStyle) {
if (!style[name]) {
elm.style[name] = '';
}
}
for (name in style) {
cur = style[name];
if (name === 'delayed') {
for (name in style.delayed) {
cur = style.delayed[name];
if (!oldHasDel || cur !== oldStyle.delayed[name]) {
setNextFrame(elm.style, name, cur);
}
}
} else if (name !== 'remove' && cur !== oldStyle[name]) {
elm.style[name] = cur;
}
}
}
function applyDestroyStyle(vnode) {
var style,
name,
elm = vnode.elm,
s = vnode.data.style;
if (!s || !(style = s.destroy)) return;
for (name in style) {
elm.style[name] = style[name];
}
}
function applyRemoveStyle(vnode, rm) {
var s = vnode.data.style;
if (!s || !s.remove) {
rm();
return;
}
var name,
elm = vnode.elm,
idx,
i = 0,
maxDur = 0,
compStyle,
style = s.remove,
amount = 0,
applied = [];
for (name in style) {
applied.push(name);
elm.style[name] = style[name];
}
compStyle = getComputedStyle(elm);
var props = compStyle['transition-property'].split(', ');
for (; i < props.length; ++i) {
if (applied.indexOf(props[i]) !== -1) amount++;
}
elm.addEventListener('transitionend', function (ev) {
if (ev.target === elm) --amount;
if (amount === 0) rm();
});
}
module.exports = { create: updateStyle, update: updateStyle, destroy: applyDestroyStyle, remove: applyRemoveStyle };
},{}],6:[function(require,module,exports){
// jshint newcap: false
/* global require, module, document, Element */
'use strict';
var VNode = require('./vnode');
var is = require('./is');
function isUndef(s) {
return s === undefined;
}
function isDef(s) {
return s !== undefined;
}
function emptyNodeAt(elm) {
return VNode(elm.tagName, {}, [], undefined, elm);
}
var emptyNode = VNode('', {}, [], undefined, undefined);
function sameVnode(vnode1, vnode2) {
return vnode1.key === vnode2.key && vnode1.sel === vnode2.sel;
}
function createKeyToOldIdx(children, beginIdx, endIdx) {
var i,
map = {},
key;
for (i = beginIdx; i <= endIdx; ++i) {
key = children[i].key;
if (isDef(key)) map[key] = i;
}
return map;
}
function createRmCb(childElm, listeners) {
return function () {
if (--listeners === 0) childElm.parentElement.removeChild(childElm);
};
}
var hooks = ['create', 'update', 'remove', 'destroy', 'pre', 'post'];
function init(modules) {
var i,
j,
cbs = {};
for (i = 0; i < hooks.length; ++i) {
cbs[hooks[i]] = [];
for (j = 0; j < modules.length; ++j) {
if (modules[j][hooks[i]] !== undefined) cbs[hooks[i]].push(modules[j][hooks[i]]);
}
}
function createElm(vnode, insertedVnodeQueue) {
var i,
data = vnode.data;
if (isDef(data)) {
if (isDef(i = data.hook) && isDef(i = i.init)) i(vnode);
if (isDef(i = data.vnode)) vnode = i;
}
var elm,
children = vnode.children,
sel = vnode.sel;
if (isDef(sel)) {
// Parse selector
var hashIdx = sel.indexOf('#');
var dotIdx = sel.indexOf('.', hashIdx);
var hash = hashIdx > 0 ? hashIdx : sel.length;
var dot = dotIdx > 0 ? dotIdx : sel.length;
var tag = hashIdx !== -1 || dotIdx !== -1 ? sel.slice(0, Math.min(hash, dot)) : sel;
elm = vnode.elm = isDef(data) && isDef(i = data.ns) ? document.createElementNS(i, tag) : document.createElement(tag);
if (hash < dot) elm.id = sel.slice(hash + 1, dot);
if (dotIdx > 0) elm.className = sel.slice(dot + 1).replace(/\./g, ' ');
if (is.array(children)) {
for (i = 0; i < children.length; ++i) {
elm.appendChild(createElm(children[i], insertedVnodeQueue));
}
} else if (is.primitive(vnode.text)) {
elm.appendChild(document.createTextNode(vnode.text));
}
for (i = 0; i < cbs.create.length; ++i) {
cbs.create[i](emptyNode, vnode);
}i = vnode.data.hook; // Reuse variable
if (isDef(i)) {
if (i.create) i.create(emptyNode, vnode);
if (i.insert) insertedVnodeQueue.push(vnode);
}
} else {
elm = vnode.elm = document.createTextNode(vnode.text);
}
return vnode.elm;
}
function addVnodes(parentElm, before, vnodes, startIdx, endIdx, insertedVnodeQueue) {
for (; startIdx <= endIdx; ++startIdx) {
parentElm.insertBefore(createElm(vnodes[startIdx], insertedVnodeQueue), before);
}
}
function invokeDestroyHook(vnode) {
var i = vnode.data,
j;
if (isDef(i)) {
if (isDef(i = i.hook) && isDef(i = i.destroy)) i(vnode);
for (i = 0; i < cbs.destroy.length; ++i) {
cbs.destroy[i](vnode);
}if (isDef(i = vnode.children)) {
for (j = 0; j < vnode.children.length; ++j) {
invokeDestroyHook(vnode.children[j]);
}
}
}
}
function removeVnodes(parentElm, vnodes, startIdx, endIdx) {
for (; startIdx <= endIdx; ++startIdx) {
var i,
listeners,
rm,
ch = vnodes[startIdx];
if (isDef(ch)) {
if (isDef(ch.sel)) {
invokeDestroyHook(ch);
listeners = cbs.remove.length + 1;
rm = createRmCb(ch.elm, listeners);
for (i = 0; i < cbs.remove.length; ++i) {
cbs.remove[i](ch, rm);
}if (isDef(i = ch.data) && isDef(i = i.hook) && isDef(i = i.remove)) {
i(ch, rm);
} else {
rm();
}
} else {
// Text node
parentElm.removeChild(ch.elm);
}
}
}
}
function updateChildren(parentElm, oldCh, newCh, insertedVnodeQueue) {
var oldStartIdx = 0,
newStartIdx = 0;
var oldEndIdx = oldCh.length - 1;
var oldStartVnode = oldCh[0];
var oldEndVnode = oldCh[oldEndIdx];
var newEndIdx = newCh.length - 1;
var newStartVnode = newCh[0];
var newEndVnode = newCh[newEndIdx];
var oldKeyToIdx, idxInOld, elmToMove, before;
while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
if (isUndef(oldStartVnode)) {
oldStartVnode = oldCh[++oldStartIdx]; // Vnode has been moved left
} else if (isUndef(oldEndVnode)) {
oldEndVnode = oldCh[--oldEndIdx];
} else if (sameVnode(oldStartVnode, newStartVnode)) {
patchVnode(oldStartVnode, newStartVnode, insertedVnodeQueue);
oldStartVnode = oldCh[++oldStartIdx];
newStartVnode = newCh[++newStartIdx];
} else if (sameVnode(oldEndVnode, newEndVnode)) {
patchVnode(oldEndVnode, newEndVnode, insertedVnodeQueue);
oldEndVnode = oldCh[--oldEndIdx];
newEndVnode = newCh[--newEndIdx];
} else if (sameVnode(oldStartVnode, newEndVnode)) {
// Vnode moved right
patchVnode(oldStartVnode, newEndVnode, insertedVnodeQueue);
parentElm.insertBefore(oldStartVnode.elm, oldEndVnode.elm.nextSibling);
oldStartVnode = oldCh[++oldStartIdx];
newEndVnode = newCh[--newEndIdx];
} else if (sameVnode(oldEndVnode, newStartVnode)) {
// Vnode moved left
patchVnode(oldEndVnode, newStartVnode, insertedVnodeQueue);
parentElm.insertBefore(oldEndVnode.elm, oldStartVnode.elm);
oldEndVnode = oldCh[--oldEndIdx];
newStartVnode = newCh[++newStartIdx];
} else {
if (isUndef(oldKeyToIdx)) oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx);
idxInOld = oldKeyToIdx[newStartVnode.key];
if (isUndef(idxInOld)) {
// New element
parentElm.insertBefore(createElm(newStartVnode, insertedVnodeQueue), oldStartVnode.elm);
newStartVnode = newCh[++newStartIdx];
} else {
elmToMove = oldCh[idxInOld];
patchVnode(elmToMove, newStartVnode, insertedVnodeQueue);
oldCh[idxInOld] = undefined;
parentElm.insertBefore(elmToMove.elm, oldStartVnode.elm);
newStartVnode = newCh[++newStartIdx];
}
}
}
if (oldStartIdx > oldEndIdx) {
before = isUndef(newCh[newEndIdx + 1]) ? null : newCh[newEndIdx + 1].elm;
addVnodes(parentElm, before, newCh, newStartIdx, newEndIdx, insertedVnodeQueue);
} else if (newStartIdx > newEndIdx) {
removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx);
}
}
function patchVnode(oldVnode, vnode, insertedVnodeQueue) {
var i, hook;
if (isDef(i = vnode.data) && isDef(hook = i.hook) && isDef(i = hook.prepatch)) {
i(oldVnode, vnode);
}
if (isDef(i = oldVnode.data) && isDef(i = i.vnode)) oldVnode = i;
if (isDef(i = vnode.data) && isDef(i = i.vnode)) vnode = i;
var elm = vnode.elm = oldVnode.elm,
oldCh = oldVnode.children,
ch = vnode.children;
if (oldVnode === vnode) return;
if (isDef(vnode.data)) {
for (i = 0; i < cbs.update.length; ++i) {
cbs.update[i](oldVnode, vnode);
}i = vnode.data.hook;
if (isDef(i) && isDef(i = i.update)) i(oldVnode, vnode);
}
if (isUndef(vnode.text)) {
if (isDef(oldCh) && isDef(ch)) {
if (oldCh !== ch) updateChildren(elm, oldCh, ch, insertedVnodeQueue);
} else if (isDef(ch)) {
addVnodes(elm, null, ch, 0, ch.length - 1, insertedVnodeQueue);
} else if (isDef(oldCh)) {
removeVnodes(elm, oldCh, 0, oldCh.length - 1);
}
} else if (oldVnode.text !== vnode.text) {
elm.textContent = vnode.text;
}
if (isDef(hook) && isDef(i = hook.postpatch)) {
i(oldVnode, vnode);
}
}
return function (oldVnode, vnode) {
var i;
var insertedVnodeQueue = [];
for (i = 0; i < cbs.pre.length; ++i) {
cbs.pre[i]();
}if (oldVnode instanceof Element) {
if (oldVnode.parentElement !== null) {
createElm(vnode, insertedVnodeQueue);
oldVnode.parentElement.replaceChild(vnode.elm, oldVnode);
} else {
oldVnode = emptyNodeAt(oldVnode);
patchVnode(oldVnode, vnode, insertedVnodeQueue);
}
} else {
patchVnode(oldVnode, vnode, insertedVnodeQueue);
}
for (i = 0; i < insertedVnodeQueue.length; ++i) {
insertedVnodeQueue[i].data.hook.insert(insertedVnodeQueue[i]);
}
for (i = 0; i < cbs.post.length; ++i) {
cbs.post[i]();
}return vnode;
};
}
module.exports = { init: init };
},{"./is":2,"./vnode":7}],7:[function(require,module,exports){
"use strict";
module.exports = function (sel, data, children, text, elm) {
var key = data === undefined ? undefined : data.key;
return { sel: sel, data: data, children: children,
text: text, elm: elm, key: key };
};
},{}],8:[function(require,module,exports){
'use strict';
var snabbdom = require('../../snabbdom.js');
var patch = snabbdom.init([require('../../modules/attributes'), require('../../modules/style'), require('../../modules/eventlisteners')]);
var h = require('../../h.js');
var vnode;
var data = {
degRotation: 0
};
function gRotation() {
//console.log("gRotation: %s", data.degRotation);
return "rotate(" + data.degRotation + "deg)";
}
function triangleClick(id) {
console.log("triangleClick: %s", id);
render();
}
function handleRotate(degs) {
data.degRotation += degs;
console.log("handleRotate: %s, %s", degs, data.degRotation);
render();
}
function handleReset(degs) {
data.degRotation = degs;
console.log("handleReset: %s", degs);
render();
}
function render() {
vnode = patch(vnode, view(data));
}
var hTriangle = function hTriangle(id, degRotation) {
return h("polygon#" + id, {
attrs: {
points: "-50,-88 0,-175 50,-88",
transform: "rotate(" + degRotation + ")",
"stroke-width": 3
},
on: { click: [triangleClick, id] }
});
};
var view = function view(data) {
return h("div.view", [h("h1", "Snabbdom SVG Carousel"), h("svg", { attrs: { width: 380, height: 380, viewBox: [-190, -190, 380, 380] } }, [h("g#carousel", { style: { "-webkit-transform": gRotation(), transform: gRotation() } }, [hTriangle("yellow", 0), hTriangle("green", 60), hTriangle("magenta", 120), hTriangle("red", 180), hTriangle("cyan", 240), hTriangle("blue", 300)])]), h("button", { on: { click: [handleRotate, 60] } }, "Rotate Clockwise"), h("button", { on: { click: [handleRotate, -60] } }, "Rotate Anticlockwise"), h("button", { on: { click: [handleReset, 0] } }, "Reset")]);
};
window.addEventListener("DOMContentLoaded", function () {
var container = document.getElementById("container");
vnode = patch(container, view(data));
render();
});
},{"../../h.js":1,"../../modules/attributes":3,"../../modules/eventlisteners":4,"../../modules/style":5,"../../snabbdom.js":6}]},{},[8]);
+74
View File
@@ -0,0 +1,74 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<meta charset="utf-8">
<title>Carousel</title>
<script type="text/javascript" src="build.js"></script>
<style type="text/css">
div.view {
margin: 10px;
}
h1 {
font-size: 24px;
color: #505000;
}
svg {
display: block;
margin-bottom: 10px;
border: 1px solid gray;
}
g#carousel {
-webkit-transition: -webkit-transform 1s ease;
transition: transform 1s ease;
}
polygon {
stroke: #808000;
transition: fill 0.5s linear;
}
polygon#yellow {
fill: rgba(255,255,0,0.4);
}
polygon#yellow:hover, polygon#yellow:active {
fill: yellow;
}
polygon#green {
fill: rgba(0,128,0,0.4);
}
polygon#green:hover, polygon#green:active {
fill: green;
}
polygon#magenta {
fill: rgba(255,0,255,0.4);
}
polygon#magenta:hover, polygon#magenta:active {
fill: magenta;
}
polygon#red {
fill: rgba(255,0,0,0.4);
}
polygon#red:hover, polygon#red:active {
fill: red;
}
polygon#cyan {
fill: rgba(0,255,255,0.4);
}
polygon#cyan:hover, polygon#cyan:active {
fill: cyan;
}
polygon#blue {
fill: rgba(0,0,255,0.4);
}
polygon#blue:hover, polygon#blue:active {
fill: blue;
}
button {
font-size: 15px;
margin: 0 0.7em 0.7em 0;
}
</style>
</head>
<body>
<div id="container"></div>
</body>
</html>
+74
View File
@@ -0,0 +1,74 @@
var snabbdom = require('../../snabbdom.js');
var patch = snabbdom.init([
require('../../modules/attributes').default,
require('../../modules/style').default,
require('../../modules/eventlisteners').default
]);
var h = require('../../h.js').default;
var vnode;
var data = {
degRotation: 0
};
function gRotation() {
//console.log("gRotation: %s", data.degRotation);
return "rotate(" + data.degRotation + "deg)";
}
function triangleClick(id) {
console.log("triangleClick: %s", id);
render();
}
function handleRotate(degs) {
data.degRotation += degs;
console.log("handleRotate: %s, %s", degs, data.degRotation);
render();
}
function handleReset(degs) {
data.degRotation = degs;
console.log("handleReset: %s", degs);
render();
}
function render() {
vnode = patch(vnode, view(data));
}
const hTriangle = (id, degRotation) =>
h("polygon#" + id, {
attrs: {
points: "-50,-88 0,-175 50,-88",
transform: "rotate(" + degRotation + ")",
"stroke-width": 3
},
on: {click: [triangleClick, id]}
});
const view = (data) =>
h("div.view", [
h("h1", "Snabbdom SVG Carousel"),
h("svg", {attrs: {width: 380, height: 380, viewBox: [-190, -190, 380, 380]}}, [
h("g#carousel",
{style: {"-webkit-transform": gRotation(), transform: gRotation()}}, [
hTriangle("yellow", 0),
hTriangle("green", 60),
hTriangle("magenta", 120),
hTriangle("red", 180),
hTriangle("cyan", 240),
hTriangle("blue", 300)
])
]),
h("button", {on: {click: [handleRotate, 60]}}, "Rotate Clockwise"),
h("button", {on: {click: [handleRotate, -60]}}, "Rotate Anticlockwise"),
h("button", {on: {click: [handleReset, 0]}}, "Reset")
]);
window.addEventListener("DOMContentLoaded", () => {
var container = document.getElementById("container");
vnode = patch(container, view(data));
render();
});
+708
View File
@@ -0,0 +1,708 @@
(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){
/* jshint esnext: true */
'use strict';
var snabbdom = require('../../snabbdom.js');
var patch = snabbdom.init([require('../../modules/class'), require('../../modules/hero'), require('../../modules/style'), require('../../modules/eventlisteners')]);
var h = require('../../h.js');
var vnode;
var data = {
selected: undefined,
movies: [{ rank: 1, title: 'This is an', desc: 'Lorem ipsum dolor sit amet, sed pede integer vitae bibendum, accumsan sit, vulputate aenean tempora ipsum. Lorem sed id et metus, eros posuere suspendisse nec nunc justo, fusce augue placerat nibh purus suspendisse. Aliquam aliquam, ut eget. Mollis a eget sed nibh tincidunt nec, mi integer, proin magna lacus iaculis tortor. Aliquam vel arcu arcu, vivamus a urna fames felis vel wisi, cursus tortor nec erat dignissim cras sem, mauris ac venenatis tellus elit.' }, { rank: 2, title: 'example of', desc: 'Consequuntur ipsum nulla, consequat curabitur in magnis risus. Taciti mattis bibendum tellus nibh, at dui neque eget, odio pede ut, sapien pede, ipsum ut. Sagittis dui, sodales sem, praesent ipsum conubia eget lorem lobortis wisi.' }, { rank: 3, title: 'Snabbdom', desc: 'Quam lorem aliquam fusce wisi, urna purus ipsum pharetra sed, at cras sodales enim vestibulum odio cras, luctus integer phasellus.' }, { rank: 4, title: 'doing hero transitions', desc: 'Et orci hac ultrices id in. Diam ultrices luctus egestas, sem aliquam auctor molestie odio laoreet. Pede nam cubilia, diam vestibulum ornare natoque, aenean etiam fusce id, eget dictum blandit et mauris mauris. Metus amet ad, elit porttitor a aliquet commodo lacus, integer neque imperdiet augue laoreet, nonummy turpis lacus sed pulvinar condimentum platea. Wisi eleifend quis, tristique dictum, ac dictumst. Sem nec tristique vel vehicula fringilla, nibh eu et posuere mi rhoncus.' }, { rank: 5, title: 'using the', desc: 'Pede nam cubilia, diam vestibulum ornare natoque, aenean etiam fusce id, eget dictum blandit et mauris mauris. Metus amet ad, elit porttitor a aliquet commodo lacus, integer neque imperdiet augue laoreet, nonummy turpis lacus sed pulvinar condimentum platea. Wisi eleifend quis, tristique dictum, ac dictumst. Sem nec tristique vel vehicula fringilla, nibh eu et posuere mi rhoncus.' }, { rank: 6, title: 'module for hero transitions', desc: 'Sapien laoreet, ligula elit tortor nulla pellentesque, maecenas enim turpis, quae duis venenatis vivamus ultricies, nunc imperdiet sollicitudin ipsum malesuada. Ut sem. Wisi fusce nullam nibh enim. Nisl hymenaeos id sed sed in. Proin leo et, pulvinar nunc pede laoreet.' }, { rank: 7, title: 'click on ar element in', desc: 'Accumsan quia, id nascetur dui et congue erat, id excepteur, primis ratione nec. At nulla et. Suspendisse lobortis, lobortis in tortor fringilla, duis adipiscing vestibulum voluptates sociosqu auctor.' }, { rank: 8, title: 'the list', desc: 'Ante tellus egestas vel hymenaeos, ut viverra nibh ut, ipsum nibh donec donec dolor. Eros ridiculus vel egestas convallis ipsum, commodo ut venenatis nullam porta iaculis, suspendisse ante proin leo, felis risus etiam.' }, { rank: 9, title: 'to witness', desc: 'Metus amet ad, elit porttitor a aliquet commodo lacus, integer neque imperdiet augue laoreet, nonummy turpis lacus sed pulvinar condimentum platea. Wisi eleifend quis, tristique dictum, ac dictumst.' }, { rank: 10, title: 'the effect', desc: 'Et orci hac ultrices id in. Diam ultrices luctus egestas, sem aliquam auctor molestie odio laoreet. Pede nam cubilia, diam vestibulum ornare natoque, aenean etiam fusce id, eget dictum blandit et mauris mauris' }]
};
function select(m) {
data.selected = m;
render();
}
function render() {
vnode = patch(vnode, view(data));
}
var fadeInOutStyle = {
opacity: '0', delayed: { opacity: '1' }, remove: { opacity: '0' }
};
var detailView = function detailView(movie) {
return h('div.page', { style: fadeInOutStyle }, [h('div.header', [h('div.header-content.detail', {
style: { opacity: '1', remove: { opacity: '0' } }
}, [h('div.rank', [h('span.header-rank.hero', { hero: { id: 'rank' + movie.rank } }, movie.rank), h('div.rank-circle', {
style: { transform: 'scale(0)',
delayed: { transform: 'scale(1)' },
destroy: { transform: 'scale(0)' } }
})]), h('div.hero.header-title', { hero: { id: movie.title } }, movie.title), h('div.spacer'), h('div.close', {
on: { click: [select, undefined] },
style: { transform: 'scale(0)',
delayed: { transform: 'scale(1)' },
destroy: { transform: 'scale(0)' } }
}, 'x')])]), h('div.page-content', [h('div.desc', {
style: { opacity: '0', transform: 'translateX(3em)',
delayed: { opacity: '1', transform: 'translate(0)' },
remove: { opacity: '0', position: 'absolute', top: '0', left: '0',
transform: 'translateX(3em)' }
}
}, [h('h2', 'Description:'), h('span', movie.desc)])])]);
};
var overviewView = function overviewView(movies) {
return h('div.page', { style: fadeInOutStyle }, [h('div.header', [h('div.header-content.overview', {
style: fadeInOutStyle
}, [h('div.header-title', {
style: { transform: 'translateY(-2em)',
delayed: { transform: 'translate(0)' },
destroy: { transform: 'translateY(-2em)' } }
}, 'Top 10 movies'), h('div.spacer')])]), h('div.page-content', [h('div.list', {
style: { opacity: '0', delayed: { opacity: '1' },
remove: { opacity: '0', position: 'absolute', top: '0', left: '0' } }
}, movies.map(function (movie) {
return h('div.row', {
on: { click: [select, movie] }
}, [h('div.hero.rank', [h('span.hero', { hero: { id: 'rank' + movie.rank } }, movie.rank)]), h('div.hero', { hero: { id: movie.title } }, movie.title)]);
}))])]);
};
var view = function view(data) {
return h('div.page-container', [data.selected ? detailView(data.selected) : overviewView(data.movies)]);
};
window.addEventListener('DOMContentLoaded', function () {
var container = document.getElementById('container');
vnode = patch(container, view(data));
render();
});
},{"../../h.js":2,"../../modules/class":4,"../../modules/eventlisteners":5,"../../modules/hero":6,"../../modules/style":7,"../../snabbdom.js":8}],2:[function(require,module,exports){
'use strict';
var VNode = require('./vnode');
var is = require('./is');
function addNS(data, children) {
data.ns = 'http://www.w3.org/2000/svg';
if (children !== undefined) {
for (var i = 0; i < children.length; ++i) {
addNS(children[i].data, children[i].children);
}
}
}
module.exports = function h(sel, b, c) {
var data = {},
children,
text,
i;
if (arguments.length === 3) {
data = b;
if (is.array(c)) {
children = c;
} else if (is.primitive(c)) {
text = c;
}
} else if (arguments.length === 2) {
if (is.array(b)) {
children = b;
} else if (is.primitive(b)) {
text = b;
} else {
data = b;
}
}
if (is.array(children)) {
for (i = 0; i < children.length; ++i) {
if (is.primitive(children[i])) children[i] = VNode(undefined, undefined, undefined, children[i]);
}
}
if (sel[0] === 's' && sel[1] === 'v' && sel[2] === 'g') {
addNS(data, children);
}
return VNode(sel, data, children, text, undefined);
};
},{"./is":3,"./vnode":9}],3:[function(require,module,exports){
'use strict';
module.exports = {
array: Array.isArray,
primitive: function primitive(s) {
return typeof s === 'string' || typeof s === 'number';
}
};
},{}],4:[function(require,module,exports){
'use strict';
function updateClass(oldVnode, vnode) {
var cur,
name,
elm = vnode.elm,
oldClass = oldVnode.data['class'] || {},
klass = vnode.data['class'] || {};
for (name in klass) {
cur = klass[name];
if (cur !== oldClass[name]) {
elm.classList[cur ? 'add' : 'remove'](name);
}
}
}
module.exports = { create: updateClass, update: updateClass };
},{}],5:[function(require,module,exports){
'use strict';
var is = require('../is');
function arrInvoker(arr) {
return function () {
// Special case when length is two, for performance
arr.length === 2 ? arr[0](arr[1]) : arr[0].apply(undefined, arr.slice(1));
};
}
function fnInvoker(o) {
return function (ev) {
o.fn(ev);
};
}
function updateEventListeners(oldVnode, vnode) {
var name,
cur,
old,
elm = vnode.elm,
oldOn = oldVnode.data.on || {},
on = vnode.data.on;
if (!on) return;
for (name in on) {
cur = on[name];
old = oldOn[name];
if (old === undefined) {
if (is.array(cur)) {
elm.addEventListener(name, arrInvoker(cur));
} else {
cur = { fn: cur };
on[name] = cur;
elm.addEventListener(name, fnInvoker(cur));
}
} else if (is.array(old)) {
// Deliberately modify old array since it's captured in closure created with `arrInvoker`
old.length = cur.length;
for (var i = 0; i < old.length; ++i) old[i] = cur[i];
on[name] = old;
} else {
old.fn = cur;
on[name] = old;
}
}
}
module.exports = { create: updateEventListeners, update: updateEventListeners };
},{"../is":3}],6:[function(require,module,exports){
'use strict';
var raf = window && window.requestAnimationFrame || setTimeout;
var nextFrame = function nextFrame(fn) {
raf(function () {
raf(fn);
});
};
function setNextFrame(obj, prop, val) {
nextFrame(function () {
obj[prop] = val;
});
}
function getTextNodeRect(textNode) {
var rect;
if (document.createRange) {
var range = document.createRange();
range.selectNodeContents(textNode);
if (range.getBoundingClientRect) {
rect = range.getBoundingClientRect();
}
}
return rect;
}
function calcTransformOrigin(isTextNode, textRect, boundingRect) {
if (isTextNode) {
if (textRect) {
//calculate pixels to center of text from left edge of bounding box
var relativeCenterX = textRect.left + textRect.width / 2 - boundingRect.left;
var relativeCenterY = textRect.top + textRect.height / 2 - boundingRect.top;
return relativeCenterX + 'px ' + relativeCenterY + 'px';
}
}
return '0 0'; //top left
}
function getTextDx(oldTextRect, newTextRect) {
if (oldTextRect && newTextRect) {
return oldTextRect.left + oldTextRect.width / 2 - (newTextRect.left + newTextRect.width / 2);
}
return 0;
}
function getTextDy(oldTextRect, newTextRect) {
if (oldTextRect && newTextRect) {
return oldTextRect.top + oldTextRect.height / 2 - (newTextRect.top + newTextRect.height / 2);
}
return 0;
}
function isTextElement(elm) {
return elm.childNodes.length === 1 && elm.childNodes[0].nodeType === 3;
}
var removed, created;
function pre(oldVnode, vnode) {
removed = {};
created = [];
}
function create(oldVnode, vnode) {
var hero = vnode.data.hero;
if (hero && hero.id) {
created.push(hero.id);
created.push(vnode);
}
}
function destroy(vnode) {
var hero = vnode.data.hero;
if (hero && hero.id) {
var elm = vnode.elm;
vnode.isTextNode = isTextElement(elm); //is this a text node?
vnode.boundingRect = elm.getBoundingClientRect(); //save the bounding rectangle to a new property on the vnode
vnode.textRect = vnode.isTextNode ? getTextNodeRect(elm.childNodes[0]) : null; //save bounding rect of inner text node
var computedStyle = window.getComputedStyle(elm, null); //get current styles (includes inherited properties)
vnode.savedStyle = JSON.parse(JSON.stringify(computedStyle)); //save a copy of computed style values
removed[hero.id] = vnode;
}
}
function post() {
var i, id, newElm, oldVnode, oldElm, hRatio, wRatio, oldRect, newRect, dx, dy, origTransform, origTransition, newStyle, oldStyle, newComputedStyle, isTextNode, newTextRect, oldTextRect;
for (i = 0; i < created.length; i += 2) {
id = created[i];
newElm = created[i + 1].elm;
oldVnode = removed[id];
if (oldVnode) {
isTextNode = oldVnode.isTextNode && isTextElement(newElm); //Are old & new both text?
newStyle = newElm.style;
newComputedStyle = window.getComputedStyle(newElm, null); //get full computed style for new element
oldElm = oldVnode.elm;
oldStyle = oldElm.style;
//Overall element bounding boxes
newRect = newElm.getBoundingClientRect();
oldRect = oldVnode.boundingRect; //previously saved bounding rect
//Text node bounding boxes & distances
if (isTextNode) {
newTextRect = getTextNodeRect(newElm.childNodes[0]);
oldTextRect = oldVnode.textRect;
dx = getTextDx(oldTextRect, newTextRect);
dy = getTextDy(oldTextRect, newTextRect);
} else {
//Calculate distances between old & new positions
dx = oldRect.left - newRect.left;
dy = oldRect.top - newRect.top;
}
hRatio = newRect.height / Math.max(oldRect.height, 1);
wRatio = isTextNode ? hRatio : newRect.width / Math.max(oldRect.width, 1); //text scales based on hRatio
// Animate new element
origTransform = newStyle.transform;
origTransition = newStyle.transition;
if (newComputedStyle.display === 'inline') //inline elements cannot be transformed
newStyle.display = 'inline-block'; //this does not appear to have any negative side effects
newStyle.transition = origTransition + 'transform 0s';
newStyle.transformOrigin = calcTransformOrigin(isTextNode, newTextRect, newRect);
newStyle.opacity = '0';
newStyle.transform = origTransform + 'translate(' + dx + 'px, ' + dy + 'px) ' + 'scale(' + 1 / wRatio + ', ' + 1 / hRatio + ')';
setNextFrame(newStyle, 'transition', origTransition);
setNextFrame(newStyle, 'transform', origTransform);
setNextFrame(newStyle, 'opacity', '1');
// Animate old element
for (var key in oldVnode.savedStyle) {
//re-apply saved inherited properties
if (parseInt(key) != key) {
var ms = key.substring(0, 2) === 'ms';
var moz = key.substring(0, 3) === 'moz';
var webkit = key.substring(0, 6) === 'webkit';
if (!ms && !moz && !webkit) //ignore prefixed style properties
oldStyle[key] = oldVnode.savedStyle[key];
}
}
oldStyle.position = 'absolute';
oldStyle.top = oldRect.top + 'px'; //start at existing position
oldStyle.left = oldRect.left + 'px';
oldStyle.width = oldRect.width + 'px'; //Needed for elements who were sized relative to their parents
oldStyle.height = oldRect.height + 'px'; //Needed for elements who were sized relative to their parents
oldStyle.margin = 0; //Margin on hero element leads to incorrect positioning
oldStyle.transformOrigin = calcTransformOrigin(isTextNode, oldTextRect, oldRect);
oldStyle.transform = '';
oldStyle.opacity = '1';
document.body.appendChild(oldElm);
setNextFrame(oldStyle, 'transform', 'translate(' + -dx + 'px, ' + -dy + 'px) scale(' + wRatio + ', ' + hRatio + ')'); //scale must be on far right for translate to be correct
setNextFrame(oldStyle, 'opacity', '0');
oldElm.addEventListener('transitionend', function (ev) {
if (ev.propertyName === 'transform') document.body.removeChild(ev.target);
});
}
}
removed = created = undefined;
}
module.exports = { pre: pre, create: create, destroy: destroy, post: post };
},{}],7:[function(require,module,exports){
'use strict';
var raf = requestAnimationFrame || setTimeout;
var nextFrame = function nextFrame(fn) {
raf(function () {
raf(fn);
});
};
function setNextFrame(obj, prop, val) {
nextFrame(function () {
obj[prop] = val;
});
}
function updateStyle(oldVnode, vnode) {
var cur,
name,
elm = vnode.elm,
oldStyle = oldVnode.data.style || {},
style = vnode.data.style || {},
oldHasDel = ('delayed' in oldStyle);
for (name in style) {
cur = style[name];
if (name === 'delayed') {
for (name in style.delayed) {
cur = style.delayed[name];
if (!oldHasDel || cur !== oldStyle.delayed[name]) {
setNextFrame(elm.style, name, cur);
}
}
} else if (name !== 'remove' && cur !== oldStyle[name]) {
elm.style[name] = cur;
}
}
}
function applyDestroyStyle(vnode) {
var style,
name,
elm = vnode.elm,
s = vnode.data.style;
if (!s || !(style = s.destroy)) return;
for (name in style) {
elm.style[name] = style[name];
}
}
function applyRemoveStyle(vnode, rm) {
var s = vnode.data.style;
if (!s || !s.remove) {
rm();
return;
}
var name,
elm = vnode.elm,
idx,
i = 0,
maxDur = 0,
compStyle,
style = s.remove,
amount = 0,
applied = [];
for (name in style) {
applied.push(name);
elm.style[name] = style[name];
}
compStyle = getComputedStyle(elm);
var props = compStyle['transition-property'].split(', ');
for (; i < props.length; ++i) {
if (applied.indexOf(props[i]) !== -1) amount++;
}
elm.addEventListener('transitionend', function (ev) {
if (ev.target === elm) --amount;
if (amount === 0) rm();
});
}
module.exports = { create: updateStyle, update: updateStyle, destroy: applyDestroyStyle, remove: applyRemoveStyle };
},{}],8:[function(require,module,exports){
// jshint newcap: false
/* global require, module, document, Element */
'use strict';
var VNode = require('./vnode');
var is = require('./is');
function isUndef(s) {
return s === undefined;
}
function isDef(s) {
return s !== undefined;
}
function emptyNodeAt(elm) {
return VNode(elm.tagName, {}, [], undefined, elm);
}
var emptyNode = VNode('', {}, [], undefined, undefined);
function sameVnode(vnode1, vnode2) {
return vnode1.key === vnode2.key && vnode1.sel === vnode2.sel;
}
function createKeyToOldIdx(children, beginIdx, endIdx) {
var i,
map = {},
key;
for (i = beginIdx; i <= endIdx; ++i) {
key = children[i].key;
if (isDef(key)) map[key] = i;
}
return map;
}
function createRmCb(childElm, listeners) {
return function () {
if (--listeners === 0) childElm.parentElement.removeChild(childElm);
};
}
var hooks = ['create', 'update', 'remove', 'destroy', 'pre', 'post'];
function init(modules) {
var i,
j,
cbs = {};
for (i = 0; i < hooks.length; ++i) {
cbs[hooks[i]] = [];
for (j = 0; j < modules.length; ++j) {
if (modules[j][hooks[i]] !== undefined) cbs[hooks[i]].push(modules[j][hooks[i]]);
}
}
function createElm(vnode, insertedVnodeQueue) {
var i,
data = vnode.data;
if (isDef(data)) {
if (isDef(i = data.hook) && isDef(i = i.init)) i(vnode);
if (isDef(i = data.vnode)) vnode = i;
}
var elm,
children = vnode.children,
sel = vnode.sel;
if (isDef(sel)) {
// Parse selector
var hashIdx = sel.indexOf('#');
var dotIdx = sel.indexOf('.', hashIdx);
var hash = hashIdx > 0 ? hashIdx : sel.length;
var dot = dotIdx > 0 ? dotIdx : sel.length;
var tag = hashIdx !== -1 || dotIdx !== -1 ? sel.slice(0, Math.min(hash, dot)) : sel;
elm = vnode.elm = isDef(data) && isDef(i = data.ns) ? document.createElementNS(i, tag) : document.createElement(tag);
if (hash < dot) elm.id = sel.slice(hash + 1, dot);
if (dotIdx > 0) elm.className = sel.slice(dot + 1).replace(/\./g, ' ');
if (is.array(children)) {
for (i = 0; i < children.length; ++i) {
elm.appendChild(createElm(children[i], insertedVnodeQueue));
}
} else if (is.primitive(vnode.text)) {
elm.appendChild(document.createTextNode(vnode.text));
}
for (i = 0; i < cbs.create.length; ++i) cbs.create[i](emptyNode, vnode);
i = vnode.data.hook; // Reuse variable
if (isDef(i)) {
if (i.create) i.create(emptyNode, vnode);
if (i.insert) insertedVnodeQueue.push(vnode);
}
} else {
elm = vnode.elm = document.createTextNode(vnode.text);
}
return vnode.elm;
}
function addVnodes(parentElm, before, vnodes, startIdx, endIdx, insertedVnodeQueue) {
for (; startIdx <= endIdx; ++startIdx) {
parentElm.insertBefore(createElm(vnodes[startIdx], insertedVnodeQueue), before);
}
}
function invokeDestroyHook(vnode) {
var i = vnode.data,
j;
if (isDef(i)) {
if (isDef(i = i.hook) && isDef(i = i.destroy)) i(vnode);
for (i = 0; i < cbs.destroy.length; ++i) cbs.destroy[i](vnode);
if (isDef(i = vnode.children)) {
for (j = 0; j < vnode.children.length; ++j) {
invokeDestroyHook(vnode.children[j]);
}
}
}
}
function removeVnodes(parentElm, vnodes, startIdx, endIdx) {
for (; startIdx <= endIdx; ++startIdx) {
var i,
listeners,
rm,
ch = vnodes[startIdx];
if (isDef(ch)) {
if (isDef(ch.sel)) {
invokeDestroyHook(ch);
listeners = cbs.remove.length + 1;
rm = createRmCb(ch.elm, listeners);
for (i = 0; i < cbs.remove.length; ++i) cbs.remove[i](ch, rm);
if (isDef(i = ch.data) && isDef(i = i.hook) && isDef(i = i.remove)) {
i(ch, rm);
} else {
rm();
}
} else {
// Text node
parentElm.removeChild(ch.elm);
}
}
}
}
function updateChildren(parentElm, oldCh, newCh, insertedVnodeQueue) {
var oldStartIdx = 0,
newStartIdx = 0;
var oldEndIdx = oldCh.length - 1;
var oldStartVnode = oldCh[0];
var oldEndVnode = oldCh[oldEndIdx];
var newEndIdx = newCh.length - 1;
var newStartVnode = newCh[0];
var newEndVnode = newCh[newEndIdx];
var oldKeyToIdx, idxInOld, elmToMove, before;
while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
if (isUndef(oldStartVnode)) {
oldStartVnode = oldCh[++oldStartIdx]; // Vnode has been moved left
} else if (isUndef(oldEndVnode)) {
oldEndVnode = oldCh[--oldEndIdx];
} else if (sameVnode(oldStartVnode, newStartVnode)) {
patchVnode(oldStartVnode, newStartVnode, insertedVnodeQueue);
oldStartVnode = oldCh[++oldStartIdx];
newStartVnode = newCh[++newStartIdx];
} else if (sameVnode(oldEndVnode, newEndVnode)) {
patchVnode(oldEndVnode, newEndVnode, insertedVnodeQueue);
oldEndVnode = oldCh[--oldEndIdx];
newEndVnode = newCh[--newEndIdx];
} else if (sameVnode(oldStartVnode, newEndVnode)) {
// Vnode moved right
patchVnode(oldStartVnode, newEndVnode, insertedVnodeQueue);
parentElm.insertBefore(oldStartVnode.elm, oldEndVnode.elm.nextSibling);
oldStartVnode = oldCh[++oldStartIdx];
newEndVnode = newCh[--newEndIdx];
} else if (sameVnode(oldEndVnode, newStartVnode)) {
// Vnode moved left
patchVnode(oldEndVnode, newStartVnode, insertedVnodeQueue);
parentElm.insertBefore(oldEndVnode.elm, oldStartVnode.elm);
oldEndVnode = oldCh[--oldEndIdx];
newStartVnode = newCh[++newStartIdx];
} else {
if (isUndef(oldKeyToIdx)) oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx);
idxInOld = oldKeyToIdx[newStartVnode.key];
if (isUndef(idxInOld)) {
// New element
parentElm.insertBefore(createElm(newStartVnode, insertedVnodeQueue), oldStartVnode.elm);
newStartVnode = newCh[++newStartIdx];
} else {
elmToMove = oldCh[idxInOld];
patchVnode(elmToMove, newStartVnode, insertedVnodeQueue);
oldCh[idxInOld] = undefined;
parentElm.insertBefore(elmToMove.elm, oldStartVnode.elm);
newStartVnode = newCh[++newStartIdx];
}
}
}
if (oldStartIdx > oldEndIdx) {
before = isUndef(newCh[newEndIdx + 1]) ? null : newCh[newEndIdx + 1].elm;
addVnodes(parentElm, before, newCh, newStartIdx, newEndIdx, insertedVnodeQueue);
} else if (newStartIdx > newEndIdx) {
removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx);
}
}
function patchVnode(oldVnode, vnode, insertedVnodeQueue) {
var i, hook;
if (isDef(i = vnode.data) && isDef(hook = i.hook) && isDef(i = hook.prepatch)) {
i(oldVnode, vnode);
}
if (isDef(i = oldVnode.data) && isDef(i = i.vnode)) oldVnode = i;
if (isDef(i = vnode.data) && isDef(i = i.vnode)) vnode = i;
var elm = vnode.elm = oldVnode.elm,
oldCh = oldVnode.children,
ch = vnode.children;
if (oldVnode === vnode) return;
if (isDef(vnode.data)) {
for (i = 0; i < cbs.update.length; ++i) cbs.update[i](oldVnode, vnode);
i = vnode.data.hook;
if (isDef(i) && isDef(i = i.update)) i(oldVnode, vnode);
}
if (isUndef(vnode.text)) {
if (isDef(oldCh) && isDef(ch)) {
if (oldCh !== ch) updateChildren(elm, oldCh, ch, insertedVnodeQueue);
} else if (isDef(ch)) {
addVnodes(elm, null, ch, 0, ch.length - 1, insertedVnodeQueue);
} else if (isDef(oldCh)) {
removeVnodes(elm, oldCh, 0, oldCh.length - 1);
}
} else if (oldVnode.text !== vnode.text) {
elm.textContent = vnode.text;
}
if (isDef(hook) && isDef(i = hook.postpatch)) {
i(oldVnode, vnode);
}
}
return function (oldVnode, vnode) {
var i;
var insertedVnodeQueue = [];
for (i = 0; i < cbs.pre.length; ++i) cbs.pre[i]();
if (oldVnode instanceof Element) {
if (oldVnode.parentElement !== null) {
createElm(vnode, insertedVnodeQueue);
oldVnode.parentElement.replaceChild(vnode.elm, oldVnode);
} else {
oldVnode = emptyNodeAt(oldVnode);
patchVnode(oldVnode, vnode, insertedVnodeQueue);
}
} else {
patchVnode(oldVnode, vnode, insertedVnodeQueue);
}
for (i = 0; i < insertedVnodeQueue.length; ++i) {
insertedVnodeQueue[i].data.hook.insert(insertedVnodeQueue[i]);
}
for (i = 0; i < cbs.post.length; ++i) cbs.post[i]();
return vnode;
};
}
module.exports = { init: init };
},{"./is":3,"./vnode":9}],9:[function(require,module,exports){
"use strict";
module.exports = function (sel, data, children, text, elm) {
var key = data === undefined ? undefined : data.key;
return { sel: sel, data: data, children: children,
text: text, elm: elm, key: key };
};
},{}]},{},[1]);
+166
View File
@@ -0,0 +1,166 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<title>Hero animation</title>
<script type="text/javascript" src="build.js"></script>
<style>
{
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
html, body {
height: 100%;
margin: 0;
}
body {
background: #fff;
font-family: sans-serif;
}
.page-container {
width: 100%;
position: relative;
background: #fff;
}
@media (min-width: 28em),
@media (min-height: 38em) {
body {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background: #aaaaaa;
position: relative;
}
.page-container {
box-shadow: 0 0 1em rgba(0, 0, 0, .5);
width: 28em;
min-height: 38em;
height: 38em;
}
}
.page {
background: #fff;
transition: opacity 0.4s ease-in-out,
transform 0.4s ease-in-out;
width: 100%;
height: 100%;
}
h2 {
font-size: 1.1em;
margin: .2em 0;
}
.header {
height: 3.5em;
background: #1293ea;
overflow: hidden;
}
.header-content {
width: 100%;
box-sizing: border-box;
padding: .4em .8em;
color: #fff;
display: flex;
align-items: center;
position: absolute;
transition: opacity 0.4s ease-in-out,
transform 0.4s ease-in-out;
}
.header h1 {
font-weight: normal;
margin: 0;
font-size: 1.5em;
line-height: 1.8em;
}
.header-title {
color: #fff;
font-size: 1.5em;
line-height: 1.8em;
transition: transform 0.4s ease-in-out;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.header .rank {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 2.7em;
height: 2.7em;
margin-right: .5em;
position: relative;
}
.header .rank-circle {
position: absolute;
background: #fff;
width: 2.7em;
height: 2.7em;
border-radius: 1.35em;
margin-right: .5em;
transition: transform 0.4s ease-in-out;
top: 0;
left: 0;
}
.header-rank {
z-index: 2;
color: #1293ea;
font-size: 1.5em;
}
.header .close {
line-height: 1.8em;
cursor: pointer;
text-align: center;
width: 1.8em;
height: 1.8em;
border-radius: .9em;
background: rgba(0, 0, 0, .5);
transition: transform 0.4s ease-in-out;
}
.hero {
transition: transform 0.4s ease-in-out,
opacity 0.4s ease-in-out;
}
.page-content {
position: relative;
overflow: hidden;
width: 100%;
height: calc(100% - 3.5em);
}
.list {
position: absolute;
width: 100%;
transition: transform 0.4s ease-in-out,
opacity 0.4s ease-in-out;
}
.desc {
position: absolute;
transition: transform 0.4s ease-in-out,
opacity 0.4s ease-in-out;
padding: 1em;
}
.spacer {
flex: 1;
}
.row {
cursor: pointer;
box-sizing: border-box;
padding: 1em;
}
.row:not(:first-child) {
border-top: 1px solid #eeeeee;
}
.row div {
display: inline-block;
}
.row > div:nth-child(1) {
text-align: center;
margin-right: 1em;
width: 1em;
}
</style>
</head>
<body>
<div id="container"></div>
</body>
</html>
+120
View File
@@ -0,0 +1,120 @@
/* jshint esnext: true */
var snabbdom = require('../../snabbdom.js');
var patch = snabbdom.init([
require('../../modules/class').default,
require('../../modules/hero').default,
require('../../modules/style').default,
require('../../modules/eventlisteners').default,
]);
var h = require('../../h.js').default;
var vnode;
var data = {
selected: undefined,
movies: [
{rank: 1, title: 'This is an', desc: 'Lorem ipsum dolor sit amet, sed pede integer vitae bibendum, accumsan sit, vulputate aenean tempora ipsum. Lorem sed id et metus, eros posuere suspendisse nec nunc justo, fusce augue placerat nibh purus suspendisse. Aliquam aliquam, ut eget. Mollis a eget sed nibh tincidunt nec, mi integer, proin magna lacus iaculis tortor. Aliquam vel arcu arcu, vivamus a urna fames felis vel wisi, cursus tortor nec erat dignissim cras sem, mauris ac venenatis tellus elit.'},
{rank: 2, title: 'example of', desc: 'Consequuntur ipsum nulla, consequat curabitur in magnis risus. Taciti mattis bibendum tellus nibh, at dui neque eget, odio pede ut, sapien pede, ipsum ut. Sagittis dui, sodales sem, praesent ipsum conubia eget lorem lobortis wisi.'},
{rank: 3, title: 'Snabbdom', desc: 'Quam lorem aliquam fusce wisi, urna purus ipsum pharetra sed, at cras sodales enim vestibulum odio cras, luctus integer phasellus.'},
{rank: 4, title: 'doing hero transitions', desc: 'Et orci hac ultrices id in. Diam ultrices luctus egestas, sem aliquam auctor molestie odio laoreet. Pede nam cubilia, diam vestibulum ornare natoque, aenean etiam fusce id, eget dictum blandit et mauris mauris. Metus amet ad, elit porttitor a aliquet commodo lacus, integer neque imperdiet augue laoreet, nonummy turpis lacus sed pulvinar condimentum platea. Wisi eleifend quis, tristique dictum, ac dictumst. Sem nec tristique vel vehicula fringilla, nibh eu et posuere mi rhoncus.'},
{rank: 5, title: 'using the', desc: 'Pede nam cubilia, diam vestibulum ornare natoque, aenean etiam fusce id, eget dictum blandit et mauris mauris. Metus amet ad, elit porttitor a aliquet commodo lacus, integer neque imperdiet augue laoreet, nonummy turpis lacus sed pulvinar condimentum platea. Wisi eleifend quis, tristique dictum, ac dictumst. Sem nec tristique vel vehicula fringilla, nibh eu et posuere mi rhoncus.'},
{rank: 6, title: 'module for hero transitions', desc: 'Sapien laoreet, ligula elit tortor nulla pellentesque, maecenas enim turpis, quae duis venenatis vivamus ultricies, nunc imperdiet sollicitudin ipsum malesuada. Ut sem. Wisi fusce nullam nibh enim. Nisl hymenaeos id sed sed in. Proin leo et, pulvinar nunc pede laoreet.'},
{rank: 7, title: 'click on ar element in', desc: 'Accumsan quia, id nascetur dui et congue erat, id excepteur, primis ratione nec. At nulla et. Suspendisse lobortis, lobortis in tortor fringilla, duis adipiscing vestibulum voluptates sociosqu auctor.'},
{rank: 8, title: 'the list', desc: 'Ante tellus egestas vel hymenaeos, ut viverra nibh ut, ipsum nibh donec donec dolor. Eros ridiculus vel egestas convallis ipsum, commodo ut venenatis nullam porta iaculis, suspendisse ante proin leo, felis risus etiam.'},
{rank: 9, title: 'to witness', desc: 'Metus amet ad, elit porttitor a aliquet commodo lacus, integer neque imperdiet augue laoreet, nonummy turpis lacus sed pulvinar condimentum platea. Wisi eleifend quis, tristique dictum, ac dictumst.'},
{rank: 10, title: 'the effect', desc: 'Et orci hac ultrices id in. Diam ultrices luctus egestas, sem aliquam auctor molestie odio laoreet. Pede nam cubilia, diam vestibulum ornare natoque, aenean etiam fusce id, eget dictum blandit et mauris mauris'},
]
};
function select(m) {
data.selected = m;
render();
}
function render() {
vnode = patch(vnode, view(data));
}
const fadeInOutStyle = {
opacity: '0', delayed: {opacity: '1'}, remove: {opacity: '0'}
};
const detailView = (movie) =>
h('div.page', {style: fadeInOutStyle}, [
h('div.header', [
h('div.header-content.detail', {
style: {opacity: '1', remove: {opacity: '0'}},
}, [
h('div.rank', [
h('span.header-rank.hero', {hero: {id: 'rank'+movie.rank}}, movie.rank),
h('div.rank-circle', {
style: {transform: 'scale(0)',
delayed: {transform: 'scale(1)'},
destroy: {transform: 'scale(0)'}},
}),
]),
h('div.hero.header-title', {hero: {id: movie.title}}, movie.title),
h('div.spacer'),
h('div.close', {
on: {click: [select, undefined]},
style: {transform: 'scale(0)',
delayed: {transform: 'scale(1)'},
destroy: {transform: 'scale(0)'}},
}, 'x'),
]),
]),
h('div.page-content', [
h('div.desc', {
style: {opacity: '0', transform: 'translateX(3em)',
delayed: {opacity: '1', transform: 'translate(0)'},
remove: {opacity: '0', position: 'absolute', top: '0', left: '0',
transform: 'translateX(3em)'}
}
}, [
h('h2', 'Description:'),
h('span', movie.desc),
]),
]),
]);
const overviewView = (movies) =>
h('div.page', {style: fadeInOutStyle}, [
h('div.header', [
h('div.header-content.overview', {
style: fadeInOutStyle,
}, [
h('div.header-title', {
style: {transform: 'translateY(-2em)',
delayed: {transform: 'translate(0)'},
destroy: {transform: 'translateY(-2em)'}}
}, 'Top 10 movies'),
h('div.spacer'),
]),
]),
h('div.page-content', [
h('div.list', {
style: {opacity: '0', delayed: {opacity: '1'},
remove: {opacity: '0', position: 'absolute', top: '0', left: '0'}}
}, movies.map((movie) =>
h('div.row', {
on: {click: [select, movie]},
}, [
h('div.hero.rank', [
h('span.hero', {hero: {id: 'rank'+movie.rank}}, movie.rank)
]),
h('div.hero', {hero: {id: movie.title}}, movie.title)
])
)),
]),
]);
const view = (data) =>
h('div.page-container', [
data.selected ? detailView(data.selected) : overviewView(data.movies),
]);
window.addEventListener('DOMContentLoaded', () => {
var container = document.getElementById('container');
vnode = patch(container, view(data));
render();
});
+523
View File
@@ -0,0 +1,523 @@
(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){
'use strict';
var snabbdom = require('../../snabbdom.js');
var patch = snabbdom.init([require('../../modules/class'), require('../../modules/props'), require('../../modules/style'), require('../../modules/eventlisteners')]);
var h = require('../../h.js');
var vnode;
var nextKey = 11;
var margin = 8;
var sortBy = 'rank';
var totalHeight = 0;
var 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 }];
var data = [originalData[0], originalData[1], originalData[2], originalData[3], originalData[4], originalData[5], originalData[6], originalData[7], originalData[8], originalData[9]];
function changeSort(prop) {
sortBy = prop;
data.sort(function (a, b) {
if (a[prop] > b[prop]) {
return 1;
}
if (a[prop] < b[prop]) {
return -1;
}
return 0;
});
render();
}
function add() {
var n = originalData[Math.floor(Math.random() * 10)];
data = [{ rank: nextKey++, title: n.title, desc: n.desc, elmHeight: 0 }].concat(data);
render();
render();
}
function remove(movie) {
data = data.filter(function (m) {
return m !== movie;
});
render();
}
function movieView(movie) {
return h('div.row', {
key: movie.rank,
style: { opacity: '0', transform: 'translate(-200px)',
delayed: { transform: 'translateY(' + movie.offset + 'px)', opacity: '1' },
remove: { opacity: '0', transform: 'translateY(' + movie.offset + 'px) translateX(200px)' } },
hook: { insert: function insert(vnode) {
movie.elmHeight = vnode.elm.offsetHeight;
} } }, [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')]);
}
function render() {
data = data.reduce(function (acc, m) {
var last = acc[acc.length - 1];
m.offset = last ? last.offset + last.elmHeight + margin : margin;
return acc.concat(m);
}, []);
totalHeight = data[data.length - 1].offset + data[data.length - 1].elmHeight;
vnode = patch(vnode, view(data));
}
function view(data) {
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))]);
}
window.addEventListener('DOMContentLoaded', function () {
var container = document.getElementById('container');
vnode = patch(container, view(data));
render();
});
},{"../../h.js":2,"../../modules/class":4,"../../modules/eventlisteners":5,"../../modules/props":6,"../../modules/style":7,"../../snabbdom.js":8}],2:[function(require,module,exports){
'use strict';
var VNode = require('./vnode');
var is = require('./is');
module.exports = function h(sel, b, c) {
var data = {},
children,
text,
i;
if (arguments.length === 3) {
data = b;
if (is.array(c)) {
children = c;
} else if (is.primitive(c)) {
text = c;
}
} else if (arguments.length === 2) {
if (is.array(b)) {
children = b;
} else if (is.primitive(b)) {
text = b;
} else {
data = b;
}
}
if (is.array(children)) {
for (i = 0; i < children.length; ++i) {
if (is.primitive(children[i])) children[i] = VNode(undefined, undefined, undefined, children[i]);
}
}
return VNode(sel, data, children, text, undefined);
};
},{"./is":3,"./vnode":9}],3:[function(require,module,exports){
'use strict';
module.exports = {
array: Array.isArray,
primitive: function primitive(s) {
return typeof s === 'string' || typeof s === 'number';
} };
},{}],4:[function(require,module,exports){
'use strict';
function updateClass(oldVnode, vnode) {
var cur,
name,
elm = vnode.elm,
oldClass = oldVnode.data['class'] || {},
klass = vnode.data['class'] || {};
for (name in klass) {
cur = klass[name];
if (cur !== oldClass[name]) {
elm.classList[cur ? 'add' : 'remove'](name);
}
}
}
module.exports = { create: updateClass, update: updateClass };
},{}],5:[function(require,module,exports){
'use strict';
var is = require('../is');
function arrInvoker(arr) {
return function () {
arr[0](arr[1]);
};
}
function updateEventListeners(oldVnode, vnode) {
var name,
cur,
old,
elm = vnode.elm,
oldOn = oldVnode.data.on || {},
on = vnode.data.on;
if (!on) return;
for (name in on) {
cur = on[name];
old = oldOn[name];
if (old === undefined) {
elm.addEventListener(name, is.array(cur) ? arrInvoker(cur) : cur);
} else if (is.array(old)) {
old[0] = cur[0]; // Deliberately modify old array since it's
old[1] = cur[1]; // captured in closure created with `arrInvoker`
}
}
}
module.exports = { create: updateEventListeners, update: updateEventListeners };
},{"../is":3}],6:[function(require,module,exports){
"use strict";
function updateProps(oldVnode, vnode) {
var key,
cur,
old,
elm = vnode.elm,
oldProps = oldVnode.data.props || {},
props = vnode.data.props || {};
for (key in props) {
cur = props[key];
old = oldProps[key];
if (old !== cur) {
elm[key] = cur;
}
}
}
module.exports = { create: updateProps, update: updateProps };
},{}],7:[function(require,module,exports){
'use strict';
var raf = requestAnimationFrame || setTimeout;
var nextFrame = function nextFrame(fn) {
raf(function () {
raf(fn);
});
};
function setNextFrame(obj, prop, val) {
nextFrame(function () {
obj[prop] = val;
});
}
function updateStyle(oldVnode, vnode) {
var cur,
name,
elm = vnode.elm,
oldStyle = oldVnode.data.style || {},
style = vnode.data.style || {},
oldHasDel = ('delayed' in oldStyle);
for (name in style) {
cur = style[name];
if (name === 'delayed') {
for (name in style.delayed) {
cur = style.delayed[name];
if (!oldHasDel || cur !== oldStyle.delayed[name]) {
setNextFrame(elm.style, name, cur);
}
}
} else if (name !== 'remove' && cur !== oldStyle[name]) {
elm.style[name] = cur;
}
}
}
function applyDestroyStyle(vnode) {
var style,
name,
elm = vnode.elm,
s = vnode.data.style;
if (!s || !(style = s.destroy)) return;
for (name in style) {
elm.style[name] = style[name];
}
}
function applyRemoveStyle(vnode, rm) {
var s = vnode.data.style;
if (!s || !s.remove) {
rm();
return;
}
var name,
elm = vnode.elm,
idx,
i = 0,
maxDur = 0,
compStyle,
style = s.remove,
amount = 0;
var applied = [];
for (name in style) {
applied.push(name);
elm.style[name] = style[name];
}
compStyle = getComputedStyle(elm);
var props = compStyle['transition-property'].split(', ');
for (; i < props.length; ++i) {
if (applied.indexOf(props[i]) !== -1) amount++;
}
elm.addEventListener('transitionend', function (ev) {
if (ev.target === elm) --amount;
if (amount === 0) rm();
});
}
module.exports = { create: updateStyle, update: updateStyle, destroy: applyDestroyStyle, remove: applyRemoveStyle };
},{}],8:[function(require,module,exports){
// jshint newcap: false
'use strict';
var VNode = require('./vnode');
var is = require('./is');
function isUndef(s) {
return s === undefined;
}
function emptyNodeAt(elm) {
return VNode(elm.tagName, {}, [], undefined, elm);
}
var emptyNode = VNode('', {}, [], undefined, undefined);
var insertedVnodeQueue;
function sameVnode(vnode1, vnode2) {
return vnode1.key === vnode2.key && vnode1.sel === vnode2.sel;
}
function createKeyToOldIdx(children, beginIdx, endIdx) {
var i,
map = {},
key;
for (i = beginIdx; i <= endIdx; ++i) {
key = children[i].key;
if (!isUndef(key)) map[key] = i;
}
return map;
}
function createRmCb(parentElm, childElm, listeners) {
return function () {
if (--listeners === 0) parentElm.removeChild(childElm);
};
}
var hooks = ['create', 'update', 'remove', 'destroy', 'pre', 'post'];
function init(modules) {
var i,
j,
cbs = {};
for (i = 0; i < hooks.length; ++i) {
cbs[hooks[i]] = [];
for (j = 0; j < modules.length; ++j) {
if (modules[j][hooks[i]] !== undefined) cbs[hooks[i]].push(modules[j][hooks[i]]);
}
}
function createElm(vnode) {
var i;
if (!isUndef(i = vnode.data) && !isUndef(i = i.hook) && !isUndef(i = i.init)) {
i(vnode);
}
if (!isUndef(i = vnode.data) && !isUndef(i = i.vnode)) vnode = i;
var elm,
children = vnode.children,
sel = vnode.sel;
if (!isUndef(sel)) {
// Parse selector
var hashIdx = sel.indexOf('#');
var dotIdx = sel.indexOf('.', hashIdx);
var hash = hashIdx > 0 ? hashIdx : sel.length;
var dot = dotIdx > 0 ? dotIdx : sel.length;
var tag = hashIdx !== -1 || dotIdx !== -1 ? sel.slice(0, Math.min(hash, dot)) : sel;
elm = vnode.elm = document.createElement(tag);
if (hash < dot) elm.id = sel.slice(hash + 1, dot);
if (dotIdx > 0) elm.className = sel.slice(dot + 1).replace(/\./g, ' ');
if (is.array(children)) {
for (i = 0; i < children.length; ++i) {
elm.appendChild(createElm(children[i]));
}
} else if (is.primitive(vnode.text)) {
elm.appendChild(document.createTextNode(vnode.text));
}
for (i = 0; i < cbs.create.length; ++i) cbs.create[i](emptyNode, vnode);
i = vnode.data.hook; // Reuse variable
if (!isUndef(i)) {
if (i.create) i.create(vnode);
if (i.insert) insertedVnodeQueue.push(vnode);
}
} else {
elm = vnode.elm = document.createTextNode(vnode.text);
}
return elm;
}
function addVnodes(parentElm, before, vnodes, startIdx, endIdx) {
if (isUndef(before)) {
for (; startIdx <= endIdx; ++startIdx) {
parentElm.appendChild(createElm(vnodes[startIdx]));
}
} else {
var elm = before.elm;
for (; startIdx <= endIdx; ++startIdx) {
parentElm.insertBefore(createElm(vnodes[startIdx]), elm);
}
}
}
function invokeDestroyHook(vnode) {
var i = vnode.data.hook,
j;
if (!isUndef(i) && !isUndef(j = i.destroy)) j(vnode);
for (i = 0; i < cbs.destroy.length; ++i) cbs.destroy[i](vnode);
if (!isUndef(vnode.children)) {
for (j = 0; j < vnode.children.length; ++j) {
invokeDestroyHook(vnode.children[j]);
}
}
}
function removeVnodes(parentElm, vnodes, startIdx, endIdx) {
for (; startIdx <= endIdx; ++startIdx) {
var i,
listeners,
rm,
ch = vnodes[startIdx];
if (!isUndef(ch)) {
listeners = cbs.remove.length + 1;
rm = createRmCb(parentElm, ch.elm, listeners);
for (i = 0; i < cbs.remove.length; ++i) cbs.remove[i](ch, rm);
invokeDestroyHook(ch);
if (ch.data.hook && ch.data.hook.remove) {
ch.data.hook.remove(ch, rm);
} else {
rm();
}
}
}
}
function updateChildren(parentElm, oldCh, newCh) {
var oldStartIdx = 0,
newStartIdx = 0;
var oldEndIdx = oldCh.length - 1;
var oldStartVnode = oldCh[0];
var oldEndVnode = oldCh[oldEndIdx];
var newEndIdx = newCh.length - 1;
var newStartVnode = newCh[0];
var newEndVnode = newCh[newEndIdx];
var oldKeyToIdx, idxInOld, elmToMove;
while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
if (isUndef(oldStartVnode)) {
oldStartVnode = oldCh[++oldStartIdx]; // Vnode has been moved left
} else if (isUndef(oldEndVnode)) {
oldEndVnode = oldCh[--oldEndIdx];
} else if (sameVnode(oldStartVnode, newStartVnode)) {
patchVnode(oldStartVnode, newStartVnode);
oldStartVnode = oldCh[++oldStartIdx];
newStartVnode = newCh[++newStartIdx];
} else if (sameVnode(oldEndVnode, newEndVnode)) {
patchVnode(oldEndVnode, newEndVnode);
oldEndVnode = oldCh[--oldEndIdx];
newEndVnode = newCh[--newEndIdx];
} else if (sameVnode(oldStartVnode, newEndVnode)) {
// Vnode moved right
patchVnode(oldStartVnode, newEndVnode);
parentElm.insertBefore(oldStartVnode.elm, oldEndVnode.elm.nextSibling);
oldStartVnode = oldCh[++oldStartIdx];
newEndVnode = newCh[--newEndIdx];
} else if (sameVnode(oldEndVnode, newStartVnode)) {
// Vnode moved left
patchVnode(oldEndVnode, newStartVnode);
parentElm.insertBefore(oldEndVnode.elm, oldStartVnode.elm);
oldEndVnode = oldCh[--oldEndIdx];
newStartVnode = newCh[++newStartIdx];
} else {
if (isUndef(oldKeyToIdx)) oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx);
idxInOld = oldKeyToIdx[newStartVnode.key];
if (isUndef(idxInOld)) {
// New element
parentElm.insertBefore(createElm(newStartVnode), oldStartVnode.elm);
newStartVnode = newCh[++newStartIdx];
} else {
elmToMove = oldCh[idxInOld];
patchVnode(elmToMove, newStartVnode);
oldCh[idxInOld] = undefined;
parentElm.insertBefore(elmToMove.elm, oldStartVnode.elm);
newStartVnode = newCh[++newStartIdx];
}
}
}
if (oldStartIdx > oldEndIdx) addVnodes(parentElm, oldStartVnode, newCh, newStartIdx, newEndIdx);else if (newStartIdx > newEndIdx) removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx);
}
function patchVnode(oldVnode, vnode) {
var i;
if (!isUndef(i = vnode.data) && !isUndef(i = i.hook) && !isUndef(i = i.patch)) {
i = i(oldVnode, vnode);
}
if (!isUndef(i = oldVnode.data) && !isUndef(i = i.vnode)) oldVnode = i;
if (!isUndef(i = vnode.data) && !isUndef(i = i.vnode)) vnode = i;
var elm = vnode.elm = oldVnode.elm,
oldCh = oldVnode.children,
ch = vnode.children;
if (oldVnode === vnode) return;
if (!isUndef(vnode.data)) {
for (i = 0; i < cbs.update.length; ++i) cbs.update[i](oldVnode, vnode);
i = vnode.data.hook;
if (!isUndef(i) && !isUndef(i = i.update)) i(vnode);
}
if (isUndef(vnode.text)) {
if (!isUndef(oldCh) && !isUndef(ch)) {
if (oldCh !== ch) updateChildren(elm, oldCh, ch);
} else if (!isUndef(ch)) {
addVnodes(elm, undefined, ch, 0, ch.length - 1);
} else if (!isUndef(oldCh)) {
removeVnodes(elm, oldCh, 0, oldCh.length - 1);
}
} else if (oldVnode.text !== vnode.text) {
elm.childNodes[0].nodeValue = vnode.text;
}
return vnode;
}
return function (oldVnode, vnode) {
var i;
insertedVnodeQueue = [];
if (oldVnode instanceof Element) {
oldVnode = emptyNodeAt(oldVnode);
}
for (i = 0; i < cbs.pre.length; ++i) cbs.pre[i]();
patchVnode(oldVnode, vnode);
for (i = 0; i < insertedVnodeQueue.length; ++i) {
insertedVnodeQueue[i].data.hook.insert(insertedVnodeQueue[i]);
}
insertedVnodeQueue = undefined;
for (i = 0; i < cbs.post.length; ++i) cbs.post[i]();
return vnode;
};
}
module.exports = { init: init };
},{"./is":3,"./vnode":9}],9:[function(require,module,exports){
"use strict";
module.exports = function (sel, data, children, text, elm) {
var key = data === undefined ? undefined : data.key;
return { sel: sel, data: data, children: children,
text: text, elm: elm, key: key };
};
},{}]},{},[1]);
+84
View File
@@ -0,0 +1,84 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Reorder animation</title>
<script type="text/javascript" src="build.js"></script>
<style>
body {
background: #fafafa;
font-family: sans-serif;
}
h1 {
font-weight: normal;
}
.btn {
display: inline-block;
cursor: pointer;
background: #fff;
box-shadow: 0 0 1px rgba(0, 0, 0, .2);
padding: .5em .8em;
transition: box-shadow .05s ease-in-out;
-webkit-transition: box-shadow .05s ease-in-out;
}
.btn:hover {
box-shadow: 0 0 2px rgba(0, 0, 0, .2);
}
.btn:active, .active, .active:hover {
box-shadow: 0 0 1px rgba(0, 0, 0, .2),
inset 0 0 4px rgba(0, 0, 0, .1);
}
.add {
float: right;
}
#container {
max-width: 42em;
margin: 0 auto 2em auto;
}
.list {
position: relative;
}
.row {
overflow: hidden;
position: absolute;
box-sizing: border-box;
width: 100%;
left: 0px;
margin: .5em 0;
padding: 1em;
background: #fff;
box-shadow: 0 0 1px rgba(0, 0, 0, .2);
transition: transform .5s ease-in-out, opacity .5s ease-out, left .5s ease-in-out;
-webkit-transition: transform .5s ease-in-out, opacity .5s ease-out, left .5s ease-in-out;
}
.row div {
display: inline-block;
vertical-align: middle;
}
.row > div:nth-child(1) {
width: 5%;
}
.row > div:nth-child(2) {
width: 30%;
}
.row > div:nth-child(3) {
width: 65%;
}
.rm-btn {
cursor: pointer;
position: absolute;
top: 0;
right: 0;
color: #C25151;
width: 1.4em;
height: 1.4em;
text-align: center;
line-height: 1.4em;
padding: 0;
}
</style>
</head>
<body>
<div id="container"></div>
</body>
</html>
+112
View File
@@ -0,0 +1,112 @@
var snabbdom = require('../../snabbdom.js');
var patch = snabbdom.init([
require('../../modules/class').default,
require('../../modules/props').default,
require('../../modules/style').default,
require('../../modules/eventlisteners').default,
]);
var h = require('../../h.js').default;
var vnode;
var nextKey = 11;
var margin = 8;
var sortBy = 'rank';
var totalHeight = 0;
var 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},
];
var data = [
originalData[0],
originalData[1],
originalData[2],
originalData[3],
originalData[4],
originalData[5],
originalData[6],
originalData[7],
originalData[8],
originalData[9],
];
function changeSort(prop) {
sortBy = prop;
data.sort((a, b) => {
if (a[prop] > b[prop]) {
return 1;
}
if (a[prop] < b[prop]) {
return -1;
}
return 0;
});
render();
}
function add() {
var n = originalData[Math.floor(Math.random() * 10)];
data = [{rank: nextKey++, title: n.title, desc: n.desc, elmHeight: 0}].concat(data);
render();
render();
}
function remove(movie) {
data = data.filter((m) => { return m !== movie; });
render();
}
function movieView(movie) {
return h('div.row', {
key: movie.rank,
style: {opacity: '0', transform: 'translate(-200px)',
delayed: {transform: `translateY(${movie.offset}px)`, opacity: '1'},
remove: {opacity: '0', transform: `translateY(${movie.offset}px) translateX(200px)`}},
hook: {insert: (vnode) => { movie.elmHeight = vnode.elm.offsetHeight; }},
}, [
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'),
]);
}
function render() {
data = data.reduce((acc, m) => {
var last = acc[acc.length - 1];
m.offset = last ? last.offset + last.elmHeight + margin : margin;
return acc.concat(m);
}, []);
totalHeight = data[data.length - 1].offset + data[data.length - 1].elmHeight;
vnode = patch(vnode, view(data));
}
function view(data) {
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)),
]);
}
window.addEventListener('DOMContentLoaded', () => {
var container = document.getElementById('container');
vnode = patch(container, view(data));
render();
});
+376
View File
@@ -0,0 +1,376 @@
(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){
'use strict';
var snabbdom = require('../../snabbdom.js');
var patch = snabbdom.init([require('../../modules/attributes')]);
var h = require('../../h.js');
var vnode;
window.addEventListener('DOMContentLoaded', function () {
var container = document.getElementById('container');
var vnode = h('div', [h('svg', { attrs: { width: 100, height: 100 } }, [h('circle', { attrs: { cx: 50, cy: 50, r: 40, stroke: 'green', 'stroke-width': 4, fill: 'yellow' } })])]);
vnode = patch(container, vnode);
});
},{"../../h.js":2,"../../modules/attributes":4,"../../snabbdom.js":5}],2:[function(require,module,exports){
'use strict';
var VNode = require('./vnode');
var is = require('./is');
function addNS(data, children) {
data.ns = 'http://www.w3.org/2000/svg';
if (children !== undefined) {
for (var i = 0; i < children.length; ++i) {
addNS(children[i].data, children[i].children);
}
}
}
module.exports = function h(sel, b, c) {
var data = {},
children,
text,
i;
if (arguments.length === 3) {
data = b;
if (is.array(c)) {
children = c;
} else if (is.primitive(c)) {
text = c;
}
} else if (arguments.length === 2) {
if (is.array(b)) {
children = b;
} else if (is.primitive(b)) {
text = b;
} else {
data = b;
}
}
if (is.array(children)) {
for (i = 0; i < children.length; ++i) {
if (is.primitive(children[i])) children[i] = VNode(undefined, undefined, undefined, children[i]);
}
}
if (sel[0] === 's' && sel[1] === 'v' && sel[2] === 'g') {
addNS(data, children);
}
return VNode(sel, data, children, text, undefined);
};
},{"./is":3,"./vnode":6}],3:[function(require,module,exports){
'use strict';
module.exports = {
array: Array.isArray,
primitive: function primitive(s) {
return typeof s === 'string' || typeof s === 'number';
} };
},{}],4:[function(require,module,exports){
"use strict";
var booleanAttrs = ["allowfullscreen", "async", "autofocus", "autoplay", "checked", "compact", "controls", "declare", "default", "defaultchecked", "defaultmuted", "defaultselected", "defer", "disabled", "draggable", "enabled", "formnovalidate", "hidden", "indeterminate", "inert", "ismap", "itemscope", "loop", "multiple", "muted", "nohref", "noresize", "noshade", "novalidate", "nowrap", "open", "pauseonexit", "readonly", "required", "reversed", "scoped", "seamless", "selected", "sortable", "spellcheck", "translate", "truespeed", "typemustmatch", "visible"];
var booleanAttrsDict = {};
for (var i = 0, len = booleanAttrs.length; i < len; i++) {
booleanAttrsDict[booleanAttrs[i]] = true;
}
function updateAttrs(oldVnode, vnode) {
var key,
cur,
old,
elm = vnode.elm,
oldAttrs = oldVnode.data.attrs || {},
attrs = vnode.data.attrs || {};
// update modified attributes, add new attributes
for (key in attrs) {
cur = attrs[key];
old = oldAttrs[key];
if (old !== cur) {
// TODO: add support to namespaced attributes (setAttributeNS)
if (!cur && booleanAttrsDict[key]) elm.removeAttribute(key);else elm.setAttribute(key, cur);
}
}
//remove removed attributes
// use `in` operator since the previous `for` iteration uses it (.i.e. add even attributes with undefined value)
// the other option is to remove all attributes with value == undefined
for (key in oldAttrs) {
if (!(key in attrs)) {
elm.removeAttribute(key);
}
}
}
module.exports = { create: updateAttrs, update: updateAttrs };
},{}],5:[function(require,module,exports){
// jshint newcap: false
/* global require, module, document, Element */
'use strict';
var VNode = require('./vnode');
var is = require('./is');
function isUndef(s) {
return s === undefined;
}
function isDef(s) {
return s !== undefined;
}
function emptyNodeAt(elm) {
return VNode(elm.tagName, {}, [], undefined, elm);
}
var emptyNode = VNode('', {}, [], undefined, undefined);
function sameVnode(vnode1, vnode2) {
return vnode1.key === vnode2.key && vnode1.sel === vnode2.sel;
}
function createKeyToOldIdx(children, beginIdx, endIdx) {
var i,
map = {},
key;
for (i = beginIdx; i <= endIdx; ++i) {
key = children[i].key;
if (isDef(key)) map[key] = i;
}
return map;
}
function createRmCb(childElm, listeners) {
return function () {
if (--listeners === 0) childElm.parentElement.removeChild(childElm);
};
}
var hooks = ['create', 'update', 'remove', 'destroy', 'pre', 'post'];
function init(modules) {
var i,
j,
cbs = {};
for (i = 0; i < hooks.length; ++i) {
cbs[hooks[i]] = [];
for (j = 0; j < modules.length; ++j) {
if (modules[j][hooks[i]] !== undefined) cbs[hooks[i]].push(modules[j][hooks[i]]);
}
}
function createElm(vnode, insertedVnodeQueue) {
var i,
data = vnode.data;
if (isDef(data)) {
if (isDef(i = data.hook) && isDef(i = i.init)) i(vnode);
if (isDef(i = data.vnode)) vnode = i;
}
var elm,
children = vnode.children,
sel = vnode.sel;
if (isDef(sel)) {
// Parse selector
var hashIdx = sel.indexOf('#');
var dotIdx = sel.indexOf('.', hashIdx);
var hash = hashIdx > 0 ? hashIdx : sel.length;
var dot = dotIdx > 0 ? dotIdx : sel.length;
var tag = hashIdx !== -1 || dotIdx !== -1 ? sel.slice(0, Math.min(hash, dot)) : sel;
elm = vnode.elm = isDef(data) && isDef(i = data.ns) ? document.createElementNS(i, tag) : document.createElement(tag);
if (hash < dot) elm.id = sel.slice(hash + 1, dot);
if (dotIdx > 0) elm.className = sel.slice(dot + 1).replace(/\./g, ' ');
if (is.array(children)) {
for (i = 0; i < children.length; ++i) {
elm.appendChild(createElm(children[i], insertedVnodeQueue));
}
} else if (is.primitive(vnode.text)) {
elm.appendChild(document.createTextNode(vnode.text));
}
for (i = 0; i < cbs.create.length; ++i) cbs.create[i](emptyNode, vnode);
i = vnode.data.hook; // Reuse variable
if (isDef(i)) {
if (i.create) i.create(emptyNode, vnode);
if (i.insert) insertedVnodeQueue.push(vnode);
}
} else {
elm = vnode.elm = document.createTextNode(vnode.text);
}
return vnode.elm;
}
function addVnodes(parentElm, before, vnodes, startIdx, endIdx, insertedVnodeQueue) {
for (; startIdx <= endIdx; ++startIdx) {
parentElm.insertBefore(createElm(vnodes[startIdx], insertedVnodeQueue), before);
}
}
function invokeDestroyHook(vnode) {
var i = vnode.data,
j;
if (isDef(i)) {
if (isDef(i = i.hook) && isDef(i = i.destroy)) i(vnode);
for (i = 0; i < cbs.destroy.length; ++i) cbs.destroy[i](vnode);
if (isDef(i = vnode.children)) {
for (j = 0; j < vnode.children.length; ++j) {
invokeDestroyHook(vnode.children[j]);
}
}
}
}
function removeVnodes(parentElm, vnodes, startIdx, endIdx) {
for (; startIdx <= endIdx; ++startIdx) {
var i,
listeners,
rm,
ch = vnodes[startIdx];
if (isDef(ch)) {
if (isDef(ch.sel)) {
invokeDestroyHook(ch);
listeners = cbs.remove.length + 1;
rm = createRmCb(ch.elm, listeners);
for (i = 0; i < cbs.remove.length; ++i) cbs.remove[i](ch, rm);
if (isDef(i = ch.data) && isDef(i = i.hook) && isDef(i = i.remove)) {
i(ch, rm);
} else {
rm();
}
} else {
// Text node
parentElm.removeChild(ch.elm);
}
}
}
}
function updateChildren(parentElm, oldCh, newCh, insertedVnodeQueue) {
var oldStartIdx = 0,
newStartIdx = 0;
var oldEndIdx = oldCh.length - 1;
var oldStartVnode = oldCh[0];
var oldEndVnode = oldCh[oldEndIdx];
var newEndIdx = newCh.length - 1;
var newStartVnode = newCh[0];
var newEndVnode = newCh[newEndIdx];
var oldKeyToIdx, idxInOld, elmToMove, before;
while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
if (isUndef(oldStartVnode)) {
oldStartVnode = oldCh[++oldStartIdx]; // Vnode has been moved left
} else if (isUndef(oldEndVnode)) {
oldEndVnode = oldCh[--oldEndIdx];
} else if (sameVnode(oldStartVnode, newStartVnode)) {
patchVnode(oldStartVnode, newStartVnode, insertedVnodeQueue);
oldStartVnode = oldCh[++oldStartIdx];
newStartVnode = newCh[++newStartIdx];
} else if (sameVnode(oldEndVnode, newEndVnode)) {
patchVnode(oldEndVnode, newEndVnode, insertedVnodeQueue);
oldEndVnode = oldCh[--oldEndIdx];
newEndVnode = newCh[--newEndIdx];
} else if (sameVnode(oldStartVnode, newEndVnode)) {
// Vnode moved right
patchVnode(oldStartVnode, newEndVnode, insertedVnodeQueue);
parentElm.insertBefore(oldStartVnode.elm, oldEndVnode.elm.nextSibling);
oldStartVnode = oldCh[++oldStartIdx];
newEndVnode = newCh[--newEndIdx];
} else if (sameVnode(oldEndVnode, newStartVnode)) {
// Vnode moved left
patchVnode(oldEndVnode, newStartVnode, insertedVnodeQueue);
parentElm.insertBefore(oldEndVnode.elm, oldStartVnode.elm);
oldEndVnode = oldCh[--oldEndIdx];
newStartVnode = newCh[++newStartIdx];
} else {
if (isUndef(oldKeyToIdx)) oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx);
idxInOld = oldKeyToIdx[newStartVnode.key];
if (isUndef(idxInOld)) {
// New element
parentElm.insertBefore(createElm(newStartVnode, insertedVnodeQueue), oldStartVnode.elm);
newStartVnode = newCh[++newStartIdx];
} else {
elmToMove = oldCh[idxInOld];
patchVnode(elmToMove, newStartVnode, insertedVnodeQueue);
oldCh[idxInOld] = undefined;
parentElm.insertBefore(elmToMove.elm, oldStartVnode.elm);
newStartVnode = newCh[++newStartIdx];
}
}
}
if (oldStartIdx > oldEndIdx) {
before = isUndef(newCh[newEndIdx + 1]) ? null : newCh[newEndIdx + 1].elm;
addVnodes(parentElm, before, newCh, newStartIdx, newEndIdx, insertedVnodeQueue);
} else if (newStartIdx > newEndIdx) {
removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx);
}
}
function patchVnode(oldVnode, vnode, insertedVnodeQueue) {
var i, hook;
if (isDef(i = vnode.data) && isDef(hook = i.hook) && isDef(i = hook.prepatch)) {
i(oldVnode, vnode);
}
if (isDef(i = oldVnode.data) && isDef(i = i.vnode)) oldVnode = i;
if (isDef(i = vnode.data) && isDef(i = i.vnode)) vnode = i;
var elm = vnode.elm = oldVnode.elm,
oldCh = oldVnode.children,
ch = vnode.children;
if (oldVnode === vnode) return;
if (isDef(vnode.data)) {
for (i = 0; i < cbs.update.length; ++i) cbs.update[i](oldVnode, vnode);
i = vnode.data.hook;
if (isDef(i) && isDef(i = i.update)) i(oldVnode, vnode);
}
if (isUndef(vnode.text)) {
if (isDef(oldCh) && isDef(ch)) {
if (oldCh !== ch) updateChildren(elm, oldCh, ch, insertedVnodeQueue);
} else if (isDef(ch)) {
addVnodes(elm, null, ch, 0, ch.length - 1, insertedVnodeQueue);
} else if (isDef(oldCh)) {
removeVnodes(elm, oldCh, 0, oldCh.length - 1);
}
} else if (oldVnode.text !== vnode.text) {
elm.textContent = vnode.text;
}
if (isDef(hook) && isDef(i = hook.postpatch)) {
i(oldVnode, vnode);
}
}
return function (oldVnode, vnode) {
var i;
var insertedVnodeQueue = [];
for (i = 0; i < cbs.pre.length; ++i) cbs.pre[i]();
if (oldVnode instanceof Element) {
if (oldVnode.parentElement !== null) {
createElm(vnode, insertedVnodeQueue);
oldVnode.parentElement.replaceChild(vnode.elm, oldVnode);
} else {
oldVnode = emptyNodeAt(oldVnode);
patchVnode(oldVnode, vnode, insertedVnodeQueue);
}
} else {
patchVnode(oldVnode, vnode, insertedVnodeQueue);
}
for (i = 0; i < insertedVnodeQueue.length; ++i) {
insertedVnodeQueue[i].data.hook.insert(insertedVnodeQueue[i]);
}
for (i = 0; i < cbs.post.length; ++i) cbs.post[i]();
return vnode;
};
}
module.exports = { init: init };
},{"./is":3,"./vnode":6}],6:[function(require,module,exports){
"use strict";
module.exports = function (sel, data, children, text, elm) {
var key = data === undefined ? undefined : data.key;
return { sel: sel, data: data, children: children,
text: text, elm: elm, key: key };
};
},{}]},{},[1]);
+84
View File
@@ -0,0 +1,84 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>SVG</title>
<script type="text/javascript" src="build.js"></script>
<style>
body {
background: #fafafa;
font-family: sans-serif;
}
h1 {
font-weight: normal;
}
.btn {
display: inline-block;
cursor: pointer;
background: #fff;
box-shadow: 0 0 1px rgba(0, 0, 0, .2);
padding: .5em .8em;
transition: box-shadow .05s ease-in-out;
-webkit-transition: box-shadow .05s ease-in-out;
}
.btn:hover {
box-shadow: 0 0 2px rgba(0, 0, 0, .2);
}
.btn:active, .active, .active:hover {
box-shadow: 0 0 1px rgba(0, 0, 0, .2),
inset 0 0 4px rgba(0, 0, 0, .1);
}
.add {
float: right;
}
#container {
max-width: 42em;
margin: 0 auto 2em auto;
}
.list {
position: relative;
}
.row {
overflow: hidden;
position: absolute;
box-sizing: border-box;
width: 100%;
left: 0px;
margin: .5em 0;
padding: 1em;
background: #fff;
box-shadow: 0 0 1px rgba(0, 0, 0, .2);
transition: transform .5s ease-in-out, opacity .5s ease-out, left .5s ease-in-out;
-webkit-transition: transform .5s ease-in-out, opacity .5s ease-out, left .5s ease-in-out;
}
.row div {
display: inline-block;
vertical-align: middle;
}
.row > div:nth-child(1) {
width: 5%;
}
.row > div:nth-child(2) {
width: 30%;
}
.row > div:nth-child(3) {
width: 65%;
}
.rm-btn {
cursor: pointer;
position: absolute;
top: 0;
right: 0;
color: #C25151;
width: 1.4em;
height: 1.4em;
text-align: center;
line-height: 1.4em;
padding: 0;
}
</style>
</head>
<body>
<div id="container"></div>
</body>
</html>
+17
View File
@@ -0,0 +1,17 @@
var snabbdom = require('../../snabbdom.js');
var patch = snabbdom.init([
require('../../modules/attributes').default,
]);
var h = require('../../h.js').default;
var vnode;
window.addEventListener('DOMContentLoaded', () => {
var container = document.getElementById('container');
var vnode = h('div', [
h('svg', {attrs: {width: 100, height: 100}}, [
h('circle', {attrs: {cx: 50, cy: 50, r: 40, stroke: 'green', 'stroke-width': 4, fill: 'yellow'}})
])
]);
vnode = patch(container, vnode);
});