forked from slab/quill
-
Notifications
You must be signed in to change notification settings - Fork 7
/
emitter.js
86 lines (71 loc) · 1.97 KB
/
emitter.js
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
import EventEmitter from 'eventemitter3';
import logger from './logger';
const debug = logger('quill:events');
const EVENTS = ['selectionchange', 'mousedown', 'mouseup', 'click'];
const EMITTERS = [];
const supportsRootNode = ('getRootNode' in document);
EVENTS.forEach(function(eventName) {
document.addEventListener(eventName, (...args) => {
EMITTERS.forEach((em) => {
em.handleDOM(...args);
});
});
});
class Emitter extends EventEmitter {
constructor() {
super();
this.listeners = {};
this.on('error', debug.error);
}
emit() {
debug.log.apply(debug, arguments);
super.emit.apply(this, arguments);
}
connect() {
EMITTERS.push(this);
}
disconnect() {
EMITTERS.splice(EMITTERS.indexOf(this), 1);
}
handleDOM(event, ...args) {
const target = (event.composedPath ? event.composedPath()[0] : event.target);
const containsNode = (node, target) => {
if (!supportsRootNode || target.getRootNode() === document) {
return node.contains(target);
}
while (!node.contains(target)) {
const root = target.getRootNode();
if (!root || !root.host) {
return false;
}
target = root.host;
}
return true;
};
(this.listeners[event.type] || []).forEach(function({ node, handler }) {
if (target === node || containsNode(node, target)) {
handler(event, ...args);
}
});
}
listenDOM(eventName, node, handler) {
if (!this.listeners[eventName]) {
this.listeners[eventName] = [];
}
this.listeners[eventName].push({ node, handler })
}
}
Emitter.events = {
EDITOR_CHANGE : 'editor-change',
SCROLL_BEFORE_UPDATE : 'scroll-before-update',
SCROLL_OPTIMIZE : 'scroll-optimize',
SCROLL_UPDATE : 'scroll-update',
SELECTION_CHANGE : 'selection-change',
TEXT_CHANGE : 'text-change'
};
Emitter.sources = {
API : 'api',
SILENT : 'silent',
USER : 'user'
};
export default Emitter;