]> git.openstreetmap.org Git - rails.git/blob - vendor/assets/jquery/jquery.simulate.js
Improve error-handling
[rails.git] / vendor / assets / jquery / jquery.simulate.js
1  /*!
2  * jQuery Simulate v0.0.1 - simulate browser mouse and keyboard events
3  * https://github.com/jquery/jquery-simulate
4  *
5  * Copyright 2012 jQuery Foundation and other contributors
6  * Released under the MIT license.
7  * http://jquery.org/license
8  *
9  * Date: Sun Dec 9 12:15:33 2012 -0500
10  */
11
12 ;(function( $, undefined ) {
13
14 var rkeyEvent = /^key/,
15         rmouseEvent = /^(?:mouse|contextmenu)|click/;
16
17 $.fn.simulate = function( type, options ) {
18         return this.each(function() {
19                 new $.simulate( this, type, options );
20         });
21 };
22
23 $.simulate = function( elem, type, options ) {
24         var method = $.camelCase( "simulate-" + type );
25
26         this.target = elem;
27         this.options = options;
28
29         if ( this[ method ] ) {
30                 this[ method ]();
31         } else {
32                 this.simulateEvent( elem, type, options );
33         }
34 };
35
36 $.extend( $.simulate, {
37
38         keyCode: {
39                 BACKSPACE: 8,
40                 COMMA: 188,
41                 DELETE: 46,
42                 DOWN: 40,
43                 END: 35,
44                 ENTER: 13,
45                 ESCAPE: 27,
46                 HOME: 36,
47                 LEFT: 37,
48                 NUMPAD_ADD: 107,
49                 NUMPAD_DECIMAL: 110,
50                 NUMPAD_DIVIDE: 111,
51                 NUMPAD_ENTER: 108,
52                 NUMPAD_MULTIPLY: 106,
53                 NUMPAD_SUBTRACT: 109,
54                 PAGE_DOWN: 34,
55                 PAGE_UP: 33,
56                 PERIOD: 190,
57                 RIGHT: 39,
58                 SPACE: 32,
59                 TAB: 9,
60                 UP: 38
61         },
62
63         buttonCode: {
64                 LEFT: 0,
65                 MIDDLE: 1,
66                 RIGHT: 2
67         }
68 });
69
70 $.extend( $.simulate.prototype, {
71
72         simulateEvent: function( elem, type, options ) {
73                 var event = this.createEvent( type, options );
74                 this.dispatchEvent( elem, type, event, options );
75         },
76
77         createEvent: function( type, options ) {
78                 if ( rkeyEvent.test( type ) ) {
79                         return this.keyEvent( type, options );
80                 }
81
82                 if ( rmouseEvent.test( type ) ) {
83                         return this.mouseEvent( type, options );
84                 }
85         },
86
87         mouseEvent: function( type, options ) {
88                 var event, eventDoc, doc, body;
89                 options = $.extend({
90                         bubbles: true,
91                         cancelable: (type !== "mousemove"),
92                         view: window,
93                         detail: 0,
94                         screenX: 0,
95                         screenY: 0,
96                         clientX: 1,
97                         clientY: 1,
98                         ctrlKey: false,
99                         altKey: false,
100                         shiftKey: false,
101                         metaKey: false,
102                         button: 0,
103                         relatedTarget: undefined
104                 }, options );
105
106                 if ( document.createEvent ) {
107                         event = document.createEvent( "MouseEvents" );
108                         event.initMouseEvent( type, options.bubbles, options.cancelable,
109                                 options.view, options.detail,
110                                 options.screenX, options.screenY, options.clientX, options.clientY,
111                                 options.ctrlKey, options.altKey, options.shiftKey, options.metaKey,
112                                 options.button, options.relatedTarget || document.body.parentNode );
113
114                         // IE 9+ creates events with pageX and pageY set to 0.
115                         // Trying to modify the properties throws an error,
116                         // so we define getters to return the correct values.
117                         if ( event.pageX === 0 && event.pageY === 0 && Object.defineProperty ) {
118                                 eventDoc = event.relatedTarget.ownerDocument || document;
119                                 doc = eventDoc.documentElement;
120                                 body = eventDoc.body;
121
122                                 Object.defineProperty( event, "pageX", {
123                                         get: function() {
124                                                 return options.clientX +
125                                                         ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) -
126                                                         ( doc && doc.clientLeft || body && body.clientLeft || 0 );
127                                         }
128                                 });
129                                 Object.defineProperty( event, "pageY", {
130                                         get: function() {
131                                                 return options.clientY +
132                                                         ( doc && doc.scrollTop || body && body.scrollTop || 0 ) -
133                                                         ( doc && doc.clientTop || body && body.clientTop || 0 );
134                                         }
135                                 });
136                         }
137                 } else if ( document.createEventObject ) {
138                         event = document.createEventObject();
139                         $.extend( event, options );
140                         // standards event.button uses constants defined here: http://msdn.microsoft.com/en-us/library/ie/ff974877(v=vs.85).aspx
141                         // old IE event.button uses constants defined here: http://msdn.microsoft.com/en-us/library/ie/ms533544(v=vs.85).aspx
142                         // so we actually need to map the standard back to oldIE
143                         event.button = {
144                                 0: 1,
145                                 1: 4,
146                                 2: 2
147                         }[ event.button ] || event.button;
148                 }
149
150                 return event;
151         },
152
153         keyEvent: function( type, options ) {
154                 var event;
155                 options = $.extend({
156                         bubbles: true,
157                         cancelable: true,
158                         view: window,
159                         ctrlKey: false,
160                         altKey: false,
161                         shiftKey: false,
162                         metaKey: false,
163                         keyCode: 0,
164                         charCode: undefined
165                 }, options );
166
167                 if ( document.createEvent ) {
168                         try {
169                                 event = document.createEvent( "KeyEvents" );
170                                 event.initKeyEvent( type, options.bubbles, options.cancelable, options.view,
171                                         options.ctrlKey, options.altKey, options.shiftKey, options.metaKey,
172                                         options.keyCode, options.charCode );
173                         // initKeyEvent throws an exception in WebKit
174                         // see: http://stackoverflow.com/questions/6406784/initkeyevent-keypress-only-works-in-firefox-need-a-cross-browser-solution
175                         // and also https://bugs.webkit.org/show_bug.cgi?id=13368
176                         // fall back to a generic event until we decide to implement initKeyboardEvent
177                         } catch( err ) {
178                                 event = document.createEvent( "Events" );
179                                 event.initEvent( type, options.bubbles, options.cancelable );
180                                 $.extend( event, {
181                                         view: options.view,
182                                         ctrlKey: options.ctrlKey,
183                                         altKey: options.altKey,
184                                         shiftKey: options.shiftKey,
185                                         metaKey: options.metaKey,
186                                         keyCode: options.keyCode,
187                                         charCode: options.charCode
188                                 });
189                         }
190                 } else if ( document.createEventObject ) {
191                         event = document.createEventObject();
192                         $.extend( event, options );
193                 }
194
195                 if ( !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() ) || (({}).toString.call( window.opera ) === "[object Opera]") ) {
196                         event.keyCode = (options.charCode > 0) ? options.charCode : options.keyCode;
197                         event.charCode = undefined;
198                 }
199
200                 return event;
201         },
202
203         dispatchEvent: function( elem, type, event ) {
204                 if ( elem.dispatchEvent ) {
205                         elem.dispatchEvent( event );
206                 } else if ( elem.fireEvent ) {
207                         elem.fireEvent( "on" + type, event );
208                 }
209         },
210
211         simulateFocus: function() {
212                 var focusinEvent,
213                         triggered = false,
214                         element = $( this.target );
215
216                 function trigger() {
217                         triggered = true;
218                 }
219
220                 element.bind( "focus", trigger );
221                 element[ 0 ].focus();
222
223                 if ( !triggered ) {
224                         focusinEvent = $.Event( "focusin" );
225                         focusinEvent.preventDefault();
226                         element.trigger( focusinEvent );
227                         element.triggerHandler( "focus" );
228                 }
229                 element.unbind( "focus", trigger );
230         },
231
232         simulateBlur: function() {
233                 var focusoutEvent,
234                         triggered = false,
235                         element = $( this.target );
236
237                 function trigger() {
238                         triggered = true;
239                 }
240
241                 element.bind( "blur", trigger );
242                 element[ 0 ].blur();
243
244                 // blur events are async in IE
245                 setTimeout(function() {
246                         // IE won't let the blur occur if the window is inactive
247                         if ( element[ 0 ].ownerDocument.activeElement === element[ 0 ] ) {
248                                 element[ 0 ].ownerDocument.body.focus();
249                         }
250
251                         // Firefox won't trigger events if the window is inactive
252                         // IE doesn't trigger events if we had to manually focus the body
253                         if ( !triggered ) {
254                                 focusoutEvent = $.Event( "focusout" );
255                                 focusoutEvent.preventDefault();
256                                 element.trigger( focusoutEvent );
257                                 element.triggerHandler( "blur" );
258                         }
259                         element.unbind( "blur", trigger );
260                 }, 1 );
261         }
262 });
263
264
265
266 /** complex events **/
267
268 function findCenter( elem ) {
269         var offset,
270                 document = $( elem.ownerDocument );
271         elem = $( elem );
272         offset = elem.offset();
273
274         return {
275                 x: offset.left + elem.outerWidth() / 2 - document.scrollLeft(),
276                 y: offset.top + elem.outerHeight() / 2 - document.scrollTop()
277         };
278 }
279
280 function findCorner( elem ) {
281         var offset,
282                 document = $( elem.ownerDocument );
283         elem = $( elem );
284         offset = elem.offset();
285
286         return {
287                 x: offset.left - document.scrollLeft(),
288                 y: offset.top - document.scrollTop()
289         };
290 }
291
292 $.extend( $.simulate.prototype, {
293         simulateDrag: function() {
294                 var i = 0,
295                         target = this.target,
296                         options = this.options,
297                         center = options.handle === "corner" ? findCorner( target ) : findCenter( target ),
298                         x = Math.floor( center.x ),
299                         y = Math.floor( center.y ),
300                         coord = { clientX: x, clientY: y },
301                         dx = options.dx || ( options.x !== undefined ? options.x - x : 0 ),
302                         dy = options.dy || ( options.y !== undefined ? options.y - y : 0 ),
303                         moves = options.moves || 3;
304
305                 this.simulateEvent( target, "mousedown", coord );
306
307                 for ( ; i < moves ; i++ ) {
308                         x += dx / moves;
309                         y += dy / moves;
310
311                         coord = {
312                                 clientX: Math.round( x ),
313                                 clientY: Math.round( y )
314                         };
315
316                         this.simulateEvent( target.ownerDocument, "mousemove", coord );
317                 }
318
319                 if ( $.contains( document, target ) ) {
320                         this.simulateEvent( target, "mouseup", coord );
321                         this.simulateEvent( target, "click", coord );
322                 } else {
323                         this.simulateEvent( document, "mouseup", coord );
324                 }
325         }
326 });
327
328 })( jQuery );