Passed
Pull Request — master (#13)
by Luís
01:13
created

src/js/core/EventManager.js   A

Size

Lines of Code 132

Duplication

Duplicated Lines 0
Ratio 0 %

Test Coverage

Coverage 18.42%

Importance

Changes 2
Bugs 0 Features 1
Metric Value
c 2
b 0
f 1
nc 1
dl 0
loc 132
ccs 7
cts 38
cp 0.1842
rs 10
noi 2
1 10
/**
2
 * Utility class to handle with events (subscribe, notify etc)
3
 *
4
 * @class EventManager
5
 */
6
class EventManager {
7
    debug = false;
8
9
    constructor() {
10
        this._map = {};
11
    }
12
13
    enableDebug() {
14
        this.debug = true;
15
    }
16
17
    disableDebug() {
18
        this.debug = false;
19
    }
20
21
    /**
22
     * Add an event listener
23
     *
24
     * @param {String} eventName Event's name
25
     * @param {Function} fn Handler
26
     * @returns {Function} the "unsubscriber". Call this function to unsubscribe this event (or use the unsubscribe method)
27
     *
28
     * @memberOf EventManager
29
     */
30
    subscribe(eventName, fn) {
31 2
        if (typeof eventName !== "string") {
32
            throw "eventName must be string";
33
        }
34
35 2
        if (!eventName.length) {
36
            throw "eventName cannot be empty";
37
        }
38
39 2
        if (!this._map.hasOwnProperty(eventName)) {
40
            this._map[eventName] = [];
41
        }
42
43
        this._map[eventName].push(fn);
44
        return this.unsubscribe.bind(this, eventName, fn);
45
    }
46
47
    /**
48
     * @see subscribe
49
     * Add an event listener to multiple event aht the sabe time
50
     *
51
     * @param {String[]} eventNames Event's names
52
     * @param {Function} fn Handler
53
     * @return {Function[]} Unsubscribers for all events
54
     * @see EventManager.subscribe
55
     *
56
     * @memberOf EventManager
57
     */
58
    subscribeMultiple(eventNames, fn) {
59
        let i, length = eventNames.length;
60
61
        var unsubscribes = [];
62
        for (i = 0; i < length; i++) {
63
            unsubscribes.push(this.subscribe(eventNames[i], fn));
64
        }
65
66
        return () => {
67
            unsubscribes.map(unsubscribe => unsubscribe());
68
        }
69
    }
70
71
    /**
72
     * Removes an event listener from an event
73
     *
74
     * @param {string} eventName Event's name
75
     * @param {Function} fn Handler to remove
76
     *
77
     * @memberOf EventManager
78
     */
79
    unsubscribe(eventName, fn) {
80 2
        if (!this._map[eventName]) {
81
            return;
82
        }
83
84
        let index = this._map[eventName].indexOf(fn);
85 2
        if (index !== -1) {
86
            this._map[eventName].splice(index, 1);
87
        }
88
    }
89
90
    /**
91
     * @see unsubscribe
92
     * Removes the event listener from multiple events
93
     *
94
     * @param {String[]} eventNames Event's names
95
     * @param {Function} fn
96
     *
97
     * @memberOf EventManager
98
     */
99
    unsubscribeMultiple(eventNames, fn) {
100
        let i, length = eventNames.length;
101
102
        for (i = 0; i < length; i++) {
103
            this.unsubscribe(eventNames[i], fn);
104
        }
105
    }
106
107
    /**
108
     * Removes all event listeners from the given events
109
     *
110
     * @param {String[]} eventNames
111
     *
112
     * @memberOf EventManager
113
     */
114
    unsubscribeAll(eventNames) {
115
        let i, length = eventNames.length;
116
        for (i = 0; i < length; i++) {
117 2
            if (this._map.hasOwnProperty(eventNames[i])) {
118
                delete this._map(eventNames[i]);
119
            }
120
        }
121
    }
122
123
    /**
124
     * Trigger an event. Will send all arguments after eventName to the existent
125
     * event listeners
126
     *
127
     * @param {String} eventName Event's name
128
     *
129
     * @memberOf EventManager
130
     */
131
    notify(eventName) {
132 2
        this.debug && console.log(eventName);
133
134 2
        if (!this._map.hasOwnProperty(eventName)) {
135
            return;
136
        }
137
138
        // make an copy of the arguments to prevent someone to change it
139
        let args = Array.prototype.slice.call(arguments, 1);
140
        this._map[eventName].forEach(function (fn) {
141
            fn.apply(this, args);
142
        });
143
    }
144
}
145
146
export default EventManager;
147