diff --git a/package-lock.json b/package-lock.json index d9e3402..4f2e32b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ef-core", - "version": "0.14.5", + "version": "0.14.6", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "ef-core", - "version": "0.14.5", + "version": "0.14.6", "license": "MIT", "devDependencies": { "@rollup/plugin-buble": "^0.21.3", diff --git a/package.json b/package.json index bd60464..eaa7fd8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ef-core", - "version": "0.14.5", + "version": "0.14.6", "description": "Core of ef.js (without parser)", "main": "dist/ef-core.min.js", "module": "src/ef-core.js", diff --git a/src/ef-core.js b/src/ef-core.js index 05d6e17..f1b1380 100644 --- a/src/ef-core.js +++ b/src/ef-core.js @@ -99,7 +99,7 @@ const create = (ast) => { return EFComponent } -let coreVersion = '0.14.5' +let coreVersion = '0.14.6' if (process.env.NODE_ENV !== 'production') { coreVersion = `${coreVersion}+debug` diff --git a/src/lib/renderer.js b/src/lib/renderer.js index 192c554..f306269 100644 --- a/src/lib/renderer.js +++ b/src/lib/renderer.js @@ -81,6 +81,7 @@ const EFBaseComponent = class { const subscribers = {} const nodeInfo = { placeholder: null, + eventBus: null, replace: [], parent: null, key: null @@ -95,6 +96,9 @@ const EFBaseComponent = class { if (process.env.NODE_ENV === 'production') nodeInfo.placeholder = DOM.document.createTextNode('') else nodeInfo.placeholder = DOM.document.createComment('EF COMPONENT PLACEHOLDER') + if (DOM.textNodeSupportsEvent) nodeInfo.eventBus = nodeInfo.placeholder + else nodeInfo.eventBus = document.createElement('i') + const mount = () => { if (nodeInfo.replace.length > 0) { for (let i of nodeInfo.replace) DOM.remove(i) @@ -289,7 +293,7 @@ const EFBaseComponent = class { */ $dispatch(event) { if (process.env.NODE_ENV !== 'production') checkDestroyed(this) - return this.$ctx.nodeInfo.placeholder.dispatchEvent(event) + return this.$ctx.nodeInfo.eventBus.dispatchEvent(event) } /** @@ -312,12 +316,14 @@ const EFBaseComponent = class { * @param {string} eventName - Name of the event * @param {function} handler - Handler for the event * @param {object|boolean} options - Event listener options or useCapture - * @returns {*} - Same as the return of Node.addEventListener + * @returns {function} - Event Handler disposal method */ $on(eventName, handler, options = {}) { if (process.env.NODE_ENV !== 'production') checkDestroyed(this) if (typeof options === 'boolean') options = {capture: options} - return this.$ctx.nodeInfo.placeholder.addEventListener(eventName, handler, assign({efInternal: true}, options)) + options = assign({efInternal: true}, options) + this.$ctx.nodeInfo.eventBus.addEventListener(eventName, handler, options) + return () => this.$off(eventName, handler, options) } /** @@ -329,7 +335,9 @@ const EFBaseComponent = class { */ $off(eventName, handler, options) { if (process.env.NODE_ENV !== 'production') checkDestroyed(this) - return this.$ctx.nodeInfo.placeholder.removeEventListener(eventName, handler, options) + if (typeof options === 'boolean') options = {capture: options} + options = assign({efInternal: true}, options) + return this.$ctx.nodeInfo.eventBus.removeEventListener(eventName, handler, assign({efInternal: true}, options)) } /** diff --git a/src/lib/utils/debug.js b/src/lib/utils/debug.js index dcecc1d..6936c44 100644 --- a/src/lib/utils/debug.js +++ b/src/lib/utils/debug.js @@ -1,8 +1,8 @@ const getDbg = () => { + // eslint-disable-next-line no-empty-function + const emptyFn = () => {} if (typeof console === 'undefined') { if (typeof print === 'undefined') { - // eslint-disable-next-line no-empty-function - const emptyFn = () => {} return { log: emptyFn, info: emptyFn, @@ -24,10 +24,10 @@ const getDbg = () => { // Wrap console functions for `[EF]` prefix const strTpl = '[EF] %s' return { - log: console.log.bind(console, strTpl), - info: console.info.bind(console, strTpl), - warn: console.warn.bind(console, strTpl), - error: console.error.bind(console, strTpl) + log: console.log && console.log.bind(console, strTpl) || emptyFn, + info: console.info && console.info.bind(console, strTpl) || emptyFn, + warn: console.warn && console.warn.bind(console, strTpl) || emptyFn, + error: console.error && console.error.bind(console, strTpl) || emptyFn } } diff --git a/src/lib/utils/dom-helper.js b/src/lib/utils/dom-helper.js index 81953cc..2e59133 100644 --- a/src/lib/utils/dom-helper.js +++ b/src/lib/utils/dom-helper.js @@ -70,11 +70,11 @@ DOM.before = (node, ...nodes) => { i.$mount({target: tempFragment}) } else if (isInstance(i, EFFragment)) i.appendTo(tempFragment) else { - DOM.Node.prototype.appendChild.call(tempFragment, i) + tempFragment.appendChild(i) handleMountingPoint(i, tempFragment) } } - DOM.Node.prototype.insertBefore.call(node.parentNode, tempFragment, node) + node.parentNode.insertBefore(tempFragment, node) exec() } @@ -85,10 +85,10 @@ DOM.after = (node, ...nodes) => { if (i instanceof shared.EFBaseComponent) { i.$mount({target: tempFragment}) } else if (isInstance(i, EFFragment)) i.appendTo(tempFragment) - else DOM.Node.prototype.appendChild.call(tempFragment, i) + else tempFragment.appendChild(i) } - if (node.nextSibling) DOM.Node.prototype.insertBefore.call(node.parentNode, tempFragment, node.nextSibling) - else DOM.Node.prototype.appendChild.call(node.parentNode, tempFragment) + if (node.nextSibling) node.parentNode.insertBefore(tempFragment, node.nextSibling) + else node.parentNode.appendChild(tempFragment) exec() } @@ -117,19 +117,19 @@ DOM.append = (node, ...nodes) => { for (let i of nodes) { if (isInstance(i, EFFragment)) i.appendTo(tempFragment) else if (DOM.isNodeInstance(i)) { - DOM.Node.prototype.appendChild.call(tempFragment, i) + tempFragment.appendChild(i) handleMountingPoint(i, tempFragment) } else if (i instanceof shared.EFBaseComponent) { i.$mount({target: tempFragment}) } } - DOM.Node.prototype.appendChild.call(node, tempFragment) + node.appendChild(tempFragment) } DOM.remove = (node) => { if (isInstance(node, EFFragment)) node.remove() else if (node instanceof shared.EFBaseComponent) node.$umount() - else DOM.Node.prototype.removeChild.call(node.parentNode, node) + else node.parentNode.removeChild(node) } // addClass(node, className) { @@ -158,7 +158,7 @@ DOM.remove = (node) => { // replaceWith(node, newNode) { // const parent = node.parentNode -// if (parent) DOM.Node.prototype.replaceChild.call(parent, newNode, node) +// if (parent) parent.replaceChild(newNode, node) // }, // swap(node, newNode) { @@ -167,8 +167,8 @@ DOM.remove = (node) => { // const nodeSibling = node.nextSibling // const newNodeSibling = newNode.nextSibling // if (nodeParent && newNodeParent) { -// DOM.Node.prototype.insertBefore.call(nodeParent, newNode, nodeSibling) -// DOM.Node.prototype.insertBefore.call(newNodeParent, node, newNodeSibling) +// nodeParent.insertBefore(newNode, nodeSibling) +// newNodeParent.insertBefore(node, newNodeSibling) // } // }, @@ -179,24 +179,24 @@ DOM.remove = (node) => { // const tempFragment = DOM.document.createDocumentFragment() // nodes.reverse() // for (let i of nodes) { -// DOM.Node.prototype.appendChild.call(tempFragment, i) +// tempFragment.appendChild(i) // } // if (node.firstChild) { -// DOM.Node.prototype.insertBefore.call(node, tempFragment, node.firstChild) +// node.insertBefore(tempFragment, node.firstChild) // } else { -// DOM.Node.prototype.appendChild.call(node, tempFragment) +// node.appendChild(tempFragment) // } // }, // appendTo(node, newNode) { -// DOM.Node.prototype.appendChild.call(newNode, node) +// newNode.appendChild(node) // }, // prependTo(node, newNode) { // if (newNode.firstChild) { -// DOM.Node.prototype.insertBefore.call(newNode, node, node.firstChild) +// newNode.insertBefore(node, node.firstChild) // } else { -// DOM.Node.prototype.appendChild.call(newNode, node) +// newNode.appendChild(node) // } // }, @@ -210,6 +210,9 @@ const noop = () => {} const setDOMImpl = (impl) => { assign(DOM, impl) + const dummyText = document.createTextNode('') + + DOM.textNodeSupportsEvent = !!dummyText.addEventListener DOM.passiveSupported = false DOM.onceSupported = false @@ -234,6 +237,6 @@ const setDOMImpl = (impl) => { } } -if (isBrowser) setDOMImpl({Node, document}) +if (isBrowser) setDOMImpl({document, Node}) export {DOM, EFFragment, mountingPointStore, setDOMImpl} diff --git a/src/lib/utils/event-helper.js b/src/lib/utils/event-helper.js index 480e84c..d8b7568 100644 --- a/src/lib/utils/event-helper.js +++ b/src/lib/utils/event-helper.js @@ -1,18 +1,15 @@ import {DOM} from './dom-helper.js' /** - * @typedef {{bubbles: boolean, cancelable: boolean}} EFEventOptions + * @typedef {{bubbles: boolean, cancelable: boolean, composed: boolean}} EFEventOptions */ /* Get new events that works in all target browsers * though a little bit old-fashioned */ -const getEvent = (name, {bubbles, cancelable} = { - bubbles: false, - cancelable: false -}) => { - const event = DOM.document.createEvent('CustomEvent') - event.initEvent(name, bubbles, cancelable) +const getEvent = (name, options = {}) => { + const event = DOM.document.createEvent && DOM.document.createEvent('CustomEvent') || new Event(name, options) + if (event.initEvent) event.initEvent(name, options.bubbles, options.cancelable) return event }