1 | import {Point} from '../geometry/Point';
|
2 | import * as Util from '../core/Util';
|
3 | import * as Browser from '../core/Browser';
|
4 | import {addPointerListener, removePointerListener} from './DomEvent.Pointer';
|
5 | import {addDoubleTapListener, removeDoubleTapListener} from './DomEvent.DoubleTap';
|
6 | import {getScale} from './DomUtil';
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 | export function on(obj, types, fn, context) {
|
25 |
|
26 | if (typeof types === 'object') {
|
27 | for (var type in types) {
|
28 | addOne(obj, type, types[type], fn);
|
29 | }
|
30 | } else {
|
31 | types = Util.splitWords(types);
|
32 |
|
33 | for (var i = 0, len = types.length; i < len; i++) {
|
34 | addOne(obj, types[i], fn, context);
|
35 | }
|
36 | }
|
37 |
|
38 | return this;
|
39 | }
|
40 |
|
41 | var eventsKey = '_leaflet_events';
|
42 |
|
43 |
|
44 |
|
45 |
|
46 |
|
47 |
|
48 |
|
49 |
|
50 |
|
51 | export function off(obj, types, fn, context) {
|
52 |
|
53 | if (typeof types === 'object') {
|
54 | for (var type in types) {
|
55 | removeOne(obj, type, types[type], fn);
|
56 | }
|
57 | } else if (types) {
|
58 | types = Util.splitWords(types);
|
59 |
|
60 | for (var i = 0, len = types.length; i < len; i++) {
|
61 | removeOne(obj, types[i], fn, context);
|
62 | }
|
63 | } else {
|
64 | for (var j in obj[eventsKey]) {
|
65 | removeOne(obj, j, obj[eventsKey][j]);
|
66 | }
|
67 | delete obj[eventsKey];
|
68 | }
|
69 |
|
70 | return this;
|
71 | }
|
72 |
|
73 | function addOne(obj, type, fn, context) {
|
74 | var id = type + Util.stamp(fn) + (context ? '_' + Util.stamp(context) : '');
|
75 |
|
76 | if (obj[eventsKey] && obj[eventsKey][id]) { return this; }
|
77 |
|
78 | var handler = function (e) {
|
79 | return fn.call(context || obj, e || window.event);
|
80 | };
|
81 |
|
82 | var originalHandler = handler;
|
83 |
|
84 | if (Browser.pointer && type.indexOf('touch') === 0) {
|
85 |
|
86 | addPointerListener(obj, type, handler, id);
|
87 |
|
88 | } else if (Browser.touch && (type === 'dblclick') && addDoubleTapListener &&
|
89 | !(Browser.pointer && Browser.chrome)) {
|
90 |
|
91 |
|
92 | addDoubleTapListener(obj, handler, id);
|
93 |
|
94 | } else if ('addEventListener' in obj) {
|
95 |
|
96 | if (type === 'mousewheel') {
|
97 | obj.addEventListener('onwheel' in obj ? 'wheel' : 'mousewheel', handler, false);
|
98 |
|
99 | } else if ((type === 'mouseenter') || (type === 'mouseleave')) {
|
100 | handler = function (e) {
|
101 | e = e || window.event;
|
102 | if (isExternalTarget(obj, e)) {
|
103 | originalHandler(e);
|
104 | }
|
105 | };
|
106 | obj.addEventListener(type === 'mouseenter' ? 'mouseover' : 'mouseout', handler, false);
|
107 |
|
108 | } else {
|
109 | if (type === 'click' && Browser.android) {
|
110 | handler = function (e) {
|
111 | filterClick(e, originalHandler);
|
112 | };
|
113 | }
|
114 | obj.addEventListener(type, handler, false);
|
115 | }
|
116 |
|
117 | } else if ('attachEvent' in obj) {
|
118 | obj.attachEvent('on' + type, handler);
|
119 | }
|
120 |
|
121 | obj[eventsKey] = obj[eventsKey] || {};
|
122 | obj[eventsKey][id] = handler;
|
123 | }
|
124 |
|
125 | function removeOne(obj, type, fn, context) {
|
126 |
|
127 | var id = type + Util.stamp(fn) + (context ? '_' + Util.stamp(context) : ''),
|
128 | handler = obj[eventsKey] && obj[eventsKey][id];
|
129 |
|
130 | if (!handler) { return this; }
|
131 |
|
132 | if (Browser.pointer && type.indexOf('touch') === 0) {
|
133 | removePointerListener(obj, type, id);
|
134 |
|
135 | } else if (Browser.touch && (type === 'dblclick') && removeDoubleTapListener &&
|
136 | !(Browser.pointer && Browser.chrome)) {
|
137 | removeDoubleTapListener(obj, id);
|
138 |
|
139 | } else if ('removeEventListener' in obj) {
|
140 |
|
141 | if (type === 'mousewheel') {
|
142 | obj.removeEventListener('onwheel' in obj ? 'wheel' : 'mousewheel', handler, false);
|
143 |
|
144 | } else {
|
145 | obj.removeEventListener(
|
146 | type === 'mouseenter' ? 'mouseover' :
|
147 | type === 'mouseleave' ? 'mouseout' : type, handler, false);
|
148 | }
|
149 |
|
150 | } else if ('detachEvent' in obj) {
|
151 | obj.detachEvent('on' + type, handler);
|
152 | }
|
153 |
|
154 | obj[eventsKey][id] = null;
|
155 | }
|
156 |
|
157 |
|
158 |
|
159 |
|
160 |
|
161 |
|
162 |
|
163 |
|
164 | export function stopPropagation(e) {
|
165 |
|
166 | if (e.stopPropagation) {
|
167 | e.stopPropagation();
|
168 | } else if (e.originalEvent) {
|
169 | e.originalEvent._stopped = true;
|
170 | } else {
|
171 | e.cancelBubble = true;
|
172 | }
|
173 | skipped(e);
|
174 |
|
175 | return this;
|
176 | }
|
177 |
|
178 |
|
179 |
|
180 | export function disableScrollPropagation(el) {
|
181 | addOne(el, 'mousewheel', stopPropagation);
|
182 | return this;
|
183 | }
|
184 |
|
185 |
|
186 |
|
187 |
|
188 | export function disableClickPropagation(el) {
|
189 | on(el, 'mousedown touchstart dblclick', stopPropagation);
|
190 | addOne(el, 'click', fakeStop);
|
191 | return this;
|
192 | }
|
193 |
|
194 |
|
195 |
|
196 |
|
197 |
|
198 |
|
199 | export function preventDefault(e) {
|
200 | if (e.preventDefault) {
|
201 | e.preventDefault();
|
202 | } else {
|
203 | e.returnValue = false;
|
204 | }
|
205 | return this;
|
206 | }
|
207 |
|
208 |
|
209 |
|
210 | export function stop(e) {
|
211 | preventDefault(e);
|
212 | stopPropagation(e);
|
213 | return this;
|
214 | }
|
215 |
|
216 |
|
217 |
|
218 |
|
219 | export function getMousePosition(e, container) {
|
220 | if (!container) {
|
221 | return new Point(e.clientX, e.clientY);
|
222 | }
|
223 |
|
224 | var scale = getScale(container),
|
225 | offset = scale.boundingClientRect;
|
226 |
|
227 | return new Point(
|
228 |
|
229 |
|
230 | (e.clientX - offset.left) / scale.x - container.clientLeft,
|
231 | (e.clientY - offset.top) / scale.y - container.clientTop
|
232 | );
|
233 | }
|
234 |
|
235 |
|
236 |
|
237 | var wheelPxFactor =
|
238 | (Browser.win && Browser.chrome) ? 2 * window.devicePixelRatio :
|
239 | Browser.gecko ? window.devicePixelRatio : 1;
|
240 |
|
241 |
|
242 |
|
243 |
|
244 |
|
245 |
|
246 | export function getWheelDelta(e) {
|
247 | return (Browser.edge) ? e.wheelDeltaY / 2 :
|
248 | (e.deltaY && e.deltaMode === 0) ? -e.deltaY / wheelPxFactor :
|
249 | (e.deltaY && e.deltaMode === 1) ? -e.deltaY * 20 :
|
250 | (e.deltaY && e.deltaMode === 2) ? -e.deltaY * 60 :
|
251 | (e.deltaX || e.deltaZ) ? 0 :
|
252 | e.wheelDelta ? (e.wheelDeltaY || e.wheelDelta) / 2 :
|
253 | (e.detail && Math.abs(e.detail) < 32765) ? -e.detail * 20 :
|
254 | e.detail ? e.detail / -32765 * 60 :
|
255 | 0;
|
256 | }
|
257 |
|
258 | var skipEvents = {};
|
259 |
|
260 | export function fakeStop(e) {
|
261 |
|
262 | skipEvents[e.type] = true;
|
263 | }
|
264 |
|
265 | export function skipped(e) {
|
266 | var events = skipEvents[e.type];
|
267 |
|
268 | skipEvents[e.type] = false;
|
269 | return events;
|
270 | }
|
271 |
|
272 |
|
273 | export function isExternalTarget(el, e) {
|
274 |
|
275 | var related = e.relatedTarget;
|
276 |
|
277 | if (!related) { return true; }
|
278 |
|
279 | try {
|
280 | while (related && (related !== el)) {
|
281 | related = related.parentNode;
|
282 | }
|
283 | } catch (err) {
|
284 | return false;
|
285 | }
|
286 | return (related !== el);
|
287 | }
|
288 |
|
289 | var lastClick;
|
290 |
|
291 |
|
292 | function filterClick(e, handler) {
|
293 | var timeStamp = (e.timeStamp || (e.originalEvent && e.originalEvent.timeStamp)),
|
294 | elapsed = lastClick && (timeStamp - lastClick);
|
295 |
|
296 |
|
297 |
|
298 |
|
299 |
|
300 |
|
301 | if ((elapsed && elapsed > 100 && elapsed < 500) || (e.target._simulatedClick && !e._simulated)) {
|
302 | stop(e);
|
303 | return;
|
304 | }
|
305 | lastClick = timeStamp;
|
306 |
|
307 | handler(e);
|
308 | }
|
309 |
|
310 |
|
311 |
|
312 | export {on as addListener};
|
313 |
|
314 |
|
315 |
|
316 | export {off as removeListener};
|