Index: tests/io-element.js |
=================================================================== |
new file mode 100644 |
--- /dev/null |
+++ b/tests/io-element.js |
@@ -0,0 +1,3315 @@ |
+/* eslint-disable */(function(){function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s}return e})()({1:[function(require,module,exports){ |
+/* globals module, require */ |
+ |
+"use strict"; |
+ |
+// Custom Elements polyfill |
+const customElementsPonyfill = require("document-register-element/pony"); |
+if (typeof customElements !== "object") |
+ customElementsPonyfill(window); |
+ |
+// external dependencies |
+const {default: HyperHTMLElement} = require("hyperhtml-element/cjs"); |
+ |
+// provides a unique-id suffix per each component |
+let counter = 0; |
+ |
+// common Custom Element class to extend |
+class IOElement extends HyperHTMLElement |
+{ |
+ // get a unique ID or, if null, set one and returns it |
+ static getID(element) |
+ { |
+ return element.getAttribute("id") || IOElement.setID(element); |
+ } |
+ |
+ // set a unique ID to a generic element and returns the ID |
+ static setID(element) |
+ { |
+ const id = `${element.nodeName.toLowerCase()}-${counter++}`; |
+ element.setAttribute("id", id); |
+ return id; |
+ } |
+ |
+ // lazily retrieve or define a custom element ID |
+ get id() |
+ { |
+ return IOElement.getID(this); |
+ } |
+ |
+ // whenever an element is created, render its content once |
+ created() { this.render(); } |
+ |
+ // by default, render is a no-op |
+ render() {} |
+} |
+ |
+// whenever an interpolation with ${{i18n: 'string-id'}} is found |
+// transform such value into the expected content |
+// example: |
+// render() { |
+// return this.html`<div>${{i18n:'about-abp'}}</div>`; |
+// } |
+const {setElementText} = ext.i18n; |
+IOElement.intent("i18n", id => |
+{ |
+ const fragment = document.createDocumentFragment(); |
+ setElementText(fragment, id); |
+ return fragment; |
+}); |
+ |
+module.exports = IOElement; |
+ |
+},{"document-register-element/pony":2,"hyperhtml-element/cjs":3}],2:[function(require,module,exports){ |
+/*! |
+ |
+Copyright (C) 2014-2016 by Andrea Giammarchi - @WebReflection |
+ |
+Permission is hereby granted, free of charge, to any person obtaining a copy |
+of this software and associated documentation files (the "Software"), to deal |
+in the Software without restriction, including without limitation the rights |
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
+copies of the Software, and to permit persons to whom the Software is |
+furnished to do so, subject to the following conditions: |
+ |
+The above copyright notice and this permission notice shall be included in |
+all copies or substantial portions of the Software. |
+ |
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
+THE SOFTWARE. |
+ |
+*/ |
+// global window Object |
+// optional polyfill info |
+// 'auto' used by default, everything is feature detected |
+// 'force' use the polyfill even if not fully needed |
+function installCustomElements(window, polyfill) {'use strict'; |
+ |
+ // DO NOT USE THIS FILE DIRECTLY, IT WON'T WORK |
+ // THIS IS A PROJECT BASED ON A BUILD SYSTEM |
+ // THIS FILE IS JUST WRAPPED UP RESULTING IN |
+ // build/document-register-element.node.js |
+ |
+ var |
+ document = window.document, |
+ Object = window.Object |
+ ; |
+ |
+ var htmlClass = (function (info) { |
+ // (C) Andrea Giammarchi - @WebReflection - MIT Style |
+ var |
+ catchClass = /^[A-Z]+[a-z]/, |
+ filterBy = function (re) { |
+ var arr = [], tag; |
+ for (tag in register) { |
+ if (re.test(tag)) arr.push(tag); |
+ } |
+ return arr; |
+ }, |
+ add = function (Class, tag) { |
+ tag = tag.toLowerCase(); |
+ if (!(tag in register)) { |
+ register[Class] = (register[Class] || []).concat(tag); |
+ register[tag] = (register[tag.toUpperCase()] = Class); |
+ } |
+ }, |
+ register = (Object.create || Object)(null), |
+ htmlClass = {}, |
+ i, section, tags, Class |
+ ; |
+ for (section in info) { |
+ for (Class in info[section]) { |
+ tags = info[section][Class]; |
+ register[Class] = tags; |
+ for (i = 0; i < tags.length; i++) { |
+ register[tags[i].toLowerCase()] = |
+ register[tags[i].toUpperCase()] = Class; |
+ } |
+ } |
+ } |
+ htmlClass.get = function get(tagOrClass) { |
+ return typeof tagOrClass === 'string' ? |
+ (register[tagOrClass] || (catchClass.test(tagOrClass) ? [] : '')) : |
+ filterBy(tagOrClass); |
+ }; |
+ htmlClass.set = function set(tag, Class) { |
+ return (catchClass.test(tag) ? |
+ add(tag, Class) : |
+ add(Class, tag) |
+ ), htmlClass; |
+ }; |
+ return htmlClass; |
+ }({ |
+ "collections": { |
+ "HTMLAllCollection": [ |
+ "all" |
+ ], |
+ "HTMLCollection": [ |
+ "forms" |
+ ], |
+ "HTMLFormControlsCollection": [ |
+ "elements" |
+ ], |
+ "HTMLOptionsCollection": [ |
+ "options" |
+ ] |
+ }, |
+ "elements": { |
+ "Element": [ |
+ "element" |
+ ], |
+ "HTMLAnchorElement": [ |
+ "a" |
+ ], |
+ "HTMLAppletElement": [ |
+ "applet" |
+ ], |
+ "HTMLAreaElement": [ |
+ "area" |
+ ], |
+ "HTMLAttachmentElement": [ |
+ "attachment" |
+ ], |
+ "HTMLAudioElement": [ |
+ "audio" |
+ ], |
+ "HTMLBRElement": [ |
+ "br" |
+ ], |
+ "HTMLBaseElement": [ |
+ "base" |
+ ], |
+ "HTMLBodyElement": [ |
+ "body" |
+ ], |
+ "HTMLButtonElement": [ |
+ "button" |
+ ], |
+ "HTMLCanvasElement": [ |
+ "canvas" |
+ ], |
+ "HTMLContentElement": [ |
+ "content" |
+ ], |
+ "HTMLDListElement": [ |
+ "dl" |
+ ], |
+ "HTMLDataElement": [ |
+ "data" |
+ ], |
+ "HTMLDataListElement": [ |
+ "datalist" |
+ ], |
+ "HTMLDetailsElement": [ |
+ "details" |
+ ], |
+ "HTMLDialogElement": [ |
+ "dialog" |
+ ], |
+ "HTMLDirectoryElement": [ |
+ "dir" |
+ ], |
+ "HTMLDivElement": [ |
+ "div" |
+ ], |
+ "HTMLDocument": [ |
+ "document" |
+ ], |
+ "HTMLElement": [ |
+ "element", |
+ "abbr", |
+ "address", |
+ "article", |
+ "aside", |
+ "b", |
+ "bdi", |
+ "bdo", |
+ "cite", |
+ "code", |
+ "command", |
+ "dd", |
+ "dfn", |
+ "dt", |
+ "em", |
+ "figcaption", |
+ "figure", |
+ "footer", |
+ "header", |
+ "i", |
+ "kbd", |
+ "mark", |
+ "nav", |
+ "noscript", |
+ "rp", |
+ "rt", |
+ "ruby", |
+ "s", |
+ "samp", |
+ "section", |
+ "small", |
+ "strong", |
+ "sub", |
+ "summary", |
+ "sup", |
+ "u", |
+ "var", |
+ "wbr" |
+ ], |
+ "HTMLEmbedElement": [ |
+ "embed" |
+ ], |
+ "HTMLFieldSetElement": [ |
+ "fieldset" |
+ ], |
+ "HTMLFontElement": [ |
+ "font" |
+ ], |
+ "HTMLFormElement": [ |
+ "form" |
+ ], |
+ "HTMLFrameElement": [ |
+ "frame" |
+ ], |
+ "HTMLFrameSetElement": [ |
+ "frameset" |
+ ], |
+ "HTMLHRElement": [ |
+ "hr" |
+ ], |
+ "HTMLHeadElement": [ |
+ "head" |
+ ], |
+ "HTMLHeadingElement": [ |
+ "h1", |
+ "h2", |
+ "h3", |
+ "h4", |
+ "h5", |
+ "h6" |
+ ], |
+ "HTMLHtmlElement": [ |
+ "html" |
+ ], |
+ "HTMLIFrameElement": [ |
+ "iframe" |
+ ], |
+ "HTMLImageElement": [ |
+ "img" |
+ ], |
+ "HTMLInputElement": [ |
+ "input" |
+ ], |
+ "HTMLKeygenElement": [ |
+ "keygen" |
+ ], |
+ "HTMLLIElement": [ |
+ "li" |
+ ], |
+ "HTMLLabelElement": [ |
+ "label" |
+ ], |
+ "HTMLLegendElement": [ |
+ "legend" |
+ ], |
+ "HTMLLinkElement": [ |
+ "link" |
+ ], |
+ "HTMLMapElement": [ |
+ "map" |
+ ], |
+ "HTMLMarqueeElement": [ |
+ "marquee" |
+ ], |
+ "HTMLMediaElement": [ |
+ "media" |
+ ], |
+ "HTMLMenuElement": [ |
+ "menu" |
+ ], |
+ "HTMLMenuItemElement": [ |
+ "menuitem" |
+ ], |
+ "HTMLMetaElement": [ |
+ "meta" |
+ ], |
+ "HTMLMeterElement": [ |
+ "meter" |
+ ], |
+ "HTMLModElement": [ |
+ "del", |
+ "ins" |
+ ], |
+ "HTMLOListElement": [ |
+ "ol" |
+ ], |
+ "HTMLObjectElement": [ |
+ "object" |
+ ], |
+ "HTMLOptGroupElement": [ |
+ "optgroup" |
+ ], |
+ "HTMLOptionElement": [ |
+ "option" |
+ ], |
+ "HTMLOutputElement": [ |
+ "output" |
+ ], |
+ "HTMLParagraphElement": [ |
+ "p" |
+ ], |
+ "HTMLParamElement": [ |
+ "param" |
+ ], |
+ "HTMLPictureElement": [ |
+ "picture" |
+ ], |
+ "HTMLPreElement": [ |
+ "pre" |
+ ], |
+ "HTMLProgressElement": [ |
+ "progress" |
+ ], |
+ "HTMLQuoteElement": [ |
+ "blockquote", |
+ "q", |
+ "quote" |
+ ], |
+ "HTMLScriptElement": [ |
+ "script" |
+ ], |
+ "HTMLSelectElement": [ |
+ "select" |
+ ], |
+ "HTMLShadowElement": [ |
+ "shadow" |
+ ], |
+ "HTMLSlotElement": [ |
+ "slot" |
+ ], |
+ "HTMLSourceElement": [ |
+ "source" |
+ ], |
+ "HTMLSpanElement": [ |
+ "span" |
+ ], |
+ "HTMLStyleElement": [ |
+ "style" |
+ ], |
+ "HTMLTableCaptionElement": [ |
+ "caption" |
+ ], |
+ "HTMLTableCellElement": [ |
+ "td", |
+ "th" |
+ ], |
+ "HTMLTableColElement": [ |
+ "col", |
+ "colgroup" |
+ ], |
+ "HTMLTableElement": [ |
+ "table" |
+ ], |
+ "HTMLTableRowElement": [ |
+ "tr" |
+ ], |
+ "HTMLTableSectionElement": [ |
+ "thead", |
+ "tbody", |
+ "tfoot" |
+ ], |
+ "HTMLTemplateElement": [ |
+ "template" |
+ ], |
+ "HTMLTextAreaElement": [ |
+ "textarea" |
+ ], |
+ "HTMLTimeElement": [ |
+ "time" |
+ ], |
+ "HTMLTitleElement": [ |
+ "title" |
+ ], |
+ "HTMLTrackElement": [ |
+ "track" |
+ ], |
+ "HTMLUListElement": [ |
+ "ul" |
+ ], |
+ "HTMLUnknownElement": [ |
+ "unknown", |
+ "vhgroupv", |
+ "vkeygen" |
+ ], |
+ "HTMLVideoElement": [ |
+ "video" |
+ ] |
+ }, |
+ "nodes": { |
+ "Attr": [ |
+ "node" |
+ ], |
+ "Audio": [ |
+ "audio" |
+ ], |
+ "CDATASection": [ |
+ "node" |
+ ], |
+ "CharacterData": [ |
+ "node" |
+ ], |
+ "Comment": [ |
+ "#comment" |
+ ], |
+ "Document": [ |
+ "#document" |
+ ], |
+ "DocumentFragment": [ |
+ "#document-fragment" |
+ ], |
+ "DocumentType": [ |
+ "node" |
+ ], |
+ "HTMLDocument": [ |
+ "#document" |
+ ], |
+ "Image": [ |
+ "img" |
+ ], |
+ "Option": [ |
+ "option" |
+ ], |
+ "ProcessingInstruction": [ |
+ "node" |
+ ], |
+ "ShadowRoot": [ |
+ "#shadow-root" |
+ ], |
+ "Text": [ |
+ "#text" |
+ ], |
+ "XMLDocument": [ |
+ "xml" |
+ ] |
+ } |
+ })); |
+ |
+ |
+ |
+ // passed at runtime, configurable via nodejs module |
+ if (typeof polyfill !== 'object') polyfill = {type: polyfill || 'auto'}; |
+ |
+ var |
+ // V0 polyfill entry |
+ REGISTER_ELEMENT = 'registerElement', |
+ |
+ // IE < 11 only + old WebKit for attributes + feature detection |
+ EXPANDO_UID = '__' + REGISTER_ELEMENT + (window.Math.random() * 10e4 >> 0), |
+ |
+ // shortcuts and costants |
+ ADD_EVENT_LISTENER = 'addEventListener', |
+ ATTACHED = 'attached', |
+ CALLBACK = 'Callback', |
+ DETACHED = 'detached', |
+ EXTENDS = 'extends', |
+ |
+ ATTRIBUTE_CHANGED_CALLBACK = 'attributeChanged' + CALLBACK, |
+ ATTACHED_CALLBACK = ATTACHED + CALLBACK, |
+ CONNECTED_CALLBACK = 'connected' + CALLBACK, |
+ DISCONNECTED_CALLBACK = 'disconnected' + CALLBACK, |
+ CREATED_CALLBACK = 'created' + CALLBACK, |
+ DETACHED_CALLBACK = DETACHED + CALLBACK, |
+ |
+ ADDITION = 'ADDITION', |
+ MODIFICATION = 'MODIFICATION', |
+ REMOVAL = 'REMOVAL', |
+ |
+ DOM_ATTR_MODIFIED = 'DOMAttrModified', |
+ DOM_CONTENT_LOADED = 'DOMContentLoaded', |
+ DOM_SUBTREE_MODIFIED = 'DOMSubtreeModified', |
+ |
+ PREFIX_TAG = '<', |
+ PREFIX_IS = '=', |
+ |
+ // valid and invalid node names |
+ validName = /^[A-Z][A-Z0-9]*(?:-[A-Z0-9]+)+$/, |
+ invalidNames = [ |
+ 'ANNOTATION-XML', |
+ 'COLOR-PROFILE', |
+ 'FONT-FACE', |
+ 'FONT-FACE-SRC', |
+ 'FONT-FACE-URI', |
+ 'FONT-FACE-FORMAT', |
+ 'FONT-FACE-NAME', |
+ 'MISSING-GLYPH' |
+ ], |
+ |
+ // registered types and their prototypes |
+ types = [], |
+ protos = [], |
+ |
+ // to query subnodes |
+ query = '', |
+ |
+ // html shortcut used to feature detect |
+ documentElement = document.documentElement, |
+ |
+ // ES5 inline helpers || basic patches |
+ indexOf = types.indexOf || function (v) { |
+ for(var i = this.length; i-- && this[i] !== v;){} |
+ return i; |
+ }, |
+ |
+ // other helpers / shortcuts |
+ OP = Object.prototype, |
+ hOP = OP.hasOwnProperty, |
+ iPO = OP.isPrototypeOf, |
+ |
+ defineProperty = Object.defineProperty, |
+ empty = [], |
+ gOPD = Object.getOwnPropertyDescriptor, |
+ gOPN = Object.getOwnPropertyNames, |
+ gPO = Object.getPrototypeOf, |
+ sPO = Object.setPrototypeOf, |
+ |
+ // jshint proto: true |
+ hasProto = !!Object.__proto__, |
+ |
+ // V1 helpers |
+ fixGetClass = false, |
+ DRECEV1 = '__dreCEv1', |
+ customElements = window.customElements, |
+ usableCustomElements = !/^force/.test(polyfill.type) && !!( |
+ customElements && |
+ customElements.define && |
+ customElements.get && |
+ customElements.whenDefined |
+ ), |
+ Dict = Object.create || Object, |
+ Map = window.Map || function Map() { |
+ var K = [], V = [], i; |
+ return { |
+ get: function (k) { |
+ return V[indexOf.call(K, k)]; |
+ }, |
+ set: function (k, v) { |
+ i = indexOf.call(K, k); |
+ if (i < 0) V[K.push(k) - 1] = v; |
+ else V[i] = v; |
+ } |
+ }; |
+ }, |
+ Promise = window.Promise || function (fn) { |
+ var |
+ notify = [], |
+ done = false, |
+ p = { |
+ 'catch': function () { |
+ return p; |
+ }, |
+ 'then': function (cb) { |
+ notify.push(cb); |
+ if (done) setTimeout(resolve, 1); |
+ return p; |
+ } |
+ } |
+ ; |
+ function resolve(value) { |
+ done = true; |
+ while (notify.length) notify.shift()(value); |
+ } |
+ fn(resolve); |
+ return p; |
+ }, |
+ justCreated = false, |
+ constructors = Dict(null), |
+ waitingList = Dict(null), |
+ nodeNames = new Map(), |
+ secondArgument = function (is) { |
+ return is.toLowerCase(); |
+ }, |
+ |
+ // used to create unique instances |
+ create = Object.create || function Bridge(proto) { |
+ // silly broken polyfill probably ever used but short enough to work |
+ return proto ? ((Bridge.prototype = proto), new Bridge()) : this; |
+ }, |
+ |
+ // will set the prototype if possible |
+ // or copy over all properties |
+ setPrototype = sPO || ( |
+ hasProto ? |
+ function (o, p) { |
+ o.__proto__ = p; |
+ return o; |
+ } : ( |
+ (gOPN && gOPD) ? |
+ (function(){ |
+ function setProperties(o, p) { |
+ for (var |
+ key, |
+ names = gOPN(p), |
+ i = 0, length = names.length; |
+ i < length; i++ |
+ ) { |
+ key = names[i]; |
+ if (!hOP.call(o, key)) { |
+ defineProperty(o, key, gOPD(p, key)); |
+ } |
+ } |
+ } |
+ return function (o, p) { |
+ do { |
+ setProperties(o, p); |
+ } while ((p = gPO(p)) && !iPO.call(p, o)); |
+ return o; |
+ }; |
+ }()) : |
+ function (o, p) { |
+ for (var key in p) { |
+ o[key] = p[key]; |
+ } |
+ return o; |
+ } |
+ )), |
+ |
+ // DOM shortcuts and helpers, if any |
+ |
+ MutationObserver = window.MutationObserver || |
+ window.WebKitMutationObserver, |
+ |
+ HTMLElementPrototype = ( |
+ window.HTMLElement || |
+ window.Element || |
+ window.Node |
+ ).prototype, |
+ |
+ IE8 = !iPO.call(HTMLElementPrototype, documentElement), |
+ |
+ safeProperty = IE8 ? function (o, k, d) { |
+ o[k] = d.value; |
+ return o; |
+ } : defineProperty, |
+ |
+ isValidNode = IE8 ? |
+ function (node) { |
+ return node.nodeType === 1; |
+ } : |
+ function (node) { |
+ return iPO.call(HTMLElementPrototype, node); |
+ }, |
+ |
+ targets = IE8 && [], |
+ |
+ attachShadow = HTMLElementPrototype.attachShadow, |
+ cloneNode = HTMLElementPrototype.cloneNode, |
+ dispatchEvent = HTMLElementPrototype.dispatchEvent, |
+ getAttribute = HTMLElementPrototype.getAttribute, |
+ hasAttribute = HTMLElementPrototype.hasAttribute, |
+ removeAttribute = HTMLElementPrototype.removeAttribute, |
+ setAttribute = HTMLElementPrototype.setAttribute, |
+ |
+ // replaced later on |
+ createElement = document.createElement, |
+ patchedCreateElement = createElement, |
+ |
+ // shared observer for all attributes |
+ attributesObserver = MutationObserver && { |
+ attributes: true, |
+ characterData: true, |
+ attributeOldValue: true |
+ }, |
+ |
+ // useful to detect only if there's no MutationObserver |
+ DOMAttrModified = MutationObserver || function(e) { |
+ doesNotSupportDOMAttrModified = false; |
+ documentElement.removeEventListener( |
+ DOM_ATTR_MODIFIED, |
+ DOMAttrModified |
+ ); |
+ }, |
+ |
+ // will both be used to make DOMNodeInserted asynchronous |
+ asapQueue, |
+ asapTimer = 0, |
+ |
+ // internal flags |
+ V0 = REGISTER_ELEMENT in document && |
+ !/^force-all/.test(polyfill.type), |
+ setListener = true, |
+ justSetup = false, |
+ doesNotSupportDOMAttrModified = true, |
+ dropDomContentLoaded = true, |
+ |
+ // needed for the innerHTML helper |
+ notFromInnerHTMLHelper = true, |
+ |
+ // optionally defined later on |
+ onSubtreeModified, |
+ callDOMAttrModified, |
+ getAttributesMirror, |
+ observer, |
+ observe, |
+ |
+ // based on setting prototype capability |
+ // will check proto or the expando attribute |
+ // in order to setup the node once |
+ patchIfNotAlready, |
+ patch |
+ ; |
+ |
+ // only if needed |
+ if (!V0) { |
+ |
+ if (sPO || hasProto) { |
+ patchIfNotAlready = function (node, proto) { |
+ if (!iPO.call(proto, node)) { |
+ setupNode(node, proto); |
+ } |
+ }; |
+ patch = setupNode; |
+ } else { |
+ patchIfNotAlready = function (node, proto) { |
+ if (!node[EXPANDO_UID]) { |
+ node[EXPANDO_UID] = Object(true); |
+ setupNode(node, proto); |
+ } |
+ }; |
+ patch = patchIfNotAlready; |
+ } |
+ |
+ if (IE8) { |
+ doesNotSupportDOMAttrModified = false; |
+ (function (){ |
+ var |
+ descriptor = gOPD(HTMLElementPrototype, ADD_EVENT_LISTENER), |
+ addEventListener = descriptor.value, |
+ patchedRemoveAttribute = function (name) { |
+ var e = new CustomEvent(DOM_ATTR_MODIFIED, {bubbles: true}); |
+ e.attrName = name; |
+ e.prevValue = getAttribute.call(this, name); |
+ e.newValue = null; |
+ e[REMOVAL] = e.attrChange = 2; |
+ removeAttribute.call(this, name); |
+ dispatchEvent.call(this, e); |
+ }, |
+ patchedSetAttribute = function (name, value) { |
+ var |
+ had = hasAttribute.call(this, name), |
+ old = had && getAttribute.call(this, name), |
+ e = new CustomEvent(DOM_ATTR_MODIFIED, {bubbles: true}) |
+ ; |
+ setAttribute.call(this, name, value); |
+ e.attrName = name; |
+ e.prevValue = had ? old : null; |
+ e.newValue = value; |
+ if (had) { |
+ e[MODIFICATION] = e.attrChange = 1; |
+ } else { |
+ e[ADDITION] = e.attrChange = 0; |
+ } |
+ dispatchEvent.call(this, e); |
+ }, |
+ onPropertyChange = function (e) { |
+ // jshint eqnull:true |
+ var |
+ node = e.currentTarget, |
+ superSecret = node[EXPANDO_UID], |
+ propertyName = e.propertyName, |
+ event |
+ ; |
+ if (superSecret.hasOwnProperty(propertyName)) { |
+ superSecret = superSecret[propertyName]; |
+ event = new CustomEvent(DOM_ATTR_MODIFIED, {bubbles: true}); |
+ event.attrName = superSecret.name; |
+ event.prevValue = superSecret.value || null; |
+ event.newValue = (superSecret.value = node[propertyName] || null); |
+ if (event.prevValue == null) { |
+ event[ADDITION] = event.attrChange = 0; |
+ } else { |
+ event[MODIFICATION] = event.attrChange = 1; |
+ } |
+ dispatchEvent.call(node, event); |
+ } |
+ } |
+ ; |
+ descriptor.value = function (type, handler, capture) { |
+ if ( |
+ type === DOM_ATTR_MODIFIED && |
+ this[ATTRIBUTE_CHANGED_CALLBACK] && |
+ this.setAttribute !== patchedSetAttribute |
+ ) { |
+ this[EXPANDO_UID] = { |
+ className: { |
+ name: 'class', |
+ value: this.className |
+ } |
+ }; |
+ this.setAttribute = patchedSetAttribute; |
+ this.removeAttribute = patchedRemoveAttribute; |
+ addEventListener.call(this, 'propertychange', onPropertyChange); |
+ } |
+ addEventListener.call(this, type, handler, capture); |
+ }; |
+ defineProperty(HTMLElementPrototype, ADD_EVENT_LISTENER, descriptor); |
+ }()); |
+ } else if (!MutationObserver) { |
+ documentElement[ADD_EVENT_LISTENER](DOM_ATTR_MODIFIED, DOMAttrModified); |
+ documentElement.setAttribute(EXPANDO_UID, 1); |
+ documentElement.removeAttribute(EXPANDO_UID); |
+ if (doesNotSupportDOMAttrModified) { |
+ onSubtreeModified = function (e) { |
+ var |
+ node = this, |
+ oldAttributes, |
+ newAttributes, |
+ key |
+ ; |
+ if (node === e.target) { |
+ oldAttributes = node[EXPANDO_UID]; |
+ node[EXPANDO_UID] = (newAttributes = getAttributesMirror(node)); |
+ for (key in newAttributes) { |
+ if (!(key in oldAttributes)) { |
+ // attribute was added |
+ return callDOMAttrModified( |
+ 0, |
+ node, |
+ key, |
+ oldAttributes[key], |
+ newAttributes[key], |
+ ADDITION |
+ ); |
+ } else if (newAttributes[key] !== oldAttributes[key]) { |
+ // attribute was changed |
+ return callDOMAttrModified( |
+ 1, |
+ node, |
+ key, |
+ oldAttributes[key], |
+ newAttributes[key], |
+ MODIFICATION |
+ ); |
+ } |
+ } |
+ // checking if it has been removed |
+ for (key in oldAttributes) { |
+ if (!(key in newAttributes)) { |
+ // attribute removed |
+ return callDOMAttrModified( |
+ 2, |
+ node, |
+ key, |
+ oldAttributes[key], |
+ newAttributes[key], |
+ REMOVAL |
+ ); |
+ } |
+ } |
+ } |
+ }; |
+ callDOMAttrModified = function ( |
+ attrChange, |
+ currentTarget, |
+ attrName, |
+ prevValue, |
+ newValue, |
+ action |
+ ) { |
+ var e = { |
+ attrChange: attrChange, |
+ currentTarget: currentTarget, |
+ attrName: attrName, |
+ prevValue: prevValue, |
+ newValue: newValue |
+ }; |
+ e[action] = attrChange; |
+ onDOMAttrModified(e); |
+ }; |
+ getAttributesMirror = function (node) { |
+ for (var |
+ attr, name, |
+ result = {}, |
+ attributes = node.attributes, |
+ i = 0, length = attributes.length; |
+ i < length; i++ |
+ ) { |
+ attr = attributes[i]; |
+ name = attr.name; |
+ if (name !== 'setAttribute') { |
+ result[name] = attr.value; |
+ } |
+ } |
+ return result; |
+ }; |
+ } |
+ } |
+ |
+ // set as enumerable, writable and configurable |
+ document[REGISTER_ELEMENT] = function registerElement(type, options) { |
+ upperType = type.toUpperCase(); |
+ if (setListener) { |
+ // only first time document.registerElement is used |
+ // we need to set this listener |
+ // setting it by default might slow down for no reason |
+ setListener = false; |
+ if (MutationObserver) { |
+ observer = (function(attached, detached){ |
+ function checkEmAll(list, callback) { |
+ for (var i = 0, length = list.length; i < length; callback(list[i++])){} |
+ } |
+ return new MutationObserver(function (records) { |
+ for (var |
+ current, node, newValue, |
+ i = 0, length = records.length; i < length; i++ |
+ ) { |
+ current = records[i]; |
+ if (current.type === 'childList') { |
+ checkEmAll(current.addedNodes, attached); |
+ checkEmAll(current.removedNodes, detached); |
+ } else { |
+ node = current.target; |
+ if (notFromInnerHTMLHelper && |
+ node[ATTRIBUTE_CHANGED_CALLBACK] && |
+ current.attributeName !== 'style') { |
+ newValue = getAttribute.call(node, current.attributeName); |
+ if (newValue !== current.oldValue) { |
+ node[ATTRIBUTE_CHANGED_CALLBACK]( |
+ current.attributeName, |
+ current.oldValue, |
+ newValue |
+ ); |
+ } |
+ } |
+ } |
+ } |
+ }); |
+ }(executeAction(ATTACHED), executeAction(DETACHED))); |
+ observe = function (node) { |
+ observer.observe( |
+ node, |
+ { |
+ childList: true, |
+ subtree: true |
+ } |
+ ); |
+ return node; |
+ }; |
+ observe(document); |
+ if (attachShadow) { |
+ HTMLElementPrototype.attachShadow = function () { |
+ return observe(attachShadow.apply(this, arguments)); |
+ }; |
+ } |
+ } else { |
+ asapQueue = []; |
+ document[ADD_EVENT_LISTENER]('DOMNodeInserted', onDOMNode(ATTACHED)); |
+ document[ADD_EVENT_LISTENER]('DOMNodeRemoved', onDOMNode(DETACHED)); |
+ } |
+ |
+ document[ADD_EVENT_LISTENER](DOM_CONTENT_LOADED, onReadyStateChange); |
+ document[ADD_EVENT_LISTENER]('readystatechange', onReadyStateChange); |
+ |
+ HTMLElementPrototype.cloneNode = function (deep) { |
+ var |
+ node = cloneNode.call(this, !!deep), |
+ i = getTypeIndex(node) |
+ ; |
+ if (-1 < i) patch(node, protos[i]); |
+ if (deep && query.length) loopAndSetup(node.querySelectorAll(query)); |
+ return node; |
+ }; |
+ } |
+ |
+ if (justSetup) return (justSetup = false); |
+ |
+ if (-2 < ( |
+ indexOf.call(types, PREFIX_IS + upperType) + |
+ indexOf.call(types, PREFIX_TAG + upperType) |
+ )) { |
+ throwTypeError(type); |
+ } |
+ |
+ if (!validName.test(upperType) || -1 < indexOf.call(invalidNames, upperType)) { |
+ throw new Error('The type ' + type + ' is invalid'); |
+ } |
+ |
+ var |
+ constructor = function () { |
+ return extending ? |
+ document.createElement(nodeName, upperType) : |
+ document.createElement(nodeName); |
+ }, |
+ opt = options || OP, |
+ extending = hOP.call(opt, EXTENDS), |
+ nodeName = extending ? options[EXTENDS].toUpperCase() : upperType, |
+ upperType, |
+ i |
+ ; |
+ |
+ if (extending && -1 < ( |
+ indexOf.call(types, PREFIX_TAG + nodeName) |
+ )) { |
+ throwTypeError(nodeName); |
+ } |
+ |
+ i = types.push((extending ? PREFIX_IS : PREFIX_TAG) + upperType) - 1; |
+ |
+ query = query.concat( |
+ query.length ? ',' : '', |
+ extending ? nodeName + '[is="' + type.toLowerCase() + '"]' : nodeName |
+ ); |
+ |
+ constructor.prototype = ( |
+ protos[i] = hOP.call(opt, 'prototype') ? |
+ opt.prototype : |
+ create(HTMLElementPrototype) |
+ ); |
+ |
+ if (query.length) loopAndVerify( |
+ document.querySelectorAll(query), |
+ ATTACHED |
+ ); |
+ |
+ return constructor; |
+ }; |
+ |
+ document.createElement = (patchedCreateElement = function (localName, typeExtension) { |
+ var |
+ is = getIs(typeExtension), |
+ node = is ? |
+ createElement.call(document, localName, secondArgument(is)) : |
+ createElement.call(document, localName), |
+ name = '' + localName, |
+ i = indexOf.call( |
+ types, |
+ (is ? PREFIX_IS : PREFIX_TAG) + |
+ (is || name).toUpperCase() |
+ ), |
+ setup = -1 < i |
+ ; |
+ if (is) { |
+ node.setAttribute('is', is = is.toLowerCase()); |
+ if (setup) { |
+ setup = isInQSA(name.toUpperCase(), is); |
+ } |
+ } |
+ notFromInnerHTMLHelper = !document.createElement.innerHTMLHelper; |
+ if (setup) patch(node, protos[i]); |
+ return node; |
+ }); |
+ |
+ } |
+ |
+ function ASAP() { |
+ var queue = asapQueue.splice(0, asapQueue.length); |
+ asapTimer = 0; |
+ while (queue.length) { |
+ queue.shift().call( |
+ null, queue.shift() |
+ ); |
+ } |
+ } |
+ |
+ function loopAndVerify(list, action) { |
+ for (var i = 0, length = list.length; i < length; i++) { |
+ verifyAndSetupAndAction(list[i], action); |
+ } |
+ } |
+ |
+ function loopAndSetup(list) { |
+ for (var i = 0, length = list.length, node; i < length; i++) { |
+ node = list[i]; |
+ patch(node, protos[getTypeIndex(node)]); |
+ } |
+ } |
+ |
+ function executeAction(action) { |
+ return function (node) { |
+ if (isValidNode(node)) { |
+ verifyAndSetupAndAction(node, action); |
+ if (query.length) loopAndVerify( |
+ node.querySelectorAll(query), |
+ action |
+ ); |
+ } |
+ }; |
+ } |
+ |
+ function getTypeIndex(target) { |
+ var |
+ is = getAttribute.call(target, 'is'), |
+ nodeName = target.nodeName.toUpperCase(), |
+ i = indexOf.call( |
+ types, |
+ is ? |
+ PREFIX_IS + is.toUpperCase() : |
+ PREFIX_TAG + nodeName |
+ ) |
+ ; |
+ return is && -1 < i && !isInQSA(nodeName, is) ? -1 : i; |
+ } |
+ |
+ function isInQSA(name, type) { |
+ return -1 < query.indexOf(name + '[is="' + type + '"]'); |
+ } |
+ |
+ function onDOMAttrModified(e) { |
+ var |
+ node = e.currentTarget, |
+ attrChange = e.attrChange, |
+ attrName = e.attrName, |
+ target = e.target, |
+ addition = e[ADDITION] || 2, |
+ removal = e[REMOVAL] || 3 |
+ ; |
+ if (notFromInnerHTMLHelper && |
+ (!target || target === node) && |
+ node[ATTRIBUTE_CHANGED_CALLBACK] && |
+ attrName !== 'style' && ( |
+ e.prevValue !== e.newValue || |
+ // IE9, IE10, and Opera 12 gotcha |
+ e.newValue === '' && ( |
+ attrChange === addition || |
+ attrChange === removal |
+ ) |
+ )) { |
+ node[ATTRIBUTE_CHANGED_CALLBACK]( |
+ attrName, |
+ attrChange === addition ? null : e.prevValue, |
+ attrChange === removal ? null : e.newValue |
+ ); |
+ } |
+ } |
+ |
+ function onDOMNode(action) { |
+ var executor = executeAction(action); |
+ return function (e) { |
+ asapQueue.push(executor, e.target); |
+ if (asapTimer) clearTimeout(asapTimer); |
+ asapTimer = setTimeout(ASAP, 1); |
+ }; |
+ } |
+ |
+ function onReadyStateChange(e) { |
+ if (dropDomContentLoaded) { |
+ dropDomContentLoaded = false; |
+ e.currentTarget.removeEventListener(DOM_CONTENT_LOADED, onReadyStateChange); |
+ } |
+ if (query.length) loopAndVerify( |
+ (e.target || document).querySelectorAll(query), |
+ e.detail === DETACHED ? DETACHED : ATTACHED |
+ ); |
+ if (IE8) purge(); |
+ } |
+ |
+ function patchedSetAttribute(name, value) { |
+ // jshint validthis:true |
+ var self = this; |
+ setAttribute.call(self, name, value); |
+ onSubtreeModified.call(self, {target: self}); |
+ } |
+ |
+ function setupNode(node, proto) { |
+ setPrototype(node, proto); |
+ if (observer) { |
+ observer.observe(node, attributesObserver); |
+ } else { |
+ if (doesNotSupportDOMAttrModified) { |
+ node.setAttribute = patchedSetAttribute; |
+ node[EXPANDO_UID] = getAttributesMirror(node); |
+ node[ADD_EVENT_LISTENER](DOM_SUBTREE_MODIFIED, onSubtreeModified); |
+ } |
+ node[ADD_EVENT_LISTENER](DOM_ATTR_MODIFIED, onDOMAttrModified); |
+ } |
+ if (node[CREATED_CALLBACK] && notFromInnerHTMLHelper) { |
+ node.created = true; |
+ node[CREATED_CALLBACK](); |
+ node.created = false; |
+ } |
+ } |
+ |
+ function purge() { |
+ for (var |
+ node, |
+ i = 0, |
+ length = targets.length; |
+ i < length; i++ |
+ ) { |
+ node = targets[i]; |
+ if (!documentElement.contains(node)) { |
+ length--; |
+ targets.splice(i--, 1); |
+ verifyAndSetupAndAction(node, DETACHED); |
+ } |
+ } |
+ } |
+ |
+ function throwTypeError(type) { |
+ throw new Error('A ' + type + ' type is already registered'); |
+ } |
+ |
+ function verifyAndSetupAndAction(node, action) { |
+ var |
+ fn, |
+ i = getTypeIndex(node), |
+ counterAction |
+ ; |
+ if (-1 < i) { |
+ patchIfNotAlready(node, protos[i]); |
+ i = 0; |
+ if (action === ATTACHED && !node[ATTACHED]) { |
+ node[DETACHED] = false; |
+ node[ATTACHED] = true; |
+ counterAction = 'connected'; |
+ i = 1; |
+ if (IE8 && indexOf.call(targets, node) < 0) { |
+ targets.push(node); |
+ } |
+ } else if (action === DETACHED && !node[DETACHED]) { |
+ node[ATTACHED] = false; |
+ node[DETACHED] = true; |
+ counterAction = 'disconnected'; |
+ i = 1; |
+ } |
+ if (i && (fn = ( |
+ node[action + CALLBACK] || |
+ node[counterAction + CALLBACK] |
+ ))) fn.call(node); |
+ } |
+ } |
+ |
+ |
+ |
+ // V1 in da House! |
+ function CustomElementRegistry() {} |
+ |
+ CustomElementRegistry.prototype = { |
+ constructor: CustomElementRegistry, |
+ // a workaround for the stubborn WebKit |
+ define: usableCustomElements ? |
+ function (name, Class, options) { |
+ if (options) { |
+ CERDefine(name, Class, options); |
+ } else { |
+ var NAME = name.toUpperCase(); |
+ constructors[NAME] = { |
+ constructor: Class, |
+ create: [NAME] |
+ }; |
+ nodeNames.set(Class, NAME); |
+ customElements.define(name, Class); |
+ } |
+ } : |
+ CERDefine, |
+ get: usableCustomElements ? |
+ function (name) { |
+ return customElements.get(name) || get(name); |
+ } : |
+ get, |
+ whenDefined: usableCustomElements ? |
+ function (name) { |
+ return Promise.race([ |
+ customElements.whenDefined(name), |
+ whenDefined(name) |
+ ]); |
+ } : |
+ whenDefined |
+ }; |
+ |
+ function CERDefine(name, Class, options) { |
+ var |
+ is = options && options[EXTENDS] || '', |
+ CProto = Class.prototype, |
+ proto = create(CProto), |
+ attributes = Class.observedAttributes || empty, |
+ definition = {prototype: proto} |
+ ; |
+ // TODO: is this needed at all since it's inherited? |
+ // defineProperty(proto, 'constructor', {value: Class}); |
+ safeProperty(proto, CREATED_CALLBACK, { |
+ value: function () { |
+ if (justCreated) justCreated = false; |
+ else if (!this[DRECEV1]) { |
+ this[DRECEV1] = true; |
+ new Class(this); |
+ if (CProto[CREATED_CALLBACK]) |
+ CProto[CREATED_CALLBACK].call(this); |
+ var info = constructors[nodeNames.get(Class)]; |
+ if (!usableCustomElements || info.create.length > 1) { |
+ notifyAttributes(this); |
+ } |
+ } |
+ } |
+ }); |
+ safeProperty(proto, ATTRIBUTE_CHANGED_CALLBACK, { |
+ value: function (name) { |
+ if (-1 < indexOf.call(attributes, name)) |
+ CProto[ATTRIBUTE_CHANGED_CALLBACK].apply(this, arguments); |
+ } |
+ }); |
+ if (CProto[CONNECTED_CALLBACK]) { |
+ safeProperty(proto, ATTACHED_CALLBACK, { |
+ value: CProto[CONNECTED_CALLBACK] |
+ }); |
+ } |
+ if (CProto[DISCONNECTED_CALLBACK]) { |
+ safeProperty(proto, DETACHED_CALLBACK, { |
+ value: CProto[DISCONNECTED_CALLBACK] |
+ }); |
+ } |
+ if (is) definition[EXTENDS] = is; |
+ name = name.toUpperCase(); |
+ constructors[name] = { |
+ constructor: Class, |
+ create: is ? [is, secondArgument(name)] : [name] |
+ }; |
+ nodeNames.set(Class, name); |
+ document[REGISTER_ELEMENT](name.toLowerCase(), definition); |
+ whenDefined(name); |
+ waitingList[name].r(); |
+ } |
+ |
+ function get(name) { |
+ var info = constructors[name.toUpperCase()]; |
+ return info && info.constructor; |
+ } |
+ |
+ function getIs(options) { |
+ return typeof options === 'string' ? |
+ options : (options && options.is || ''); |
+ } |
+ |
+ function notifyAttributes(self) { |
+ var |
+ callback = self[ATTRIBUTE_CHANGED_CALLBACK], |
+ attributes = callback ? self.attributes : empty, |
+ i = attributes.length, |
+ attribute |
+ ; |
+ while (i--) { |
+ attribute = attributes[i]; // || attributes.item(i); |
+ callback.call( |
+ self, |
+ attribute.name || attribute.nodeName, |
+ null, |
+ attribute.value || attribute.nodeValue |
+ ); |
+ } |
+ } |
+ |
+ function whenDefined(name) { |
+ name = name.toUpperCase(); |
+ if (!(name in waitingList)) { |
+ waitingList[name] = {}; |
+ waitingList[name].p = new Promise(function (resolve) { |
+ waitingList[name].r = resolve; |
+ }); |
+ } |
+ return waitingList[name].p; |
+ } |
+ |
+ function polyfillV1() { |
+ if (customElements) delete window.customElements; |
+ defineProperty(window, 'customElements', { |
+ configurable: true, |
+ value: new CustomElementRegistry() |
+ }); |
+ defineProperty(window, 'CustomElementRegistry', { |
+ configurable: true, |
+ value: CustomElementRegistry |
+ }); |
+ for (var |
+ patchClass = function (name) { |
+ var Class = window[name]; |
+ if (Class) { |
+ window[name] = function CustomElementsV1(self) { |
+ var info, isNative; |
+ if (!self) self = this; |
+ if (!self[DRECEV1]) { |
+ justCreated = true; |
+ info = constructors[nodeNames.get(self.constructor)]; |
+ isNative = usableCustomElements && info.create.length === 1; |
+ self = isNative ? |
+ Reflect.construct(Class, empty, info.constructor) : |
+ document.createElement.apply(document, info.create); |
+ self[DRECEV1] = true; |
+ justCreated = false; |
+ if (!isNative) notifyAttributes(self); |
+ } |
+ return self; |
+ }; |
+ window[name].prototype = Class.prototype; |
+ try { |
+ Class.prototype.constructor = window[name]; |
+ } catch(WebKit) { |
+ fixGetClass = true; |
+ defineProperty(Class, DRECEV1, {value: window[name]}); |
+ } |
+ } |
+ }, |
+ Classes = htmlClass.get(/^HTML[A-Z]*[a-z]/), |
+ i = Classes.length; |
+ i--; |
+ patchClass(Classes[i]) |
+ ) {} |
+ (document.createElement = function (name, options) { |
+ var is = getIs(options); |
+ return is ? |
+ patchedCreateElement.call(this, name, secondArgument(is)) : |
+ patchedCreateElement.call(this, name); |
+ }); |
+ if (!V0) { |
+ justSetup = true; |
+ document[REGISTER_ELEMENT](''); |
+ } |
+ } |
+ |
+ // if customElements is not there at all |
+ if (!customElements || /^force/.test(polyfill.type)) polyfillV1(); |
+ else if(!polyfill.noBuiltIn) { |
+ // if available test extends work as expected |
+ try { |
+ (function (DRE, options, name) { |
+ options[EXTENDS] = 'a'; |
+ DRE.prototype = create(HTMLAnchorElement.prototype); |
+ DRE.prototype.constructor = DRE; |
+ window.customElements.define(name, DRE, options); |
+ if ( |
+ getAttribute.call(document.createElement('a', {is: name}), 'is') !== name || |
+ (usableCustomElements && getAttribute.call(new DRE(), 'is') !== name) |
+ ) { |
+ throw options; |
+ } |
+ }( |
+ function DRE() { |
+ return Reflect.construct(HTMLAnchorElement, [], DRE); |
+ }, |
+ {}, |
+ 'document-register-element-a' |
+ )); |
+ } catch(o_O) { |
+ // or force the polyfill if not |
+ // and keep internal original reference |
+ polyfillV1(); |
+ } |
+ } |
+ |
+ // FireFox only issue |
+ if(!polyfill.noBuiltIn) { |
+ try { |
+ createElement.call(document, 'a', 'a'); |
+ } catch(FireFox) { |
+ secondArgument = function (is) { |
+ return {is: is.toLowerCase()}; |
+ }; |
+ } |
+ } |
+ |
+} |
+ |
+module.exports = installCustomElements; |
+ |
+},{}],3:[function(require,module,exports){ |
+'use strict'; |
+/*! (C) 2017 Andrea Giammarchi - ISC Style License */ |
+ |
+const {Component, bind, define, hyper, wire} = require('hyperhtml/cjs'); |
+ |
+const _init$ = {value: false}; |
+ |
+const defineProperty = Object.defineProperty; |
+ |
+const extend = (target, source) => { |
+ for (const key in source) target[key] = source[key]; |
+}; |
+ |
+class HyperHTMLElement extends HTMLElement { |
+ |
+ // define a custom-element in the CustomElementsRegistry |
+ // class MyEl extends HyperHTMLElement {} |
+ // MyEl.define('my-el'); |
+ static define(name) { |
+ const Class = this; |
+ const proto = Class.prototype; |
+ |
+ // if observedAttributes contains attributes to observe |
+ // HyperHTMLElement will directly reflect get/setAttribute |
+ // operation once these attributes are used, example: |
+ // el.observed = 123; |
+ // will automatically do |
+ // el.setAttribute('observed', 123); |
+ // triggering also the attributeChangedCallback |
+ (Class.observedAttributes || []).forEach(name => { |
+ if (!(name in proto)) defineProperty( |
+ proto, |
+ name.replace(/-([a-z])/g, ($0, $1) => $1.toUpperCase()), |
+ { |
+ configurable: true, |
+ get() { return this.getAttribute(name); }, |
+ set(value) { this.setAttribute(name, value); } |
+ } |
+ ); |
+ }); |
+ |
+ const onChanged = proto.attributeChangedCallback; |
+ const hasChange = !!onChanged; |
+ |
+ // created() {} is the entry point to do whatever you want. |
+ // Once the node is live and upgraded as Custom Element. |
+ // This method grants to be triggered at the right time, |
+ // which is always once, and right before either |
+ // attributeChangedCallback or connectedCallback |
+ const created = proto.created; |
+ if (created) { |
+ // used to ensure create() is called once and once only |
+ defineProperty( |
+ proto, |
+ '_init$', |
+ { |
+ configurable: true, |
+ writable: true, |
+ value: true |
+ } |
+ ); |
+ |
+ // ⚠️ if you need to overwrite/change attributeChangedCallback method |
+ // at runtime after class definition, be sure you do so |
+ // via Object.defineProperty to preserve its non-enumerable nature. |
+ defineProperty( |
+ proto, |
+ 'attributeChangedCallback', |
+ { |
+ configurable: true, |
+ value(name, prev, curr) { |
+ if (this._init$) { |
+ created.call(defineProperty(this, '_init$', _init$)); |
+ } |
+ // ensure setting same value twice |
+ // won't trigger twice attributeChangedCallback |
+ if (hasChange && prev !== curr) { |
+ onChanged.apply(this, arguments); |
+ } |
+ } |
+ } |
+ ); |
+ |
+ // ⚠️ if you need to overwrite/change connectedCallback method |
+ // at runtime after class definition, be sure you do so |
+ // via Object.defineProperty to preserve its non-enumerable nature. |
+ const onConnected = proto.connectedCallback; |
+ const hasConnect = !!onConnected; |
+ defineProperty( |
+ proto, |
+ 'connectedCallback', |
+ { |
+ configurable: true, |
+ value() { |
+ if (this._init$) { |
+ created.call(defineProperty(this, '_init$', _init$)); |
+ } |
+ if (hasConnect) { |
+ onConnected.apply(this, arguments); |
+ } |
+ } |
+ } |
+ ); |
+ } else if (hasChange) { |
+ // ⚠️ if you need to overwrite/change attributeChangedCallback method |
+ // at runtime after class definition, be sure you do so |
+ // via Object.defineProperty to preserve its non-enumerable nature. |
+ defineProperty( |
+ proto, |
+ 'attributeChangedCallback', |
+ { |
+ configurable: true, |
+ value(name, prev, curr) { |
+ // ensure setting same value twice |
+ // won't trigger twice attributeChangedCallback |
+ if (prev !== curr) { |
+ onChanged.apply(this, arguments); |
+ } |
+ } |
+ } |
+ ); |
+ } |
+ |
+ // define lazily all handlers |
+ // class { handleClick() { ... } |
+ // render() { `<a onclick=${this.handleClick}>` } } |
+ Object.getOwnPropertyNames(proto).forEach(key => { |
+ if (/^handle[A-Z]/.test(key)) { |
+ const _key$ = '_' + key + '$'; |
+ const method = proto[key]; |
+ defineProperty(proto, key, { |
+ configurable: true, |
+ get() { |
+ return this[_key$] || |
+ (this[_key$] = method.bind(this)); |
+ } |
+ }); |
+ } |
+ }); |
+ |
+ // whenever you want to directly use the component itself |
+ // as EventListener, you can pass it directly. |
+ // https://medium.com/@WebReflection/dom-handleevent-a-cross-platform-standard-since-year-2000-5bf17287fd38 |
+ // class Reactive extends HyperHTMLElement { |
+ // oninput(e) { console.log(this, 'changed', e.target.value); } |
+ // render() { this.html`<input oninput="${this}">`; } |
+ // } |
+ if (!('handleEvent' in proto)) { |
+ // ⚠️ if you need to overwrite/change handleEvent method |
+ // at runtime after class definition, be sure you do so |
+ // via Object.defineProperty to preserve its non-enumerable nature. |
+ defineProperty( |
+ proto, |
+ 'handleEvent', |
+ { |
+ configurable: true, |
+ value(event) { |
+ this[ |
+ (event.currentTarget.dataset || {}).call || |
+ ('on' + event.type) |
+ ](event); |
+ } |
+ } |
+ ); |
+ } |
+ |
+ customElements.define(name, Class); |
+ return Class; |
+ } |
+ |
+ // lazily bind once hyperHTML logic |
+ // to either the shadowRoot, if present and open, |
+ // the _shadowRoot property, if set due closed shadow root, |
+ // or the custom-element itself if no Shadow DOM is used. |
+ get html() { |
+ return this._html$ || (this.html = bind( |
+ // in case of Shadow DOM {mode: "open"}, use it |
+ this.shadowRoot || |
+ // in case of Shadow DOM {mode: "close"}, use it |
+ // this needs the following reference created upfront |
+ // this._shadowRoot = this.attachShadow({mode: "close"}); |
+ this._shadowRoot || |
+ // if no Shadow DOM is used, simply use the component |
+ // as container for its own content (it just works too) |
+ this |
+ )); |
+ } |
+ |
+ // it can be set too if necessary, it won't invoke render() |
+ set html(value) { |
+ defineProperty(this, '_html$', {configurable: true, value: value}); |
+ } |
+ |
+ // ---------------------// |
+ // Basic State Handling // |
+ // ---------------------// |
+ |
+ // overwrite this method with your own render |
+ render() {} |
+ |
+ // define the default state object |
+ // you could use observed properties too |
+ get defaultState() { return {}; } |
+ |
+ // the state with a default |
+ get state() { |
+ return this._state$ || (this.state = this.defaultState); |
+ } |
+ |
+ // it can be set too if necessary, it won't invoke render() |
+ set state(value) { |
+ defineProperty(this, '_state$', {configurable: true, value: value}); |
+ } |
+ |
+ // currently a state is a shallow copy, like in Preact or other libraries. |
+ // after the state is updated, the render() method will be invoked. |
+ // ⚠️ do not ever call this.setState() inside this.render() |
+ setState(state) { |
+ extend( |
+ this.state, |
+ typeof state === 'function' ? |
+ state.call(this, this.state) : state |
+ ); |
+ this.render(); |
+ } |
+ |
+}; |
+ |
+// exposing hyperHTML utilities |
+HyperHTMLElement.Component = Component; |
+HyperHTMLElement.bind = bind; |
+HyperHTMLElement.intent = define; |
+HyperHTMLElement.wire = wire; |
+HyperHTMLElement.hyper = hyper; |
+ |
+Object.defineProperty(exports, '__esModule', {value: true}).default = HyperHTMLElement; |
+ |
+},{"hyperhtml/cjs":8}],4:[function(require,module,exports){ |
+'use strict'; |
+const { UID } = require('../shared/constants.js'); |
+const { WeakMap } = require('../shared/poorlyfills.js'); |
+ |
+// hyperHTML.Component is a very basic class |
+// able to create Custom Elements like components |
+// including the ability to listen to connect/disconnect |
+// events via onconnect/ondisconnect attributes |
+// Components can be created imperatively or declaratively. |
+// The main difference is that declared components |
+// will not automatically render on setState(...) |
+// to simplify state handling on render. |
+function Component() {} |
+Object.defineProperty(exports, '__esModule', {value: true}).default = Component |
+ |
+// components will lazily define html or svg properties |
+// as soon as these are invoked within the .render() method |
+// Such render() method is not provided by the base class |
+// but it must be available through the Component extend. |
+// Declared components could implement a |
+// render(props) method too and use props as needed. |
+function setup(content) { |
+ const children = new WeakMap; |
+ const create = Object.create; |
+ const createEntry = (wm, id, component) => { |
+ wm.set(id, component); |
+ return component; |
+ }; |
+ const get = (Class, info, id) => { |
+ switch (typeof id) { |
+ case 'object': |
+ case 'function': |
+ const wm = info.w || (info.w = new WeakMap); |
+ return wm.get(id) || createEntry(wm, id, new Class); |
+ default: |
+ const sm = info.p || (info.p = create(null)); |
+ return sm[id] || (sm[id] = new Class); |
+ } |
+ }; |
+ const set = context => { |
+ const info = {w: null, p: null}; |
+ children.set(context, info); |
+ return info; |
+ }; |
+ Object.defineProperties( |
+ Component, |
+ { |
+ for: { |
+ configurable: true, |
+ value(context, id) { |
+ const info = children.get(context) || set(context); |
+ return get(this, info, id == null ? 'default' : id); |
+ } |
+ } |
+ } |
+ ); |
+ Object.defineProperties( |
+ Component.prototype, |
+ { |
+ handleEvent: {value(e) { |
+ const ct = e.currentTarget; |
+ this[ |
+ ('getAttribute' in ct && ct.getAttribute('data-call')) || |
+ ('on' + e.type) |
+ ](e); |
+ }}, |
+ html: lazyGetter('html', content), |
+ svg: lazyGetter('svg', content), |
+ state: lazyGetter('state', function () { return this.defaultState; }), |
+ defaultState: {get() { return {}; }}, |
+ setState: {value(state, render) { |
+ const target = this.state; |
+ const source = typeof state === 'function' ? state.call(this, target) : state; |
+ for (const key in source) target[key] = source[key]; |
+ if (render !== false) this.render(); |
+ return this; |
+ }} |
+ } |
+ ); |
+} |
+exports.setup = setup |
+ |
+// instead of a secret key I could've used a WeakMap |
+// However, attaching a property directly will result |
+// into better performance with thousands of components |
+// hanging around, and less memory pressure caused by the WeakMap |
+const lazyGetter = (type, fn) => { |
+ const secret = '_' + type + '$'; |
+ return { |
+ get() { |
+ return this[secret] || (this[type] = fn.call(this, type)); |
+ }, |
+ set(value) { |
+ Object.defineProperty(this, secret, {configurable: true, value}); |
+ } |
+ }; |
+}; |
+ |
+},{"../shared/constants.js":13,"../shared/poorlyfills.js":17}],5:[function(require,module,exports){ |
+'use strict'; |
+const { append } = require('../shared/utils.js'); |
+const { doc, fragment } = require('../shared/easy-dom.js'); |
+ |
+function Wire(childNodes) { |
+ this.childNodes = childNodes; |
+ this.length = childNodes.length; |
+ this.first = childNodes[0]; |
+ this.last = childNodes[this.length - 1]; |
+} |
+Object.defineProperty(exports, '__esModule', {value: true}).default = Wire |
+ |
+// when a wire is inserted, all its nodes will follow |
+Wire.prototype.insert = function insert() { |
+ const df = fragment(this.first); |
+ append(df, this.childNodes); |
+ return df; |
+}; |
+ |
+// when a wire is removed, all its nodes must be removed as well |
+Wire.prototype.remove = function remove() { |
+ const first = this.first; |
+ const last = this.last; |
+ if (this.length === 2) { |
+ last.parentNode.removeChild(last); |
+ } else { |
+ const range = doc(first).createRange(); |
+ range.setStartBefore(this.childNodes[1]); |
+ range.setEndAfter(last); |
+ range.deleteContents(); |
+ } |
+ return first; |
+}; |
+ |
+},{"../shared/easy-dom.js":15,"../shared/utils.js":19}],6:[function(require,module,exports){ |
+'use strict'; |
+const {Map, WeakMap} = require('../shared/poorlyfills.js'); |
+const {UIDC, VOID_ELEMENTS} = require('../shared/constants.js'); |
+const Updates = (m => m.__esModule ? m.default : m)(require('../objects/Updates.js')); |
+const { |
+ createFragment, |
+ importNode, |
+ unique |
+} = require('../shared/utils.js'); |
+ |
+const {selfClosing} = require('../shared/re.js'); |
+ |
+// a weak collection of contexts that |
+// are already known to hyperHTML |
+const bewitched = new WeakMap; |
+ |
+// the collection of all template literals |
+// since these are unique and immutable |
+// for the whole application life-cycle |
+const templates = new Map; |
+ |
+// better known as hyper.bind(node), the render is |
+// the main tag function in charge of fully upgrading |
+// or simply updating, contexts used as hyperHTML targets. |
+// The `this` context is either a regular DOM node or a fragment. |
+function render(template) { |
+ const wicked = bewitched.get(this); |
+ if (wicked && wicked.template === unique(template)) { |
+ update.apply(wicked.updates, arguments); |
+ } else { |
+ upgrade.apply(this, arguments); |
+ } |
+ return this; |
+} |
+ |
+// an upgrade is in charge of collecting template info, |
+// parse it once, if unknown, to map all interpolations |
+// as single DOM callbacks, relate such template |
+// to the current context, and render it after cleaning the context up |
+function upgrade(template) { |
+ template = unique(template); |
+ const info = templates.get(template) || |
+ createTemplate.call(this, template); |
+ const fragment = importNode(this.ownerDocument, info.fragment); |
+ const updates = Updates.create(fragment, info.paths); |
+ bewitched.set(this, {template, updates}); |
+ update.apply(updates, arguments); |
+ this.textContent = ''; |
+ this.appendChild(fragment); |
+} |
+ |
+// an update simply loops over all mapped DOM operations |
+function update() { |
+ const length = arguments.length; |
+ for (let i = 1; i < length; i++) { |
+ this[i - 1](arguments[i]); |
+ } |
+} |
+ |
+// a template can be used to create a document fragment |
+// aware of all interpolations and with a list |
+// of paths used to find once those nodes that need updates, |
+// no matter if these are attributes, text nodes, or regular one |
+function createTemplate(template) { |
+ const paths = []; |
+ const html = template.join(UIDC).replace(SC_RE, SC_PLACE); |
+ const fragment = createFragment(this, html); |
+ Updates.find(fragment, paths, template.slice()); |
+ const info = {fragment, paths}; |
+ templates.set(template, info); |
+ return info; |
+} |
+ |
+// some node could be special though, like a custom element |
+// with a self closing tag, which should work through these changes. |
+const SC_RE = selfClosing; |
+const SC_PLACE = ($0, $1, $2) => { |
+ return VOID_ELEMENTS.test($1) ? $0 : ('<' + $1 + $2 + '></' + $1 + '>'); |
+}; |
+ |
+Object.defineProperty(exports, '__esModule', {value: true}).default = render; |
+ |
+},{"../objects/Updates.js":12,"../shared/constants.js":13,"../shared/poorlyfills.js":17,"../shared/re.js":18,"../shared/utils.js":19}],7:[function(require,module,exports){ |
+'use strict'; |
+const {ELEMENT_NODE, SVG_NAMESPACE} = require('../shared/constants.js'); |
+const {WeakMap, trim} = require('../shared/poorlyfills.js'); |
+const {fragment} = require('../shared/easy-dom.js'); |
+const {append, slice, unique} = require('../shared/utils.js'); |
+const Wire = (m => m.__esModule ? m.default : m)(require('../classes/Wire.js')); |
+const render = (m => m.__esModule ? m.default : m)(require('./render.js')); |
+ |
+// all wires used per each context |
+const wires = new WeakMap; |
+ |
+// A wire is a callback used as tag function |
+// to lazily relate a generic object to a template literal. |
+// hyper.wire(user)`<div id=user>${user.name}</div>`; => the div#user |
+// This provides the ability to have a unique DOM structure |
+// related to a unique JS object through a reusable template literal. |
+// A wire can specify a type, as svg or html, and also an id |
+// via html:id or :id convention. Such :id allows same JS objects |
+// to be associated to different DOM structures accordingly with |
+// the used template literal without losing previously rendered parts. |
+const wire = (obj, type) => obj == null ? |
+ content(type || 'html') : |
+ weakly(obj, type || 'html'); |
+ |
+// A wire content is a virtual reference to one or more nodes. |
+// It's represented by either a DOM node, or an Array. |
+// In both cases, the wire content role is to simply update |
+// all nodes through the list of related callbacks. |
+// In few words, a wire content is like an invisible parent node |
+// in charge of updating its content like a bound element would do. |
+const content = type => { |
+ let wire, container, content, template, updates; |
+ return function (statics) { |
+ statics = unique(statics); |
+ let setup = template !== statics; |
+ if (setup) { |
+ template = statics; |
+ content = fragment(document); |
+ container = type === 'svg' ? |
+ document.createElementNS(SVG_NAMESPACE, 'svg') : |
+ content; |
+ updates = render.bind(container); |
+ } |
+ updates.apply(null, arguments); |
+ if (setup) { |
+ if (type === 'svg') { |
+ append(content, slice.call(container.childNodes)); |
+ } |
+ wire = wireContent(content); |
+ } |
+ return wire; |
+ }; |
+}; |
+ |
+// wires are weakly created through objects. |
+// Each object can have multiple wires associated |
+// and this is thanks to the type + :id feature. |
+const weakly = (obj, type) => { |
+ const i = type.indexOf(':'); |
+ let wire = wires.get(obj); |
+ let id = type; |
+ if (-1 < i) { |
+ id = type.slice(i + 1); |
+ type = type.slice(0, i) || 'html'; |
+ } |
+ if (!wire) wires.set(obj, wire = {}); |
+ return wire[id] || (wire[id] = content(type)); |
+}; |
+ |
+// a document fragment loses its nodes as soon |
+// as it's appended into another node. |
+// This would easily lose wired content |
+// so that on a second render call, the parent |
+// node wouldn't know which node was there |
+// associated to the interpolation. |
+// To prevent hyperHTML to forget about wired nodes, |
+// these are either returned as Array or, if there's ony one entry, |
+// as single referenced node that won't disappear from the fragment. |
+// The initial fragment, at this point, would be used as unique reference. |
+const wireContent = node => { |
+ const childNodes = node.childNodes; |
+ const length = childNodes.length; |
+ const wireNodes = []; |
+ for (let i = 0; i < length; i++) { |
+ let child = childNodes[i]; |
+ if ( |
+ child.nodeType === ELEMENT_NODE || |
+ trim.call(child.textContent).length !== 0 |
+ ) { |
+ wireNodes.push(child); |
+ } |
+ } |
+ return wireNodes.length === 1 ? wireNodes[0] : new Wire(wireNodes); |
+}; |
+ |
+exports.content = content; |
+exports.weakly = weakly; |
+Object.defineProperty(exports, '__esModule', {value: true}).default = wire; |
+ |
+},{"../classes/Wire.js":5,"../shared/constants.js":13,"../shared/easy-dom.js":15,"../shared/poorlyfills.js":17,"../shared/utils.js":19,"./render.js":6}],8:[function(require,module,exports){ |
+'use strict'; |
+/*! (c) Andrea Giammarchi (ISC) */ |
+ |
+const Component = (m => m.__esModule ? m.default : m)(require('./classes/Component.js')); |
+const {setup} = require('./classes/Component.js'); |
+const Intent = (m => m.__esModule ? m.default : m)(require('./objects/Intent.js')); |
+const wire = (m => m.__esModule ? m.default : m)(require('./hyper/wire.js')); |
+const {content, weakly} = require('./hyper/wire.js'); |
+const render = (m => m.__esModule ? m.default : m)(require('./hyper/render.js')); |
+const diff = (m => m.__esModule ? m.default : m)(require('./shared/domdiff.js')); |
+ |
+// all functions are self bound to the right context |
+// you can do the following |
+// const {bind, wire} = hyperHTML; |
+// and use them right away: bind(node)`hello!`; |
+const bind = context => render.bind(context); |
+const define = Intent.define; |
+ |
+hyper.Component = Component; |
+hyper.bind = bind; |
+hyper.define = define; |
+hyper.diff = diff; |
+hyper.hyper = hyper; |
+hyper.wire = wire; |
+ |
+// the wire content is the lazy defined |
+// html or svg property of each hyper.Component |
+setup(content); |
+ |
+// everything is exported directly or through the |
+// hyperHTML callback, when used as top level script |
+exports.Component = Component; |
+exports.bind = bind; |
+exports.define = define; |
+exports.diff = diff; |
+exports.hyper = hyper; |
+exports.wire = wire; |
+ |
+// by default, hyperHTML is a smart function |
+// that "magically" understands what's the best |
+// thing to do with passed arguments |
+function hyper(HTML) { |
+ return arguments.length < 2 ? |
+ (HTML == null ? |
+ content('html') : |
+ (typeof HTML === 'string' ? |
+ hyper.wire(null, HTML) : |
+ ('raw' in HTML ? |
+ content('html')(HTML) : |
+ ('nodeType' in HTML ? |
+ hyper.bind(HTML) : |
+ weakly(HTML, 'html') |
+ ) |
+ ) |
+ )) : |
+ ('raw' in HTML ? |
+ content('html') : hyper.wire |
+ ).apply(null, arguments); |
+} |
+Object.defineProperty(exports, '__esModule', {value: true}).default = hyper |
+ |
+},{"./classes/Component.js":4,"./hyper/render.js":6,"./hyper/wire.js":7,"./objects/Intent.js":9,"./shared/domdiff.js":14}],9:[function(require,module,exports){ |
+'use strict'; |
+const intents = {}; |
+const keys = []; |
+const hasOwnProperty = intents.hasOwnProperty; |
+ |
+let length = 0; |
+ |
+Object.defineProperty(exports, '__esModule', {value: true}).default = { |
+ |
+ // hyperHTML.define('intent', (object, update) => {...}) |
+ // can be used to define a third parts update mechanism |
+ // when every other known mechanism failed. |
+ // hyper.define('user', info => info.name); |
+ // hyper(node)`<p>${{user}}</p>`; |
+ define: (intent, callback) => { |
+ if (!(intent in intents)) { |
+ length = keys.push(intent); |
+ } |
+ intents[intent] = callback; |
+ }, |
+ |
+ // this method is used internally as last resort |
+ // to retrieve a value out of an object |
+ invoke: (object, callback) => { |
+ for (let i = 0; i < length; i++) { |
+ let key = keys[i]; |
+ if (hasOwnProperty.call(object, key)) { |
+ return intents[key](object[key], callback); |
+ } |
+ } |
+ } |
+}; |
+ |
+},{}],10:[function(require,module,exports){ |
+'use strict'; |
+const { |
+ COMMENT_NODE, |
+ DOCUMENT_FRAGMENT_NODE, |
+ ELEMENT_NODE |
+} = require('../shared/constants.js'); |
+ |
+// every template literal interpolation indicates |
+// a precise target in the DOM the template is representing. |
+// `<p id=${'attribute'}>some ${'content'}</p>` |
+// hyperHTML finds only once per template literal, |
+// hence once per entire application life-cycle, |
+// all nodes that are related to interpolations. |
+// These nodes are stored as indexes used to retrieve, |
+// once per upgrade, nodes that will change on each future update. |
+// A path example is [2, 0, 1] representing the operation: |
+// node.childNodes[2].childNodes[0].childNodes[1] |
+// Attributes are addressed via their owner node and their name. |
+const createPath = node => { |
+ const path = []; |
+ let parentNode; |
+ switch (node.nodeType) { |
+ case ELEMENT_NODE: |
+ case DOCUMENT_FRAGMENT_NODE: |
+ parentNode = node; |
+ break; |
+ case COMMENT_NODE: |
+ parentNode = node.parentNode; |
+ prepend(path, parentNode, node); |
+ break; |
+ default: |
+ parentNode = node.ownerElement; |
+ break; |
+ } |
+ for ( |
+ node = parentNode; |
+ (parentNode = parentNode.parentNode); |
+ node = parentNode |
+ ) { |
+ prepend(path, parentNode, node); |
+ } |
+ return path; |
+}; |
+ |
+const prepend = (path, parent, node) => { |
+ path.unshift(path.indexOf.call(parent.childNodes, node)); |
+}; |
+ |
+Object.defineProperty(exports, '__esModule', {value: true}).default = { |
+ create: (type, node, name) => ({type, name, node, path: createPath(node)}), |
+ find: (node, path) => { |
+ const length = path.length; |
+ for (let i = 0; i < length; i++) { |
+ node = node.childNodes[path[i]]; |
+ } |
+ return node; |
+ } |
+} |
+ |
+},{"../shared/constants.js":13}],11:[function(require,module,exports){ |
+'use strict'; |
+// from https://github.com/developit/preact/blob/33fc697ac11762a1cb6e71e9847670d047af7ce5/src/constants.js |
+const IS_NON_DIMENSIONAL = /acit|ex(?:s|g|n|p|$)|rph|ows|mnc|ntw|ine[ch]|zoo|^ord/i; |
+ |
+// style is handled as both string and object |
+// even if the target is an SVG element (consistency) |
+Object.defineProperty(exports, '__esModule', {value: true}).default = (node, original, isSVG) => { |
+ if (isSVG) { |
+ const style = original.cloneNode(true); |
+ style.value = ''; |
+ node.setAttributeNode(style); |
+ return update(style, isSVG); |
+ } |
+ return update(node.style, isSVG); |
+}; |
+ |
+// the update takes care or changing/replacing |
+// only properties that are different or |
+// in case of string, the whole node |
+const update = (style, isSVG) => { |
+ let oldType, oldValue; |
+ return newValue => { |
+ switch (typeof newValue) { |
+ case 'object': |
+ if (newValue) { |
+ if (oldType === 'object') { |
+ if (!isSVG) { |
+ if (oldValue !== newValue) { |
+ for (const key in oldValue) { |
+ if (!(key in newValue)) { |
+ style[key] = ''; |
+ } |
+ } |
+ } |
+ } |
+ } else { |
+ if (isSVG) style.value = ''; |
+ else style.cssText = ''; |
+ } |
+ const info = isSVG ? {} : style; |
+ for (const key in newValue) { |
+ const value = newValue[key]; |
+ info[key] = typeof value === 'number' && |
+ !IS_NON_DIMENSIONAL.test(key) ? |
+ (value + 'px') : value; |
+ } |
+ oldType = 'object'; |
+ if (isSVG) style.value = toStyle((oldValue = info)); |
+ else oldValue = newValue; |
+ break; |
+ } |
+ default: |
+ if (oldValue != newValue) { |
+ oldType = 'string'; |
+ oldValue = newValue; |
+ if (isSVG) style.value = newValue || ''; |
+ else style.cssText = newValue || ''; |
+ } |
+ break; |
+ } |
+ }; |
+}; |
+ |
+const hyphen = /([^A-Z])([A-Z]+)/g; |
+const ized = ($0, $1, $2) => $1 + '-' + $2.toLowerCase(); |
+const toStyle = object => { |
+ const css = []; |
+ for (const key in object) { |
+ css.push(key.replace(hyphen, ized), ':', object[key], ';'); |
+ } |
+ return css.join(''); |
+}; |
+},{}],12:[function(require,module,exports){ |
+'use strict'; |
+const { |
+ CONNECTED, DISCONNECTED, COMMENT_NODE, DOCUMENT_FRAGMENT_NODE, ELEMENT_NODE, TEXT_NODE, OWNER_SVG_ELEMENT, SHOULD_USE_TEXT_CONTENT, UID, UIDC |
+} = require('../shared/constants.js'); |
+ |
+const Component = (m => m.__esModule ? m.default : m)(require('../classes/Component.js')); |
+const Wire = (m => m.__esModule ? m.default : m)(require('../classes/Wire.js')); |
+const Path = (m => m.__esModule ? m.default : m)(require('./Path.js')); |
+const Style = (m => m.__esModule ? m.default : m)(require('./Style.js')); |
+const Intent = (m => m.__esModule ? m.default : m)(require('./Intent.js')); |
+const domdiff = (m => m.__esModule ? m.default : m)(require('../shared/domdiff.js')); |
+const { create: createElement, text } = require('../shared/easy-dom.js'); |
+const { Event, WeakSet, isArray, trim } = require('../shared/poorlyfills.js'); |
+const { createFragment, slice } = require('../shared/utils.js'); |
+ |
+// hyper.Component have a connected/disconnected |
+// mechanism provided by MutationObserver |
+// This weak set is used to recognize components |
+// as DOM node that needs to trigger connected/disconnected events |
+const components = new WeakSet; |
+ |
+// a basic dictionary used to filter already cached attributes |
+// while looking for special hyperHTML values. |
+function Cache() {} |
+Cache.prototype = Object.create(null); |
+ |
+// returns an intent to explicitly inject content as html |
+const asHTML = html => ({html}); |
+ |
+// returns nodes from wires and components |
+const asNode = (item, i) => { |
+ return 'ELEMENT_NODE' in item ? |
+ item : |
+ (item.constructor === Wire ? |
+ // in the Wire case, the content can be |
+ // removed, post-pended, inserted, or pre-pended and |
+ // all these cases are handled by domdiff already |
+ /* istanbul ignore next */ |
+ ((1 / i) < 0 ? |
+ (i ? item.remove() : item.last) : |
+ (i ? item.insert() : item.first)) : |
+ asNode(item.render(), i)); |
+} |
+ |
+// returns true if domdiff can handle the value |
+const canDiff = value => 'ELEMENT_NODE' in value || |
+value instanceof Wire || |
+value instanceof Component; |
+ |
+// updates are created once per context upgrade |
+// within the main render function (../hyper/render.js) |
+// These are an Array of callbacks to invoke passing |
+// each interpolation value. |
+// Updates can be related to any kind of content, |
+// attributes, or special text-only cases such <style> |
+// elements or <textarea> |
+const create = (root, paths) => { |
+ const updates = []; |
+ const length = paths.length; |
+ for (let i = 0; i < length; i++) { |
+ const info = paths[i]; |
+ const node = Path.find(root, info.path); |
+ switch (info.type) { |
+ case 'any': |
+ updates.push(setAnyContent(node, [])); |
+ break; |
+ case 'attr': |
+ updates.push(setAttribute(node, info.name, info.node)); |
+ break; |
+ case 'text': |
+ updates.push(setTextContent(node)); |
+ break; |
+ } |
+ } |
+ return updates; |
+}; |
+ |
+// finding all paths is a one-off operation performed |
+// when a new template literal is used. |
+// The goal is to map all target nodes that will be |
+// used to update content/attributes every time |
+// the same template literal is used to create content. |
+// The result is a list of paths related to the template |
+// with all the necessary info to create updates as |
+// list of callbacks that target directly affected nodes. |
+const find = (node, paths, parts) => { |
+ const childNodes = node.childNodes; |
+ const length = childNodes.length; |
+ for (let i = 0; i < length; i++) { |
+ let child = childNodes[i]; |
+ switch (child.nodeType) { |
+ case ELEMENT_NODE: |
+ findAttributes(child, paths, parts); |
+ find(child, paths, parts); |
+ break; |
+ case COMMENT_NODE: |
+ if (child.textContent === UID) { |
+ parts.shift(); |
+ paths.push( |
+ // basicHTML or other non standard engines |
+ // might end up having comments in nodes |
+ // where they shouldn't, hence this check. |
+ SHOULD_USE_TEXT_CONTENT.test(node.nodeName) ? |
+ Path.create('text', node) : |
+ Path.create('any', child) |
+ ); |
+ } |
+ break; |
+ case TEXT_NODE: |
+ // the following ignore is actually covered by browsers |
+ // only basicHTML ends up on previous COMMENT_NODE case |
+ // instead of TEXT_NODE because it knows nothing about |
+ // special style or textarea behavior |
+ /* istanbul ignore if */ |
+ if ( |
+ SHOULD_USE_TEXT_CONTENT.test(node.nodeName) && |
+ trim.call(child.textContent) === UIDC |
+ ) { |
+ parts.shift(); |
+ paths.push(Path.create('text', node)); |
+ } |
+ break; |
+ } |
+ } |
+}; |
+ |
+// attributes are searched via unique hyperHTML id value. |
+// Despite HTML being case insensitive, hyperHTML is able |
+// to recognize attributes by name in a caseSensitive way. |
+// This plays well with Custom Elements definitions |
+// and also with XML-like environments, without trusting |
+// the resulting DOM but the template literal as the source of truth. |
+// IE/Edge has a funny bug with attributes and these might be duplicated. |
+// This is why there is a cache in charge of being sure no duplicated |
+// attributes are ever considered in future updates. |
+const findAttributes = (node, paths, parts) => { |
+ const cache = new Cache; |
+ const attributes = node.attributes; |
+ const array = slice.call(attributes); |
+ const remove = []; |
+ const length = array.length; |
+ for (let i = 0; i < length; i++) { |
+ const attribute = array[i]; |
+ if (attribute.value === UID) { |
+ const name = attribute.name; |
+ // the following ignore is covered by IE |
+ // and the IE9 double viewBox test |
+ /* istanbul ignore else */ |
+ if (!(name in cache)) { |
+ const realName = parts.shift().replace(/^(?:|[\S\s]*?\s)(\S+?)=['"]?$/, '$1'); |
+ cache[name] = attributes[realName] || |
+ // the following ignore is covered by browsers |
+ // while basicHTML is already case-sensitive |
+ /* istanbul ignore next */ |
+ attributes[realName.toLowerCase()]; |
+ paths.push(Path.create('attr', cache[name], realName)); |
+ } |
+ remove.push(attribute); |
+ } |
+ } |
+ const len = remove.length; |
+ for (let i = 0; i < len; i++) { |
+ node.removeAttributeNode(remove[i]); |
+ } |
+ |
+ // This is a very specific Firefox/Safari issue |
+ // but since it should be a not so common pattern, |
+ // it's probably worth patching regardless. |
+ // Basically, scripts created through strings are death. |
+ // You need to create fresh new scripts instead. |
+ // TODO: is there any other node that needs such nonsense ? |
+ const nodeName = node.nodeName; |
+ if (/^script$/i.test(nodeName)) { |
+ const script = createElement(node, nodeName); |
+ for (let i = 0; i < attributes.length; i++) { |
+ script.setAttributeNode(attributes[i].cloneNode(true)); |
+ } |
+ script.textContent = node.textContent; |
+ node.parentNode.replaceChild(script, node); |
+ } |
+}; |
+ |
+// when a Promise is used as interpolation value |
+// its result must be parsed once resolved. |
+// This callback is in charge of understanding what to do |
+// with a returned value once the promise is resolved. |
+const invokeAtDistance = (value, callback) => { |
+ callback(value.placeholder); |
+ if ('text' in value) { |
+ Promise.resolve(value.text).then(String).then(callback); |
+ } else if ('any' in value) { |
+ Promise.resolve(value.any).then(callback); |
+ } else if ('html' in value) { |
+ Promise.resolve(value.html).then(asHTML).then(callback); |
+ } else { |
+ Promise.resolve(Intent.invoke(value, callback)).then(callback); |
+ } |
+}; |
+ |
+// quick and dirty way to check for Promise/ish values |
+const isPromise_ish = value => value != null && 'then' in value; |
+ |
+// in a hyper(node)`<div>${content}</div>` case |
+// everything could happen: |
+// * it's a JS primitive, stored as text |
+// * it's null or undefined, the node should be cleaned |
+// * it's a component, update the content by rendering it |
+// * it's a promise, update the content once resolved |
+// * it's an explicit intent, perform the desired operation |
+// * it's an Array, resolve all values if Promises and/or |
+// update the node with the resulting list of content |
+const setAnyContent = (node, childNodes) => { |
+ let fastPath = false; |
+ let oldValue; |
+ const anyContent = value => { |
+ switch (typeof value) { |
+ case 'string': |
+ case 'number': |
+ case 'boolean': |
+ if (fastPath) { |
+ if (oldValue !== value) { |
+ oldValue = value; |
+ childNodes[0].textContent = value; |
+ } |
+ } else { |
+ fastPath = true; |
+ oldValue = value; |
+ childNodes = domdiff( |
+ node.parentNode, |
+ childNodes, |
+ [text(node, value)], |
+ asNode, |
+ node |
+ ); |
+ } |
+ break; |
+ case 'object': |
+ case 'undefined': |
+ if (value == null) { |
+ fastPath = false; |
+ childNodes = domdiff( |
+ node.parentNode, |
+ childNodes, |
+ [], |
+ asNode, |
+ node |
+ ); |
+ break; |
+ } |
+ default: |
+ fastPath = false; |
+ oldValue = value; |
+ if (isArray(value)) { |
+ if (value.length === 0) { |
+ if (childNodes.length) { |
+ childNodes = domdiff( |
+ node.parentNode, |
+ childNodes, |
+ [], |
+ asNode, |
+ node |
+ ); |
+ } |
+ } else { |
+ switch (typeof value[0]) { |
+ case 'string': |
+ case 'number': |
+ case 'boolean': |
+ anyContent({html: value}); |
+ break; |
+ case 'object': |
+ if (isArray(value[0])) { |
+ value = value.concat.apply([], value); |
+ } |
+ if (isPromise_ish(value[0])) { |
+ Promise.all(value).then(anyContent); |
+ break; |
+ } |
+ default: |
+ childNodes = domdiff( |
+ node.parentNode, |
+ childNodes, |
+ value, |
+ asNode, |
+ node |
+ ); |
+ break; |
+ } |
+ } |
+ } else if (canDiff(value)) { |
+ childNodes = domdiff( |
+ node.parentNode, |
+ childNodes, |
+ value.nodeType === DOCUMENT_FRAGMENT_NODE ? |
+ slice.call(value.childNodes) : |
+ [value], |
+ asNode, |
+ node |
+ ); |
+ } else if (isPromise_ish(value)) { |
+ value.then(anyContent); |
+ } else if ('placeholder' in value) { |
+ invokeAtDistance(value, anyContent); |
+ } else if ('text' in value) { |
+ anyContent(String(value.text)); |
+ } else if ('any' in value) { |
+ anyContent(value.any); |
+ } else if ('html' in value) { |
+ childNodes = domdiff( |
+ node.parentNode, |
+ childNodes, |
+ slice.call( |
+ createFragment( |
+ node, |
+ [].concat(value.html).join('') |
+ ).childNodes |
+ ), |
+ asNode, |
+ node |
+ ); |
+ } else if ('length' in value) { |
+ anyContent(slice.call(value)); |
+ } else { |
+ anyContent(Intent.invoke(value, anyContent)); |
+ } |
+ break; |
+ } |
+ }; |
+ return anyContent; |
+}; |
+ |
+// there are four kind of attributes, and related behavior: |
+// * events, with a name starting with `on`, to add/remove event listeners |
+// * special, with a name present in their inherited prototype, accessed directly |
+// * regular, accessed through get/setAttribute standard DOM methods |
+// * style, the only regular attribute that also accepts an object as value |
+// so that you can style=${{width: 120}}. In this case, the behavior has been |
+// fully inspired by Preact library and its simplicity. |
+const setAttribute = (node, name, original) => { |
+ const isSVG = OWNER_SVG_ELEMENT in node; |
+ let oldValue; |
+ // if the attribute is the style one |
+ // handle it differently from others |
+ if (name === 'style') { |
+ return Style(node, original, isSVG); |
+ } |
+ // the name is an event one, |
+ // add/remove event listeners accordingly |
+ else if (/^on/.test(name)) { |
+ let type = name.slice(2); |
+ if (type === CONNECTED || type === DISCONNECTED) { |
+ if (notObserving) { |
+ notObserving = false; |
+ observe(); |
+ } |
+ components.add(node); |
+ } |
+ else if (name.toLowerCase() in node) { |
+ type = type.toLowerCase(); |
+ } |
+ return newValue => { |
+ if (oldValue !== newValue) { |
+ if (oldValue) node.removeEventListener(type, oldValue, false); |
+ oldValue = newValue; |
+ if (newValue) node.addEventListener(type, newValue, false); |
+ } |
+ }; |
+ } |
+ // the attribute is special ('value' in input) |
+ // and it's not SVG *or* the name is exactly data, |
+ // in this case assign the value directly |
+ else if (name === 'data' || (!isSVG && name in node)) { |
+ return newValue => { |
+ if (oldValue !== newValue) { |
+ oldValue = newValue; |
+ if (node[name] !== newValue) { |
+ node[name] = newValue; |
+ if (newValue == null) { |
+ node.removeAttribute(name); |
+ } |
+ } |
+ } |
+ }; |
+ } |
+ // in every other case, use the attribute node as it is |
+ // update only the value, set it as node only when/if needed |
+ else { |
+ let owner = false; |
+ const attribute = original.cloneNode(true); |
+ return newValue => { |
+ if (oldValue !== newValue) { |
+ oldValue = newValue; |
+ if (attribute.value !== newValue) { |
+ if (newValue == null) { |
+ if (owner) { |
+ owner = false; |
+ node.removeAttributeNode(attribute); |
+ } |
+ attribute.value = newValue; |
+ } else { |
+ attribute.value = newValue; |
+ if (!owner) { |
+ owner = true; |
+ node.setAttributeNode(attribute); |
+ } |
+ } |
+ } |
+ } |
+ }; |
+ } |
+}; |
+ |
+// style or textareas don't accept HTML as content |
+// it's pointless to transform or analyze anything |
+// different from text there but it's worth checking |
+// for possible defined intents. |
+const setTextContent = node => { |
+ // avoid hyper comments inside textarea/style when value is undefined |
+ let oldValue = ''; |
+ const textContent = value => { |
+ if (oldValue !== value) { |
+ oldValue = value; |
+ if (typeof value === 'object' && value) { |
+ if (isPromise_ish(value)) { |
+ value.then(textContent); |
+ } else if ('placeholder' in value) { |
+ invokeAtDistance(value, textContent); |
+ } else if ('text' in value) { |
+ textContent(String(value.text)); |
+ } else if ('any' in value) { |
+ textContent(value.any); |
+ } else if ('html' in value) { |
+ textContent([].concat(value.html).join('')); |
+ } else if ('length' in value) { |
+ textContent(slice.call(value).join('')); |
+ } else { |
+ textContent(Intent.invoke(value, textContent)); |
+ } |
+ } else { |
+ node.textContent = value == null ? '' : value; |
+ } |
+ } |
+ }; |
+ return textContent; |
+}; |
+ |
+Object.defineProperty(exports, '__esModule', {value: true}).default = {create, find}; |
+ |
+// hyper.Components might need connected/disconnected notifications |
+// used by components and their onconnect/ondisconnect callbacks. |
+// When one of these callbacks is encountered, |
+// the document starts being observed. |
+let notObserving = true; |
+function observe() { |
+ |
+ // when hyper.Component related DOM nodes |
+ // are appended or removed from the live tree |
+ // these might listen to connected/disconnected events |
+ // This utility is in charge of finding all components |
+ // involved in the DOM update/change and dispatch |
+ // related information to them |
+ const dispatchAll = (nodes, type) => { |
+ const event = new Event(type); |
+ const length = nodes.length; |
+ for (let i = 0; i < length; i++) { |
+ let node = nodes[i]; |
+ if (node.nodeType === ELEMENT_NODE) { |
+ dispatchTarget(node, event); |
+ } |
+ } |
+ }; |
+ |
+ // the way it's done is via the components weak set |
+ // and recursively looking for nested components too |
+ const dispatchTarget = (node, event) => { |
+ if (components.has(node)) { |
+ node.dispatchEvent(event); |
+ } |
+ |
+ const children = node.children; |
+ const length = children.length; |
+ for (let i = 0; i < length; i++) { |
+ dispatchTarget(children[i], event); |
+ } |
+ } |
+ |
+ // The MutationObserver is the best way to implement that |
+ // but there is a fallback to deprecated DOMNodeInserted/Removed |
+ // so that even older browsers/engines can help components life-cycle |
+ try { |
+ (new MutationObserver(records => { |
+ const length = records.length; |
+ for (let i = 0; i < length; i++) { |
+ let record = records[i]; |
+ dispatchAll(record.removedNodes, DISCONNECTED); |
+ dispatchAll(record.addedNodes, CONNECTED); |
+ } |
+ })).observe(document, {subtree: true, childList: true}); |
+ } catch(o_O) { |
+ document.addEventListener('DOMNodeRemoved', event => { |
+ dispatchAll([event.target], DISCONNECTED); |
+ }, false); |
+ document.addEventListener('DOMNodeInserted', event => { |
+ dispatchAll([event.target], CONNECTED); |
+ }, false); |
+ } |
+} |
+ |
+},{"../classes/Component.js":4,"../classes/Wire.js":5,"../shared/constants.js":13,"../shared/domdiff.js":14,"../shared/easy-dom.js":15,"../shared/poorlyfills.js":17,"../shared/utils.js":19,"./Intent.js":9,"./Path.js":10,"./Style.js":11}],13:[function(require,module,exports){ |
+'use strict'; |
+const G = document.defaultView; |
+exports.G = G; |
+ |
+// Node.CONSTANTS |
+// 'cause some engine has no global Node defined |
+// (i.e. Node, NativeScript, basicHTML ... ) |
+const ELEMENT_NODE = 1; |
+exports.ELEMENT_NODE = ELEMENT_NODE; |
+const ATTRIBUTE_NODE = 2; |
+exports.ATTRIBUTE_NODE = ATTRIBUTE_NODE; |
+const TEXT_NODE = 3; |
+exports.TEXT_NODE = TEXT_NODE; |
+const COMMENT_NODE = 8; |
+exports.COMMENT_NODE = COMMENT_NODE; |
+const DOCUMENT_FRAGMENT_NODE = 11; |
+exports.DOCUMENT_FRAGMENT_NODE = DOCUMENT_FRAGMENT_NODE; |
+ |
+// HTML related constants |
+const VOID_ELEMENTS = /^area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr$/i; |
+exports.VOID_ELEMENTS = VOID_ELEMENTS; |
+ |
+// SVG related constants |
+const OWNER_SVG_ELEMENT = 'ownerSVGElement'; |
+exports.OWNER_SVG_ELEMENT = OWNER_SVG_ELEMENT; |
+const SVG_NAMESPACE = 'http://www.w3.org/2000/svg'; |
+exports.SVG_NAMESPACE = SVG_NAMESPACE; |
+ |
+// Custom Elements / MutationObserver constants |
+const CONNECTED = 'connected'; |
+exports.CONNECTED = CONNECTED; |
+const DISCONNECTED = 'dis' + CONNECTED; |
+exports.DISCONNECTED = DISCONNECTED; |
+ |
+// hyperHTML related constants |
+const EXPANDO = '_hyper: '; |
+exports.EXPANDO = EXPANDO; |
+const SHOULD_USE_TEXT_CONTENT = /^style|textarea$/i; |
+exports.SHOULD_USE_TEXT_CONTENT = SHOULD_USE_TEXT_CONTENT; |
+const UID = EXPANDO + ((Math.random() * new Date) | 0) + ';'; |
+exports.UID = UID; |
+const UIDC = '<!--' + UID + '-->'; |
+exports.UIDC = UIDC; |
+ |
+},{}],14:[function(require,module,exports){ |
+'use strict'; |
+/* AUTOMATICALLY IMPORTED, DO NOT MODIFY */ |
+/*! (c) 2017 Andrea Giammarchi (ISC) */ |
+ |
+/** |
+ * This code is a revisited port of the snabbdom vDOM diffing logic, |
+ * the same that fuels as fork Vue.js or other libraries. |
+ * @credits https://github.com/snabbdom/snabbdom |
+ */ |
+ |
+const identity = O => O; |
+ |
+const domdiff = ( |
+ parentNode, // where changes happen |
+ currentNodes, // Array of current items/nodes |
+ futureNodes, // Array of future items/nodes |
+ getNode, // optional way to retrieve a node from an item |
+ beforeNode // optional item/node to use as insertBefore delimiter |
+) => { |
+ const get = getNode || identity; |
+ const before = beforeNode == null ? null : get(beforeNode, 0); |
+ let currentStart = 0, futureStart = 0; |
+ let currentEnd = currentNodes.length - 1; |
+ let currentStartNode = currentNodes[0]; |
+ let currentEndNode = currentNodes[currentEnd]; |
+ let futureEnd = futureNodes.length - 1; |
+ let futureStartNode = futureNodes[0]; |
+ let futureEndNode = futureNodes[futureEnd]; |
+ while (currentStart <= currentEnd && futureStart <= futureEnd) { |
+ if (currentStartNode == null) { |
+ currentStartNode = currentNodes[++currentStart]; |
+ } |
+ else if (currentEndNode == null) { |
+ currentEndNode = currentNodes[--currentEnd]; |
+ } |
+ else if (futureStartNode == null) { |
+ futureStartNode = futureNodes[++futureStart]; |
+ } |
+ else if (futureEndNode == null) { |
+ futureEndNode = futureNodes[--futureEnd]; |
+ } |
+ else if (currentStartNode == futureStartNode) { |
+ currentStartNode = currentNodes[++currentStart]; |
+ futureStartNode = futureNodes[++futureStart]; |
+ } |
+ else if (currentEndNode == futureEndNode) { |
+ currentEndNode = currentNodes[--currentEnd]; |
+ futureEndNode = futureNodes[--futureEnd]; |
+ } |
+ else if (currentStartNode == futureEndNode) { |
+ parentNode.insertBefore( |
+ get(currentStartNode, 1), |
+ get(currentEndNode, -0).nextSibling |
+ ); |
+ currentStartNode = currentNodes[++currentStart]; |
+ futureEndNode = futureNodes[--futureEnd]; |
+ } |
+ else if (currentEndNode == futureStartNode) { |
+ parentNode.insertBefore( |
+ get(currentEndNode, 1), |
+ get(currentStartNode, 0) |
+ ); |
+ currentEndNode = currentNodes[--currentEnd]; |
+ futureStartNode = futureNodes[++futureStart]; |
+ } |
+ else { |
+ let index = currentNodes.indexOf(futureStartNode); |
+ if (index < 0) { |
+ parentNode.insertBefore( |
+ get(futureStartNode, 1), |
+ get(currentStartNode, 0) |
+ ); |
+ futureStartNode = futureNodes[++futureStart]; |
+ } |
+ else { |
+ let el = currentNodes[index]; |
+ currentNodes[index] = null; |
+ parentNode.insertBefore( |
+ get(el, 1), |
+ get(currentStartNode, 0) |
+ ); |
+ futureStartNode = futureNodes[++futureStart]; |
+ } |
+ } |
+ } |
+ if (currentStart <= currentEnd || futureStart <= futureEnd) { |
+ if (currentStart > currentEnd) { |
+ const pin = futureNodes[futureEnd + 1]; |
+ const place = pin == null ? before : get(pin, 0); |
+ if (futureStart === futureEnd) { |
+ parentNode.insertBefore(get(futureNodes[futureStart], 1), place); |
+ } |
+ else { |
+ const fragment = parentNode.ownerDocument.createDocumentFragment(); |
+ while (futureStart <= futureEnd) { |
+ fragment.appendChild(get(futureNodes[futureStart++], 1)); |
+ } |
+ parentNode.insertBefore(fragment, place); |
+ } |
+ } |
+ else { |
+ if (currentNodes[currentStart] == null) currentStart++; |
+ if (currentStart === currentEnd) { |
+ parentNode.removeChild(get(currentNodes[currentStart], -1)); |
+ } |
+ else { |
+ const range = parentNode.ownerDocument.createRange(); |
+ range.setStartBefore(get(currentNodes[currentStart], -1)); |
+ range.setEndAfter(get(currentNodes[currentEnd], -1)); |
+ range.deleteContents(); |
+ } |
+ } |
+ } |
+ return futureNodes; |
+}; |
+ |
+Object.defineProperty(exports, '__esModule', {value: true}).default = domdiff; |
+ |
+},{}],15:[function(require,module,exports){ |
+'use strict'; |
+// these are tiny helpers to simplify most common operations needed here |
+const create = (node, type) => doc(node).createElement(type); |
+exports.create = create; |
+const doc = node => node.ownerDocument || node; |
+exports.doc = doc; |
+const fragment = node => doc(node).createDocumentFragment(); |
+exports.fragment = fragment; |
+const text = (node, text) => doc(node).createTextNode(text); |
+exports.text = text; |
+ |
+},{}],16:[function(require,module,exports){ |
+'use strict'; |
+const {create, fragment, text} = require('./easy-dom.js'); |
+ |
+const testFragment = fragment(document); |
+ |
+// DOM4 node.append(...many) |
+const hasAppend = 'append' in testFragment; |
+exports.hasAppend = hasAppend; |
+ |
+// detect old browsers without HTMLTemplateElement content support |
+const hasContent = 'content' in create(document, 'template'); |
+exports.hasContent = hasContent; |
+ |
+// IE 11 has problems with cloning templates: it "forgets" empty childNodes |
+testFragment.appendChild(text(testFragment, 'g')); |
+testFragment.appendChild(text(testFragment, '')); |
+const hasDoomedCloneNode = testFragment.cloneNode(true).childNodes.length === 1; |
+exports.hasDoomedCloneNode = hasDoomedCloneNode; |
+ |
+// old browsers need to fallback to cloneNode |
+// Custom Elements V0 and V1 will work polyfilled |
+// but native implementations need importNode instead |
+// (specially Chromium and its old V0 implementation) |
+const hasImportNode = 'importNode' in document; |
+exports.hasImportNode = hasImportNode; |
+ |
+},{"./easy-dom.js":15}],17:[function(require,module,exports){ |
+'use strict'; |
+const {G, UID} = require('./constants.js'); |
+ |
+// you know that kind of basics you need to cover |
+// your use case only but you don't want to bloat the library? |
+// There's even a package in here: |
+// https://www.npmjs.com/package/poorlyfills |
+ |
+// used to dispatch simple events |
+let Event = G.Event; |
+try { |
+ new Event('Event'); |
+} catch(o_O) { |
+ Event = function (type) { |
+ const e = document.createEvent('Event'); |
+ e.initEvent(type, false, false); |
+ return e; |
+ }; |
+} |
+exports.Event = Event; |
+ |
+// used to store template literals |
+const Map = G.Map || function Map() { |
+ const keys = [], values = []; |
+ return { |
+ get(obj) { |
+ return values[keys.indexOf(obj)]; |
+ }, |
+ set(obj, value) { |
+ values[keys.push(obj) - 1] = value; |
+ } |
+ }; |
+}; |
+exports.Map = Map; |
+ |
+// used to store wired content |
+const WeakMap = G.WeakMap || function WeakMap() { |
+ return { |
+ get(obj) { return obj[UID]; }, |
+ set(obj, value) { |
+ Object.defineProperty(obj, UID, { |
+ configurable: true, |
+ value |
+ }); |
+ } |
+ }; |
+}; |
+exports.WeakMap = WeakMap; |
+ |
+// used to store hyper.Components |
+const WeakSet = G.WeakSet || function WeakSet() { |
+ const wm = new WeakMap; |
+ return { |
+ add(obj) { wm.set(obj, true); }, |
+ has(obj) { return wm.get(obj) === true; } |
+ }; |
+}; |
+exports.WeakSet = WeakSet; |
+ |
+// used to be sure IE9 or older Androids work as expected |
+const isArray = Array.isArray || (toString => |
+ arr => toString.call(arr) === '[object Array]' |
+)({}.toString); |
+exports.isArray = isArray; |
+ |
+const trim = UID.trim || function () { |
+ return this.replace(/^\s+|\s+$/g, ''); |
+}; |
+exports.trim = trim; |
+ |
+},{"./constants.js":13}],18:[function(require,module,exports){ |
+'use strict'; |
+// TODO: I'd love to code-cover RegExp too here |
+// these are fundamental for this library |
+ |
+const spaces = ' \\f\\n\\r\\t'; |
+const almostEverything = '[^ ' + spaces + '\\/>"\'=]+'; |
+const attrName = '[ ' + spaces + ']+' + almostEverything; |
+const tagName = '<([A-Za-z]+[A-Za-z0-9:_-]*)((?:'; |
+const attrPartials = '(?:=(?:\'[^\']*?\'|"[^"]*?"|<[^>]*?>|' + almostEverything + '))?)'; |
+ |
+const attrSeeker = new RegExp( |
+ tagName + attrName + attrPartials + '+)([ ' + spaces + ']*/?>)', |
+ 'g' |
+); |
+ |
+const selfClosing = new RegExp( |
+ tagName + attrName + attrPartials + '*)([ ' + spaces + ']*/>)', |
+ 'g' |
+); |
+ |
+exports.attrName = attrName; |
+exports.attrSeeker = attrSeeker; |
+exports.selfClosing = selfClosing; |
+ |
+},{}],19:[function(require,module,exports){ |
+'use strict'; |
+const {attrName, attrSeeker} = require('./re.js'); |
+ |
+const { |
+ G, |
+ OWNER_SVG_ELEMENT, |
+ SVG_NAMESPACE, |
+ UID, |
+ UIDC |
+} = require('./constants.js'); |
+ |
+const { |
+ hasAppend, |
+ hasContent, |
+ hasDoomedCloneNode, |
+ hasImportNode |
+} = require('./features-detection.js'); |
+ |
+const {create, doc, fragment} = require('./easy-dom.js'); |
+ |
+// appends an array of nodes |
+// to a generic node/fragment |
+// When available, uses append passing all arguments at once |
+// hoping that's somehow faster, even if append has more checks on type |
+const append = hasAppend ? |
+ (node, childNodes) => { |
+ node.append.apply(node, childNodes); |
+ } : |
+ (node, childNodes) => { |
+ const length = childNodes.length; |
+ for (let i = 0; i < length; i++) { |
+ node.appendChild(childNodes[i]); |
+ } |
+ }; |
+exports.append = append; |
+ |
+const findAttributes = new RegExp('(' + attrName + '=)([\'"]?)' + UIDC + '\\2', 'gi'); |
+const comments = ($0, $1, $2, $3) => |
+ '<' + $1 + $2.replace(findAttributes, replaceAttributes) + $3; |
+const replaceAttributes = ($0, $1, $2) => $1 + ($2 || '"') + UID + ($2 || '"'); |
+ |
+// given a node and a generic HTML content, |
+// create either an SVG or an HTML fragment |
+// where such content will be injected |
+const createFragment = (node, html) => |
+ (OWNER_SVG_ELEMENT in node ? |
+ SVGFragment : |
+ HTMLFragment |
+ )(node, html.replace(attrSeeker, comments)); |
+exports.createFragment = createFragment; |
+ |
+// IE/Edge shenanigans proof cloneNode |
+// it goes through all nodes manually |
+// instead of relying the engine to suddenly |
+// merge nodes together |
+const cloneNode = hasDoomedCloneNode ? |
+ node => { |
+ const clone = node.cloneNode(); |
+ const childNodes = node.childNodes || |
+ // this is an excess of caution |
+ // but some node, in IE, might not |
+ // have childNodes property. |
+ // The following fallback ensure working code |
+ // in older IE without compromising performance |
+ // or any other browser/engine involved. |
+ /* istanbul ignore next */ |
+ []; |
+ const length = childNodes.length; |
+ for (let i = 0; i < length; i++) { |
+ clone.appendChild(cloneNode(childNodes[i])); |
+ } |
+ return clone; |
+ } : |
+ // the following ignore is due code-coverage |
+ // combination of not having document.importNode |
+ // but having a working node.cloneNode. |
+ // This shenario is common on older Android/WebKit browsers |
+ // but basicHTML here tests just two major cases: |
+ // with document.importNode or with broken cloneNode. |
+ /* istanbul ignore next */ |
+ node => node.cloneNode(true); |
+ |
+// used to import html into fragments |
+const importNode = hasImportNode ? |
+ (doc, node) => doc.importNode(node, true) : |
+ (doc, node) => cloneNode(node) |
+exports.importNode = importNode |
+ |
+// just recycling a one-off array to use slice |
+// in every needed place |
+const slice = [].slice; |
+exports.slice = slice; |
+ |
+// lazy evaluated, returns the unique identity |
+// of a template literal, as tempalte literal itself. |
+// By default, ES2015 template literals are unique |
+// tag`a${1}z` === tag`a${2}z` |
+// even if interpolated values are different |
+// the template chunks are in a frozen Array |
+// that is identical each time you use the same |
+// literal to represent same static content |
+// around its own interpolations. |
+const unique = template => TL(template); |
+exports.unique = unique; |
+ |
+// TL returns a unique version of the template |
+// it needs lazy feature detection |
+// (cannot trust literals with transpiled code) |
+let TL = template => { |
+ if ( |
+ // TypeScript template literals are not standard |
+ template.propertyIsEnumerable('raw') || |
+ ( |
+ // Firefox < 55 has not standard implementation neither |
+ /Firefox\/(\d+)/.test((G.navigator || {}).userAgent) && |
+ parseFloat(RegExp.$1) < 55 |
+ ) |
+ ) { |
+ // in these cases, address templates once |
+ const templateObjects = {}; |
+ // but always return the same template |
+ TL = template => { |
+ const key = '_' + template.join(UID); |
+ return templateObjects[key] || ( |
+ templateObjects[key] = template |
+ ); |
+ }; |
+ } |
+ else { |
+ // make TL an identity like function |
+ TL = template => template; |
+ } |
+ return TL(template); |
+}; |
+ |
+// create document fragments via native template |
+// with a fallback for browsers that won't be able |
+// to deal with some injected element such <td> or others |
+const HTMLFragment = hasContent ? |
+ (node, html) => { |
+ const container = create(node, 'template'); |
+ container.innerHTML = html; |
+ return container.content; |
+ } : |
+ (node, html) => { |
+ const container = create(node, 'template'); |
+ const content = fragment(node); |
+ if (/^[^\S]*?<(col(?:group)?|t(?:head|body|foot|r|d|h))/i.test(html)) { |
+ const selector = RegExp.$1; |
+ container.innerHTML = '<table>' + html + '</table>'; |
+ append(content, slice.call(container.querySelectorAll(selector))); |
+ } else { |
+ container.innerHTML = html; |
+ append(content, slice.call(container.childNodes)); |
+ } |
+ return content; |
+ }; |
+ |
+// creates SVG fragment with a fallback for IE that needs SVG |
+// within the HTML content |
+const SVGFragment = hasContent ? |
+ (node, html) => { |
+ const content = fragment(node); |
+ const container = doc(node).createElementNS(SVG_NAMESPACE, 'svg'); |
+ container.innerHTML = html; |
+ append(content, slice.call(container.childNodes)); |
+ return content; |
+ } : |
+ (node, html) => { |
+ const content = fragment(node); |
+ const container = create(node, 'div'); |
+ container.innerHTML = '<svg xmlns="' + SVG_NAMESPACE + '">' + html + '</svg>'; |
+ append(content, slice.call(container.firstChild.childNodes)); |
+ return content; |
+ }; |
+ |
+},{"./constants.js":13,"./easy-dom.js":15,"./features-detection.js":16,"./re.js":18}],20:[function(require,module,exports){ |
+/* globals module, require */ |
+ |
+"use strict"; |
+ |
+const IOElement = require("../js/io-element"); |
+ |
+class IOClock extends IOElement |
+{ |
+ connectedCallback() |
+ { |
+ this._timer = setInterval(() => this.render(), 1000); |
+ } |
+ |
+ disconnectedCallback() |
+ { |
+ clearInterval(this._timer); |
+ } |
+ |
+ render() |
+ { |
+ this.html` |
+ ${{i18n: "io_clock"}} |
+ @${(new Date()).toLocaleTimeString()} |
+ `; |
+ } |
+} |
+ |
+IOClock.define("io-clock"); |
+ |
+},{"../js/io-element":1}]},{},[20]); |