├── .gitignore
├── .npmignore
├── README.md
├── index.js
├── package.json
└── test.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | npm-debug.log
3 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | test
2 | test.js
3 | example
4 | examples
5 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## html-patcher
2 |
3 | Virtual DOM Diff & Patch with HTML Templates. Based on [the virtual-dom on NPM](http://npmjs.org/virtual-dom)
4 |
5 | ## Install
6 |
7 | ```bash
8 | $ npm install html-patch
9 | ```
10 |
11 | ## Usage
12 |
13 | A simple app to show epoch time every second:
14 |
15 | ```js
16 | var patcher = require('html-patcher')
17 |
18 | var patch = patcher(document.body, render());
19 |
20 | setInterval(function () {
21 | patch(render())
22 | }, 1000);
23 |
24 | function render () {
25 | return '
' + Date.now() + '
';
26 | }
27 | ```
28 |
29 | See `test.js` for more info.
30 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | var createRootNode = require('virtual-dom/create-element');
2 | var diff = require('virtual-dom/diff');
3 | var applyPatches = require('virtual-dom/patch');
4 | var virtualHTML = require("virtual-html");
5 |
6 | module.exports = newPatch;
7 |
8 | function newPatch (parentNode, html) {
9 | var tree;
10 | var rootNode;
11 |
12 | patch(html);
13 |
14 | return patch;
15 |
16 | function patch (newHtml) {
17 | var vdom = virtualHTML(newHtml || html);
18 |
19 | if (!tree) {
20 | tree = vdom;
21 | rootNode = createRootNode(vdom);
22 | parentNode.appendChild(rootNode);
23 | return patch;
24 | }
25 |
26 | var patches = diff(tree, vdom);
27 | applyPatches(rootNode, patches);
28 | tree = vdom;
29 |
30 | return patch;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "html-patcher",
3 | "version": "1.0.0",
4 | "description": "Virtual DOM Diff & Patch with HTML Templates",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "node test"
8 | },
9 | "keywords": [
10 | "html",
11 | "virtual dom",
12 | "domdiff",
13 | "dom diffing",
14 | "patch",
15 | "virtualdom"
16 | ],
17 | "repository": {
18 | "url": "git@github.com:azer/html-patcher.git",
19 | "type": "git"
20 | },
21 | "author": "azer",
22 | "license": "BSD",
23 | "dependencies": {
24 | "virtual-dom": "^2.0.1",
25 | "virtual-html": "^1.2.0"
26 | },
27 | "devDependencies": {
28 | "prova": "^1.15.0"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/test.js:
--------------------------------------------------------------------------------
1 | var test = require("prova");
2 | var patcher = require('./');
3 |
4 | var fruits = ['apple', 'grape', 'orange'];
5 | var moreFruits = ['apple', 'grape', 'cherry', 'melon', 'orange'];
6 |
7 | test('Basic DOM diffing and patching', function (t) {
8 | t.plan(3);
9 | clear();
10 |
11 | var patch = patcher(document.body, basic('hi'));
12 | t.equal(document.body.innerHTML.trim(), 'hi
');
13 |
14 | var root = document.querySelector('basic');
15 |
16 | patch(basic('yo'));
17 | t.equal(document.body.innerHTML.trim(), 'yo
');
18 | t.equal(document.querySelector('basic'), document.querySelector('basic'));
19 | });
20 |
21 | test('Lists', function (t) {
22 | t.plan(9);
23 | clear();
24 |
25 | var patch = patcher(document.body, list(fruits));
26 | t.equal(document.body.innerHTML.trim(), list(fruits));
27 |
28 | Array.prototype.forEach.call(document.querySelectorAll('li'), function (el) {
29 | el.style.color = 'purple';
30 | t.equal(el.style.color, 'purple');
31 | });
32 |
33 | patch(list(moreFruits));
34 |
35 | Array.prototype.forEach.call(document.querySelectorAll('li'), function (el, ind) {
36 | if (ind > 2) { // cherry, melon or orange
37 | t.notOk(el.style.color);
38 | return;
39 | };
40 |
41 | t.equal(el.style.color, 'purple');
42 | });
43 | });
44 |
45 | test('Countback example', function (t) {
46 | t.plan(2);
47 |
48 | clear();
49 |
50 | var n = 3;
51 | var patch = patcher(document.body, render);
52 | var timer = setInterval(patch, 1000);
53 |
54 | function render () {
55 | if (n == 1) {
56 | clearInterval(timer);
57 | }
58 |
59 | if (n < 3) {
60 | t.equal(document.body.innerHTML.trim(), countback(n + 1));
61 | }
62 |
63 | return countback(n--);
64 | }
65 | });
66 |
67 | function basic (content) {
68 | return '' + content + '
';
69 | }
70 |
71 | function list (content) {
72 | var html = '';
73 |
74 | html += content.map(function (el) {
75 | return '- ' + el + '
';
76 | }).join('\n');
77 |
78 | html += '
';
79 |
80 | return html;
81 | }
82 |
83 | function countback (n) {
84 | var size = 48 - (n * 5);
85 | var colors = ['red', 'blue', 'green'];
86 | return '' + n + '
';
87 | }
88 |
89 | function clear () {
90 | document.body.innerHTML = '';
91 | }
92 |
--------------------------------------------------------------------------------