Comparing version 0.1.5 to 0.2.0
{ | ||
"name": "snabbdom", | ||
"version": "0.1.5", | ||
"version": "0.2.0", | ||
"description": "A virtual DOM library with focus on simplicity, modularity, powerful features and performance.", | ||
@@ -5,0 +5,0 @@ "main": "snabbdom.js", |
# Snabbdom | ||
[![Join the chat at https://gitter.im/paldepind/snabbdom](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/paldepind/snabbdom?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) | ||
A virtual DOM library with focus on simplicity, modularity, powerful features | ||
and performance. | ||
_Note:_ Snabbdom is mostly done. I'm currently only making minor tweaks. The | ||
documentation however is still quite lagging. | ||
## Table of contents | ||
@@ -14,2 +19,9 @@ | ||
## Why | ||
Virtual DOM is awesome. It allow us to express our applications view as a | ||
function of its state. But existing solutions were way way too bloated, too | ||
slow, lacked features, had an API biased towards OOP and/or lacked features I | ||
needed. | ||
## Introduction | ||
@@ -19,3 +31,3 @@ | ||
is only ≈ 200 SLOC. It offers a modular architecture with rich functionality | ||
for extensions through custom modules. To keep the core simple all non-esential | ||
for extensions through custom modules. To keep the core simple all non-essential | ||
functionality is delegated to modules. | ||
@@ -113,13 +125,17 @@ | ||
| Name | Triggered when | Arguments to callback | | ||
| --------- | -------------- | --------------------- | | ||
| `pre` | the patch process begins. | | | ||
| `create` | a DOM element has been created based on a VNode. | `emptyVNode, createdVnode` | | ||
| `insert` | an element has been inserted into the DOM. | `insertedVnode` | | ||
| `patch` | an element is about to be patched. | `oldVnode, newVnode` | | ||
| `update` | an element is being updated. | `oldVnode, newVnode` | | ||
| `remove` | an element is directly being removed from the DOM. | `vnode, removeCallback` | | ||
| `destroy` | an element is begin removed from the DOM or it's parent is. | `vnode` | | ||
| `post` | the patch process is done. | | | ||
#### Overview | ||
| Name | Triggered when | Arguments to callback | | ||
| ----------- | -------------- | --------------------- | | ||
| `pre` | the patch process begins. | none | | ||
| `create` | a DOM element has been created based on a VNode. | `emptyVNode, vnode` | | ||
| `insert` | an element has been inserted into the DOM. | `vnode` | | ||
| `prepatch` | an element is about to be patched. | `oldVnode, vnode` | | ||
| `update` | an element is being updated. | `oldVnode, vnode` | | ||
| `postpatch` | an element has been patched. | `oldVnode, vnode` | | ||
| `remove` | an element is directly being removed from the DOM. | `vnode, removeCallback` | | ||
| `destroy` | an element is being removed from the DOM or it's parent is. | `vnode` | | ||
| `post` | the patch process is done. | none | | ||
## Modules documentation | ||
@@ -157,3 +173,3 @@ | ||
}, 'Say my name, and every colour illuminates'); | ||
``` | ||
`````` | ||
@@ -194,3 +210,6 @@ #### Delayed properties | ||
You can attach a function that will be called with the event object. | ||
You can attach a function to an event on a VNode by supplying an object at `on` | ||
with a property corresponding to the name of the event you want to listen to. | ||
The function will be called when the event happens and will be passed the event | ||
object that belongs to it. | ||
@@ -202,5 +221,14 @@ ```javascript | ||
We can also use the array syntax to attach a function that will be | ||
invoked with a constant value. | ||
Very often however you're not really interested in the event object itself. | ||
Often you have some data associated with the element that triggers an event | ||
and you want that data passed along instead. | ||
Consider a counter application with three buttons, one to increment the counter | ||
by 1, one to increment the counter by 2 and one to increment the counter by 3. | ||
You're don't really care exactly which button was pressed. Instead you're | ||
interested in what number was associated with the clicked button. The event listeners | ||
module allows one to express that by supplying an array at the named event property. | ||
The first element in the array should be a function that will be invoked with | ||
the value in the second element once the event occurs. | ||
```javascript | ||
@@ -214,1 +242,5 @@ function clickHandler(number) { console.log('button ' + number + ' was clicked!'); } | ||
``` | ||
Snabbdom allows swapping event handlers between renders. This happens without | ||
actually touching the event handlers attached to the DOM. | ||
// jshint newcap: false | ||
/* global require, module, document, Element */ | ||
'use strict'; | ||
@@ -48,7 +49,7 @@ | ||
function createElm(vnode) { | ||
var i; | ||
if (!isUndef(i = vnode.data) && !isUndef(i = i.hook) && !isUndef(i = i.init)) { | ||
i(vnode); | ||
var i, data = vnode.data; | ||
if (!isUndef(data)) { | ||
if (!isUndef(i = data.hook) && !isUndef(i = i.init)) i(vnode); | ||
if (!isUndef(i = data.vnode)) vnode = i; | ||
} | ||
if (!isUndef(i = vnode.data) && !isUndef(i = i.vnode)) vnode = i; | ||
var elm, children = vnode.children, sel = vnode.sel; | ||
@@ -62,3 +63,4 @@ if (!isUndef(sel)) { | ||
var tag = hashIdx !== -1 || dotIdx !== -1 ? sel.slice(0, Math.min(hash, dot)) : sel; | ||
elm = vnode.elm = document.createElement(tag); | ||
elm = vnode.elm = !isUndef(data) && !isUndef(i = data.ns) ? document.createElementNS(i, tag) | ||
: document.createElement(tag); | ||
if (hash < dot) elm.id = sel.slice(hash + 1, dot); | ||
@@ -82,3 +84,3 @@ if (dotIdx > 0) elm.className = sel.slice(dot+1).replace(/\./g, ' '); | ||
} | ||
return elm; | ||
return vnode.elm; | ||
} | ||
@@ -94,7 +96,9 @@ | ||
var i = vnode.data, j; | ||
if (!isUndef(i) && !isUndef(i = i.hook) && !isUndef(i = i.destroy)) i(vnode); | ||
for (i = 0; i < cbs.destroy.length; ++i) cbs.destroy[i](vnode); | ||
if (!isUndef(i = vnode.children)) { | ||
for (j = 0; j < vnode.children.length; ++j) { | ||
invokeDestroyHook(vnode.children[j]); | ||
if (!isUndef(i)) { | ||
if (!isUndef(i = i.hook) && !isUndef(i = i.destroy)) i(vnode); | ||
for (i = 0; i < cbs.destroy.length; ++i) cbs.destroy[i](vnode); | ||
if (!isUndef(i = vnode.children)) { | ||
for (j = 0; j < vnode.children.length; ++j) { | ||
invokeDestroyHook(vnode.children[j]); | ||
} | ||
} | ||
@@ -108,6 +112,6 @@ } | ||
if (!isUndef(ch)) { | ||
invokeDestroyHook(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 (!isUndef(i = ch.data) && !isUndef(i = i.hook) && !isUndef(i = i.remove)) { | ||
@@ -179,5 +183,5 @@ i(ch, rm); | ||
function patchVnode(oldVnode, vnode) { | ||
var i; | ||
if (!isUndef(i = vnode.data) && !isUndef(i = i.hook) && !isUndef(i = i.patch)) { | ||
i = i(oldVnode, vnode); | ||
var i, hook; | ||
if (!isUndef(i = vnode.data) && !isUndef(hook = i.hook) && !isUndef(i = hook.prepatch)) { | ||
i(oldVnode, vnode); | ||
} | ||
@@ -204,2 +208,5 @@ if (!isUndef(i = oldVnode.data) && !isUndef(i = i.vnode)) oldVnode = i; | ||
} | ||
if (!isUndef(hook) && !isUndef(i = hook.postpatch)) { | ||
i(oldVnode, vnode); | ||
} | ||
return vnode; | ||
@@ -206,0 +213,0 @@ } |
@@ -67,2 +67,6 @@ var assert = require('assert'); | ||
}); | ||
it('has correct namespace', function() { | ||
patch(vnode0, h('div', [h('div', {ns: 'http://www.w3.org/2000/svg'})])); | ||
assert.equal(elm.firstChild.namespaceURI, 'http://www.w3.org/2000/svg'); | ||
}); | ||
it('is recieves classes in selector', function() { | ||
@@ -505,3 +509,3 @@ patch(vnode0, h('div', [h('i.am.a.class')])); | ||
}); | ||
it('calls `patch` listener', function() { | ||
it('calls `prepatch` listener', function() { | ||
var result = []; | ||
@@ -515,3 +519,3 @@ function cb(oldVnode, vnode) { | ||
h('span', 'First sibling'), | ||
h('div', {hook: {patch: cb}}, [ | ||
h('div', {hook: {prepatch: cb}}, [ | ||
h('span', 'Child 1'), | ||
@@ -523,3 +527,3 @@ h('span', 'Child 2'), | ||
h('span', 'First sibling'), | ||
h('div', {hook: {patch: cb}}, [ | ||
h('div', {hook: {prepatch: cb}}, [ | ||
h('span', 'Child 1'), | ||
@@ -533,2 +537,30 @@ h('span', 'Child 2'), | ||
}); | ||
it('calls `postpatch` after `prepatch` listener', function() { | ||
var pre = [], post = []; | ||
function preCb(oldVnode, vnode) { | ||
pre.push(pre); | ||
} | ||
function postCb(oldVnode, vnode) { | ||
assert.equal(pre.length, post.length + 1); | ||
post.push(post); | ||
} | ||
var vnode1 = h('div', [ | ||
h('span', 'First sibling'), | ||
h('div', {hook: {prepatch: preCb, postpatch: postCb}}, [ | ||
h('span', 'Child 1'), | ||
h('span', 'Child 2'), | ||
]), | ||
]); | ||
var vnode2 = h('div', [ | ||
h('span', 'First sibling'), | ||
h('div', {hook: {prepatch: preCb, postpatch: postCb}}, [ | ||
h('span', 'Child 1'), | ||
h('span', 'Child 2'), | ||
]), | ||
]); | ||
patch(vnode0, vnode1); | ||
patch(vnode1, vnode2); | ||
assert.equal(pre.length, 1); | ||
assert.equal(post.length, 1); | ||
}); | ||
it('calls `update` listener', function() { | ||
@@ -592,4 +624,4 @@ var result1 = []; | ||
var patch = snabbdom.init([ | ||
{remove: function(_, rm) { rm1 = rm; }}, | ||
{remove: function(_, rm) { rm2 = rm; }}, | ||
{remove: function(_, rm) { rm1 = rm; }}, | ||
{remove: function(_, rm) { rm2 = rm; }}, | ||
]); | ||
@@ -613,4 +645,4 @@ var vnode1 = h('div', [h('a', {hook: {remove: function(_, rm) { rm3 = rm; }}})]); | ||
var patch = snabbdom.init([ | ||
{pre: function() { result.push('pre'); }}, | ||
{post: function() { result.push('post'); }}, | ||
{pre: function() { result.push('pre'); }}, | ||
{post: function() { result.push('post'); }}, | ||
]); | ||
@@ -621,3 +653,3 @@ var vnode1 = h('div'); | ||
}); | ||
it('invokes `destroy` hook for all removed children', function() { | ||
it('invokes global `destroy` hook for all removed children', function() { | ||
var result = []; | ||
@@ -663,2 +695,21 @@ function cb(vnode) { result.push(vnode); } | ||
}); | ||
it('does not invoke `destroy` module hook for text nodes', function() { | ||
var created = 0; | ||
var destroyed = 0; | ||
var patch = snabbdom.init([ | ||
{create: function() { created++; }}, | ||
{destroy: function() { destroyed++; }}, | ||
]); | ||
var vnode1 = h('div', [ | ||
h('span', 'First sibling'), | ||
h('div', [ | ||
h('span', 'Child 1'), | ||
h('span', ['Text 1', 'Text 2']), | ||
]), | ||
]); | ||
patch(vnode0, vnode1); | ||
patch(vnode1, vnode0); | ||
assert.equal(created, 4); | ||
assert.equal(destroyed, 4); | ||
}); | ||
}); | ||
@@ -665,0 +716,0 @@ }); |
require('./core'); | ||
require('./style'); | ||
require('./attachto'); | ||
require('./thunk'); |
@@ -8,3 +8,3 @@ var h = require('./h'); | ||
function patch(oldThunk, thunk) { | ||
function prepatch(oldThunk, thunk) { | ||
var i, old = oldThunk.data, cur = thunk.data; | ||
@@ -31,5 +31,5 @@ var oldArgs = old.args, args = cur.args; | ||
return h('thunk' + name, { | ||
hook: {init: init, patch: patch}, | ||
hook: {init: init, prepatch: prepatch}, | ||
fn: fn, args: args, | ||
}); | ||
}; |
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
469667
31
9616
240