-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathfx-listener.html
131 lines (119 loc) · 4.29 KB
/
fx-listener.html
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
129
130
131
<!--
Listens for external elements and notifies locally. Target can be any window
accessible property path, for example "document" or "screen.orientation". By
default if no path is specified events are listened for on the window
itself.
The presence of an attribute that starts with "on-" will trigger a listener
on the target for the event name following the dash. This works implicitly
in polymer's declarative event handlers. If you're not using polymer, or are
creating an element programatically you can add an attribute
"on-{eventname}" to the element with no value.
Dynamically changing the target or event attributes after inserting into the
document is not supported.
Usage:
<fx-listener on-hashchange="{{ handleHashChange }}"></fx-listener>
<fx-listener
target="screen.orientation"
on-orientationchange="{{ handleHashChange }}"></fx-listener>
-->
<link href="../polymer/polymer.html" rel="import">
<polymer-element name="fx-listener" constructor="FxListener" attributes="target">
<script>
(function() {
var listeners = {};
function addEventListener(target, eventName, listener) {
if (!target || !target.addEventListener || !eventName)
return;
var data = findListenerData(target, eventName);
if (!data) {
data = {
target: target,
listeners: [],
handler: function(event) {
dispatchEvents(event, data.listeners);
},
};
listeners[eventName] = listeners[eventName] || [];
listeners[eventName].push(data);
target.addEventListener(eventName, data.handler);
}
if (!data.listeners.find(listener))
data.listeners.add(listener);
}
function removeEventListener(target, eventName, listener) {
if (!target || !target.addEventListener || !eventName)
return;
var data = findListenerData(target, eventName);
if (!data)
return;
data.listeners.remove(listener);
if (!data.listeners.length) {
listeners[eventName].remove(data);
target.removeEventListener(eventName, data.handler);
}
}
function dispatchEvents(event, listeners) {
listeners.forEach(function(listener) {
if (!listener.active)
return;
listener.fire(event.type, event, /*onNode*/ null, /*bubbles*/ false,
/*cancelable*/ false);
});
}
function findListenerData(target, eventName) {
var entries = listeners[eventName] || [];
for (var i = 0; i < entries.length; ++i) {
if (entries[i].target == target)
return entries[i];
}
return null;
}
function findTarget(path) {
var object = window;
var parts = path.split(".");
for (var i = 0; i < parts.length && object; ++i) {
if (parts[i])
object = object[parts[i]];
}
return object;
}
function findEventNames(element) {
var eventsNames = [];
for (var i = 0; i < element.attributes.length; ++i) {
var name = element.attributes[i].name;
if (name.to(3) != "on-")
return;
var eventName = name.from(3);
if (eventName)
eventsNames.push(eventName);
}
return eventsNames;
}
Polymer({
target: "",
events: null,
active: false,
created: function() {
this.style.display = "none";
},
attached: function() {
this.active = true;
this.events = findEventNames(this);
if (!this.events.length)
return;
var target = findTarget(this.target);
for (var i = 0; i < this.events.length; ++i)
addEventListener(target, this.events[i], this);
},
detached: function() {
if (!this.events || !this.events.length)
return;
var target = findTarget(this.target);
for (var i = 0; i < this.events.length; ++i)
removeEventListener(target, this.events[i], this);
this.active = false;
},
});
})();
</script>
</polymer-element>