UNPKG

13.6 kBJavaScriptView Raw
1"use strict";
2
3(function (global, factory) {
4 "use strict";
5
6 if (typeof define === "function" && define.amd) {
7 // export as AMD
8 define([], factory);
9 } else if (typeof module !== "undefined" && module.exports && typeof require === "function") {
10 // node/browserify
11 module.exports = factory();
12 } else {
13 // browser global
14 global.simulant = factory();
15 }
16}(typeof window !== "undefined" ? window : this, function () {
17 "use strict";
18
19 var maps__defaults = {
20 bubbles: true,
21 cancelable: true,
22 view: window,
23 detail: null,
24 screenX: 0,
25 screenY: 0,
26 clientX: 0,
27 clientY: 0,
28 ctrlKey: false,
29 altKey: false,
30 shiftKey: false,
31 metaKey: false,
32 button: 0,
33 relatedTarget: null,
34 locale: "",
35 oldURL: "",
36 newURL: "",
37 origin: "",
38 lastEventId: "",
39 source: null,
40 ports: [],
41 oldValue: null,
42 newValue: null,
43 url: "",
44 storageArea: null,
45 deltaX: 0,
46 deltaY: 0,
47 deltaZ: 0,
48 deltaMode: 0
49 };
50
51
52 // TODO remove the ones that aren't supported in any browser
53 var maps__eventTypesByGroup = {
54 UIEvent: "abort error resize scroll select unload",
55 Event: "afterprint beforeprint cached canplay canplaythrough change chargingchange chargingtimechange checking close dischargingtimechange DOMContentLoaded downloading durationchange emptied ended fullscreenchange fullscreenerror input invalid levelchange loadeddata loadedmetadata noupdate obsolete offline online open orientationchange pause pointerlockchange pointerlockerror play playing ratechange readystatechange reset seeked seeking stalled submit success suspend timeupdate updateready visibilitychange volumechange waiting",
56 AnimationEvent: "animationend animationiteration animationstart",
57 AudioProcessingEvent: "audioprocess",
58 BeforeUnloadEvent: "beforeunload",
59 TimeEvent: "beginEvent endEvent repeatEvent",
60 FocusEvent: "blur focus focusin focusout",
61 MouseEvent: "click contextmenu dblclick mousedown mouseenter mouseleave mousemove mouseout mouseover mouseup show",
62 SensorEvent: "compassneedscalibration userproximity",
63 OfflineAudioCompletionEvent: "complete",
64 CompositionEvent: "compositionend compositionstart compositionupdate",
65 ClipboardEvent: "copy cut paste",
66 DeviceLightEvent: "devicelight",
67 DeviceMotionEvent: "devicemotion",
68 DeviceOrientationEvent: "deviceorientation",
69 DeviceProximityEvent: "deviceproximity",
70 DragEvent: "drag dragend dragenter dragleave dragover dragstart drop",
71 GamepadEvent: "gamepadconnected gamepaddisconnected",
72 HashChangeEvent: "hashchange",
73 KeyboardEvent: "keydown keypress keyup",
74 ProgressEvent: "loadend loadstart progress timeout",
75 MessageEvent: "message",
76 PageTransitionEvent: "pagehide pageshow",
77 PopStateEvent: "popstate",
78 StorageEvent: "storage",
79 SVGEvent: "SVGAbort SVGError SVGLoad SVGResize SVGScroll SVGUnload",
80 SVGZoomEvent: "SVGZoom",
81 TouchEvent: "touchcancel touchend touchenter touchleave touchmove touchstart",
82 TransitionEvent: "transitionend",
83 WheelEvent: "wheel"
84 };
85
86 var maps__eventGroupByType = {};
87
88 Object.keys(maps__eventTypesByGroup).forEach(function (group) {
89 var maps__types = maps__eventTypesByGroup[group].split(" ");
90
91 maps__types.forEach(function (t) {
92 maps__eventGroupByType[t] = group;
93 });
94 });
95
96
97 // The parameters required by event constructors and init methods, in the order the init methods need them.
98
99 // There is no initKeyboardEvent or initKeyEvent here. Keyboard events are a goddamned mess. You can't fake them
100 // well in any browser - the which and keyCode properties are readonly, for example. So we don't actually use the
101 // KeyboardEvent constructor, or the initKeyboardEvent or initKeyEvent methods. Instead we use a bog standard
102 // Event and add the required parameters as expando properties.
103
104 // TODO I think in some browsers we need to use modifiersList instead of ctrlKey/shiftKey etc?
105 var maps__initialiserParams = {
106 initUIEvent: "view detail",
107 initMouseEvent: "view detail screenX screenY clientX clientY ctrlKey altKey shiftKey metaKey button relatedTarget",
108 initCompositionEvent: "view detail data locale",
109 initHashChangeEvent: "oldURL newURL",
110 initMessageEvent: "data origin lastEventId source ports",
111 initStorageEvent: "key oldValue newValue url storageArea",
112 initWheelEvent: "view detail screenX screenY clientX clientY ctrlKey altKey shiftKey metaKey button relatedTarget deltaX deltaY deltaZ deltaMode"
113 };
114
115 Object.keys(maps__initialiserParams).forEach(function (initMethod) {
116 maps__initialiserParams[initMethod] = maps__initialiserParams[initMethod].split(" ");
117 });
118
119
120 var maps__initialisersByGroup = {
121 UIEvent: [window.UIEvent, "initUIEvent"],
122 Event: [window.Event, "initEvent"],
123 FocusEvent: [window.FocusEvent, "initUIEvent"],
124 MouseEvent: [window.MouseEvent, "initMouseEvent"],
125 CompositionEvent: [window.CompositionEvent, "initCompositionEvent"],
126 HashChangeEvent: [window.HashChangeEvent, "initHashChangeEvent"],
127 KeyboardEvent: [window.Event, "initEvent"],
128 ProgressEvent: [window.ProgressEvent, "initEvent"],
129 MessageEvent: [window.MessageEvent, "initMessageEvent"], // TODO prefixed?
130 PageTransitionEvent: [window.PageTransitionEvent, "initEvent"],
131 PopStateEvent: [window.PopStateEvent, "initEvent"],
132 StorageEvent: [window.StorageEvent, "initStorageEvent"],
133 TouchEvent: [window.TouchEvent, "initTouchEvent"],
134 WheelEvent: [window.WheelEvent, "initWheelEvent"] // TODO this differs between browsers...
135 };
136
137 var extendWithKeyboardParams__keyboardParams = ["which", "keyCode", "shiftKey", "ctrlKey", "altKey", "metaKey"];
138
139 function extendWithKeyboardParams__extendWithKeyboardParams(event, params) {
140 var i = extendWithKeyboardParams__keyboardParams.length;
141 while (i--) {
142 event[extendWithKeyboardParams__keyboardParams[i]] = params[extendWithKeyboardParams__keyboardParams[i]];
143 }
144 }
145 var extendWithKeyboardParams__default = extendWithKeyboardParams__extendWithKeyboardParams;
146
147 var ancient__default = function () {
148 var methodName, initialisers, makeInitialiser, simulant;
149
150 initialisers = {};
151
152 makeInitialiser = function (methodName, paramsList) {
153 return function (event, type, params) {
154 var paramName, i;
155
156 event.type = type;
157
158 i = paramsList.length;
159 while (i--) {
160 paramName = paramsList[i];
161 event[paramName] = params[paramName] || maps__defaults[paramName];
162 }
163 };
164 };
165
166 for (methodName in maps__initialiserParams) {
167 if (maps__initialiserParams.hasOwnProperty(methodName)) {
168 initialisers[methodName] = makeInitialiser(methodName, maps__initialiserParams[methodName]);
169 }
170 }
171
172 initialisers.initEvent = makeInitialiser("initEvent", []);
173
174 simulant = function (type, params) {
175 var event, group, initialiserName, initialise, isKeyboardEvent;
176
177 group = maps__eventGroupByType[type];
178
179 if (group === "KeyboardEvent") {
180 isKeyboardEvent = true;
181 group = "Event";
182 }
183
184 initialiserName = maps__initialisersByGroup[group][1];
185 initialise = initialisers[initialiserName];
186
187 event = document.createEventObject();
188 initialise(event, type, params || {});
189
190 if (isKeyboardEvent) {
191 extendWithKeyboardParams__default(event, params);
192 }
193
194 return event;
195 };
196
197 simulant.mode = "ancient";
198 return simulant;
199 };
200
201 var legacy__default = function () {
202 var methodName, initialisers, makeInitialiser, simulant;
203
204 initialisers = {};
205
206 makeInitialiser = function (methodName, paramsList) {
207 return function (event, type, params) {
208 var args;
209
210 // first three args are always `type`, `bubbles`, `cancelable`
211 args = [type, true, true]; // TODO some events don't bubble?
212
213 paramsList.forEach(function (paramName) {
214 args.push(params[paramName] || maps__defaults[paramName]);
215 });
216
217 event[methodName].apply(event, args);
218 };
219 };
220
221 Object.keys(maps__initialiserParams).forEach(function (methodName) {
222 initialisers[methodName] = makeInitialiser(methodName, maps__initialiserParams[methodName]);
223 });
224
225 initialisers.initEvent = makeInitialiser("initEvent", []);
226
227 simulant = function (type, params) {
228 var event, group, initialiserName, initialise, isKeyboardEvent;
229
230 group = maps__eventGroupByType[type];
231
232 if (group === "KeyboardEvent") {
233 isKeyboardEvent = true;
234 group = "Event";
235 }
236
237 initialiserName = maps__initialisersByGroup[group][1];
238 initialise = initialisers[initialiserName];
239
240 event = document.createEvent(group);
241 initialise(event, type, params || {});
242
243 if (isKeyboardEvent) {
244 extendWithKeyboardParams__default(event, params);
245 }
246
247 return event;
248 };
249
250 simulant.mode = "legacy";
251 return simulant;
252 };
253
254 var modern__default = function () {
255 var simulant = function (type, params) {
256 if (params === undefined) params = {};
257 var event, group, Constructor, paramsList, paramName, i, extendedParams, isKeyboardEvent;
258
259 group = maps__eventGroupByType[type];
260
261 if (group === "KeyboardEvent") {
262 group = "Event"; // because you can't fake KeyboardEvents well in any browser
263 isKeyboardEvent = true;
264 }
265
266 Constructor = maps__initialisersByGroup[group][0];
267
268 extendedParams = {
269 bubbles: true, // TODO some events don't bubble?
270 cancelable: true
271 };
272
273 paramsList = maps__initialiserParams[maps__initialisersByGroup[group][1]];
274 i = (paramsList ? paramsList.length : 0);
275
276 while (i--) {
277 paramName = paramsList[i];
278 extendedParams[paramName] = (paramName in params ? params[paramName] : maps__defaults[paramName]);
279 }
280
281 event = new Constructor(type, extendedParams);
282
283 if (isKeyboardEvent) {
284 extendWithKeyboardParams__default(event, params);
285 }
286
287 return event;
288 };
289
290 simulant.mode = "modern";
291 return simulant;
292 };
293
294 function polyfill__polyfill() {
295 // https://gist.github.com/Rich-Harris/6010282 via https://gist.github.com/jonathantneal/2869388
296 // addEventListener polyfill IE6+
297 var Event, addEventListener, removeEventListener, head, style;
298
299 Event = function (e, element) {
300 var property, instance = this;
301
302 for (property in e) {
303 instance[property] = e[property];
304 }
305
306 instance.currentTarget = element;
307 instance.target = e.srcElement || element;
308 instance.timeStamp = +new Date();
309
310 instance.preventDefault = function () {
311 e.returnValue = false;
312 };
313
314 instance.stopPropagation = function () {
315 e.cancelBubble = true;
316 };
317 };
318
319 addEventListener = function (type, listener) {
320 var element = this, listeners, i;
321
322 listeners = element.listeners || (element.listeners = []);
323 i = listeners.length;
324
325 listeners[i] = [listener, function (e) {
326 listener.call(element, new Event(e, element));
327 }];
328
329 element.attachEvent("on" + type, listeners[i][1]);
330 };
331
332 removeEventListener = function (type, listener) {
333 var element = this, listeners, i;
334
335 if (!element.listeners) {
336 return;
337 }
338
339 listeners = element.listeners;
340 i = listeners.length;
341
342 while (i--) {
343 if (listeners[i][0] === listener) {
344 element.detachEvent("on" + type, listeners[i][1]);
345 }
346 }
347 };
348
349 window.addEventListener = document.addEventListener = addEventListener;
350 window.removeEventListener = document.removeEventListener = removeEventListener;
351
352 if ("Element" in window) {
353 Element.prototype.addEventListener = addEventListener;
354 Element.prototype.removeEventListener = removeEventListener;
355 } else {
356 head = document.getElementsByTagName("head")[0];
357 style = document.createElement("style");
358
359 head.insertBefore(style, head.firstChild);
360
361 style.styleSheet.cssText = "*{-ms-event-prototype:expression(!this.addEventListener&&(this.addEventListener=addEventListener)&&(this.removeEventListener=removeEventListener))}";
362 }
363
364 addEventListener.simulant = true;
365 }
366 var polyfill__default = polyfill__polyfill;
367
368 var simulant__simulant;
369
370 try {
371 new MouseEvent("click");
372 simulant__simulant = modern__default();
373 } catch (err) {
374 if (!document.createEvent) {
375 if (document.createEventObject) {
376 simulant__simulant = ancient__default();
377 } else {
378 throw new Error("Events cannot be created in this browser");
379 }
380 } else {
381 simulant__simulant = legacy__default();
382 }
383 }
384
385 if (document.dispatchEvent) {
386 simulant__simulant.fire = function (node, event, params) {
387 if (typeof event === "string") {
388 event = simulant__simulant(event, params);
389 }
390
391 node.dispatchEvent(event);
392 return event;
393 };
394 } else if (document.fireEvent) {
395 simulant__simulant.fire = function (node, event, params) {
396 if (typeof event === "string") {
397 event = simulant__simulant(event, params);
398 }
399
400 node.fireEvent("on" + event.type, event);
401
402 // Special case - checkbox inputs
403 if (node.tagName === "INPUT" && node.type === "checkbox") {
404 node.click();
405 }
406 return event;
407 };
408 }
409
410 simulant__simulant.polyfill = polyfill__default;
411
412 var simulant__default = simulant__simulant;
413
414 return simulant__default;
415}));
\No newline at end of file