]> source.dussan.org Git - svg.js.git/commitdiff
proposal for #807, includes #550, allow multiple events for `SVG.off()` and add optio...
authorUlrich-Matthias Schäfer <ulima.ums@googlemail.com>
Sun, 11 Feb 2018 12:11:31 +0000 (13:11 +0100)
committerUlrich-Matthias Schäfer <ulima.ums@googlemail.com>
Tue, 27 Feb 2018 09:01:52 +0000 (10:01 +0100)
src/element.js
src/event.js
src/svg.js

index eca535b4eb0efee1419ae0e3b1902ad636ee80bc..a2c8cc5eb9b5ef9542dcff4b2f9ab712b0154d74 100644 (file)
@@ -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)
index c53e0b383cfc723d28e9281df65a26f7be751421..6501beb3031210a8c3c2cdb294bbc51f3b84b0e6 100644 (file)
@@ -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)
     }
   })
 
-// 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
   }
 })
index e6903da0a88c6f140c94a0642328417b0cb434ef..55cb88d834b5bbd60c264056a3ff7f1da09e856d 100644 (file)
@@ -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)