2 Copyright (c) 2010, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.com/yui/license.html
8 YUI.add('event-simulate', function(Y) {
12 * Synthetic DOM events
13 * @module event-simulate
20 isFunction = L.isFunction,
21 isString = L.isString,
22 isBoolean = L.isBoolean,
23 isObject = L.isObject,
24 isNumber = L.isNumber,
27 //mouse events supported
38 //key events supported
45 //HTML events supported
55 //events that bubble by default
67 //all key and mouse events bubble
68 Y.mix(bubbleEvents, mouseEvents);
69 Y.mix(bubbleEvents, keyEvents);
72 * Note: Intentionally not for YUIDoc generation.
73 * Simulates a key event using the given event information to populate
74 * the generated event object. This method does browser-equalizing
75 * calculations to account for differences in the DOM and IE event models
76 * as well as different browser quirks. Note: keydown causes Safari 2.x to
78 * @method simulateKeyEvent
81 * @param {HTMLElement} target The target of the given event.
82 * @param {String} type The type of event to fire. This can be any one of
83 * the following: keyup, keydown, and keypress.
84 * @param {Boolean} bubbles (Optional) Indicates if the event can be
85 * bubbled up. DOM Level 3 specifies that all key events bubble by
86 * default. The default is true.
87 * @param {Boolean} cancelable (Optional) Indicates if the event can be
88 * canceled using preventDefault(). DOM Level 3 specifies that all
89 * key events can be cancelled. The default
91 * @param {Window} view (Optional) The view containing the target. This is
92 * typically the window object. The default is window.
93 * @param {Boolean} ctrlKey (Optional) Indicates if one of the CTRL keys
94 * is pressed while the event is firing. The default is false.
95 * @param {Boolean} altKey (Optional) Indicates if one of the ALT keys
96 * is pressed while the event is firing. The default is false.
97 * @param {Boolean} shiftKey (Optional) Indicates if one of the SHIFT keys
98 * is pressed while the event is firing. The default is false.
99 * @param {Boolean} metaKey (Optional) Indicates if one of the META keys
100 * is pressed while the event is firing. The default is false.
101 * @param {int} keyCode (Optional) The code for the key that is in use.
103 * @param {int} charCode (Optional) The Unicode code for the character
104 * associated with the key being used. The default is 0.
106 function simulateKeyEvent(target /*:HTMLElement*/, type /*:String*/,
107 bubbles /*:Boolean*/, cancelable /*:Boolean*/,
109 ctrlKey /*:Boolean*/, altKey /*:Boolean*/,
110 shiftKey /*:Boolean*/, metaKey /*:Boolean*/,
111 keyCode /*:int*/, charCode /*:int*/) /*:Void*/
115 Y.error("simulateKeyEvent(): Invalid target.");
120 type = type.toLowerCase();
122 case "textevent": //DOM Level 3
130 Y.error("simulateKeyEvent(): Event type '" + type + "' not supported.");
133 Y.error("simulateKeyEvent(): Event type must be a string.");
136 //setup default values
137 if (!isBoolean(bubbles)){
138 bubbles = true; //all key events bubble
140 if (!isBoolean(cancelable)){
141 cancelable = true; //all key events can be cancelled
143 if (!isObject(view)){
144 view = window; //view is typically window
146 if (!isBoolean(ctrlKey)){
149 if (!isBoolean(altKey)){
152 if (!isBoolean(shiftKey)){
155 if (!isBoolean(metaKey)){
158 if (!isNumber(keyCode)){
161 if (!isNumber(charCode)){
165 //try to create a mouse event
166 var customEvent /*:MouseEvent*/ = null;
168 //check for DOM-compliant browsers first
169 if (isFunction(doc.createEvent)){
173 //try to create key event
174 customEvent = doc.createEvent("KeyEvents");
177 * Interesting problem: Firefox implemented a non-standard
178 * version of initKeyEvent() based on DOM Level 2 specs.
179 * Key event was removed from DOM Level 2 and re-introduced
180 * in DOM Level 3 with a different interface. Firefox is the
181 * only browser with any implementation of Key Events, so for
182 * now, assume it's Firefox if the above line doesn't error.
184 // @TODO: Decipher between Firefox's implementation and a correct one.
185 customEvent.initKeyEvent(type, bubbles, cancelable, view, ctrlKey,
186 altKey, shiftKey, metaKey, keyCode, charCode);
188 } catch (ex /*:Error*/){
191 * If it got here, that means key events aren't officially supported.
192 * Safari/WebKit is a real problem now. WebKit 522 won't let you
193 * set keyCode, charCode, or other properties if you use a
194 * UIEvent, so we first must try to create a generic event. The
195 * fun part is that this will throw an error on Safari 2.x. The
196 * end result is that we need another try...catch statement just to
197 * deal with this mess.
201 //try to create generic event - will fail in Safari 2.x
202 customEvent = doc.createEvent("Events");
204 } catch (uierror /*:Error*/){
206 //the above failed, so create a UIEvent for Safari 2.x
207 customEvent = doc.createEvent("UIEvents");
211 customEvent.initEvent(type, bubbles, cancelable);
214 customEvent.view = view;
215 customEvent.altKey = altKey;
216 customEvent.ctrlKey = ctrlKey;
217 customEvent.shiftKey = shiftKey;
218 customEvent.metaKey = metaKey;
219 customEvent.keyCode = keyCode;
220 customEvent.charCode = charCode;
227 target.dispatchEvent(customEvent);
229 } else if (isObject(doc.createEventObject)){ //IE
231 //create an IE event object
232 customEvent = doc.createEventObject();
234 //assign available properties
235 customEvent.bubbles = bubbles;
236 customEvent.cancelable = cancelable;
237 customEvent.view = view;
238 customEvent.ctrlKey = ctrlKey;
239 customEvent.altKey = altKey;
240 customEvent.shiftKey = shiftKey;
241 customEvent.metaKey = metaKey;
244 * IE doesn't support charCode explicitly. CharCode should
245 * take precedence over any keyCode value for accurate
248 customEvent.keyCode = (charCode > 0) ? charCode : keyCode;
251 target.fireEvent("on" + type, customEvent);
254 Y.error("simulateKeyEvent(): No event simulation framework present.");
259 * Note: Intentionally not for YUIDoc generation.
260 * Simulates a mouse event using the given event information to populate
261 * the generated event object. This method does browser-equalizing
262 * calculations to account for differences in the DOM and IE event models
263 * as well as different browser quirks.
264 * @method simulateMouseEvent
267 * @param {HTMLElement} target The target of the given event.
268 * @param {String} type The type of event to fire. This can be any one of
269 * the following: click, dblclick, mousedown, mouseup, mouseout,
270 * mouseover, and mousemove.
271 * @param {Boolean} bubbles (Optional) Indicates if the event can be
272 * bubbled up. DOM Level 2 specifies that all mouse events bubble by
273 * default. The default is true.
274 * @param {Boolean} cancelable (Optional) Indicates if the event can be
275 * canceled using preventDefault(). DOM Level 2 specifies that all
276 * mouse events except mousemove can be cancelled. The default
277 * is true for all events except mousemove, for which the default
279 * @param {Window} view (Optional) The view containing the target. This is
280 * typically the window object. The default is window.
281 * @param {int} detail (Optional) The number of times the mouse button has
282 * been used. The default value is 1.
283 * @param {int} screenX (Optional) The x-coordinate on the screen at which
284 * point the event occured. The default is 0.
285 * @param {int} screenY (Optional) The y-coordinate on the screen at which
286 * point the event occured. The default is 0.
287 * @param {int} clientX (Optional) The x-coordinate on the client at which
288 * point the event occured. The default is 0.
289 * @param {int} clientY (Optional) The y-coordinate on the client at which
290 * point the event occured. The default is 0.
291 * @param {Boolean} ctrlKey (Optional) Indicates if one of the CTRL keys
292 * is pressed while the event is firing. The default is false.
293 * @param {Boolean} altKey (Optional) Indicates if one of the ALT keys
294 * is pressed while the event is firing. The default is false.
295 * @param {Boolean} shiftKey (Optional) Indicates if one of the SHIFT keys
296 * is pressed while the event is firing. The default is false.
297 * @param {Boolean} metaKey (Optional) Indicates if one of the META keys
298 * is pressed while the event is firing. The default is false.
299 * @param {int} button (Optional) The button being pressed while the event
300 * is executing. The value should be 0 for the primary mouse button
301 * (typically the left button), 1 for the terciary mouse button
302 * (typically the middle button), and 2 for the secondary mouse button
303 * (typically the right button). The default is 0.
304 * @param {HTMLElement} relatedTarget (Optional) For mouseout events,
305 * this is the element that the mouse has moved to. For mouseover
306 * events, this is the element that the mouse has moved from. This
307 * argument is ignored for all other events. The default is null.
309 function simulateMouseEvent(target /*:HTMLElement*/, type /*:String*/,
310 bubbles /*:Boolean*/, cancelable /*:Boolean*/,
311 view /*:Window*/, detail /*:int*/,
312 screenX /*:int*/, screenY /*:int*/,
313 clientX /*:int*/, clientY /*:int*/,
314 ctrlKey /*:Boolean*/, altKey /*:Boolean*/,
315 shiftKey /*:Boolean*/, metaKey /*:Boolean*/,
316 button /*:int*/, relatedTarget /*:HTMLElement*/) /*:Void*/
321 Y.error("simulateMouseEvent(): Invalid target.");
326 type = type.toLowerCase();
328 //make sure it's a supported mouse event
329 if (!mouseEvents[type]){
330 Y.error("simulateMouseEvent(): Event type '" + type + "' not supported.");
333 Y.error("simulateMouseEvent(): Event type must be a string.");
336 //setup default values
337 if (!isBoolean(bubbles)){
338 bubbles = true; //all mouse events bubble
340 if (!isBoolean(cancelable)){
341 cancelable = (type != "mousemove"); //mousemove is the only one that can't be cancelled
343 if (!isObject(view)){
344 view = window; //view is typically window
346 if (!isNumber(detail)){
347 detail = 1; //number of mouse clicks must be at least one
349 if (!isNumber(screenX)){
352 if (!isNumber(screenY)){
355 if (!isNumber(clientX)){
358 if (!isNumber(clientY)){
361 if (!isBoolean(ctrlKey)){
364 if (!isBoolean(altKey)){
367 if (!isBoolean(shiftKey)){
370 if (!isBoolean(metaKey)){
373 if (!isNumber(button)){
377 relatedTarget = relatedTarget || null;
379 //try to create a mouse event
380 var customEvent /*:MouseEvent*/ = null;
382 //check for DOM-compliant browsers first
383 if (isFunction(doc.createEvent)){
385 customEvent = doc.createEvent("MouseEvents");
387 //Safari 2.x (WebKit 418) still doesn't implement initMouseEvent()
388 if (customEvent.initMouseEvent){
389 customEvent.initMouseEvent(type, bubbles, cancelable, view, detail,
390 screenX, screenY, clientX, clientY,
391 ctrlKey, altKey, shiftKey, metaKey,
392 button, relatedTarget);
395 //the closest thing available in Safari 2.x is UIEvents
396 customEvent = doc.createEvent("UIEvents");
397 customEvent.initEvent(type, bubbles, cancelable);
398 customEvent.view = view;
399 customEvent.detail = detail;
400 customEvent.screenX = screenX;
401 customEvent.screenY = screenY;
402 customEvent.clientX = clientX;
403 customEvent.clientY = clientY;
404 customEvent.ctrlKey = ctrlKey;
405 customEvent.altKey = altKey;
406 customEvent.metaKey = metaKey;
407 customEvent.shiftKey = shiftKey;
408 customEvent.button = button;
409 customEvent.relatedTarget = relatedTarget;
413 * Check to see if relatedTarget has been assigned. Firefox
414 * versions less than 2.0 don't allow it to be assigned via
415 * initMouseEvent() and the property is readonly after event
416 * creation, so in order to keep YAHOO.util.getRelatedTarget()
417 * working, assign to the IE proprietary toElement property
418 * for mouseout event and fromElement property for mouseover
421 if (relatedTarget && !customEvent.relatedTarget){
422 if (type == "mouseout"){
423 customEvent.toElement = relatedTarget;
424 } else if (type == "mouseover"){
425 customEvent.fromElement = relatedTarget;
430 target.dispatchEvent(customEvent);
432 } else if (isObject(doc.createEventObject)){ //IE
434 //create an IE event object
435 customEvent = doc.createEventObject();
437 //assign available properties
438 customEvent.bubbles = bubbles;
439 customEvent.cancelable = cancelable;
440 customEvent.view = view;
441 customEvent.detail = detail;
442 customEvent.screenX = screenX;
443 customEvent.screenY = screenY;
444 customEvent.clientX = clientX;
445 customEvent.clientY = clientY;
446 customEvent.ctrlKey = ctrlKey;
447 customEvent.altKey = altKey;
448 customEvent.metaKey = metaKey;
449 customEvent.shiftKey = shiftKey;
451 //fix button property for IE's wacky implementation
454 customEvent.button = 1;
457 customEvent.button = 4;
463 customEvent.button = 0;
467 * Have to use relatedTarget because IE won't allow assignment
468 * to toElement or fromElement on generic events. This keeps
469 * YAHOO.util.customEvent.getRelatedTarget() functional.
471 customEvent.relatedTarget = relatedTarget;
474 target.fireEvent("on" + type, customEvent);
477 Y.error("simulateMouseEvent(): No event simulation framework present.");
482 * Note: Intentionally not for YUIDoc generation.
483 * Simulates a UI event using the given event information to populate
484 * the generated event object. This method does browser-equalizing
485 * calculations to account for differences in the DOM and IE event models
486 * as well as different browser quirks.
487 * @method simulateHTMLEvent
490 * @param {HTMLElement} target The target of the given event.
491 * @param {String} type The type of event to fire. This can be any one of
492 * the following: click, dblclick, mousedown, mouseup, mouseout,
493 * mouseover, and mousemove.
494 * @param {Boolean} bubbles (Optional) Indicates if the event can be
495 * bubbled up. DOM Level 2 specifies that all mouse events bubble by
496 * default. The default is true.
497 * @param {Boolean} cancelable (Optional) Indicates if the event can be
498 * canceled using preventDefault(). DOM Level 2 specifies that all
499 * mouse events except mousemove can be cancelled. The default
500 * is true for all events except mousemove, for which the default
502 * @param {Window} view (Optional) The view containing the target. This is
503 * typically the window object. The default is window.
504 * @param {int} detail (Optional) The number of times the mouse button has
505 * been used. The default value is 1.
507 function simulateUIEvent(target /*:HTMLElement*/, type /*:String*/,
508 bubbles /*:Boolean*/, cancelable /*:Boolean*/,
509 view /*:Window*/, detail /*:int*/) /*:Void*/
514 Y.error("simulateUIEvent(): Invalid target.");
519 type = type.toLowerCase();
521 //make sure it's a supported mouse event
522 if (!uiEvents[type]){
523 Y.error("simulateUIEvent(): Event type '" + type + "' not supported.");
526 Y.error("simulateUIEvent(): Event type must be a string.");
529 //try to create a mouse event
530 var customEvent = null;
533 //setup default values
534 if (!isBoolean(bubbles)){
535 bubbles = (type in bubbleEvents); //not all events bubble
537 if (!isBoolean(cancelable)){
538 cancelable = (type == "submit"); //submit is the only one that can be cancelled
540 if (!isObject(view)){
541 view = window; //view is typically window
543 if (!isNumber(detail)){
544 detail = 1; //usually not used but defaulted to this
547 //check for DOM-compliant browsers first
548 if (isFunction(doc.createEvent)){
550 //just a generic UI Event object is needed
551 customEvent = doc.createEvent("UIEvents");
552 customEvent.initUIEvent(type, bubbles, cancelable, view, detail);
555 target.dispatchEvent(customEvent);
557 } else if (isObject(doc.createEventObject)){ //IE
559 //create an IE event object
560 customEvent = doc.createEventObject();
562 //assign available properties
563 customEvent.bubbles = bubbles;
564 customEvent.cancelable = cancelable;
565 customEvent.view = view;
566 customEvent.detail = detail;
569 target.fireEvent("on" + type, customEvent);
572 Y.error("simulateUIEvent(): No event simulation framework present.");
577 * Simulates the event with the given name on a target.
578 * @param {HTMLElement} target The DOM element that's the target of the event.
579 * @param {String} type The type of event to simulate (i.e., "click").
580 * @param {Object} options (Optional) Extra options to copy onto the event object.
586 Y.Event.simulate = function(target, type, options){
588 options = options || {};
590 if (mouseEvents[type]){
591 simulateMouseEvent(target, type, options.bubbles,
592 options.cancelable, options.view, options.detail, options.screenX,
593 options.screenY, options.clientX, options.clientY, options.ctrlKey,
594 options.altKey, options.shiftKey, options.metaKey, options.button,
595 options.relatedTarget);
596 } else if (keyEvents[type]){
597 simulateKeyEvent(target, type, options.bubbles,
598 options.cancelable, options.view, options.ctrlKey,
599 options.altKey, options.shiftKey, options.metaKey,
600 options.keyCode, options.charCode);
601 } else if (uiEvents[type]){
602 simulateUIEvent(target, type, options.bubbles,
603 options.cancelable, options.view, options.detail);
605 Y.error("simulate(): Event '" + type + "' can't be simulated.");
614 }, '3.3.0' ,{requires:['event-base']});