-
Notifications
You must be signed in to change notification settings - Fork 3
/
dombuilder.js
104 lines (89 loc) · 3.14 KB
/
dombuilder.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
//////////////////////////////////////
// //
// JS domBuilder Library //
// //
// Tim Caswell <[email protected]> //
// //
//////////////////////////////////////
( // Module boilerplate to support component, browser globals and AMD.
(typeof module === "object" && typeof module.exports === "object" && function (m) { module.exports = m(); }) ||
(typeof define === "function" && function (m) { define("dombuilder", m); }) ||
(function (m) { window.domBuilder = m(); })
)(function () {
"use strict";
function domBuilder(json, refs) {
// Render strings as text nodes
if (typeof json === 'string') return document.createTextNode(json);
// Pass through html elements and text nodes as-is
if (json instanceof HTMLElement || json instanceof window.Text) return json;
// Stringify any other value types
if (!Array.isArray(json)) return document.createTextNode(json + "");
// Empty arrays are just empty fragments.
if (!json.length) return document.createDocumentFragment();
var node, first;
for (var i = 0, l = json.length; i < l; i++) {
var part = json[i];
if (!node) {
if (typeof part === 'string') {
// Create a new dom node by parsing the tagline
var tag = part.match(TAG_MATCH);
tag = tag ? tag[0] : "div";
node = document.createElement(tag);
first = true;
var classes = part.match(CLASS_MATCH);
if (classes) node.setAttribute('class', classes.map(stripFirst).join(' '));
var id = part.match(ID_MATCH);
if (id) node.setAttribute('id', id[0].substr(1));
var ref = part.match(REF_MATCH);
if (refs && ref) refs[ref[0].substr(1)] = node;
continue;
} else if (typeof part === "function") {
return domBuilder(part.apply(null, json.slice(i + 1)), refs);
} else {
node = document.createDocumentFragment();
}
}
// Except the first item if it's an attribute object
if (first && typeof part === 'object' && part.constructor === Object) {
setAttrs(node, part);
} else {
node.appendChild(domBuilder(part, refs));
}
first = false;
}
return node;
}
function setAttrs(node, attrs) {
var keys = Object.keys(attrs);
for (var i = 0, l = keys.length; i < l; i++) {
var key = keys[i];
var value = attrs[key];
if (key === "$") {
value(node);
} else if (key === "css" || key === "style" && value.constructor === Object) {
setStyle(node.style, value);
} else if (key.substr(0, 2) === "on") {
node.addEventListener(key.substr(2), value, false);
} else if (typeof value === "boolean") {
if (value) node.setAttribute(key, key);
} else {
node.setAttribute(key, value);
}
}
}
function setStyle(style, attrs) {
var keys = Object.keys(attrs);
for (var i = 0, l = keys.length; i < l; i++) {
var key = keys[i];
style[key] = attrs[key];
}
}
var CLASS_MATCH = /\.[^.#$]+/g,
ID_MATCH = /#[^.#$]+/,
REF_MATCH = /\$[^.#$]+/,
TAG_MATCH = /^[^.#$]+/;
function stripFirst(part) {
return part.substr(1);
}
return domBuilder;
});