]> git.openstreetmap.org Git - osqa.git/blob - forum/skins/default/media/js/ui.core.js
Merge branch 'threadsafe_requestholder' into update_django
[osqa.git] / forum / skins / default / media / js / ui.core.js
1 /*
2  * jQuery UI 1.7.2
3  *
4  * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
5  * Dual licensed under the MIT (MIT-LICENSE.txt)
6  * and GPL (GPL-LICENSE.txt) licenses.
7  *
8  * http://docs.jquery.com/UI
9  */
10 ;jQuery.ui || (function($) {
11
12 var _remove = $.fn.remove,
13         isFF2 = $.browser.mozilla && (parseFloat($.browser.version) < 1.9);
14
15 //Helper functions and ui object
16 $.ui = {
17         version: "1.7.2",
18
19         // $.ui.plugin is deprecated.  Use the proxy pattern instead.
20         plugin: {
21                 add: function(module, option, set) {
22                         var proto = $.ui[module].prototype;
23                         for(var i in set) {
24                                 proto.plugins[i] = proto.plugins[i] || [];
25                                 proto.plugins[i].push([option, set[i]]);
26                         }
27                 },
28                 call: function(instance, name, args) {
29                         var set = instance.plugins[name];
30                         if(!set || !instance.element[0].parentNode) { return; }
31
32                         for (var i = 0; i < set.length; i++) {
33                                 if (instance.options[set[i][0]]) {
34                                         set[i][1].apply(instance.element, args);
35                                 }
36                         }
37                 }
38         },
39
40         contains: function(a, b) {
41                 return document.compareDocumentPosition
42                         ? a.compareDocumentPosition(b) & 16
43                         : a !== b && a.contains(b);
44         },
45
46         hasScroll: function(el, a) {
47
48                 //If overflow is hidden, the element might have extra content, but the user wants to hide it
49                 if ($(el).css('overflow') == 'hidden') { return false; }
50
51                 var scroll = (a && a == 'left') ? 'scrollLeft' : 'scrollTop',
52                         has = false;
53
54                 if (el[scroll] > 0) { return true; }
55
56                 // TODO: determine which cases actually cause this to happen
57                 // if the element doesn't have the scroll set, see if it's possible to
58                 // set the scroll
59                 el[scroll] = 1;
60                 has = (el[scroll] > 0);
61                 el[scroll] = 0;
62                 return has;
63         },
64
65         isOverAxis: function(x, reference, size) {
66                 //Determines when x coordinate is over "b" element axis
67                 return (x > reference) && (x < (reference + size));
68         },
69
70         isOver: function(y, x, top, left, height, width) {
71                 //Determines when x, y coordinates is over "b" element
72                 return $.ui.isOverAxis(y, top, height) && $.ui.isOverAxis(x, left, width);
73         },
74
75         keyCode: {
76                 BACKSPACE: 8,
77                 CAPS_LOCK: 20,
78                 COMMA: 188,
79                 CONTROL: 17,
80                 DELETE: 46,
81                 DOWN: 40,
82                 END: 35,
83                 ENTER: 13,
84                 ESCAPE: 27,
85                 HOME: 36,
86                 INSERT: 45,
87                 LEFT: 37,
88                 NUMPAD_ADD: 107,
89                 NUMPAD_DECIMAL: 110,
90                 NUMPAD_DIVIDE: 111,
91                 NUMPAD_ENTER: 108,
92                 NUMPAD_MULTIPLY: 106,
93                 NUMPAD_SUBTRACT: 109,
94                 PAGE_DOWN: 34,
95                 PAGE_UP: 33,
96                 PERIOD: 190,
97                 RIGHT: 39,
98                 SHIFT: 16,
99                 SPACE: 32,
100                 TAB: 9,
101                 UP: 38
102         }
103 };
104
105 // WAI-ARIA normalization
106 if (isFF2) {
107         var attr = $.attr,
108                 removeAttr = $.fn.removeAttr,
109                 ariaNS = "http://www.w3.org/2005/07/aaa",
110                 ariaState = /^aria-/,
111                 ariaRole = /^wairole:/;
112
113         $.attr = function(elem, name, value) {
114                 var set = value !== undefined;
115
116                 return (name == 'role'
117                         ? (set
118                                 ? attr.call(this, elem, name, "wairole:" + value)
119                                 : (attr.apply(this, arguments) || "").replace(ariaRole, ""))
120                         : (ariaState.test(name)
121                                 ? (set
122                                         ? elem.setAttributeNS(ariaNS,
123                                                 name.replace(ariaState, "aaa:"), value)
124                                         : attr.call(this, elem, name.replace(ariaState, "aaa:")))
125                                 : attr.apply(this, arguments)));
126         };
127
128         $.fn.removeAttr = function(name) {
129                 return (ariaState.test(name)
130                         ? this.each(function() {
131                                 this.removeAttributeNS(ariaNS, name.replace(ariaState, ""));
132                         }) : removeAttr.call(this, name));
133         };
134 }
135
136 //jQuery plugins
137 $.fn.extend({
138         remove: function() {
139                 // Safari has a native remove event which actually removes DOM elements,
140                 // so we have to use triggerHandler instead of trigger (#3037).
141                 $("*", this).add(this).each(function() {
142                         $(this).triggerHandler("remove");
143                 });
144                 return _remove.apply(this, arguments );
145         },
146
147         enableSelection: function() {
148                 return this
149                         .attr('unselectable', 'off')
150                         .css('MozUserSelect', '')
151                         .unbind('selectstart.ui');
152         },
153
154         disableSelection: function() {
155                 return this
156                         .attr('unselectable', 'on')
157                         .css('MozUserSelect', 'none')
158                         .bind('selectstart.ui', function() { return false; });
159         },
160
161         scrollParent: function() {
162                 var scrollParent;
163                 if(($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
164                         scrollParent = this.parents().filter(function() {
165                                 return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
166                         }).eq(0);
167                 } else {
168                         scrollParent = this.parents().filter(function() {
169                                 return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
170                         }).eq(0);
171                 }
172
173                 return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
174         }
175 });
176
177
178 //Additional selectors
179 $.extend($.expr[':'], {
180         data: function(elem, i, match) {
181                 return !!$.data(elem, match[3]);
182         },
183
184         focusable: function(element) {
185                 var nodeName = element.nodeName.toLowerCase(),
186                         tabIndex = $.attr(element, 'tabindex');
187                 return (/input|select|textarea|button|object/.test(nodeName)
188                         ? !element.disabled
189                         : 'a' == nodeName || 'area' == nodeName
190                                 ? element.href || !isNaN(tabIndex)
191                                 : !isNaN(tabIndex))
192                         // the element and all of its ancestors must be visible
193                         // the browser may report that the area is hidden
194                         && !$(element)['area' == nodeName ? 'parents' : 'closest'](':hidden').length;
195         },
196
197         tabbable: function(element) {
198                 var tabIndex = $.attr(element, 'tabindex');
199                 return (isNaN(tabIndex) || tabIndex >= 0) && $(element).is(':focusable');
200         }
201 });
202
203
204 // $.widget is a factory to create jQuery plugins
205 // taking some boilerplate code out of the plugin code
206 function getter(namespace, plugin, method, args) {
207         function getMethods(type) {
208                 var methods = $[namespace][plugin][type] || [];
209                 return (typeof methods == 'string' ? methods.split(/,?\s+/) : methods);
210         }
211
212         var methods = getMethods('getter');
213         if (args.length == 1 && typeof args[0] == 'string') {
214                 methods = methods.concat(getMethods('getterSetter'));
215         }
216         return ($.inArray(method, methods) != -1);
217 }
218
219 $.widget = function(name, prototype) {
220         var namespace = name.split(".")[0];
221         name = name.split(".")[1];
222
223         // create plugin method
224         $.fn[name] = function(options) {
225                 var isMethodCall = (typeof options == 'string'),
226                         args = Array.prototype.slice.call(arguments, 1);
227
228                 // prevent calls to internal methods
229                 if (isMethodCall && options.substring(0, 1) == '_') {
230                         return this;
231                 }
232
233                 // handle getter methods
234                 if (isMethodCall && getter(namespace, name, options, args)) {
235                         var instance = $.data(this[0], name);
236                         return (instance ? instance[options].apply(instance, args)
237                                 : undefined);
238                 }
239
240                 // handle initialization and non-getter methods
241                 return this.each(function() {
242                         var instance = $.data(this, name);
243
244                         // constructor
245                         (!instance && !isMethodCall &&
246                                 $.data(this, name, new $[namespace][name](this, options))._init());
247
248                         // method call
249                         (instance && isMethodCall && $.isFunction(instance[options]) &&
250                                 instance[options].apply(instance, args));
251                 });
252         };
253
254         // create widget constructor
255         $[namespace] = $[namespace] || {};
256         $[namespace][name] = function(element, options) {
257                 var self = this;
258
259                 this.namespace = namespace;
260                 this.widgetName = name;
261                 this.widgetEventPrefix = $[namespace][name].eventPrefix || name;
262                 this.widgetBaseClass = namespace + '-' + name;
263
264                 this.options = $.extend({},
265                         $.widget.defaults,
266                         $[namespace][name].defaults,
267                         $.metadata && $.metadata.get(element)[name],
268                         options);
269
270                 this.element = $(element)
271                         .bind('setData.' + name, function(event, key, value) {
272                                 if (event.target == element) {
273                                         return self._setData(key, value);
274                                 }
275                         })
276                         .bind('getData.' + name, function(event, key) {
277                                 if (event.target == element) {
278                                         return self._getData(key);
279                                 }
280                         })
281                         .bind('remove', function() {
282                                 return self.destroy();
283                         });
284         };
285
286         // add widget prototype
287         $[namespace][name].prototype = $.extend({}, $.widget.prototype, prototype);
288
289         // TODO: merge getter and getterSetter properties from widget prototype
290         // and plugin prototype
291         $[namespace][name].getterSetter = 'option';
292 };
293
294 $.widget.prototype = {
295         _init: function() {},
296         destroy: function() {
297                 this.element.removeData(this.widgetName)
298                         .removeClass(this.widgetBaseClass + '-disabled' + ' ' + this.namespace + '-state-disabled')
299                         .removeAttr('aria-disabled');
300         },
301
302         option: function(key, value) {
303                 var options = key,
304                         self = this;
305
306                 if (typeof key == "string") {
307                         if (value === undefined) {
308                                 return this._getData(key);
309                         }
310                         options = {};
311                         options[key] = value;
312                 }
313
314                 $.each(options, function(key, value) {
315                         self._setData(key, value);
316                 });
317         },
318         _getData: function(key) {
319                 return this.options[key];
320         },
321         _setData: function(key, value) {
322                 this.options[key] = value;
323
324                 if (key == 'disabled') {
325                         this.element
326                                 [value ? 'addClass' : 'removeClass'](
327                                         this.widgetBaseClass + '-disabled' + ' ' +
328                                         this.namespace + '-state-disabled')
329                                 .attr("aria-disabled", value);
330                 }
331         },
332
333         enable: function() {
334                 this._setData('disabled', false);
335         },
336         disable: function() {
337                 this._setData('disabled', true);
338         },
339
340         _trigger: function(type, event, data) {
341                 var callback = this.options[type],
342                         eventName = (type == this.widgetEventPrefix
343                                 ? type : this.widgetEventPrefix + type);
344
345                 event = $.Event(event);
346                 event.type = eventName;
347
348                 // copy original event properties over to the new event
349                 // this would happen if we could call $.event.fix instead of $.Event
350                 // but we don't have a way to force an event to be fixed multiple times
351                 if (event.originalEvent) {
352                         for (var i = $.event.props.length, prop; i;) {
353                                 prop = $.event.props[--i];
354                                 event[prop] = event.originalEvent[prop];
355                         }
356                 }
357
358                 this.element.trigger(event, data);
359
360                 return !($.isFunction(callback) && callback.call(this.element[0], event, data) === false
361                         || event.isDefaultPrevented());
362         }
363 };
364
365 $.widget.defaults = {
366         disabled: false
367 };
368
369
370 /** Mouse Interaction Plugin **/
371
372 $.ui.mouse = {
373         _mouseInit: function() {
374                 var self = this;
375
376                 this.element
377                         .bind('mousedown.'+this.widgetName, function(event) {
378                                 return self._mouseDown(event);
379                         })
380                         .bind('click.'+this.widgetName, function(event) {
381                                 if(self._preventClickEvent) {
382                                         self._preventClickEvent = false;
383                                         event.stopImmediatePropagation();
384                                         return false;
385                                 }
386                         });
387
388                 // Prevent text selection in IE
389                 if ($.browser.msie) {
390                         this._mouseUnselectable = this.element.attr('unselectable');
391                         this.element.attr('unselectable', 'on');
392                 }
393
394                 this.started = false;
395         },
396
397         // TODO: make sure destroying one instance of mouse doesn't mess with
398         // other instances of mouse
399         _mouseDestroy: function() {
400                 this.element.unbind('.'+this.widgetName);
401
402                 // Restore text selection in IE
403                 ($.browser.msie
404                         && this.element.attr('unselectable', this._mouseUnselectable));
405         },
406
407         _mouseDown: function(event) {
408                 // don't let more than one widget handle mouseStart
409                 // TODO: figure out why we have to use originalEvent
410                 event.originalEvent = event.originalEvent || {};
411                 if (event.originalEvent.mouseHandled) { return; }
412
413                 // we may have missed mouseup (out of window)
414                 (this._mouseStarted && this._mouseUp(event));
415
416                 this._mouseDownEvent = event;
417
418                 var self = this,
419                         btnIsLeft = (event.which == 1),
420                         elIsCancel = (typeof this.options.cancel == "string" ? $(event.target).parents().add(event.target).filter(this.options.cancel).length : false);
421                 if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
422                         return true;
423                 }
424
425                 this.mouseDelayMet = !this.options.delay;
426                 if (!this.mouseDelayMet) {
427                         this._mouseDelayTimer = setTimeout(function() {
428                                 self.mouseDelayMet = true;
429                         }, this.options.delay);
430                 }
431
432                 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
433                         this._mouseStarted = (this._mouseStart(event) !== false);
434                         if (!this._mouseStarted) {
435                                 event.preventDefault();
436                                 return true;
437                         }
438                 }
439
440                 // these delegates are required to keep context
441                 this._mouseMoveDelegate = function(event) {
442                         return self._mouseMove(event);
443                 };
444                 this._mouseUpDelegate = function(event) {
445                         return self._mouseUp(event);
446                 };
447                 $(document)
448                         .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
449                         .bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
450
451                 // preventDefault() is used to prevent the selection of text here -
452                 // however, in Safari, this causes select boxes not to be selectable
453                 // anymore, so this fix is needed
454                 ($.browser.safari || event.preventDefault());
455
456                 event.originalEvent.mouseHandled = true;
457                 return true;
458         },
459
460         _mouseMove: function(event) {
461                 // IE mouseup check - mouseup happened when mouse was out of window
462                 if ($.browser.msie && !event.button) {
463                         return this._mouseUp(event);
464                 }
465
466                 if (this._mouseStarted) {
467                         this._mouseDrag(event);
468                         return event.preventDefault();
469                 }
470
471                 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
472                         this._mouseStarted =
473                                 (this._mouseStart(this._mouseDownEvent, event) !== false);
474                         (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
475                 }
476
477                 return !this._mouseStarted;
478         },
479
480         _mouseUp: function(event) {
481                 $(document)
482                         .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
483                         .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
484
485                 if (this._mouseStarted) {
486                         this._mouseStarted = false;
487                         this._preventClickEvent = (event.target == this._mouseDownEvent.target);
488                         this._mouseStop(event);
489                 }
490
491                 return false;
492         },
493
494         _mouseDistanceMet: function(event) {
495                 return (Math.max(
496                                 Math.abs(this._mouseDownEvent.pageX - event.pageX),
497                                 Math.abs(this._mouseDownEvent.pageY - event.pageY)
498                         ) >= this.options.distance
499                 );
500         },
501
502         _mouseDelayMet: function(event) {
503                 return this.mouseDelayMet;
504         },
505
506         // These are placeholder methods, to be overriden by extending plugin
507         _mouseStart: function(event) {},
508         _mouseDrag: function(event) {},
509         _mouseStop: function(event) {},
510         _mouseCapture: function(event) { return true; }
511 };
512
513 $.ui.mouse.defaults = {
514         cancel: null,
515         distance: 1,
516         delay: 0
517 };
518
519 })(jQuery);