/** First-party DOM for summon page JS. Wraps the HTML tree; no host objects leak. */ function bareSummonClassList(node) { return { add: function () { var set = (node.attrs.class || '').split(/\s+/).filter(Boolean) var i for (i = 0; i < arguments.length; i++) { var n = String(arguments[i] || '') if (n && set.indexOf(n) < 0) set.push(n) } node.attrs.class = set.join(' ') }, remove: function () { var set = (node.attrs.class || '').split(/\s+/).filter(Boolean) var i for (i = 0; i < arguments.length; i++) { var n = String(arguments[i] || '') var x = set.indexOf(n) if (x >= 0) set.splice(x, 1) } node.attrs.class = set.join(' ') }, contains: function (n) { return (node.attrs.class || '').split(/\s+/).indexOf(String(n || '')) >= 0 }, toggle: function (n) { n = String(n || '') if (this.contains(n)) this.remove(n) else this.add(n) }, toString: function () { return node.attrs.class || '' } } } function bareSummonWrapNode(node, env) { if (!node) return null if (node._el) return node._el if (node.type === 'text') { var tn = { nodeType: 3, nodeName: '#text', get data() { return node.text || '' }, set data(v) { node.text = String(v) }, get textContent() { return node.text || '' }, set textContent(v) { node.text = String(v) } } node._el = tn return tn } var el = { nodeType: 1, nodeName: String(node.name || '').toUpperCase(), tagName: String(node.name || '').toUpperCase(), _node: node, get id() { return node.attrs.id || '' }, set id(v) { node.attrs.id = String(v == null ? '' : v) }, get className() { return node.attrs.class || '' }, set className(v) { node.attrs.class = String(v == null ? '' : v) }, get classList() { return bareSummonClassList(node) }, get href() { return node.attrs.href || '' }, set href(v) { node.attrs.href = String(v == null ? '' : v) }, get src() { return node.attrs.src || '' }, set src(v) { node.attrs.src = String(v == null ? '' : v) }, get value() { return node.attrs.value != null ? String(node.attrs.value) : '' }, set value(v) { node.attrs.value = String(v == null ? '' : v) }, get textContent() { return bareSummonTextContent(node) }, set textContent(v) { node.children = [ { type: 'text', text: String(v == null ? '' : v), parent: node, children: [] } ] }, get innerHTML() { return bareSummonSerializeInner(node) }, set innerHTML(v) { var kids = bareSummonParseFragment(String(v == null ? '' : v)) var i for (i = 0; i < kids.length; i++) kids[i].parent = node node.children = kids }, getAttribute: function (k) { k = String(k || '').toLowerCase() return node.attrs && node.attrs[k] != null ? String(node.attrs[k]) : null }, setAttribute: function (k, v) { node.attrs[String(k || '').toLowerCase()] = String(v == null ? '' : v) }, removeAttribute: function (k) { delete node.attrs[String(k || '').toLowerCase()] }, hasAttribute: function (k) { return ( node.attrs && Object.prototype.hasOwnProperty.call( node.attrs, String(k || '').toLowerCase() ) ) }, appendChild: function (child) { var cn = child && child._node ? child._node : child if (!cn || !cn.type) return child if (cn.parent && cn.parent.children) { var ix = cn.parent.children.indexOf(cn) if (ix >= 0) cn.parent.children.splice(ix, 1) } cn.parent = node node.children.push(cn) return bareSummonWrapNode(cn, env) }, removeChild: function (child) { var cn = child && child._node ? child._node : child var ix = node.children.indexOf(cn) if (ix >= 0) { node.children.splice(ix, 1) cn.parent = null } return child }, insertBefore: function (child, ref) { var cn = child && child._node ? child._node : child var rn = ref && ref._node ? ref._node : ref if (cn.parent && cn.parent.children) { var px = cn.parent.children.indexOf(cn) if (px >= 0) cn.parent.children.splice(px, 1) } cn.parent = node var at = rn ? node.children.indexOf(rn) : -1 if (at < 0) node.children.push(cn) else node.children.splice(at, 0, cn) return bareSummonWrapNode(cn, env) }, querySelector: function (sel) { var hits = bareSummonQueryAll(node, sel, 1) return hits[0] ? bareSummonWrapNode(hits[0], env) : null }, querySelectorAll: function (sel) { return bareSummonQueryAll(node, sel, 500).map(function (n) { return bareSummonWrapNode(n, env) }) }, getElementsByTagName: function (name) { name = String(name || '').toLowerCase() return bareSummonQueryAll(node, name === '*' ? '*' : name, 500).map( function (n) { return bareSummonWrapNode(n, env) } ) }, getElementsByClassName: function (name) { return bareSummonQueryAll(node, '.' + String(name || ''), 500).map( function (n) { return bareSummonWrapNode(n, env) } ) }, addEventListener: function (type, fn) { if (!node._listeners) node._listeners = {} var t = String(type || '') if (!node._listeners[t]) node._listeners[t] = [] node._listeners[t].push(fn) }, removeEventListener: function (type, fn) { var t = String(type || '') var arr = node._listeners && node._listeners[t] if (!arr) return node._listeners[t] = arr.filter(function (x) { return x !== fn }) }, click: function () { var arr = (node._listeners && node._listeners.click) || [] var i for (i = 0; i < arr.length; i++) { try { arr[i].call(el) } catch (e) { if (env && env.console && env.console.error) env.console.error(e) } } } } Object.defineProperty(el, 'style', { get: function () { if (!node._styleProxy) { var decl = bareSummonParseDeclarations(node.attrs.style || '') node._styleProxy = decl } return node._styleProxy } }) Object.defineProperty(el, 'children', { get: function () { return (node.children || []) .filter(function (c) { return c.type === 'element' }) .map(function (c) { return bareSummonWrapNode(c, env) }) } }) Object.defineProperty(el, 'childNodes', { get: function () { return (node.children || []).map(function (c) { return bareSummonWrapNode(c, env) }) } }) Object.defineProperty(el, 'parentNode', { get: function () { return node.parent ? bareSummonWrapNode(node.parent, env) : null } }) Object.defineProperty(el, 'firstChild', { get: function () { var c = node.children && node.children[0] return c ? bareSummonWrapNode(c, env) : null } }) node._el = el return el } function bareSummonFlushInlineStyle(node) { if (!node) return if (node._styleProxy) { var bits = [] var k for (k in node._styleProxy) { if (Object.prototype.hasOwnProperty.call(node._styleProxy, k)) { bits.push(k + ':' + node._styleProxy[k]) } } node.attrs.style = bits.join(';') } var ch = node.children || [] var i for (i = 0; i < ch.length; i++) bareSummonFlushInlineStyle(ch[i]) } function bareSummonCreateDocumentApi(doc, env) { env = env || {} var api = { nodeType: 9, nodeName: '#document', documentElement: bareSummonWrapNode(doc.html, env), head: bareSummonWrapNode(doc.head, env), body: bareSummonWrapNode(doc.body, env), get title() { return doc.title || '' }, set title(v) { doc.title = String(v == null ? '' : v) }, getElementById: function (id) { var hits = bareSummonQueryAll(doc.root, '#' + String(id || ''), 1) return hits[0] ? bareSummonWrapNode(hits[0], env) : null }, querySelector: function (sel) { var hits = bareSummonQueryAll(doc.root, sel, 1) return hits[0] ? bareSummonWrapNode(hits[0], env) : null }, querySelectorAll: function (sel) { return bareSummonQueryAll(doc.root, sel, 500).map(function (n) { return bareSummonWrapNode(n, env) }) }, getElementsByTagName: function (name) { name = String(name || '').toLowerCase() return bareSummonQueryAll(doc.root, name === '*' ? '*' : name, 500).map( function (n) { return bareSummonWrapNode(n, env) } ) }, getElementsByClassName: function (name) { return bareSummonQueryAll(doc.root, '.' + String(name || ''), 500).map( function (n) { return bareSummonWrapNode(n, env) } ) }, createElement: function (name) { return bareSummonWrapNode( bareSummonCreateNode( 'element', String(name || 'div').toLowerCase(), {} ), env ) }, createTextNode: function (text) { return bareSummonWrapNode( { type: 'text', text: String(text == null ? '' : text), parent: null, children: [] }, env ) }, createDocumentFragment: function () { return bareSummonWrapNode( bareSummonCreateNode('element', 'fragment', {}), env ) } } env.document = api return api }