-
Notifications
You must be signed in to change notification settings - Fork 285
/
dispatcher.js
111 lines (105 loc) · 3.43 KB
/
dispatcher.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
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
//* @protected
enyo.$ = {};
enyo.dispatcher = {
// these events come from document
events: ["mousedown", "mouseup", "mouseover", "mouseout", "mousemove", "mousewheel", "click", "dblclick", "change", "keydown", "keyup", "keypress", "input"],
// these events come from window
windowEvents: ["resize", "load", "unload", "message"],
// feature plugins (aka filters)
features: [],
connect: function() {
var d = enyo.dispatcher;
for (var i=0, n; n=d.events[i]; i++) {
d.listen(document, n);
}
for (i=0, n; n=d.windowEvents[i]; i++) {
d.listen(window, n);
}
},
listen: function(inListener, inEventName) {
var d = enyo.dispatch;
if (inListener.addEventListener) {
this.listen = function(inListener, inEventName) {
inListener.addEventListener(inEventName, d, false);
};
} else {
//console.log("IE8 COMPAT: using 'attachEvent'");
this.listen = function(inListener, inEvent, inCb) {
inListener.attachEvent("on" + inEvent, function(e) {
e.target = e.srcElement;
if (!e.preventDefault) {
e.preventDefault = enyo.iePreventDefault;
}
return d(e);
});
};
}
this.listen(inListener, inEventName);
},
//* Fire an event for Enyo to listen for
dispatch: function(e) {
// Find the control who maps to e.target, or the first control that maps to an ancestor of e.target.
var c = this.findDispatchTarget(e.target) || this.findDefaultTarget(e);
// Cache the original target
e.dispatchTarget = c;
// support pluggable features return true to abort immediately or set e.preventDispatch to avoid processing.
for (var i=0, fn; fn=this.features[i]; i++) {
if (fn.call(this, e) === true) {
return;
}
}
if (c && !e.preventDispatch) {
this.dispatchBubble(e, c);
}
},
//* Takes an Event.target and finds the corresponding enyo control
findDispatchTarget: function(inNode) {
var t, n = inNode;
// FIXME: Mozilla: try/catch is here to squelch "Permission denied to access property xxx from a non-chrome context"
// which appears to happen for scrollbar nodes in particular. It's unclear why those nodes are valid targets if
// it is illegal to interrogate them. Would like to trap the bad nodes explicitly rather than using an exception block.
try {
while (n) {
if (t = enyo.$[n.id]) {
// there could be multiple nodes with this id, the relevant node for this event is n
// we don't push this directly to t.node because sometimes we are just asking what
// the target 'would be' (aka, calling findDispatchTarget from handleMouseOverOut)
t.eventNode = n;
break;
}
n = n.parentNode;
}
} catch(x) {
console.log(x, n);
}
return t;
},
//* Return the default enyo control for events
findDefaultTarget: function(e) {
return enyo.master;
},
dispatchBubble: function(e, c) {
return c.bubble("on" + e.type, e, c);
}
};
// called in the context of an event
enyo.iePreventDefault = function() {
this.returnValue = false;
};
enyo.dispatch = function(inEvent) {
return enyo.dispatcher.dispatch(inEvent);
};
enyo.bubble = function(inEvent) {
// '|| window.event' clause needed for IE8
var e = inEvent || window.event;
if (e) {
// We depend on e.target existing for event tracking and dispatching.
if (!e.target) {
e.target = e.srcElement;
}
enyo.dispatch(e);
}
};
enyo.bubbler = 'enyo.bubble(arguments[0])';
// FIXME: we need to create and initialize dispatcher someplace else to allow overrides
enyo.requiresWindow(enyo.dispatcher.connect);