Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

snabbdom

Package Overview
Dependencies
Maintainers
1
Versions
61
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

snabbdom - npm Package Compare versions

Comparing version 0.4.2 to 0.5.0

#snabbdom.js#

4

h.js

@@ -15,7 +15,7 @@ var VNode = require('./vnode');

var data = {}, children, text, i;
if (arguments.length === 3) {
if (c !== undefined) {
data = b;
if (is.array(c)) { children = c; }
else if (is.primitive(c)) { text = c; }
} else if (arguments.length === 2) {
} else if (b !== undefined) {
if (is.array(b)) { children = b; }

@@ -22,0 +22,0 @@ else if (is.primitive(b)) { text = b; }

@@ -5,2 +5,3 @@ var is = require('../is');

return function() {
if (!arr.length) return;
// Special case when length is two, for performance

@@ -12,3 +13,6 @@ arr.length === 2 ? arr[0](arr[1]) : arr[0].apply(undefined, arr.slice(1));

function fnInvoker(o) {
return function(ev) { o.fn(ev); };
return function(ev) {
if (o.fn === null) return;
o.fn(ev);
};
}

@@ -41,4 +45,17 @@

}
if (oldOn) {
for (name in oldOn) {
if (on[name] === undefined) {
var old = oldOn[name];
if (is.array(old)) {
old.length = 0;
}
else {
old.fn = null;
}
}
}
}
}
module.exports = {create: updateEventListeners, update: updateEventListeners};
{
"name": "snabbdom",
"version": "0.4.2",
"version": "0.5.0",
"description": "A virtual DOM library with focus on simplicity, modularity, powerful features and performance.",

@@ -5,0 +5,0 @@ "main": "snabbdom.js",

@@ -17,2 +17,3 @@ # Snabbdom

* [Helpers](#helpers)
* [Virtual Node documentation](#virtual-node)
* [Structuring applications](#structuring-applications)

@@ -22,3 +23,3 @@

Virtual DOM is awesome. It allows us to express our applications view as a
Virtual DOM is awesome. It allows us to express our application's view as a
function of its state. But existing solutions were way way too bloated, too

@@ -46,4 +47,4 @@ slow, lacked features, had an API biased towards OOP and/or lacked features I

* Extendable through modules.
* A rich set of hooks available both per vnode and globally for modules,
so they can hook into any part of the diff and patch process.
* A rich set of hooks available, both per vnode and globally for modules,
to hook into any part of the diff and patch process.
* Splendid performance. Snabbdom is among the fastest virtual DOM libraries

@@ -61,3 +62,5 @@ in the [Virtual DOM Benchmark](http://vdom-benchmark.github.io/vdom-benchmark/).

There is also a Babel plugin [babel-snabbdom-jsx](https://github.com/finnsson/babel-snabbdom-jsx).
* Server-side HTML output provided by [snabbdom-to-html](https://github.com/acstll/snabbdom-to-html).
* Server-side HTML output provided by
[snabbdom-to-html](https://github.com/acstll/snabbdom-to-html).
* Compact virtual DOM creation with [snabbdom-helpers](https://github.com/krainboltgreene/snabbdom-helpers).

@@ -74,3 +77,3 @@ ## Inline example

]);
var h = require('snabbdom/h'); // helper function for creating VNodes
var h = require('snabbdom/h'); // helper function for creating vnodes
var vnode = h('div#container.two.classes', {on: {click: someFn}}, [

@@ -120,3 +123,3 @@ h('span', {style: {fontWeight: 'bold'}}, 'This is bold'),

element or a vnode representing the current view. The second is a vnode
representing the new updated view.
representing the new, updated view.

@@ -139,3 +142,3 @@ If a DOM element with a parent is passed, `newVnode` will be turned into a DOM

It is recommended that you use `snabbdom/h` to create VNodes. `h` accepts a
It is recommended that you use `snabbdom/h` to create vnodes. `h` accepts a
tag/selector as a string, an optional data object and an optional string or

@@ -165,3 +168,3 @@ array of children.

| `init` | a vnode has been added | vnode |
| `create` | a DOM element has been created based on a VNode | `emptyVNode, vnode` |
| `create` | a DOM element has been created based on a vnode | `emptyVnode, vnode` |
| `insert` | an element has been inserted into the DOM | `vnode` |

@@ -200,3 +203,3 @@ | `prepatch` | an element is about to be patched | `oldVnode, vnode` |

found. The hook is called before Snabbdom has processed the node in any way.
I.e. before at has created a DOM node based on the vnode.
I.e., before it has created a DOM node based on the vnode.

@@ -208,6 +211,6 @@ If the hook handler sets the `vnode` property on the vnode, then Snabbdom will

This hook is invoked once the DOM element to a vnode has been inserted into the
This hook is invoked once the DOM element for a vnode has been inserted into the
document _and_ the rest of the patch cycle is done. This means that you can do
DOM measurements (like using [getBoundingClientRect](https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect)
in this hook safely knowing that no elements will be changed afterwards which
in this hook safely, knowing that no elements will be changed afterwards that
could affect the position of the inserted elements.

@@ -220,7 +223,7 @@

vnode and a callback. You can control and delay the removal with the callback.
It should be invoked once the hook is done doing its business, and the element
The callback should be invoked once the hook is done doing its business, and the element
will only be removed once all `remove` hooks have invoked their callback.
The hook is only triggered when an element is to be removed from its parent –
not if it is the child of an element that is removed. For that, see the destroy
not if it is the child of an element that is removed. For that, see the `destroy`
hook.

@@ -243,6 +246,6 @@

Here `destroy` is triggered for both the inner `div` element _and_ the `span`
element it contains. `remove` on the other hand is only triggered on the `div`
element it contains. `remove`, on the other hand, is only triggered on the `div`
element because it is the only element being detached from its parent.
You can for instance use `remove` to trigger an animation when an element is
You can, for instance, use `remove` to trigger an animation when an element is
being removed and use the `destroy` hook to additionally animate the

@@ -253,3 +256,3 @@ disappearance of the removed element's children.

Modules works by registering global listeners for the [hooks](#hooks). A module as simply a dictionary from hook names to functions.
Modules works by registering global listeners for [hooks](#hooks). A module is simply a dictionary mapping hook names to functions.

@@ -280,3 +283,3 @@ ```javascript

map class names to booleans that indicates whether or not the class should stay
or go on the VNode.
or go on the vnode.

@@ -304,3 +307,3 @@ ```javascript

Attributes are added and updated using `setAttribute`. In case of an attribute
that has been previously added/set and is no longer present in the `attrs` object,
that had been previously added/set and is no longer present in the `attrs` object,
it is removed from the DOM element's attribute list using `removeAttribute`.

@@ -319,3 +322,3 @@

The style module is for making your HTML look slick and animate smoothly. At
it's core it allows you to set CSS properties on elements.
its core it allows you to set CSS properties on elements.

@@ -355,3 +358,3 @@ ```javascript

to be removed from the DOM. The applied styles should be animated with CSS
transitions. Only once all the styles is done animating, will the element be
transitions. Only once all the styles are done animating will the element be
removed from the DOM.

@@ -382,3 +385,3 @@

You can attach a function to an event on a VNode by supplying an object at `on`
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.

@@ -418,4 +421,4 @@ The function will be called when the event happens and will be passed the event

Note, however, that **you should be careful when sharing event handlers between
VNodes**, because of the technique this module uses to avoid re-binding
event handlers to the DOM. (And in general, sharing data between VNodes is
vnodes**, because of the technique this module uses to avoid re-binding
event handlers to the DOM. (And in general, sharing data between vnodes is
not guaranteed to work, because modules are allowed to mutate the given data).

@@ -476,9 +479,14 @@

The `thunk` function takes a name for identifying a thunk, a function that
returns a vnode and a variable amount of state parameters. If invoked, the
render function will recieve the state parameters.
The `thunk` function takes a selector, a key for identifying a thunk,
a function that returns a vnode and a variable amount of state
parameters. If invoked, the render function will recieve the state
arguments.
`thunk(uniqueName, renderFn, [stateAguments])`
`thunk(selector, key, renderFn, [stateArguments])`
Thunks is an optimization strategy that can be used when one is dealing with
The `key` is optional. It should be supplied when the `selector` is
not unique among the thunks siblings. This ensures that the thunk is
always matched correctly when diffing.
Thunks are an optimization strategy that can be used when one is dealing with
immutable data.

@@ -511,5 +519,68 @@

The view function here is only an example. In practice thunks are only
relevant if you are rendering a complicated view that takes a significant
computation time to generate.
relevant if you are rendering a complicated view that takes significant
computational time to generate.
## Virtual Node
**Properties**
- [sel](#sel--string)
- [data](#data--object)
- [children](#children--array)
- [text](#text--string)
- [elm](#elm--element)
- [key](#key--string--number)
#### sel : String
The `.sel` property of a virtual node is the CSS selector passed to [`h()`](#snabbdomh) during creation.
For example: `h('div#container', {}, [...])` will create a a virtual node which has `div#container` as its `.sel` property.
#### data : Object
The `.data` property of a virtual node is the place to add information for [modules](#modules-documentation) to access and manipulate the real DOM element when it is created; Add styles, CSS classes, attributes, etc.
The data object is the (optional) second parameter to [`h()`](#snabbdomh)
For example `h('div', {props: {className: 'container'}}, [...])` will produce a virtual node with
```js
{
"props": {
className: "container"
}
}
```
as its `.data` object.
#### children : Array<vnode>
The `.children` property of a virtual node is the third (optional) parameter to [`h()`](#snabbdomh) during creation.
`.children` is simply an Array of virtual nodes that should be added as children of the parent DOM node upon creation.
For example `h('div', {}, [ h('h1', {}, 'Hello, World') ])` will create a virtual node with
```js
[
{
sel: 'h1',
data: {},
children: undefined,
text: 'Hello, World',
elm: Element,
key: undefined,
}
]
```
as its `.children` property.
#### text : string
The `.text` property is created when a virtual node is created with only a single child that possesses text and only requires `document.createTextNode()` to be used.
For example: `h('h1', {}, 'Hello')` will create a virtual node with `Hello` as its `.text` property.
#### elm : Element
The `.elm` property of a virtual node is a pointer to the real DOM node created by snabbdom. This property is very useful to do calculations in [hooks](#hooks) as well as [modules](#modules-documentation).
#### key : string | number
The `.key` property is created when a key is provided inside of your [`.data`](#data--object) object. The `.key` property is used to keep pointers to DOM nodes that existed previously to avoid recreating them if it is unnecessary. This is very useful for things like list reordering. A key must be either a string or a number to allow for proper lookup as it is stored internally as a key/value pair inside of an object, where `.key` is the key and the value is the [`.elm`](#elm--element) property created.
For example: `h('div', {key: 1}, [])` will create a virtual node object with a `.key` property with the value of `1`.
## Structuring applications

@@ -530,2 +601,2 @@

Be sure to share it if you're building an application in another way
using Snabbdom.
using Snabbdom.

@@ -7,3 +7,3 @@ // jshint newcap: false

var is = require('./is');
var domApi = require('./htmldomapi.js');
var domApi = require('./htmldomapi');

@@ -56,8 +56,7 @@ function isUndef(s) { return s === undefined; }

function createElm(vnode, insertedVnodeQueue) {
var i, thunk, data = vnode.data;
var i, data = vnode.data;
if (isDef(data)) {
if (isDef(i = data.hook) && isDef(i = i.init)) i(vnode);
if (isDef(i = data.vnode)) {
thunk = vnode;
vnode = i;
if (isDef(i = data.hook) && isDef(i = i.init)) {
i(vnode);
data = vnode.data;
}

@@ -93,3 +92,2 @@ }

}
if (isDef(thunk)) thunk.elm = vnode.elm;
return vnode.elm;

@@ -114,3 +112,2 @@ }

}
if (isDef(i = data.vnode)) invokeDestroyHook(i);
}

@@ -201,8 +198,2 @@ }

}
if (isDef(i = oldVnode.data) && isDef(i = i.vnode)) oldVnode = i;
if (isDef(i = vnode.data) && isDef(i = i.vnode)) {
patchVnode(oldVnode, i, insertedVnodeQueue);
vnode.elm = i.elm;
return;
}
var elm = vnode.elm = oldVnode.elm, oldCh = oldVnode.children, ch = vnode.children;

@@ -209,0 +200,0 @@ if (oldVnode === vnode) return;

require('./core');
require('./style');
require('./dataset');
require('./eventlisteners');
require('./attachto');
require('./thunk');

@@ -18,4 +18,5 @@ var assert = require('assert');

}
var vnode = thunk('num', numberInSpan, 22);
assert.deepEqual(vnode.sel, 'thunknum');
var vnode = thunk('span', 'num', numberInSpan, [22]);
assert.deepEqual(vnode.sel, 'span');
assert.deepEqual(vnode.data.key, 'num');
assert.deepEqual(vnode.data.args, [22]);

@@ -27,12 +28,12 @@ });

called++;
return h('span', 'Number is ' + n);
return h('span', {key: 'num'}, 'Number is ' + n);
}
var vnode1 = h('div', [
thunk('num', numberInSpan, 1)
thunk('span', 'num', numberInSpan, [1])
]);
var vnode2 = h('div', [
thunk('num', numberInSpan, 1)
thunk('span', 'num', numberInSpan, [1])
]);
var vnode3 = h('div', [
thunk('num', numberInSpan, 2)
thunk('span', 'num', numberInSpan, [2])
]);

@@ -48,12 +49,12 @@ patch(vnode0, vnode1);

called++;
return h('span', 'Number is ' + n);
return h('span', {key: 'num'}, 'Number is ' + n);
}
var vnode1 = h('div', [
thunk('num', numberInSpan, 1)
thunk('span', 'num', numberInSpan, [1])
]);
var vnode2 = h('div', [
thunk('num', numberInSpan, 1)
thunk('span', 'num', numberInSpan, [1])
]);
var vnode3 = h('div', [
thunk('num', numberInSpan, 2)
thunk('span', 'num', numberInSpan, [2])
]);

@@ -71,42 +72,10 @@ elm = patch(vnode0, vnode1).elm;

});
it('renders correctly child thunk', function() {
function oddEven(n) {
var oddEvenSel = (n % 2) ? 'span.odd' : 'span.even';
return h(oddEvenSel, n);
}
function numberInSpan(n) {
return h('span.number', ['Number is ', thunk('oddeven', oddEven, n)]);
}
var vnode1 = thunk('num', numberInSpan, 1);
var vnode2 = thunk('num', numberInSpan, 2);
elm = patch(vnode0, vnode1).elm;
assert.equal(elm.tagName.toLowerCase(), 'span');
assert.equal(elm.className, 'number');
assert.equal(elm.childNodes[1].tagName.toLowerCase(), 'span');
assert.equal(elm.childNodes[1].className, 'odd');
elm = patch(vnode1, vnode2).elm;
assert.equal(elm.tagName.toLowerCase(), 'span');
assert.equal(elm.className, 'number');
assert.equal(elm.childNodes[1].tagName.toLowerCase(), 'span');
assert.equal(elm.childNodes[1].className, 'even');
it('supports leaving out the `key` argument', function() {
function vnodeFn(s) {
return h('span.number', 'Hello ' + s);
}
var vnode1 = thunk('span.number', vnodeFn, ['World!']);
elm = patch(vnode0, vnode1).elm;
assert.equal(elm.innerText, 'Hello World!');
});
/* NOT WORKING YET
it('renders correctly nested thunk', function() {
function oddEven(n) {
var oddEvenSel = (n % 2) ? 'span.odd' : 'span.even';
return h(oddEvenSel, n);
}
function nested(n) {
return thunk('oddeven', oddEven, n);
}
var vnode1 = thunk('num', nested, 1);
var vnode2 = thunk('num', nested, 2);
elm = patch(vnode0, vnode1).elm;
assert.equal(elm.tagName.toLowerCase(), 'span');
assert.equal(elm.className, 'odd');
elm = patch(vnode1, vnode2).elm;
assert.equal(elm.tagName.toLowerCase(), 'span');
assert.equal(elm.className, 'even');
});
*/
it('renders correctly when root', function() {

@@ -116,7 +85,7 @@ var called = 0;

called++;
return h('span', 'Number is ' + n);
return h('span', {key: 'num'}, 'Number is ' + n);
}
var vnode1 = thunk('num', numberInSpan, 1);
var vnode2 = thunk('num', numberInSpan, 1);
var vnode3 = thunk('num', numberInSpan, 2);
var vnode1 = thunk('span', 'num', numberInSpan, [1]);
var vnode2 = thunk('span', 'num', numberInSpan, [1]);
var vnode3 = thunk('span', 'num', numberInSpan, [2]);

@@ -136,56 +105,82 @@ elm = patch(vnode0, vnode1).elm;

});
it('can mutate its root tag', function() {
function oddEven(n) {
var oddEvenSel = (n % 2) ? 'div.odd' : 'p.even';
return h(oddEvenSel, n);
}
var vnode1 = h('div', [thunk('oddEven', oddEven, 1)]);
var vnode2 = h('div', [thunk('oddEven', oddEven, 4)]);
elm = patch(vnode0, vnode1).elm;
assert.equal(elm.firstChild.tagName.toLowerCase(), 'div');
assert.equal(elm.firstChild.className, 'odd');
elm = patch(vnode1, vnode2).elm;
assert.equal(elm.firstChild.tagName.toLowerCase(), 'p');
assert.equal(elm.firstChild.className, 'even');
});
it('can be replaced and removed', function() {
function numberInSpan(n) {
return h('span.numberInSpan', 'Number is ' + n);
return h('span', {key: 'num'}, 'Number is ' + n);
}
function oddEven(n) {
var oddEvenClass = (n % 2) ? '.odd' : '.even';
return h('div' + oddEvenClass, 'Number is ' + n);
var prefix = (n % 2) === 0 ? 'Even' : 'Odd';
return h('div', {key: oddEven}, prefix + ': ' + n);
}
var vnode1 = h('div', [thunk('num', numberInSpan, 1)]);
var vnode2 = h('div', [thunk('oddEven', oddEven, 4)]);
var vnode1 = h('div', [thunk('span', 'num', numberInSpan, [1])]);
var vnode2 = h('div', [thunk('div', 'oddEven', oddEven, [4])]);
elm = patch(vnode0, vnode1).elm;
assert.equal(elm.firstChild.tagName.toLowerCase(), 'span');
assert.equal(elm.firstChild.className, 'numberInSpan');
assert.equal(elm.firstChild.innerHTML, 'Number is 1');
elm = patch(vnode1, vnode2).elm;
assert.equal(elm.firstChild.tagName.toLowerCase(), 'div');
assert.equal(elm.firstChild.className, 'even');
assert.equal(elm.firstChild.innerHTML, 'Even: 4');
});
it('can be replaced and removed when root', function() {
function numberInSpan(n) {
return h('span.numberInSpan', 'Number is ' + n);
return h('span', {key: 'num'}, 'Number is ' + n);
}
function oddEven(n) {
var oddEvenClass = (n % 2) ? '.odd' : '.even';
return h('div' + oddEvenClass, 'Number is ' + n);
var prefix = (n % 2) === 0 ? 'Even' : 'Odd';
return h('div', {key: oddEven}, prefix + ': ' + n);
}
var vnode1 = thunk('num', numberInSpan, 1);
var vnode2 = thunk('oddEven', oddEven, 4);
var vnode1 = thunk('span', 'num', numberInSpan, [1]);
var vnode2 = thunk('div', 'oddEven', oddEven, [4]);
elm = patch(vnode0, vnode1).elm;
assert.equal(elm.tagName.toLowerCase(), 'span');
assert.equal(elm.className, 'numberInSpan');
assert.equal(elm.innerHTML, 'Number is 1');
elm = patch(vnode1, vnode2).elm;
assert.equal(elm.tagName.toLowerCase(), 'div');
assert.equal(elm.className, 'even');
assert.equal(elm.innerHTML, 'Even: 4');
});
it('invokes destroy hook on thunks', function() {
var called = 0;
function destroyHook() {
called++;
}
function numberInSpan(n) {
return h('span', {key: 'num', hook: {destroy: destroyHook}}, 'Number is ' + n);
}
var vnode1 = h('div', [
h('div', 'Foo'),
thunk('span', 'num', numberInSpan, [1]),
h('div', 'Foo')
]);
var vnode2 = h('div', [
h('div', 'Foo'),
h('div', 'Foo')
]);
patch(vnode0, vnode1);
patch(vnode1, vnode2);
assert.equal(called, 1);
});
it('invokes remove hook on thunks', function() {
var called = 0;
function hook() {
called++;
}
function numberInSpan(n) {
return h('span', {key: 'num', hook: {remove: hook}}, 'Number is ' + n);
}
var vnode1 = h('div', [
h('div', 'Foo'),
thunk('span', 'num', numberInSpan, [1]),
h('div', 'Foo')
]);
var vnode2 = h('div', [
h('div', 'Foo'),
h('div', 'Foo')
]);
patch(vnode0, vnode1);
patch(vnode1, vnode2);
assert.equal(called, 1);
});
});
var h = require('./h');
function copyToThunk(vnode, thunk) {
thunk.elm = vnode.elm;
vnode.data.fn = thunk.data.fn;
vnode.data.args = thunk.data.args;
thunk.data = vnode.data;
thunk.children = vnode.children;
thunk.text = vnode.text;
thunk.elm = vnode.elm;
}
function init(thunk) {
var i, cur = thunk.data;
cur.vnode = cur.fn.apply(undefined, cur.args);
var vnode = cur.fn.apply(undefined, cur.args);
copyToThunk(vnode, thunk);
}
function prepatch(oldThunk, thunk) {
var i, old = oldThunk.data, cur = thunk.data;
function prepatch(oldVnode, thunk) {
var i, old = oldVnode.data, cur = thunk.data, vnode;
var oldArgs = old.args, args = cur.args;
cur.vnode = old.vnode;
if (old.fn !== cur.fn || oldArgs.length !== args.length) {
cur.vnode = cur.fn.apply(undefined, args);
return;
copyToThunk(cur.fn.apply(undefined, args), thunk);
}
for (i = 0; i < args.length; ++i) {
if (oldArgs[i] !== args[i]) {
cur.vnode = cur.fn.apply(undefined, args);
copyToThunk(cur.fn.apply(undefined, args), thunk);
return;
}
}
copyToThunk(oldVnode, thunk);
}
module.exports = function(name, fn /* args */) {
var i, args = [];
for (i = 2; i < arguments.length; ++i) {
args[i - 2] = arguments[i];
module.exports = function(sel, key, fn, args) {
if (args === undefined) {
args = fn;
fn = key;
key = undefined;
}
return h('thunk' + name, {
return h(sel, {
key: key,
hook: {init: init, prepatch: prepatch},
fn: fn, args: args,
fn: fn,
args: args
});
};
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc