2 Copyright (c) 2009, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.net/yui/license.txt
9 * DOM event simulation utility
10 * @module event-simulate
11 * @namespace YAHOO.util
12 * @requires yahoo,dom,event
16 * The UserAction object provides functions that simulate events occurring in
17 * the browser. Since these are simulated events, they do not behave exactly
18 * as regular, user-initiated events do, but can be used to test simple
19 * user interactions safely.
21 * @namespace YAHOO.util
25 YAHOO.util.UserAction = {
27 //--------------------------------------------------------------------------
28 // Generic event methods
29 //--------------------------------------------------------------------------
32 * Simulates a key event using the given event information to populate
33 * the generated event object. This method does browser-equalizing
34 * calculations to account for differences in the DOM and IE event models
35 * as well as different browser quirks. Note: keydown causes Safari 2.x to
37 * @method simulateKeyEvent
40 * @param {HTMLElement} target The target of the given event.
41 * @param {String} type The type of event to fire. This can be any one of
42 * the following: keyup, keydown, and keypress.
43 * @param {Boolean} bubbles (Optional) Indicates if the event can be
44 * bubbled up. DOM Level 3 specifies that all key events bubble by
45 * default. The default is true.
46 * @param {Boolean} cancelable (Optional) Indicates if the event can be
47 * canceled using preventDefault(). DOM Level 3 specifies that all
48 * key events can be cancelled. The default
50 * @param {Window} view (Optional) The view containing the target. This is
51 * typically the window object. The default is window.
52 * @param {Boolean} ctrlKey (Optional) Indicates if one of the CTRL keys
53 * is pressed while the event is firing. The default is false.
54 * @param {Boolean} altKey (Optional) Indicates if one of the ALT keys
55 * is pressed while the event is firing. The default is false.
56 * @param {Boolean} shiftKey (Optional) Indicates if one of the SHIFT keys
57 * is pressed while the event is firing. The default is false.
58 * @param {Boolean} metaKey (Optional) Indicates if one of the META keys
59 * is pressed while the event is firing. The default is false.
60 * @param {int} keyCode (Optional) The code for the key that is in use.
62 * @param {int} charCode (Optional) The Unicode code for the character
63 * associated with the key being used. The default is 0.
65 simulateKeyEvent : function (target /*:HTMLElement*/, type /*:String*/,
66 bubbles /*:Boolean*/, cancelable /*:Boolean*/,
68 ctrlKey /*:Boolean*/, altKey /*:Boolean*/,
69 shiftKey /*:Boolean*/, metaKey /*:Boolean*/,
70 keyCode /*:int*/, charCode /*:int*/) /*:Void*/
73 target = YAHOO.util.Dom.get(target);
75 throw new Error("simulateKeyEvent(): Invalid target.");
79 if (YAHOO.lang.isString(type)){
80 type = type.toLowerCase();
86 case "textevent": //DOM Level 3
89 // @TODO was the fallthrough intentional, if so throw error
91 throw new Error("simulateKeyEvent(): Event type '" + type + "' not supported.");
94 throw new Error("simulateKeyEvent(): Event type must be a string.");
97 //setup default values
98 if (!YAHOO.lang.isBoolean(bubbles)){
99 bubbles = true; //all key events bubble
101 if (!YAHOO.lang.isBoolean(cancelable)){
102 cancelable = true; //all key events can be cancelled
104 if (!YAHOO.lang.isObject(view)){
105 view = window; //view is typically window
107 if (!YAHOO.lang.isBoolean(ctrlKey)){
110 if (!YAHOO.lang.isBoolean(altKey)){
113 if (!YAHOO.lang.isBoolean(shiftKey)){
116 if (!YAHOO.lang.isBoolean(metaKey)){
119 if (!YAHOO.lang.isNumber(keyCode)){
122 if (!YAHOO.lang.isNumber(charCode)){
126 //try to create a mouse event
127 var customEvent /*:MouseEvent*/ = null;
129 //check for DOM-compliant browsers first
130 if (YAHOO.lang.isFunction(document.createEvent)){
134 //try to create key event
135 customEvent = document.createEvent("KeyEvents");
138 * Interesting problem: Firefox implemented a non-standard
139 * version of initKeyEvent() based on DOM Level 2 specs.
140 * Key event was removed from DOM Level 2 and re-introduced
141 * in DOM Level 3 with a different interface. Firefox is the
142 * only browser with any implementation of Key Events, so for
143 * now, assume it's Firefox if the above line doesn't error.
145 //TODO: Decipher between Firefox's implementation and a correct one.
146 customEvent.initKeyEvent(type, bubbles, cancelable, view, ctrlKey,
147 altKey, shiftKey, metaKey, keyCode, charCode);
149 } catch (ex /*:Error*/){
152 * If it got here, that means key events aren't officially supported.
153 * Safari/WebKit is a real problem now. WebKit 522 won't let you
154 * set keyCode, charCode, or other properties if you use a
155 * UIEvent, so we first must try to create a generic event. The
156 * fun part is that this will throw an error on Safari 2.x. The
157 * end result is that we need another try...catch statement just to
158 * deal with this mess.
162 //try to create generic event - will fail in Safari 2.x
163 customEvent = document.createEvent("Events");
165 } catch (uierror /*:Error*/){
167 //the above failed, so create a UIEvent for Safari 2.x
168 customEvent = document.createEvent("UIEvents");
172 customEvent.initEvent(type, bubbles, cancelable);
175 customEvent.view = view;
176 customEvent.altKey = altKey;
177 customEvent.ctrlKey = ctrlKey;
178 customEvent.shiftKey = shiftKey;
179 customEvent.metaKey = metaKey;
180 customEvent.keyCode = keyCode;
181 customEvent.charCode = charCode;
188 target.dispatchEvent(customEvent);
190 } else if (YAHOO.lang.isObject(document.createEventObject)){ //IE
192 //create an IE event object
193 customEvent = document.createEventObject();
195 //assign available properties
196 customEvent.bubbles = bubbles;
197 customEvent.cancelable = cancelable;
198 customEvent.view = view;
199 customEvent.ctrlKey = ctrlKey;
200 customEvent.altKey = altKey;
201 customEvent.shiftKey = shiftKey;
202 customEvent.metaKey = metaKey;
205 * IE doesn't support charCode explicitly. CharCode should
206 * take precedence over any keyCode value for accurate
209 customEvent.keyCode = (charCode > 0) ? charCode : keyCode;
212 target.fireEvent("on" + type, customEvent);
215 throw new Error("simulateKeyEvent(): No event simulation framework present.");
220 * Simulates a mouse event using the given event information to populate
221 * the generated event object. This method does browser-equalizing
222 * calculations to account for differences in the DOM and IE event models
223 * as well as different browser quirks.
224 * @method simulateMouseEvent
227 * @param {HTMLElement} target The target of the given event.
228 * @param {String} type The type of event to fire. This can be any one of
229 * the following: click, dblclick, mousedown, mouseup, mouseout,
230 * mouseover, and mousemove.
231 * @param {Boolean} bubbles (Optional) Indicates if the event can be
232 * bubbled up. DOM Level 2 specifies that all mouse events bubble by
233 * default. The default is true.
234 * @param {Boolean} cancelable (Optional) Indicates if the event can be
235 * canceled using preventDefault(). DOM Level 2 specifies that all
236 * mouse events except mousemove can be cancelled. The default
237 * is true for all events except mousemove, for which the default
239 * @param {Window} view (Optional) The view containing the target. This is
240 * typically the window object. The default is window.
241 * @param {int} detail (Optional) The number of times the mouse button has
242 * been used. The default value is 1.
243 * @param {int} screenX (Optional) The x-coordinate on the screen at which
244 * point the event occured. The default is 0.
245 * @param {int} screenY (Optional) The y-coordinate on the screen at which
246 * point the event occured. The default is 0.
247 * @param {int} clientX (Optional) The x-coordinate on the client at which
248 * point the event occured. The default is 0.
249 * @param {int} clientY (Optional) The y-coordinate on the client at which
250 * point the event occured. The default is 0.
251 * @param {Boolean} ctrlKey (Optional) Indicates if one of the CTRL keys
252 * is pressed while the event is firing. The default is false.
253 * @param {Boolean} altKey (Optional) Indicates if one of the ALT keys
254 * is pressed while the event is firing. The default is false.
255 * @param {Boolean} shiftKey (Optional) Indicates if one of the SHIFT keys
256 * is pressed while the event is firing. The default is false.
257 * @param {Boolean} metaKey (Optional) Indicates if one of the META keys
258 * is pressed while the event is firing. The default is false.
259 * @param {int} button (Optional) The button being pressed while the event
260 * is executing. The value should be 0 for the primary mouse button
261 * (typically the left button), 1 for the terciary mouse button
262 * (typically the middle button), and 2 for the secondary mouse button
263 * (typically the right button). The default is 0.
264 * @param {HTMLElement} relatedTarget (Optional) For mouseout events,
265 * this is the element that the mouse has moved to. For mouseover
266 * events, this is the element that the mouse has moved from. This
267 * argument is ignored for all other events. The default is null.
269 simulateMouseEvent : function (target /*:HTMLElement*/, type /*:String*/,
270 bubbles /*:Boolean*/, cancelable /*:Boolean*/,
271 view /*:Window*/, detail /*:int*/,
272 screenX /*:int*/, screenY /*:int*/,
273 clientX /*:int*/, clientY /*:int*/,
274 ctrlKey /*:Boolean*/, altKey /*:Boolean*/,
275 shiftKey /*:Boolean*/, metaKey /*:Boolean*/,
276 button /*:int*/, relatedTarget /*:HTMLElement*/) /*:Void*/
280 target = YAHOO.util.Dom.get(target);
282 throw new Error("simulateMouseEvent(): Invalid target.");
286 if (YAHOO.lang.isString(type)){
287 type = type.toLowerCase();
298 throw new Error("simulateMouseEvent(): Event type '" + type + "' not supported.");
301 throw new Error("simulateMouseEvent(): Event type must be a string.");
304 //setup default values
305 if (!YAHOO.lang.isBoolean(bubbles)){
306 bubbles = true; //all mouse events bubble
308 if (!YAHOO.lang.isBoolean(cancelable)){
309 cancelable = (type != "mousemove"); //mousemove is the only one that can't be cancelled
311 if (!YAHOO.lang.isObject(view)){
312 view = window; //view is typically window
314 if (!YAHOO.lang.isNumber(detail)){
315 detail = 1; //number of mouse clicks must be at least one
317 if (!YAHOO.lang.isNumber(screenX)){
320 if (!YAHOO.lang.isNumber(screenY)){
323 if (!YAHOO.lang.isNumber(clientX)){
326 if (!YAHOO.lang.isNumber(clientY)){
329 if (!YAHOO.lang.isBoolean(ctrlKey)){
332 if (!YAHOO.lang.isBoolean(altKey)){
335 if (!YAHOO.lang.isBoolean(shiftKey)){
338 if (!YAHOO.lang.isBoolean(metaKey)){
341 if (!YAHOO.lang.isNumber(button)){
345 //try to create a mouse event
346 var customEvent /*:MouseEvent*/ = null;
348 //check for DOM-compliant browsers first
349 if (YAHOO.lang.isFunction(document.createEvent)){
351 customEvent = document.createEvent("MouseEvents");
353 //Safari 2.x (WebKit 418) still doesn't implement initMouseEvent()
354 if (customEvent.initMouseEvent){
355 customEvent.initMouseEvent(type, bubbles, cancelable, view, detail,
356 screenX, screenY, clientX, clientY,
357 ctrlKey, altKey, shiftKey, metaKey,
358 button, relatedTarget);
361 //the closest thing available in Safari 2.x is UIEvents
362 customEvent = document.createEvent("UIEvents");
363 customEvent.initEvent(type, bubbles, cancelable);
364 customEvent.view = view;
365 customEvent.detail = detail;
366 customEvent.screenX = screenX;
367 customEvent.screenY = screenY;
368 customEvent.clientX = clientX;
369 customEvent.clientY = clientY;
370 customEvent.ctrlKey = ctrlKey;
371 customEvent.altKey = altKey;
372 customEvent.metaKey = metaKey;
373 customEvent.shiftKey = shiftKey;
374 customEvent.button = button;
375 customEvent.relatedTarget = relatedTarget;
379 * Check to see if relatedTarget has been assigned. Firefox
380 * versions less than 2.0 don't allow it to be assigned via
381 * initMouseEvent() and the property is readonly after event
382 * creation, so in order to keep YAHOO.util.getRelatedTarget()
383 * working, assign to the IE proprietary toElement property
384 * for mouseout event and fromElement property for mouseover
387 if (relatedTarget && !customEvent.relatedTarget){
388 if (type == "mouseout"){
389 customEvent.toElement = relatedTarget;
390 } else if (type == "mouseover"){
391 customEvent.fromElement = relatedTarget;
396 target.dispatchEvent(customEvent);
398 } else if (YAHOO.lang.isObject(document.createEventObject)){ //IE
400 //create an IE event object
401 customEvent = document.createEventObject();
403 //assign available properties
404 customEvent.bubbles = bubbles;
405 customEvent.cancelable = cancelable;
406 customEvent.view = view;
407 customEvent.detail = detail;
408 customEvent.screenX = screenX;
409 customEvent.screenY = screenY;
410 customEvent.clientX = clientX;
411 customEvent.clientY = clientY;
412 customEvent.ctrlKey = ctrlKey;
413 customEvent.altKey = altKey;
414 customEvent.metaKey = metaKey;
415 customEvent.shiftKey = shiftKey;
417 //fix button property for IE's wacky implementation
420 customEvent.button = 1;
423 customEvent.button = 4;
429 customEvent.button = 0;
433 * Have to use relatedTarget because IE won't allow assignment
434 * to toElement or fromElement on generic events. This keeps
435 * YAHOO.util.customEvent.getRelatedTarget() functional.
437 customEvent.relatedTarget = relatedTarget;
440 target.fireEvent("on" + type, customEvent);
443 throw new Error("simulateMouseEvent(): No event simulation framework present.");
447 //--------------------------------------------------------------------------
449 //--------------------------------------------------------------------------
452 * Simulates a mouse event on a particular element.
453 * @param {HTMLElement} target The element to click on.
454 * @param {String} type The type of event to fire. This can be any one of
455 * the following: click, dblclick, mousedown, mouseup, mouseout,
456 * mouseover, and mousemove.
457 * @param {Object} options Additional event options (use DOM standard names).
461 fireMouseEvent : function (target /*:HTMLElement*/, type /*:String*/,
462 options /*:Object*/) /*:Void*/
464 options = options || {};
465 this.simulateMouseEvent(target, type, options.bubbles,
466 options.cancelable, options.view, options.detail, options.screenX,
467 options.screenY, options.clientX, options.clientY, options.ctrlKey,
468 options.altKey, options.shiftKey, options.metaKey, options.button,
469 options.relatedTarget);
473 * Simulates a click on a particular element.
474 * @param {HTMLElement} target The element to click on.
475 * @param {Object} options Additional event options (use DOM standard names).
479 click : function (target /*:HTMLElement*/, options /*:Object*/) /*:Void*/ {
480 this.fireMouseEvent(target, "click", options);
484 * Simulates a double click on a particular element.
485 * @param {HTMLElement} target The element to double click on.
486 * @param {Object} options Additional event options (use DOM standard names).
490 dblclick : function (target /*:HTMLElement*/, options /*:Object*/) /*:Void*/ {
491 this.fireMouseEvent( target, "dblclick", options);
495 * Simulates a mousedown on a particular element.
496 * @param {HTMLElement} target The element to act on.
497 * @param {Object} options Additional event options (use DOM standard names).
501 mousedown : function (target /*:HTMLElement*/, options /*Object*/) /*:Void*/ {
502 this.fireMouseEvent(target, "mousedown", options);
506 * Simulates a mousemove on a particular element.
507 * @param {HTMLElement} target The element to act on.
508 * @param {Object} options Additional event options (use DOM standard names).
512 mousemove : function (target /*:HTMLElement*/, options /*Object*/) /*:Void*/ {
513 this.fireMouseEvent(target, "mousemove", options);
517 * Simulates a mouseout event on a particular element. Use "relatedTarget"
518 * on the options object to specify where the mouse moved to.
519 * Quirks: Firefox less than 2.0 doesn't set relatedTarget properly, so
520 * toElement is assigned in its place. IE doesn't allow toElement to be
521 * be assigned, so relatedTarget is assigned in its place. Both of these
522 * concessions allow YAHOO.util.Event.getRelatedTarget() to work correctly
524 * @param {HTMLElement} target The element to act on.
525 * @param {Object} options Additional event options (use DOM standard names).
529 mouseout : function (target /*:HTMLElement*/, options /*Object*/) /*:Void*/ {
530 this.fireMouseEvent(target, "mouseout", options);
534 * Simulates a mouseover event on a particular element. Use "relatedTarget"
535 * on the options object to specify where the mouse moved from.
536 * Quirks: Firefox less than 2.0 doesn't set relatedTarget properly, so
537 * fromElement is assigned in its place. IE doesn't allow fromElement to be
538 * be assigned, so relatedTarget is assigned in its place. Both of these
539 * concessions allow YAHOO.util.Event.getRelatedTarget() to work correctly
541 * @param {HTMLElement} target The element to act on.
542 * @param {Object} options Additional event options (use DOM standard names).
546 mouseover : function (target /*:HTMLElement*/, options /*Object*/) /*:Void*/ {
547 this.fireMouseEvent(target, "mouseover", options);
551 * Simulates a mouseup on a particular element.
552 * @param {HTMLElement} target The element to act on.
553 * @param {Object} options Additional event options (use DOM standard names).
557 mouseup : function (target /*:HTMLElement*/, options /*Object*/) /*:Void*/ {
558 this.fireMouseEvent(target, "mouseup", options);
561 //--------------------------------------------------------------------------
563 //--------------------------------------------------------------------------
566 * Fires an event that normally would be fired by the keyboard (keyup,
567 * keydown, keypress). Make sure to specify either keyCode or charCode as
570 * @param {String} type The type of event ("keyup", "keydown" or "keypress").
571 * @param {HTMLElement} target The target of the event.
572 * @param {Object} options Options for the event. Either keyCode or charCode
574 * @method fireKeyEvent
577 fireKeyEvent : function (type /*:String*/, target /*:HTMLElement*/,
578 options /*:Object*/) /*:Void*/
580 options = options || {};
581 this.simulateKeyEvent(target, type, options.bubbles,
582 options.cancelable, options.view, options.ctrlKey,
583 options.altKey, options.shiftKey, options.metaKey,
584 options.keyCode, options.charCode);
588 * Simulates a keydown event on a particular element.
589 * @param {HTMLElement} target The element to act on.
590 * @param {Object} options Additional event options (use DOM standard names).
594 keydown : function (target /*:HTMLElement*/, options /*:Object*/) /*:Void*/ {
595 this.fireKeyEvent("keydown", target, options);
599 * Simulates a keypress on a particular element.
600 * @param {HTMLElement} target The element to act on.
601 * @param {Object} options Additional event options (use DOM standard names).
605 keypress : function (target /*:HTMLElement*/, options /*:Object*/) /*:Void*/ {
606 this.fireKeyEvent("keypress", target, options);
610 * Simulates a keyup event on a particular element.
611 * @param {HTMLElement} target The element to act on.
612 * @param {Object} options Additional event options (use DOM standard names).
616 keyup : function (target /*:HTMLElement*/, options /*Object*/) /*:Void*/ {
617 this.fireKeyEvent("keyup", target, options);
622 YAHOO.register("event-simulate", YAHOO.util.UserAction, {version: "2.8.0r4", build: "2449"});