diff options
Diffstat (limited to 'thirdparty/preact/src/dom/index.js')
-rw-r--r-- | thirdparty/preact/src/dom/index.js | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/thirdparty/preact/src/dom/index.js b/thirdparty/preact/src/dom/index.js new file mode 100644 index 000000000..248a3cdc5 --- /dev/null +++ b/thirdparty/preact/src/dom/index.js @@ -0,0 +1,100 @@ +import { ATTR_KEY, NON_DIMENSION_PROPS, NON_BUBBLING_EVENTS } from '../constants'; +import options from '../options'; +import { toLowerCase, isString, isFunction, hashToClassName } from '../util'; + + + + +/** Removes a given DOM Node from its parent. */ +export function removeNode(node) { + let p = node.parentNode; + if (p) p.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} value An attribute value, such as a function to be used as an event handler + * @param {any} previousValue The last value that was set for this name/node pair + * @private + */ +export function setAccessor(node, name, value, old, isSvg) { + node[ATTR_KEY][name] = value; + + if (name==='className') name = 'class'; + + if (name==='class' && value && typeof value==='object') { + value = hashToClassName(value); + } + + if (name==='key' || name==='children' || name==='innerHTML') { + // skip these + } + else if (name==='class' && !isSvg) { + node.className = value || ''; + } + else if (name==='style') { + if (!value || isString(value) || isString(old)) { + node.style.cssText = value || ''; + } + if (value && typeof value==='object') { + if (!isString(old)) { + for (let i in old) if (!(i in value)) node.style[i] = ''; + } + for (let i in value) { + node.style[i] = typeof value[i]==='number' && !NON_DIMENSION_PROPS[i] ? (value[i]+'px') : value[i]; + } + } + } + else if (name==='dangerouslySetInnerHTML') { + if (value) node.innerHTML = value.__html; + } + else if (name[0]=='o' && name[1]=='n') { + let l = node._listeners || (node._listeners = {}); + name = toLowerCase(name.substring(2)); + // @TODO: this might be worth it later, un-breaks focus/blur bubbling in IE9: + // if (node.attachEvent) name = name=='focus'?'focusin':name=='blur'?'focusout':name; + if (value) { + if (!l[name]) node.addEventListener(name, eventProxy, !!NON_BUBBLING_EVENTS[name]); + } + else if (l[name]) { + node.removeEventListener(name, eventProxy, !!NON_BUBBLING_EVENTS[name]); + } + l[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.match(/^xlink\:?(.+)/); + if (value==null || value===false) { + if (ns) node.removeAttributeNS('http://www.w3.org/1999/xlink', toLowerCase(ns[1])); + else node.removeAttribute(name); + } + else if (typeof value!=='object' && !isFunction(value)) { + if (ns) node.setAttributeNS('http://www.w3.org/1999/xlink', toLowerCase(ns[1]), 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); +} |