-
-
Notifications
You must be signed in to change notification settings - Fork 2k
/
index.js
109 lines (97 loc) · 3.36 KB
/
index.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
105
106
107
108
109
import { IS_NON_DIMENSIONAL } from '../constants';
import options from '../options';
/** Create an element with the given nodeName.
* @param {String} nodeName
* @param {Boolean} [isSvg=false] If `true`, creates an element within the SVG namespace.
* @returns {Element} node
*/
export function createNode(nodeName, isSvg) {
let node = isSvg ? document.createElementNS('http://www.w3.org/2000/svg', nodeName) : document.createElement(nodeName);
node.normalizedNodeName = nodeName;
return node;
}
/** Remove a child node from its parent if attached.
* @param {Element} node The node to remove
*/
export function removeNode(node) {
let parentNode = node.parentNode;
if (parentNode) parentNode.removeChild(node);
}
/** Set a named attribute on the given Node, with special behavior for some names and event handlers.
* If `value` is `null`, the attribute/handler will be removed.
* @param {Element} node An element to mutate
* @param {string} name The name/key to set, such as an event or attribute name
* @param {any} old The last value that was set for this name/node pair
* @param {any} value An attribute value, such as a function to be used as an event handler
* @param {Boolean} isSvg Are we currently diffing inside an svg?
* @private
*/
export function setAccessor(node, name, old, value, isSvg) {
if (name==='className') name = 'class';
if (name==='key') {
// ignore
}
else if (name==='ref') {
if (old) old(null);
if (value) value(node);
}
else if (name==='class' && !isSvg) {
node.className = value || '';
}
else if (name==='style') {
if (!value || typeof value==='string' || typeof old==='string') {
node.style.cssText = value || '';
}
if (value && typeof value==='object') {
if (typeof old!=='string') {
for (let i in old) if (!(i in value)) node.style[i] = '';
}
for (let i in value) {
node.style[i] = typeof value[i]==='number' && IS_NON_DIMENSIONAL.test(i)===false ? (value[i]+'px') : value[i];
}
}
}
else if (name==='dangerouslySetInnerHTML') {
if (value) node.innerHTML = value.__html || '';
}
else if (name[0]=='o' && name[1]=='n') {
let useCapture = name !== (name=name.replace(/Capture$/, ''));
name = name.toLowerCase().substring(2);
if (value) {
if (!old) node.addEventListener(name, eventProxy, useCapture);
}
else {
node.removeEventListener(name, eventProxy, useCapture);
}
(node._listeners || (node._listeners = {}))[name] = value;
}
else if (name!=='list' && name!=='type' && !isSvg && name in node) {
setProperty(node, name, value==null ? '' : value);
if (value==null || value===false) node.removeAttribute(name);
}
else {
let ns = isSvg && (name !== (name = name.replace(/^xlink\:?/, '')));
if (value==null || value===false) {
if (ns) node.removeAttributeNS('http://www.w3.org/1999/xlink', name.toLowerCase());
else node.removeAttribute(name);
}
else if (typeof value!=='function') {
if (ns) node.setAttributeNS('http://www.w3.org/1999/xlink', name.toLowerCase(), value);
else node.setAttribute(name, value);
}
}
}
/** Attempt to set a DOM property to the given value.
* IE & FF throw for certain property-value combinations.
*/
function setProperty(node, name, value) {
try {
node[name] = value;
} catch (e) { }
}
/** Proxy an event to hooked event handlers
* @private
*/
function eventProxy(e) {
return this._listeners[e.type](options.event && options.event(e) || e);
}