From: Ulrich-Matthias Schäfer Date: Sun, 11 Feb 2018 12:11:31 +0000 (+0100) Subject: proposal for #807, includes #550, allow multiple events for `SVG.off()` and add optio... X-Git-Tag: 3.0.0~67^2~5 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=c60946188a076d8013440b141f85d57c920160a9;p=svg.js.git proposal for #807, includes #550, allow multiple events for `SVG.off()` and add option argument --- diff --git a/src/element.js b/src/element.js index eca535b..a2c8cc5 100644 --- a/src/element.js +++ b/src/element.js @@ -2,9 +2,9 @@ SVG.Element = SVG.invent({ // Initialize node - create: function (node) { - // last fired event on node - this._event = null + create: function(node) { + // event listener + this.events = {} // initialize data object this.dom = {} @@ -14,6 +14,7 @@ SVG.Element = SVG.invent({ if (this.node) { this.type = node.nodeName this.node.instance = this + this.events = node.events || {} if (node.hasAttribute('svgjs:data')) { // pull svgjs data from the dom (getAttributeNS doesn't work in html5) diff --git a/src/event.js b/src/event.js index c53e0b3..6501beb 100644 --- a/src/event.js +++ b/src/event.js @@ -1,4 +1,5 @@ // Add events to elements + ;[ 'click', 'dblclick', 'mousedown', @@ -6,14 +7,14 @@ 'mouseover', 'mouseout', 'mousemove', - // , 'mouseenter' -> not supported by IE - // , 'mouseleave' -> not supported by IE + 'mouseenter', + 'mouseleave', 'touchstart', 'touchmove', 'touchleave', 'touchend', 'touchcancel' ].forEach(function (event) { - // add event to SVG.Element + // add event to SVG.Element SVG.Element.prototype[event] = function (f) { // bind event to element rather than element node SVG.on(this, event, f) @@ -21,32 +22,31 @@ } }) -// Initialize listeners stack -SVG.listeners = [] -SVG.handlerMap = [] SVG.listenerId = 0 // Add event binder in the SVG namespace SVG.on = function (node, events, listener, binding, options) { + var l = listener.bind(binding || node), + n = node instanceof SVG.Element ? node.node : node + + // ensure instance object for nodes which are not adopted + n.instance = n.instance || {events: {}} + + var bag = n.instance.events + + // ensure valid object + bag[ev] = bag[ev] || {} + bag[ev][ns] = bag[ev][ns] || {} + + // add id to listener + if (!listener._svgjsListenerId) { listener._svgjsListenerId = ++SVG.listenerId } + events.split(SVG.regex.delimiter).forEach(function (event) { - // create listener, get object-index - var l = listener.bind(binding || node) - var n = node instanceof SVG.Element ? node.node : node - var index = (SVG.handlerMap.indexOf(n) + 1 || SVG.handlerMap.push(n)) - 1 - var ev = event.split('.')[0] - var ns = event.split('.')[1] || '*' - - // ensure valid object - SVG.listeners[index] = SVG.listeners[index] || {} - SVG.listeners[index][ev] = SVG.listeners[index][ev] || {} - SVG.listeners[index][ev][ns] = SVG.listeners[index][ev][ns] || {} - - if (!listener._svgjsListenerId) { - listener._svgjsListenerId = ++SVG.listenerId - } + var ev = event.split('.')[0], + ns = event.split('.')[1] || '*' // reference listener - SVG.listeners[index][ev][ns][listener._svgjsListenerId] = l + bag[ev][ns][listener._svgjsListenerId] = l // add listener n.addEventListener(ev, l, options || false) @@ -54,91 +54,83 @@ SVG.on = function (node, events, listener, binding, options) { } // Add event unbinder in the SVG namespace -SVG.off = function (node, event, listener) { - var index = SVG.handlerMap.indexOf(node) - var ev = event && event.split('.')[0] - var ns = event && event.split('.')[1] - var namespace = '' - - if (index === -1) return +SVG.off = function (node, events, listener, options) { + var n = node instanceof SVG.Element ? node.node : node + if (!n.instance) return + // make a precheck for a valid listener here to avoid repetition in the loop if (listener) { if (typeof listener === 'function') listener = listener._svgjsListenerId if (!listener) return + } - // remove listener reference - if (SVG.listeners[index][ev] && SVG.listeners[index][ev][ns || '*']) { - // remove listener - node.removeEventListener(ev, SVG.listeners[index][ev][ns || '*'][listener], false) + var bag = n.instance.events - delete SVG.listeners[index][ev][ns || '*'][listener] - } - } else if (ns && ev) { - // remove all listeners for a namespaced event - if (SVG.listeners[index][ev] && SVG.listeners[index][ev][ns]) { - for (listener in SVG.listeners[index][ev][ns]) { - SVG.off(node, [ev, ns].join('.'), listener) + ;(events || '').split(SVG.regex.delimiter).forEach(function (event) { + var ev = event && event.split('.')[0], + ns = event && event.split('.')[1], + namespace + + if (listener) { + // remove listener reference + if (bag[ev] && bag[ev][ns || '*']) { + // remove listener + n.removeEventListener(ev, bag[ev][ns || '*'][listener], options || false) + + delete bag[ev][ns || '*'][listener] } + } else if (ev && ns) { + // remove all listeners for a namespaced event + if (bag[ev] && bag[ev][ns]) { + for (listener in bag[ev][ns]) { SVG.off(n, [ev, ns].join('.'), listener) } - delete SVG.listeners[index][ev][ns] - } - } else if (ns) { - // remove all listeners for a specific namespace - for (event in SVG.listeners[index]) { - for (namespace in SVG.listeners[index][event]) { - if (ns === namespace) { - SVG.off(node, [event, ns].join('.')) + delete bag[ev][ns] + } + } else if (ns) { + // remove all listeners for a specific namespace + for (event in bag) { + for (namespace in bag[event]) { + if (ns === namespace) { SVG.off(n, [event, ns].join('.')) } } } - } - } else if (ev) { - // remove all listeners for the event - if (SVG.listeners[index][ev]) { - for (namespace in SVG.listeners[index][ev]) { - SVG.off(node, [ev, namespace].join('.')) + } else if (ev) { + // remove all listeners for the event + if (bag[ev]) { + for (namespace in bag[ev]) { SVG.off(n, [ev, namespace].join('.')) } + + delete bag[ev] } + } else { + // remove all listeners on a given node + for (event in bag) { SVG.off(n, event) } - delete SVG.listeners[index][ev] - } - } else { - // remove all listeners on a given node - for (event in SVG.listeners[index]) { - SVG.off(node, event) + n.instance.events = {} } - - delete SVG.listeners[index] - delete SVG.handlerMap[index] - } + }) } -// SVG.extend(SVG.Element, { // Bind given event to listener on: function (event, listener, binding, options) { SVG.on(this, event, listener, binding, options) return this }, - // Unbind event from listener off: function (event, listener) { SVG.off(this.node, event, listener) - return this }, - - // Fire given event - fire: function (event, data) { + dispatch: function (event, data) { // Dispatch event if (event instanceof window.Event) { this.node.dispatchEvent(event) } else { this.node.dispatchEvent(event = new window.CustomEvent(event, {detail: data, cancelable: true})) } - - this._event = event - return this + return event }, - - event: function () { - return this._event + // Fire given event + fire: function (event, data) { + this.dispatch(event, data) + return this } }) diff --git a/src/svg.js b/src/svg.js index e6903da..55cb88d 100644 --- a/src/svg.js +++ b/src/svg.js @@ -77,7 +77,7 @@ SVG.adopt = function (node) { if (!node) return null // make sure a node isn't already adopted - if (node.instance) return node.instance + if (node.instance instanceof SVG.Element) return node.instance if (!(node instanceof window.SVGElement)) { return new SVG.HtmlNode(node)