Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
SeleniumHQ
GitHub Repository: SeleniumHQ/Selenium
Path: blob/trunk/javascript/atoms/events.js
3985 views
1
// Licensed to the Software Freedom Conservancy (SFC) under one
2
// or more contributor license agreements. See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership. The SFC licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License. You may obtain a copy of the License at
8
//
9
// http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied. See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
/**
19
* @fileoverview Functions to do with firing and simulating events.
20
*/
21
22
23
goog.provide('bot.events');
24
goog.provide('bot.events.EventArgs');
25
goog.provide('bot.events.EventType');
26
goog.provide('bot.events.KeyboardArgs');
27
goog.provide('bot.events.MSGestureArgs');
28
goog.provide('bot.events.MSPointerArgs');
29
goog.provide('bot.events.MouseArgs');
30
goog.provide('bot.events.Touch');
31
goog.provide('bot.events.TouchArgs');
32
33
goog.require('bot');
34
goog.require('bot.Error');
35
goog.require('bot.ErrorCode');
36
goog.require('bot.userAgent');
37
goog.require('goog.array');
38
goog.require('goog.dom');
39
goog.require('goog.events.BrowserEvent');
40
goog.require('goog.style');
41
goog.require('goog.userAgent');
42
goog.require('goog.userAgent.product');
43
goog.require('goog.utils');
44
45
46
/**
47
* Whether the browser supports the construction of touch events.
48
*
49
* @const
50
* @type {boolean}
51
*/
52
bot.events.SUPPORTS_TOUCH_EVENTS = !(goog.userAgent.IE &&
53
!bot.userAgent.isEngineVersion(10));
54
55
56
/**
57
* Whether the browser supports a native touch api.
58
* @private {boolean}
59
* @const
60
*/
61
bot.events.BROKEN_TOUCH_API_ = (function () {
62
if (goog.userAgent.product.ANDROID) {
63
// Native touch api supported starting in version 4.0 (Ice Cream Sandwich).
64
return !bot.userAgent.isProductVersion(4);
65
}
66
return !bot.userAgent.IOS;
67
})();
68
69
70
/**
71
* Whether the browser supports the construction of MSPointer events.
72
*
73
* @const
74
* @type {boolean}
75
*/
76
bot.events.SUPPORTS_MSPOINTER_EVENTS =
77
goog.userAgent.IE && bot.getWindow().navigator.msPointerEnabled;
78
79
80
/**
81
* Arguments to initialize an event.
82
*
83
* @typedef {bot.events.MouseArgs|bot.events.KeyboardArgs|bot.events.TouchArgs|
84
bot.events.MSGestureArgs|bot.events.MSPointerArgs}
85
*/
86
bot.events.EventArgs;
87
88
89
/**
90
* Arguments to initialize a mouse event.
91
*
92
* @typedef {{clientX: number,
93
* clientY: number,
94
* button: number,
95
* altKey: boolean,
96
* ctrlKey: boolean,
97
* shiftKey: boolean,
98
* metaKey: boolean,
99
* relatedTarget: Element,
100
* wheelDelta: number}}
101
*/
102
bot.events.MouseArgs;
103
104
105
/**
106
* Arguments to initialize a keyboard event.
107
*
108
* @typedef {{keyCode: number,
109
* charCode: number,
110
* altKey: boolean,
111
* ctrlKey: boolean,
112
* shiftKey: boolean,
113
* metaKey: boolean,
114
* preventDefault: boolean}}
115
*/
116
bot.events.KeyboardArgs;
117
118
119
/**
120
* Argument to initialize a touch event.
121
*
122
* @typedef {{touches: !Array.<bot.events.Touch>,
123
* targetTouches: !Array.<bot.events.Touch>,
124
* changedTouches: !Array.<bot.events.Touch>,
125
* altKey: boolean,
126
* ctrlKey: boolean,
127
* shiftKey: boolean,
128
* metaKey: boolean,
129
* relatedTarget: Element,
130
* scale: number,
131
* rotation: number}}
132
*/
133
bot.events.TouchArgs;
134
135
136
/**
137
* @typedef {{identifier: number,
138
* screenX: number,
139
* screenY: number,
140
* clientX: number,
141
* clientY: number,
142
* pageX: number,
143
* pageY: number}}
144
*/
145
bot.events.Touch;
146
147
148
/**
149
* Arguments to initialize an MSGesture event.
150
*
151
* @typedef {{clientX: number,
152
* clientY: number,
153
* translationX: number,
154
* translationY: number,
155
* scale: number,
156
* expansion: number,
157
* rotation: number,
158
* velocityX: number,
159
* velocityY: number,
160
* velocityExpansion: number,
161
* velocityAngular: number,
162
* relatedTarget: Element}}
163
*/
164
bot.events.MSGestureArgs;
165
166
167
/**
168
* Arguments to initialize an MSPointer event.
169
*
170
* @typedef {{clientX: number,
171
* clientY: number,
172
* button: number,
173
* altKey: boolean,
174
* ctrlKey: boolean,
175
* shiftKey: boolean,
176
* metaKey: boolean,
177
* relatedTarget: Element,
178
* width: number,
179
* height: number,
180
* pressure: number,
181
* rotation: number,
182
* pointerId: number,
183
* tiltX: number,
184
* tiltY: number,
185
* pointerType: number,
186
* isPrimary: boolean}}
187
*/
188
bot.events.MSPointerArgs;
189
190
191
192
/**
193
* Factory for event objects of a specific type.
194
*
195
* @constructor
196
* @param {string} type Type of the created events.
197
* @param {boolean} bubbles Whether the created events bubble.
198
* @param {boolean} cancelable Whether the created events are cancelable.
199
* @private
200
*/
201
bot.events.EventFactory_ = function (type, bubbles, cancelable) {
202
/** @private {string} */
203
this.type_ = type;
204
205
/** @private {boolean} */
206
this.bubbles_ = bubbles;
207
208
/** @private {boolean} */
209
this.cancelable_ = cancelable;
210
};
211
212
213
/**
214
* Creates an event.
215
*
216
* @param {!Element|!Window} target Target element of the event.
217
* @param {bot.events.EventArgs=} opt_args Event arguments.
218
* @return {!Event} Newly created event.
219
*/
220
bot.events.EventFactory_.prototype.create = function (target, opt_args) {
221
var doc = goog.dom.getOwnerDocument(target);
222
223
var event = doc.createEvent('HTMLEvents');
224
event.initEvent(this.type_, this.bubbles_, this.cancelable_);
225
226
return event;
227
};
228
229
230
/**
231
* Overriding toString to return the unique type string improves debugging,
232
* and it allows event types to be mapped in JS objects without collisions.
233
*
234
* @return {string} String representation of the event type.
235
* @override
236
*/
237
bot.events.EventFactory_.prototype.toString = function () {
238
return this.type_;
239
};
240
241
242
243
/**
244
* Factory for mouse event objects of a specific type.
245
*
246
* @constructor
247
* @param {string} type Type of the created events.
248
* @param {boolean} bubbles Whether the created events bubble.
249
* @param {boolean} cancelable Whether the created events are cancelable.
250
* @extends {bot.events.EventFactory_}
251
* @private
252
*/
253
bot.events.MouseEventFactory_ = function (type, bubbles, cancelable) {
254
bot.events.EventFactory_.call(this, type, bubbles, cancelable);
255
};
256
goog.utils.inherits(bot.events.MouseEventFactory_, bot.events.EventFactory_);
257
258
259
/**
260
* @override
261
* @param {!Element|!Window} target Target element of the event.
262
* @param {bot.events.EventArgs=} opt_args Event arguments.
263
* @return {!Event} Newly created event.
264
*/
265
bot.events.MouseEventFactory_.prototype.create = function (target, opt_args) {
266
// Only Gecko supports the mouse pixel scroll event.
267
if (!goog.userAgent.GECKO && this == bot.events.EventType.MOUSEPIXELSCROLL) {
268
throw new bot.Error(bot.ErrorCode.UNSUPPORTED_OPERATION,
269
'Browser does not support a mouse pixel scroll event.');
270
}
271
272
var args = /** @type {!bot.events.MouseArgs} */ (opt_args);
273
var doc = goog.dom.getOwnerDocument(target);
274
var event;
275
276
var view = goog.dom.getWindow(doc);
277
event = doc.createEvent('MouseEvents');
278
var detail = 1;
279
280
// All browser but Firefox provide the wheelDelta value in the event.
281
// Firefox provides the scroll amount in the detail field, where it has the
282
// opposite polarity of the wheelDelta (upward scroll is negative) and is a
283
// factor of 40 less than the wheelDelta value.
284
// The wheelDelta value is normally some multiple of 40.
285
if (this == bot.events.EventType.MOUSEWHEEL) {
286
if (!goog.userAgent.GECKO) {
287
event.wheelDelta = args.wheelDelta;
288
}
289
if (goog.userAgent.GECKO) {
290
detail = args.wheelDelta / -40;
291
}
292
}
293
294
// Only Gecko supports a mouse pixel scroll event, so we use it as the
295
// "standard" and pass it along as is as the "detail" of the event.
296
if (goog.userAgent.GECKO && this == bot.events.EventType.MOUSEPIXELSCROLL) {
297
detail = args.wheelDelta;
298
}
299
300
// For screenX and screenY, we set those to clientX and clientY values.
301
// While not strictly correct, applications under test depend on
302
// accurate relative positioning which is satisfied.
303
event.initMouseEvent(this.type_, this.bubbles_, this.cancelable_, view,
304
detail, /*screenX*/ args.clientX, /*screenY*/ args.clientY,
305
args.clientX, args.clientY, args.ctrlKey, args.altKey,
306
args.shiftKey, args.metaKey, args.button, args.relatedTarget);
307
308
// Trying to modify the properties throws an error,
309
// so we define getters to return the correct values.
310
if (goog.userAgent.IE &&
311
event.pageX === 0 && event.pageY === 0 && Object.defineProperty) {
312
var scrollElem = goog.dom.getDomHelper(target).getDocumentScrollElement();
313
var clientElem = goog.style.getClientViewportElement(doc);
314
var pageX = args.clientX + scrollElem.scrollLeft - clientElem.clientLeft;
315
var pageY = args.clientY + scrollElem.scrollTop - clientElem.clientTop;
316
317
Object.defineProperty(event, 'pageX', {
318
get: function () {
319
return pageX;
320
}
321
});
322
Object.defineProperty(event, 'pageY', {
323
get: function () {
324
return pageY;
325
}
326
});
327
}
328
329
return event;
330
};
331
332
333
334
/**
335
* Factory for keyboard event objects of a specific type.
336
*
337
* @constructor
338
* @param {string} type Type of the created events.
339
* @param {boolean} bubbles Whether the created events bubble.
340
* @param {boolean} cancelable Whether the created events are cancelable.
341
* @extends {bot.events.EventFactory_}
342
* @private
343
*/
344
bot.events.KeyboardEventFactory_ = function (type, bubbles, cancelable) {
345
bot.events.EventFactory_.call(this, type, bubbles, cancelable);
346
};
347
goog.utils.inherits(bot.events.KeyboardEventFactory_, bot.events.EventFactory_);
348
349
350
/**
351
* @override
352
* @param {!Element|!Window} target Target element of the event.
353
* @param {bot.events.EventArgs=} opt_args Event arguments.
354
* @return {!Event} Newly created event.
355
*/
356
bot.events.KeyboardEventFactory_.prototype.create = function (target, opt_args) {
357
var args = /** @type {!bot.events.KeyboardArgs} */ (opt_args);
358
var doc = goog.dom.getOwnerDocument(target);
359
var event;
360
361
if (goog.userAgent.GECKO && !bot.userAgent.isEngineVersion(93)) {
362
var view = goog.dom.getWindow(doc);
363
var keyCode = args.charCode ? 0 : args.keyCode;
364
event = doc.createEvent('KeyboardEvent');
365
event.initKeyEvent(this.type_, this.bubbles_, this.cancelable_, view,
366
args.ctrlKey, args.altKey, args.shiftKey, args.metaKey, keyCode,
367
args.charCode);
368
// https://bugzilla.mozilla.org/show_bug.cgi?id=501496
369
if (this.type_ == bot.events.EventType.KEYPRESS && args.preventDefault) {
370
event.preventDefault();
371
}
372
} else {
373
event = doc.createEvent('Events');
374
event.initEvent(this.type_, this.bubbles_, this.cancelable_);
375
event.altKey = args.altKey;
376
event.ctrlKey = args.ctrlKey;
377
event.metaKey = args.metaKey;
378
event.shiftKey = args.shiftKey;
379
if (goog.userAgent.GECKO) {
380
event.keyCode = args.charCode ? 0 : args.keyCode;
381
event.charCode = args.charCode;
382
} else {
383
event.keyCode = args.charCode || args.keyCode;
384
if (goog.userAgent.WEBKIT || goog.userAgent.EDGE) {
385
event.charCode = (this == bot.events.EventType.KEYPRESS) ?
386
event.keyCode : 0;
387
}
388
}
389
}
390
391
return event;
392
};
393
394
395
396
/**
397
* Enum representing which mechanism to use for creating touch events.
398
* @enum {number}
399
* @private
400
*/
401
bot.events.TouchEventStrategy_ = {
402
MOUSE_EVENTS: 1,
403
INIT_TOUCH_EVENT: 2,
404
TOUCH_EVENT_CTOR: 3
405
};
406
407
408
409
/**
410
* Factory for touch event objects of a specific type.
411
*
412
* @constructor
413
* @param {string} type Type of the created events.
414
* @param {boolean} bubbles Whether the created events bubble.
415
* @param {boolean} cancelable Whether the created events are cancelable.
416
* @extends {bot.events.EventFactory_}
417
* @private
418
*/
419
bot.events.TouchEventFactory_ = function (type, bubbles, cancelable) {
420
bot.events.EventFactory_.call(this, type, bubbles, cancelable);
421
};
422
goog.utils.inherits(bot.events.TouchEventFactory_, bot.events.EventFactory_);
423
424
425
/**
426
* @override
427
* @param {!Element|!Window} target Target element of the event.
428
* @param {bot.events.EventArgs=} opt_args Event arguments.
429
* @return {!Event} Newly created event.
430
*/
431
bot.events.TouchEventFactory_.prototype.create = function (target, opt_args) {
432
if (!bot.events.SUPPORTS_TOUCH_EVENTS) {
433
throw new bot.Error(bot.ErrorCode.UNSUPPORTED_OPERATION,
434
'Browser does not support firing touch events.');
435
}
436
437
var args = /** @type {!bot.events.TouchArgs} */ (opt_args);
438
var doc = goog.dom.getOwnerDocument(target);
439
var view = goog.dom.getWindow(doc);
440
441
// Creates a TouchList, using native touch Api, for touch events.
442
function createNativeTouchList(touchListArgs) {
443
var touches = goog.array.map(touchListArgs, function (touchArg) {
444
return doc.createTouch(view, target, touchArg.identifier,
445
touchArg.pageX, touchArg.pageY, touchArg.screenX, touchArg.screenY);
446
});
447
448
return doc.createTouchList.apply(doc, touches);
449
}
450
451
// Creates a TouchList, using simulated touch Api, for touch events.
452
function createGenericTouchList(touchListArgs) {
453
var touches = goog.array.map(touchListArgs, function (touchArg) {
454
// The target field is not part of the W3C spec, but both android and iOS
455
// add the target field to each touch.
456
return {
457
identifier: touchArg.identifier,
458
screenX: touchArg.screenX,
459
screenY: touchArg.screenY,
460
clientX: touchArg.clientX,
461
clientY: touchArg.clientY,
462
pageX: touchArg.pageX,
463
pageY: touchArg.pageY,
464
target: target
465
};
466
});
467
touches.item = function (i) {
468
return touches[i];
469
};
470
return touches;
471
}
472
473
function createTouchEventTouchList(touchListArgs) {
474
/** @type {!Array<!Touch>} */
475
var touches = goog.array.map(touchListArgs, function (touchArg) {
476
return new Touch({
477
identifier: touchArg.identifier,
478
screenX: touchArg.screenX,
479
screenY: touchArg.screenY,
480
clientX: touchArg.clientX,
481
clientY: touchArg.clientY,
482
pageX: touchArg.pageX,
483
pageY: touchArg.pageY,
484
target: target
485
});
486
});
487
return touches;
488
}
489
490
function createTouchList(touchStrategy, touches) {
491
switch (touchStrategy) {
492
case bot.events.TouchEventStrategy_.MOUSE_EVENTS:
493
return createGenericTouchList(touches);
494
case bot.events.TouchEventStrategy_.INIT_TOUCH_EVENT:
495
return createNativeTouchList(touches);
496
case bot.events.TouchEventStrategy_.TOUCH_EVENT_CTOR:
497
return createTouchEventTouchList(touches);
498
}
499
return null;
500
}
501
502
// TODO(juangj): Always use the TouchEvent constructor, if available.
503
var strategy;
504
if (bot.events.BROKEN_TOUCH_API_) {
505
strategy = bot.events.TouchEventStrategy_.MOUSE_EVENTS;
506
} else {
507
if (TouchEvent.prototype.initTouchEvent) {
508
strategy = bot.events.TouchEventStrategy_.INIT_TOUCH_EVENT;
509
} else if (TouchEvent && TouchEvent.length > 0) {
510
strategy = bot.events.TouchEventStrategy_.TOUCH_EVENT_CTOR;
511
} else {
512
throw new bot.Error(
513
bot.ErrorCode.UNSUPPORTED_OPERATION,
514
'Not able to create touch events in this browser');
515
}
516
}
517
518
// As a performance optimization, reuse the created touchlist when the lists
519
// are the same, which is often the case in practice.
520
var changedTouches = createTouchList(strategy, args.changedTouches);
521
var touches = (args.touches == args.changedTouches) ?
522
changedTouches : createTouchList(strategy, args.touches);
523
var targetTouches = (args.targetTouches == args.changedTouches) ?
524
changedTouches : createTouchList(strategy, args.targetTouches);
525
526
var event;
527
if (strategy == bot.events.TouchEventStrategy_.MOUSE_EVENTS) {
528
event = doc.createEvent('MouseEvents');
529
event.initMouseEvent(this.type_, this.bubbles_, this.cancelable_, view,
530
/*detail*/ 1, /*screenX*/ 0, /*screenY*/ 0, args.clientX, args.clientY,
531
args.ctrlKey, args.altKey, args.shiftKey, args.metaKey, /*button*/ 0,
532
args.relatedTarget);
533
event.touches = touches;
534
event.targetTouches = targetTouches;
535
event.changedTouches = changedTouches;
536
event.scale = args.scale;
537
event.rotation = args.rotation;
538
} else if (strategy == bot.events.TouchEventStrategy_.INIT_TOUCH_EVENT) {
539
event = doc.createEvent('TouchEvent');
540
// Different browsers have different implementations of initTouchEvent.
541
if (event.initTouchEvent.length == 0) {
542
// Chrome/Android.
543
event.initTouchEvent(touches, targetTouches, changedTouches,
544
this.type_, view, /*screenX*/ 0, /*screenY*/ 0, args.clientX,
545
args.clientY, args.ctrlKey, args.altKey, args.shiftKey, args.metaKey);
546
} else {
547
// iOS.
548
event.initTouchEvent(this.type_, this.bubbles_, this.cancelable_, view,
549
/*detail*/ 1, /*screenX*/ 0, /*screenY*/ 0, args.clientX,
550
args.clientY, args.ctrlKey, args.altKey, args.shiftKey, args.metaKey,
551
touches, targetTouches, changedTouches, args.scale, args.rotation);
552
}
553
event.relatedTarget = args.relatedTarget;
554
} else if (strategy == bot.events.TouchEventStrategy_.TOUCH_EVENT_CTOR) {
555
var touchProperties = /** @type {!TouchEventInit} */ ({
556
touches: touches,
557
targetTouches: targetTouches,
558
changedTouches: changedTouches,
559
bubbles: this.bubbles_,
560
cancelable: this.cancelable_,
561
ctrlKey: args.ctrlKey,
562
shiftKey: args.shiftKey,
563
altKey: args.altKey,
564
metaKey: args.metaKey
565
});
566
event = new TouchEvent(this.type_, touchProperties);
567
} else {
568
throw new bot.Error(
569
bot.ErrorCode.UNSUPPORTED_OPERATION,
570
'Illegal TouchEventStrategy_ value (this is a bug)');
571
}
572
573
return event;
574
};
575
576
577
578
/**
579
* Factory for MSGesture event objects of a specific type.
580
*
581
* @constructor
582
* @param {string} type Type of the created events.
583
* @param {boolean} bubbles Whether the created events bubble.
584
* @param {boolean} cancelable Whether the created events are cancelable.
585
* @extends {bot.events.EventFactory_}
586
* @private
587
*/
588
bot.events.MSGestureEventFactory_ = function (type, bubbles, cancelable) {
589
bot.events.EventFactory_.call(this, type, bubbles, cancelable);
590
};
591
goog.utils.inherits(bot.events.MSGestureEventFactory_, bot.events.EventFactory_);
592
593
594
/**
595
* @override
596
* @param {!Element|!Window} target Target element of the event.
597
* @param {bot.events.EventArgs=} opt_args Event arguments.
598
* @return {!Event} Newly created event.
599
*/
600
bot.events.MSGestureEventFactory_.prototype.create = function (target,
601
opt_args) {
602
if (!bot.events.SUPPORTS_MSPOINTER_EVENTS) {
603
throw new bot.Error(bot.ErrorCode.UNSUPPORTED_OPERATION,
604
'Browser does not support MSGesture events.');
605
}
606
607
var args = /** @type {!bot.events.MSGestureArgs} */ (opt_args);
608
var doc = goog.dom.getOwnerDocument(target);
609
var view = goog.dom.getWindow(doc);
610
var event = doc.createEvent('MSGestureEvent');
611
var timestamp = (new Date).getTime();
612
613
// See http://msdn.microsoft.com/en-us/library/windows/apps/hh441187.aspx
614
event.initGestureEvent(this.type_, this.bubbles_, this.cancelable_, view,
615
/*detail*/ 1, /*screenX*/ 0, /*screenY*/ 0,
616
args.clientX, args.clientY, /*offsetX*/ 0,
617
/*offsetY*/ 0, args.translationX, args.translationY,
618
args.scale, args.expansion, args.rotation,
619
args.velocityX, args.velocityY, args.velocityExpansion,
620
args.velocityAngular, timestamp, args.relatedTarget);
621
return event;
622
};
623
624
625
626
/**
627
* Factory for MSPointer event objects of a specific type.
628
*
629
* @constructor
630
* @param {string} type Type of the created events.
631
* @param {boolean} bubbles Whether the created events bubble.
632
* @param {boolean} cancelable Whether the created events are cancelable.
633
* @extends {bot.events.EventFactory_}
634
* @private
635
*/
636
bot.events.MSPointerEventFactory_ = function (type, bubbles, cancelable) {
637
bot.events.EventFactory_.call(this, type, bubbles, cancelable);
638
};
639
goog.utils.inherits(bot.events.MSPointerEventFactory_, bot.events.EventFactory_);
640
641
642
/**
643
* @override
644
* @param {!Element|!Window} target Target element of the event.
645
* @param {bot.events.EventArgs=} opt_args Event arguments.
646
* @return {!Event} Newly created event.
647
* @suppress {checkTypes} Closure compiler externs don't know about pointer
648
* events
649
*/
650
bot.events.MSPointerEventFactory_.prototype.create = function (target,
651
opt_args) {
652
if (!bot.events.SUPPORTS_MSPOINTER_EVENTS) {
653
throw new bot.Error(bot.ErrorCode.UNSUPPORTED_OPERATION,
654
'Browser does not support MSPointer events.');
655
}
656
657
var args = /** @type {!bot.events.MSPointerArgs} */ (opt_args);
658
var doc = goog.dom.getOwnerDocument(target);
659
var view = goog.dom.getWindow(doc);
660
var event = doc.createEvent('MSPointerEvent');
661
662
// See http://msdn.microsoft.com/en-us/library/ie/hh772109(v=vs.85).aspx
663
event.initPointerEvent(this.type_, this.bubbles_, this.cancelable_, view,
664
/*detail*/ 0, /*screenX*/ 0, /*screenY*/ 0,
665
args.clientX, args.clientY, args.ctrlKey, args.altKey,
666
args.shiftKey, args.metaKey, args.button,
667
args.relatedTarget, /*offsetX*/ 0, /*offsetY*/ 0,
668
args.width, args.height, args.pressure, args.rotation,
669
args.tiltX, args.tiltY, args.pointerId,
670
args.pointerType, /*hwTimeStamp*/ 0, args.isPrimary);
671
672
return event;
673
};
674
675
676
/**
677
* The types of events this modules supports firing.
678
*
679
* <p>To see which events bubble and are cancelable, see:
680
* http://en.wikipedia.org/wiki/DOM_events and
681
* http://www.w3.org/Submission/pointer-events/#pointer-event-types
682
*
683
* @const {!Object<string, !bot.events.EventFactory_>}
684
*/
685
bot.events.EventType = {
686
BLUR: new bot.events.EventFactory_('blur', false, false),
687
CHANGE: new bot.events.EventFactory_('change', true, false),
688
FOCUS: new bot.events.EventFactory_('focus', false, false),
689
FOCUSIN: new bot.events.EventFactory_('focusin', true, false),
690
FOCUSOUT: new bot.events.EventFactory_('focusout', true, false),
691
INPUT: new bot.events.EventFactory_('input', true, false),
692
ORIENTATIONCHANGE: new bot.events.EventFactory_(
693
'orientationchange', false, false),
694
PROPERTYCHANGE: new bot.events.EventFactory_('propertychange', false, false),
695
SELECT: new bot.events.EventFactory_('select', true, false),
696
SUBMIT: new bot.events.EventFactory_('submit', true, true),
697
TEXTINPUT: new bot.events.EventFactory_('textInput', true, true),
698
699
// Mouse events.
700
CLICK: new bot.events.MouseEventFactory_('click', true, true),
701
CONTEXTMENU: new bot.events.MouseEventFactory_('contextmenu', true, true),
702
DBLCLICK: new bot.events.MouseEventFactory_('dblclick', true, true),
703
MOUSEDOWN: new bot.events.MouseEventFactory_('mousedown', true, true),
704
MOUSEMOVE: new bot.events.MouseEventFactory_('mousemove', true, false),
705
MOUSEOUT: new bot.events.MouseEventFactory_('mouseout', true, true),
706
MOUSEOVER: new bot.events.MouseEventFactory_('mouseover', true, true),
707
MOUSEUP: new bot.events.MouseEventFactory_('mouseup', true, true),
708
MOUSEWHEEL: new bot.events.MouseEventFactory_(
709
goog.userAgent.GECKO ? 'DOMMouseScroll' : 'mousewheel', true, true),
710
MOUSEPIXELSCROLL: new bot.events.MouseEventFactory_(
711
'MozMousePixelScroll', true, true),
712
713
// Keyboard events.
714
KEYDOWN: new bot.events.KeyboardEventFactory_('keydown', true, true),
715
KEYPRESS: new bot.events.KeyboardEventFactory_('keypress', true, true),
716
KEYUP: new bot.events.KeyboardEventFactory_('keyup', true, true),
717
718
// Touch events.
719
TOUCHEND: new bot.events.TouchEventFactory_('touchend', true, true),
720
TOUCHMOVE: new bot.events.TouchEventFactory_('touchmove', true, true),
721
TOUCHSTART: new bot.events.TouchEventFactory_('touchstart', true, true),
722
723
// MSGesture events
724
MSGESTURECHANGE: new bot.events.MSGestureEventFactory_(
725
'MSGestureChange', true, true),
726
MSGESTUREEND: new bot.events.MSGestureEventFactory_(
727
'MSGestureEnd', true, true),
728
MSGESTUREHOLD: new bot.events.MSGestureEventFactory_(
729
'MSGestureHold', true, true),
730
MSGESTURESTART: new bot.events.MSGestureEventFactory_(
731
'MSGestureStart', true, true),
732
MSGESTURETAP: new bot.events.MSGestureEventFactory_(
733
'MSGestureTap', true, true),
734
MSINERTIASTART: new bot.events.MSGestureEventFactory_(
735
'MSInertiaStart', true, true),
736
737
// MSPointer events
738
MSGOTPOINTERCAPTURE: new bot.events.MSPointerEventFactory_(
739
'MSGotPointerCapture', true, false),
740
MSLOSTPOINTERCAPTURE: new bot.events.MSPointerEventFactory_(
741
'MSLostPointerCapture', true, false),
742
MSPOINTERCANCEL: new bot.events.MSPointerEventFactory_(
743
'MSPointerCancel', true, true),
744
MSPOINTERDOWN: new bot.events.MSPointerEventFactory_(
745
'MSPointerDown', true, true),
746
MSPOINTERMOVE: new bot.events.MSPointerEventFactory_(
747
'MSPointerMove', true, true),
748
MSPOINTEROVER: new bot.events.MSPointerEventFactory_(
749
'MSPointerOver', true, true),
750
MSPOINTEROUT: new bot.events.MSPointerEventFactory_(
751
'MSPointerOut', true, true),
752
MSPOINTERUP: new bot.events.MSPointerEventFactory_(
753
'MSPointerUp', true, true)
754
};
755
756
757
/**
758
* Fire a named event on a particular element.
759
*
760
* @param {!Element|!Window} target The element on which to fire the event.
761
* @param {!bot.events.EventFactory_} type Event type.
762
* @param {bot.events.EventArgs=} opt_args Arguments to initialize the event.
763
* @return {boolean} Whether the event fired successfully or was cancelled.
764
*/
765
bot.events.fire = function (target, type, opt_args) {
766
var event = type.create(target, opt_args);
767
768
// Ensure the event's isTrusted property is set to false, so that
769
// bot.events.isSynthetic() can identify synthetic events from native ones.
770
if (!('isTrusted' in event)) {
771
event['isTrusted'] = false;
772
}
773
return target.dispatchEvent(event);
774
};
775
776
777
/**
778
* Returns whether the event was synthetically created by the atoms;
779
* if false, was created by the browser in response to a live user action.
780
*
781
* @param {!(Event|goog.events.BrowserEvent)} event An event.
782
* @return {boolean} Whether the event was synthetically created.
783
*/
784
bot.events.isSynthetic = function (event) {
785
var e = event.getBrowserEvent ? event.getBrowserEvent() : event;
786
return 'isTrusted' in e ? !e['isTrusted'] : false;
787
};
788
789