summaryrefslogtreecommitdiffstats
path: root/src/modules/core/event.js
blob: 507e91f763157cc8365a3f4da9efee2c9e0cc0a0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import { delimiter } from './regex.js'
import { makeInstance } from '../../utils/adopter.js'
import { globals } from '../../utils/window.js'

let listenerId = 0

function getEvents (node) {
  const n = makeInstance(node).getEventHolder()
  if (!n.events) n.events = {}
  return n.events
}

function getEventTarget (node) {
  return makeInstance(node).getEventTarget()
}

function clearEvents (node) {
  const n = makeInstance(node).getEventHolder()
  if (n.events) n.events = {}
}

// Add event binder in the SVG namespace
export function on (node, events, listener, binding, options) {
  var l = listener.bind(binding || node)
  var bag = getEvents(node)
  var n = getEventTarget(node)

  // events can be an array of events or a string of events
  events = Array.isArray(events) ? events : events.split(delimiter)

  // add id to listener
  if (!listener._svgjsListenerId) {
    listener._svgjsListenerId = ++listenerId
  }

  events.forEach(function (event) {
    var ev = event.split('.')[0]
    var ns = event.split('.')[1] || '*'

    // ensure valid object
    bag[ev] = bag[ev] || {}
    bag[ev][ns] = bag[ev][ns] || {}

    // reference listener
    bag[ev][ns][listener._svgjsListenerId] = l

    // add listener
    n.addEventListener(ev, l, options || false)
  })
}

// Add event unbinder in the SVG namespace
export function off (node, events, listener, options) {
  var bag = getEvents(node)
  var n = getEventTarget(node)

  // listener can be a function or a number
  if (typeof listener === 'function') {
    listener = listener._svgjsListenerId
    if (!listener) return
  }

  // events can be an array of events or a string or undefined
  events = Array.isArray(events) ? events : (events || '').split(delimiter)

  events.forEach(function (event) {
    var ev = event && event.split('.')[0]
    var ns = event && event.split('.')[1]
    var namespace, l

    if (listener) {
      // remove listener reference
      if (bag[ev] && bag[ev][ns || '*']) {
        // removeListener
        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 (l in bag[ev][ns]) {
          off(n, [ ev, ns ].join('.'), l)
        }

        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) {
            off(n, [ event, ns ].join('.'))
          }
        }
      }
    } else if (ev) {
      // remove all listeners for the event
      if (bag[ev]) {
        for (namespace in bag[ev]) {
          off(n, [ ev, namespace ].join('.'))
        }

        delete bag[ev]
      }
    } else {
      // remove all listeners on a given node
      for (event in bag) {
        off(n, event)
      }

      clearEvents(node)
    }
  })
}

export function dispatch (node, event, data) {
  var n = getEventTarget(node)

  // Dispatch event
  if (event instanceof globals.window.Event) {
    n.dispatchEvent(event)
  } else {
    event = new globals.window.CustomEvent(event, { detail: data, cancelable: true })
    n.dispatchEvent(event)
  }
  return event
}