Mercurial > hg > ismi-richfaces
comparison src/main/webapp/imageServer/resources/js/jquery-ui-1.10.4/ui/jquery-ui.js @ 7:764f47286679
(none)
author | jurzua |
---|---|
date | Wed, 29 Oct 2014 14:28:34 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
6:ded3bccf2cf9 | 7:764f47286679 |
---|---|
1 /*! jQuery UI - v1.10.4 - 2014-01-17 | |
2 * http://jqueryui.com | |
3 * Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.draggable.js, jquery.ui.droppable.js, jquery.ui.resizable.js, jquery.ui.selectable.js, jquery.ui.sortable.js, jquery.ui.effect.js, jquery.ui.accordion.js, jquery.ui.autocomplete.js, jquery.ui.button.js, jquery.ui.datepicker.js, jquery.ui.dialog.js, jquery.ui.effect-blind.js, jquery.ui.effect-bounce.js, jquery.ui.effect-clip.js, jquery.ui.effect-drop.js, jquery.ui.effect-explode.js, jquery.ui.effect-fade.js, jquery.ui.effect-fold.js, jquery.ui.effect-highlight.js, jquery.ui.effect-pulsate.js, jquery.ui.effect-scale.js, jquery.ui.effect-shake.js, jquery.ui.effect-slide.js, jquery.ui.effect-transfer.js, jquery.ui.menu.js, jquery.ui.position.js, jquery.ui.progressbar.js, jquery.ui.slider.js, jquery.ui.spinner.js, jquery.ui.tabs.js, jquery.ui.tooltip.js | |
4 * Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */ | |
5 (function( $, undefined ) { | |
6 | |
7 var uuid = 0, | |
8 runiqueId = /^ui-id-\d+$/; | |
9 | |
10 // $.ui might exist from components with no dependencies, e.g., $.ui.position | |
11 $.ui = $.ui || {}; | |
12 | |
13 $.extend( $.ui, { | |
14 version: "1.10.4", | |
15 | |
16 keyCode: { | |
17 BACKSPACE: 8, | |
18 COMMA: 188, | |
19 DELETE: 46, | |
20 DOWN: 40, | |
21 END: 35, | |
22 ENTER: 13, | |
23 ESCAPE: 27, | |
24 HOME: 36, | |
25 LEFT: 37, | |
26 NUMPAD_ADD: 107, | |
27 NUMPAD_DECIMAL: 110, | |
28 NUMPAD_DIVIDE: 111, | |
29 NUMPAD_ENTER: 108, | |
30 NUMPAD_MULTIPLY: 106, | |
31 NUMPAD_SUBTRACT: 109, | |
32 PAGE_DOWN: 34, | |
33 PAGE_UP: 33, | |
34 PERIOD: 190, | |
35 RIGHT: 39, | |
36 SPACE: 32, | |
37 TAB: 9, | |
38 UP: 38 | |
39 } | |
40 }); | |
41 | |
42 // plugins | |
43 $.fn.extend({ | |
44 focus: (function( orig ) { | |
45 return function( delay, fn ) { | |
46 return typeof delay === "number" ? | |
47 this.each(function() { | |
48 var elem = this; | |
49 setTimeout(function() { | |
50 $( elem ).focus(); | |
51 if ( fn ) { | |
52 fn.call( elem ); | |
53 } | |
54 }, delay ); | |
55 }) : | |
56 orig.apply( this, arguments ); | |
57 }; | |
58 })( $.fn.focus ), | |
59 | |
60 scrollParent: function() { | |
61 var scrollParent; | |
62 if (($.ui.ie && (/(static|relative)/).test(this.css("position"))) || (/absolute/).test(this.css("position"))) { | |
63 scrollParent = this.parents().filter(function() { | |
64 return (/(relative|absolute|fixed)/).test($.css(this,"position")) && (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x")); | |
65 }).eq(0); | |
66 } else { | |
67 scrollParent = this.parents().filter(function() { | |
68 return (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x")); | |
69 }).eq(0); | |
70 } | |
71 | |
72 return (/fixed/).test(this.css("position")) || !scrollParent.length ? $(document) : scrollParent; | |
73 }, | |
74 | |
75 zIndex: function( zIndex ) { | |
76 if ( zIndex !== undefined ) { | |
77 return this.css( "zIndex", zIndex ); | |
78 } | |
79 | |
80 if ( this.length ) { | |
81 var elem = $( this[ 0 ] ), position, value; | |
82 while ( elem.length && elem[ 0 ] !== document ) { | |
83 // Ignore z-index if position is set to a value where z-index is ignored by the browser | |
84 // This makes behavior of this function consistent across browsers | |
85 // WebKit always returns auto if the element is positioned | |
86 position = elem.css( "position" ); | |
87 if ( position === "absolute" || position === "relative" || position === "fixed" ) { | |
88 // IE returns 0 when zIndex is not specified | |
89 // other browsers return a string | |
90 // we ignore the case of nested elements with an explicit value of 0 | |
91 // <div style="z-index: -10;"><div style="z-index: 0;"></div></div> | |
92 value = parseInt( elem.css( "zIndex" ), 10 ); | |
93 if ( !isNaN( value ) && value !== 0 ) { | |
94 return value; | |
95 } | |
96 } | |
97 elem = elem.parent(); | |
98 } | |
99 } | |
100 | |
101 return 0; | |
102 }, | |
103 | |
104 uniqueId: function() { | |
105 return this.each(function() { | |
106 if ( !this.id ) { | |
107 this.id = "ui-id-" + (++uuid); | |
108 } | |
109 }); | |
110 }, | |
111 | |
112 removeUniqueId: function() { | |
113 return this.each(function() { | |
114 if ( runiqueId.test( this.id ) ) { | |
115 $( this ).removeAttr( "id" ); | |
116 } | |
117 }); | |
118 } | |
119 }); | |
120 | |
121 // selectors | |
122 function focusable( element, isTabIndexNotNaN ) { | |
123 var map, mapName, img, | |
124 nodeName = element.nodeName.toLowerCase(); | |
125 if ( "area" === nodeName ) { | |
126 map = element.parentNode; | |
127 mapName = map.name; | |
128 if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) { | |
129 return false; | |
130 } | |
131 img = $( "img[usemap=#" + mapName + "]" )[0]; | |
132 return !!img && visible( img ); | |
133 } | |
134 return ( /input|select|textarea|button|object/.test( nodeName ) ? | |
135 !element.disabled : | |
136 "a" === nodeName ? | |
137 element.href || isTabIndexNotNaN : | |
138 isTabIndexNotNaN) && | |
139 // the element and all of its ancestors must be visible | |
140 visible( element ); | |
141 } | |
142 | |
143 function visible( element ) { | |
144 return $.expr.filters.visible( element ) && | |
145 !$( element ).parents().addBack().filter(function() { | |
146 return $.css( this, "visibility" ) === "hidden"; | |
147 }).length; | |
148 } | |
149 | |
150 $.extend( $.expr[ ":" ], { | |
151 data: $.expr.createPseudo ? | |
152 $.expr.createPseudo(function( dataName ) { | |
153 return function( elem ) { | |
154 return !!$.data( elem, dataName ); | |
155 }; | |
156 }) : | |
157 // support: jQuery <1.8 | |
158 function( elem, i, match ) { | |
159 return !!$.data( elem, match[ 3 ] ); | |
160 }, | |
161 | |
162 focusable: function( element ) { | |
163 return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) ); | |
164 }, | |
165 | |
166 tabbable: function( element ) { | |
167 var tabIndex = $.attr( element, "tabindex" ), | |
168 isTabIndexNaN = isNaN( tabIndex ); | |
169 return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN ); | |
170 } | |
171 }); | |
172 | |
173 // support: jQuery <1.8 | |
174 if ( !$( "<a>" ).outerWidth( 1 ).jquery ) { | |
175 $.each( [ "Width", "Height" ], function( i, name ) { | |
176 var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ], | |
177 type = name.toLowerCase(), | |
178 orig = { | |
179 innerWidth: $.fn.innerWidth, | |
180 innerHeight: $.fn.innerHeight, | |
181 outerWidth: $.fn.outerWidth, | |
182 outerHeight: $.fn.outerHeight | |
183 }; | |
184 | |
185 function reduce( elem, size, border, margin ) { | |
186 $.each( side, function() { | |
187 size -= parseFloat( $.css( elem, "padding" + this ) ) || 0; | |
188 if ( border ) { | |
189 size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0; | |
190 } | |
191 if ( margin ) { | |
192 size -= parseFloat( $.css( elem, "margin" + this ) ) || 0; | |
193 } | |
194 }); | |
195 return size; | |
196 } | |
197 | |
198 $.fn[ "inner" + name ] = function( size ) { | |
199 if ( size === undefined ) { | |
200 return orig[ "inner" + name ].call( this ); | |
201 } | |
202 | |
203 return this.each(function() { | |
204 $( this ).css( type, reduce( this, size ) + "px" ); | |
205 }); | |
206 }; | |
207 | |
208 $.fn[ "outer" + name] = function( size, margin ) { | |
209 if ( typeof size !== "number" ) { | |
210 return orig[ "outer" + name ].call( this, size ); | |
211 } | |
212 | |
213 return this.each(function() { | |
214 $( this).css( type, reduce( this, size, true, margin ) + "px" ); | |
215 }); | |
216 }; | |
217 }); | |
218 } | |
219 | |
220 // support: jQuery <1.8 | |
221 if ( !$.fn.addBack ) { | |
222 $.fn.addBack = function( selector ) { | |
223 return this.add( selector == null ? | |
224 this.prevObject : this.prevObject.filter( selector ) | |
225 ); | |
226 }; | |
227 } | |
228 | |
229 // support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413) | |
230 if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) { | |
231 $.fn.removeData = (function( removeData ) { | |
232 return function( key ) { | |
233 if ( arguments.length ) { | |
234 return removeData.call( this, $.camelCase( key ) ); | |
235 } else { | |
236 return removeData.call( this ); | |
237 } | |
238 }; | |
239 })( $.fn.removeData ); | |
240 } | |
241 | |
242 | |
243 | |
244 | |
245 | |
246 // deprecated | |
247 $.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() ); | |
248 | |
249 $.support.selectstart = "onselectstart" in document.createElement( "div" ); | |
250 $.fn.extend({ | |
251 disableSelection: function() { | |
252 return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) + | |
253 ".ui-disableSelection", function( event ) { | |
254 event.preventDefault(); | |
255 }); | |
256 }, | |
257 | |
258 enableSelection: function() { | |
259 return this.unbind( ".ui-disableSelection" ); | |
260 } | |
261 }); | |
262 | |
263 $.extend( $.ui, { | |
264 // $.ui.plugin is deprecated. Use $.widget() extensions instead. | |
265 plugin: { | |
266 add: function( module, option, set ) { | |
267 var i, | |
268 proto = $.ui[ module ].prototype; | |
269 for ( i in set ) { | |
270 proto.plugins[ i ] = proto.plugins[ i ] || []; | |
271 proto.plugins[ i ].push( [ option, set[ i ] ] ); | |
272 } | |
273 }, | |
274 call: function( instance, name, args ) { | |
275 var i, | |
276 set = instance.plugins[ name ]; | |
277 if ( !set || !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) { | |
278 return; | |
279 } | |
280 | |
281 for ( i = 0; i < set.length; i++ ) { | |
282 if ( instance.options[ set[ i ][ 0 ] ] ) { | |
283 set[ i ][ 1 ].apply( instance.element, args ); | |
284 } | |
285 } | |
286 } | |
287 }, | |
288 | |
289 // only used by resizable | |
290 hasScroll: function( el, a ) { | |
291 | |
292 //If overflow is hidden, the element might have extra content, but the user wants to hide it | |
293 if ( $( el ).css( "overflow" ) === "hidden") { | |
294 return false; | |
295 } | |
296 | |
297 var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop", | |
298 has = false; | |
299 | |
300 if ( el[ scroll ] > 0 ) { | |
301 return true; | |
302 } | |
303 | |
304 // TODO: determine which cases actually cause this to happen | |
305 // if the element doesn't have the scroll set, see if it's possible to | |
306 // set the scroll | |
307 el[ scroll ] = 1; | |
308 has = ( el[ scroll ] > 0 ); | |
309 el[ scroll ] = 0; | |
310 return has; | |
311 } | |
312 }); | |
313 | |
314 })( jQuery ); | |
315 | |
316 (function( $, undefined ) { | |
317 | |
318 var uuid = 0, | |
319 slice = Array.prototype.slice, | |
320 _cleanData = $.cleanData; | |
321 $.cleanData = function( elems ) { | |
322 for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { | |
323 try { | |
324 $( elem ).triggerHandler( "remove" ); | |
325 // http://bugs.jquery.com/ticket/8235 | |
326 } catch( e ) {} | |
327 } | |
328 _cleanData( elems ); | |
329 }; | |
330 | |
331 $.widget = function( name, base, prototype ) { | |
332 var fullName, existingConstructor, constructor, basePrototype, | |
333 // proxiedPrototype allows the provided prototype to remain unmodified | |
334 // so that it can be used as a mixin for multiple widgets (#8876) | |
335 proxiedPrototype = {}, | |
336 namespace = name.split( "." )[ 0 ]; | |
337 | |
338 name = name.split( "." )[ 1 ]; | |
339 fullName = namespace + "-" + name; | |
340 | |
341 if ( !prototype ) { | |
342 prototype = base; | |
343 base = $.Widget; | |
344 } | |
345 | |
346 // create selector for plugin | |
347 $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) { | |
348 return !!$.data( elem, fullName ); | |
349 }; | |
350 | |
351 $[ namespace ] = $[ namespace ] || {}; | |
352 existingConstructor = $[ namespace ][ name ]; | |
353 constructor = $[ namespace ][ name ] = function( options, element ) { | |
354 // allow instantiation without "new" keyword | |
355 if ( !this._createWidget ) { | |
356 return new constructor( options, element ); | |
357 } | |
358 | |
359 // allow instantiation without initializing for simple inheritance | |
360 // must use "new" keyword (the code above always passes args) | |
361 if ( arguments.length ) { | |
362 this._createWidget( options, element ); | |
363 } | |
364 }; | |
365 // extend with the existing constructor to carry over any static properties | |
366 $.extend( constructor, existingConstructor, { | |
367 version: prototype.version, | |
368 // copy the object used to create the prototype in case we need to | |
369 // redefine the widget later | |
370 _proto: $.extend( {}, prototype ), | |
371 // track widgets that inherit from this widget in case this widget is | |
372 // redefined after a widget inherits from it | |
373 _childConstructors: [] | |
374 }); | |
375 | |
376 basePrototype = new base(); | |
377 // we need to make the options hash a property directly on the new instance | |
378 // otherwise we'll modify the options hash on the prototype that we're | |
379 // inheriting from | |
380 basePrototype.options = $.widget.extend( {}, basePrototype.options ); | |
381 $.each( prototype, function( prop, value ) { | |
382 if ( !$.isFunction( value ) ) { | |
383 proxiedPrototype[ prop ] = value; | |
384 return; | |
385 } | |
386 proxiedPrototype[ prop ] = (function() { | |
387 var _super = function() { | |
388 return base.prototype[ prop ].apply( this, arguments ); | |
389 }, | |
390 _superApply = function( args ) { | |
391 return base.prototype[ prop ].apply( this, args ); | |
392 }; | |
393 return function() { | |
394 var __super = this._super, | |
395 __superApply = this._superApply, | |
396 returnValue; | |
397 | |
398 this._super = _super; | |
399 this._superApply = _superApply; | |
400 | |
401 returnValue = value.apply( this, arguments ); | |
402 | |
403 this._super = __super; | |
404 this._superApply = __superApply; | |
405 | |
406 return returnValue; | |
407 }; | |
408 })(); | |
409 }); | |
410 constructor.prototype = $.widget.extend( basePrototype, { | |
411 // TODO: remove support for widgetEventPrefix | |
412 // always use the name + a colon as the prefix, e.g., draggable:start | |
413 // don't prefix for widgets that aren't DOM-based | |
414 widgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name | |
415 }, proxiedPrototype, { | |
416 constructor: constructor, | |
417 namespace: namespace, | |
418 widgetName: name, | |
419 widgetFullName: fullName | |
420 }); | |
421 | |
422 // If this widget is being redefined then we need to find all widgets that | |
423 // are inheriting from it and redefine all of them so that they inherit from | |
424 // the new version of this widget. We're essentially trying to replace one | |
425 // level in the prototype chain. | |
426 if ( existingConstructor ) { | |
427 $.each( existingConstructor._childConstructors, function( i, child ) { | |
428 var childPrototype = child.prototype; | |
429 | |
430 // redefine the child widget using the same prototype that was | |
431 // originally used, but inherit from the new version of the base | |
432 $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto ); | |
433 }); | |
434 // remove the list of existing child constructors from the old constructor | |
435 // so the old child constructors can be garbage collected | |
436 delete existingConstructor._childConstructors; | |
437 } else { | |
438 base._childConstructors.push( constructor ); | |
439 } | |
440 | |
441 $.widget.bridge( name, constructor ); | |
442 }; | |
443 | |
444 $.widget.extend = function( target ) { | |
445 var input = slice.call( arguments, 1 ), | |
446 inputIndex = 0, | |
447 inputLength = input.length, | |
448 key, | |
449 value; | |
450 for ( ; inputIndex < inputLength; inputIndex++ ) { | |
451 for ( key in input[ inputIndex ] ) { | |
452 value = input[ inputIndex ][ key ]; | |
453 if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) { | |
454 // Clone objects | |
455 if ( $.isPlainObject( value ) ) { | |
456 target[ key ] = $.isPlainObject( target[ key ] ) ? | |
457 $.widget.extend( {}, target[ key ], value ) : | |
458 // Don't extend strings, arrays, etc. with objects | |
459 $.widget.extend( {}, value ); | |
460 // Copy everything else by reference | |
461 } else { | |
462 target[ key ] = value; | |
463 } | |
464 } | |
465 } | |
466 } | |
467 return target; | |
468 }; | |
469 | |
470 $.widget.bridge = function( name, object ) { | |
471 var fullName = object.prototype.widgetFullName || name; | |
472 $.fn[ name ] = function( options ) { | |
473 var isMethodCall = typeof options === "string", | |
474 args = slice.call( arguments, 1 ), | |
475 returnValue = this; | |
476 | |
477 // allow multiple hashes to be passed on init | |
478 options = !isMethodCall && args.length ? | |
479 $.widget.extend.apply( null, [ options ].concat(args) ) : | |
480 options; | |
481 | |
482 if ( isMethodCall ) { | |
483 this.each(function() { | |
484 var methodValue, | |
485 instance = $.data( this, fullName ); | |
486 if ( !instance ) { | |
487 return $.error( "cannot call methods on " + name + " prior to initialization; " + | |
488 "attempted to call method '" + options + "'" ); | |
489 } | |
490 if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) { | |
491 return $.error( "no such method '" + options + "' for " + name + " widget instance" ); | |
492 } | |
493 methodValue = instance[ options ].apply( instance, args ); | |
494 if ( methodValue !== instance && methodValue !== undefined ) { | |
495 returnValue = methodValue && methodValue.jquery ? | |
496 returnValue.pushStack( methodValue.get() ) : | |
497 methodValue; | |
498 return false; | |
499 } | |
500 }); | |
501 } else { | |
502 this.each(function() { | |
503 var instance = $.data( this, fullName ); | |
504 if ( instance ) { | |
505 instance.option( options || {} )._init(); | |
506 } else { | |
507 $.data( this, fullName, new object( options, this ) ); | |
508 } | |
509 }); | |
510 } | |
511 | |
512 return returnValue; | |
513 }; | |
514 }; | |
515 | |
516 $.Widget = function( /* options, element */ ) {}; | |
517 $.Widget._childConstructors = []; | |
518 | |
519 $.Widget.prototype = { | |
520 widgetName: "widget", | |
521 widgetEventPrefix: "", | |
522 defaultElement: "<div>", | |
523 options: { | |
524 disabled: false, | |
525 | |
526 // callbacks | |
527 create: null | |
528 }, | |
529 _createWidget: function( options, element ) { | |
530 element = $( element || this.defaultElement || this )[ 0 ]; | |
531 this.element = $( element ); | |
532 this.uuid = uuid++; | |
533 this.eventNamespace = "." + this.widgetName + this.uuid; | |
534 this.options = $.widget.extend( {}, | |
535 this.options, | |
536 this._getCreateOptions(), | |
537 options ); | |
538 | |
539 this.bindings = $(); | |
540 this.hoverable = $(); | |
541 this.focusable = $(); | |
542 | |
543 if ( element !== this ) { | |
544 $.data( element, this.widgetFullName, this ); | |
545 this._on( true, this.element, { | |
546 remove: function( event ) { | |
547 if ( event.target === element ) { | |
548 this.destroy(); | |
549 } | |
550 } | |
551 }); | |
552 this.document = $( element.style ? | |
553 // element within the document | |
554 element.ownerDocument : | |
555 // element is window or document | |
556 element.document || element ); | |
557 this.window = $( this.document[0].defaultView || this.document[0].parentWindow ); | |
558 } | |
559 | |
560 this._create(); | |
561 this._trigger( "create", null, this._getCreateEventData() ); | |
562 this._init(); | |
563 }, | |
564 _getCreateOptions: $.noop, | |
565 _getCreateEventData: $.noop, | |
566 _create: $.noop, | |
567 _init: $.noop, | |
568 | |
569 destroy: function() { | |
570 this._destroy(); | |
571 // we can probably remove the unbind calls in 2.0 | |
572 // all event bindings should go through this._on() | |
573 this.element | |
574 .unbind( this.eventNamespace ) | |
575 // 1.9 BC for #7810 | |
576 // TODO remove dual storage | |
577 .removeData( this.widgetName ) | |
578 .removeData( this.widgetFullName ) | |
579 // support: jquery <1.6.3 | |
580 // http://bugs.jquery.com/ticket/9413 | |
581 .removeData( $.camelCase( this.widgetFullName ) ); | |
582 this.widget() | |
583 .unbind( this.eventNamespace ) | |
584 .removeAttr( "aria-disabled" ) | |
585 .removeClass( | |
586 this.widgetFullName + "-disabled " + | |
587 "ui-state-disabled" ); | |
588 | |
589 // clean up events and states | |
590 this.bindings.unbind( this.eventNamespace ); | |
591 this.hoverable.removeClass( "ui-state-hover" ); | |
592 this.focusable.removeClass( "ui-state-focus" ); | |
593 }, | |
594 _destroy: $.noop, | |
595 | |
596 widget: function() { | |
597 return this.element; | |
598 }, | |
599 | |
600 option: function( key, value ) { | |
601 var options = key, | |
602 parts, | |
603 curOption, | |
604 i; | |
605 | |
606 if ( arguments.length === 0 ) { | |
607 // don't return a reference to the internal hash | |
608 return $.widget.extend( {}, this.options ); | |
609 } | |
610 | |
611 if ( typeof key === "string" ) { | |
612 // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } } | |
613 options = {}; | |
614 parts = key.split( "." ); | |
615 key = parts.shift(); | |
616 if ( parts.length ) { | |
617 curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] ); | |
618 for ( i = 0; i < parts.length - 1; i++ ) { | |
619 curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {}; | |
620 curOption = curOption[ parts[ i ] ]; | |
621 } | |
622 key = parts.pop(); | |
623 if ( arguments.length === 1 ) { | |
624 return curOption[ key ] === undefined ? null : curOption[ key ]; | |
625 } | |
626 curOption[ key ] = value; | |
627 } else { | |
628 if ( arguments.length === 1 ) { | |
629 return this.options[ key ] === undefined ? null : this.options[ key ]; | |
630 } | |
631 options[ key ] = value; | |
632 } | |
633 } | |
634 | |
635 this._setOptions( options ); | |
636 | |
637 return this; | |
638 }, | |
639 _setOptions: function( options ) { | |
640 var key; | |
641 | |
642 for ( key in options ) { | |
643 this._setOption( key, options[ key ] ); | |
644 } | |
645 | |
646 return this; | |
647 }, | |
648 _setOption: function( key, value ) { | |
649 this.options[ key ] = value; | |
650 | |
651 if ( key === "disabled" ) { | |
652 this.widget() | |
653 .toggleClass( this.widgetFullName + "-disabled ui-state-disabled", !!value ) | |
654 .attr( "aria-disabled", value ); | |
655 this.hoverable.removeClass( "ui-state-hover" ); | |
656 this.focusable.removeClass( "ui-state-focus" ); | |
657 } | |
658 | |
659 return this; | |
660 }, | |
661 | |
662 enable: function() { | |
663 return this._setOption( "disabled", false ); | |
664 }, | |
665 disable: function() { | |
666 return this._setOption( "disabled", true ); | |
667 }, | |
668 | |
669 _on: function( suppressDisabledCheck, element, handlers ) { | |
670 var delegateElement, | |
671 instance = this; | |
672 | |
673 // no suppressDisabledCheck flag, shuffle arguments | |
674 if ( typeof suppressDisabledCheck !== "boolean" ) { | |
675 handlers = element; | |
676 element = suppressDisabledCheck; | |
677 suppressDisabledCheck = false; | |
678 } | |
679 | |
680 // no element argument, shuffle and use this.element | |
681 if ( !handlers ) { | |
682 handlers = element; | |
683 element = this.element; | |
684 delegateElement = this.widget(); | |
685 } else { | |
686 // accept selectors, DOM elements | |
687 element = delegateElement = $( element ); | |
688 this.bindings = this.bindings.add( element ); | |
689 } | |
690 | |
691 $.each( handlers, function( event, handler ) { | |
692 function handlerProxy() { | |
693 // allow widgets to customize the disabled handling | |
694 // - disabled as an array instead of boolean | |
695 // - disabled class as method for disabling individual parts | |
696 if ( !suppressDisabledCheck && | |
697 ( instance.options.disabled === true || | |
698 $( this ).hasClass( "ui-state-disabled" ) ) ) { | |
699 return; | |
700 } | |
701 return ( typeof handler === "string" ? instance[ handler ] : handler ) | |
702 .apply( instance, arguments ); | |
703 } | |
704 | |
705 // copy the guid so direct unbinding works | |
706 if ( typeof handler !== "string" ) { | |
707 handlerProxy.guid = handler.guid = | |
708 handler.guid || handlerProxy.guid || $.guid++; | |
709 } | |
710 | |
711 var match = event.match( /^(\w+)\s*(.*)$/ ), | |
712 eventName = match[1] + instance.eventNamespace, | |
713 selector = match[2]; | |
714 if ( selector ) { | |
715 delegateElement.delegate( selector, eventName, handlerProxy ); | |
716 } else { | |
717 element.bind( eventName, handlerProxy ); | |
718 } | |
719 }); | |
720 }, | |
721 | |
722 _off: function( element, eventName ) { | |
723 eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace; | |
724 element.unbind( eventName ).undelegate( eventName ); | |
725 }, | |
726 | |
727 _delay: function( handler, delay ) { | |
728 function handlerProxy() { | |
729 return ( typeof handler === "string" ? instance[ handler ] : handler ) | |
730 .apply( instance, arguments ); | |
731 } | |
732 var instance = this; | |
733 return setTimeout( handlerProxy, delay || 0 ); | |
734 }, | |
735 | |
736 _hoverable: function( element ) { | |
737 this.hoverable = this.hoverable.add( element ); | |
738 this._on( element, { | |
739 mouseenter: function( event ) { | |
740 $( event.currentTarget ).addClass( "ui-state-hover" ); | |
741 }, | |
742 mouseleave: function( event ) { | |
743 $( event.currentTarget ).removeClass( "ui-state-hover" ); | |
744 } | |
745 }); | |
746 }, | |
747 | |
748 _focusable: function( element ) { | |
749 this.focusable = this.focusable.add( element ); | |
750 this._on( element, { | |
751 focusin: function( event ) { | |
752 $( event.currentTarget ).addClass( "ui-state-focus" ); | |
753 }, | |
754 focusout: function( event ) { | |
755 $( event.currentTarget ).removeClass( "ui-state-focus" ); | |
756 } | |
757 }); | |
758 }, | |
759 | |
760 _trigger: function( type, event, data ) { | |
761 var prop, orig, | |
762 callback = this.options[ type ]; | |
763 | |
764 data = data || {}; | |
765 event = $.Event( event ); | |
766 event.type = ( type === this.widgetEventPrefix ? | |
767 type : | |
768 this.widgetEventPrefix + type ).toLowerCase(); | |
769 // the original event may come from any element | |
770 // so we need to reset the target on the new event | |
771 event.target = this.element[ 0 ]; | |
772 | |
773 // copy original event properties over to the new event | |
774 orig = event.originalEvent; | |
775 if ( orig ) { | |
776 for ( prop in orig ) { | |
777 if ( !( prop in event ) ) { | |
778 event[ prop ] = orig[ prop ]; | |
779 } | |
780 } | |
781 } | |
782 | |
783 this.element.trigger( event, data ); | |
784 return !( $.isFunction( callback ) && | |
785 callback.apply( this.element[0], [ event ].concat( data ) ) === false || | |
786 event.isDefaultPrevented() ); | |
787 } | |
788 }; | |
789 | |
790 $.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) { | |
791 $.Widget.prototype[ "_" + method ] = function( element, options, callback ) { | |
792 if ( typeof options === "string" ) { | |
793 options = { effect: options }; | |
794 } | |
795 var hasOptions, | |
796 effectName = !options ? | |
797 method : | |
798 options === true || typeof options === "number" ? | |
799 defaultEffect : | |
800 options.effect || defaultEffect; | |
801 options = options || {}; | |
802 if ( typeof options === "number" ) { | |
803 options = { duration: options }; | |
804 } | |
805 hasOptions = !$.isEmptyObject( options ); | |
806 options.complete = callback; | |
807 if ( options.delay ) { | |
808 element.delay( options.delay ); | |
809 } | |
810 if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) { | |
811 element[ method ]( options ); | |
812 } else if ( effectName !== method && element[ effectName ] ) { | |
813 element[ effectName ]( options.duration, options.easing, callback ); | |
814 } else { | |
815 element.queue(function( next ) { | |
816 $( this )[ method ](); | |
817 if ( callback ) { | |
818 callback.call( element[ 0 ] ); | |
819 } | |
820 next(); | |
821 }); | |
822 } | |
823 }; | |
824 }); | |
825 | |
826 })( jQuery ); | |
827 | |
828 (function( $, undefined ) { | |
829 | |
830 var mouseHandled = false; | |
831 $( document ).mouseup( function() { | |
832 mouseHandled = false; | |
833 }); | |
834 | |
835 $.widget("ui.mouse", { | |
836 version: "1.10.4", | |
837 options: { | |
838 cancel: "input,textarea,button,select,option", | |
839 distance: 1, | |
840 delay: 0 | |
841 }, | |
842 _mouseInit: function() { | |
843 var that = this; | |
844 | |
845 this.element | |
846 .bind("mousedown."+this.widgetName, function(event) { | |
847 return that._mouseDown(event); | |
848 }) | |
849 .bind("click."+this.widgetName, function(event) { | |
850 if (true === $.data(event.target, that.widgetName + ".preventClickEvent")) { | |
851 $.removeData(event.target, that.widgetName + ".preventClickEvent"); | |
852 event.stopImmediatePropagation(); | |
853 return false; | |
854 } | |
855 }); | |
856 | |
857 this.started = false; | |
858 }, | |
859 | |
860 // TODO: make sure destroying one instance of mouse doesn't mess with | |
861 // other instances of mouse | |
862 _mouseDestroy: function() { | |
863 this.element.unbind("."+this.widgetName); | |
864 if ( this._mouseMoveDelegate ) { | |
865 $(document) | |
866 .unbind("mousemove."+this.widgetName, this._mouseMoveDelegate) | |
867 .unbind("mouseup."+this.widgetName, this._mouseUpDelegate); | |
868 } | |
869 }, | |
870 | |
871 _mouseDown: function(event) { | |
872 // don't let more than one widget handle mouseStart | |
873 if( mouseHandled ) { return; } | |
874 | |
875 // we may have missed mouseup (out of window) | |
876 (this._mouseStarted && this._mouseUp(event)); | |
877 | |
878 this._mouseDownEvent = event; | |
879 | |
880 var that = this, | |
881 btnIsLeft = (event.which === 1), | |
882 // event.target.nodeName works around a bug in IE 8 with | |
883 // disabled inputs (#7620) | |
884 elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false); | |
885 if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) { | |
886 return true; | |
887 } | |
888 | |
889 this.mouseDelayMet = !this.options.delay; | |
890 if (!this.mouseDelayMet) { | |
891 this._mouseDelayTimer = setTimeout(function() { | |
892 that.mouseDelayMet = true; | |
893 }, this.options.delay); | |
894 } | |
895 | |
896 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { | |
897 this._mouseStarted = (this._mouseStart(event) !== false); | |
898 if (!this._mouseStarted) { | |
899 event.preventDefault(); | |
900 return true; | |
901 } | |
902 } | |
903 | |
904 // Click event may never have fired (Gecko & Opera) | |
905 if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) { | |
906 $.removeData(event.target, this.widgetName + ".preventClickEvent"); | |
907 } | |
908 | |
909 // these delegates are required to keep context | |
910 this._mouseMoveDelegate = function(event) { | |
911 return that._mouseMove(event); | |
912 }; | |
913 this._mouseUpDelegate = function(event) { | |
914 return that._mouseUp(event); | |
915 }; | |
916 $(document) | |
917 .bind("mousemove."+this.widgetName, this._mouseMoveDelegate) | |
918 .bind("mouseup."+this.widgetName, this._mouseUpDelegate); | |
919 | |
920 event.preventDefault(); | |
921 | |
922 mouseHandled = true; | |
923 return true; | |
924 }, | |
925 | |
926 _mouseMove: function(event) { | |
927 // IE mouseup check - mouseup happened when mouse was out of window | |
928 if ($.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) { | |
929 return this._mouseUp(event); | |
930 } | |
931 | |
932 if (this._mouseStarted) { | |
933 this._mouseDrag(event); | |
934 return event.preventDefault(); | |
935 } | |
936 | |
937 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { | |
938 this._mouseStarted = | |
939 (this._mouseStart(this._mouseDownEvent, event) !== false); | |
940 (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event)); | |
941 } | |
942 | |
943 return !this._mouseStarted; | |
944 }, | |
945 | |
946 _mouseUp: function(event) { | |
947 $(document) | |
948 .unbind("mousemove."+this.widgetName, this._mouseMoveDelegate) | |
949 .unbind("mouseup."+this.widgetName, this._mouseUpDelegate); | |
950 | |
951 if (this._mouseStarted) { | |
952 this._mouseStarted = false; | |
953 | |
954 if (event.target === this._mouseDownEvent.target) { | |
955 $.data(event.target, this.widgetName + ".preventClickEvent", true); | |
956 } | |
957 | |
958 this._mouseStop(event); | |
959 } | |
960 | |
961 return false; | |
962 }, | |
963 | |
964 _mouseDistanceMet: function(event) { | |
965 return (Math.max( | |
966 Math.abs(this._mouseDownEvent.pageX - event.pageX), | |
967 Math.abs(this._mouseDownEvent.pageY - event.pageY) | |
968 ) >= this.options.distance | |
969 ); | |
970 }, | |
971 | |
972 _mouseDelayMet: function(/* event */) { | |
973 return this.mouseDelayMet; | |
974 }, | |
975 | |
976 // These are placeholder methods, to be overriden by extending plugin | |
977 _mouseStart: function(/* event */) {}, | |
978 _mouseDrag: function(/* event */) {}, | |
979 _mouseStop: function(/* event */) {}, | |
980 _mouseCapture: function(/* event */) { return true; } | |
981 }); | |
982 | |
983 })(jQuery); | |
984 | |
985 (function( $, undefined ) { | |
986 | |
987 $.widget("ui.draggable", $.ui.mouse, { | |
988 version: "1.10.4", | |
989 widgetEventPrefix: "drag", | |
990 options: { | |
991 addClasses: true, | |
992 appendTo: "parent", | |
993 axis: false, | |
994 connectToSortable: false, | |
995 containment: false, | |
996 cursor: "auto", | |
997 cursorAt: false, | |
998 grid: false, | |
999 handle: false, | |
1000 helper: "original", | |
1001 iframeFix: false, | |
1002 opacity: false, | |
1003 refreshPositions: false, | |
1004 revert: false, | |
1005 revertDuration: 500, | |
1006 scope: "default", | |
1007 scroll: true, | |
1008 scrollSensitivity: 20, | |
1009 scrollSpeed: 20, | |
1010 snap: false, | |
1011 snapMode: "both", | |
1012 snapTolerance: 20, | |
1013 stack: false, | |
1014 zIndex: false, | |
1015 | |
1016 // callbacks | |
1017 drag: null, | |
1018 start: null, | |
1019 stop: null | |
1020 }, | |
1021 _create: function() { | |
1022 | |
1023 if (this.options.helper === "original" && !(/^(?:r|a|f)/).test(this.element.css("position"))) { | |
1024 this.element[0].style.position = "relative"; | |
1025 } | |
1026 if (this.options.addClasses){ | |
1027 this.element.addClass("ui-draggable"); | |
1028 } | |
1029 if (this.options.disabled){ | |
1030 this.element.addClass("ui-draggable-disabled"); | |
1031 } | |
1032 | |
1033 this._mouseInit(); | |
1034 | |
1035 }, | |
1036 | |
1037 _destroy: function() { | |
1038 this.element.removeClass( "ui-draggable ui-draggable-dragging ui-draggable-disabled" ); | |
1039 this._mouseDestroy(); | |
1040 }, | |
1041 | |
1042 _mouseCapture: function(event) { | |
1043 | |
1044 var o = this.options; | |
1045 | |
1046 // among others, prevent a drag on a resizable-handle | |
1047 if (this.helper || o.disabled || $(event.target).closest(".ui-resizable-handle").length > 0) { | |
1048 return false; | |
1049 } | |
1050 | |
1051 //Quit if we're not on a valid handle | |
1052 this.handle = this._getHandle(event); | |
1053 if (!this.handle) { | |
1054 return false; | |
1055 } | |
1056 | |
1057 $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() { | |
1058 $("<div class='ui-draggable-iframeFix' style='background: #fff;'></div>") | |
1059 .css({ | |
1060 width: this.offsetWidth+"px", height: this.offsetHeight+"px", | |
1061 position: "absolute", opacity: "0.001", zIndex: 1000 | |
1062 }) | |
1063 .css($(this).offset()) | |
1064 .appendTo("body"); | |
1065 }); | |
1066 | |
1067 return true; | |
1068 | |
1069 }, | |
1070 | |
1071 _mouseStart: function(event) { | |
1072 | |
1073 var o = this.options; | |
1074 | |
1075 //Create and append the visible helper | |
1076 this.helper = this._createHelper(event); | |
1077 | |
1078 this.helper.addClass("ui-draggable-dragging"); | |
1079 | |
1080 //Cache the helper size | |
1081 this._cacheHelperProportions(); | |
1082 | |
1083 //If ddmanager is used for droppables, set the global draggable | |
1084 if($.ui.ddmanager) { | |
1085 $.ui.ddmanager.current = this; | |
1086 } | |
1087 | |
1088 /* | |
1089 * - Position generation - | |
1090 * This block generates everything position related - it's the core of draggables. | |
1091 */ | |
1092 | |
1093 //Cache the margins of the original element | |
1094 this._cacheMargins(); | |
1095 | |
1096 //Store the helper's css position | |
1097 this.cssPosition = this.helper.css( "position" ); | |
1098 this.scrollParent = this.helper.scrollParent(); | |
1099 this.offsetParent = this.helper.offsetParent(); | |
1100 this.offsetParentCssPosition = this.offsetParent.css( "position" ); | |
1101 | |
1102 //The element's absolute position on the page minus margins | |
1103 this.offset = this.positionAbs = this.element.offset(); | |
1104 this.offset = { | |
1105 top: this.offset.top - this.margins.top, | |
1106 left: this.offset.left - this.margins.left | |
1107 }; | |
1108 | |
1109 //Reset scroll cache | |
1110 this.offset.scroll = false; | |
1111 | |
1112 $.extend(this.offset, { | |
1113 click: { //Where the click happened, relative to the element | |
1114 left: event.pageX - this.offset.left, | |
1115 top: event.pageY - this.offset.top | |
1116 }, | |
1117 parent: this._getParentOffset(), | |
1118 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper | |
1119 }); | |
1120 | |
1121 //Generate the original position | |
1122 this.originalPosition = this.position = this._generatePosition(event); | |
1123 this.originalPageX = event.pageX; | |
1124 this.originalPageY = event.pageY; | |
1125 | |
1126 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied | |
1127 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)); | |
1128 | |
1129 //Set a containment if given in the options | |
1130 this._setContainment(); | |
1131 | |
1132 //Trigger event + callbacks | |
1133 if(this._trigger("start", event) === false) { | |
1134 this._clear(); | |
1135 return false; | |
1136 } | |
1137 | |
1138 //Recache the helper size | |
1139 this._cacheHelperProportions(); | |
1140 | |
1141 //Prepare the droppable offsets | |
1142 if ($.ui.ddmanager && !o.dropBehaviour) { | |
1143 $.ui.ddmanager.prepareOffsets(this, event); | |
1144 } | |
1145 | |
1146 | |
1147 this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position | |
1148 | |
1149 //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003) | |
1150 if ( $.ui.ddmanager ) { | |
1151 $.ui.ddmanager.dragStart(this, event); | |
1152 } | |
1153 | |
1154 return true; | |
1155 }, | |
1156 | |
1157 _mouseDrag: function(event, noPropagation) { | |
1158 // reset any necessary cached properties (see #5009) | |
1159 if ( this.offsetParentCssPosition === "fixed" ) { | |
1160 this.offset.parent = this._getParentOffset(); | |
1161 } | |
1162 | |
1163 //Compute the helpers position | |
1164 this.position = this._generatePosition(event); | |
1165 this.positionAbs = this._convertPositionTo("absolute"); | |
1166 | |
1167 //Call plugins and callbacks and use the resulting position if something is returned | |
1168 if (!noPropagation) { | |
1169 var ui = this._uiHash(); | |
1170 if(this._trigger("drag", event, ui) === false) { | |
1171 this._mouseUp({}); | |
1172 return false; | |
1173 } | |
1174 this.position = ui.position; | |
1175 } | |
1176 | |
1177 if(!this.options.axis || this.options.axis !== "y") { | |
1178 this.helper[0].style.left = this.position.left+"px"; | |
1179 } | |
1180 if(!this.options.axis || this.options.axis !== "x") { | |
1181 this.helper[0].style.top = this.position.top+"px"; | |
1182 } | |
1183 if($.ui.ddmanager) { | |
1184 $.ui.ddmanager.drag(this, event); | |
1185 } | |
1186 | |
1187 return false; | |
1188 }, | |
1189 | |
1190 _mouseStop: function(event) { | |
1191 | |
1192 //If we are using droppables, inform the manager about the drop | |
1193 var that = this, | |
1194 dropped = false; | |
1195 if ($.ui.ddmanager && !this.options.dropBehaviour) { | |
1196 dropped = $.ui.ddmanager.drop(this, event); | |
1197 } | |
1198 | |
1199 //if a drop comes from outside (a sortable) | |
1200 if(this.dropped) { | |
1201 dropped = this.dropped; | |
1202 this.dropped = false; | |
1203 } | |
1204 | |
1205 //if the original element is no longer in the DOM don't bother to continue (see #8269) | |
1206 if ( this.options.helper === "original" && !$.contains( this.element[ 0 ].ownerDocument, this.element[ 0 ] ) ) { | |
1207 return false; | |
1208 } | |
1209 | |
1210 if((this.options.revert === "invalid" && !dropped) || (this.options.revert === "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) { | |
1211 $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() { | |
1212 if(that._trigger("stop", event) !== false) { | |
1213 that._clear(); | |
1214 } | |
1215 }); | |
1216 } else { | |
1217 if(this._trigger("stop", event) !== false) { | |
1218 this._clear(); | |
1219 } | |
1220 } | |
1221 | |
1222 return false; | |
1223 }, | |
1224 | |
1225 _mouseUp: function(event) { | |
1226 //Remove frame helpers | |
1227 $("div.ui-draggable-iframeFix").each(function() { | |
1228 this.parentNode.removeChild(this); | |
1229 }); | |
1230 | |
1231 //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003) | |
1232 if( $.ui.ddmanager ) { | |
1233 $.ui.ddmanager.dragStop(this, event); | |
1234 } | |
1235 | |
1236 return $.ui.mouse.prototype._mouseUp.call(this, event); | |
1237 }, | |
1238 | |
1239 cancel: function() { | |
1240 | |
1241 if(this.helper.is(".ui-draggable-dragging")) { | |
1242 this._mouseUp({}); | |
1243 } else { | |
1244 this._clear(); | |
1245 } | |
1246 | |
1247 return this; | |
1248 | |
1249 }, | |
1250 | |
1251 _getHandle: function(event) { | |
1252 return this.options.handle ? | |
1253 !!$( event.target ).closest( this.element.find( this.options.handle ) ).length : | |
1254 true; | |
1255 }, | |
1256 | |
1257 _createHelper: function(event) { | |
1258 | |
1259 var o = this.options, | |
1260 helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper === "clone" ? this.element.clone().removeAttr("id") : this.element); | |
1261 | |
1262 if(!helper.parents("body").length) { | |
1263 helper.appendTo((o.appendTo === "parent" ? this.element[0].parentNode : o.appendTo)); | |
1264 } | |
1265 | |
1266 if(helper[0] !== this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) { | |
1267 helper.css("position", "absolute"); | |
1268 } | |
1269 | |
1270 return helper; | |
1271 | |
1272 }, | |
1273 | |
1274 _adjustOffsetFromHelper: function(obj) { | |
1275 if (typeof obj === "string") { | |
1276 obj = obj.split(" "); | |
1277 } | |
1278 if ($.isArray(obj)) { | |
1279 obj = {left: +obj[0], top: +obj[1] || 0}; | |
1280 } | |
1281 if ("left" in obj) { | |
1282 this.offset.click.left = obj.left + this.margins.left; | |
1283 } | |
1284 if ("right" in obj) { | |
1285 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; | |
1286 } | |
1287 if ("top" in obj) { | |
1288 this.offset.click.top = obj.top + this.margins.top; | |
1289 } | |
1290 if ("bottom" in obj) { | |
1291 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; | |
1292 } | |
1293 }, | |
1294 | |
1295 _getParentOffset: function() { | |
1296 | |
1297 //Get the offsetParent and cache its position | |
1298 var po = this.offsetParent.offset(); | |
1299 | |
1300 // This is a special case where we need to modify a offset calculated on start, since the following happened: | |
1301 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent | |
1302 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that | |
1303 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag | |
1304 if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) { | |
1305 po.left += this.scrollParent.scrollLeft(); | |
1306 po.top += this.scrollParent.scrollTop(); | |
1307 } | |
1308 | |
1309 //This needs to be actually done for all browsers, since pageX/pageY includes this information | |
1310 //Ugly IE fix | |
1311 if((this.offsetParent[0] === document.body) || | |
1312 (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) { | |
1313 po = { top: 0, left: 0 }; | |
1314 } | |
1315 | |
1316 return { | |
1317 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0), | |
1318 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0) | |
1319 }; | |
1320 | |
1321 }, | |
1322 | |
1323 _getRelativeOffset: function() { | |
1324 | |
1325 if(this.cssPosition === "relative") { | |
1326 var p = this.element.position(); | |
1327 return { | |
1328 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(), | |
1329 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft() | |
1330 }; | |
1331 } else { | |
1332 return { top: 0, left: 0 }; | |
1333 } | |
1334 | |
1335 }, | |
1336 | |
1337 _cacheMargins: function() { | |
1338 this.margins = { | |
1339 left: (parseInt(this.element.css("marginLeft"),10) || 0), | |
1340 top: (parseInt(this.element.css("marginTop"),10) || 0), | |
1341 right: (parseInt(this.element.css("marginRight"),10) || 0), | |
1342 bottom: (parseInt(this.element.css("marginBottom"),10) || 0) | |
1343 }; | |
1344 }, | |
1345 | |
1346 _cacheHelperProportions: function() { | |
1347 this.helperProportions = { | |
1348 width: this.helper.outerWidth(), | |
1349 height: this.helper.outerHeight() | |
1350 }; | |
1351 }, | |
1352 | |
1353 _setContainment: function() { | |
1354 | |
1355 var over, c, ce, | |
1356 o = this.options; | |
1357 | |
1358 if ( !o.containment ) { | |
1359 this.containment = null; | |
1360 return; | |
1361 } | |
1362 | |
1363 if ( o.containment === "window" ) { | |
1364 this.containment = [ | |
1365 $( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left, | |
1366 $( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top, | |
1367 $( window ).scrollLeft() + $( window ).width() - this.helperProportions.width - this.margins.left, | |
1368 $( window ).scrollTop() + ( $( window ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top | |
1369 ]; | |
1370 return; | |
1371 } | |
1372 | |
1373 if ( o.containment === "document") { | |
1374 this.containment = [ | |
1375 0, | |
1376 0, | |
1377 $( document ).width() - this.helperProportions.width - this.margins.left, | |
1378 ( $( document ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top | |
1379 ]; | |
1380 return; | |
1381 } | |
1382 | |
1383 if ( o.containment.constructor === Array ) { | |
1384 this.containment = o.containment; | |
1385 return; | |
1386 } | |
1387 | |
1388 if ( o.containment === "parent" ) { | |
1389 o.containment = this.helper[ 0 ].parentNode; | |
1390 } | |
1391 | |
1392 c = $( o.containment ); | |
1393 ce = c[ 0 ]; | |
1394 | |
1395 if( !ce ) { | |
1396 return; | |
1397 } | |
1398 | |
1399 over = c.css( "overflow" ) !== "hidden"; | |
1400 | |
1401 this.containment = [ | |
1402 ( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ), | |
1403 ( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingTop" ), 10 ) || 0 ) , | |
1404 ( over ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) - ( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) - ( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) - this.helperProportions.width - this.margins.left - this.margins.right, | |
1405 ( over ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) - ( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) - ( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) - this.helperProportions.height - this.margins.top - this.margins.bottom | |
1406 ]; | |
1407 this.relative_container = c; | |
1408 }, | |
1409 | |
1410 _convertPositionTo: function(d, pos) { | |
1411 | |
1412 if(!pos) { | |
1413 pos = this.position; | |
1414 } | |
1415 | |
1416 var mod = d === "absolute" ? 1 : -1, | |
1417 scroll = this.cssPosition === "absolute" && !( this.scrollParent[ 0 ] !== document && $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ? this.offsetParent : this.scrollParent; | |
1418 | |
1419 //Cache the scroll | |
1420 if (!this.offset.scroll) { | |
1421 this.offset.scroll = {top : scroll.scrollTop(), left : scroll.scrollLeft()}; | |
1422 } | |
1423 | |
1424 return { | |
1425 top: ( | |
1426 pos.top + // The absolute mouse position | |
1427 this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent | |
1428 this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border) | |
1429 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : this.offset.scroll.top ) * mod ) | |
1430 ), | |
1431 left: ( | |
1432 pos.left + // The absolute mouse position | |
1433 this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent | |
1434 this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border) | |
1435 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : this.offset.scroll.left ) * mod ) | |
1436 ) | |
1437 }; | |
1438 | |
1439 }, | |
1440 | |
1441 _generatePosition: function(event) { | |
1442 | |
1443 var containment, co, top, left, | |
1444 o = this.options, | |
1445 scroll = this.cssPosition === "absolute" && !( this.scrollParent[ 0 ] !== document && $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ? this.offsetParent : this.scrollParent, | |
1446 pageX = event.pageX, | |
1447 pageY = event.pageY; | |
1448 | |
1449 //Cache the scroll | |
1450 if (!this.offset.scroll) { | |
1451 this.offset.scroll = {top : scroll.scrollTop(), left : scroll.scrollLeft()}; | |
1452 } | |
1453 | |
1454 /* | |
1455 * - Position constraining - | |
1456 * Constrain the position to a mix of grid, containment. | |
1457 */ | |
1458 | |
1459 // If we are not dragging yet, we won't check for options | |
1460 if ( this.originalPosition ) { | |
1461 if ( this.containment ) { | |
1462 if ( this.relative_container ){ | |
1463 co = this.relative_container.offset(); | |
1464 containment = [ | |
1465 this.containment[ 0 ] + co.left, | |
1466 this.containment[ 1 ] + co.top, | |
1467 this.containment[ 2 ] + co.left, | |
1468 this.containment[ 3 ] + co.top | |
1469 ]; | |
1470 } | |
1471 else { | |
1472 containment = this.containment; | |
1473 } | |
1474 | |
1475 if(event.pageX - this.offset.click.left < containment[0]) { | |
1476 pageX = containment[0] + this.offset.click.left; | |
1477 } | |
1478 if(event.pageY - this.offset.click.top < containment[1]) { | |
1479 pageY = containment[1] + this.offset.click.top; | |
1480 } | |
1481 if(event.pageX - this.offset.click.left > containment[2]) { | |
1482 pageX = containment[2] + this.offset.click.left; | |
1483 } | |
1484 if(event.pageY - this.offset.click.top > containment[3]) { | |
1485 pageY = containment[3] + this.offset.click.top; | |
1486 } | |
1487 } | |
1488 | |
1489 if(o.grid) { | |
1490 //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950) | |
1491 top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY; | |
1492 pageY = containment ? ((top - this.offset.click.top >= containment[1] || top - this.offset.click.top > containment[3]) ? top : ((top - this.offset.click.top >= containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top; | |
1493 | |
1494 left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX; | |
1495 pageX = containment ? ((left - this.offset.click.left >= containment[0] || left - this.offset.click.left > containment[2]) ? left : ((left - this.offset.click.left >= containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left; | |
1496 } | |
1497 | |
1498 } | |
1499 | |
1500 return { | |
1501 top: ( | |
1502 pageY - // The absolute mouse position | |
1503 this.offset.click.top - // Click offset (relative to the element) | |
1504 this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent | |
1505 this.offset.parent.top + // The offsetParent's offset without borders (offset + border) | |
1506 ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : this.offset.scroll.top ) | |
1507 ), | |
1508 left: ( | |
1509 pageX - // The absolute mouse position | |
1510 this.offset.click.left - // Click offset (relative to the element) | |
1511 this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent | |
1512 this.offset.parent.left + // The offsetParent's offset without borders (offset + border) | |
1513 ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : this.offset.scroll.left ) | |
1514 ) | |
1515 }; | |
1516 | |
1517 }, | |
1518 | |
1519 _clear: function() { | |
1520 this.helper.removeClass("ui-draggable-dragging"); | |
1521 if(this.helper[0] !== this.element[0] && !this.cancelHelperRemoval) { | |
1522 this.helper.remove(); | |
1523 } | |
1524 this.helper = null; | |
1525 this.cancelHelperRemoval = false; | |
1526 }, | |
1527 | |
1528 // From now on bulk stuff - mainly helpers | |
1529 | |
1530 _trigger: function(type, event, ui) { | |
1531 ui = ui || this._uiHash(); | |
1532 $.ui.plugin.call(this, type, [event, ui]); | |
1533 //The absolute position has to be recalculated after plugins | |
1534 if(type === "drag") { | |
1535 this.positionAbs = this._convertPositionTo("absolute"); | |
1536 } | |
1537 return $.Widget.prototype._trigger.call(this, type, event, ui); | |
1538 }, | |
1539 | |
1540 plugins: {}, | |
1541 | |
1542 _uiHash: function() { | |
1543 return { | |
1544 helper: this.helper, | |
1545 position: this.position, | |
1546 originalPosition: this.originalPosition, | |
1547 offset: this.positionAbs | |
1548 }; | |
1549 } | |
1550 | |
1551 }); | |
1552 | |
1553 $.ui.plugin.add("draggable", "connectToSortable", { | |
1554 start: function(event, ui) { | |
1555 | |
1556 var inst = $(this).data("ui-draggable"), o = inst.options, | |
1557 uiSortable = $.extend({}, ui, { item: inst.element }); | |
1558 inst.sortables = []; | |
1559 $(o.connectToSortable).each(function() { | |
1560 var sortable = $.data(this, "ui-sortable"); | |
1561 if (sortable && !sortable.options.disabled) { | |
1562 inst.sortables.push({ | |
1563 instance: sortable, | |
1564 shouldRevert: sortable.options.revert | |
1565 }); | |
1566 sortable.refreshPositions(); // Call the sortable's refreshPositions at drag start to refresh the containerCache since the sortable container cache is used in drag and needs to be up to date (this will ensure it's initialised as well as being kept in step with any changes that might have happened on the page). | |
1567 sortable._trigger("activate", event, uiSortable); | |
1568 } | |
1569 }); | |
1570 | |
1571 }, | |
1572 stop: function(event, ui) { | |
1573 | |
1574 //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper | |
1575 var inst = $(this).data("ui-draggable"), | |
1576 uiSortable = $.extend({}, ui, { item: inst.element }); | |
1577 | |
1578 $.each(inst.sortables, function() { | |
1579 if(this.instance.isOver) { | |
1580 | |
1581 this.instance.isOver = 0; | |
1582 | |
1583 inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance | |
1584 this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work) | |
1585 | |
1586 //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: "valid/invalid" | |
1587 if(this.shouldRevert) { | |
1588 this.instance.options.revert = this.shouldRevert; | |
1589 } | |
1590 | |
1591 //Trigger the stop of the sortable | |
1592 this.instance._mouseStop(event); | |
1593 | |
1594 this.instance.options.helper = this.instance.options._helper; | |
1595 | |
1596 //If the helper has been the original item, restore properties in the sortable | |
1597 if(inst.options.helper === "original") { | |
1598 this.instance.currentItem.css({ top: "auto", left: "auto" }); | |
1599 } | |
1600 | |
1601 } else { | |
1602 this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance | |
1603 this.instance._trigger("deactivate", event, uiSortable); | |
1604 } | |
1605 | |
1606 }); | |
1607 | |
1608 }, | |
1609 drag: function(event, ui) { | |
1610 | |
1611 var inst = $(this).data("ui-draggable"), that = this; | |
1612 | |
1613 $.each(inst.sortables, function() { | |
1614 | |
1615 var innermostIntersecting = false, | |
1616 thisSortable = this; | |
1617 | |
1618 //Copy over some variables to allow calling the sortable's native _intersectsWith | |
1619 this.instance.positionAbs = inst.positionAbs; | |
1620 this.instance.helperProportions = inst.helperProportions; | |
1621 this.instance.offset.click = inst.offset.click; | |
1622 | |
1623 if(this.instance._intersectsWith(this.instance.containerCache)) { | |
1624 innermostIntersecting = true; | |
1625 $.each(inst.sortables, function () { | |
1626 this.instance.positionAbs = inst.positionAbs; | |
1627 this.instance.helperProportions = inst.helperProportions; | |
1628 this.instance.offset.click = inst.offset.click; | |
1629 if (this !== thisSortable && | |
1630 this.instance._intersectsWith(this.instance.containerCache) && | |
1631 $.contains(thisSortable.instance.element[0], this.instance.element[0]) | |
1632 ) { | |
1633 innermostIntersecting = false; | |
1634 } | |
1635 return innermostIntersecting; | |
1636 }); | |
1637 } | |
1638 | |
1639 | |
1640 if(innermostIntersecting) { | |
1641 //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once | |
1642 if(!this.instance.isOver) { | |
1643 | |
1644 this.instance.isOver = 1; | |
1645 //Now we fake the start of dragging for the sortable instance, | |
1646 //by cloning the list group item, appending it to the sortable and using it as inst.currentItem | |
1647 //We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one) | |
1648 this.instance.currentItem = $(that).clone().removeAttr("id").appendTo(this.instance.element).data("ui-sortable-item", true); | |
1649 this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it | |
1650 this.instance.options.helper = function() { return ui.helper[0]; }; | |
1651 | |
1652 event.target = this.instance.currentItem[0]; | |
1653 this.instance._mouseCapture(event, true); | |
1654 this.instance._mouseStart(event, true, true); | |
1655 | |
1656 //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes | |
1657 this.instance.offset.click.top = inst.offset.click.top; | |
1658 this.instance.offset.click.left = inst.offset.click.left; | |
1659 this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left; | |
1660 this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top; | |
1661 | |
1662 inst._trigger("toSortable", event); | |
1663 inst.dropped = this.instance.element; //draggable revert needs that | |
1664 //hack so receive/update callbacks work (mostly) | |
1665 inst.currentItem = inst.element; | |
1666 this.instance.fromOutside = inst; | |
1667 | |
1668 } | |
1669 | |
1670 //Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable | |
1671 if(this.instance.currentItem) { | |
1672 this.instance._mouseDrag(event); | |
1673 } | |
1674 | |
1675 } else { | |
1676 | |
1677 //If it doesn't intersect with the sortable, and it intersected before, | |
1678 //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval | |
1679 if(this.instance.isOver) { | |
1680 | |
1681 this.instance.isOver = 0; | |
1682 this.instance.cancelHelperRemoval = true; | |
1683 | |
1684 //Prevent reverting on this forced stop | |
1685 this.instance.options.revert = false; | |
1686 | |
1687 // The out event needs to be triggered independently | |
1688 this.instance._trigger("out", event, this.instance._uiHash(this.instance)); | |
1689 | |
1690 this.instance._mouseStop(event, true); | |
1691 this.instance.options.helper = this.instance.options._helper; | |
1692 | |
1693 //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size | |
1694 this.instance.currentItem.remove(); | |
1695 if(this.instance.placeholder) { | |
1696 this.instance.placeholder.remove(); | |
1697 } | |
1698 | |
1699 inst._trigger("fromSortable", event); | |
1700 inst.dropped = false; //draggable revert needs that | |
1701 } | |
1702 | |
1703 } | |
1704 | |
1705 }); | |
1706 | |
1707 } | |
1708 }); | |
1709 | |
1710 $.ui.plugin.add("draggable", "cursor", { | |
1711 start: function() { | |
1712 var t = $("body"), o = $(this).data("ui-draggable").options; | |
1713 if (t.css("cursor")) { | |
1714 o._cursor = t.css("cursor"); | |
1715 } | |
1716 t.css("cursor", o.cursor); | |
1717 }, | |
1718 stop: function() { | |
1719 var o = $(this).data("ui-draggable").options; | |
1720 if (o._cursor) { | |
1721 $("body").css("cursor", o._cursor); | |
1722 } | |
1723 } | |
1724 }); | |
1725 | |
1726 $.ui.plugin.add("draggable", "opacity", { | |
1727 start: function(event, ui) { | |
1728 var t = $(ui.helper), o = $(this).data("ui-draggable").options; | |
1729 if(t.css("opacity")) { | |
1730 o._opacity = t.css("opacity"); | |
1731 } | |
1732 t.css("opacity", o.opacity); | |
1733 }, | |
1734 stop: function(event, ui) { | |
1735 var o = $(this).data("ui-draggable").options; | |
1736 if(o._opacity) { | |
1737 $(ui.helper).css("opacity", o._opacity); | |
1738 } | |
1739 } | |
1740 }); | |
1741 | |
1742 $.ui.plugin.add("draggable", "scroll", { | |
1743 start: function() { | |
1744 var i = $(this).data("ui-draggable"); | |
1745 if(i.scrollParent[0] !== document && i.scrollParent[0].tagName !== "HTML") { | |
1746 i.overflowOffset = i.scrollParent.offset(); | |
1747 } | |
1748 }, | |
1749 drag: function( event ) { | |
1750 | |
1751 var i = $(this).data("ui-draggable"), o = i.options, scrolled = false; | |
1752 | |
1753 if(i.scrollParent[0] !== document && i.scrollParent[0].tagName !== "HTML") { | |
1754 | |
1755 if(!o.axis || o.axis !== "x") { | |
1756 if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) { | |
1757 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed; | |
1758 } else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity) { | |
1759 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed; | |
1760 } | |
1761 } | |
1762 | |
1763 if(!o.axis || o.axis !== "y") { | |
1764 if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) { | |
1765 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed; | |
1766 } else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity) { | |
1767 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed; | |
1768 } | |
1769 } | |
1770 | |
1771 } else { | |
1772 | |
1773 if(!o.axis || o.axis !== "x") { | |
1774 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) { | |
1775 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); | |
1776 } else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) { | |
1777 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); | |
1778 } | |
1779 } | |
1780 | |
1781 if(!o.axis || o.axis !== "y") { | |
1782 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) { | |
1783 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); | |
1784 } else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) { | |
1785 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); | |
1786 } | |
1787 } | |
1788 | |
1789 } | |
1790 | |
1791 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) { | |
1792 $.ui.ddmanager.prepareOffsets(i, event); | |
1793 } | |
1794 | |
1795 } | |
1796 }); | |
1797 | |
1798 $.ui.plugin.add("draggable", "snap", { | |
1799 start: function() { | |
1800 | |
1801 var i = $(this).data("ui-draggable"), | |
1802 o = i.options; | |
1803 | |
1804 i.snapElements = []; | |
1805 | |
1806 $(o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap).each(function() { | |
1807 var $t = $(this), | |
1808 $o = $t.offset(); | |
1809 if(this !== i.element[0]) { | |
1810 i.snapElements.push({ | |
1811 item: this, | |
1812 width: $t.outerWidth(), height: $t.outerHeight(), | |
1813 top: $o.top, left: $o.left | |
1814 }); | |
1815 } | |
1816 }); | |
1817 | |
1818 }, | |
1819 drag: function(event, ui) { | |
1820 | |
1821 var ts, bs, ls, rs, l, r, t, b, i, first, | |
1822 inst = $(this).data("ui-draggable"), | |
1823 o = inst.options, | |
1824 d = o.snapTolerance, | |
1825 x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width, | |
1826 y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height; | |
1827 | |
1828 for (i = inst.snapElements.length - 1; i >= 0; i--){ | |
1829 | |
1830 l = inst.snapElements[i].left; | |
1831 r = l + inst.snapElements[i].width; | |
1832 t = inst.snapElements[i].top; | |
1833 b = t + inst.snapElements[i].height; | |
1834 | |
1835 if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d || !$.contains( inst.snapElements[ i ].item.ownerDocument, inst.snapElements[ i ].item ) ) { | |
1836 if(inst.snapElements[i].snapping) { | |
1837 (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); | |
1838 } | |
1839 inst.snapElements[i].snapping = false; | |
1840 continue; | |
1841 } | |
1842 | |
1843 if(o.snapMode !== "inner") { | |
1844 ts = Math.abs(t - y2) <= d; | |
1845 bs = Math.abs(b - y1) <= d; | |
1846 ls = Math.abs(l - x2) <= d; | |
1847 rs = Math.abs(r - x1) <= d; | |
1848 if(ts) { | |
1849 ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top; | |
1850 } | |
1851 if(bs) { | |
1852 ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top; | |
1853 } | |
1854 if(ls) { | |
1855 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left; | |
1856 } | |
1857 if(rs) { | |
1858 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left; | |
1859 } | |
1860 } | |
1861 | |
1862 first = (ts || bs || ls || rs); | |
1863 | |
1864 if(o.snapMode !== "outer") { | |
1865 ts = Math.abs(t - y1) <= d; | |
1866 bs = Math.abs(b - y2) <= d; | |
1867 ls = Math.abs(l - x1) <= d; | |
1868 rs = Math.abs(r - x2) <= d; | |
1869 if(ts) { | |
1870 ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top; | |
1871 } | |
1872 if(bs) { | |
1873 ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top; | |
1874 } | |
1875 if(ls) { | |
1876 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left; | |
1877 } | |
1878 if(rs) { | |
1879 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left; | |
1880 } | |
1881 } | |
1882 | |
1883 if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) { | |
1884 (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); | |
1885 } | |
1886 inst.snapElements[i].snapping = (ts || bs || ls || rs || first); | |
1887 | |
1888 } | |
1889 | |
1890 } | |
1891 }); | |
1892 | |
1893 $.ui.plugin.add("draggable", "stack", { | |
1894 start: function() { | |
1895 var min, | |
1896 o = this.data("ui-draggable").options, | |
1897 group = $.makeArray($(o.stack)).sort(function(a,b) { | |
1898 return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0); | |
1899 }); | |
1900 | |
1901 if (!group.length) { return; } | |
1902 | |
1903 min = parseInt($(group[0]).css("zIndex"), 10) || 0; | |
1904 $(group).each(function(i) { | |
1905 $(this).css("zIndex", min + i); | |
1906 }); | |
1907 this.css("zIndex", (min + group.length)); | |
1908 } | |
1909 }); | |
1910 | |
1911 $.ui.plugin.add("draggable", "zIndex", { | |
1912 start: function(event, ui) { | |
1913 var t = $(ui.helper), o = $(this).data("ui-draggable").options; | |
1914 if(t.css("zIndex")) { | |
1915 o._zIndex = t.css("zIndex"); | |
1916 } | |
1917 t.css("zIndex", o.zIndex); | |
1918 }, | |
1919 stop: function(event, ui) { | |
1920 var o = $(this).data("ui-draggable").options; | |
1921 if(o._zIndex) { | |
1922 $(ui.helper).css("zIndex", o._zIndex); | |
1923 } | |
1924 } | |
1925 }); | |
1926 | |
1927 })(jQuery); | |
1928 | |
1929 (function( $, undefined ) { | |
1930 | |
1931 function isOverAxis( x, reference, size ) { | |
1932 return ( x > reference ) && ( x < ( reference + size ) ); | |
1933 } | |
1934 | |
1935 $.widget("ui.droppable", { | |
1936 version: "1.10.4", | |
1937 widgetEventPrefix: "drop", | |
1938 options: { | |
1939 accept: "*", | |
1940 activeClass: false, | |
1941 addClasses: true, | |
1942 greedy: false, | |
1943 hoverClass: false, | |
1944 scope: "default", | |
1945 tolerance: "intersect", | |
1946 | |
1947 // callbacks | |
1948 activate: null, | |
1949 deactivate: null, | |
1950 drop: null, | |
1951 out: null, | |
1952 over: null | |
1953 }, | |
1954 _create: function() { | |
1955 | |
1956 var proportions, | |
1957 o = this.options, | |
1958 accept = o.accept; | |
1959 | |
1960 this.isover = false; | |
1961 this.isout = true; | |
1962 | |
1963 this.accept = $.isFunction(accept) ? accept : function(d) { | |
1964 return d.is(accept); | |
1965 }; | |
1966 | |
1967 this.proportions = function( /* valueToWrite */ ) { | |
1968 if ( arguments.length ) { | |
1969 // Store the droppable's proportions | |
1970 proportions = arguments[ 0 ]; | |
1971 } else { | |
1972 // Retrieve or derive the droppable's proportions | |
1973 return proportions ? | |
1974 proportions : | |
1975 proportions = { | |
1976 width: this.element[ 0 ].offsetWidth, | |
1977 height: this.element[ 0 ].offsetHeight | |
1978 }; | |
1979 } | |
1980 }; | |
1981 | |
1982 // Add the reference and positions to the manager | |
1983 $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || []; | |
1984 $.ui.ddmanager.droppables[o.scope].push(this); | |
1985 | |
1986 (o.addClasses && this.element.addClass("ui-droppable")); | |
1987 | |
1988 }, | |
1989 | |
1990 _destroy: function() { | |
1991 var i = 0, | |
1992 drop = $.ui.ddmanager.droppables[this.options.scope]; | |
1993 | |
1994 for ( ; i < drop.length; i++ ) { | |
1995 if ( drop[i] === this ) { | |
1996 drop.splice(i, 1); | |
1997 } | |
1998 } | |
1999 | |
2000 this.element.removeClass("ui-droppable ui-droppable-disabled"); | |
2001 }, | |
2002 | |
2003 _setOption: function(key, value) { | |
2004 | |
2005 if(key === "accept") { | |
2006 this.accept = $.isFunction(value) ? value : function(d) { | |
2007 return d.is(value); | |
2008 }; | |
2009 } | |
2010 $.Widget.prototype._setOption.apply(this, arguments); | |
2011 }, | |
2012 | |
2013 _activate: function(event) { | |
2014 var draggable = $.ui.ddmanager.current; | |
2015 if(this.options.activeClass) { | |
2016 this.element.addClass(this.options.activeClass); | |
2017 } | |
2018 if(draggable){ | |
2019 this._trigger("activate", event, this.ui(draggable)); | |
2020 } | |
2021 }, | |
2022 | |
2023 _deactivate: function(event) { | |
2024 var draggable = $.ui.ddmanager.current; | |
2025 if(this.options.activeClass) { | |
2026 this.element.removeClass(this.options.activeClass); | |
2027 } | |
2028 if(draggable){ | |
2029 this._trigger("deactivate", event, this.ui(draggable)); | |
2030 } | |
2031 }, | |
2032 | |
2033 _over: function(event) { | |
2034 | |
2035 var draggable = $.ui.ddmanager.current; | |
2036 | |
2037 // Bail if draggable and droppable are same element | |
2038 if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) { | |
2039 return; | |
2040 } | |
2041 | |
2042 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { | |
2043 if(this.options.hoverClass) { | |
2044 this.element.addClass(this.options.hoverClass); | |
2045 } | |
2046 this._trigger("over", event, this.ui(draggable)); | |
2047 } | |
2048 | |
2049 }, | |
2050 | |
2051 _out: function(event) { | |
2052 | |
2053 var draggable = $.ui.ddmanager.current; | |
2054 | |
2055 // Bail if draggable and droppable are same element | |
2056 if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) { | |
2057 return; | |
2058 } | |
2059 | |
2060 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { | |
2061 if(this.options.hoverClass) { | |
2062 this.element.removeClass(this.options.hoverClass); | |
2063 } | |
2064 this._trigger("out", event, this.ui(draggable)); | |
2065 } | |
2066 | |
2067 }, | |
2068 | |
2069 _drop: function(event,custom) { | |
2070 | |
2071 var draggable = custom || $.ui.ddmanager.current, | |
2072 childrenIntersection = false; | |
2073 | |
2074 // Bail if draggable and droppable are same element | |
2075 if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) { | |
2076 return false; | |
2077 } | |
2078 | |
2079 this.element.find(":data(ui-droppable)").not(".ui-draggable-dragging").each(function() { | |
2080 var inst = $.data(this, "ui-droppable"); | |
2081 if( | |
2082 inst.options.greedy && | |
2083 !inst.options.disabled && | |
2084 inst.options.scope === draggable.options.scope && | |
2085 inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element)) && | |
2086 $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance) | |
2087 ) { childrenIntersection = true; return false; } | |
2088 }); | |
2089 if(childrenIntersection) { | |
2090 return false; | |
2091 } | |
2092 | |
2093 if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { | |
2094 if(this.options.activeClass) { | |
2095 this.element.removeClass(this.options.activeClass); | |
2096 } | |
2097 if(this.options.hoverClass) { | |
2098 this.element.removeClass(this.options.hoverClass); | |
2099 } | |
2100 this._trigger("drop", event, this.ui(draggable)); | |
2101 return this.element; | |
2102 } | |
2103 | |
2104 return false; | |
2105 | |
2106 }, | |
2107 | |
2108 ui: function(c) { | |
2109 return { | |
2110 draggable: (c.currentItem || c.element), | |
2111 helper: c.helper, | |
2112 position: c.position, | |
2113 offset: c.positionAbs | |
2114 }; | |
2115 } | |
2116 | |
2117 }); | |
2118 | |
2119 $.ui.intersect = function(draggable, droppable, toleranceMode) { | |
2120 | |
2121 if (!droppable.offset) { | |
2122 return false; | |
2123 } | |
2124 | |
2125 var draggableLeft, draggableTop, | |
2126 x1 = (draggable.positionAbs || draggable.position.absolute).left, | |
2127 y1 = (draggable.positionAbs || draggable.position.absolute).top, | |
2128 x2 = x1 + draggable.helperProportions.width, | |
2129 y2 = y1 + draggable.helperProportions.height, | |
2130 l = droppable.offset.left, | |
2131 t = droppable.offset.top, | |
2132 r = l + droppable.proportions().width, | |
2133 b = t + droppable.proportions().height; | |
2134 | |
2135 switch (toleranceMode) { | |
2136 case "fit": | |
2137 return (l <= x1 && x2 <= r && t <= y1 && y2 <= b); | |
2138 case "intersect": | |
2139 return (l < x1 + (draggable.helperProportions.width / 2) && // Right Half | |
2140 x2 - (draggable.helperProportions.width / 2) < r && // Left Half | |
2141 t < y1 + (draggable.helperProportions.height / 2) && // Bottom Half | |
2142 y2 - (draggable.helperProportions.height / 2) < b ); // Top Half | |
2143 case "pointer": | |
2144 draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left); | |
2145 draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top); | |
2146 return isOverAxis( draggableTop, t, droppable.proportions().height ) && isOverAxis( draggableLeft, l, droppable.proportions().width ); | |
2147 case "touch": | |
2148 return ( | |
2149 (y1 >= t && y1 <= b) || // Top edge touching | |
2150 (y2 >= t && y2 <= b) || // Bottom edge touching | |
2151 (y1 < t && y2 > b) // Surrounded vertically | |
2152 ) && ( | |
2153 (x1 >= l && x1 <= r) || // Left edge touching | |
2154 (x2 >= l && x2 <= r) || // Right edge touching | |
2155 (x1 < l && x2 > r) // Surrounded horizontally | |
2156 ); | |
2157 default: | |
2158 return false; | |
2159 } | |
2160 | |
2161 }; | |
2162 | |
2163 /* | |
2164 This manager tracks offsets of draggables and droppables | |
2165 */ | |
2166 $.ui.ddmanager = { | |
2167 current: null, | |
2168 droppables: { "default": [] }, | |
2169 prepareOffsets: function(t, event) { | |
2170 | |
2171 var i, j, | |
2172 m = $.ui.ddmanager.droppables[t.options.scope] || [], | |
2173 type = event ? event.type : null, // workaround for #2317 | |
2174 list = (t.currentItem || t.element).find(":data(ui-droppable)").addBack(); | |
2175 | |
2176 droppablesLoop: for (i = 0; i < m.length; i++) { | |
2177 | |
2178 //No disabled and non-accepted | |
2179 if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) { | |
2180 continue; | |
2181 } | |
2182 | |
2183 // Filter out elements in the current dragged item | |
2184 for (j=0; j < list.length; j++) { | |
2185 if(list[j] === m[i].element[0]) { | |
2186 m[i].proportions().height = 0; | |
2187 continue droppablesLoop; | |
2188 } | |
2189 } | |
2190 | |
2191 m[i].visible = m[i].element.css("display") !== "none"; | |
2192 if(!m[i].visible) { | |
2193 continue; | |
2194 } | |
2195 | |
2196 //Activate the droppable if used directly from draggables | |
2197 if(type === "mousedown") { | |
2198 m[i]._activate.call(m[i], event); | |
2199 } | |
2200 | |
2201 m[ i ].offset = m[ i ].element.offset(); | |
2202 m[ i ].proportions({ width: m[ i ].element[ 0 ].offsetWidth, height: m[ i ].element[ 0 ].offsetHeight }); | |
2203 | |
2204 } | |
2205 | |
2206 }, | |
2207 drop: function(draggable, event) { | |
2208 | |
2209 var dropped = false; | |
2210 // Create a copy of the droppables in case the list changes during the drop (#9116) | |
2211 $.each(($.ui.ddmanager.droppables[draggable.options.scope] || []).slice(), function() { | |
2212 | |
2213 if(!this.options) { | |
2214 return; | |
2215 } | |
2216 if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance)) { | |
2217 dropped = this._drop.call(this, event) || dropped; | |
2218 } | |
2219 | |
2220 if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { | |
2221 this.isout = true; | |
2222 this.isover = false; | |
2223 this._deactivate.call(this, event); | |
2224 } | |
2225 | |
2226 }); | |
2227 return dropped; | |
2228 | |
2229 }, | |
2230 dragStart: function( draggable, event ) { | |
2231 //Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003) | |
2232 draggable.element.parentsUntil( "body" ).bind( "scroll.droppable", function() { | |
2233 if( !draggable.options.refreshPositions ) { | |
2234 $.ui.ddmanager.prepareOffsets( draggable, event ); | |
2235 } | |
2236 }); | |
2237 }, | |
2238 drag: function(draggable, event) { | |
2239 | |
2240 //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse. | |
2241 if(draggable.options.refreshPositions) { | |
2242 $.ui.ddmanager.prepareOffsets(draggable, event); | |
2243 } | |
2244 | |
2245 //Run through all droppables and check their positions based on specific tolerance options | |
2246 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() { | |
2247 | |
2248 if(this.options.disabled || this.greedyChild || !this.visible) { | |
2249 return; | |
2250 } | |
2251 | |
2252 var parentInstance, scope, parent, | |
2253 intersects = $.ui.intersect(draggable, this, this.options.tolerance), | |
2254 c = !intersects && this.isover ? "isout" : (intersects && !this.isover ? "isover" : null); | |
2255 if(!c) { | |
2256 return; | |
2257 } | |
2258 | |
2259 if (this.options.greedy) { | |
2260 // find droppable parents with same scope | |
2261 scope = this.options.scope; | |
2262 parent = this.element.parents(":data(ui-droppable)").filter(function () { | |
2263 return $.data(this, "ui-droppable").options.scope === scope; | |
2264 }); | |
2265 | |
2266 if (parent.length) { | |
2267 parentInstance = $.data(parent[0], "ui-droppable"); | |
2268 parentInstance.greedyChild = (c === "isover"); | |
2269 } | |
2270 } | |
2271 | |
2272 // we just moved into a greedy child | |
2273 if (parentInstance && c === "isover") { | |
2274 parentInstance.isover = false; | |
2275 parentInstance.isout = true; | |
2276 parentInstance._out.call(parentInstance, event); | |
2277 } | |
2278 | |
2279 this[c] = true; | |
2280 this[c === "isout" ? "isover" : "isout"] = false; | |
2281 this[c === "isover" ? "_over" : "_out"].call(this, event); | |
2282 | |
2283 // we just moved out of a greedy child | |
2284 if (parentInstance && c === "isout") { | |
2285 parentInstance.isout = false; | |
2286 parentInstance.isover = true; | |
2287 parentInstance._over.call(parentInstance, event); | |
2288 } | |
2289 }); | |
2290 | |
2291 }, | |
2292 dragStop: function( draggable, event ) { | |
2293 draggable.element.parentsUntil( "body" ).unbind( "scroll.droppable" ); | |
2294 //Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003) | |
2295 if( !draggable.options.refreshPositions ) { | |
2296 $.ui.ddmanager.prepareOffsets( draggable, event ); | |
2297 } | |
2298 } | |
2299 }; | |
2300 | |
2301 })(jQuery); | |
2302 | |
2303 (function( $, undefined ) { | |
2304 | |
2305 function num(v) { | |
2306 return parseInt(v, 10) || 0; | |
2307 } | |
2308 | |
2309 function isNumber(value) { | |
2310 return !isNaN(parseInt(value, 10)); | |
2311 } | |
2312 | |
2313 $.widget("ui.resizable", $.ui.mouse, { | |
2314 version: "1.10.4", | |
2315 widgetEventPrefix: "resize", | |
2316 options: { | |
2317 alsoResize: false, | |
2318 animate: false, | |
2319 animateDuration: "slow", | |
2320 animateEasing: "swing", | |
2321 aspectRatio: false, | |
2322 autoHide: false, | |
2323 containment: false, | |
2324 ghost: false, | |
2325 grid: false, | |
2326 handles: "e,s,se", | |
2327 helper: false, | |
2328 maxHeight: null, | |
2329 maxWidth: null, | |
2330 minHeight: 10, | |
2331 minWidth: 10, | |
2332 // See #7960 | |
2333 zIndex: 90, | |
2334 | |
2335 // callbacks | |
2336 resize: null, | |
2337 start: null, | |
2338 stop: null | |
2339 }, | |
2340 _create: function() { | |
2341 | |
2342 var n, i, handle, axis, hname, | |
2343 that = this, | |
2344 o = this.options; | |
2345 this.element.addClass("ui-resizable"); | |
2346 | |
2347 $.extend(this, { | |
2348 _aspectRatio: !!(o.aspectRatio), | |
2349 aspectRatio: o.aspectRatio, | |
2350 originalElement: this.element, | |
2351 _proportionallyResizeElements: [], | |
2352 _helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null | |
2353 }); | |
2354 | |
2355 //Wrap the element if it cannot hold child nodes | |
2356 if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) { | |
2357 | |
2358 //Create a wrapper element and set the wrapper to the new current internal element | |
2359 this.element.wrap( | |
2360 $("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({ | |
2361 position: this.element.css("position"), | |
2362 width: this.element.outerWidth(), | |
2363 height: this.element.outerHeight(), | |
2364 top: this.element.css("top"), | |
2365 left: this.element.css("left") | |
2366 }) | |
2367 ); | |
2368 | |
2369 //Overwrite the original this.element | |
2370 this.element = this.element.parent().data( | |
2371 "ui-resizable", this.element.data("ui-resizable") | |
2372 ); | |
2373 | |
2374 this.elementIsWrapper = true; | |
2375 | |
2376 //Move margins to the wrapper | |
2377 this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") }); | |
2378 this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0}); | |
2379 | |
2380 //Prevent Safari textarea resize | |
2381 this.originalResizeStyle = this.originalElement.css("resize"); | |
2382 this.originalElement.css("resize", "none"); | |
2383 | |
2384 //Push the actual element to our proportionallyResize internal array | |
2385 this._proportionallyResizeElements.push(this.originalElement.css({ position: "static", zoom: 1, display: "block" })); | |
2386 | |
2387 // avoid IE jump (hard set the margin) | |
2388 this.originalElement.css({ margin: this.originalElement.css("margin") }); | |
2389 | |
2390 // fix handlers offset | |
2391 this._proportionallyResize(); | |
2392 | |
2393 } | |
2394 | |
2395 this.handles = o.handles || (!$(".ui-resizable-handle", this.element).length ? "e,s,se" : { n: ".ui-resizable-n", e: ".ui-resizable-e", s: ".ui-resizable-s", w: ".ui-resizable-w", se: ".ui-resizable-se", sw: ".ui-resizable-sw", ne: ".ui-resizable-ne", nw: ".ui-resizable-nw" }); | |
2396 if(this.handles.constructor === String) { | |
2397 | |
2398 if ( this.handles === "all") { | |
2399 this.handles = "n,e,s,w,se,sw,ne,nw"; | |
2400 } | |
2401 | |
2402 n = this.handles.split(","); | |
2403 this.handles = {}; | |
2404 | |
2405 for(i = 0; i < n.length; i++) { | |
2406 | |
2407 handle = $.trim(n[i]); | |
2408 hname = "ui-resizable-"+handle; | |
2409 axis = $("<div class='ui-resizable-handle " + hname + "'></div>"); | |
2410 | |
2411 // Apply zIndex to all handles - see #7960 | |
2412 axis.css({ zIndex: o.zIndex }); | |
2413 | |
2414 //TODO : What's going on here? | |
2415 if ("se" === handle) { | |
2416 axis.addClass("ui-icon ui-icon-gripsmall-diagonal-se"); | |
2417 } | |
2418 | |
2419 //Insert into internal handles object and append to element | |
2420 this.handles[handle] = ".ui-resizable-"+handle; | |
2421 this.element.append(axis); | |
2422 } | |
2423 | |
2424 } | |
2425 | |
2426 this._renderAxis = function(target) { | |
2427 | |
2428 var i, axis, padPos, padWrapper; | |
2429 | |
2430 target = target || this.element; | |
2431 | |
2432 for(i in this.handles) { | |
2433 | |
2434 if(this.handles[i].constructor === String) { | |
2435 this.handles[i] = $(this.handles[i], this.element).show(); | |
2436 } | |
2437 | |
2438 //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls) | |
2439 if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) { | |
2440 | |
2441 axis = $(this.handles[i], this.element); | |
2442 | |
2443 //Checking the correct pad and border | |
2444 padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth(); | |
2445 | |
2446 //The padding type i have to apply... | |
2447 padPos = [ "padding", | |
2448 /ne|nw|n/.test(i) ? "Top" : | |
2449 /se|sw|s/.test(i) ? "Bottom" : | |
2450 /^e$/.test(i) ? "Right" : "Left" ].join(""); | |
2451 | |
2452 target.css(padPos, padWrapper); | |
2453 | |
2454 this._proportionallyResize(); | |
2455 | |
2456 } | |
2457 | |
2458 //TODO: What's that good for? There's not anything to be executed left | |
2459 if(!$(this.handles[i]).length) { | |
2460 continue; | |
2461 } | |
2462 } | |
2463 }; | |
2464 | |
2465 //TODO: make renderAxis a prototype function | |
2466 this._renderAxis(this.element); | |
2467 | |
2468 this._handles = $(".ui-resizable-handle", this.element) | |
2469 .disableSelection(); | |
2470 | |
2471 //Matching axis name | |
2472 this._handles.mouseover(function() { | |
2473 if (!that.resizing) { | |
2474 if (this.className) { | |
2475 axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i); | |
2476 } | |
2477 //Axis, default = se | |
2478 that.axis = axis && axis[1] ? axis[1] : "se"; | |
2479 } | |
2480 }); | |
2481 | |
2482 //If we want to auto hide the elements | |
2483 if (o.autoHide) { | |
2484 this._handles.hide(); | |
2485 $(this.element) | |
2486 .addClass("ui-resizable-autohide") | |
2487 .mouseenter(function() { | |
2488 if (o.disabled) { | |
2489 return; | |
2490 } | |
2491 $(this).removeClass("ui-resizable-autohide"); | |
2492 that._handles.show(); | |
2493 }) | |
2494 .mouseleave(function(){ | |
2495 if (o.disabled) { | |
2496 return; | |
2497 } | |
2498 if (!that.resizing) { | |
2499 $(this).addClass("ui-resizable-autohide"); | |
2500 that._handles.hide(); | |
2501 } | |
2502 }); | |
2503 } | |
2504 | |
2505 //Initialize the mouse interaction | |
2506 this._mouseInit(); | |
2507 | |
2508 }, | |
2509 | |
2510 _destroy: function() { | |
2511 | |
2512 this._mouseDestroy(); | |
2513 | |
2514 var wrapper, | |
2515 _destroy = function(exp) { | |
2516 $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing") | |
2517 .removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove(); | |
2518 }; | |
2519 | |
2520 //TODO: Unwrap at same DOM position | |
2521 if (this.elementIsWrapper) { | |
2522 _destroy(this.element); | |
2523 wrapper = this.element; | |
2524 this.originalElement.css({ | |
2525 position: wrapper.css("position"), | |
2526 width: wrapper.outerWidth(), | |
2527 height: wrapper.outerHeight(), | |
2528 top: wrapper.css("top"), | |
2529 left: wrapper.css("left") | |
2530 }).insertAfter( wrapper ); | |
2531 wrapper.remove(); | |
2532 } | |
2533 | |
2534 this.originalElement.css("resize", this.originalResizeStyle); | |
2535 _destroy(this.originalElement); | |
2536 | |
2537 return this; | |
2538 }, | |
2539 | |
2540 _mouseCapture: function(event) { | |
2541 var i, handle, | |
2542 capture = false; | |
2543 | |
2544 for (i in this.handles) { | |
2545 handle = $(this.handles[i])[0]; | |
2546 if (handle === event.target || $.contains(handle, event.target)) { | |
2547 capture = true; | |
2548 } | |
2549 } | |
2550 | |
2551 return !this.options.disabled && capture; | |
2552 }, | |
2553 | |
2554 _mouseStart: function(event) { | |
2555 | |
2556 var curleft, curtop, cursor, | |
2557 o = this.options, | |
2558 iniPos = this.element.position(), | |
2559 el = this.element; | |
2560 | |
2561 this.resizing = true; | |
2562 | |
2563 // bugfix for http://dev.jquery.com/ticket/1749 | |
2564 if ( (/absolute/).test( el.css("position") ) ) { | |
2565 el.css({ position: "absolute", top: el.css("top"), left: el.css("left") }); | |
2566 } else if (el.is(".ui-draggable")) { | |
2567 el.css({ position: "absolute", top: iniPos.top, left: iniPos.left }); | |
2568 } | |
2569 | |
2570 this._renderProxy(); | |
2571 | |
2572 curleft = num(this.helper.css("left")); | |
2573 curtop = num(this.helper.css("top")); | |
2574 | |
2575 if (o.containment) { | |
2576 curleft += $(o.containment).scrollLeft() || 0; | |
2577 curtop += $(o.containment).scrollTop() || 0; | |
2578 } | |
2579 | |
2580 //Store needed variables | |
2581 this.offset = this.helper.offset(); | |
2582 this.position = { left: curleft, top: curtop }; | |
2583 this.size = this._helper ? { width: this.helper.width(), height: this.helper.height() } : { width: el.width(), height: el.height() }; | |
2584 this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() }; | |
2585 this.originalPosition = { left: curleft, top: curtop }; | |
2586 this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() }; | |
2587 this.originalMousePosition = { left: event.pageX, top: event.pageY }; | |
2588 | |
2589 //Aspect Ratio | |
2590 this.aspectRatio = (typeof o.aspectRatio === "number") ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1); | |
2591 | |
2592 cursor = $(".ui-resizable-" + this.axis).css("cursor"); | |
2593 $("body").css("cursor", cursor === "auto" ? this.axis + "-resize" : cursor); | |
2594 | |
2595 el.addClass("ui-resizable-resizing"); | |
2596 this._propagate("start", event); | |
2597 return true; | |
2598 }, | |
2599 | |
2600 _mouseDrag: function(event) { | |
2601 | |
2602 //Increase performance, avoid regex | |
2603 var data, | |
2604 el = this.helper, props = {}, | |
2605 smp = this.originalMousePosition, | |
2606 a = this.axis, | |
2607 prevTop = this.position.top, | |
2608 prevLeft = this.position.left, | |
2609 prevWidth = this.size.width, | |
2610 prevHeight = this.size.height, | |
2611 dx = (event.pageX-smp.left)||0, | |
2612 dy = (event.pageY-smp.top)||0, | |
2613 trigger = this._change[a]; | |
2614 | |
2615 if (!trigger) { | |
2616 return false; | |
2617 } | |
2618 | |
2619 // Calculate the attrs that will be change | |
2620 data = trigger.apply(this, [event, dx, dy]); | |
2621 | |
2622 // Put this in the mouseDrag handler since the user can start pressing shift while resizing | |
2623 this._updateVirtualBoundaries(event.shiftKey); | |
2624 if (this._aspectRatio || event.shiftKey) { | |
2625 data = this._updateRatio(data, event); | |
2626 } | |
2627 | |
2628 data = this._respectSize(data, event); | |
2629 | |
2630 this._updateCache(data); | |
2631 | |
2632 // plugins callbacks need to be called first | |
2633 this._propagate("resize", event); | |
2634 | |
2635 if (this.position.top !== prevTop) { | |
2636 props.top = this.position.top + "px"; | |
2637 } | |
2638 if (this.position.left !== prevLeft) { | |
2639 props.left = this.position.left + "px"; | |
2640 } | |
2641 if (this.size.width !== prevWidth) { | |
2642 props.width = this.size.width + "px"; | |
2643 } | |
2644 if (this.size.height !== prevHeight) { | |
2645 props.height = this.size.height + "px"; | |
2646 } | |
2647 el.css(props); | |
2648 | |
2649 if (!this._helper && this._proportionallyResizeElements.length) { | |
2650 this._proportionallyResize(); | |
2651 } | |
2652 | |
2653 // Call the user callback if the element was resized | |
2654 if ( ! $.isEmptyObject(props) ) { | |
2655 this._trigger("resize", event, this.ui()); | |
2656 } | |
2657 | |
2658 return false; | |
2659 }, | |
2660 | |
2661 _mouseStop: function(event) { | |
2662 | |
2663 this.resizing = false; | |
2664 var pr, ista, soffseth, soffsetw, s, left, top, | |
2665 o = this.options, that = this; | |
2666 | |
2667 if(this._helper) { | |
2668 | |
2669 pr = this._proportionallyResizeElements; | |
2670 ista = pr.length && (/textarea/i).test(pr[0].nodeName); | |
2671 soffseth = ista && $.ui.hasScroll(pr[0], "left") /* TODO - jump height */ ? 0 : that.sizeDiff.height; | |
2672 soffsetw = ista ? 0 : that.sizeDiff.width; | |
2673 | |
2674 s = { width: (that.helper.width() - soffsetw), height: (that.helper.height() - soffseth) }; | |
2675 left = (parseInt(that.element.css("left"), 10) + (that.position.left - that.originalPosition.left)) || null; | |
2676 top = (parseInt(that.element.css("top"), 10) + (that.position.top - that.originalPosition.top)) || null; | |
2677 | |
2678 if (!o.animate) { | |
2679 this.element.css($.extend(s, { top: top, left: left })); | |
2680 } | |
2681 | |
2682 that.helper.height(that.size.height); | |
2683 that.helper.width(that.size.width); | |
2684 | |
2685 if (this._helper && !o.animate) { | |
2686 this._proportionallyResize(); | |
2687 } | |
2688 } | |
2689 | |
2690 $("body").css("cursor", "auto"); | |
2691 | |
2692 this.element.removeClass("ui-resizable-resizing"); | |
2693 | |
2694 this._propagate("stop", event); | |
2695 | |
2696 if (this._helper) { | |
2697 this.helper.remove(); | |
2698 } | |
2699 | |
2700 return false; | |
2701 | |
2702 }, | |
2703 | |
2704 _updateVirtualBoundaries: function(forceAspectRatio) { | |
2705 var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b, | |
2706 o = this.options; | |
2707 | |
2708 b = { | |
2709 minWidth: isNumber(o.minWidth) ? o.minWidth : 0, | |
2710 maxWidth: isNumber(o.maxWidth) ? o.maxWidth : Infinity, | |
2711 minHeight: isNumber(o.minHeight) ? o.minHeight : 0, | |
2712 maxHeight: isNumber(o.maxHeight) ? o.maxHeight : Infinity | |
2713 }; | |
2714 | |
2715 if(this._aspectRatio || forceAspectRatio) { | |
2716 // We want to create an enclosing box whose aspect ration is the requested one | |
2717 // First, compute the "projected" size for each dimension based on the aspect ratio and other dimension | |
2718 pMinWidth = b.minHeight * this.aspectRatio; | |
2719 pMinHeight = b.minWidth / this.aspectRatio; | |
2720 pMaxWidth = b.maxHeight * this.aspectRatio; | |
2721 pMaxHeight = b.maxWidth / this.aspectRatio; | |
2722 | |
2723 if(pMinWidth > b.minWidth) { | |
2724 b.minWidth = pMinWidth; | |
2725 } | |
2726 if(pMinHeight > b.minHeight) { | |
2727 b.minHeight = pMinHeight; | |
2728 } | |
2729 if(pMaxWidth < b.maxWidth) { | |
2730 b.maxWidth = pMaxWidth; | |
2731 } | |
2732 if(pMaxHeight < b.maxHeight) { | |
2733 b.maxHeight = pMaxHeight; | |
2734 } | |
2735 } | |
2736 this._vBoundaries = b; | |
2737 }, | |
2738 | |
2739 _updateCache: function(data) { | |
2740 this.offset = this.helper.offset(); | |
2741 if (isNumber(data.left)) { | |
2742 this.position.left = data.left; | |
2743 } | |
2744 if (isNumber(data.top)) { | |
2745 this.position.top = data.top; | |
2746 } | |
2747 if (isNumber(data.height)) { | |
2748 this.size.height = data.height; | |
2749 } | |
2750 if (isNumber(data.width)) { | |
2751 this.size.width = data.width; | |
2752 } | |
2753 }, | |
2754 | |
2755 _updateRatio: function( data ) { | |
2756 | |
2757 var cpos = this.position, | |
2758 csize = this.size, | |
2759 a = this.axis; | |
2760 | |
2761 if (isNumber(data.height)) { | |
2762 data.width = (data.height * this.aspectRatio); | |
2763 } else if (isNumber(data.width)) { | |
2764 data.height = (data.width / this.aspectRatio); | |
2765 } | |
2766 | |
2767 if (a === "sw") { | |
2768 data.left = cpos.left + (csize.width - data.width); | |
2769 data.top = null; | |
2770 } | |
2771 if (a === "nw") { | |
2772 data.top = cpos.top + (csize.height - data.height); | |
2773 data.left = cpos.left + (csize.width - data.width); | |
2774 } | |
2775 | |
2776 return data; | |
2777 }, | |
2778 | |
2779 _respectSize: function( data ) { | |
2780 | |
2781 var o = this._vBoundaries, | |
2782 a = this.axis, | |
2783 ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height), | |
2784 isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height), | |
2785 dw = this.originalPosition.left + this.originalSize.width, | |
2786 dh = this.position.top + this.size.height, | |
2787 cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a); | |
2788 if (isminw) { | |
2789 data.width = o.minWidth; | |
2790 } | |
2791 if (isminh) { | |
2792 data.height = o.minHeight; | |
2793 } | |
2794 if (ismaxw) { | |
2795 data.width = o.maxWidth; | |
2796 } | |
2797 if (ismaxh) { | |
2798 data.height = o.maxHeight; | |
2799 } | |
2800 | |
2801 if (isminw && cw) { | |
2802 data.left = dw - o.minWidth; | |
2803 } | |
2804 if (ismaxw && cw) { | |
2805 data.left = dw - o.maxWidth; | |
2806 } | |
2807 if (isminh && ch) { | |
2808 data.top = dh - o.minHeight; | |
2809 } | |
2810 if (ismaxh && ch) { | |
2811 data.top = dh - o.maxHeight; | |
2812 } | |
2813 | |
2814 // fixing jump error on top/left - bug #2330 | |
2815 if (!data.width && !data.height && !data.left && data.top) { | |
2816 data.top = null; | |
2817 } else if (!data.width && !data.height && !data.top && data.left) { | |
2818 data.left = null; | |
2819 } | |
2820 | |
2821 return data; | |
2822 }, | |
2823 | |
2824 _proportionallyResize: function() { | |
2825 | |
2826 if (!this._proportionallyResizeElements.length) { | |
2827 return; | |
2828 } | |
2829 | |
2830 var i, j, borders, paddings, prel, | |
2831 element = this.helper || this.element; | |
2832 | |
2833 for ( i=0; i < this._proportionallyResizeElements.length; i++) { | |
2834 | |
2835 prel = this._proportionallyResizeElements[i]; | |
2836 | |
2837 if (!this.borderDif) { | |
2838 this.borderDif = []; | |
2839 borders = [prel.css("borderTopWidth"), prel.css("borderRightWidth"), prel.css("borderBottomWidth"), prel.css("borderLeftWidth")]; | |
2840 paddings = [prel.css("paddingTop"), prel.css("paddingRight"), prel.css("paddingBottom"), prel.css("paddingLeft")]; | |
2841 | |
2842 for ( j = 0; j < borders.length; j++ ) { | |
2843 this.borderDif[ j ] = ( parseInt( borders[ j ], 10 ) || 0 ) + ( parseInt( paddings[ j ], 10 ) || 0 ); | |
2844 } | |
2845 } | |
2846 | |
2847 prel.css({ | |
2848 height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0, | |
2849 width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0 | |
2850 }); | |
2851 | |
2852 } | |
2853 | |
2854 }, | |
2855 | |
2856 _renderProxy: function() { | |
2857 | |
2858 var el = this.element, o = this.options; | |
2859 this.elementOffset = el.offset(); | |
2860 | |
2861 if(this._helper) { | |
2862 | |
2863 this.helper = this.helper || $("<div style='overflow:hidden;'></div>"); | |
2864 | |
2865 this.helper.addClass(this._helper).css({ | |
2866 width: this.element.outerWidth() - 1, | |
2867 height: this.element.outerHeight() - 1, | |
2868 position: "absolute", | |
2869 left: this.elementOffset.left +"px", | |
2870 top: this.elementOffset.top +"px", | |
2871 zIndex: ++o.zIndex //TODO: Don't modify option | |
2872 }); | |
2873 | |
2874 this.helper | |
2875 .appendTo("body") | |
2876 .disableSelection(); | |
2877 | |
2878 } else { | |
2879 this.helper = this.element; | |
2880 } | |
2881 | |
2882 }, | |
2883 | |
2884 _change: { | |
2885 e: function(event, dx) { | |
2886 return { width: this.originalSize.width + dx }; | |
2887 }, | |
2888 w: function(event, dx) { | |
2889 var cs = this.originalSize, sp = this.originalPosition; | |
2890 return { left: sp.left + dx, width: cs.width - dx }; | |
2891 }, | |
2892 n: function(event, dx, dy) { | |
2893 var cs = this.originalSize, sp = this.originalPosition; | |
2894 return { top: sp.top + dy, height: cs.height - dy }; | |
2895 }, | |
2896 s: function(event, dx, dy) { | |
2897 return { height: this.originalSize.height + dy }; | |
2898 }, | |
2899 se: function(event, dx, dy) { | |
2900 return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy])); | |
2901 }, | |
2902 sw: function(event, dx, dy) { | |
2903 return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy])); | |
2904 }, | |
2905 ne: function(event, dx, dy) { | |
2906 return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy])); | |
2907 }, | |
2908 nw: function(event, dx, dy) { | |
2909 return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy])); | |
2910 } | |
2911 }, | |
2912 | |
2913 _propagate: function(n, event) { | |
2914 $.ui.plugin.call(this, n, [event, this.ui()]); | |
2915 (n !== "resize" && this._trigger(n, event, this.ui())); | |
2916 }, | |
2917 | |
2918 plugins: {}, | |
2919 | |
2920 ui: function() { | |
2921 return { | |
2922 originalElement: this.originalElement, | |
2923 element: this.element, | |
2924 helper: this.helper, | |
2925 position: this.position, | |
2926 size: this.size, | |
2927 originalSize: this.originalSize, | |
2928 originalPosition: this.originalPosition | |
2929 }; | |
2930 } | |
2931 | |
2932 }); | |
2933 | |
2934 /* | |
2935 * Resizable Extensions | |
2936 */ | |
2937 | |
2938 $.ui.plugin.add("resizable", "animate", { | |
2939 | |
2940 stop: function( event ) { | |
2941 var that = $(this).data("ui-resizable"), | |
2942 o = that.options, | |
2943 pr = that._proportionallyResizeElements, | |
2944 ista = pr.length && (/textarea/i).test(pr[0].nodeName), | |
2945 soffseth = ista && $.ui.hasScroll(pr[0], "left") /* TODO - jump height */ ? 0 : that.sizeDiff.height, | |
2946 soffsetw = ista ? 0 : that.sizeDiff.width, | |
2947 style = { width: (that.size.width - soffsetw), height: (that.size.height - soffseth) }, | |
2948 left = (parseInt(that.element.css("left"), 10) + (that.position.left - that.originalPosition.left)) || null, | |
2949 top = (parseInt(that.element.css("top"), 10) + (that.position.top - that.originalPosition.top)) || null; | |
2950 | |
2951 that.element.animate( | |
2952 $.extend(style, top && left ? { top: top, left: left } : {}), { | |
2953 duration: o.animateDuration, | |
2954 easing: o.animateEasing, | |
2955 step: function() { | |
2956 | |
2957 var data = { | |
2958 width: parseInt(that.element.css("width"), 10), | |
2959 height: parseInt(that.element.css("height"), 10), | |
2960 top: parseInt(that.element.css("top"), 10), | |
2961 left: parseInt(that.element.css("left"), 10) | |
2962 }; | |
2963 | |
2964 if (pr && pr.length) { | |
2965 $(pr[0]).css({ width: data.width, height: data.height }); | |
2966 } | |
2967 | |
2968 // propagating resize, and updating values for each animation step | |
2969 that._updateCache(data); | |
2970 that._propagate("resize", event); | |
2971 | |
2972 } | |
2973 } | |
2974 ); | |
2975 } | |
2976 | |
2977 }); | |
2978 | |
2979 $.ui.plugin.add("resizable", "containment", { | |
2980 | |
2981 start: function() { | |
2982 var element, p, co, ch, cw, width, height, | |
2983 that = $(this).data("ui-resizable"), | |
2984 o = that.options, | |
2985 el = that.element, | |
2986 oc = o.containment, | |
2987 ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc; | |
2988 | |
2989 if (!ce) { | |
2990 return; | |
2991 } | |
2992 | |
2993 that.containerElement = $(ce); | |
2994 | |
2995 if (/document/.test(oc) || oc === document) { | |
2996 that.containerOffset = { left: 0, top: 0 }; | |
2997 that.containerPosition = { left: 0, top: 0 }; | |
2998 | |
2999 that.parentData = { | |
3000 element: $(document), left: 0, top: 0, | |
3001 width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight | |
3002 }; | |
3003 } | |
3004 | |
3005 // i'm a node, so compute top, left, right, bottom | |
3006 else { | |
3007 element = $(ce); | |
3008 p = []; | |
3009 $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); }); | |
3010 | |
3011 that.containerOffset = element.offset(); | |
3012 that.containerPosition = element.position(); | |
3013 that.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) }; | |
3014 | |
3015 co = that.containerOffset; | |
3016 ch = that.containerSize.height; | |
3017 cw = that.containerSize.width; | |
3018 width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ); | |
3019 height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch); | |
3020 | |
3021 that.parentData = { | |
3022 element: ce, left: co.left, top: co.top, width: width, height: height | |
3023 }; | |
3024 } | |
3025 }, | |
3026 | |
3027 resize: function( event ) { | |
3028 var woset, hoset, isParent, isOffsetRelative, | |
3029 that = $(this).data("ui-resizable"), | |
3030 o = that.options, | |
3031 co = that.containerOffset, cp = that.position, | |
3032 pRatio = that._aspectRatio || event.shiftKey, | |
3033 cop = { top:0, left:0 }, ce = that.containerElement; | |
3034 | |
3035 if (ce[0] !== document && (/static/).test(ce.css("position"))) { | |
3036 cop = co; | |
3037 } | |
3038 | |
3039 if (cp.left < (that._helper ? co.left : 0)) { | |
3040 that.size.width = that.size.width + (that._helper ? (that.position.left - co.left) : (that.position.left - cop.left)); | |
3041 if (pRatio) { | |
3042 that.size.height = that.size.width / that.aspectRatio; | |
3043 } | |
3044 that.position.left = o.helper ? co.left : 0; | |
3045 } | |
3046 | |
3047 if (cp.top < (that._helper ? co.top : 0)) { | |
3048 that.size.height = that.size.height + (that._helper ? (that.position.top - co.top) : that.position.top); | |
3049 if (pRatio) { | |
3050 that.size.width = that.size.height * that.aspectRatio; | |
3051 } | |
3052 that.position.top = that._helper ? co.top : 0; | |
3053 } | |
3054 | |
3055 that.offset.left = that.parentData.left+that.position.left; | |
3056 that.offset.top = that.parentData.top+that.position.top; | |
3057 | |
3058 woset = Math.abs( (that._helper ? that.offset.left - cop.left : (that.offset.left - cop.left)) + that.sizeDiff.width ); | |
3059 hoset = Math.abs( (that._helper ? that.offset.top - cop.top : (that.offset.top - co.top)) + that.sizeDiff.height ); | |
3060 | |
3061 isParent = that.containerElement.get(0) === that.element.parent().get(0); | |
3062 isOffsetRelative = /relative|absolute/.test(that.containerElement.css("position")); | |
3063 | |
3064 if ( isParent && isOffsetRelative ) { | |
3065 woset -= Math.abs( that.parentData.left ); | |
3066 } | |
3067 | |
3068 if (woset + that.size.width >= that.parentData.width) { | |
3069 that.size.width = that.parentData.width - woset; | |
3070 if (pRatio) { | |
3071 that.size.height = that.size.width / that.aspectRatio; | |
3072 } | |
3073 } | |
3074 | |
3075 if (hoset + that.size.height >= that.parentData.height) { | |
3076 that.size.height = that.parentData.height - hoset; | |
3077 if (pRatio) { | |
3078 that.size.width = that.size.height * that.aspectRatio; | |
3079 } | |
3080 } | |
3081 }, | |
3082 | |
3083 stop: function(){ | |
3084 var that = $(this).data("ui-resizable"), | |
3085 o = that.options, | |
3086 co = that.containerOffset, | |
3087 cop = that.containerPosition, | |
3088 ce = that.containerElement, | |
3089 helper = $(that.helper), | |
3090 ho = helper.offset(), | |
3091 w = helper.outerWidth() - that.sizeDiff.width, | |
3092 h = helper.outerHeight() - that.sizeDiff.height; | |
3093 | |
3094 if (that._helper && !o.animate && (/relative/).test(ce.css("position"))) { | |
3095 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h }); | |
3096 } | |
3097 | |
3098 if (that._helper && !o.animate && (/static/).test(ce.css("position"))) { | |
3099 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h }); | |
3100 } | |
3101 | |
3102 } | |
3103 }); | |
3104 | |
3105 $.ui.plugin.add("resizable", "alsoResize", { | |
3106 | |
3107 start: function () { | |
3108 var that = $(this).data("ui-resizable"), | |
3109 o = that.options, | |
3110 _store = function (exp) { | |
3111 $(exp).each(function() { | |
3112 var el = $(this); | |
3113 el.data("ui-resizable-alsoresize", { | |
3114 width: parseInt(el.width(), 10), height: parseInt(el.height(), 10), | |
3115 left: parseInt(el.css("left"), 10), top: parseInt(el.css("top"), 10) | |
3116 }); | |
3117 }); | |
3118 }; | |
3119 | |
3120 if (typeof(o.alsoResize) === "object" && !o.alsoResize.parentNode) { | |
3121 if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); } | |
3122 else { $.each(o.alsoResize, function (exp) { _store(exp); }); } | |
3123 }else{ | |
3124 _store(o.alsoResize); | |
3125 } | |
3126 }, | |
3127 | |
3128 resize: function (event, ui) { | |
3129 var that = $(this).data("ui-resizable"), | |
3130 o = that.options, | |
3131 os = that.originalSize, | |
3132 op = that.originalPosition, | |
3133 delta = { | |
3134 height: (that.size.height - os.height) || 0, width: (that.size.width - os.width) || 0, | |
3135 top: (that.position.top - op.top) || 0, left: (that.position.left - op.left) || 0 | |
3136 }, | |
3137 | |
3138 _alsoResize = function (exp, c) { | |
3139 $(exp).each(function() { | |
3140 var el = $(this), start = $(this).data("ui-resizable-alsoresize"), style = {}, | |
3141 css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ["width", "height"] : ["width", "height", "top", "left"]; | |
3142 | |
3143 $.each(css, function (i, prop) { | |
3144 var sum = (start[prop]||0) + (delta[prop]||0); | |
3145 if (sum && sum >= 0) { | |
3146 style[prop] = sum || null; | |
3147 } | |
3148 }); | |
3149 | |
3150 el.css(style); | |
3151 }); | |
3152 }; | |
3153 | |
3154 if (typeof(o.alsoResize) === "object" && !o.alsoResize.nodeType) { | |
3155 $.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); }); | |
3156 }else{ | |
3157 _alsoResize(o.alsoResize); | |
3158 } | |
3159 }, | |
3160 | |
3161 stop: function () { | |
3162 $(this).removeData("resizable-alsoresize"); | |
3163 } | |
3164 }); | |
3165 | |
3166 $.ui.plugin.add("resizable", "ghost", { | |
3167 | |
3168 start: function() { | |
3169 | |
3170 var that = $(this).data("ui-resizable"), o = that.options, cs = that.size; | |
3171 | |
3172 that.ghost = that.originalElement.clone(); | |
3173 that.ghost | |
3174 .css({ opacity: 0.25, display: "block", position: "relative", height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 }) | |
3175 .addClass("ui-resizable-ghost") | |
3176 .addClass(typeof o.ghost === "string" ? o.ghost : ""); | |
3177 | |
3178 that.ghost.appendTo(that.helper); | |
3179 | |
3180 }, | |
3181 | |
3182 resize: function(){ | |
3183 var that = $(this).data("ui-resizable"); | |
3184 if (that.ghost) { | |
3185 that.ghost.css({ position: "relative", height: that.size.height, width: that.size.width }); | |
3186 } | |
3187 }, | |
3188 | |
3189 stop: function() { | |
3190 var that = $(this).data("ui-resizable"); | |
3191 if (that.ghost && that.helper) { | |
3192 that.helper.get(0).removeChild(that.ghost.get(0)); | |
3193 } | |
3194 } | |
3195 | |
3196 }); | |
3197 | |
3198 $.ui.plugin.add("resizable", "grid", { | |
3199 | |
3200 resize: function() { | |
3201 var that = $(this).data("ui-resizable"), | |
3202 o = that.options, | |
3203 cs = that.size, | |
3204 os = that.originalSize, | |
3205 op = that.originalPosition, | |
3206 a = that.axis, | |
3207 grid = typeof o.grid === "number" ? [o.grid, o.grid] : o.grid, | |
3208 gridX = (grid[0]||1), | |
3209 gridY = (grid[1]||1), | |
3210 ox = Math.round((cs.width - os.width) / gridX) * gridX, | |
3211 oy = Math.round((cs.height - os.height) / gridY) * gridY, | |
3212 newWidth = os.width + ox, | |
3213 newHeight = os.height + oy, | |
3214 isMaxWidth = o.maxWidth && (o.maxWidth < newWidth), | |
3215 isMaxHeight = o.maxHeight && (o.maxHeight < newHeight), | |
3216 isMinWidth = o.minWidth && (o.minWidth > newWidth), | |
3217 isMinHeight = o.minHeight && (o.minHeight > newHeight); | |
3218 | |
3219 o.grid = grid; | |
3220 | |
3221 if (isMinWidth) { | |
3222 newWidth = newWidth + gridX; | |
3223 } | |
3224 if (isMinHeight) { | |
3225 newHeight = newHeight + gridY; | |
3226 } | |
3227 if (isMaxWidth) { | |
3228 newWidth = newWidth - gridX; | |
3229 } | |
3230 if (isMaxHeight) { | |
3231 newHeight = newHeight - gridY; | |
3232 } | |
3233 | |
3234 if (/^(se|s|e)$/.test(a)) { | |
3235 that.size.width = newWidth; | |
3236 that.size.height = newHeight; | |
3237 } else if (/^(ne)$/.test(a)) { | |
3238 that.size.width = newWidth; | |
3239 that.size.height = newHeight; | |
3240 that.position.top = op.top - oy; | |
3241 } else if (/^(sw)$/.test(a)) { | |
3242 that.size.width = newWidth; | |
3243 that.size.height = newHeight; | |
3244 that.position.left = op.left - ox; | |
3245 } else { | |
3246 if ( newHeight - gridY > 0 ) { | |
3247 that.size.height = newHeight; | |
3248 that.position.top = op.top - oy; | |
3249 } else { | |
3250 that.size.height = gridY; | |
3251 that.position.top = op.top + os.height - gridY; | |
3252 } | |
3253 if ( newWidth - gridX > 0 ) { | |
3254 that.size.width = newWidth; | |
3255 that.position.left = op.left - ox; | |
3256 } else { | |
3257 that.size.width = gridX; | |
3258 that.position.left = op.left + os.width - gridX; | |
3259 } | |
3260 } | |
3261 } | |
3262 | |
3263 }); | |
3264 | |
3265 })(jQuery); | |
3266 | |
3267 (function( $, undefined ) { | |
3268 | |
3269 $.widget("ui.selectable", $.ui.mouse, { | |
3270 version: "1.10.4", | |
3271 options: { | |
3272 appendTo: "body", | |
3273 autoRefresh: true, | |
3274 distance: 0, | |
3275 filter: "*", | |
3276 tolerance: "touch", | |
3277 | |
3278 // callbacks | |
3279 selected: null, | |
3280 selecting: null, | |
3281 start: null, | |
3282 stop: null, | |
3283 unselected: null, | |
3284 unselecting: null | |
3285 }, | |
3286 _create: function() { | |
3287 var selectees, | |
3288 that = this; | |
3289 | |
3290 this.element.addClass("ui-selectable"); | |
3291 | |
3292 this.dragged = false; | |
3293 | |
3294 // cache selectee children based on filter | |
3295 this.refresh = function() { | |
3296 selectees = $(that.options.filter, that.element[0]); | |
3297 selectees.addClass("ui-selectee"); | |
3298 selectees.each(function() { | |
3299 var $this = $(this), | |
3300 pos = $this.offset(); | |
3301 $.data(this, "selectable-item", { | |
3302 element: this, | |
3303 $element: $this, | |
3304 left: pos.left, | |
3305 top: pos.top, | |
3306 right: pos.left + $this.outerWidth(), | |
3307 bottom: pos.top + $this.outerHeight(), | |
3308 startselected: false, | |
3309 selected: $this.hasClass("ui-selected"), | |
3310 selecting: $this.hasClass("ui-selecting"), | |
3311 unselecting: $this.hasClass("ui-unselecting") | |
3312 }); | |
3313 }); | |
3314 }; | |
3315 this.refresh(); | |
3316 | |
3317 this.selectees = selectees.addClass("ui-selectee"); | |
3318 | |
3319 this._mouseInit(); | |
3320 | |
3321 this.helper = $("<div class='ui-selectable-helper'></div>"); | |
3322 }, | |
3323 | |
3324 _destroy: function() { | |
3325 this.selectees | |
3326 .removeClass("ui-selectee") | |
3327 .removeData("selectable-item"); | |
3328 this.element | |
3329 .removeClass("ui-selectable ui-selectable-disabled"); | |
3330 this._mouseDestroy(); | |
3331 }, | |
3332 | |
3333 _mouseStart: function(event) { | |
3334 var that = this, | |
3335 options = this.options; | |
3336 | |
3337 this.opos = [event.pageX, event.pageY]; | |
3338 | |
3339 if (this.options.disabled) { | |
3340 return; | |
3341 } | |
3342 | |
3343 this.selectees = $(options.filter, this.element[0]); | |
3344 | |
3345 this._trigger("start", event); | |
3346 | |
3347 $(options.appendTo).append(this.helper); | |
3348 // position helper (lasso) | |
3349 this.helper.css({ | |
3350 "left": event.pageX, | |
3351 "top": event.pageY, | |
3352 "width": 0, | |
3353 "height": 0 | |
3354 }); | |
3355 | |
3356 if (options.autoRefresh) { | |
3357 this.refresh(); | |
3358 } | |
3359 | |
3360 this.selectees.filter(".ui-selected").each(function() { | |
3361 var selectee = $.data(this, "selectable-item"); | |
3362 selectee.startselected = true; | |
3363 if (!event.metaKey && !event.ctrlKey) { | |
3364 selectee.$element.removeClass("ui-selected"); | |
3365 selectee.selected = false; | |
3366 selectee.$element.addClass("ui-unselecting"); | |
3367 selectee.unselecting = true; | |
3368 // selectable UNSELECTING callback | |
3369 that._trigger("unselecting", event, { | |
3370 unselecting: selectee.element | |
3371 }); | |
3372 } | |
3373 }); | |
3374 | |
3375 $(event.target).parents().addBack().each(function() { | |
3376 var doSelect, | |
3377 selectee = $.data(this, "selectable-item"); | |
3378 if (selectee) { | |
3379 doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass("ui-selected"); | |
3380 selectee.$element | |
3381 .removeClass(doSelect ? "ui-unselecting" : "ui-selected") | |
3382 .addClass(doSelect ? "ui-selecting" : "ui-unselecting"); | |
3383 selectee.unselecting = !doSelect; | |
3384 selectee.selecting = doSelect; | |
3385 selectee.selected = doSelect; | |
3386 // selectable (UN)SELECTING callback | |
3387 if (doSelect) { | |
3388 that._trigger("selecting", event, { | |
3389 selecting: selectee.element | |
3390 }); | |
3391 } else { | |
3392 that._trigger("unselecting", event, { | |
3393 unselecting: selectee.element | |
3394 }); | |
3395 } | |
3396 return false; | |
3397 } | |
3398 }); | |
3399 | |
3400 }, | |
3401 | |
3402 _mouseDrag: function(event) { | |
3403 | |
3404 this.dragged = true; | |
3405 | |
3406 if (this.options.disabled) { | |
3407 return; | |
3408 } | |
3409 | |
3410 var tmp, | |
3411 that = this, | |
3412 options = this.options, | |
3413 x1 = this.opos[0], | |
3414 y1 = this.opos[1], | |
3415 x2 = event.pageX, | |
3416 y2 = event.pageY; | |
3417 | |
3418 if (x1 > x2) { tmp = x2; x2 = x1; x1 = tmp; } | |
3419 if (y1 > y2) { tmp = y2; y2 = y1; y1 = tmp; } | |
3420 this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1}); | |
3421 | |
3422 this.selectees.each(function() { | |
3423 var selectee = $.data(this, "selectable-item"), | |
3424 hit = false; | |
3425 | |
3426 //prevent helper from being selected if appendTo: selectable | |
3427 if (!selectee || selectee.element === that.element[0]) { | |
3428 return; | |
3429 } | |
3430 | |
3431 if (options.tolerance === "touch") { | |
3432 hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) ); | |
3433 } else if (options.tolerance === "fit") { | |
3434 hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2); | |
3435 } | |
3436 | |
3437 if (hit) { | |
3438 // SELECT | |
3439 if (selectee.selected) { | |
3440 selectee.$element.removeClass("ui-selected"); | |
3441 selectee.selected = false; | |
3442 } | |
3443 if (selectee.unselecting) { | |
3444 selectee.$element.removeClass("ui-unselecting"); | |
3445 selectee.unselecting = false; | |
3446 } | |
3447 if (!selectee.selecting) { | |
3448 selectee.$element.addClass("ui-selecting"); | |
3449 selectee.selecting = true; | |
3450 // selectable SELECTING callback | |
3451 that._trigger("selecting", event, { | |
3452 selecting: selectee.element | |
3453 }); | |
3454 } | |
3455 } else { | |
3456 // UNSELECT | |
3457 if (selectee.selecting) { | |
3458 if ((event.metaKey || event.ctrlKey) && selectee.startselected) { | |
3459 selectee.$element.removeClass("ui-selecting"); | |
3460 selectee.selecting = false; | |
3461 selectee.$element.addClass("ui-selected"); | |
3462 selectee.selected = true; | |
3463 } else { | |
3464 selectee.$element.removeClass("ui-selecting"); | |
3465 selectee.selecting = false; | |
3466 if (selectee.startselected) { | |
3467 selectee.$element.addClass("ui-unselecting"); | |
3468 selectee.unselecting = true; | |
3469 } | |
3470 // selectable UNSELECTING callback | |
3471 that._trigger("unselecting", event, { | |
3472 unselecting: selectee.element | |
3473 }); | |
3474 } | |
3475 } | |
3476 if (selectee.selected) { | |
3477 if (!event.metaKey && !event.ctrlKey && !selectee.startselected) { | |
3478 selectee.$element.removeClass("ui-selected"); | |
3479 selectee.selected = false; | |
3480 | |
3481 selectee.$element.addClass("ui-unselecting"); | |
3482 selectee.unselecting = true; | |
3483 // selectable UNSELECTING callback | |
3484 that._trigger("unselecting", event, { | |
3485 unselecting: selectee.element | |
3486 }); | |
3487 } | |
3488 } | |
3489 } | |
3490 }); | |
3491 | |
3492 return false; | |
3493 }, | |
3494 | |
3495 _mouseStop: function(event) { | |
3496 var that = this; | |
3497 | |
3498 this.dragged = false; | |
3499 | |
3500 $(".ui-unselecting", this.element[0]).each(function() { | |
3501 var selectee = $.data(this, "selectable-item"); | |
3502 selectee.$element.removeClass("ui-unselecting"); | |
3503 selectee.unselecting = false; | |
3504 selectee.startselected = false; | |
3505 that._trigger("unselected", event, { | |
3506 unselected: selectee.element | |
3507 }); | |
3508 }); | |
3509 $(".ui-selecting", this.element[0]).each(function() { | |
3510 var selectee = $.data(this, "selectable-item"); | |
3511 selectee.$element.removeClass("ui-selecting").addClass("ui-selected"); | |
3512 selectee.selecting = false; | |
3513 selectee.selected = true; | |
3514 selectee.startselected = true; | |
3515 that._trigger("selected", event, { | |
3516 selected: selectee.element | |
3517 }); | |
3518 }); | |
3519 this._trigger("stop", event); | |
3520 | |
3521 this.helper.remove(); | |
3522 | |
3523 return false; | |
3524 } | |
3525 | |
3526 }); | |
3527 | |
3528 })(jQuery); | |
3529 | |
3530 (function( $, undefined ) { | |
3531 | |
3532 function isOverAxis( x, reference, size ) { | |
3533 return ( x > reference ) && ( x < ( reference + size ) ); | |
3534 } | |
3535 | |
3536 function isFloating(item) { | |
3537 return (/left|right/).test(item.css("float")) || (/inline|table-cell/).test(item.css("display")); | |
3538 } | |
3539 | |
3540 $.widget("ui.sortable", $.ui.mouse, { | |
3541 version: "1.10.4", | |
3542 widgetEventPrefix: "sort", | |
3543 ready: false, | |
3544 options: { | |
3545 appendTo: "parent", | |
3546 axis: false, | |
3547 connectWith: false, | |
3548 containment: false, | |
3549 cursor: "auto", | |
3550 cursorAt: false, | |
3551 dropOnEmpty: true, | |
3552 forcePlaceholderSize: false, | |
3553 forceHelperSize: false, | |
3554 grid: false, | |
3555 handle: false, | |
3556 helper: "original", | |
3557 items: "> *", | |
3558 opacity: false, | |
3559 placeholder: false, | |
3560 revert: false, | |
3561 scroll: true, | |
3562 scrollSensitivity: 20, | |
3563 scrollSpeed: 20, | |
3564 scope: "default", | |
3565 tolerance: "intersect", | |
3566 zIndex: 1000, | |
3567 | |
3568 // callbacks | |
3569 activate: null, | |
3570 beforeStop: null, | |
3571 change: null, | |
3572 deactivate: null, | |
3573 out: null, | |
3574 over: null, | |
3575 receive: null, | |
3576 remove: null, | |
3577 sort: null, | |
3578 start: null, | |
3579 stop: null, | |
3580 update: null | |
3581 }, | |
3582 _create: function() { | |
3583 | |
3584 var o = this.options; | |
3585 this.containerCache = {}; | |
3586 this.element.addClass("ui-sortable"); | |
3587 | |
3588 //Get the items | |
3589 this.refresh(); | |
3590 | |
3591 //Let's determine if the items are being displayed horizontally | |
3592 this.floating = this.items.length ? o.axis === "x" || isFloating(this.items[0].item) : false; | |
3593 | |
3594 //Let's determine the parent's offset | |
3595 this.offset = this.element.offset(); | |
3596 | |
3597 //Initialize mouse events for interaction | |
3598 this._mouseInit(); | |
3599 | |
3600 //We're ready to go | |
3601 this.ready = true; | |
3602 | |
3603 }, | |
3604 | |
3605 _destroy: function() { | |
3606 this.element | |
3607 .removeClass("ui-sortable ui-sortable-disabled"); | |
3608 this._mouseDestroy(); | |
3609 | |
3610 for ( var i = this.items.length - 1; i >= 0; i-- ) { | |
3611 this.items[i].item.removeData(this.widgetName + "-item"); | |
3612 } | |
3613 | |
3614 return this; | |
3615 }, | |
3616 | |
3617 _setOption: function(key, value){ | |
3618 if ( key === "disabled" ) { | |
3619 this.options[ key ] = value; | |
3620 | |
3621 this.widget().toggleClass( "ui-sortable-disabled", !!value ); | |
3622 } else { | |
3623 // Don't call widget base _setOption for disable as it adds ui-state-disabled class | |
3624 $.Widget.prototype._setOption.apply(this, arguments); | |
3625 } | |
3626 }, | |
3627 | |
3628 _mouseCapture: function(event, overrideHandle) { | |
3629 var currentItem = null, | |
3630 validHandle = false, | |
3631 that = this; | |
3632 | |
3633 if (this.reverting) { | |
3634 return false; | |
3635 } | |
3636 | |
3637 if(this.options.disabled || this.options.type === "static") { | |
3638 return false; | |
3639 } | |
3640 | |
3641 //We have to refresh the items data once first | |
3642 this._refreshItems(event); | |
3643 | |
3644 //Find out if the clicked node (or one of its parents) is a actual item in this.items | |
3645 $(event.target).parents().each(function() { | |
3646 if($.data(this, that.widgetName + "-item") === that) { | |
3647 currentItem = $(this); | |
3648 return false; | |
3649 } | |
3650 }); | |
3651 if($.data(event.target, that.widgetName + "-item") === that) { | |
3652 currentItem = $(event.target); | |
3653 } | |
3654 | |
3655 if(!currentItem) { | |
3656 return false; | |
3657 } | |
3658 if(this.options.handle && !overrideHandle) { | |
3659 $(this.options.handle, currentItem).find("*").addBack().each(function() { | |
3660 if(this === event.target) { | |
3661 validHandle = true; | |
3662 } | |
3663 }); | |
3664 if(!validHandle) { | |
3665 return false; | |
3666 } | |
3667 } | |
3668 | |
3669 this.currentItem = currentItem; | |
3670 this._removeCurrentsFromItems(); | |
3671 return true; | |
3672 | |
3673 }, | |
3674 | |
3675 _mouseStart: function(event, overrideHandle, noActivation) { | |
3676 | |
3677 var i, body, | |
3678 o = this.options; | |
3679 | |
3680 this.currentContainer = this; | |
3681 | |
3682 //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture | |
3683 this.refreshPositions(); | |
3684 | |
3685 //Create and append the visible helper | |
3686 this.helper = this._createHelper(event); | |
3687 | |
3688 //Cache the helper size | |
3689 this._cacheHelperProportions(); | |
3690 | |
3691 /* | |
3692 * - Position generation - | |
3693 * This block generates everything position related - it's the core of draggables. | |
3694 */ | |
3695 | |
3696 //Cache the margins of the original element | |
3697 this._cacheMargins(); | |
3698 | |
3699 //Get the next scrolling parent | |
3700 this.scrollParent = this.helper.scrollParent(); | |
3701 | |
3702 //The element's absolute position on the page minus margins | |
3703 this.offset = this.currentItem.offset(); | |
3704 this.offset = { | |
3705 top: this.offset.top - this.margins.top, | |
3706 left: this.offset.left - this.margins.left | |
3707 }; | |
3708 | |
3709 $.extend(this.offset, { | |
3710 click: { //Where the click happened, relative to the element | |
3711 left: event.pageX - this.offset.left, | |
3712 top: event.pageY - this.offset.top | |
3713 }, | |
3714 parent: this._getParentOffset(), | |
3715 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper | |
3716 }); | |
3717 | |
3718 // Only after we got the offset, we can change the helper's position to absolute | |
3719 // TODO: Still need to figure out a way to make relative sorting possible | |
3720 this.helper.css("position", "absolute"); | |
3721 this.cssPosition = this.helper.css("position"); | |
3722 | |
3723 //Generate the original position | |
3724 this.originalPosition = this._generatePosition(event); | |
3725 this.originalPageX = event.pageX; | |
3726 this.originalPageY = event.pageY; | |
3727 | |
3728 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied | |
3729 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)); | |
3730 | |
3731 //Cache the former DOM position | |
3732 this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] }; | |
3733 | |
3734 //If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way | |
3735 if(this.helper[0] !== this.currentItem[0]) { | |
3736 this.currentItem.hide(); | |
3737 } | |
3738 | |
3739 //Create the placeholder | |
3740 this._createPlaceholder(); | |
3741 | |
3742 //Set a containment if given in the options | |
3743 if(o.containment) { | |
3744 this._setContainment(); | |
3745 } | |
3746 | |
3747 if( o.cursor && o.cursor !== "auto" ) { // cursor option | |
3748 body = this.document.find( "body" ); | |
3749 | |
3750 // support: IE | |
3751 this.storedCursor = body.css( "cursor" ); | |
3752 body.css( "cursor", o.cursor ); | |
3753 | |
3754 this.storedStylesheet = $( "<style>*{ cursor: "+o.cursor+" !important; }</style>" ).appendTo( body ); | |
3755 } | |
3756 | |
3757 if(o.opacity) { // opacity option | |
3758 if (this.helper.css("opacity")) { | |
3759 this._storedOpacity = this.helper.css("opacity"); | |
3760 } | |
3761 this.helper.css("opacity", o.opacity); | |
3762 } | |
3763 | |
3764 if(o.zIndex) { // zIndex option | |
3765 if (this.helper.css("zIndex")) { | |
3766 this._storedZIndex = this.helper.css("zIndex"); | |
3767 } | |
3768 this.helper.css("zIndex", o.zIndex); | |
3769 } | |
3770 | |
3771 //Prepare scrolling | |
3772 if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") { | |
3773 this.overflowOffset = this.scrollParent.offset(); | |
3774 } | |
3775 | |
3776 //Call callbacks | |
3777 this._trigger("start", event, this._uiHash()); | |
3778 | |
3779 //Recache the helper size | |
3780 if(!this._preserveHelperProportions) { | |
3781 this._cacheHelperProportions(); | |
3782 } | |
3783 | |
3784 | |
3785 //Post "activate" events to possible containers | |
3786 if( !noActivation ) { | |
3787 for ( i = this.containers.length - 1; i >= 0; i-- ) { | |
3788 this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) ); | |
3789 } | |
3790 } | |
3791 | |
3792 //Prepare possible droppables | |
3793 if($.ui.ddmanager) { | |
3794 $.ui.ddmanager.current = this; | |
3795 } | |
3796 | |
3797 if ($.ui.ddmanager && !o.dropBehaviour) { | |
3798 $.ui.ddmanager.prepareOffsets(this, event); | |
3799 } | |
3800 | |
3801 this.dragging = true; | |
3802 | |
3803 this.helper.addClass("ui-sortable-helper"); | |
3804 this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position | |
3805 return true; | |
3806 | |
3807 }, | |
3808 | |
3809 _mouseDrag: function(event) { | |
3810 var i, item, itemElement, intersection, | |
3811 o = this.options, | |
3812 scrolled = false; | |
3813 | |
3814 //Compute the helpers position | |
3815 this.position = this._generatePosition(event); | |
3816 this.positionAbs = this._convertPositionTo("absolute"); | |
3817 | |
3818 if (!this.lastPositionAbs) { | |
3819 this.lastPositionAbs = this.positionAbs; | |
3820 } | |
3821 | |
3822 //Do scrolling | |
3823 if(this.options.scroll) { | |
3824 if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") { | |
3825 | |
3826 if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) { | |
3827 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed; | |
3828 } else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) { | |
3829 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed; | |
3830 } | |
3831 | |
3832 if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) { | |
3833 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed; | |
3834 } else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) { | |
3835 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed; | |
3836 } | |
3837 | |
3838 } else { | |
3839 | |
3840 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) { | |
3841 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); | |
3842 } else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) { | |
3843 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); | |
3844 } | |
3845 | |
3846 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) { | |
3847 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); | |
3848 } else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) { | |
3849 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); | |
3850 } | |
3851 | |
3852 } | |
3853 | |
3854 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) { | |
3855 $.ui.ddmanager.prepareOffsets(this, event); | |
3856 } | |
3857 } | |
3858 | |
3859 //Regenerate the absolute position used for position checks | |
3860 this.positionAbs = this._convertPositionTo("absolute"); | |
3861 | |
3862 //Set the helper position | |
3863 if(!this.options.axis || this.options.axis !== "y") { | |
3864 this.helper[0].style.left = this.position.left+"px"; | |
3865 } | |
3866 if(!this.options.axis || this.options.axis !== "x") { | |
3867 this.helper[0].style.top = this.position.top+"px"; | |
3868 } | |
3869 | |
3870 //Rearrange | |
3871 for (i = this.items.length - 1; i >= 0; i--) { | |
3872 | |
3873 //Cache variables and intersection, continue if no intersection | |
3874 item = this.items[i]; | |
3875 itemElement = item.item[0]; | |
3876 intersection = this._intersectsWithPointer(item); | |
3877 if (!intersection) { | |
3878 continue; | |
3879 } | |
3880 | |
3881 // Only put the placeholder inside the current Container, skip all | |
3882 // items from other containers. This works because when moving | |
3883 // an item from one container to another the | |
3884 // currentContainer is switched before the placeholder is moved. | |
3885 // | |
3886 // Without this, moving items in "sub-sortables" can cause | |
3887 // the placeholder to jitter beetween the outer and inner container. | |
3888 if (item.instance !== this.currentContainer) { | |
3889 continue; | |
3890 } | |
3891 | |
3892 // cannot intersect with itself | |
3893 // no useless actions that have been done before | |
3894 // no action if the item moved is the parent of the item checked | |
3895 if (itemElement !== this.currentItem[0] && | |
3896 this.placeholder[intersection === 1 ? "next" : "prev"]()[0] !== itemElement && | |
3897 !$.contains(this.placeholder[0], itemElement) && | |
3898 (this.options.type === "semi-dynamic" ? !$.contains(this.element[0], itemElement) : true) | |
3899 ) { | |
3900 | |
3901 this.direction = intersection === 1 ? "down" : "up"; | |
3902 | |
3903 if (this.options.tolerance === "pointer" || this._intersectsWithSides(item)) { | |
3904 this._rearrange(event, item); | |
3905 } else { | |
3906 break; | |
3907 } | |
3908 | |
3909 this._trigger("change", event, this._uiHash()); | |
3910 break; | |
3911 } | |
3912 } | |
3913 | |
3914 //Post events to containers | |
3915 this._contactContainers(event); | |
3916 | |
3917 //Interconnect with droppables | |
3918 if($.ui.ddmanager) { | |
3919 $.ui.ddmanager.drag(this, event); | |
3920 } | |
3921 | |
3922 //Call callbacks | |
3923 this._trigger("sort", event, this._uiHash()); | |
3924 | |
3925 this.lastPositionAbs = this.positionAbs; | |
3926 return false; | |
3927 | |
3928 }, | |
3929 | |
3930 _mouseStop: function(event, noPropagation) { | |
3931 | |
3932 if(!event) { | |
3933 return; | |
3934 } | |
3935 | |
3936 //If we are using droppables, inform the manager about the drop | |
3937 if ($.ui.ddmanager && !this.options.dropBehaviour) { | |
3938 $.ui.ddmanager.drop(this, event); | |
3939 } | |
3940 | |
3941 if(this.options.revert) { | |
3942 var that = this, | |
3943 cur = this.placeholder.offset(), | |
3944 axis = this.options.axis, | |
3945 animation = {}; | |
3946 | |
3947 if ( !axis || axis === "x" ) { | |
3948 animation.left = cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollLeft); | |
3949 } | |
3950 if ( !axis || axis === "y" ) { | |
3951 animation.top = cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollTop); | |
3952 } | |
3953 this.reverting = true; | |
3954 $(this.helper).animate( animation, parseInt(this.options.revert, 10) || 500, function() { | |
3955 that._clear(event); | |
3956 }); | |
3957 } else { | |
3958 this._clear(event, noPropagation); | |
3959 } | |
3960 | |
3961 return false; | |
3962 | |
3963 }, | |
3964 | |
3965 cancel: function() { | |
3966 | |
3967 if(this.dragging) { | |
3968 | |
3969 this._mouseUp({ target: null }); | |
3970 | |
3971 if(this.options.helper === "original") { | |
3972 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); | |
3973 } else { | |
3974 this.currentItem.show(); | |
3975 } | |
3976 | |
3977 //Post deactivating events to containers | |
3978 for (var i = this.containers.length - 1; i >= 0; i--){ | |
3979 this.containers[i]._trigger("deactivate", null, this._uiHash(this)); | |
3980 if(this.containers[i].containerCache.over) { | |
3981 this.containers[i]._trigger("out", null, this._uiHash(this)); | |
3982 this.containers[i].containerCache.over = 0; | |
3983 } | |
3984 } | |
3985 | |
3986 } | |
3987 | |
3988 if (this.placeholder) { | |
3989 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! | |
3990 if(this.placeholder[0].parentNode) { | |
3991 this.placeholder[0].parentNode.removeChild(this.placeholder[0]); | |
3992 } | |
3993 if(this.options.helper !== "original" && this.helper && this.helper[0].parentNode) { | |
3994 this.helper.remove(); | |
3995 } | |
3996 | |
3997 $.extend(this, { | |
3998 helper: null, | |
3999 dragging: false, | |
4000 reverting: false, | |
4001 _noFinalSort: null | |
4002 }); | |
4003 | |
4004 if(this.domPosition.prev) { | |
4005 $(this.domPosition.prev).after(this.currentItem); | |
4006 } else { | |
4007 $(this.domPosition.parent).prepend(this.currentItem); | |
4008 } | |
4009 } | |
4010 | |
4011 return this; | |
4012 | |
4013 }, | |
4014 | |
4015 serialize: function(o) { | |
4016 | |
4017 var items = this._getItemsAsjQuery(o && o.connected), | |
4018 str = []; | |
4019 o = o || {}; | |
4020 | |
4021 $(items).each(function() { | |
4022 var res = ($(o.item || this).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[\-=_](.+)/)); | |
4023 if (res) { | |
4024 str.push((o.key || res[1]+"[]")+"="+(o.key && o.expression ? res[1] : res[2])); | |
4025 } | |
4026 }); | |
4027 | |
4028 if(!str.length && o.key) { | |
4029 str.push(o.key + "="); | |
4030 } | |
4031 | |
4032 return str.join("&"); | |
4033 | |
4034 }, | |
4035 | |
4036 toArray: function(o) { | |
4037 | |
4038 var items = this._getItemsAsjQuery(o && o.connected), | |
4039 ret = []; | |
4040 | |
4041 o = o || {}; | |
4042 | |
4043 items.each(function() { ret.push($(o.item || this).attr(o.attribute || "id") || ""); }); | |
4044 return ret; | |
4045 | |
4046 }, | |
4047 | |
4048 /* Be careful with the following core functions */ | |
4049 _intersectsWith: function(item) { | |
4050 | |
4051 var x1 = this.positionAbs.left, | |
4052 x2 = x1 + this.helperProportions.width, | |
4053 y1 = this.positionAbs.top, | |
4054 y2 = y1 + this.helperProportions.height, | |
4055 l = item.left, | |
4056 r = l + item.width, | |
4057 t = item.top, | |
4058 b = t + item.height, | |
4059 dyClick = this.offset.click.top, | |
4060 dxClick = this.offset.click.left, | |
4061 isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t && ( y1 + dyClick ) < b ), | |
4062 isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l && ( x1 + dxClick ) < r ), | |
4063 isOverElement = isOverElementHeight && isOverElementWidth; | |
4064 | |
4065 if ( this.options.tolerance === "pointer" || | |
4066 this.options.forcePointerForContainers || | |
4067 (this.options.tolerance !== "pointer" && this.helperProportions[this.floating ? "width" : "height"] > item[this.floating ? "width" : "height"]) | |
4068 ) { | |
4069 return isOverElement; | |
4070 } else { | |
4071 | |
4072 return (l < x1 + (this.helperProportions.width / 2) && // Right Half | |
4073 x2 - (this.helperProportions.width / 2) < r && // Left Half | |
4074 t < y1 + (this.helperProportions.height / 2) && // Bottom Half | |
4075 y2 - (this.helperProportions.height / 2) < b ); // Top Half | |
4076 | |
4077 } | |
4078 }, | |
4079 | |
4080 _intersectsWithPointer: function(item) { | |
4081 | |
4082 var isOverElementHeight = (this.options.axis === "x") || isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height), | |
4083 isOverElementWidth = (this.options.axis === "y") || isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width), | |
4084 isOverElement = isOverElementHeight && isOverElementWidth, | |
4085 verticalDirection = this._getDragVerticalDirection(), | |
4086 horizontalDirection = this._getDragHorizontalDirection(); | |
4087 | |
4088 if (!isOverElement) { | |
4089 return false; | |
4090 } | |
4091 | |
4092 return this.floating ? | |
4093 ( ((horizontalDirection && horizontalDirection === "right") || verticalDirection === "down") ? 2 : 1 ) | |
4094 : ( verticalDirection && (verticalDirection === "down" ? 2 : 1) ); | |
4095 | |
4096 }, | |
4097 | |
4098 _intersectsWithSides: function(item) { | |
4099 | |
4100 var isOverBottomHalf = isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height), | |
4101 isOverRightHalf = isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width), | |
4102 verticalDirection = this._getDragVerticalDirection(), | |
4103 horizontalDirection = this._getDragHorizontalDirection(); | |
4104 | |
4105 if (this.floating && horizontalDirection) { | |
4106 return ((horizontalDirection === "right" && isOverRightHalf) || (horizontalDirection === "left" && !isOverRightHalf)); | |
4107 } else { | |
4108 return verticalDirection && ((verticalDirection === "down" && isOverBottomHalf) || (verticalDirection === "up" && !isOverBottomHalf)); | |
4109 } | |
4110 | |
4111 }, | |
4112 | |
4113 _getDragVerticalDirection: function() { | |
4114 var delta = this.positionAbs.top - this.lastPositionAbs.top; | |
4115 return delta !== 0 && (delta > 0 ? "down" : "up"); | |
4116 }, | |
4117 | |
4118 _getDragHorizontalDirection: function() { | |
4119 var delta = this.positionAbs.left - this.lastPositionAbs.left; | |
4120 return delta !== 0 && (delta > 0 ? "right" : "left"); | |
4121 }, | |
4122 | |
4123 refresh: function(event) { | |
4124 this._refreshItems(event); | |
4125 this.refreshPositions(); | |
4126 return this; | |
4127 }, | |
4128 | |
4129 _connectWith: function() { | |
4130 var options = this.options; | |
4131 return options.connectWith.constructor === String ? [options.connectWith] : options.connectWith; | |
4132 }, | |
4133 | |
4134 _getItemsAsjQuery: function(connected) { | |
4135 | |
4136 var i, j, cur, inst, | |
4137 items = [], | |
4138 queries = [], | |
4139 connectWith = this._connectWith(); | |
4140 | |
4141 if(connectWith && connected) { | |
4142 for (i = connectWith.length - 1; i >= 0; i--){ | |
4143 cur = $(connectWith[i]); | |
4144 for ( j = cur.length - 1; j >= 0; j--){ | |
4145 inst = $.data(cur[j], this.widgetFullName); | |
4146 if(inst && inst !== this && !inst.options.disabled) { | |
4147 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), inst]); | |
4148 } | |
4149 } | |
4150 } | |
4151 } | |
4152 | |
4153 queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), this]); | |
4154 | |
4155 function addItems() { | |
4156 items.push( this ); | |
4157 } | |
4158 for (i = queries.length - 1; i >= 0; i--){ | |
4159 queries[i][0].each( addItems ); | |
4160 } | |
4161 | |
4162 return $(items); | |
4163 | |
4164 }, | |
4165 | |
4166 _removeCurrentsFromItems: function() { | |
4167 | |
4168 var list = this.currentItem.find(":data(" + this.widgetName + "-item)"); | |
4169 | |
4170 this.items = $.grep(this.items, function (item) { | |
4171 for (var j=0; j < list.length; j++) { | |
4172 if(list[j] === item.item[0]) { | |
4173 return false; | |
4174 } | |
4175 } | |
4176 return true; | |
4177 }); | |
4178 | |
4179 }, | |
4180 | |
4181 _refreshItems: function(event) { | |
4182 | |
4183 this.items = []; | |
4184 this.containers = [this]; | |
4185 | |
4186 var i, j, cur, inst, targetData, _queries, item, queriesLength, | |
4187 items = this.items, | |
4188 queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]], | |
4189 connectWith = this._connectWith(); | |
4190 | |
4191 if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down | |
4192 for (i = connectWith.length - 1; i >= 0; i--){ | |
4193 cur = $(connectWith[i]); | |
4194 for (j = cur.length - 1; j >= 0; j--){ | |
4195 inst = $.data(cur[j], this.widgetFullName); | |
4196 if(inst && inst !== this && !inst.options.disabled) { | |
4197 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]); | |
4198 this.containers.push(inst); | |
4199 } | |
4200 } | |
4201 } | |
4202 } | |
4203 | |
4204 for (i = queries.length - 1; i >= 0; i--) { | |
4205 targetData = queries[i][1]; | |
4206 _queries = queries[i][0]; | |
4207 | |
4208 for (j=0, queriesLength = _queries.length; j < queriesLength; j++) { | |
4209 item = $(_queries[j]); | |
4210 | |
4211 item.data(this.widgetName + "-item", targetData); // Data for target checking (mouse manager) | |
4212 | |
4213 items.push({ | |
4214 item: item, | |
4215 instance: targetData, | |
4216 width: 0, height: 0, | |
4217 left: 0, top: 0 | |
4218 }); | |
4219 } | |
4220 } | |
4221 | |
4222 }, | |
4223 | |
4224 refreshPositions: function(fast) { | |
4225 | |
4226 //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change | |
4227 if(this.offsetParent && this.helper) { | |
4228 this.offset.parent = this._getParentOffset(); | |
4229 } | |
4230 | |
4231 var i, item, t, p; | |
4232 | |
4233 for (i = this.items.length - 1; i >= 0; i--){ | |
4234 item = this.items[i]; | |
4235 | |
4236 //We ignore calculating positions of all connected containers when we're not over them | |
4237 if(item.instance !== this.currentContainer && this.currentContainer && item.item[0] !== this.currentItem[0]) { | |
4238 continue; | |
4239 } | |
4240 | |
4241 t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item; | |
4242 | |
4243 if (!fast) { | |
4244 item.width = t.outerWidth(); | |
4245 item.height = t.outerHeight(); | |
4246 } | |
4247 | |
4248 p = t.offset(); | |
4249 item.left = p.left; | |
4250 item.top = p.top; | |
4251 } | |
4252 | |
4253 if(this.options.custom && this.options.custom.refreshContainers) { | |
4254 this.options.custom.refreshContainers.call(this); | |
4255 } else { | |
4256 for (i = this.containers.length - 1; i >= 0; i--){ | |
4257 p = this.containers[i].element.offset(); | |
4258 this.containers[i].containerCache.left = p.left; | |
4259 this.containers[i].containerCache.top = p.top; | |
4260 this.containers[i].containerCache.width = this.containers[i].element.outerWidth(); | |
4261 this.containers[i].containerCache.height = this.containers[i].element.outerHeight(); | |
4262 } | |
4263 } | |
4264 | |
4265 return this; | |
4266 }, | |
4267 | |
4268 _createPlaceholder: function(that) { | |
4269 that = that || this; | |
4270 var className, | |
4271 o = that.options; | |
4272 | |
4273 if(!o.placeholder || o.placeholder.constructor === String) { | |
4274 className = o.placeholder; | |
4275 o.placeholder = { | |
4276 element: function() { | |
4277 | |
4278 var nodeName = that.currentItem[0].nodeName.toLowerCase(), | |
4279 element = $( "<" + nodeName + ">", that.document[0] ) | |
4280 .addClass(className || that.currentItem[0].className+" ui-sortable-placeholder") | |
4281 .removeClass("ui-sortable-helper"); | |
4282 | |
4283 if ( nodeName === "tr" ) { | |
4284 that.currentItem.children().each(function() { | |
4285 $( "<td> </td>", that.document[0] ) | |
4286 .attr( "colspan", $( this ).attr( "colspan" ) || 1 ) | |
4287 .appendTo( element ); | |
4288 }); | |
4289 } else if ( nodeName === "img" ) { | |
4290 element.attr( "src", that.currentItem.attr( "src" ) ); | |
4291 } | |
4292 | |
4293 if ( !className ) { | |
4294 element.css( "visibility", "hidden" ); | |
4295 } | |
4296 | |
4297 return element; | |
4298 }, | |
4299 update: function(container, p) { | |
4300 | |
4301 // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that | |
4302 // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified | |
4303 if(className && !o.forcePlaceholderSize) { | |
4304 return; | |
4305 } | |
4306 | |
4307 //If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item | |
4308 if(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css("paddingTop")||0, 10) - parseInt(that.currentItem.css("paddingBottom")||0, 10)); } | |
4309 if(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css("paddingLeft")||0, 10) - parseInt(that.currentItem.css("paddingRight")||0, 10)); } | |
4310 } | |
4311 }; | |
4312 } | |
4313 | |
4314 //Create the placeholder | |
4315 that.placeholder = $(o.placeholder.element.call(that.element, that.currentItem)); | |
4316 | |
4317 //Append it after the actual current item | |
4318 that.currentItem.after(that.placeholder); | |
4319 | |
4320 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317) | |
4321 o.placeholder.update(that, that.placeholder); | |
4322 | |
4323 }, | |
4324 | |
4325 _contactContainers: function(event) { | |
4326 var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, base, cur, nearBottom, floating, | |
4327 innermostContainer = null, | |
4328 innermostIndex = null; | |
4329 | |
4330 // get innermost container that intersects with item | |
4331 for (i = this.containers.length - 1; i >= 0; i--) { | |
4332 | |
4333 // never consider a container that's located within the item itself | |
4334 if($.contains(this.currentItem[0], this.containers[i].element[0])) { | |
4335 continue; | |
4336 } | |
4337 | |
4338 if(this._intersectsWith(this.containers[i].containerCache)) { | |
4339 | |
4340 // if we've already found a container and it's more "inner" than this, then continue | |
4341 if(innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0])) { | |
4342 continue; | |
4343 } | |
4344 | |
4345 innermostContainer = this.containers[i]; | |
4346 innermostIndex = i; | |
4347 | |
4348 } else { | |
4349 // container doesn't intersect. trigger "out" event if necessary | |
4350 if(this.containers[i].containerCache.over) { | |
4351 this.containers[i]._trigger("out", event, this._uiHash(this)); | |
4352 this.containers[i].containerCache.over = 0; | |
4353 } | |
4354 } | |
4355 | |
4356 } | |
4357 | |
4358 // if no intersecting containers found, return | |
4359 if(!innermostContainer) { | |
4360 return; | |
4361 } | |
4362 | |
4363 // move the item into the container if it's not there already | |
4364 if(this.containers.length === 1) { | |
4365 if (!this.containers[innermostIndex].containerCache.over) { | |
4366 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); | |
4367 this.containers[innermostIndex].containerCache.over = 1; | |
4368 } | |
4369 } else { | |
4370 | |
4371 //When entering a new container, we will find the item with the least distance and append our item near it | |
4372 dist = 10000; | |
4373 itemWithLeastDistance = null; | |
4374 floating = innermostContainer.floating || isFloating(this.currentItem); | |
4375 posProperty = floating ? "left" : "top"; | |
4376 sizeProperty = floating ? "width" : "height"; | |
4377 base = this.positionAbs[posProperty] + this.offset.click[posProperty]; | |
4378 for (j = this.items.length - 1; j >= 0; j--) { | |
4379 if(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) { | |
4380 continue; | |
4381 } | |
4382 if(this.items[j].item[0] === this.currentItem[0]) { | |
4383 continue; | |
4384 } | |
4385 if (floating && !isOverAxis(this.positionAbs.top + this.offset.click.top, this.items[j].top, this.items[j].height)) { | |
4386 continue; | |
4387 } | |
4388 cur = this.items[j].item.offset()[posProperty]; | |
4389 nearBottom = false; | |
4390 if(Math.abs(cur - base) > Math.abs(cur + this.items[j][sizeProperty] - base)){ | |
4391 nearBottom = true; | |
4392 cur += this.items[j][sizeProperty]; | |
4393 } | |
4394 | |
4395 if(Math.abs(cur - base) < dist) { | |
4396 dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j]; | |
4397 this.direction = nearBottom ? "up": "down"; | |
4398 } | |
4399 } | |
4400 | |
4401 //Check if dropOnEmpty is enabled | |
4402 if(!itemWithLeastDistance && !this.options.dropOnEmpty) { | |
4403 return; | |
4404 } | |
4405 | |
4406 if(this.currentContainer === this.containers[innermostIndex]) { | |
4407 return; | |
4408 } | |
4409 | |
4410 itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true); | |
4411 this._trigger("change", event, this._uiHash()); | |
4412 this.containers[innermostIndex]._trigger("change", event, this._uiHash(this)); | |
4413 this.currentContainer = this.containers[innermostIndex]; | |
4414 | |
4415 //Update the placeholder | |
4416 this.options.placeholder.update(this.currentContainer, this.placeholder); | |
4417 | |
4418 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); | |
4419 this.containers[innermostIndex].containerCache.over = 1; | |
4420 } | |
4421 | |
4422 | |
4423 }, | |
4424 | |
4425 _createHelper: function(event) { | |
4426 | |
4427 var o = this.options, | |
4428 helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper === "clone" ? this.currentItem.clone() : this.currentItem); | |
4429 | |
4430 //Add the helper to the DOM if that didn't happen already | |
4431 if(!helper.parents("body").length) { | |
4432 $(o.appendTo !== "parent" ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]); | |
4433 } | |
4434 | |
4435 if(helper[0] === this.currentItem[0]) { | |
4436 this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") }; | |
4437 } | |
4438 | |
4439 if(!helper[0].style.width || o.forceHelperSize) { | |
4440 helper.width(this.currentItem.width()); | |
4441 } | |
4442 if(!helper[0].style.height || o.forceHelperSize) { | |
4443 helper.height(this.currentItem.height()); | |
4444 } | |
4445 | |
4446 return helper; | |
4447 | |
4448 }, | |
4449 | |
4450 _adjustOffsetFromHelper: function(obj) { | |
4451 if (typeof obj === "string") { | |
4452 obj = obj.split(" "); | |
4453 } | |
4454 if ($.isArray(obj)) { | |
4455 obj = {left: +obj[0], top: +obj[1] || 0}; | |
4456 } | |
4457 if ("left" in obj) { | |
4458 this.offset.click.left = obj.left + this.margins.left; | |
4459 } | |
4460 if ("right" in obj) { | |
4461 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; | |
4462 } | |
4463 if ("top" in obj) { | |
4464 this.offset.click.top = obj.top + this.margins.top; | |
4465 } | |
4466 if ("bottom" in obj) { | |
4467 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; | |
4468 } | |
4469 }, | |
4470 | |
4471 _getParentOffset: function() { | |
4472 | |
4473 | |
4474 //Get the offsetParent and cache its position | |
4475 this.offsetParent = this.helper.offsetParent(); | |
4476 var po = this.offsetParent.offset(); | |
4477 | |
4478 // This is a special case where we need to modify a offset calculated on start, since the following happened: | |
4479 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent | |
4480 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that | |
4481 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag | |
4482 if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) { | |
4483 po.left += this.scrollParent.scrollLeft(); | |
4484 po.top += this.scrollParent.scrollTop(); | |
4485 } | |
4486 | |
4487 // This needs to be actually done for all browsers, since pageX/pageY includes this information | |
4488 // with an ugly IE fix | |
4489 if( this.offsetParent[0] === document.body || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) { | |
4490 po = { top: 0, left: 0 }; | |
4491 } | |
4492 | |
4493 return { | |
4494 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0), | |
4495 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0) | |
4496 }; | |
4497 | |
4498 }, | |
4499 | |
4500 _getRelativeOffset: function() { | |
4501 | |
4502 if(this.cssPosition === "relative") { | |
4503 var p = this.currentItem.position(); | |
4504 return { | |
4505 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(), | |
4506 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft() | |
4507 }; | |
4508 } else { | |
4509 return { top: 0, left: 0 }; | |
4510 } | |
4511 | |
4512 }, | |
4513 | |
4514 _cacheMargins: function() { | |
4515 this.margins = { | |
4516 left: (parseInt(this.currentItem.css("marginLeft"),10) || 0), | |
4517 top: (parseInt(this.currentItem.css("marginTop"),10) || 0) | |
4518 }; | |
4519 }, | |
4520 | |
4521 _cacheHelperProportions: function() { | |
4522 this.helperProportions = { | |
4523 width: this.helper.outerWidth(), | |
4524 height: this.helper.outerHeight() | |
4525 }; | |
4526 }, | |
4527 | |
4528 _setContainment: function() { | |
4529 | |
4530 var ce, co, over, | |
4531 o = this.options; | |
4532 if(o.containment === "parent") { | |
4533 o.containment = this.helper[0].parentNode; | |
4534 } | |
4535 if(o.containment === "document" || o.containment === "window") { | |
4536 this.containment = [ | |
4537 0 - this.offset.relative.left - this.offset.parent.left, | |
4538 0 - this.offset.relative.top - this.offset.parent.top, | |
4539 $(o.containment === "document" ? document : window).width() - this.helperProportions.width - this.margins.left, | |
4540 ($(o.containment === "document" ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top | |
4541 ]; | |
4542 } | |
4543 | |
4544 if(!(/^(document|window|parent)$/).test(o.containment)) { | |
4545 ce = $(o.containment)[0]; | |
4546 co = $(o.containment).offset(); | |
4547 over = ($(ce).css("overflow") !== "hidden"); | |
4548 | |
4549 this.containment = [ | |
4550 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left, | |
4551 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top, | |
4552 co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left, | |
4553 co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top | |
4554 ]; | |
4555 } | |
4556 | |
4557 }, | |
4558 | |
4559 _convertPositionTo: function(d, pos) { | |
4560 | |
4561 if(!pos) { | |
4562 pos = this.position; | |
4563 } | |
4564 var mod = d === "absolute" ? 1 : -1, | |
4565 scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, | |
4566 scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); | |
4567 | |
4568 return { | |
4569 top: ( | |
4570 pos.top + // The absolute mouse position | |
4571 this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent | |
4572 this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border) | |
4573 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod) | |
4574 ), | |
4575 left: ( | |
4576 pos.left + // The absolute mouse position | |
4577 this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent | |
4578 this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border) | |
4579 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod) | |
4580 ) | |
4581 }; | |
4582 | |
4583 }, | |
4584 | |
4585 _generatePosition: function(event) { | |
4586 | |
4587 var top, left, | |
4588 o = this.options, | |
4589 pageX = event.pageX, | |
4590 pageY = event.pageY, | |
4591 scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); | |
4592 | |
4593 // This is another very weird special case that only happens for relative elements: | |
4594 // 1. If the css position is relative | |
4595 // 2. and the scroll parent is the document or similar to the offset parent | |
4596 // we have to refresh the relative offset during the scroll so there are no jumps | |
4597 if(this.cssPosition === "relative" && !(this.scrollParent[0] !== document && this.scrollParent[0] !== this.offsetParent[0])) { | |
4598 this.offset.relative = this._getRelativeOffset(); | |
4599 } | |
4600 | |
4601 /* | |
4602 * - Position constraining - | |
4603 * Constrain the position to a mix of grid, containment. | |
4604 */ | |
4605 | |
4606 if(this.originalPosition) { //If we are not dragging yet, we won't check for options | |
4607 | |
4608 if(this.containment) { | |
4609 if(event.pageX - this.offset.click.left < this.containment[0]) { | |
4610 pageX = this.containment[0] + this.offset.click.left; | |
4611 } | |
4612 if(event.pageY - this.offset.click.top < this.containment[1]) { | |
4613 pageY = this.containment[1] + this.offset.click.top; | |
4614 } | |
4615 if(event.pageX - this.offset.click.left > this.containment[2]) { | |
4616 pageX = this.containment[2] + this.offset.click.left; | |
4617 } | |
4618 if(event.pageY - this.offset.click.top > this.containment[3]) { | |
4619 pageY = this.containment[3] + this.offset.click.top; | |
4620 } | |
4621 } | |
4622 | |
4623 if(o.grid) { | |
4624 top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1]; | |
4625 pageY = this.containment ? ( (top - this.offset.click.top >= this.containment[1] && top - this.offset.click.top <= this.containment[3]) ? top : ((top - this.offset.click.top >= this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top; | |
4626 | |
4627 left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0]; | |
4628 pageX = this.containment ? ( (left - this.offset.click.left >= this.containment[0] && left - this.offset.click.left <= this.containment[2]) ? left : ((left - this.offset.click.left >= this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left; | |
4629 } | |
4630 | |
4631 } | |
4632 | |
4633 return { | |
4634 top: ( | |
4635 pageY - // The absolute mouse position | |
4636 this.offset.click.top - // Click offset (relative to the element) | |
4637 this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent | |
4638 this.offset.parent.top + // The offsetParent's offset without borders (offset + border) | |
4639 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) )) | |
4640 ), | |
4641 left: ( | |
4642 pageX - // The absolute mouse position | |
4643 this.offset.click.left - // Click offset (relative to the element) | |
4644 this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent | |
4645 this.offset.parent.left + // The offsetParent's offset without borders (offset + border) | |
4646 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() )) | |
4647 ) | |
4648 }; | |
4649 | |
4650 }, | |
4651 | |
4652 _rearrange: function(event, i, a, hardRefresh) { | |
4653 | |
4654 a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction === "down" ? i.item[0] : i.item[0].nextSibling)); | |
4655 | |
4656 //Various things done here to improve the performance: | |
4657 // 1. we create a setTimeout, that calls refreshPositions | |
4658 // 2. on the instance, we have a counter variable, that get's higher after every append | |
4659 // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same | |
4660 // 4. this lets only the last addition to the timeout stack through | |
4661 this.counter = this.counter ? ++this.counter : 1; | |
4662 var counter = this.counter; | |
4663 | |
4664 this._delay(function() { | |
4665 if(counter === this.counter) { | |
4666 this.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove | |
4667 } | |
4668 }); | |
4669 | |
4670 }, | |
4671 | |
4672 _clear: function(event, noPropagation) { | |
4673 | |
4674 this.reverting = false; | |
4675 // We delay all events that have to be triggered to after the point where the placeholder has been removed and | |
4676 // everything else normalized again | |
4677 var i, | |
4678 delayedTriggers = []; | |
4679 | |
4680 // We first have to update the dom position of the actual currentItem | |
4681 // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088) | |
4682 if(!this._noFinalSort && this.currentItem.parent().length) { | |
4683 this.placeholder.before(this.currentItem); | |
4684 } | |
4685 this._noFinalSort = null; | |
4686 | |
4687 if(this.helper[0] === this.currentItem[0]) { | |
4688 for(i in this._storedCSS) { | |
4689 if(this._storedCSS[i] === "auto" || this._storedCSS[i] === "static") { | |
4690 this._storedCSS[i] = ""; | |
4691 } | |
4692 } | |
4693 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); | |
4694 } else { | |
4695 this.currentItem.show(); | |
4696 } | |
4697 | |
4698 if(this.fromOutside && !noPropagation) { | |
4699 delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); }); | |
4700 } | |
4701 if((this.fromOutside || this.domPosition.prev !== this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent !== this.currentItem.parent()[0]) && !noPropagation) { | |
4702 delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed | |
4703 } | |
4704 | |
4705 // Check if the items Container has Changed and trigger appropriate | |
4706 // events. | |
4707 if (this !== this.currentContainer) { | |
4708 if(!noPropagation) { | |
4709 delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); }); | |
4710 delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.currentContainer)); | |
4711 delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.currentContainer)); | |
4712 } | |
4713 } | |
4714 | |
4715 | |
4716 //Post events to containers | |
4717 function delayEvent( type, instance, container ) { | |
4718 return function( event ) { | |
4719 container._trigger( type, event, instance._uiHash( instance ) ); | |
4720 }; | |
4721 } | |
4722 for (i = this.containers.length - 1; i >= 0; i--){ | |
4723 if (!noPropagation) { | |
4724 delayedTriggers.push( delayEvent( "deactivate", this, this.containers[ i ] ) ); | |
4725 } | |
4726 if(this.containers[i].containerCache.over) { | |
4727 delayedTriggers.push( delayEvent( "out", this, this.containers[ i ] ) ); | |
4728 this.containers[i].containerCache.over = 0; | |
4729 } | |
4730 } | |
4731 | |
4732 //Do what was originally in plugins | |
4733 if ( this.storedCursor ) { | |
4734 this.document.find( "body" ).css( "cursor", this.storedCursor ); | |
4735 this.storedStylesheet.remove(); | |
4736 } | |
4737 if(this._storedOpacity) { | |
4738 this.helper.css("opacity", this._storedOpacity); | |
4739 } | |
4740 if(this._storedZIndex) { | |
4741 this.helper.css("zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex); | |
4742 } | |
4743 | |
4744 this.dragging = false; | |
4745 if(this.cancelHelperRemoval) { | |
4746 if(!noPropagation) { | |
4747 this._trigger("beforeStop", event, this._uiHash()); | |
4748 for (i=0; i < delayedTriggers.length; i++) { | |
4749 delayedTriggers[i].call(this, event); | |
4750 } //Trigger all delayed events | |
4751 this._trigger("stop", event, this._uiHash()); | |
4752 } | |
4753 | |
4754 this.fromOutside = false; | |
4755 return false; | |
4756 } | |
4757 | |
4758 if(!noPropagation) { | |
4759 this._trigger("beforeStop", event, this._uiHash()); | |
4760 } | |
4761 | |
4762 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! | |
4763 this.placeholder[0].parentNode.removeChild(this.placeholder[0]); | |
4764 | |
4765 if(this.helper[0] !== this.currentItem[0]) { | |
4766 this.helper.remove(); | |
4767 } | |
4768 this.helper = null; | |
4769 | |
4770 if(!noPropagation) { | |
4771 for (i=0; i < delayedTriggers.length; i++) { | |
4772 delayedTriggers[i].call(this, event); | |
4773 } //Trigger all delayed events | |
4774 this._trigger("stop", event, this._uiHash()); | |
4775 } | |
4776 | |
4777 this.fromOutside = false; | |
4778 return true; | |
4779 | |
4780 }, | |
4781 | |
4782 _trigger: function() { | |
4783 if ($.Widget.prototype._trigger.apply(this, arguments) === false) { | |
4784 this.cancel(); | |
4785 } | |
4786 }, | |
4787 | |
4788 _uiHash: function(_inst) { | |
4789 var inst = _inst || this; | |
4790 return { | |
4791 helper: inst.helper, | |
4792 placeholder: inst.placeholder || $([]), | |
4793 position: inst.position, | |
4794 originalPosition: inst.originalPosition, | |
4795 offset: inst.positionAbs, | |
4796 item: inst.currentItem, | |
4797 sender: _inst ? _inst.element : null | |
4798 }; | |
4799 } | |
4800 | |
4801 }); | |
4802 | |
4803 })(jQuery); | |
4804 | |
4805 (function($, undefined) { | |
4806 | |
4807 var dataSpace = "ui-effects-"; | |
4808 | |
4809 $.effects = { | |
4810 effect: {} | |
4811 }; | |
4812 | |
4813 /*! | |
4814 * jQuery Color Animations v2.1.2 | |
4815 * https://github.com/jquery/jquery-color | |
4816 * | |
4817 * Copyright 2013 jQuery Foundation and other contributors | |
4818 * Released under the MIT license. | |
4819 * http://jquery.org/license | |
4820 * | |
4821 * Date: Wed Jan 16 08:47:09 2013 -0600 | |
4822 */ | |
4823 (function( jQuery, undefined ) { | |
4824 | |
4825 var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor", | |
4826 | |
4827 // plusequals test for += 100 -= 100 | |
4828 rplusequals = /^([\-+])=\s*(\d+\.?\d*)/, | |
4829 // a set of RE's that can match strings and generate color tuples. | |
4830 stringParsers = [{ | |
4831 re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, | |
4832 parse: function( execResult ) { | |
4833 return [ | |
4834 execResult[ 1 ], | |
4835 execResult[ 2 ], | |
4836 execResult[ 3 ], | |
4837 execResult[ 4 ] | |
4838 ]; | |
4839 } | |
4840 }, { | |
4841 re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, | |
4842 parse: function( execResult ) { | |
4843 return [ | |
4844 execResult[ 1 ] * 2.55, | |
4845 execResult[ 2 ] * 2.55, | |
4846 execResult[ 3 ] * 2.55, | |
4847 execResult[ 4 ] | |
4848 ]; | |
4849 } | |
4850 }, { | |
4851 // this regex ignores A-F because it's compared against an already lowercased string | |
4852 re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/, | |
4853 parse: function( execResult ) { | |
4854 return [ | |
4855 parseInt( execResult[ 1 ], 16 ), | |
4856 parseInt( execResult[ 2 ], 16 ), | |
4857 parseInt( execResult[ 3 ], 16 ) | |
4858 ]; | |
4859 } | |
4860 }, { | |
4861 // this regex ignores A-F because it's compared against an already lowercased string | |
4862 re: /#([a-f0-9])([a-f0-9])([a-f0-9])/, | |
4863 parse: function( execResult ) { | |
4864 return [ | |
4865 parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ), | |
4866 parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ), | |
4867 parseInt( execResult[ 3 ] + execResult[ 3 ], 16 ) | |
4868 ]; | |
4869 } | |
4870 }, { | |
4871 re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, | |
4872 space: "hsla", | |
4873 parse: function( execResult ) { | |
4874 return [ | |
4875 execResult[ 1 ], | |
4876 execResult[ 2 ] / 100, | |
4877 execResult[ 3 ] / 100, | |
4878 execResult[ 4 ] | |
4879 ]; | |
4880 } | |
4881 }], | |
4882 | |
4883 // jQuery.Color( ) | |
4884 color = jQuery.Color = function( color, green, blue, alpha ) { | |
4885 return new jQuery.Color.fn.parse( color, green, blue, alpha ); | |
4886 }, | |
4887 spaces = { | |
4888 rgba: { | |
4889 props: { | |
4890 red: { | |
4891 idx: 0, | |
4892 type: "byte" | |
4893 }, | |
4894 green: { | |
4895 idx: 1, | |
4896 type: "byte" | |
4897 }, | |
4898 blue: { | |
4899 idx: 2, | |
4900 type: "byte" | |
4901 } | |
4902 } | |
4903 }, | |
4904 | |
4905 hsla: { | |
4906 props: { | |
4907 hue: { | |
4908 idx: 0, | |
4909 type: "degrees" | |
4910 }, | |
4911 saturation: { | |
4912 idx: 1, | |
4913 type: "percent" | |
4914 }, | |
4915 lightness: { | |
4916 idx: 2, | |
4917 type: "percent" | |
4918 } | |
4919 } | |
4920 } | |
4921 }, | |
4922 propTypes = { | |
4923 "byte": { | |
4924 floor: true, | |
4925 max: 255 | |
4926 }, | |
4927 "percent": { | |
4928 max: 1 | |
4929 }, | |
4930 "degrees": { | |
4931 mod: 360, | |
4932 floor: true | |
4933 } | |
4934 }, | |
4935 support = color.support = {}, | |
4936 | |
4937 // element for support tests | |
4938 supportElem = jQuery( "<p>" )[ 0 ], | |
4939 | |
4940 // colors = jQuery.Color.names | |
4941 colors, | |
4942 | |
4943 // local aliases of functions called often | |
4944 each = jQuery.each; | |
4945 | |
4946 // determine rgba support immediately | |
4947 supportElem.style.cssText = "background-color:rgba(1,1,1,.5)"; | |
4948 support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1; | |
4949 | |
4950 // define cache name and alpha properties | |
4951 // for rgba and hsla spaces | |
4952 each( spaces, function( spaceName, space ) { | |
4953 space.cache = "_" + spaceName; | |
4954 space.props.alpha = { | |
4955 idx: 3, | |
4956 type: "percent", | |
4957 def: 1 | |
4958 }; | |
4959 }); | |
4960 | |
4961 function clamp( value, prop, allowEmpty ) { | |
4962 var type = propTypes[ prop.type ] || {}; | |
4963 | |
4964 if ( value == null ) { | |
4965 return (allowEmpty || !prop.def) ? null : prop.def; | |
4966 } | |
4967 | |
4968 // ~~ is an short way of doing floor for positive numbers | |
4969 value = type.floor ? ~~value : parseFloat( value ); | |
4970 | |
4971 // IE will pass in empty strings as value for alpha, | |
4972 // which will hit this case | |
4973 if ( isNaN( value ) ) { | |
4974 return prop.def; | |
4975 } | |
4976 | |
4977 if ( type.mod ) { | |
4978 // we add mod before modding to make sure that negatives values | |
4979 // get converted properly: -10 -> 350 | |
4980 return (value + type.mod) % type.mod; | |
4981 } | |
4982 | |
4983 // for now all property types without mod have min and max | |
4984 return 0 > value ? 0 : type.max < value ? type.max : value; | |
4985 } | |
4986 | |
4987 function stringParse( string ) { | |
4988 var inst = color(), | |
4989 rgba = inst._rgba = []; | |
4990 | |
4991 string = string.toLowerCase(); | |
4992 | |
4993 each( stringParsers, function( i, parser ) { | |
4994 var parsed, | |
4995 match = parser.re.exec( string ), | |
4996 values = match && parser.parse( match ), | |
4997 spaceName = parser.space || "rgba"; | |
4998 | |
4999 if ( values ) { | |
5000 parsed = inst[ spaceName ]( values ); | |
5001 | |
5002 // if this was an rgba parse the assignment might happen twice | |
5003 // oh well.... | |
5004 inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ]; | |
5005 rgba = inst._rgba = parsed._rgba; | |
5006 | |
5007 // exit each( stringParsers ) here because we matched | |
5008 return false; | |
5009 } | |
5010 }); | |
5011 | |
5012 // Found a stringParser that handled it | |
5013 if ( rgba.length ) { | |
5014 | |
5015 // if this came from a parsed string, force "transparent" when alpha is 0 | |
5016 // chrome, (and maybe others) return "transparent" as rgba(0,0,0,0) | |
5017 if ( rgba.join() === "0,0,0,0" ) { | |
5018 jQuery.extend( rgba, colors.transparent ); | |
5019 } | |
5020 return inst; | |
5021 } | |
5022 | |
5023 // named colors | |
5024 return colors[ string ]; | |
5025 } | |
5026 | |
5027 color.fn = jQuery.extend( color.prototype, { | |
5028 parse: function( red, green, blue, alpha ) { | |
5029 if ( red === undefined ) { | |
5030 this._rgba = [ null, null, null, null ]; | |
5031 return this; | |
5032 } | |
5033 if ( red.jquery || red.nodeType ) { | |
5034 red = jQuery( red ).css( green ); | |
5035 green = undefined; | |
5036 } | |
5037 | |
5038 var inst = this, | |
5039 type = jQuery.type( red ), | |
5040 rgba = this._rgba = []; | |
5041 | |
5042 // more than 1 argument specified - assume ( red, green, blue, alpha ) | |
5043 if ( green !== undefined ) { | |
5044 red = [ red, green, blue, alpha ]; | |
5045 type = "array"; | |
5046 } | |
5047 | |
5048 if ( type === "string" ) { | |
5049 return this.parse( stringParse( red ) || colors._default ); | |
5050 } | |
5051 | |
5052 if ( type === "array" ) { | |
5053 each( spaces.rgba.props, function( key, prop ) { | |
5054 rgba[ prop.idx ] = clamp( red[ prop.idx ], prop ); | |
5055 }); | |
5056 return this; | |
5057 } | |
5058 | |
5059 if ( type === "object" ) { | |
5060 if ( red instanceof color ) { | |
5061 each( spaces, function( spaceName, space ) { | |
5062 if ( red[ space.cache ] ) { | |
5063 inst[ space.cache ] = red[ space.cache ].slice(); | |
5064 } | |
5065 }); | |
5066 } else { | |
5067 each( spaces, function( spaceName, space ) { | |
5068 var cache = space.cache; | |
5069 each( space.props, function( key, prop ) { | |
5070 | |
5071 // if the cache doesn't exist, and we know how to convert | |
5072 if ( !inst[ cache ] && space.to ) { | |
5073 | |
5074 // if the value was null, we don't need to copy it | |
5075 // if the key was alpha, we don't need to copy it either | |
5076 if ( key === "alpha" || red[ key ] == null ) { | |
5077 return; | |
5078 } | |
5079 inst[ cache ] = space.to( inst._rgba ); | |
5080 } | |
5081 | |
5082 // this is the only case where we allow nulls for ALL properties. | |
5083 // call clamp with alwaysAllowEmpty | |
5084 inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true ); | |
5085 }); | |
5086 | |
5087 // everything defined but alpha? | |
5088 if ( inst[ cache ] && jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) { | |
5089 // use the default of 1 | |
5090 inst[ cache ][ 3 ] = 1; | |
5091 if ( space.from ) { | |
5092 inst._rgba = space.from( inst[ cache ] ); | |
5093 } | |
5094 } | |
5095 }); | |
5096 } | |
5097 return this; | |
5098 } | |
5099 }, | |
5100 is: function( compare ) { | |
5101 var is = color( compare ), | |
5102 same = true, | |
5103 inst = this; | |
5104 | |
5105 each( spaces, function( _, space ) { | |
5106 var localCache, | |
5107 isCache = is[ space.cache ]; | |
5108 if (isCache) { | |
5109 localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || []; | |
5110 each( space.props, function( _, prop ) { | |
5111 if ( isCache[ prop.idx ] != null ) { | |
5112 same = ( isCache[ prop.idx ] === localCache[ prop.idx ] ); | |
5113 return same; | |
5114 } | |
5115 }); | |
5116 } | |
5117 return same; | |
5118 }); | |
5119 return same; | |
5120 }, | |
5121 _space: function() { | |
5122 var used = [], | |
5123 inst = this; | |
5124 each( spaces, function( spaceName, space ) { | |
5125 if ( inst[ space.cache ] ) { | |
5126 used.push( spaceName ); | |
5127 } | |
5128 }); | |
5129 return used.pop(); | |
5130 }, | |
5131 transition: function( other, distance ) { | |
5132 var end = color( other ), | |
5133 spaceName = end._space(), | |
5134 space = spaces[ spaceName ], | |
5135 startColor = this.alpha() === 0 ? color( "transparent" ) : this, | |
5136 start = startColor[ space.cache ] || space.to( startColor._rgba ), | |
5137 result = start.slice(); | |
5138 | |
5139 end = end[ space.cache ]; | |
5140 each( space.props, function( key, prop ) { | |
5141 var index = prop.idx, | |
5142 startValue = start[ index ], | |
5143 endValue = end[ index ], | |
5144 type = propTypes[ prop.type ] || {}; | |
5145 | |
5146 // if null, don't override start value | |
5147 if ( endValue === null ) { | |
5148 return; | |
5149 } | |
5150 // if null - use end | |
5151 if ( startValue === null ) { | |
5152 result[ index ] = endValue; | |
5153 } else { | |
5154 if ( type.mod ) { | |
5155 if ( endValue - startValue > type.mod / 2 ) { | |
5156 startValue += type.mod; | |
5157 } else if ( startValue - endValue > type.mod / 2 ) { | |
5158 startValue -= type.mod; | |
5159 } | |
5160 } | |
5161 result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop ); | |
5162 } | |
5163 }); | |
5164 return this[ spaceName ]( result ); | |
5165 }, | |
5166 blend: function( opaque ) { | |
5167 // if we are already opaque - return ourself | |
5168 if ( this._rgba[ 3 ] === 1 ) { | |
5169 return this; | |
5170 } | |
5171 | |
5172 var rgb = this._rgba.slice(), | |
5173 a = rgb.pop(), | |
5174 blend = color( opaque )._rgba; | |
5175 | |
5176 return color( jQuery.map( rgb, function( v, i ) { | |
5177 return ( 1 - a ) * blend[ i ] + a * v; | |
5178 })); | |
5179 }, | |
5180 toRgbaString: function() { | |
5181 var prefix = "rgba(", | |
5182 rgba = jQuery.map( this._rgba, function( v, i ) { | |
5183 return v == null ? ( i > 2 ? 1 : 0 ) : v; | |
5184 }); | |
5185 | |
5186 if ( rgba[ 3 ] === 1 ) { | |
5187 rgba.pop(); | |
5188 prefix = "rgb("; | |
5189 } | |
5190 | |
5191 return prefix + rgba.join() + ")"; | |
5192 }, | |
5193 toHslaString: function() { | |
5194 var prefix = "hsla(", | |
5195 hsla = jQuery.map( this.hsla(), function( v, i ) { | |
5196 if ( v == null ) { | |
5197 v = i > 2 ? 1 : 0; | |
5198 } | |
5199 | |
5200 // catch 1 and 2 | |
5201 if ( i && i < 3 ) { | |
5202 v = Math.round( v * 100 ) + "%"; | |
5203 } | |
5204 return v; | |
5205 }); | |
5206 | |
5207 if ( hsla[ 3 ] === 1 ) { | |
5208 hsla.pop(); | |
5209 prefix = "hsl("; | |
5210 } | |
5211 return prefix + hsla.join() + ")"; | |
5212 }, | |
5213 toHexString: function( includeAlpha ) { | |
5214 var rgba = this._rgba.slice(), | |
5215 alpha = rgba.pop(); | |
5216 | |
5217 if ( includeAlpha ) { | |
5218 rgba.push( ~~( alpha * 255 ) ); | |
5219 } | |
5220 | |
5221 return "#" + jQuery.map( rgba, function( v ) { | |
5222 | |
5223 // default to 0 when nulls exist | |
5224 v = ( v || 0 ).toString( 16 ); | |
5225 return v.length === 1 ? "0" + v : v; | |
5226 }).join(""); | |
5227 }, | |
5228 toString: function() { | |
5229 return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString(); | |
5230 } | |
5231 }); | |
5232 color.fn.parse.prototype = color.fn; | |
5233 | |
5234 // hsla conversions adapted from: | |
5235 // https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021 | |
5236 | |
5237 function hue2rgb( p, q, h ) { | |
5238 h = ( h + 1 ) % 1; | |
5239 if ( h * 6 < 1 ) { | |
5240 return p + (q - p) * h * 6; | |
5241 } | |
5242 if ( h * 2 < 1) { | |
5243 return q; | |
5244 } | |
5245 if ( h * 3 < 2 ) { | |
5246 return p + (q - p) * ((2/3) - h) * 6; | |
5247 } | |
5248 return p; | |
5249 } | |
5250 | |
5251 spaces.hsla.to = function ( rgba ) { | |
5252 if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) { | |
5253 return [ null, null, null, rgba[ 3 ] ]; | |
5254 } | |
5255 var r = rgba[ 0 ] / 255, | |
5256 g = rgba[ 1 ] / 255, | |
5257 b = rgba[ 2 ] / 255, | |
5258 a = rgba[ 3 ], | |
5259 max = Math.max( r, g, b ), | |
5260 min = Math.min( r, g, b ), | |
5261 diff = max - min, | |
5262 add = max + min, | |
5263 l = add * 0.5, | |
5264 h, s; | |
5265 | |
5266 if ( min === max ) { | |
5267 h = 0; | |
5268 } else if ( r === max ) { | |
5269 h = ( 60 * ( g - b ) / diff ) + 360; | |
5270 } else if ( g === max ) { | |
5271 h = ( 60 * ( b - r ) / diff ) + 120; | |
5272 } else { | |
5273 h = ( 60 * ( r - g ) / diff ) + 240; | |
5274 } | |
5275 | |
5276 // chroma (diff) == 0 means greyscale which, by definition, saturation = 0% | |
5277 // otherwise, saturation is based on the ratio of chroma (diff) to lightness (add) | |
5278 if ( diff === 0 ) { | |
5279 s = 0; | |
5280 } else if ( l <= 0.5 ) { | |
5281 s = diff / add; | |
5282 } else { | |
5283 s = diff / ( 2 - add ); | |
5284 } | |
5285 return [ Math.round(h) % 360, s, l, a == null ? 1 : a ]; | |
5286 }; | |
5287 | |
5288 spaces.hsla.from = function ( hsla ) { | |
5289 if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) { | |
5290 return [ null, null, null, hsla[ 3 ] ]; | |
5291 } | |
5292 var h = hsla[ 0 ] / 360, | |
5293 s = hsla[ 1 ], | |
5294 l = hsla[ 2 ], | |
5295 a = hsla[ 3 ], | |
5296 q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s, | |
5297 p = 2 * l - q; | |
5298 | |
5299 return [ | |
5300 Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ), | |
5301 Math.round( hue2rgb( p, q, h ) * 255 ), | |
5302 Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ), | |
5303 a | |
5304 ]; | |
5305 }; | |
5306 | |
5307 | |
5308 each( spaces, function( spaceName, space ) { | |
5309 var props = space.props, | |
5310 cache = space.cache, | |
5311 to = space.to, | |
5312 from = space.from; | |
5313 | |
5314 // makes rgba() and hsla() | |
5315 color.fn[ spaceName ] = function( value ) { | |
5316 | |
5317 // generate a cache for this space if it doesn't exist | |
5318 if ( to && !this[ cache ] ) { | |
5319 this[ cache ] = to( this._rgba ); | |
5320 } | |
5321 if ( value === undefined ) { | |
5322 return this[ cache ].slice(); | |
5323 } | |
5324 | |
5325 var ret, | |
5326 type = jQuery.type( value ), | |
5327 arr = ( type === "array" || type === "object" ) ? value : arguments, | |
5328 local = this[ cache ].slice(); | |
5329 | |
5330 each( props, function( key, prop ) { | |
5331 var val = arr[ type === "object" ? key : prop.idx ]; | |
5332 if ( val == null ) { | |
5333 val = local[ prop.idx ]; | |
5334 } | |
5335 local[ prop.idx ] = clamp( val, prop ); | |
5336 }); | |
5337 | |
5338 if ( from ) { | |
5339 ret = color( from( local ) ); | |
5340 ret[ cache ] = local; | |
5341 return ret; | |
5342 } else { | |
5343 return color( local ); | |
5344 } | |
5345 }; | |
5346 | |
5347 // makes red() green() blue() alpha() hue() saturation() lightness() | |
5348 each( props, function( key, prop ) { | |
5349 // alpha is included in more than one space | |
5350 if ( color.fn[ key ] ) { | |
5351 return; | |
5352 } | |
5353 color.fn[ key ] = function( value ) { | |
5354 var vtype = jQuery.type( value ), | |
5355 fn = ( key === "alpha" ? ( this._hsla ? "hsla" : "rgba" ) : spaceName ), | |
5356 local = this[ fn ](), | |
5357 cur = local[ prop.idx ], | |
5358 match; | |
5359 | |
5360 if ( vtype === "undefined" ) { | |
5361 return cur; | |
5362 } | |
5363 | |
5364 if ( vtype === "function" ) { | |
5365 value = value.call( this, cur ); | |
5366 vtype = jQuery.type( value ); | |
5367 } | |
5368 if ( value == null && prop.empty ) { | |
5369 return this; | |
5370 } | |
5371 if ( vtype === "string" ) { | |
5372 match = rplusequals.exec( value ); | |
5373 if ( match ) { | |
5374 value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 ); | |
5375 } | |
5376 } | |
5377 local[ prop.idx ] = value; | |
5378 return this[ fn ]( local ); | |
5379 }; | |
5380 }); | |
5381 }); | |
5382 | |
5383 // add cssHook and .fx.step function for each named hook. | |
5384 // accept a space separated string of properties | |
5385 color.hook = function( hook ) { | |
5386 var hooks = hook.split( " " ); | |
5387 each( hooks, function( i, hook ) { | |
5388 jQuery.cssHooks[ hook ] = { | |
5389 set: function( elem, value ) { | |
5390 var parsed, curElem, | |
5391 backgroundColor = ""; | |
5392 | |
5393 if ( value !== "transparent" && ( jQuery.type( value ) !== "string" || ( parsed = stringParse( value ) ) ) ) { | |
5394 value = color( parsed || value ); | |
5395 if ( !support.rgba && value._rgba[ 3 ] !== 1 ) { | |
5396 curElem = hook === "backgroundColor" ? elem.parentNode : elem; | |
5397 while ( | |
5398 (backgroundColor === "" || backgroundColor === "transparent") && | |
5399 curElem && curElem.style | |
5400 ) { | |
5401 try { | |
5402 backgroundColor = jQuery.css( curElem, "backgroundColor" ); | |
5403 curElem = curElem.parentNode; | |
5404 } catch ( e ) { | |
5405 } | |
5406 } | |
5407 | |
5408 value = value.blend( backgroundColor && backgroundColor !== "transparent" ? | |
5409 backgroundColor : | |
5410 "_default" ); | |
5411 } | |
5412 | |
5413 value = value.toRgbaString(); | |
5414 } | |
5415 try { | |
5416 elem.style[ hook ] = value; | |
5417 } catch( e ) { | |
5418 // wrapped to prevent IE from throwing errors on "invalid" values like 'auto' or 'inherit' | |
5419 } | |
5420 } | |
5421 }; | |
5422 jQuery.fx.step[ hook ] = function( fx ) { | |
5423 if ( !fx.colorInit ) { | |
5424 fx.start = color( fx.elem, hook ); | |
5425 fx.end = color( fx.end ); | |
5426 fx.colorInit = true; | |
5427 } | |
5428 jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) ); | |
5429 }; | |
5430 }); | |
5431 | |
5432 }; | |
5433 | |
5434 color.hook( stepHooks ); | |
5435 | |
5436 jQuery.cssHooks.borderColor = { | |
5437 expand: function( value ) { | |
5438 var expanded = {}; | |
5439 | |
5440 each( [ "Top", "Right", "Bottom", "Left" ], function( i, part ) { | |
5441 expanded[ "border" + part + "Color" ] = value; | |
5442 }); | |
5443 return expanded; | |
5444 } | |
5445 }; | |
5446 | |
5447 // Basic color names only. | |
5448 // Usage of any of the other color names requires adding yourself or including | |
5449 // jquery.color.svg-names.js. | |
5450 colors = jQuery.Color.names = { | |
5451 // 4.1. Basic color keywords | |
5452 aqua: "#00ffff", | |
5453 black: "#000000", | |
5454 blue: "#0000ff", | |
5455 fuchsia: "#ff00ff", | |
5456 gray: "#808080", | |
5457 green: "#008000", | |
5458 lime: "#00ff00", | |
5459 maroon: "#800000", | |
5460 navy: "#000080", | |
5461 olive: "#808000", | |
5462 purple: "#800080", | |
5463 red: "#ff0000", | |
5464 silver: "#c0c0c0", | |
5465 teal: "#008080", | |
5466 white: "#ffffff", | |
5467 yellow: "#ffff00", | |
5468 | |
5469 // 4.2.3. "transparent" color keyword | |
5470 transparent: [ null, null, null, 0 ], | |
5471 | |
5472 _default: "#ffffff" | |
5473 }; | |
5474 | |
5475 })( jQuery ); | |
5476 | |
5477 | |
5478 /******************************************************************************/ | |
5479 /****************************** CLASS ANIMATIONS ******************************/ | |
5480 /******************************************************************************/ | |
5481 (function() { | |
5482 | |
5483 var classAnimationActions = [ "add", "remove", "toggle" ], | |
5484 shorthandStyles = { | |
5485 border: 1, | |
5486 borderBottom: 1, | |
5487 borderColor: 1, | |
5488 borderLeft: 1, | |
5489 borderRight: 1, | |
5490 borderTop: 1, | |
5491 borderWidth: 1, | |
5492 margin: 1, | |
5493 padding: 1 | |
5494 }; | |
5495 | |
5496 $.each([ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], function( _, prop ) { | |
5497 $.fx.step[ prop ] = function( fx ) { | |
5498 if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) { | |
5499 jQuery.style( fx.elem, prop, fx.end ); | |
5500 fx.setAttr = true; | |
5501 } | |
5502 }; | |
5503 }); | |
5504 | |
5505 function getElementStyles( elem ) { | |
5506 var key, len, | |
5507 style = elem.ownerDocument.defaultView ? | |
5508 elem.ownerDocument.defaultView.getComputedStyle( elem, null ) : | |
5509 elem.currentStyle, | |
5510 styles = {}; | |
5511 | |
5512 if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) { | |
5513 len = style.length; | |
5514 while ( len-- ) { | |
5515 key = style[ len ]; | |
5516 if ( typeof style[ key ] === "string" ) { | |
5517 styles[ $.camelCase( key ) ] = style[ key ]; | |
5518 } | |
5519 } | |
5520 // support: Opera, IE <9 | |
5521 } else { | |
5522 for ( key in style ) { | |
5523 if ( typeof style[ key ] === "string" ) { | |
5524 styles[ key ] = style[ key ]; | |
5525 } | |
5526 } | |
5527 } | |
5528 | |
5529 return styles; | |
5530 } | |
5531 | |
5532 | |
5533 function styleDifference( oldStyle, newStyle ) { | |
5534 var diff = {}, | |
5535 name, value; | |
5536 | |
5537 for ( name in newStyle ) { | |
5538 value = newStyle[ name ]; | |
5539 if ( oldStyle[ name ] !== value ) { | |
5540 if ( !shorthandStyles[ name ] ) { | |
5541 if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) { | |
5542 diff[ name ] = value; | |
5543 } | |
5544 } | |
5545 } | |
5546 } | |
5547 | |
5548 return diff; | |
5549 } | |
5550 | |
5551 // support: jQuery <1.8 | |
5552 if ( !$.fn.addBack ) { | |
5553 $.fn.addBack = function( selector ) { | |
5554 return this.add( selector == null ? | |
5555 this.prevObject : this.prevObject.filter( selector ) | |
5556 ); | |
5557 }; | |
5558 } | |
5559 | |
5560 $.effects.animateClass = function( value, duration, easing, callback ) { | |
5561 var o = $.speed( duration, easing, callback ); | |
5562 | |
5563 return this.queue( function() { | |
5564 var animated = $( this ), | |
5565 baseClass = animated.attr( "class" ) || "", | |
5566 applyClassChange, | |
5567 allAnimations = o.children ? animated.find( "*" ).addBack() : animated; | |
5568 | |
5569 // map the animated objects to store the original styles. | |
5570 allAnimations = allAnimations.map(function() { | |
5571 var el = $( this ); | |
5572 return { | |
5573 el: el, | |
5574 start: getElementStyles( this ) | |
5575 }; | |
5576 }); | |
5577 | |
5578 // apply class change | |
5579 applyClassChange = function() { | |
5580 $.each( classAnimationActions, function(i, action) { | |
5581 if ( value[ action ] ) { | |
5582 animated[ action + "Class" ]( value[ action ] ); | |
5583 } | |
5584 }); | |
5585 }; | |
5586 applyClassChange(); | |
5587 | |
5588 // map all animated objects again - calculate new styles and diff | |
5589 allAnimations = allAnimations.map(function() { | |
5590 this.end = getElementStyles( this.el[ 0 ] ); | |
5591 this.diff = styleDifference( this.start, this.end ); | |
5592 return this; | |
5593 }); | |
5594 | |
5595 // apply original class | |
5596 animated.attr( "class", baseClass ); | |
5597 | |
5598 // map all animated objects again - this time collecting a promise | |
5599 allAnimations = allAnimations.map(function() { | |
5600 var styleInfo = this, | |
5601 dfd = $.Deferred(), | |
5602 opts = $.extend({}, o, { | |
5603 queue: false, | |
5604 complete: function() { | |
5605 dfd.resolve( styleInfo ); | |
5606 } | |
5607 }); | |
5608 | |
5609 this.el.animate( this.diff, opts ); | |
5610 return dfd.promise(); | |
5611 }); | |
5612 | |
5613 // once all animations have completed: | |
5614 $.when.apply( $, allAnimations.get() ).done(function() { | |
5615 | |
5616 // set the final class | |
5617 applyClassChange(); | |
5618 | |
5619 // for each animated element, | |
5620 // clear all css properties that were animated | |
5621 $.each( arguments, function() { | |
5622 var el = this.el; | |
5623 $.each( this.diff, function(key) { | |
5624 el.css( key, "" ); | |
5625 }); | |
5626 }); | |
5627 | |
5628 // this is guarnteed to be there if you use jQuery.speed() | |
5629 // it also handles dequeuing the next anim... | |
5630 o.complete.call( animated[ 0 ] ); | |
5631 }); | |
5632 }); | |
5633 }; | |
5634 | |
5635 $.fn.extend({ | |
5636 addClass: (function( orig ) { | |
5637 return function( classNames, speed, easing, callback ) { | |
5638 return speed ? | |
5639 $.effects.animateClass.call( this, | |
5640 { add: classNames }, speed, easing, callback ) : | |
5641 orig.apply( this, arguments ); | |
5642 }; | |
5643 })( $.fn.addClass ), | |
5644 | |
5645 removeClass: (function( orig ) { | |
5646 return function( classNames, speed, easing, callback ) { | |
5647 return arguments.length > 1 ? | |
5648 $.effects.animateClass.call( this, | |
5649 { remove: classNames }, speed, easing, callback ) : | |
5650 orig.apply( this, arguments ); | |
5651 }; | |
5652 })( $.fn.removeClass ), | |
5653 | |
5654 toggleClass: (function( orig ) { | |
5655 return function( classNames, force, speed, easing, callback ) { | |
5656 if ( typeof force === "boolean" || force === undefined ) { | |
5657 if ( !speed ) { | |
5658 // without speed parameter | |
5659 return orig.apply( this, arguments ); | |
5660 } else { | |
5661 return $.effects.animateClass.call( this, | |
5662 (force ? { add: classNames } : { remove: classNames }), | |
5663 speed, easing, callback ); | |
5664 } | |
5665 } else { | |
5666 // without force parameter | |
5667 return $.effects.animateClass.call( this, | |
5668 { toggle: classNames }, force, speed, easing ); | |
5669 } | |
5670 }; | |
5671 })( $.fn.toggleClass ), | |
5672 | |
5673 switchClass: function( remove, add, speed, easing, callback) { | |
5674 return $.effects.animateClass.call( this, { | |
5675 add: add, | |
5676 remove: remove | |
5677 }, speed, easing, callback ); | |
5678 } | |
5679 }); | |
5680 | |
5681 })(); | |
5682 | |
5683 /******************************************************************************/ | |
5684 /*********************************** EFFECTS **********************************/ | |
5685 /******************************************************************************/ | |
5686 | |
5687 (function() { | |
5688 | |
5689 $.extend( $.effects, { | |
5690 version: "1.10.4", | |
5691 | |
5692 // Saves a set of properties in a data storage | |
5693 save: function( element, set ) { | |
5694 for( var i=0; i < set.length; i++ ) { | |
5695 if ( set[ i ] !== null ) { | |
5696 element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] ); | |
5697 } | |
5698 } | |
5699 }, | |
5700 | |
5701 // Restores a set of previously saved properties from a data storage | |
5702 restore: function( element, set ) { | |
5703 var val, i; | |
5704 for( i=0; i < set.length; i++ ) { | |
5705 if ( set[ i ] !== null ) { | |
5706 val = element.data( dataSpace + set[ i ] ); | |
5707 // support: jQuery 1.6.2 | |
5708 // http://bugs.jquery.com/ticket/9917 | |
5709 // jQuery 1.6.2 incorrectly returns undefined for any falsy value. | |
5710 // We can't differentiate between "" and 0 here, so we just assume | |
5711 // empty string since it's likely to be a more common value... | |
5712 if ( val === undefined ) { | |
5713 val = ""; | |
5714 } | |
5715 element.css( set[ i ], val ); | |
5716 } | |
5717 } | |
5718 }, | |
5719 | |
5720 setMode: function( el, mode ) { | |
5721 if (mode === "toggle") { | |
5722 mode = el.is( ":hidden" ) ? "show" : "hide"; | |
5723 } | |
5724 return mode; | |
5725 }, | |
5726 | |
5727 // Translates a [top,left] array into a baseline value | |
5728 // this should be a little more flexible in the future to handle a string & hash | |
5729 getBaseline: function( origin, original ) { | |
5730 var y, x; | |
5731 switch ( origin[ 0 ] ) { | |
5732 case "top": y = 0; break; | |
5733 case "middle": y = 0.5; break; | |
5734 case "bottom": y = 1; break; | |
5735 default: y = origin[ 0 ] / original.height; | |
5736 } | |
5737 switch ( origin[ 1 ] ) { | |
5738 case "left": x = 0; break; | |
5739 case "center": x = 0.5; break; | |
5740 case "right": x = 1; break; | |
5741 default: x = origin[ 1 ] / original.width; | |
5742 } | |
5743 return { | |
5744 x: x, | |
5745 y: y | |
5746 }; | |
5747 }, | |
5748 | |
5749 // Wraps the element around a wrapper that copies position properties | |
5750 createWrapper: function( element ) { | |
5751 | |
5752 // if the element is already wrapped, return it | |
5753 if ( element.parent().is( ".ui-effects-wrapper" )) { | |
5754 return element.parent(); | |
5755 } | |
5756 | |
5757 // wrap the element | |
5758 var props = { | |
5759 width: element.outerWidth(true), | |
5760 height: element.outerHeight(true), | |
5761 "float": element.css( "float" ) | |
5762 }, | |
5763 wrapper = $( "<div></div>" ) | |
5764 .addClass( "ui-effects-wrapper" ) | |
5765 .css({ | |
5766 fontSize: "100%", | |
5767 background: "transparent", | |
5768 border: "none", | |
5769 margin: 0, | |
5770 padding: 0 | |
5771 }), | |
5772 // Store the size in case width/height are defined in % - Fixes #5245 | |
5773 size = { | |
5774 width: element.width(), | |
5775 height: element.height() | |
5776 }, | |
5777 active = document.activeElement; | |
5778 | |
5779 // support: Firefox | |
5780 // Firefox incorrectly exposes anonymous content | |
5781 // https://bugzilla.mozilla.org/show_bug.cgi?id=561664 | |
5782 try { | |
5783 active.id; | |
5784 } catch( e ) { | |
5785 active = document.body; | |
5786 } | |
5787 | |
5788 element.wrap( wrapper ); | |
5789 | |
5790 // Fixes #7595 - Elements lose focus when wrapped. | |
5791 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { | |
5792 $( active ).focus(); | |
5793 } | |
5794 | |
5795 wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually lose the reference to the wrapped element | |
5796 | |
5797 // transfer positioning properties to the wrapper | |
5798 if ( element.css( "position" ) === "static" ) { | |
5799 wrapper.css({ position: "relative" }); | |
5800 element.css({ position: "relative" }); | |
5801 } else { | |
5802 $.extend( props, { | |
5803 position: element.css( "position" ), | |
5804 zIndex: element.css( "z-index" ) | |
5805 }); | |
5806 $.each([ "top", "left", "bottom", "right" ], function(i, pos) { | |
5807 props[ pos ] = element.css( pos ); | |
5808 if ( isNaN( parseInt( props[ pos ], 10 ) ) ) { | |
5809 props[ pos ] = "auto"; | |
5810 } | |
5811 }); | |
5812 element.css({ | |
5813 position: "relative", | |
5814 top: 0, | |
5815 left: 0, | |
5816 right: "auto", | |
5817 bottom: "auto" | |
5818 }); | |
5819 } | |
5820 element.css(size); | |
5821 | |
5822 return wrapper.css( props ).show(); | |
5823 }, | |
5824 | |
5825 removeWrapper: function( element ) { | |
5826 var active = document.activeElement; | |
5827 | |
5828 if ( element.parent().is( ".ui-effects-wrapper" ) ) { | |
5829 element.parent().replaceWith( element ); | |
5830 | |
5831 // Fixes #7595 - Elements lose focus when wrapped. | |
5832 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { | |
5833 $( active ).focus(); | |
5834 } | |
5835 } | |
5836 | |
5837 | |
5838 return element; | |
5839 }, | |
5840 | |
5841 setTransition: function( element, list, factor, value ) { | |
5842 value = value || {}; | |
5843 $.each( list, function( i, x ) { | |
5844 var unit = element.cssUnit( x ); | |
5845 if ( unit[ 0 ] > 0 ) { | |
5846 value[ x ] = unit[ 0 ] * factor + unit[ 1 ]; | |
5847 } | |
5848 }); | |
5849 return value; | |
5850 } | |
5851 }); | |
5852 | |
5853 // return an effect options object for the given parameters: | |
5854 function _normalizeArguments( effect, options, speed, callback ) { | |
5855 | |
5856 // allow passing all options as the first parameter | |
5857 if ( $.isPlainObject( effect ) ) { | |
5858 options = effect; | |
5859 effect = effect.effect; | |
5860 } | |
5861 | |
5862 // convert to an object | |
5863 effect = { effect: effect }; | |
5864 | |
5865 // catch (effect, null, ...) | |
5866 if ( options == null ) { | |
5867 options = {}; | |
5868 } | |
5869 | |
5870 // catch (effect, callback) | |
5871 if ( $.isFunction( options ) ) { | |
5872 callback = options; | |
5873 speed = null; | |
5874 options = {}; | |
5875 } | |
5876 | |
5877 // catch (effect, speed, ?) | |
5878 if ( typeof options === "number" || $.fx.speeds[ options ] ) { | |
5879 callback = speed; | |
5880 speed = options; | |
5881 options = {}; | |
5882 } | |
5883 | |
5884 // catch (effect, options, callback) | |
5885 if ( $.isFunction( speed ) ) { | |
5886 callback = speed; | |
5887 speed = null; | |
5888 } | |
5889 | |
5890 // add options to effect | |
5891 if ( options ) { | |
5892 $.extend( effect, options ); | |
5893 } | |
5894 | |
5895 speed = speed || options.duration; | |
5896 effect.duration = $.fx.off ? 0 : | |
5897 typeof speed === "number" ? speed : | |
5898 speed in $.fx.speeds ? $.fx.speeds[ speed ] : | |
5899 $.fx.speeds._default; | |
5900 | |
5901 effect.complete = callback || options.complete; | |
5902 | |
5903 return effect; | |
5904 } | |
5905 | |
5906 function standardAnimationOption( option ) { | |
5907 // Valid standard speeds (nothing, number, named speed) | |
5908 if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) { | |
5909 return true; | |
5910 } | |
5911 | |
5912 // Invalid strings - treat as "normal" speed | |
5913 if ( typeof option === "string" && !$.effects.effect[ option ] ) { | |
5914 return true; | |
5915 } | |
5916 | |
5917 // Complete callback | |
5918 if ( $.isFunction( option ) ) { | |
5919 return true; | |
5920 } | |
5921 | |
5922 // Options hash (but not naming an effect) | |
5923 if ( typeof option === "object" && !option.effect ) { | |
5924 return true; | |
5925 } | |
5926 | |
5927 // Didn't match any standard API | |
5928 return false; | |
5929 } | |
5930 | |
5931 $.fn.extend({ | |
5932 effect: function( /* effect, options, speed, callback */ ) { | |
5933 var args = _normalizeArguments.apply( this, arguments ), | |
5934 mode = args.mode, | |
5935 queue = args.queue, | |
5936 effectMethod = $.effects.effect[ args.effect ]; | |
5937 | |
5938 if ( $.fx.off || !effectMethod ) { | |
5939 // delegate to the original method (e.g., .show()) if possible | |
5940 if ( mode ) { | |
5941 return this[ mode ]( args.duration, args.complete ); | |
5942 } else { | |
5943 return this.each( function() { | |
5944 if ( args.complete ) { | |
5945 args.complete.call( this ); | |
5946 } | |
5947 }); | |
5948 } | |
5949 } | |
5950 | |
5951 function run( next ) { | |
5952 var elem = $( this ), | |
5953 complete = args.complete, | |
5954 mode = args.mode; | |
5955 | |
5956 function done() { | |
5957 if ( $.isFunction( complete ) ) { | |
5958 complete.call( elem[0] ); | |
5959 } | |
5960 if ( $.isFunction( next ) ) { | |
5961 next(); | |
5962 } | |
5963 } | |
5964 | |
5965 // If the element already has the correct final state, delegate to | |
5966 // the core methods so the internal tracking of "olddisplay" works. | |
5967 if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) { | |
5968 elem[ mode ](); | |
5969 done(); | |
5970 } else { | |
5971 effectMethod.call( elem[0], args, done ); | |
5972 } | |
5973 } | |
5974 | |
5975 return queue === false ? this.each( run ) : this.queue( queue || "fx", run ); | |
5976 }, | |
5977 | |
5978 show: (function( orig ) { | |
5979 return function( option ) { | |
5980 if ( standardAnimationOption( option ) ) { | |
5981 return orig.apply( this, arguments ); | |
5982 } else { | |
5983 var args = _normalizeArguments.apply( this, arguments ); | |
5984 args.mode = "show"; | |
5985 return this.effect.call( this, args ); | |
5986 } | |
5987 }; | |
5988 })( $.fn.show ), | |
5989 | |
5990 hide: (function( orig ) { | |
5991 return function( option ) { | |
5992 if ( standardAnimationOption( option ) ) { | |
5993 return orig.apply( this, arguments ); | |
5994 } else { | |
5995 var args = _normalizeArguments.apply( this, arguments ); | |
5996 args.mode = "hide"; | |
5997 return this.effect.call( this, args ); | |
5998 } | |
5999 }; | |
6000 })( $.fn.hide ), | |
6001 | |
6002 toggle: (function( orig ) { | |
6003 return function( option ) { | |
6004 if ( standardAnimationOption( option ) || typeof option === "boolean" ) { | |
6005 return orig.apply( this, arguments ); | |
6006 } else { | |
6007 var args = _normalizeArguments.apply( this, arguments ); | |
6008 args.mode = "toggle"; | |
6009 return this.effect.call( this, args ); | |
6010 } | |
6011 }; | |
6012 })( $.fn.toggle ), | |
6013 | |
6014 // helper functions | |
6015 cssUnit: function(key) { | |
6016 var style = this.css( key ), | |
6017 val = []; | |
6018 | |
6019 $.each( [ "em", "px", "%", "pt" ], function( i, unit ) { | |
6020 if ( style.indexOf( unit ) > 0 ) { | |
6021 val = [ parseFloat( style ), unit ]; | |
6022 } | |
6023 }); | |
6024 return val; | |
6025 } | |
6026 }); | |
6027 | |
6028 })(); | |
6029 | |
6030 /******************************************************************************/ | |
6031 /*********************************** EASING ***********************************/ | |
6032 /******************************************************************************/ | |
6033 | |
6034 (function() { | |
6035 | |
6036 // based on easing equations from Robert Penner (http://www.robertpenner.com/easing) | |
6037 | |
6038 var baseEasings = {}; | |
6039 | |
6040 $.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) { | |
6041 baseEasings[ name ] = function( p ) { | |
6042 return Math.pow( p, i + 2 ); | |
6043 }; | |
6044 }); | |
6045 | |
6046 $.extend( baseEasings, { | |
6047 Sine: function ( p ) { | |
6048 return 1 - Math.cos( p * Math.PI / 2 ); | |
6049 }, | |
6050 Circ: function ( p ) { | |
6051 return 1 - Math.sqrt( 1 - p * p ); | |
6052 }, | |
6053 Elastic: function( p ) { | |
6054 return p === 0 || p === 1 ? p : | |
6055 -Math.pow( 2, 8 * (p - 1) ) * Math.sin( ( (p - 1) * 80 - 7.5 ) * Math.PI / 15 ); | |
6056 }, | |
6057 Back: function( p ) { | |
6058 return p * p * ( 3 * p - 2 ); | |
6059 }, | |
6060 Bounce: function ( p ) { | |
6061 var pow2, | |
6062 bounce = 4; | |
6063 | |
6064 while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {} | |
6065 return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 ); | |
6066 } | |
6067 }); | |
6068 | |
6069 $.each( baseEasings, function( name, easeIn ) { | |
6070 $.easing[ "easeIn" + name ] = easeIn; | |
6071 $.easing[ "easeOut" + name ] = function( p ) { | |
6072 return 1 - easeIn( 1 - p ); | |
6073 }; | |
6074 $.easing[ "easeInOut" + name ] = function( p ) { | |
6075 return p < 0.5 ? | |
6076 easeIn( p * 2 ) / 2 : | |
6077 1 - easeIn( p * -2 + 2 ) / 2; | |
6078 }; | |
6079 }); | |
6080 | |
6081 })(); | |
6082 | |
6083 })(jQuery); | |
6084 | |
6085 (function( $, undefined ) { | |
6086 | |
6087 var uid = 0, | |
6088 hideProps = {}, | |
6089 showProps = {}; | |
6090 | |
6091 hideProps.height = hideProps.paddingTop = hideProps.paddingBottom = | |
6092 hideProps.borderTopWidth = hideProps.borderBottomWidth = "hide"; | |
6093 showProps.height = showProps.paddingTop = showProps.paddingBottom = | |
6094 showProps.borderTopWidth = showProps.borderBottomWidth = "show"; | |
6095 | |
6096 $.widget( "ui.accordion", { | |
6097 version: "1.10.4", | |
6098 options: { | |
6099 active: 0, | |
6100 animate: {}, | |
6101 collapsible: false, | |
6102 event: "click", | |
6103 header: "> li > :first-child,> :not(li):even", | |
6104 heightStyle: "auto", | |
6105 icons: { | |
6106 activeHeader: "ui-icon-triangle-1-s", | |
6107 header: "ui-icon-triangle-1-e" | |
6108 }, | |
6109 | |
6110 // callbacks | |
6111 activate: null, | |
6112 beforeActivate: null | |
6113 }, | |
6114 | |
6115 _create: function() { | |
6116 var options = this.options; | |
6117 this.prevShow = this.prevHide = $(); | |
6118 this.element.addClass( "ui-accordion ui-widget ui-helper-reset" ) | |
6119 // ARIA | |
6120 .attr( "role", "tablist" ); | |
6121 | |
6122 // don't allow collapsible: false and active: false / null | |
6123 if ( !options.collapsible && (options.active === false || options.active == null) ) { | |
6124 options.active = 0; | |
6125 } | |
6126 | |
6127 this._processPanels(); | |
6128 // handle negative values | |
6129 if ( options.active < 0 ) { | |
6130 options.active += this.headers.length; | |
6131 } | |
6132 this._refresh(); | |
6133 }, | |
6134 | |
6135 _getCreateEventData: function() { | |
6136 return { | |
6137 header: this.active, | |
6138 panel: !this.active.length ? $() : this.active.next(), | |
6139 content: !this.active.length ? $() : this.active.next() | |
6140 }; | |
6141 }, | |
6142 | |
6143 _createIcons: function() { | |
6144 var icons = this.options.icons; | |
6145 if ( icons ) { | |
6146 $( "<span>" ) | |
6147 .addClass( "ui-accordion-header-icon ui-icon " + icons.header ) | |
6148 .prependTo( this.headers ); | |
6149 this.active.children( ".ui-accordion-header-icon" ) | |
6150 .removeClass( icons.header ) | |
6151 .addClass( icons.activeHeader ); | |
6152 this.headers.addClass( "ui-accordion-icons" ); | |
6153 } | |
6154 }, | |
6155 | |
6156 _destroyIcons: function() { | |
6157 this.headers | |
6158 .removeClass( "ui-accordion-icons" ) | |
6159 .children( ".ui-accordion-header-icon" ) | |
6160 .remove(); | |
6161 }, | |
6162 | |
6163 _destroy: function() { | |
6164 var contents; | |
6165 | |
6166 // clean up main element | |
6167 this.element | |
6168 .removeClass( "ui-accordion ui-widget ui-helper-reset" ) | |
6169 .removeAttr( "role" ); | |
6170 | |
6171 // clean up headers | |
6172 this.headers | |
6173 .removeClass( "ui-accordion-header ui-accordion-header-active ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" ) | |
6174 .removeAttr( "role" ) | |
6175 .removeAttr( "aria-expanded" ) | |
6176 .removeAttr( "aria-selected" ) | |
6177 .removeAttr( "aria-controls" ) | |
6178 .removeAttr( "tabIndex" ) | |
6179 .each(function() { | |
6180 if ( /^ui-accordion/.test( this.id ) ) { | |
6181 this.removeAttribute( "id" ); | |
6182 } | |
6183 }); | |
6184 this._destroyIcons(); | |
6185 | |
6186 // clean up content panels | |
6187 contents = this.headers.next() | |
6188 .css( "display", "" ) | |
6189 .removeAttr( "role" ) | |
6190 .removeAttr( "aria-hidden" ) | |
6191 .removeAttr( "aria-labelledby" ) | |
6192 .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled" ) | |
6193 .each(function() { | |
6194 if ( /^ui-accordion/.test( this.id ) ) { | |
6195 this.removeAttribute( "id" ); | |
6196 } | |
6197 }); | |
6198 if ( this.options.heightStyle !== "content" ) { | |
6199 contents.css( "height", "" ); | |
6200 } | |
6201 }, | |
6202 | |
6203 _setOption: function( key, value ) { | |
6204 if ( key === "active" ) { | |
6205 // _activate() will handle invalid values and update this.options | |
6206 this._activate( value ); | |
6207 return; | |
6208 } | |
6209 | |
6210 if ( key === "event" ) { | |
6211 if ( this.options.event ) { | |
6212 this._off( this.headers, this.options.event ); | |
6213 } | |
6214 this._setupEvents( value ); | |
6215 } | |
6216 | |
6217 this._super( key, value ); | |
6218 | |
6219 // setting collapsible: false while collapsed; open first panel | |
6220 if ( key === "collapsible" && !value && this.options.active === false ) { | |
6221 this._activate( 0 ); | |
6222 } | |
6223 | |
6224 if ( key === "icons" ) { | |
6225 this._destroyIcons(); | |
6226 if ( value ) { | |
6227 this._createIcons(); | |
6228 } | |
6229 } | |
6230 | |
6231 // #5332 - opacity doesn't cascade to positioned elements in IE | |
6232 // so we need to add the disabled class to the headers and panels | |
6233 if ( key === "disabled" ) { | |
6234 this.headers.add( this.headers.next() ) | |
6235 .toggleClass( "ui-state-disabled", !!value ); | |
6236 } | |
6237 }, | |
6238 | |
6239 _keydown: function( event ) { | |
6240 if ( event.altKey || event.ctrlKey ) { | |
6241 return; | |
6242 } | |
6243 | |
6244 var keyCode = $.ui.keyCode, | |
6245 length = this.headers.length, | |
6246 currentIndex = this.headers.index( event.target ), | |
6247 toFocus = false; | |
6248 | |
6249 switch ( event.keyCode ) { | |
6250 case keyCode.RIGHT: | |
6251 case keyCode.DOWN: | |
6252 toFocus = this.headers[ ( currentIndex + 1 ) % length ]; | |
6253 break; | |
6254 case keyCode.LEFT: | |
6255 case keyCode.UP: | |
6256 toFocus = this.headers[ ( currentIndex - 1 + length ) % length ]; | |
6257 break; | |
6258 case keyCode.SPACE: | |
6259 case keyCode.ENTER: | |
6260 this._eventHandler( event ); | |
6261 break; | |
6262 case keyCode.HOME: | |
6263 toFocus = this.headers[ 0 ]; | |
6264 break; | |
6265 case keyCode.END: | |
6266 toFocus = this.headers[ length - 1 ]; | |
6267 break; | |
6268 } | |
6269 | |
6270 if ( toFocus ) { | |
6271 $( event.target ).attr( "tabIndex", -1 ); | |
6272 $( toFocus ).attr( "tabIndex", 0 ); | |
6273 toFocus.focus(); | |
6274 event.preventDefault(); | |
6275 } | |
6276 }, | |
6277 | |
6278 _panelKeyDown : function( event ) { | |
6279 if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) { | |
6280 $( event.currentTarget ).prev().focus(); | |
6281 } | |
6282 }, | |
6283 | |
6284 refresh: function() { | |
6285 var options = this.options; | |
6286 this._processPanels(); | |
6287 | |
6288 // was collapsed or no panel | |
6289 if ( ( options.active === false && options.collapsible === true ) || !this.headers.length ) { | |
6290 options.active = false; | |
6291 this.active = $(); | |
6292 // active false only when collapsible is true | |
6293 } else if ( options.active === false ) { | |
6294 this._activate( 0 ); | |
6295 // was active, but active panel is gone | |
6296 } else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) { | |
6297 // all remaining panel are disabled | |
6298 if ( this.headers.length === this.headers.find(".ui-state-disabled").length ) { | |
6299 options.active = false; | |
6300 this.active = $(); | |
6301 // activate previous panel | |
6302 } else { | |
6303 this._activate( Math.max( 0, options.active - 1 ) ); | |
6304 } | |
6305 // was active, active panel still exists | |
6306 } else { | |
6307 // make sure active index is correct | |
6308 options.active = this.headers.index( this.active ); | |
6309 } | |
6310 | |
6311 this._destroyIcons(); | |
6312 | |
6313 this._refresh(); | |
6314 }, | |
6315 | |
6316 _processPanels: function() { | |
6317 this.headers = this.element.find( this.options.header ) | |
6318 .addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" ); | |
6319 | |
6320 this.headers.next() | |
6321 .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" ) | |
6322 .filter(":not(.ui-accordion-content-active)") | |
6323 .hide(); | |
6324 }, | |
6325 | |
6326 _refresh: function() { | |
6327 var maxHeight, | |
6328 options = this.options, | |
6329 heightStyle = options.heightStyle, | |
6330 parent = this.element.parent(), | |
6331 accordionId = this.accordionId = "ui-accordion-" + | |
6332 (this.element.attr( "id" ) || ++uid); | |
6333 | |
6334 this.active = this._findActive( options.active ) | |
6335 .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" ) | |
6336 .removeClass( "ui-corner-all" ); | |
6337 this.active.next() | |
6338 .addClass( "ui-accordion-content-active" ) | |
6339 .show(); | |
6340 | |
6341 this.headers | |
6342 .attr( "role", "tab" ) | |
6343 .each(function( i ) { | |
6344 var header = $( this ), | |
6345 headerId = header.attr( "id" ), | |
6346 panel = header.next(), | |
6347 panelId = panel.attr( "id" ); | |
6348 if ( !headerId ) { | |
6349 headerId = accordionId + "-header-" + i; | |
6350 header.attr( "id", headerId ); | |
6351 } | |
6352 if ( !panelId ) { | |
6353 panelId = accordionId + "-panel-" + i; | |
6354 panel.attr( "id", panelId ); | |
6355 } | |
6356 header.attr( "aria-controls", panelId ); | |
6357 panel.attr( "aria-labelledby", headerId ); | |
6358 }) | |
6359 .next() | |
6360 .attr( "role", "tabpanel" ); | |
6361 | |
6362 this.headers | |
6363 .not( this.active ) | |
6364 .attr({ | |
6365 "aria-selected": "false", | |
6366 "aria-expanded": "false", | |
6367 tabIndex: -1 | |
6368 }) | |
6369 .next() | |
6370 .attr({ | |
6371 "aria-hidden": "true" | |
6372 }) | |
6373 .hide(); | |
6374 | |
6375 // make sure at least one header is in the tab order | |
6376 if ( !this.active.length ) { | |
6377 this.headers.eq( 0 ).attr( "tabIndex", 0 ); | |
6378 } else { | |
6379 this.active.attr({ | |
6380 "aria-selected": "true", | |
6381 "aria-expanded": "true", | |
6382 tabIndex: 0 | |
6383 }) | |
6384 .next() | |
6385 .attr({ | |
6386 "aria-hidden": "false" | |
6387 }); | |
6388 } | |
6389 | |
6390 this._createIcons(); | |
6391 | |
6392 this._setupEvents( options.event ); | |
6393 | |
6394 if ( heightStyle === "fill" ) { | |
6395 maxHeight = parent.height(); | |
6396 this.element.siblings( ":visible" ).each(function() { | |
6397 var elem = $( this ), | |
6398 position = elem.css( "position" ); | |
6399 | |
6400 if ( position === "absolute" || position === "fixed" ) { | |
6401 return; | |
6402 } | |
6403 maxHeight -= elem.outerHeight( true ); | |
6404 }); | |
6405 | |
6406 this.headers.each(function() { | |
6407 maxHeight -= $( this ).outerHeight( true ); | |
6408 }); | |
6409 | |
6410 this.headers.next() | |
6411 .each(function() { | |
6412 $( this ).height( Math.max( 0, maxHeight - | |
6413 $( this ).innerHeight() + $( this ).height() ) ); | |
6414 }) | |
6415 .css( "overflow", "auto" ); | |
6416 } else if ( heightStyle === "auto" ) { | |
6417 maxHeight = 0; | |
6418 this.headers.next() | |
6419 .each(function() { | |
6420 maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() ); | |
6421 }) | |
6422 .height( maxHeight ); | |
6423 } | |
6424 }, | |
6425 | |
6426 _activate: function( index ) { | |
6427 var active = this._findActive( index )[ 0 ]; | |
6428 | |
6429 // trying to activate the already active panel | |
6430 if ( active === this.active[ 0 ] ) { | |
6431 return; | |
6432 } | |
6433 | |
6434 // trying to collapse, simulate a click on the currently active header | |
6435 active = active || this.active[ 0 ]; | |
6436 | |
6437 this._eventHandler({ | |
6438 target: active, | |
6439 currentTarget: active, | |
6440 preventDefault: $.noop | |
6441 }); | |
6442 }, | |
6443 | |
6444 _findActive: function( selector ) { | |
6445 return typeof selector === "number" ? this.headers.eq( selector ) : $(); | |
6446 }, | |
6447 | |
6448 _setupEvents: function( event ) { | |
6449 var events = { | |
6450 keydown: "_keydown" | |
6451 }; | |
6452 if ( event ) { | |
6453 $.each( event.split(" "), function( index, eventName ) { | |
6454 events[ eventName ] = "_eventHandler"; | |
6455 }); | |
6456 } | |
6457 | |
6458 this._off( this.headers.add( this.headers.next() ) ); | |
6459 this._on( this.headers, events ); | |
6460 this._on( this.headers.next(), { keydown: "_panelKeyDown" }); | |
6461 this._hoverable( this.headers ); | |
6462 this._focusable( this.headers ); | |
6463 }, | |
6464 | |
6465 _eventHandler: function( event ) { | |
6466 var options = this.options, | |
6467 active = this.active, | |
6468 clicked = $( event.currentTarget ), | |
6469 clickedIsActive = clicked[ 0 ] === active[ 0 ], | |
6470 collapsing = clickedIsActive && options.collapsible, | |
6471 toShow = collapsing ? $() : clicked.next(), | |
6472 toHide = active.next(), | |
6473 eventData = { | |
6474 oldHeader: active, | |
6475 oldPanel: toHide, | |
6476 newHeader: collapsing ? $() : clicked, | |
6477 newPanel: toShow | |
6478 }; | |
6479 | |
6480 event.preventDefault(); | |
6481 | |
6482 if ( | |
6483 // click on active header, but not collapsible | |
6484 ( clickedIsActive && !options.collapsible ) || | |
6485 // allow canceling activation | |
6486 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { | |
6487 return; | |
6488 } | |
6489 | |
6490 options.active = collapsing ? false : this.headers.index( clicked ); | |
6491 | |
6492 // when the call to ._toggle() comes after the class changes | |
6493 // it causes a very odd bug in IE 8 (see #6720) | |
6494 this.active = clickedIsActive ? $() : clicked; | |
6495 this._toggle( eventData ); | |
6496 | |
6497 // switch classes | |
6498 // corner classes on the previously active header stay after the animation | |
6499 active.removeClass( "ui-accordion-header-active ui-state-active" ); | |
6500 if ( options.icons ) { | |
6501 active.children( ".ui-accordion-header-icon" ) | |
6502 .removeClass( options.icons.activeHeader ) | |
6503 .addClass( options.icons.header ); | |
6504 } | |
6505 | |
6506 if ( !clickedIsActive ) { | |
6507 clicked | |
6508 .removeClass( "ui-corner-all" ) | |
6509 .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" ); | |
6510 if ( options.icons ) { | |
6511 clicked.children( ".ui-accordion-header-icon" ) | |
6512 .removeClass( options.icons.header ) | |
6513 .addClass( options.icons.activeHeader ); | |
6514 } | |
6515 | |
6516 clicked | |
6517 .next() | |
6518 .addClass( "ui-accordion-content-active" ); | |
6519 } | |
6520 }, | |
6521 | |
6522 _toggle: function( data ) { | |
6523 var toShow = data.newPanel, | |
6524 toHide = this.prevShow.length ? this.prevShow : data.oldPanel; | |
6525 | |
6526 // handle activating a panel during the animation for another activation | |
6527 this.prevShow.add( this.prevHide ).stop( true, true ); | |
6528 this.prevShow = toShow; | |
6529 this.prevHide = toHide; | |
6530 | |
6531 if ( this.options.animate ) { | |
6532 this._animate( toShow, toHide, data ); | |
6533 } else { | |
6534 toHide.hide(); | |
6535 toShow.show(); | |
6536 this._toggleComplete( data ); | |
6537 } | |
6538 | |
6539 toHide.attr({ | |
6540 "aria-hidden": "true" | |
6541 }); | |
6542 toHide.prev().attr( "aria-selected", "false" ); | |
6543 // if we're switching panels, remove the old header from the tab order | |
6544 // if we're opening from collapsed state, remove the previous header from the tab order | |
6545 // if we're collapsing, then keep the collapsing header in the tab order | |
6546 if ( toShow.length && toHide.length ) { | |
6547 toHide.prev().attr({ | |
6548 "tabIndex": -1, | |
6549 "aria-expanded": "false" | |
6550 }); | |
6551 } else if ( toShow.length ) { | |
6552 this.headers.filter(function() { | |
6553 return $( this ).attr( "tabIndex" ) === 0; | |
6554 }) | |
6555 .attr( "tabIndex", -1 ); | |
6556 } | |
6557 | |
6558 toShow | |
6559 .attr( "aria-hidden", "false" ) | |
6560 .prev() | |
6561 .attr({ | |
6562 "aria-selected": "true", | |
6563 tabIndex: 0, | |
6564 "aria-expanded": "true" | |
6565 }); | |
6566 }, | |
6567 | |
6568 _animate: function( toShow, toHide, data ) { | |
6569 var total, easing, duration, | |
6570 that = this, | |
6571 adjust = 0, | |
6572 down = toShow.length && | |
6573 ( !toHide.length || ( toShow.index() < toHide.index() ) ), | |
6574 animate = this.options.animate || {}, | |
6575 options = down && animate.down || animate, | |
6576 complete = function() { | |
6577 that._toggleComplete( data ); | |
6578 }; | |
6579 | |
6580 if ( typeof options === "number" ) { | |
6581 duration = options; | |
6582 } | |
6583 if ( typeof options === "string" ) { | |
6584 easing = options; | |
6585 } | |
6586 // fall back from options to animation in case of partial down settings | |
6587 easing = easing || options.easing || animate.easing; | |
6588 duration = duration || options.duration || animate.duration; | |
6589 | |
6590 if ( !toHide.length ) { | |
6591 return toShow.animate( showProps, duration, easing, complete ); | |
6592 } | |
6593 if ( !toShow.length ) { | |
6594 return toHide.animate( hideProps, duration, easing, complete ); | |
6595 } | |
6596 | |
6597 total = toShow.show().outerHeight(); | |
6598 toHide.animate( hideProps, { | |
6599 duration: duration, | |
6600 easing: easing, | |
6601 step: function( now, fx ) { | |
6602 fx.now = Math.round( now ); | |
6603 } | |
6604 }); | |
6605 toShow | |
6606 .hide() | |
6607 .animate( showProps, { | |
6608 duration: duration, | |
6609 easing: easing, | |
6610 complete: complete, | |
6611 step: function( now, fx ) { | |
6612 fx.now = Math.round( now ); | |
6613 if ( fx.prop !== "height" ) { | |
6614 adjust += fx.now; | |
6615 } else if ( that.options.heightStyle !== "content" ) { | |
6616 fx.now = Math.round( total - toHide.outerHeight() - adjust ); | |
6617 adjust = 0; | |
6618 } | |
6619 } | |
6620 }); | |
6621 }, | |
6622 | |
6623 _toggleComplete: function( data ) { | |
6624 var toHide = data.oldPanel; | |
6625 | |
6626 toHide | |
6627 .removeClass( "ui-accordion-content-active" ) | |
6628 .prev() | |
6629 .removeClass( "ui-corner-top" ) | |
6630 .addClass( "ui-corner-all" ); | |
6631 | |
6632 // Work around for rendering bug in IE (#5421) | |
6633 if ( toHide.length ) { | |
6634 toHide.parent()[0].className = toHide.parent()[0].className; | |
6635 } | |
6636 this._trigger( "activate", null, data ); | |
6637 } | |
6638 }); | |
6639 | |
6640 })( jQuery ); | |
6641 | |
6642 (function( $, undefined ) { | |
6643 | |
6644 $.widget( "ui.autocomplete", { | |
6645 version: "1.10.4", | |
6646 defaultElement: "<input>", | |
6647 options: { | |
6648 appendTo: null, | |
6649 autoFocus: false, | |
6650 delay: 300, | |
6651 minLength: 1, | |
6652 position: { | |
6653 my: "left top", | |
6654 at: "left bottom", | |
6655 collision: "none" | |
6656 }, | |
6657 source: null, | |
6658 | |
6659 // callbacks | |
6660 change: null, | |
6661 close: null, | |
6662 focus: null, | |
6663 open: null, | |
6664 response: null, | |
6665 search: null, | |
6666 select: null | |
6667 }, | |
6668 | |
6669 requestIndex: 0, | |
6670 pending: 0, | |
6671 | |
6672 _create: function() { | |
6673 // Some browsers only repeat keydown events, not keypress events, | |
6674 // so we use the suppressKeyPress flag to determine if we've already | |
6675 // handled the keydown event. #7269 | |
6676 // Unfortunately the code for & in keypress is the same as the up arrow, | |
6677 // so we use the suppressKeyPressRepeat flag to avoid handling keypress | |
6678 // events when we know the keydown event was used to modify the | |
6679 // search term. #7799 | |
6680 var suppressKeyPress, suppressKeyPressRepeat, suppressInput, | |
6681 nodeName = this.element[0].nodeName.toLowerCase(), | |
6682 isTextarea = nodeName === "textarea", | |
6683 isInput = nodeName === "input"; | |
6684 | |
6685 this.isMultiLine = | |
6686 // Textareas are always multi-line | |
6687 isTextarea ? true : | |
6688 // Inputs are always single-line, even if inside a contentEditable element | |
6689 // IE also treats inputs as contentEditable | |
6690 isInput ? false : | |
6691 // All other element types are determined by whether or not they're contentEditable | |
6692 this.element.prop( "isContentEditable" ); | |
6693 | |
6694 this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ]; | |
6695 this.isNewMenu = true; | |
6696 | |
6697 this.element | |
6698 .addClass( "ui-autocomplete-input" ) | |
6699 .attr( "autocomplete", "off" ); | |
6700 | |
6701 this._on( this.element, { | |
6702 keydown: function( event ) { | |
6703 if ( this.element.prop( "readOnly" ) ) { | |
6704 suppressKeyPress = true; | |
6705 suppressInput = true; | |
6706 suppressKeyPressRepeat = true; | |
6707 return; | |
6708 } | |
6709 | |
6710 suppressKeyPress = false; | |
6711 suppressInput = false; | |
6712 suppressKeyPressRepeat = false; | |
6713 var keyCode = $.ui.keyCode; | |
6714 switch( event.keyCode ) { | |
6715 case keyCode.PAGE_UP: | |
6716 suppressKeyPress = true; | |
6717 this._move( "previousPage", event ); | |
6718 break; | |
6719 case keyCode.PAGE_DOWN: | |
6720 suppressKeyPress = true; | |
6721 this._move( "nextPage", event ); | |
6722 break; | |
6723 case keyCode.UP: | |
6724 suppressKeyPress = true; | |
6725 this._keyEvent( "previous", event ); | |
6726 break; | |
6727 case keyCode.DOWN: | |
6728 suppressKeyPress = true; | |
6729 this._keyEvent( "next", event ); | |
6730 break; | |
6731 case keyCode.ENTER: | |
6732 case keyCode.NUMPAD_ENTER: | |
6733 // when menu is open and has focus | |
6734 if ( this.menu.active ) { | |
6735 // #6055 - Opera still allows the keypress to occur | |
6736 // which causes forms to submit | |
6737 suppressKeyPress = true; | |
6738 event.preventDefault(); | |
6739 this.menu.select( event ); | |
6740 } | |
6741 break; | |
6742 case keyCode.TAB: | |
6743 if ( this.menu.active ) { | |
6744 this.menu.select( event ); | |
6745 } | |
6746 break; | |
6747 case keyCode.ESCAPE: | |
6748 if ( this.menu.element.is( ":visible" ) ) { | |
6749 this._value( this.term ); | |
6750 this.close( event ); | |
6751 // Different browsers have different default behavior for escape | |
6752 // Single press can mean undo or clear | |
6753 // Double press in IE means clear the whole form | |
6754 event.preventDefault(); | |
6755 } | |
6756 break; | |
6757 default: | |
6758 suppressKeyPressRepeat = true; | |
6759 // search timeout should be triggered before the input value is changed | |
6760 this._searchTimeout( event ); | |
6761 break; | |
6762 } | |
6763 }, | |
6764 keypress: function( event ) { | |
6765 if ( suppressKeyPress ) { | |
6766 suppressKeyPress = false; | |
6767 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) { | |
6768 event.preventDefault(); | |
6769 } | |
6770 return; | |
6771 } | |
6772 if ( suppressKeyPressRepeat ) { | |
6773 return; | |
6774 } | |
6775 | |
6776 // replicate some key handlers to allow them to repeat in Firefox and Opera | |
6777 var keyCode = $.ui.keyCode; | |
6778 switch( event.keyCode ) { | |
6779 case keyCode.PAGE_UP: | |
6780 this._move( "previousPage", event ); | |
6781 break; | |
6782 case keyCode.PAGE_DOWN: | |
6783 this._move( "nextPage", event ); | |
6784 break; | |
6785 case keyCode.UP: | |
6786 this._keyEvent( "previous", event ); | |
6787 break; | |
6788 case keyCode.DOWN: | |
6789 this._keyEvent( "next", event ); | |
6790 break; | |
6791 } | |
6792 }, | |
6793 input: function( event ) { | |
6794 if ( suppressInput ) { | |
6795 suppressInput = false; | |
6796 event.preventDefault(); | |
6797 return; | |
6798 } | |
6799 this._searchTimeout( event ); | |
6800 }, | |
6801 focus: function() { | |
6802 this.selectedItem = null; | |
6803 this.previous = this._value(); | |
6804 }, | |
6805 blur: function( event ) { | |
6806 if ( this.cancelBlur ) { | |
6807 delete this.cancelBlur; | |
6808 return; | |
6809 } | |
6810 | |
6811 clearTimeout( this.searching ); | |
6812 this.close( event ); | |
6813 this._change( event ); | |
6814 } | |
6815 }); | |
6816 | |
6817 this._initSource(); | |
6818 this.menu = $( "<ul>" ) | |
6819 .addClass( "ui-autocomplete ui-front" ) | |
6820 .appendTo( this._appendTo() ) | |
6821 .menu({ | |
6822 // disable ARIA support, the live region takes care of that | |
6823 role: null | |
6824 }) | |
6825 .hide() | |
6826 .data( "ui-menu" ); | |
6827 | |
6828 this._on( this.menu.element, { | |
6829 mousedown: function( event ) { | |
6830 // prevent moving focus out of the text field | |
6831 event.preventDefault(); | |
6832 | |
6833 // IE doesn't prevent moving focus even with event.preventDefault() | |
6834 // so we set a flag to know when we should ignore the blur event | |
6835 this.cancelBlur = true; | |
6836 this._delay(function() { | |
6837 delete this.cancelBlur; | |
6838 }); | |
6839 | |
6840 // clicking on the scrollbar causes focus to shift to the body | |
6841 // but we can't detect a mouseup or a click immediately afterward | |
6842 // so we have to track the next mousedown and close the menu if | |
6843 // the user clicks somewhere outside of the autocomplete | |
6844 var menuElement = this.menu.element[ 0 ]; | |
6845 if ( !$( event.target ).closest( ".ui-menu-item" ).length ) { | |
6846 this._delay(function() { | |
6847 var that = this; | |
6848 this.document.one( "mousedown", function( event ) { | |
6849 if ( event.target !== that.element[ 0 ] && | |
6850 event.target !== menuElement && | |
6851 !$.contains( menuElement, event.target ) ) { | |
6852 that.close(); | |
6853 } | |
6854 }); | |
6855 }); | |
6856 } | |
6857 }, | |
6858 menufocus: function( event, ui ) { | |
6859 // support: Firefox | |
6860 // Prevent accidental activation of menu items in Firefox (#7024 #9118) | |
6861 if ( this.isNewMenu ) { | |
6862 this.isNewMenu = false; | |
6863 if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) { | |
6864 this.menu.blur(); | |
6865 | |
6866 this.document.one( "mousemove", function() { | |
6867 $( event.target ).trigger( event.originalEvent ); | |
6868 }); | |
6869 | |
6870 return; | |
6871 } | |
6872 } | |
6873 | |
6874 var item = ui.item.data( "ui-autocomplete-item" ); | |
6875 if ( false !== this._trigger( "focus", event, { item: item } ) ) { | |
6876 // use value to match what will end up in the input, if it was a key event | |
6877 if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) { | |
6878 this._value( item.value ); | |
6879 } | |
6880 } else { | |
6881 // Normally the input is populated with the item's value as the | |
6882 // menu is navigated, causing screen readers to notice a change and | |
6883 // announce the item. Since the focus event was canceled, this doesn't | |
6884 // happen, so we update the live region so that screen readers can | |
6885 // still notice the change and announce it. | |
6886 this.liveRegion.text( item.value ); | |
6887 } | |
6888 }, | |
6889 menuselect: function( event, ui ) { | |
6890 var item = ui.item.data( "ui-autocomplete-item" ), | |
6891 previous = this.previous; | |
6892 | |
6893 // only trigger when focus was lost (click on menu) | |
6894 if ( this.element[0] !== this.document[0].activeElement ) { | |
6895 this.element.focus(); | |
6896 this.previous = previous; | |
6897 // #6109 - IE triggers two focus events and the second | |
6898 // is asynchronous, so we need to reset the previous | |
6899 // term synchronously and asynchronously :-( | |
6900 this._delay(function() { | |
6901 this.previous = previous; | |
6902 this.selectedItem = item; | |
6903 }); | |
6904 } | |
6905 | |
6906 if ( false !== this._trigger( "select", event, { item: item } ) ) { | |
6907 this._value( item.value ); | |
6908 } | |
6909 // reset the term after the select event | |
6910 // this allows custom select handling to work properly | |
6911 this.term = this._value(); | |
6912 | |
6913 this.close( event ); | |
6914 this.selectedItem = item; | |
6915 } | |
6916 }); | |
6917 | |
6918 this.liveRegion = $( "<span>", { | |
6919 role: "status", | |
6920 "aria-live": "polite" | |
6921 }) | |
6922 .addClass( "ui-helper-hidden-accessible" ) | |
6923 .insertBefore( this.element ); | |
6924 | |
6925 // turning off autocomplete prevents the browser from remembering the | |
6926 // value when navigating through history, so we re-enable autocomplete | |
6927 // if the page is unloaded before the widget is destroyed. #7790 | |
6928 this._on( this.window, { | |
6929 beforeunload: function() { | |
6930 this.element.removeAttr( "autocomplete" ); | |
6931 } | |
6932 }); | |
6933 }, | |
6934 | |
6935 _destroy: function() { | |
6936 clearTimeout( this.searching ); | |
6937 this.element | |
6938 .removeClass( "ui-autocomplete-input" ) | |
6939 .removeAttr( "autocomplete" ); | |
6940 this.menu.element.remove(); | |
6941 this.liveRegion.remove(); | |
6942 }, | |
6943 | |
6944 _setOption: function( key, value ) { | |
6945 this._super( key, value ); | |
6946 if ( key === "source" ) { | |
6947 this._initSource(); | |
6948 } | |
6949 if ( key === "appendTo" ) { | |
6950 this.menu.element.appendTo( this._appendTo() ); | |
6951 } | |
6952 if ( key === "disabled" && value && this.xhr ) { | |
6953 this.xhr.abort(); | |
6954 } | |
6955 }, | |
6956 | |
6957 _appendTo: function() { | |
6958 var element = this.options.appendTo; | |
6959 | |
6960 if ( element ) { | |
6961 element = element.jquery || element.nodeType ? | |
6962 $( element ) : | |
6963 this.document.find( element ).eq( 0 ); | |
6964 } | |
6965 | |
6966 if ( !element ) { | |
6967 element = this.element.closest( ".ui-front" ); | |
6968 } | |
6969 | |
6970 if ( !element.length ) { | |
6971 element = this.document[0].body; | |
6972 } | |
6973 | |
6974 return element; | |
6975 }, | |
6976 | |
6977 _initSource: function() { | |
6978 var array, url, | |
6979 that = this; | |
6980 if ( $.isArray(this.options.source) ) { | |
6981 array = this.options.source; | |
6982 this.source = function( request, response ) { | |
6983 response( $.ui.autocomplete.filter( array, request.term ) ); | |
6984 }; | |
6985 } else if ( typeof this.options.source === "string" ) { | |
6986 url = this.options.source; | |
6987 this.source = function( request, response ) { | |
6988 if ( that.xhr ) { | |
6989 that.xhr.abort(); | |
6990 } | |
6991 that.xhr = $.ajax({ | |
6992 url: url, | |
6993 data: request, | |
6994 dataType: "json", | |
6995 success: function( data ) { | |
6996 response( data ); | |
6997 }, | |
6998 error: function() { | |
6999 response( [] ); | |
7000 } | |
7001 }); | |
7002 }; | |
7003 } else { | |
7004 this.source = this.options.source; | |
7005 } | |
7006 }, | |
7007 | |
7008 _searchTimeout: function( event ) { | |
7009 clearTimeout( this.searching ); | |
7010 this.searching = this._delay(function() { | |
7011 // only search if the value has changed | |
7012 if ( this.term !== this._value() ) { | |
7013 this.selectedItem = null; | |
7014 this.search( null, event ); | |
7015 } | |
7016 }, this.options.delay ); | |
7017 }, | |
7018 | |
7019 search: function( value, event ) { | |
7020 value = value != null ? value : this._value(); | |
7021 | |
7022 // always save the actual value, not the one passed as an argument | |
7023 this.term = this._value(); | |
7024 | |
7025 if ( value.length < this.options.minLength ) { | |
7026 return this.close( event ); | |
7027 } | |
7028 | |
7029 if ( this._trigger( "search", event ) === false ) { | |
7030 return; | |
7031 } | |
7032 | |
7033 return this._search( value ); | |
7034 }, | |
7035 | |
7036 _search: function( value ) { | |
7037 this.pending++; | |
7038 this.element.addClass( "ui-autocomplete-loading" ); | |
7039 this.cancelSearch = false; | |
7040 | |
7041 this.source( { term: value }, this._response() ); | |
7042 }, | |
7043 | |
7044 _response: function() { | |
7045 var index = ++this.requestIndex; | |
7046 | |
7047 return $.proxy(function( content ) { | |
7048 if ( index === this.requestIndex ) { | |
7049 this.__response( content ); | |
7050 } | |
7051 | |
7052 this.pending--; | |
7053 if ( !this.pending ) { | |
7054 this.element.removeClass( "ui-autocomplete-loading" ); | |
7055 } | |
7056 }, this ); | |
7057 }, | |
7058 | |
7059 __response: function( content ) { | |
7060 if ( content ) { | |
7061 content = this._normalize( content ); | |
7062 } | |
7063 this._trigger( "response", null, { content: content } ); | |
7064 if ( !this.options.disabled && content && content.length && !this.cancelSearch ) { | |
7065 this._suggest( content ); | |
7066 this._trigger( "open" ); | |
7067 } else { | |
7068 // use ._close() instead of .close() so we don't cancel future searches | |
7069 this._close(); | |
7070 } | |
7071 }, | |
7072 | |
7073 close: function( event ) { | |
7074 this.cancelSearch = true; | |
7075 this._close( event ); | |
7076 }, | |
7077 | |
7078 _close: function( event ) { | |
7079 if ( this.menu.element.is( ":visible" ) ) { | |
7080 this.menu.element.hide(); | |
7081 this.menu.blur(); | |
7082 this.isNewMenu = true; | |
7083 this._trigger( "close", event ); | |
7084 } | |
7085 }, | |
7086 | |
7087 _change: function( event ) { | |
7088 if ( this.previous !== this._value() ) { | |
7089 this._trigger( "change", event, { item: this.selectedItem } ); | |
7090 } | |
7091 }, | |
7092 | |
7093 _normalize: function( items ) { | |
7094 // assume all items have the right format when the first item is complete | |
7095 if ( items.length && items[0].label && items[0].value ) { | |
7096 return items; | |
7097 } | |
7098 return $.map( items, function( item ) { | |
7099 if ( typeof item === "string" ) { | |
7100 return { | |
7101 label: item, | |
7102 value: item | |
7103 }; | |
7104 } | |
7105 return $.extend({ | |
7106 label: item.label || item.value, | |
7107 value: item.value || item.label | |
7108 }, item ); | |
7109 }); | |
7110 }, | |
7111 | |
7112 _suggest: function( items ) { | |
7113 var ul = this.menu.element.empty(); | |
7114 this._renderMenu( ul, items ); | |
7115 this.isNewMenu = true; | |
7116 this.menu.refresh(); | |
7117 | |
7118 // size and position menu | |
7119 ul.show(); | |
7120 this._resizeMenu(); | |
7121 ul.position( $.extend({ | |
7122 of: this.element | |
7123 }, this.options.position )); | |
7124 | |
7125 if ( this.options.autoFocus ) { | |
7126 this.menu.next(); | |
7127 } | |
7128 }, | |
7129 | |
7130 _resizeMenu: function() { | |
7131 var ul = this.menu.element; | |
7132 ul.outerWidth( Math.max( | |
7133 // Firefox wraps long text (possibly a rounding bug) | |
7134 // so we add 1px to avoid the wrapping (#7513) | |
7135 ul.width( "" ).outerWidth() + 1, | |
7136 this.element.outerWidth() | |
7137 ) ); | |
7138 }, | |
7139 | |
7140 _renderMenu: function( ul, items ) { | |
7141 var that = this; | |
7142 $.each( items, function( index, item ) { | |
7143 that._renderItemData( ul, item ); | |
7144 }); | |
7145 }, | |
7146 | |
7147 _renderItemData: function( ul, item ) { | |
7148 return this._renderItem( ul, item ).data( "ui-autocomplete-item", item ); | |
7149 }, | |
7150 | |
7151 _renderItem: function( ul, item ) { | |
7152 return $( "<li>" ) | |
7153 .append( $( "<a>" ).text( item.label ) ) | |
7154 .appendTo( ul ); | |
7155 }, | |
7156 | |
7157 _move: function( direction, event ) { | |
7158 if ( !this.menu.element.is( ":visible" ) ) { | |
7159 this.search( null, event ); | |
7160 return; | |
7161 } | |
7162 if ( this.menu.isFirstItem() && /^previous/.test( direction ) || | |
7163 this.menu.isLastItem() && /^next/.test( direction ) ) { | |
7164 this._value( this.term ); | |
7165 this.menu.blur(); | |
7166 return; | |
7167 } | |
7168 this.menu[ direction ]( event ); | |
7169 }, | |
7170 | |
7171 widget: function() { | |
7172 return this.menu.element; | |
7173 }, | |
7174 | |
7175 _value: function() { | |
7176 return this.valueMethod.apply( this.element, arguments ); | |
7177 }, | |
7178 | |
7179 _keyEvent: function( keyEvent, event ) { | |
7180 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) { | |
7181 this._move( keyEvent, event ); | |
7182 | |
7183 // prevents moving cursor to beginning/end of the text field in some browsers | |
7184 event.preventDefault(); | |
7185 } | |
7186 } | |
7187 }); | |
7188 | |
7189 $.extend( $.ui.autocomplete, { | |
7190 escapeRegex: function( value ) { | |
7191 return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&"); | |
7192 }, | |
7193 filter: function(array, term) { | |
7194 var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" ); | |
7195 return $.grep( array, function(value) { | |
7196 return matcher.test( value.label || value.value || value ); | |
7197 }); | |
7198 } | |
7199 }); | |
7200 | |
7201 | |
7202 // live region extension, adding a `messages` option | |
7203 // NOTE: This is an experimental API. We are still investigating | |
7204 // a full solution for string manipulation and internationalization. | |
7205 $.widget( "ui.autocomplete", $.ui.autocomplete, { | |
7206 options: { | |
7207 messages: { | |
7208 noResults: "No search results.", | |
7209 results: function( amount ) { | |
7210 return amount + ( amount > 1 ? " results are" : " result is" ) + | |
7211 " available, use up and down arrow keys to navigate."; | |
7212 } | |
7213 } | |
7214 }, | |
7215 | |
7216 __response: function( content ) { | |
7217 var message; | |
7218 this._superApply( arguments ); | |
7219 if ( this.options.disabled || this.cancelSearch ) { | |
7220 return; | |
7221 } | |
7222 if ( content && content.length ) { | |
7223 message = this.options.messages.results( content.length ); | |
7224 } else { | |
7225 message = this.options.messages.noResults; | |
7226 } | |
7227 this.liveRegion.text( message ); | |
7228 } | |
7229 }); | |
7230 | |
7231 }( jQuery )); | |
7232 | |
7233 (function( $, undefined ) { | |
7234 | |
7235 var lastActive, | |
7236 baseClasses = "ui-button ui-widget ui-state-default ui-corner-all", | |
7237 typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only", | |
7238 formResetHandler = function() { | |
7239 var form = $( this ); | |
7240 setTimeout(function() { | |
7241 form.find( ":ui-button" ).button( "refresh" ); | |
7242 }, 1 ); | |
7243 }, | |
7244 radioGroup = function( radio ) { | |
7245 var name = radio.name, | |
7246 form = radio.form, | |
7247 radios = $( [] ); | |
7248 if ( name ) { | |
7249 name = name.replace( /'/g, "\\'" ); | |
7250 if ( form ) { | |
7251 radios = $( form ).find( "[name='" + name + "']" ); | |
7252 } else { | |
7253 radios = $( "[name='" + name + "']", radio.ownerDocument ) | |
7254 .filter(function() { | |
7255 return !this.form; | |
7256 }); | |
7257 } | |
7258 } | |
7259 return radios; | |
7260 }; | |
7261 | |
7262 $.widget( "ui.button", { | |
7263 version: "1.10.4", | |
7264 defaultElement: "<button>", | |
7265 options: { | |
7266 disabled: null, | |
7267 text: true, | |
7268 label: null, | |
7269 icons: { | |
7270 primary: null, | |
7271 secondary: null | |
7272 } | |
7273 }, | |
7274 _create: function() { | |
7275 this.element.closest( "form" ) | |
7276 .unbind( "reset" + this.eventNamespace ) | |
7277 .bind( "reset" + this.eventNamespace, formResetHandler ); | |
7278 | |
7279 if ( typeof this.options.disabled !== "boolean" ) { | |
7280 this.options.disabled = !!this.element.prop( "disabled" ); | |
7281 } else { | |
7282 this.element.prop( "disabled", this.options.disabled ); | |
7283 } | |
7284 | |
7285 this._determineButtonType(); | |
7286 this.hasTitle = !!this.buttonElement.attr( "title" ); | |
7287 | |
7288 var that = this, | |
7289 options = this.options, | |
7290 toggleButton = this.type === "checkbox" || this.type === "radio", | |
7291 activeClass = !toggleButton ? "ui-state-active" : ""; | |
7292 | |
7293 if ( options.label === null ) { | |
7294 options.label = (this.type === "input" ? this.buttonElement.val() : this.buttonElement.html()); | |
7295 } | |
7296 | |
7297 this._hoverable( this.buttonElement ); | |
7298 | |
7299 this.buttonElement | |
7300 .addClass( baseClasses ) | |
7301 .attr( "role", "button" ) | |
7302 .bind( "mouseenter" + this.eventNamespace, function() { | |
7303 if ( options.disabled ) { | |
7304 return; | |
7305 } | |
7306 if ( this === lastActive ) { | |
7307 $( this ).addClass( "ui-state-active" ); | |
7308 } | |
7309 }) | |
7310 .bind( "mouseleave" + this.eventNamespace, function() { | |
7311 if ( options.disabled ) { | |
7312 return; | |
7313 } | |
7314 $( this ).removeClass( activeClass ); | |
7315 }) | |
7316 .bind( "click" + this.eventNamespace, function( event ) { | |
7317 if ( options.disabled ) { | |
7318 event.preventDefault(); | |
7319 event.stopImmediatePropagation(); | |
7320 } | |
7321 }); | |
7322 | |
7323 // Can't use _focusable() because the element that receives focus | |
7324 // and the element that gets the ui-state-focus class are different | |
7325 this._on({ | |
7326 focus: function() { | |
7327 this.buttonElement.addClass( "ui-state-focus" ); | |
7328 }, | |
7329 blur: function() { | |
7330 this.buttonElement.removeClass( "ui-state-focus" ); | |
7331 } | |
7332 }); | |
7333 | |
7334 if ( toggleButton ) { | |
7335 this.element.bind( "change" + this.eventNamespace, function() { | |
7336 that.refresh(); | |
7337 }); | |
7338 } | |
7339 | |
7340 if ( this.type === "checkbox" ) { | |
7341 this.buttonElement.bind( "click" + this.eventNamespace, function() { | |
7342 if ( options.disabled ) { | |
7343 return false; | |
7344 } | |
7345 }); | |
7346 } else if ( this.type === "radio" ) { | |
7347 this.buttonElement.bind( "click" + this.eventNamespace, function() { | |
7348 if ( options.disabled ) { | |
7349 return false; | |
7350 } | |
7351 $( this ).addClass( "ui-state-active" ); | |
7352 that.buttonElement.attr( "aria-pressed", "true" ); | |
7353 | |
7354 var radio = that.element[ 0 ]; | |
7355 radioGroup( radio ) | |
7356 .not( radio ) | |
7357 .map(function() { | |
7358 return $( this ).button( "widget" )[ 0 ]; | |
7359 }) | |
7360 .removeClass( "ui-state-active" ) | |
7361 .attr( "aria-pressed", "false" ); | |
7362 }); | |
7363 } else { | |
7364 this.buttonElement | |
7365 .bind( "mousedown" + this.eventNamespace, function() { | |
7366 if ( options.disabled ) { | |
7367 return false; | |
7368 } | |
7369 $( this ).addClass( "ui-state-active" ); | |
7370 lastActive = this; | |
7371 that.document.one( "mouseup", function() { | |
7372 lastActive = null; | |
7373 }); | |
7374 }) | |
7375 .bind( "mouseup" + this.eventNamespace, function() { | |
7376 if ( options.disabled ) { | |
7377 return false; | |
7378 } | |
7379 $( this ).removeClass( "ui-state-active" ); | |
7380 }) | |
7381 .bind( "keydown" + this.eventNamespace, function(event) { | |
7382 if ( options.disabled ) { | |
7383 return false; | |
7384 } | |
7385 if ( event.keyCode === $.ui.keyCode.SPACE || event.keyCode === $.ui.keyCode.ENTER ) { | |
7386 $( this ).addClass( "ui-state-active" ); | |
7387 } | |
7388 }) | |
7389 // see #8559, we bind to blur here in case the button element loses | |
7390 // focus between keydown and keyup, it would be left in an "active" state | |
7391 .bind( "keyup" + this.eventNamespace + " blur" + this.eventNamespace, function() { | |
7392 $( this ).removeClass( "ui-state-active" ); | |
7393 }); | |
7394 | |
7395 if ( this.buttonElement.is("a") ) { | |
7396 this.buttonElement.keyup(function(event) { | |
7397 if ( event.keyCode === $.ui.keyCode.SPACE ) { | |
7398 // TODO pass through original event correctly (just as 2nd argument doesn't work) | |
7399 $( this ).click(); | |
7400 } | |
7401 }); | |
7402 } | |
7403 } | |
7404 | |
7405 // TODO: pull out $.Widget's handling for the disabled option into | |
7406 // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can | |
7407 // be overridden by individual plugins | |
7408 this._setOption( "disabled", options.disabled ); | |
7409 this._resetButton(); | |
7410 }, | |
7411 | |
7412 _determineButtonType: function() { | |
7413 var ancestor, labelSelector, checked; | |
7414 | |
7415 if ( this.element.is("[type=checkbox]") ) { | |
7416 this.type = "checkbox"; | |
7417 } else if ( this.element.is("[type=radio]") ) { | |
7418 this.type = "radio"; | |
7419 } else if ( this.element.is("input") ) { | |
7420 this.type = "input"; | |
7421 } else { | |
7422 this.type = "button"; | |
7423 } | |
7424 | |
7425 if ( this.type === "checkbox" || this.type === "radio" ) { | |
7426 // we don't search against the document in case the element | |
7427 // is disconnected from the DOM | |
7428 ancestor = this.element.parents().last(); | |
7429 labelSelector = "label[for='" + this.element.attr("id") + "']"; | |
7430 this.buttonElement = ancestor.find( labelSelector ); | |
7431 if ( !this.buttonElement.length ) { | |
7432 ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings(); | |
7433 this.buttonElement = ancestor.filter( labelSelector ); | |
7434 if ( !this.buttonElement.length ) { | |
7435 this.buttonElement = ancestor.find( labelSelector ); | |
7436 } | |
7437 } | |
7438 this.element.addClass( "ui-helper-hidden-accessible" ); | |
7439 | |
7440 checked = this.element.is( ":checked" ); | |
7441 if ( checked ) { | |
7442 this.buttonElement.addClass( "ui-state-active" ); | |
7443 } | |
7444 this.buttonElement.prop( "aria-pressed", checked ); | |
7445 } else { | |
7446 this.buttonElement = this.element; | |
7447 } | |
7448 }, | |
7449 | |
7450 widget: function() { | |
7451 return this.buttonElement; | |
7452 }, | |
7453 | |
7454 _destroy: function() { | |
7455 this.element | |
7456 .removeClass( "ui-helper-hidden-accessible" ); | |
7457 this.buttonElement | |
7458 .removeClass( baseClasses + " ui-state-active " + typeClasses ) | |
7459 .removeAttr( "role" ) | |
7460 .removeAttr( "aria-pressed" ) | |
7461 .html( this.buttonElement.find(".ui-button-text").html() ); | |
7462 | |
7463 if ( !this.hasTitle ) { | |
7464 this.buttonElement.removeAttr( "title" ); | |
7465 } | |
7466 }, | |
7467 | |
7468 _setOption: function( key, value ) { | |
7469 this._super( key, value ); | |
7470 if ( key === "disabled" ) { | |
7471 this.element.prop( "disabled", !!value ); | |
7472 if ( value ) { | |
7473 this.buttonElement.removeClass( "ui-state-focus" ); | |
7474 } | |
7475 return; | |
7476 } | |
7477 this._resetButton(); | |
7478 }, | |
7479 | |
7480 refresh: function() { | |
7481 //See #8237 & #8828 | |
7482 var isDisabled = this.element.is( "input, button" ) ? this.element.is( ":disabled" ) : this.element.hasClass( "ui-button-disabled" ); | |
7483 | |
7484 if ( isDisabled !== this.options.disabled ) { | |
7485 this._setOption( "disabled", isDisabled ); | |
7486 } | |
7487 if ( this.type === "radio" ) { | |
7488 radioGroup( this.element[0] ).each(function() { | |
7489 if ( $( this ).is( ":checked" ) ) { | |
7490 $( this ).button( "widget" ) | |
7491 .addClass( "ui-state-active" ) | |
7492 .attr( "aria-pressed", "true" ); | |
7493 } else { | |
7494 $( this ).button( "widget" ) | |
7495 .removeClass( "ui-state-active" ) | |
7496 .attr( "aria-pressed", "false" ); | |
7497 } | |
7498 }); | |
7499 } else if ( this.type === "checkbox" ) { | |
7500 if ( this.element.is( ":checked" ) ) { | |
7501 this.buttonElement | |
7502 .addClass( "ui-state-active" ) | |
7503 .attr( "aria-pressed", "true" ); | |
7504 } else { | |
7505 this.buttonElement | |
7506 .removeClass( "ui-state-active" ) | |
7507 .attr( "aria-pressed", "false" ); | |
7508 } | |
7509 } | |
7510 }, | |
7511 | |
7512 _resetButton: function() { | |
7513 if ( this.type === "input" ) { | |
7514 if ( this.options.label ) { | |
7515 this.element.val( this.options.label ); | |
7516 } | |
7517 return; | |
7518 } | |
7519 var buttonElement = this.buttonElement.removeClass( typeClasses ), | |
7520 buttonText = $( "<span></span>", this.document[0] ) | |
7521 .addClass( "ui-button-text" ) | |
7522 .html( this.options.label ) | |
7523 .appendTo( buttonElement.empty() ) | |
7524 .text(), | |
7525 icons = this.options.icons, | |
7526 multipleIcons = icons.primary && icons.secondary, | |
7527 buttonClasses = []; | |
7528 | |
7529 if ( icons.primary || icons.secondary ) { | |
7530 if ( this.options.text ) { | |
7531 buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) ); | |
7532 } | |
7533 | |
7534 if ( icons.primary ) { | |
7535 buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" ); | |
7536 } | |
7537 | |
7538 if ( icons.secondary ) { | |
7539 buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" ); | |
7540 } | |
7541 | |
7542 if ( !this.options.text ) { | |
7543 buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" ); | |
7544 | |
7545 if ( !this.hasTitle ) { | |
7546 buttonElement.attr( "title", $.trim( buttonText ) ); | |
7547 } | |
7548 } | |
7549 } else { | |
7550 buttonClasses.push( "ui-button-text-only" ); | |
7551 } | |
7552 buttonElement.addClass( buttonClasses.join( " " ) ); | |
7553 } | |
7554 }); | |
7555 | |
7556 $.widget( "ui.buttonset", { | |
7557 version: "1.10.4", | |
7558 options: { | |
7559 items: "button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)" | |
7560 }, | |
7561 | |
7562 _create: function() { | |
7563 this.element.addClass( "ui-buttonset" ); | |
7564 }, | |
7565 | |
7566 _init: function() { | |
7567 this.refresh(); | |
7568 }, | |
7569 | |
7570 _setOption: function( key, value ) { | |
7571 if ( key === "disabled" ) { | |
7572 this.buttons.button( "option", key, value ); | |
7573 } | |
7574 | |
7575 this._super( key, value ); | |
7576 }, | |
7577 | |
7578 refresh: function() { | |
7579 var rtl = this.element.css( "direction" ) === "rtl"; | |
7580 | |
7581 this.buttons = this.element.find( this.options.items ) | |
7582 .filter( ":ui-button" ) | |
7583 .button( "refresh" ) | |
7584 .end() | |
7585 .not( ":ui-button" ) | |
7586 .button() | |
7587 .end() | |
7588 .map(function() { | |
7589 return $( this ).button( "widget" )[ 0 ]; | |
7590 }) | |
7591 .removeClass( "ui-corner-all ui-corner-left ui-corner-right" ) | |
7592 .filter( ":first" ) | |
7593 .addClass( rtl ? "ui-corner-right" : "ui-corner-left" ) | |
7594 .end() | |
7595 .filter( ":last" ) | |
7596 .addClass( rtl ? "ui-corner-left" : "ui-corner-right" ) | |
7597 .end() | |
7598 .end(); | |
7599 }, | |
7600 | |
7601 _destroy: function() { | |
7602 this.element.removeClass( "ui-buttonset" ); | |
7603 this.buttons | |
7604 .map(function() { | |
7605 return $( this ).button( "widget" )[ 0 ]; | |
7606 }) | |
7607 .removeClass( "ui-corner-left ui-corner-right" ) | |
7608 .end() | |
7609 .button( "destroy" ); | |
7610 } | |
7611 }); | |
7612 | |
7613 }( jQuery ) ); | |
7614 | |
7615 (function( $, undefined ) { | |
7616 | |
7617 $.extend($.ui, { datepicker: { version: "1.10.4" } }); | |
7618 | |
7619 var PROP_NAME = "datepicker", | |
7620 instActive; | |
7621 | |
7622 /* Date picker manager. | |
7623 Use the singleton instance of this class, $.datepicker, to interact with the date picker. | |
7624 Settings for (groups of) date pickers are maintained in an instance object, | |
7625 allowing multiple different settings on the same page. */ | |
7626 | |
7627 function Datepicker() { | |
7628 this._curInst = null; // The current instance in use | |
7629 this._keyEvent = false; // If the last event was a key event | |
7630 this._disabledInputs = []; // List of date picker inputs that have been disabled | |
7631 this._datepickerShowing = false; // True if the popup picker is showing , false if not | |
7632 this._inDialog = false; // True if showing within a "dialog", false if not | |
7633 this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division | |
7634 this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class | |
7635 this._appendClass = "ui-datepicker-append"; // The name of the append marker class | |
7636 this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class | |
7637 this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class | |
7638 this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class | |
7639 this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class | |
7640 this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class | |
7641 this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class | |
7642 this.regional = []; // Available regional settings, indexed by language code | |
7643 this.regional[""] = { // Default regional settings | |
7644 closeText: "Done", // Display text for close link | |
7645 prevText: "Prev", // Display text for previous month link | |
7646 nextText: "Next", // Display text for next month link | |
7647 currentText: "Today", // Display text for current month link | |
7648 monthNames: ["January","February","March","April","May","June", | |
7649 "July","August","September","October","November","December"], // Names of months for drop-down and formatting | |
7650 monthNamesShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], // For formatting | |
7651 dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], // For formatting | |
7652 dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], // For formatting | |
7653 dayNamesMin: ["Su","Mo","Tu","We","Th","Fr","Sa"], // Column headings for days starting at Sunday | |
7654 weekHeader: "Wk", // Column header for week of the year | |
7655 dateFormat: "mm/dd/yy", // See format options on parseDate | |
7656 firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ... | |
7657 isRTL: false, // True if right-to-left language, false if left-to-right | |
7658 showMonthAfterYear: false, // True if the year select precedes month, false for month then year | |
7659 yearSuffix: "" // Additional text to append to the year in the month headers | |
7660 }; | |
7661 this._defaults = { // Global defaults for all the date picker instances | |
7662 showOn: "focus", // "focus" for popup on focus, | |
7663 // "button" for trigger button, or "both" for either | |
7664 showAnim: "fadeIn", // Name of jQuery animation for popup | |
7665 showOptions: {}, // Options for enhanced animations | |
7666 defaultDate: null, // Used when field is blank: actual date, | |
7667 // +/-number for offset from today, null for today | |
7668 appendText: "", // Display text following the input box, e.g. showing the format | |
7669 buttonText: "...", // Text for trigger button | |
7670 buttonImage: "", // URL for trigger button image | |
7671 buttonImageOnly: false, // True if the image appears alone, false if it appears on a button | |
7672 hideIfNoPrevNext: false, // True to hide next/previous month links | |
7673 // if not applicable, false to just disable them | |
7674 navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links | |
7675 gotoCurrent: false, // True if today link goes back to current selection instead | |
7676 changeMonth: false, // True if month can be selected directly, false if only prev/next | |
7677 changeYear: false, // True if year can be selected directly, false if only prev/next | |
7678 yearRange: "c-10:c+10", // Range of years to display in drop-down, | |
7679 // either relative to today's year (-nn:+nn), relative to currently displayed year | |
7680 // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n) | |
7681 showOtherMonths: false, // True to show dates in other months, false to leave blank | |
7682 selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable | |
7683 showWeek: false, // True to show week of the year, false to not show it | |
7684 calculateWeek: this.iso8601Week, // How to calculate the week of the year, | |
7685 // takes a Date and returns the number of the week for it | |
7686 shortYearCutoff: "+10", // Short year values < this are in the current century, | |
7687 // > this are in the previous century, | |
7688 // string value starting with "+" for current year + value | |
7689 minDate: null, // The earliest selectable date, or null for no limit | |
7690 maxDate: null, // The latest selectable date, or null for no limit | |
7691 duration: "fast", // Duration of display/closure | |
7692 beforeShowDay: null, // Function that takes a date and returns an array with | |
7693 // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "", | |
7694 // [2] = cell title (optional), e.g. $.datepicker.noWeekends | |
7695 beforeShow: null, // Function that takes an input field and | |
7696 // returns a set of custom settings for the date picker | |
7697 onSelect: null, // Define a callback function when a date is selected | |
7698 onChangeMonthYear: null, // Define a callback function when the month or year is changed | |
7699 onClose: null, // Define a callback function when the datepicker is closed | |
7700 numberOfMonths: 1, // Number of months to show at a time | |
7701 showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0) | |
7702 stepMonths: 1, // Number of months to step back/forward | |
7703 stepBigMonths: 12, // Number of months to step back/forward for the big links | |
7704 altField: "", // Selector for an alternate field to store selected dates into | |
7705 altFormat: "", // The date format to use for the alternate field | |
7706 constrainInput: true, // The input is constrained by the current date format | |
7707 showButtonPanel: false, // True to show button panel, false to not show it | |
7708 autoSize: false, // True to size the input for the date format, false to leave as is | |
7709 disabled: false // The initial disabled state | |
7710 }; | |
7711 $.extend(this._defaults, this.regional[""]); | |
7712 this.dpDiv = bindHover($("<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")); | |
7713 } | |
7714 | |
7715 $.extend(Datepicker.prototype, { | |
7716 /* Class name added to elements to indicate already configured with a date picker. */ | |
7717 markerClassName: "hasDatepicker", | |
7718 | |
7719 //Keep track of the maximum number of rows displayed (see #7043) | |
7720 maxRows: 4, | |
7721 | |
7722 // TODO rename to "widget" when switching to widget factory | |
7723 _widgetDatepicker: function() { | |
7724 return this.dpDiv; | |
7725 }, | |
7726 | |
7727 /* Override the default settings for all instances of the date picker. | |
7728 * @param settings object - the new settings to use as defaults (anonymous object) | |
7729 * @return the manager object | |
7730 */ | |
7731 setDefaults: function(settings) { | |
7732 extendRemove(this._defaults, settings || {}); | |
7733 return this; | |
7734 }, | |
7735 | |
7736 /* Attach the date picker to a jQuery selection. | |
7737 * @param target element - the target input field or division or span | |
7738 * @param settings object - the new settings to use for this date picker instance (anonymous) | |
7739 */ | |
7740 _attachDatepicker: function(target, settings) { | |
7741 var nodeName, inline, inst; | |
7742 nodeName = target.nodeName.toLowerCase(); | |
7743 inline = (nodeName === "div" || nodeName === "span"); | |
7744 if (!target.id) { | |
7745 this.uuid += 1; | |
7746 target.id = "dp" + this.uuid; | |
7747 } | |
7748 inst = this._newInst($(target), inline); | |
7749 inst.settings = $.extend({}, settings || {}); | |
7750 if (nodeName === "input") { | |
7751 this._connectDatepicker(target, inst); | |
7752 } else if (inline) { | |
7753 this._inlineDatepicker(target, inst); | |
7754 } | |
7755 }, | |
7756 | |
7757 /* Create a new instance object. */ | |
7758 _newInst: function(target, inline) { | |
7759 var id = target[0].id.replace(/([^A-Za-z0-9_\-])/g, "\\\\$1"); // escape jQuery meta chars | |
7760 return {id: id, input: target, // associated target | |
7761 selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection | |
7762 drawMonth: 0, drawYear: 0, // month being drawn | |
7763 inline: inline, // is datepicker inline or not | |
7764 dpDiv: (!inline ? this.dpDiv : // presentation div | |
7765 bindHover($("<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")))}; | |
7766 }, | |
7767 | |
7768 /* Attach the date picker to an input field. */ | |
7769 _connectDatepicker: function(target, inst) { | |
7770 var input = $(target); | |
7771 inst.append = $([]); | |
7772 inst.trigger = $([]); | |
7773 if (input.hasClass(this.markerClassName)) { | |
7774 return; | |
7775 } | |
7776 this._attachments(input, inst); | |
7777 input.addClass(this.markerClassName).keydown(this._doKeyDown). | |
7778 keypress(this._doKeyPress).keyup(this._doKeyUp); | |
7779 this._autoSize(inst); | |
7780 $.data(target, PROP_NAME, inst); | |
7781 //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665) | |
7782 if( inst.settings.disabled ) { | |
7783 this._disableDatepicker( target ); | |
7784 } | |
7785 }, | |
7786 | |
7787 /* Make attachments based on settings. */ | |
7788 _attachments: function(input, inst) { | |
7789 var showOn, buttonText, buttonImage, | |
7790 appendText = this._get(inst, "appendText"), | |
7791 isRTL = this._get(inst, "isRTL"); | |
7792 | |
7793 if (inst.append) { | |
7794 inst.append.remove(); | |
7795 } | |
7796 if (appendText) { | |
7797 inst.append = $("<span class='" + this._appendClass + "'>" + appendText + "</span>"); | |
7798 input[isRTL ? "before" : "after"](inst.append); | |
7799 } | |
7800 | |
7801 input.unbind("focus", this._showDatepicker); | |
7802 | |
7803 if (inst.trigger) { | |
7804 inst.trigger.remove(); | |
7805 } | |
7806 | |
7807 showOn = this._get(inst, "showOn"); | |
7808 if (showOn === "focus" || showOn === "both") { // pop-up date picker when in the marked field | |
7809 input.focus(this._showDatepicker); | |
7810 } | |
7811 if (showOn === "button" || showOn === "both") { // pop-up date picker when button clicked | |
7812 buttonText = this._get(inst, "buttonText"); | |
7813 buttonImage = this._get(inst, "buttonImage"); | |
7814 inst.trigger = $(this._get(inst, "buttonImageOnly") ? | |
7815 $("<img/>").addClass(this._triggerClass). | |
7816 attr({ src: buttonImage, alt: buttonText, title: buttonText }) : | |
7817 $("<button type='button'></button>").addClass(this._triggerClass). | |
7818 html(!buttonImage ? buttonText : $("<img/>").attr( | |
7819 { src:buttonImage, alt:buttonText, title:buttonText }))); | |
7820 input[isRTL ? "before" : "after"](inst.trigger); | |
7821 inst.trigger.click(function() { | |
7822 if ($.datepicker._datepickerShowing && $.datepicker._lastInput === input[0]) { | |
7823 $.datepicker._hideDatepicker(); | |
7824 } else if ($.datepicker._datepickerShowing && $.datepicker._lastInput !== input[0]) { | |
7825 $.datepicker._hideDatepicker(); | |
7826 $.datepicker._showDatepicker(input[0]); | |
7827 } else { | |
7828 $.datepicker._showDatepicker(input[0]); | |
7829 } | |
7830 return false; | |
7831 }); | |
7832 } | |
7833 }, | |
7834 | |
7835 /* Apply the maximum length for the date format. */ | |
7836 _autoSize: function(inst) { | |
7837 if (this._get(inst, "autoSize") && !inst.inline) { | |
7838 var findMax, max, maxI, i, | |
7839 date = new Date(2009, 12 - 1, 20), // Ensure double digits | |
7840 dateFormat = this._get(inst, "dateFormat"); | |
7841 | |
7842 if (dateFormat.match(/[DM]/)) { | |
7843 findMax = function(names) { | |
7844 max = 0; | |
7845 maxI = 0; | |
7846 for (i = 0; i < names.length; i++) { | |
7847 if (names[i].length > max) { | |
7848 max = names[i].length; | |
7849 maxI = i; | |
7850 } | |
7851 } | |
7852 return maxI; | |
7853 }; | |
7854 date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ? | |
7855 "monthNames" : "monthNamesShort")))); | |
7856 date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ? | |
7857 "dayNames" : "dayNamesShort"))) + 20 - date.getDay()); | |
7858 } | |
7859 inst.input.attr("size", this._formatDate(inst, date).length); | |
7860 } | |
7861 }, | |
7862 | |
7863 /* Attach an inline date picker to a div. */ | |
7864 _inlineDatepicker: function(target, inst) { | |
7865 var divSpan = $(target); | |
7866 if (divSpan.hasClass(this.markerClassName)) { | |
7867 return; | |
7868 } | |
7869 divSpan.addClass(this.markerClassName).append(inst.dpDiv); | |
7870 $.data(target, PROP_NAME, inst); | |
7871 this._setDate(inst, this._getDefaultDate(inst), true); | |
7872 this._updateDatepicker(inst); | |
7873 this._updateAlternate(inst); | |
7874 //If disabled option is true, disable the datepicker before showing it (see ticket #5665) | |
7875 if( inst.settings.disabled ) { | |
7876 this._disableDatepicker( target ); | |
7877 } | |
7878 // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements | |
7879 // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height | |
7880 inst.dpDiv.css( "display", "block" ); | |
7881 }, | |
7882 | |
7883 /* Pop-up the date picker in a "dialog" box. | |
7884 * @param input element - ignored | |
7885 * @param date string or Date - the initial date to display | |
7886 * @param onSelect function - the function to call when a date is selected | |
7887 * @param settings object - update the dialog date picker instance's settings (anonymous object) | |
7888 * @param pos int[2] - coordinates for the dialog's position within the screen or | |
7889 * event - with x/y coordinates or | |
7890 * leave empty for default (screen centre) | |
7891 * @return the manager object | |
7892 */ | |
7893 _dialogDatepicker: function(input, date, onSelect, settings, pos) { | |
7894 var id, browserWidth, browserHeight, scrollX, scrollY, | |
7895 inst = this._dialogInst; // internal instance | |
7896 | |
7897 if (!inst) { | |
7898 this.uuid += 1; | |
7899 id = "dp" + this.uuid; | |
7900 this._dialogInput = $("<input type='text' id='" + id + | |
7901 "' style='position: absolute; top: -100px; width: 0px;'/>"); | |
7902 this._dialogInput.keydown(this._doKeyDown); | |
7903 $("body").append(this._dialogInput); | |
7904 inst = this._dialogInst = this._newInst(this._dialogInput, false); | |
7905 inst.settings = {}; | |
7906 $.data(this._dialogInput[0], PROP_NAME, inst); | |
7907 } | |
7908 extendRemove(inst.settings, settings || {}); | |
7909 date = (date && date.constructor === Date ? this._formatDate(inst, date) : date); | |
7910 this._dialogInput.val(date); | |
7911 | |
7912 this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null); | |
7913 if (!this._pos) { | |
7914 browserWidth = document.documentElement.clientWidth; | |
7915 browserHeight = document.documentElement.clientHeight; | |
7916 scrollX = document.documentElement.scrollLeft || document.body.scrollLeft; | |
7917 scrollY = document.documentElement.scrollTop || document.body.scrollTop; | |
7918 this._pos = // should use actual width/height below | |
7919 [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY]; | |
7920 } | |
7921 | |
7922 // move input on screen for focus, but hidden behind dialog | |
7923 this._dialogInput.css("left", (this._pos[0] + 20) + "px").css("top", this._pos[1] + "px"); | |
7924 inst.settings.onSelect = onSelect; | |
7925 this._inDialog = true; | |
7926 this.dpDiv.addClass(this._dialogClass); | |
7927 this._showDatepicker(this._dialogInput[0]); | |
7928 if ($.blockUI) { | |
7929 $.blockUI(this.dpDiv); | |
7930 } | |
7931 $.data(this._dialogInput[0], PROP_NAME, inst); | |
7932 return this; | |
7933 }, | |
7934 | |
7935 /* Detach a datepicker from its control. | |
7936 * @param target element - the target input field or division or span | |
7937 */ | |
7938 _destroyDatepicker: function(target) { | |
7939 var nodeName, | |
7940 $target = $(target), | |
7941 inst = $.data(target, PROP_NAME); | |
7942 | |
7943 if (!$target.hasClass(this.markerClassName)) { | |
7944 return; | |
7945 } | |
7946 | |
7947 nodeName = target.nodeName.toLowerCase(); | |
7948 $.removeData(target, PROP_NAME); | |
7949 if (nodeName === "input") { | |
7950 inst.append.remove(); | |
7951 inst.trigger.remove(); | |
7952 $target.removeClass(this.markerClassName). | |
7953 unbind("focus", this._showDatepicker). | |
7954 unbind("keydown", this._doKeyDown). | |
7955 unbind("keypress", this._doKeyPress). | |
7956 unbind("keyup", this._doKeyUp); | |
7957 } else if (nodeName === "div" || nodeName === "span") { | |
7958 $target.removeClass(this.markerClassName).empty(); | |
7959 } | |
7960 }, | |
7961 | |
7962 /* Enable the date picker to a jQuery selection. | |
7963 * @param target element - the target input field or division or span | |
7964 */ | |
7965 _enableDatepicker: function(target) { | |
7966 var nodeName, inline, | |
7967 $target = $(target), | |
7968 inst = $.data(target, PROP_NAME); | |
7969 | |
7970 if (!$target.hasClass(this.markerClassName)) { | |
7971 return; | |
7972 } | |
7973 | |
7974 nodeName = target.nodeName.toLowerCase(); | |
7975 if (nodeName === "input") { | |
7976 target.disabled = false; | |
7977 inst.trigger.filter("button"). | |
7978 each(function() { this.disabled = false; }).end(). | |
7979 filter("img").css({opacity: "1.0", cursor: ""}); | |
7980 } else if (nodeName === "div" || nodeName === "span") { | |
7981 inline = $target.children("." + this._inlineClass); | |
7982 inline.children().removeClass("ui-state-disabled"); | |
7983 inline.find("select.ui-datepicker-month, select.ui-datepicker-year"). | |
7984 prop("disabled", false); | |
7985 } | |
7986 this._disabledInputs = $.map(this._disabledInputs, | |
7987 function(value) { return (value === target ? null : value); }); // delete entry | |
7988 }, | |
7989 | |
7990 /* Disable the date picker to a jQuery selection. | |
7991 * @param target element - the target input field or division or span | |
7992 */ | |
7993 _disableDatepicker: function(target) { | |
7994 var nodeName, inline, | |
7995 $target = $(target), | |
7996 inst = $.data(target, PROP_NAME); | |
7997 | |
7998 if (!$target.hasClass(this.markerClassName)) { | |
7999 return; | |
8000 } | |
8001 | |
8002 nodeName = target.nodeName.toLowerCase(); | |
8003 if (nodeName === "input") { | |
8004 target.disabled = true; | |
8005 inst.trigger.filter("button"). | |
8006 each(function() { this.disabled = true; }).end(). | |
8007 filter("img").css({opacity: "0.5", cursor: "default"}); | |
8008 } else if (nodeName === "div" || nodeName === "span") { | |
8009 inline = $target.children("." + this._inlineClass); | |
8010 inline.children().addClass("ui-state-disabled"); | |
8011 inline.find("select.ui-datepicker-month, select.ui-datepicker-year"). | |
8012 prop("disabled", true); | |
8013 } | |
8014 this._disabledInputs = $.map(this._disabledInputs, | |
8015 function(value) { return (value === target ? null : value); }); // delete entry | |
8016 this._disabledInputs[this._disabledInputs.length] = target; | |
8017 }, | |
8018 | |
8019 /* Is the first field in a jQuery collection disabled as a datepicker? | |
8020 * @param target element - the target input field or division or span | |
8021 * @return boolean - true if disabled, false if enabled | |
8022 */ | |
8023 _isDisabledDatepicker: function(target) { | |
8024 if (!target) { | |
8025 return false; | |
8026 } | |
8027 for (var i = 0; i < this._disabledInputs.length; i++) { | |
8028 if (this._disabledInputs[i] === target) { | |
8029 return true; | |
8030 } | |
8031 } | |
8032 return false; | |
8033 }, | |
8034 | |
8035 /* Retrieve the instance data for the target control. | |
8036 * @param target element - the target input field or division or span | |
8037 * @return object - the associated instance data | |
8038 * @throws error if a jQuery problem getting data | |
8039 */ | |
8040 _getInst: function(target) { | |
8041 try { | |
8042 return $.data(target, PROP_NAME); | |
8043 } | |
8044 catch (err) { | |
8045 throw "Missing instance data for this datepicker"; | |
8046 } | |
8047 }, | |
8048 | |
8049 /* Update or retrieve the settings for a date picker attached to an input field or division. | |
8050 * @param target element - the target input field or division or span | |
8051 * @param name object - the new settings to update or | |
8052 * string - the name of the setting to change or retrieve, | |
8053 * when retrieving also "all" for all instance settings or | |
8054 * "defaults" for all global defaults | |
8055 * @param value any - the new value for the setting | |
8056 * (omit if above is an object or to retrieve a value) | |
8057 */ | |
8058 _optionDatepicker: function(target, name, value) { | |
8059 var settings, date, minDate, maxDate, | |
8060 inst = this._getInst(target); | |
8061 | |
8062 if (arguments.length === 2 && typeof name === "string") { | |
8063 return (name === "defaults" ? $.extend({}, $.datepicker._defaults) : | |
8064 (inst ? (name === "all" ? $.extend({}, inst.settings) : | |
8065 this._get(inst, name)) : null)); | |
8066 } | |
8067 | |
8068 settings = name || {}; | |
8069 if (typeof name === "string") { | |
8070 settings = {}; | |
8071 settings[name] = value; | |
8072 } | |
8073 | |
8074 if (inst) { | |
8075 if (this._curInst === inst) { | |
8076 this._hideDatepicker(); | |
8077 } | |
8078 | |
8079 date = this._getDateDatepicker(target, true); | |
8080 minDate = this._getMinMaxDate(inst, "min"); | |
8081 maxDate = this._getMinMaxDate(inst, "max"); | |
8082 extendRemove(inst.settings, settings); | |
8083 // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided | |
8084 if (minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined) { | |
8085 inst.settings.minDate = this._formatDate(inst, minDate); | |
8086 } | |
8087 if (maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined) { | |
8088 inst.settings.maxDate = this._formatDate(inst, maxDate); | |
8089 } | |
8090 if ( "disabled" in settings ) { | |
8091 if ( settings.disabled ) { | |
8092 this._disableDatepicker(target); | |
8093 } else { | |
8094 this._enableDatepicker(target); | |
8095 } | |
8096 } | |
8097 this._attachments($(target), inst); | |
8098 this._autoSize(inst); | |
8099 this._setDate(inst, date); | |
8100 this._updateAlternate(inst); | |
8101 this._updateDatepicker(inst); | |
8102 } | |
8103 }, | |
8104 | |
8105 // change method deprecated | |
8106 _changeDatepicker: function(target, name, value) { | |
8107 this._optionDatepicker(target, name, value); | |
8108 }, | |
8109 | |
8110 /* Redraw the date picker attached to an input field or division. | |
8111 * @param target element - the target input field or division or span | |
8112 */ | |
8113 _refreshDatepicker: function(target) { | |
8114 var inst = this._getInst(target); | |
8115 if (inst) { | |
8116 this._updateDatepicker(inst); | |
8117 } | |
8118 }, | |
8119 | |
8120 /* Set the dates for a jQuery selection. | |
8121 * @param target element - the target input field or division or span | |
8122 * @param date Date - the new date | |
8123 */ | |
8124 _setDateDatepicker: function(target, date) { | |
8125 var inst = this._getInst(target); | |
8126 if (inst) { | |
8127 this._setDate(inst, date); | |
8128 this._updateDatepicker(inst); | |
8129 this._updateAlternate(inst); | |
8130 } | |
8131 }, | |
8132 | |
8133 /* Get the date(s) for the first entry in a jQuery selection. | |
8134 * @param target element - the target input field or division or span | |
8135 * @param noDefault boolean - true if no default date is to be used | |
8136 * @return Date - the current date | |
8137 */ | |
8138 _getDateDatepicker: function(target, noDefault) { | |
8139 var inst = this._getInst(target); | |
8140 if (inst && !inst.inline) { | |
8141 this._setDateFromField(inst, noDefault); | |
8142 } | |
8143 return (inst ? this._getDate(inst) : null); | |
8144 }, | |
8145 | |
8146 /* Handle keystrokes. */ | |
8147 _doKeyDown: function(event) { | |
8148 var onSelect, dateStr, sel, | |
8149 inst = $.datepicker._getInst(event.target), | |
8150 handled = true, | |
8151 isRTL = inst.dpDiv.is(".ui-datepicker-rtl"); | |
8152 | |
8153 inst._keyEvent = true; | |
8154 if ($.datepicker._datepickerShowing) { | |
8155 switch (event.keyCode) { | |
8156 case 9: $.datepicker._hideDatepicker(); | |
8157 handled = false; | |
8158 break; // hide on tab out | |
8159 case 13: sel = $("td." + $.datepicker._dayOverClass + ":not(." + | |
8160 $.datepicker._currentClass + ")", inst.dpDiv); | |
8161 if (sel[0]) { | |
8162 $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]); | |
8163 } | |
8164 | |
8165 onSelect = $.datepicker._get(inst, "onSelect"); | |
8166 if (onSelect) { | |
8167 dateStr = $.datepicker._formatDate(inst); | |
8168 | |
8169 // trigger custom callback | |
8170 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); | |
8171 } else { | |
8172 $.datepicker._hideDatepicker(); | |
8173 } | |
8174 | |
8175 return false; // don't submit the form | |
8176 case 27: $.datepicker._hideDatepicker(); | |
8177 break; // hide on escape | |
8178 case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ? | |
8179 -$.datepicker._get(inst, "stepBigMonths") : | |
8180 -$.datepicker._get(inst, "stepMonths")), "M"); | |
8181 break; // previous month/year on page up/+ ctrl | |
8182 case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ? | |
8183 +$.datepicker._get(inst, "stepBigMonths") : | |
8184 +$.datepicker._get(inst, "stepMonths")), "M"); | |
8185 break; // next month/year on page down/+ ctrl | |
8186 case 35: if (event.ctrlKey || event.metaKey) { | |
8187 $.datepicker._clearDate(event.target); | |
8188 } | |
8189 handled = event.ctrlKey || event.metaKey; | |
8190 break; // clear on ctrl or command +end | |
8191 case 36: if (event.ctrlKey || event.metaKey) { | |
8192 $.datepicker._gotoToday(event.target); | |
8193 } | |
8194 handled = event.ctrlKey || event.metaKey; | |
8195 break; // current on ctrl or command +home | |
8196 case 37: if (event.ctrlKey || event.metaKey) { | |
8197 $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), "D"); | |
8198 } | |
8199 handled = event.ctrlKey || event.metaKey; | |
8200 // -1 day on ctrl or command +left | |
8201 if (event.originalEvent.altKey) { | |
8202 $.datepicker._adjustDate(event.target, (event.ctrlKey ? | |
8203 -$.datepicker._get(inst, "stepBigMonths") : | |
8204 -$.datepicker._get(inst, "stepMonths")), "M"); | |
8205 } | |
8206 // next month/year on alt +left on Mac | |
8207 break; | |
8208 case 38: if (event.ctrlKey || event.metaKey) { | |
8209 $.datepicker._adjustDate(event.target, -7, "D"); | |
8210 } | |
8211 handled = event.ctrlKey || event.metaKey; | |
8212 break; // -1 week on ctrl or command +up | |
8213 case 39: if (event.ctrlKey || event.metaKey) { | |
8214 $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), "D"); | |
8215 } | |
8216 handled = event.ctrlKey || event.metaKey; | |
8217 // +1 day on ctrl or command +right | |
8218 if (event.originalEvent.altKey) { | |
8219 $.datepicker._adjustDate(event.target, (event.ctrlKey ? | |
8220 +$.datepicker._get(inst, "stepBigMonths") : | |
8221 +$.datepicker._get(inst, "stepMonths")), "M"); | |
8222 } | |
8223 // next month/year on alt +right | |
8224 break; | |
8225 case 40: if (event.ctrlKey || event.metaKey) { | |
8226 $.datepicker._adjustDate(event.target, +7, "D"); | |
8227 } | |
8228 handled = event.ctrlKey || event.metaKey; | |
8229 break; // +1 week on ctrl or command +down | |
8230 default: handled = false; | |
8231 } | |
8232 } else if (event.keyCode === 36 && event.ctrlKey) { // display the date picker on ctrl+home | |
8233 $.datepicker._showDatepicker(this); | |
8234 } else { | |
8235 handled = false; | |
8236 } | |
8237 | |
8238 if (handled) { | |
8239 event.preventDefault(); | |
8240 event.stopPropagation(); | |
8241 } | |
8242 }, | |
8243 | |
8244 /* Filter entered characters - based on date format. */ | |
8245 _doKeyPress: function(event) { | |
8246 var chars, chr, | |
8247 inst = $.datepicker._getInst(event.target); | |
8248 | |
8249 if ($.datepicker._get(inst, "constrainInput")) { | |
8250 chars = $.datepicker._possibleChars($.datepicker._get(inst, "dateFormat")); | |
8251 chr = String.fromCharCode(event.charCode == null ? event.keyCode : event.charCode); | |
8252 return event.ctrlKey || event.metaKey || (chr < " " || !chars || chars.indexOf(chr) > -1); | |
8253 } | |
8254 }, | |
8255 | |
8256 /* Synchronise manual entry and field/alternate field. */ | |
8257 _doKeyUp: function(event) { | |
8258 var date, | |
8259 inst = $.datepicker._getInst(event.target); | |
8260 | |
8261 if (inst.input.val() !== inst.lastVal) { | |
8262 try { | |
8263 date = $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"), | |
8264 (inst.input ? inst.input.val() : null), | |
8265 $.datepicker._getFormatConfig(inst)); | |
8266 | |
8267 if (date) { // only if valid | |
8268 $.datepicker._setDateFromField(inst); | |
8269 $.datepicker._updateAlternate(inst); | |
8270 $.datepicker._updateDatepicker(inst); | |
8271 } | |
8272 } | |
8273 catch (err) { | |
8274 } | |
8275 } | |
8276 return true; | |
8277 }, | |
8278 | |
8279 /* Pop-up the date picker for a given input field. | |
8280 * If false returned from beforeShow event handler do not show. | |
8281 * @param input element - the input field attached to the date picker or | |
8282 * event - if triggered by focus | |
8283 */ | |
8284 _showDatepicker: function(input) { | |
8285 input = input.target || input; | |
8286 if (input.nodeName.toLowerCase() !== "input") { // find from button/image trigger | |
8287 input = $("input", input.parentNode)[0]; | |
8288 } | |
8289 | |
8290 if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput === input) { // already here | |
8291 return; | |
8292 } | |
8293 | |
8294 var inst, beforeShow, beforeShowSettings, isFixed, | |
8295 offset, showAnim, duration; | |
8296 | |
8297 inst = $.datepicker._getInst(input); | |
8298 if ($.datepicker._curInst && $.datepicker._curInst !== inst) { | |
8299 $.datepicker._curInst.dpDiv.stop(true, true); | |
8300 if ( inst && $.datepicker._datepickerShowing ) { | |
8301 $.datepicker._hideDatepicker( $.datepicker._curInst.input[0] ); | |
8302 } | |
8303 } | |
8304 | |
8305 beforeShow = $.datepicker._get(inst, "beforeShow"); | |
8306 beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {}; | |
8307 if(beforeShowSettings === false){ | |
8308 return; | |
8309 } | |
8310 extendRemove(inst.settings, beforeShowSettings); | |
8311 | |
8312 inst.lastVal = null; | |
8313 $.datepicker._lastInput = input; | |
8314 $.datepicker._setDateFromField(inst); | |
8315 | |
8316 if ($.datepicker._inDialog) { // hide cursor | |
8317 input.value = ""; | |
8318 } | |
8319 if (!$.datepicker._pos) { // position below input | |
8320 $.datepicker._pos = $.datepicker._findPos(input); | |
8321 $.datepicker._pos[1] += input.offsetHeight; // add the height | |
8322 } | |
8323 | |
8324 isFixed = false; | |
8325 $(input).parents().each(function() { | |
8326 isFixed |= $(this).css("position") === "fixed"; | |
8327 return !isFixed; | |
8328 }); | |
8329 | |
8330 offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]}; | |
8331 $.datepicker._pos = null; | |
8332 //to avoid flashes on Firefox | |
8333 inst.dpDiv.empty(); | |
8334 // determine sizing offscreen | |
8335 inst.dpDiv.css({position: "absolute", display: "block", top: "-1000px"}); | |
8336 $.datepicker._updateDatepicker(inst); | |
8337 // fix width for dynamic number of date pickers | |
8338 // and adjust position before showing | |
8339 offset = $.datepicker._checkOffset(inst, offset, isFixed); | |
8340 inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ? | |
8341 "static" : (isFixed ? "fixed" : "absolute")), display: "none", | |
8342 left: offset.left + "px", top: offset.top + "px"}); | |
8343 | |
8344 if (!inst.inline) { | |
8345 showAnim = $.datepicker._get(inst, "showAnim"); | |
8346 duration = $.datepicker._get(inst, "duration"); | |
8347 inst.dpDiv.zIndex($(input).zIndex()+1); | |
8348 $.datepicker._datepickerShowing = true; | |
8349 | |
8350 if ( $.effects && $.effects.effect[ showAnim ] ) { | |
8351 inst.dpDiv.show(showAnim, $.datepicker._get(inst, "showOptions"), duration); | |
8352 } else { | |
8353 inst.dpDiv[showAnim || "show"](showAnim ? duration : null); | |
8354 } | |
8355 | |
8356 if ( $.datepicker._shouldFocusInput( inst ) ) { | |
8357 inst.input.focus(); | |
8358 } | |
8359 | |
8360 $.datepicker._curInst = inst; | |
8361 } | |
8362 }, | |
8363 | |
8364 /* Generate the date picker content. */ | |
8365 _updateDatepicker: function(inst) { | |
8366 this.maxRows = 4; //Reset the max number of rows being displayed (see #7043) | |
8367 instActive = inst; // for delegate hover events | |
8368 inst.dpDiv.empty().append(this._generateHTML(inst)); | |
8369 this._attachHandlers(inst); | |
8370 inst.dpDiv.find("." + this._dayOverClass + " a").mouseover(); | |
8371 | |
8372 var origyearshtml, | |
8373 numMonths = this._getNumberOfMonths(inst), | |
8374 cols = numMonths[1], | |
8375 width = 17; | |
8376 | |
8377 inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""); | |
8378 if (cols > 1) { | |
8379 inst.dpDiv.addClass("ui-datepicker-multi-" + cols).css("width", (width * cols) + "em"); | |
8380 } | |
8381 inst.dpDiv[(numMonths[0] !== 1 || numMonths[1] !== 1 ? "add" : "remove") + | |
8382 "Class"]("ui-datepicker-multi"); | |
8383 inst.dpDiv[(this._get(inst, "isRTL") ? "add" : "remove") + | |
8384 "Class"]("ui-datepicker-rtl"); | |
8385 | |
8386 if (inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) { | |
8387 inst.input.focus(); | |
8388 } | |
8389 | |
8390 // deffered render of the years select (to avoid flashes on Firefox) | |
8391 if( inst.yearshtml ){ | |
8392 origyearshtml = inst.yearshtml; | |
8393 setTimeout(function(){ | |
8394 //assure that inst.yearshtml didn't change. | |
8395 if( origyearshtml === inst.yearshtml && inst.yearshtml ){ | |
8396 inst.dpDiv.find("select.ui-datepicker-year:first").replaceWith(inst.yearshtml); | |
8397 } | |
8398 origyearshtml = inst.yearshtml = null; | |
8399 }, 0); | |
8400 } | |
8401 }, | |
8402 | |
8403 // #6694 - don't focus the input if it's already focused | |
8404 // this breaks the change event in IE | |
8405 // Support: IE and jQuery <1.9 | |
8406 _shouldFocusInput: function( inst ) { | |
8407 return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" ); | |
8408 }, | |
8409 | |
8410 /* Check positioning to remain on screen. */ | |
8411 _checkOffset: function(inst, offset, isFixed) { | |
8412 var dpWidth = inst.dpDiv.outerWidth(), | |
8413 dpHeight = inst.dpDiv.outerHeight(), | |
8414 inputWidth = inst.input ? inst.input.outerWidth() : 0, | |
8415 inputHeight = inst.input ? inst.input.outerHeight() : 0, | |
8416 viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft()), | |
8417 viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop()); | |
8418 | |
8419 offset.left -= (this._get(inst, "isRTL") ? (dpWidth - inputWidth) : 0); | |
8420 offset.left -= (isFixed && offset.left === inst.input.offset().left) ? $(document).scrollLeft() : 0; | |
8421 offset.top -= (isFixed && offset.top === (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0; | |
8422 | |
8423 // now check if datepicker is showing outside window viewport - move to a better place if so. | |
8424 offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ? | |
8425 Math.abs(offset.left + dpWidth - viewWidth) : 0); | |
8426 offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ? | |
8427 Math.abs(dpHeight + inputHeight) : 0); | |
8428 | |
8429 return offset; | |
8430 }, | |
8431 | |
8432 /* Find an object's position on the screen. */ | |
8433 _findPos: function(obj) { | |
8434 var position, | |
8435 inst = this._getInst(obj), | |
8436 isRTL = this._get(inst, "isRTL"); | |
8437 | |
8438 while (obj && (obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden(obj))) { | |
8439 obj = obj[isRTL ? "previousSibling" : "nextSibling"]; | |
8440 } | |
8441 | |
8442 position = $(obj).offset(); | |
8443 return [position.left, position.top]; | |
8444 }, | |
8445 | |
8446 /* Hide the date picker from view. | |
8447 * @param input element - the input field attached to the date picker | |
8448 */ | |
8449 _hideDatepicker: function(input) { | |
8450 var showAnim, duration, postProcess, onClose, | |
8451 inst = this._curInst; | |
8452 | |
8453 if (!inst || (input && inst !== $.data(input, PROP_NAME))) { | |
8454 return; | |
8455 } | |
8456 | |
8457 if (this._datepickerShowing) { | |
8458 showAnim = this._get(inst, "showAnim"); | |
8459 duration = this._get(inst, "duration"); | |
8460 postProcess = function() { | |
8461 $.datepicker._tidyDialog(inst); | |
8462 }; | |
8463 | |
8464 // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed | |
8465 if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) { | |
8466 inst.dpDiv.hide(showAnim, $.datepicker._get(inst, "showOptions"), duration, postProcess); | |
8467 } else { | |
8468 inst.dpDiv[(showAnim === "slideDown" ? "slideUp" : | |
8469 (showAnim === "fadeIn" ? "fadeOut" : "hide"))]((showAnim ? duration : null), postProcess); | |
8470 } | |
8471 | |
8472 if (!showAnim) { | |
8473 postProcess(); | |
8474 } | |
8475 this._datepickerShowing = false; | |
8476 | |
8477 onClose = this._get(inst, "onClose"); | |
8478 if (onClose) { | |
8479 onClose.apply((inst.input ? inst.input[0] : null), [(inst.input ? inst.input.val() : ""), inst]); | |
8480 } | |
8481 | |
8482 this._lastInput = null; | |
8483 if (this._inDialog) { | |
8484 this._dialogInput.css({ position: "absolute", left: "0", top: "-100px" }); | |
8485 if ($.blockUI) { | |
8486 $.unblockUI(); | |
8487 $("body").append(this.dpDiv); | |
8488 } | |
8489 } | |
8490 this._inDialog = false; | |
8491 } | |
8492 }, | |
8493 | |
8494 /* Tidy up after a dialog display. */ | |
8495 _tidyDialog: function(inst) { | |
8496 inst.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar"); | |
8497 }, | |
8498 | |
8499 /* Close date picker if clicked elsewhere. */ | |
8500 _checkExternalClick: function(event) { | |
8501 if (!$.datepicker._curInst) { | |
8502 return; | |
8503 } | |
8504 | |
8505 var $target = $(event.target), | |
8506 inst = $.datepicker._getInst($target[0]); | |
8507 | |
8508 if ( ( ( $target[0].id !== $.datepicker._mainDivId && | |
8509 $target.parents("#" + $.datepicker._mainDivId).length === 0 && | |
8510 !$target.hasClass($.datepicker.markerClassName) && | |
8511 !$target.closest("." + $.datepicker._triggerClass).length && | |
8512 $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) || | |
8513 ( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst !== inst ) ) { | |
8514 $.datepicker._hideDatepicker(); | |
8515 } | |
8516 }, | |
8517 | |
8518 /* Adjust one of the date sub-fields. */ | |
8519 _adjustDate: function(id, offset, period) { | |
8520 var target = $(id), | |
8521 inst = this._getInst(target[0]); | |
8522 | |
8523 if (this._isDisabledDatepicker(target[0])) { | |
8524 return; | |
8525 } | |
8526 this._adjustInstDate(inst, offset + | |
8527 (period === "M" ? this._get(inst, "showCurrentAtPos") : 0), // undo positioning | |
8528 period); | |
8529 this._updateDatepicker(inst); | |
8530 }, | |
8531 | |
8532 /* Action for current link. */ | |
8533 _gotoToday: function(id) { | |
8534 var date, | |
8535 target = $(id), | |
8536 inst = this._getInst(target[0]); | |
8537 | |
8538 if (this._get(inst, "gotoCurrent") && inst.currentDay) { | |
8539 inst.selectedDay = inst.currentDay; | |
8540 inst.drawMonth = inst.selectedMonth = inst.currentMonth; | |
8541 inst.drawYear = inst.selectedYear = inst.currentYear; | |
8542 } else { | |
8543 date = new Date(); | |
8544 inst.selectedDay = date.getDate(); | |
8545 inst.drawMonth = inst.selectedMonth = date.getMonth(); | |
8546 inst.drawYear = inst.selectedYear = date.getFullYear(); | |
8547 } | |
8548 this._notifyChange(inst); | |
8549 this._adjustDate(target); | |
8550 }, | |
8551 | |
8552 /* Action for selecting a new month/year. */ | |
8553 _selectMonthYear: function(id, select, period) { | |
8554 var target = $(id), | |
8555 inst = this._getInst(target[0]); | |
8556 | |
8557 inst["selected" + (period === "M" ? "Month" : "Year")] = | |
8558 inst["draw" + (period === "M" ? "Month" : "Year")] = | |
8559 parseInt(select.options[select.selectedIndex].value,10); | |
8560 | |
8561 this._notifyChange(inst); | |
8562 this._adjustDate(target); | |
8563 }, | |
8564 | |
8565 /* Action for selecting a day. */ | |
8566 _selectDay: function(id, month, year, td) { | |
8567 var inst, | |
8568 target = $(id); | |
8569 | |
8570 if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) { | |
8571 return; | |
8572 } | |
8573 | |
8574 inst = this._getInst(target[0]); | |
8575 inst.selectedDay = inst.currentDay = $("a", td).html(); | |
8576 inst.selectedMonth = inst.currentMonth = month; | |
8577 inst.selectedYear = inst.currentYear = year; | |
8578 this._selectDate(id, this._formatDate(inst, | |
8579 inst.currentDay, inst.currentMonth, inst.currentYear)); | |
8580 }, | |
8581 | |
8582 /* Erase the input field and hide the date picker. */ | |
8583 _clearDate: function(id) { | |
8584 var target = $(id); | |
8585 this._selectDate(target, ""); | |
8586 }, | |
8587 | |
8588 /* Update the input field with the selected date. */ | |
8589 _selectDate: function(id, dateStr) { | |
8590 var onSelect, | |
8591 target = $(id), | |
8592 inst = this._getInst(target[0]); | |
8593 | |
8594 dateStr = (dateStr != null ? dateStr : this._formatDate(inst)); | |
8595 if (inst.input) { | |
8596 inst.input.val(dateStr); | |
8597 } | |
8598 this._updateAlternate(inst); | |
8599 | |
8600 onSelect = this._get(inst, "onSelect"); | |
8601 if (onSelect) { | |
8602 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback | |
8603 } else if (inst.input) { | |
8604 inst.input.trigger("change"); // fire the change event | |
8605 } | |
8606 | |
8607 if (inst.inline){ | |
8608 this._updateDatepicker(inst); | |
8609 } else { | |
8610 this._hideDatepicker(); | |
8611 this._lastInput = inst.input[0]; | |
8612 if (typeof(inst.input[0]) !== "object") { | |
8613 inst.input.focus(); // restore focus | |
8614 } | |
8615 this._lastInput = null; | |
8616 } | |
8617 }, | |
8618 | |
8619 /* Update any alternate field to synchronise with the main field. */ | |
8620 _updateAlternate: function(inst) { | |
8621 var altFormat, date, dateStr, | |
8622 altField = this._get(inst, "altField"); | |
8623 | |
8624 if (altField) { // update alternate field too | |
8625 altFormat = this._get(inst, "altFormat") || this._get(inst, "dateFormat"); | |
8626 date = this._getDate(inst); | |
8627 dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst)); | |
8628 $(altField).each(function() { $(this).val(dateStr); }); | |
8629 } | |
8630 }, | |
8631 | |
8632 /* Set as beforeShowDay function to prevent selection of weekends. | |
8633 * @param date Date - the date to customise | |
8634 * @return [boolean, string] - is this date selectable?, what is its CSS class? | |
8635 */ | |
8636 noWeekends: function(date) { | |
8637 var day = date.getDay(); | |
8638 return [(day > 0 && day < 6), ""]; | |
8639 }, | |
8640 | |
8641 /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition. | |
8642 * @param date Date - the date to get the week for | |
8643 * @return number - the number of the week within the year that contains this date | |
8644 */ | |
8645 iso8601Week: function(date) { | |
8646 var time, | |
8647 checkDate = new Date(date.getTime()); | |
8648 | |
8649 // Find Thursday of this week starting on Monday | |
8650 checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); | |
8651 | |
8652 time = checkDate.getTime(); | |
8653 checkDate.setMonth(0); // Compare with Jan 1 | |
8654 checkDate.setDate(1); | |
8655 return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1; | |
8656 }, | |
8657 | |
8658 /* Parse a string value into a date object. | |
8659 * See formatDate below for the possible formats. | |
8660 * | |
8661 * @param format string - the expected format of the date | |
8662 * @param value string - the date in the above format | |
8663 * @param settings Object - attributes include: | |
8664 * shortYearCutoff number - the cutoff year for determining the century (optional) | |
8665 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) | |
8666 * dayNames string[7] - names of the days from Sunday (optional) | |
8667 * monthNamesShort string[12] - abbreviated names of the months (optional) | |
8668 * monthNames string[12] - names of the months (optional) | |
8669 * @return Date - the extracted date value or null if value is blank | |
8670 */ | |
8671 parseDate: function (format, value, settings) { | |
8672 if (format == null || value == null) { | |
8673 throw "Invalid arguments"; | |
8674 } | |
8675 | |
8676 value = (typeof value === "object" ? value.toString() : value + ""); | |
8677 if (value === "") { | |
8678 return null; | |
8679 } | |
8680 | |
8681 var iFormat, dim, extra, | |
8682 iValue = 0, | |
8683 shortYearCutoffTemp = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff, | |
8684 shortYearCutoff = (typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp : | |
8685 new Date().getFullYear() % 100 + parseInt(shortYearCutoffTemp, 10)), | |
8686 dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort, | |
8687 dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames, | |
8688 monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort, | |
8689 monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames, | |
8690 year = -1, | |
8691 month = -1, | |
8692 day = -1, | |
8693 doy = -1, | |
8694 literal = false, | |
8695 date, | |
8696 // Check whether a format character is doubled | |
8697 lookAhead = function(match) { | |
8698 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match); | |
8699 if (matches) { | |
8700 iFormat++; | |
8701 } | |
8702 return matches; | |
8703 }, | |
8704 // Extract a number from the string value | |
8705 getNumber = function(match) { | |
8706 var isDoubled = lookAhead(match), | |
8707 size = (match === "@" ? 14 : (match === "!" ? 20 : | |
8708 (match === "y" && isDoubled ? 4 : (match === "o" ? 3 : 2)))), | |
8709 digits = new RegExp("^\\d{1," + size + "}"), | |
8710 num = value.substring(iValue).match(digits); | |
8711 if (!num) { | |
8712 throw "Missing number at position " + iValue; | |
8713 } | |
8714 iValue += num[0].length; | |
8715 return parseInt(num[0], 10); | |
8716 }, | |
8717 // Extract a name from the string value and convert to an index | |
8718 getName = function(match, shortNames, longNames) { | |
8719 var index = -1, | |
8720 names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) { | |
8721 return [ [k, v] ]; | |
8722 }).sort(function (a, b) { | |
8723 return -(a[1].length - b[1].length); | |
8724 }); | |
8725 | |
8726 $.each(names, function (i, pair) { | |
8727 var name = pair[1]; | |
8728 if (value.substr(iValue, name.length).toLowerCase() === name.toLowerCase()) { | |
8729 index = pair[0]; | |
8730 iValue += name.length; | |
8731 return false; | |
8732 } | |
8733 }); | |
8734 if (index !== -1) { | |
8735 return index + 1; | |
8736 } else { | |
8737 throw "Unknown name at position " + iValue; | |
8738 } | |
8739 }, | |
8740 // Confirm that a literal character matches the string value | |
8741 checkLiteral = function() { | |
8742 if (value.charAt(iValue) !== format.charAt(iFormat)) { | |
8743 throw "Unexpected literal at position " + iValue; | |
8744 } | |
8745 iValue++; | |
8746 }; | |
8747 | |
8748 for (iFormat = 0; iFormat < format.length; iFormat++) { | |
8749 if (literal) { | |
8750 if (format.charAt(iFormat) === "'" && !lookAhead("'")) { | |
8751 literal = false; | |
8752 } else { | |
8753 checkLiteral(); | |
8754 } | |
8755 } else { | |
8756 switch (format.charAt(iFormat)) { | |
8757 case "d": | |
8758 day = getNumber("d"); | |
8759 break; | |
8760 case "D": | |
8761 getName("D", dayNamesShort, dayNames); | |
8762 break; | |
8763 case "o": | |
8764 doy = getNumber("o"); | |
8765 break; | |
8766 case "m": | |
8767 month = getNumber("m"); | |
8768 break; | |
8769 case "M": | |
8770 month = getName("M", monthNamesShort, monthNames); | |
8771 break; | |
8772 case "y": | |
8773 year = getNumber("y"); | |
8774 break; | |
8775 case "@": | |
8776 date = new Date(getNumber("@")); | |
8777 year = date.getFullYear(); | |
8778 month = date.getMonth() + 1; | |
8779 day = date.getDate(); | |
8780 break; | |
8781 case "!": | |
8782 date = new Date((getNumber("!") - this._ticksTo1970) / 10000); | |
8783 year = date.getFullYear(); | |
8784 month = date.getMonth() + 1; | |
8785 day = date.getDate(); | |
8786 break; | |
8787 case "'": | |
8788 if (lookAhead("'")){ | |
8789 checkLiteral(); | |
8790 } else { | |
8791 literal = true; | |
8792 } | |
8793 break; | |
8794 default: | |
8795 checkLiteral(); | |
8796 } | |
8797 } | |
8798 } | |
8799 | |
8800 if (iValue < value.length){ | |
8801 extra = value.substr(iValue); | |
8802 if (!/^\s+/.test(extra)) { | |
8803 throw "Extra/unparsed characters found in date: " + extra; | |
8804 } | |
8805 } | |
8806 | |
8807 if (year === -1) { | |
8808 year = new Date().getFullYear(); | |
8809 } else if (year < 100) { | |
8810 year += new Date().getFullYear() - new Date().getFullYear() % 100 + | |
8811 (year <= shortYearCutoff ? 0 : -100); | |
8812 } | |
8813 | |
8814 if (doy > -1) { | |
8815 month = 1; | |
8816 day = doy; | |
8817 do { | |
8818 dim = this._getDaysInMonth(year, month - 1); | |
8819 if (day <= dim) { | |
8820 break; | |
8821 } | |
8822 month++; | |
8823 day -= dim; | |
8824 } while (true); | |
8825 } | |
8826 | |
8827 date = this._daylightSavingAdjust(new Date(year, month - 1, day)); | |
8828 if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) { | |
8829 throw "Invalid date"; // E.g. 31/02/00 | |
8830 } | |
8831 return date; | |
8832 }, | |
8833 | |
8834 /* Standard date formats. */ | |
8835 ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601) | |
8836 COOKIE: "D, dd M yy", | |
8837 ISO_8601: "yy-mm-dd", | |
8838 RFC_822: "D, d M y", | |
8839 RFC_850: "DD, dd-M-y", | |
8840 RFC_1036: "D, d M y", | |
8841 RFC_1123: "D, d M yy", | |
8842 RFC_2822: "D, d M yy", | |
8843 RSS: "D, d M y", // RFC 822 | |
8844 TICKS: "!", | |
8845 TIMESTAMP: "@", | |
8846 W3C: "yy-mm-dd", // ISO 8601 | |
8847 | |
8848 _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) + | |
8849 Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000), | |
8850 | |
8851 /* Format a date object into a string value. | |
8852 * The format can be combinations of the following: | |
8853 * d - day of month (no leading zero) | |
8854 * dd - day of month (two digit) | |
8855 * o - day of year (no leading zeros) | |
8856 * oo - day of year (three digit) | |
8857 * D - day name short | |
8858 * DD - day name long | |
8859 * m - month of year (no leading zero) | |
8860 * mm - month of year (two digit) | |
8861 * M - month name short | |
8862 * MM - month name long | |
8863 * y - year (two digit) | |
8864 * yy - year (four digit) | |
8865 * @ - Unix timestamp (ms since 01/01/1970) | |
8866 * ! - Windows ticks (100ns since 01/01/0001) | |
8867 * "..." - literal text | |
8868 * '' - single quote | |
8869 * | |
8870 * @param format string - the desired format of the date | |
8871 * @param date Date - the date value to format | |
8872 * @param settings Object - attributes include: | |
8873 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) | |
8874 * dayNames string[7] - names of the days from Sunday (optional) | |
8875 * monthNamesShort string[12] - abbreviated names of the months (optional) | |
8876 * monthNames string[12] - names of the months (optional) | |
8877 * @return string - the date in the above format | |
8878 */ | |
8879 formatDate: function (format, date, settings) { | |
8880 if (!date) { | |
8881 return ""; | |
8882 } | |
8883 | |
8884 var iFormat, | |
8885 dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort, | |
8886 dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames, | |
8887 monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort, | |
8888 monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames, | |
8889 // Check whether a format character is doubled | |
8890 lookAhead = function(match) { | |
8891 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match); | |
8892 if (matches) { | |
8893 iFormat++; | |
8894 } | |
8895 return matches; | |
8896 }, | |
8897 // Format a number, with leading zero if necessary | |
8898 formatNumber = function(match, value, len) { | |
8899 var num = "" + value; | |
8900 if (lookAhead(match)) { | |
8901 while (num.length < len) { | |
8902 num = "0" + num; | |
8903 } | |
8904 } | |
8905 return num; | |
8906 }, | |
8907 // Format a name, short or long as requested | |
8908 formatName = function(match, value, shortNames, longNames) { | |
8909 return (lookAhead(match) ? longNames[value] : shortNames[value]); | |
8910 }, | |
8911 output = "", | |
8912 literal = false; | |
8913 | |
8914 if (date) { | |
8915 for (iFormat = 0; iFormat < format.length; iFormat++) { | |
8916 if (literal) { | |
8917 if (format.charAt(iFormat) === "'" && !lookAhead("'")) { | |
8918 literal = false; | |
8919 } else { | |
8920 output += format.charAt(iFormat); | |
8921 } | |
8922 } else { | |
8923 switch (format.charAt(iFormat)) { | |
8924 case "d": | |
8925 output += formatNumber("d", date.getDate(), 2); | |
8926 break; | |
8927 case "D": | |
8928 output += formatName("D", date.getDay(), dayNamesShort, dayNames); | |
8929 break; | |
8930 case "o": | |
8931 output += formatNumber("o", | |
8932 Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3); | |
8933 break; | |
8934 case "m": | |
8935 output += formatNumber("m", date.getMonth() + 1, 2); | |
8936 break; | |
8937 case "M": | |
8938 output += formatName("M", date.getMonth(), monthNamesShort, monthNames); | |
8939 break; | |
8940 case "y": | |
8941 output += (lookAhead("y") ? date.getFullYear() : | |
8942 (date.getYear() % 100 < 10 ? "0" : "") + date.getYear() % 100); | |
8943 break; | |
8944 case "@": | |
8945 output += date.getTime(); | |
8946 break; | |
8947 case "!": | |
8948 output += date.getTime() * 10000 + this._ticksTo1970; | |
8949 break; | |
8950 case "'": | |
8951 if (lookAhead("'")) { | |
8952 output += "'"; | |
8953 } else { | |
8954 literal = true; | |
8955 } | |
8956 break; | |
8957 default: | |
8958 output += format.charAt(iFormat); | |
8959 } | |
8960 } | |
8961 } | |
8962 } | |
8963 return output; | |
8964 }, | |
8965 | |
8966 /* Extract all possible characters from the date format. */ | |
8967 _possibleChars: function (format) { | |
8968 var iFormat, | |
8969 chars = "", | |
8970 literal = false, | |
8971 // Check whether a format character is doubled | |
8972 lookAhead = function(match) { | |
8973 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match); | |
8974 if (matches) { | |
8975 iFormat++; | |
8976 } | |
8977 return matches; | |
8978 }; | |
8979 | |
8980 for (iFormat = 0; iFormat < format.length; iFormat++) { | |
8981 if (literal) { | |
8982 if (format.charAt(iFormat) === "'" && !lookAhead("'")) { | |
8983 literal = false; | |
8984 } else { | |
8985 chars += format.charAt(iFormat); | |
8986 } | |
8987 } else { | |
8988 switch (format.charAt(iFormat)) { | |
8989 case "d": case "m": case "y": case "@": | |
8990 chars += "0123456789"; | |
8991 break; | |
8992 case "D": case "M": | |
8993 return null; // Accept anything | |
8994 case "'": | |
8995 if (lookAhead("'")) { | |
8996 chars += "'"; | |
8997 } else { | |
8998 literal = true; | |
8999 } | |
9000 break; | |
9001 default: | |
9002 chars += format.charAt(iFormat); | |
9003 } | |
9004 } | |
9005 } | |
9006 return chars; | |
9007 }, | |
9008 | |
9009 /* Get a setting value, defaulting if necessary. */ | |
9010 _get: function(inst, name) { | |
9011 return inst.settings[name] !== undefined ? | |
9012 inst.settings[name] : this._defaults[name]; | |
9013 }, | |
9014 | |
9015 /* Parse existing date and initialise date picker. */ | |
9016 _setDateFromField: function(inst, noDefault) { | |
9017 if (inst.input.val() === inst.lastVal) { | |
9018 return; | |
9019 } | |
9020 | |
9021 var dateFormat = this._get(inst, "dateFormat"), | |
9022 dates = inst.lastVal = inst.input ? inst.input.val() : null, | |
9023 defaultDate = this._getDefaultDate(inst), | |
9024 date = defaultDate, | |
9025 settings = this._getFormatConfig(inst); | |
9026 | |
9027 try { | |
9028 date = this.parseDate(dateFormat, dates, settings) || defaultDate; | |
9029 } catch (event) { | |
9030 dates = (noDefault ? "" : dates); | |
9031 } | |
9032 inst.selectedDay = date.getDate(); | |
9033 inst.drawMonth = inst.selectedMonth = date.getMonth(); | |
9034 inst.drawYear = inst.selectedYear = date.getFullYear(); | |
9035 inst.currentDay = (dates ? date.getDate() : 0); | |
9036 inst.currentMonth = (dates ? date.getMonth() : 0); | |
9037 inst.currentYear = (dates ? date.getFullYear() : 0); | |
9038 this._adjustInstDate(inst); | |
9039 }, | |
9040 | |
9041 /* Retrieve the default date shown on opening. */ | |
9042 _getDefaultDate: function(inst) { | |
9043 return this._restrictMinMax(inst, | |
9044 this._determineDate(inst, this._get(inst, "defaultDate"), new Date())); | |
9045 }, | |
9046 | |
9047 /* A date may be specified as an exact value or a relative one. */ | |
9048 _determineDate: function(inst, date, defaultDate) { | |
9049 var offsetNumeric = function(offset) { | |
9050 var date = new Date(); | |
9051 date.setDate(date.getDate() + offset); | |
9052 return date; | |
9053 }, | |
9054 offsetString = function(offset) { | |
9055 try { | |
9056 return $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"), | |
9057 offset, $.datepicker._getFormatConfig(inst)); | |
9058 } | |
9059 catch (e) { | |
9060 // Ignore | |
9061 } | |
9062 | |
9063 var date = (offset.toLowerCase().match(/^c/) ? | |
9064 $.datepicker._getDate(inst) : null) || new Date(), | |
9065 year = date.getFullYear(), | |
9066 month = date.getMonth(), | |
9067 day = date.getDate(), | |
9068 pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g, | |
9069 matches = pattern.exec(offset); | |
9070 | |
9071 while (matches) { | |
9072 switch (matches[2] || "d") { | |
9073 case "d" : case "D" : | |
9074 day += parseInt(matches[1],10); break; | |
9075 case "w" : case "W" : | |
9076 day += parseInt(matches[1],10) * 7; break; | |
9077 case "m" : case "M" : | |
9078 month += parseInt(matches[1],10); | |
9079 day = Math.min(day, $.datepicker._getDaysInMonth(year, month)); | |
9080 break; | |
9081 case "y": case "Y" : | |
9082 year += parseInt(matches[1],10); | |
9083 day = Math.min(day, $.datepicker._getDaysInMonth(year, month)); | |
9084 break; | |
9085 } | |
9086 matches = pattern.exec(offset); | |
9087 } | |
9088 return new Date(year, month, day); | |
9089 }, | |
9090 newDate = (date == null || date === "" ? defaultDate : (typeof date === "string" ? offsetString(date) : | |
9091 (typeof date === "number" ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime())))); | |
9092 | |
9093 newDate = (newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate); | |
9094 if (newDate) { | |
9095 newDate.setHours(0); | |
9096 newDate.setMinutes(0); | |
9097 newDate.setSeconds(0); | |
9098 newDate.setMilliseconds(0); | |
9099 } | |
9100 return this._daylightSavingAdjust(newDate); | |
9101 }, | |
9102 | |
9103 /* Handle switch to/from daylight saving. | |
9104 * Hours may be non-zero on daylight saving cut-over: | |
9105 * > 12 when midnight changeover, but then cannot generate | |
9106 * midnight datetime, so jump to 1AM, otherwise reset. | |
9107 * @param date (Date) the date to check | |
9108 * @return (Date) the corrected date | |
9109 */ | |
9110 _daylightSavingAdjust: function(date) { | |
9111 if (!date) { | |
9112 return null; | |
9113 } | |
9114 date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0); | |
9115 return date; | |
9116 }, | |
9117 | |
9118 /* Set the date(s) directly. */ | |
9119 _setDate: function(inst, date, noChange) { | |
9120 var clear = !date, | |
9121 origMonth = inst.selectedMonth, | |
9122 origYear = inst.selectedYear, | |
9123 newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date())); | |
9124 | |
9125 inst.selectedDay = inst.currentDay = newDate.getDate(); | |
9126 inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth(); | |
9127 inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear(); | |
9128 if ((origMonth !== inst.selectedMonth || origYear !== inst.selectedYear) && !noChange) { | |
9129 this._notifyChange(inst); | |
9130 } | |
9131 this._adjustInstDate(inst); | |
9132 if (inst.input) { | |
9133 inst.input.val(clear ? "" : this._formatDate(inst)); | |
9134 } | |
9135 }, | |
9136 | |
9137 /* Retrieve the date(s) directly. */ | |
9138 _getDate: function(inst) { | |
9139 var startDate = (!inst.currentYear || (inst.input && inst.input.val() === "") ? null : | |
9140 this._daylightSavingAdjust(new Date( | |
9141 inst.currentYear, inst.currentMonth, inst.currentDay))); | |
9142 return startDate; | |
9143 }, | |
9144 | |
9145 /* Attach the onxxx handlers. These are declared statically so | |
9146 * they work with static code transformers like Caja. | |
9147 */ | |
9148 _attachHandlers: function(inst) { | |
9149 var stepMonths = this._get(inst, "stepMonths"), | |
9150 id = "#" + inst.id.replace( /\\\\/g, "\\" ); | |
9151 inst.dpDiv.find("[data-handler]").map(function () { | |
9152 var handler = { | |
9153 prev: function () { | |
9154 $.datepicker._adjustDate(id, -stepMonths, "M"); | |
9155 }, | |
9156 next: function () { | |
9157 $.datepicker._adjustDate(id, +stepMonths, "M"); | |
9158 }, | |
9159 hide: function () { | |
9160 $.datepicker._hideDatepicker(); | |
9161 }, | |
9162 today: function () { | |
9163 $.datepicker._gotoToday(id); | |
9164 }, | |
9165 selectDay: function () { | |
9166 $.datepicker._selectDay(id, +this.getAttribute("data-month"), +this.getAttribute("data-year"), this); | |
9167 return false; | |
9168 }, | |
9169 selectMonth: function () { | |
9170 $.datepicker._selectMonthYear(id, this, "M"); | |
9171 return false; | |
9172 }, | |
9173 selectYear: function () { | |
9174 $.datepicker._selectMonthYear(id, this, "Y"); | |
9175 return false; | |
9176 } | |
9177 }; | |
9178 $(this).bind(this.getAttribute("data-event"), handler[this.getAttribute("data-handler")]); | |
9179 }); | |
9180 }, | |
9181 | |
9182 /* Generate the HTML for the current state of the date picker. */ | |
9183 _generateHTML: function(inst) { | |
9184 var maxDraw, prevText, prev, nextText, next, currentText, gotoDate, | |
9185 controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin, | |
9186 monthNames, monthNamesShort, beforeShowDay, showOtherMonths, | |
9187 selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate, | |
9188 cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows, | |
9189 printDate, dRow, tbody, daySettings, otherMonth, unselectable, | |
9190 tempDate = new Date(), | |
9191 today = this._daylightSavingAdjust( | |
9192 new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate())), // clear time | |
9193 isRTL = this._get(inst, "isRTL"), | |
9194 showButtonPanel = this._get(inst, "showButtonPanel"), | |
9195 hideIfNoPrevNext = this._get(inst, "hideIfNoPrevNext"), | |
9196 navigationAsDateFormat = this._get(inst, "navigationAsDateFormat"), | |
9197 numMonths = this._getNumberOfMonths(inst), | |
9198 showCurrentAtPos = this._get(inst, "showCurrentAtPos"), | |
9199 stepMonths = this._get(inst, "stepMonths"), | |
9200 isMultiMonth = (numMonths[0] !== 1 || numMonths[1] !== 1), | |
9201 currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) : | |
9202 new Date(inst.currentYear, inst.currentMonth, inst.currentDay))), | |
9203 minDate = this._getMinMaxDate(inst, "min"), | |
9204 maxDate = this._getMinMaxDate(inst, "max"), | |
9205 drawMonth = inst.drawMonth - showCurrentAtPos, | |
9206 drawYear = inst.drawYear; | |
9207 | |
9208 if (drawMonth < 0) { | |
9209 drawMonth += 12; | |
9210 drawYear--; | |
9211 } | |
9212 if (maxDate) { | |
9213 maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(), | |
9214 maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate())); | |
9215 maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw); | |
9216 while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) { | |
9217 drawMonth--; | |
9218 if (drawMonth < 0) { | |
9219 drawMonth = 11; | |
9220 drawYear--; | |
9221 } | |
9222 } | |
9223 } | |
9224 inst.drawMonth = drawMonth; | |
9225 inst.drawYear = drawYear; | |
9226 | |
9227 prevText = this._get(inst, "prevText"); | |
9228 prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText, | |
9229 this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)), | |
9230 this._getFormatConfig(inst))); | |
9231 | |
9232 prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ? | |
9233 "<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'" + | |
9234 " title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>" : | |
9235 (hideIfNoPrevNext ? "" : "<a class='ui-datepicker-prev ui-corner-all ui-state-disabled' title='"+ prevText +"'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>")); | |
9236 | |
9237 nextText = this._get(inst, "nextText"); | |
9238 nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText, | |
9239 this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)), | |
9240 this._getFormatConfig(inst))); | |
9241 | |
9242 next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ? | |
9243 "<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'" + | |
9244 " title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>" : | |
9245 (hideIfNoPrevNext ? "" : "<a class='ui-datepicker-next ui-corner-all ui-state-disabled' title='"+ nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>")); | |
9246 | |
9247 currentText = this._get(inst, "currentText"); | |
9248 gotoDate = (this._get(inst, "gotoCurrent") && inst.currentDay ? currentDate : today); | |
9249 currentText = (!navigationAsDateFormat ? currentText : | |
9250 this.formatDate(currentText, gotoDate, this._getFormatConfig(inst))); | |
9251 | |
9252 controls = (!inst.inline ? "<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>" + | |
9253 this._get(inst, "closeText") + "</button>" : ""); | |
9254 | |
9255 buttonPanel = (showButtonPanel) ? "<div class='ui-datepicker-buttonpane ui-widget-content'>" + (isRTL ? controls : "") + | |
9256 (this._isInRange(inst, gotoDate) ? "<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'" + | |
9257 ">" + currentText + "</button>" : "") + (isRTL ? "" : controls) + "</div>" : ""; | |
9258 | |
9259 firstDay = parseInt(this._get(inst, "firstDay"),10); | |
9260 firstDay = (isNaN(firstDay) ? 0 : firstDay); | |
9261 | |
9262 showWeek = this._get(inst, "showWeek"); | |
9263 dayNames = this._get(inst, "dayNames"); | |
9264 dayNamesMin = this._get(inst, "dayNamesMin"); | |
9265 monthNames = this._get(inst, "monthNames"); | |
9266 monthNamesShort = this._get(inst, "monthNamesShort"); | |
9267 beforeShowDay = this._get(inst, "beforeShowDay"); | |
9268 showOtherMonths = this._get(inst, "showOtherMonths"); | |
9269 selectOtherMonths = this._get(inst, "selectOtherMonths"); | |
9270 defaultDate = this._getDefaultDate(inst); | |
9271 html = ""; | |
9272 dow; | |
9273 for (row = 0; row < numMonths[0]; row++) { | |
9274 group = ""; | |
9275 this.maxRows = 4; | |
9276 for (col = 0; col < numMonths[1]; col++) { | |
9277 selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay)); | |
9278 cornerClass = " ui-corner-all"; | |
9279 calender = ""; | |
9280 if (isMultiMonth) { | |
9281 calender += "<div class='ui-datepicker-group"; | |
9282 if (numMonths[1] > 1) { | |
9283 switch (col) { | |
9284 case 0: calender += " ui-datepicker-group-first"; | |
9285 cornerClass = " ui-corner-" + (isRTL ? "right" : "left"); break; | |
9286 case numMonths[1]-1: calender += " ui-datepicker-group-last"; | |
9287 cornerClass = " ui-corner-" + (isRTL ? "left" : "right"); break; | |
9288 default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break; | |
9289 } | |
9290 } | |
9291 calender += "'>"; | |
9292 } | |
9293 calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" + | |
9294 (/all|left/.test(cornerClass) && row === 0 ? (isRTL ? next : prev) : "") + | |
9295 (/all|right/.test(cornerClass) && row === 0 ? (isRTL ? prev : next) : "") + | |
9296 this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate, | |
9297 row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers | |
9298 "</div><table class='ui-datepicker-calendar'><thead>" + | |
9299 "<tr>"; | |
9300 thead = (showWeek ? "<th class='ui-datepicker-week-col'>" + this._get(inst, "weekHeader") + "</th>" : ""); | |
9301 for (dow = 0; dow < 7; dow++) { // days of the week | |
9302 day = (dow + firstDay) % 7; | |
9303 thead += "<th" + ((dow + firstDay + 6) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "") + ">" + | |
9304 "<span title='" + dayNames[day] + "'>" + dayNamesMin[day] + "</span></th>"; | |
9305 } | |
9306 calender += thead + "</tr></thead><tbody>"; | |
9307 daysInMonth = this._getDaysInMonth(drawYear, drawMonth); | |
9308 if (drawYear === inst.selectedYear && drawMonth === inst.selectedMonth) { | |
9309 inst.selectedDay = Math.min(inst.selectedDay, daysInMonth); | |
9310 } | |
9311 leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7; | |
9312 curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate | |
9313 numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043) | |
9314 this.maxRows = numRows; | |
9315 printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays)); | |
9316 for (dRow = 0; dRow < numRows; dRow++) { // create date picker rows | |
9317 calender += "<tr>"; | |
9318 tbody = (!showWeek ? "" : "<td class='ui-datepicker-week-col'>" + | |
9319 this._get(inst, "calculateWeek")(printDate) + "</td>"); | |
9320 for (dow = 0; dow < 7; dow++) { // create date picker days | |
9321 daySettings = (beforeShowDay ? | |
9322 beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, ""]); | |
9323 otherMonth = (printDate.getMonth() !== drawMonth); | |
9324 unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] || | |
9325 (minDate && printDate < minDate) || (maxDate && printDate > maxDate); | |
9326 tbody += "<td class='" + | |
9327 ((dow + firstDay + 6) % 7 >= 5 ? " ui-datepicker-week-end" : "") + // highlight weekends | |
9328 (otherMonth ? " ui-datepicker-other-month" : "") + // highlight days from other months | |
9329 ((printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent) || // user pressed key | |
9330 (defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime()) ? | |
9331 // or defaultDate is current printedDate and defaultDate is selectedDate | |
9332 " " + this._dayOverClass : "") + // highlight selected day | |
9333 (unselectable ? " " + this._unselectableClass + " ui-state-disabled": "") + // highlight unselectable days | |
9334 (otherMonth && !showOtherMonths ? "" : " " + daySettings[1] + // highlight custom dates | |
9335 (printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "") + // highlight selected day | |
9336 (printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "")) + "'" + // highlight today (if different) | |
9337 ((!otherMonth || showOtherMonths) && daySettings[2] ? " title='" + daySettings[2].replace(/'/g, "'") + "'" : "") + // cell title | |
9338 (unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'") + ">" + // actions | |
9339 (otherMonth && !showOtherMonths ? " " : // display for other months | |
9340 (unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" + | |
9341 (printDate.getTime() === today.getTime() ? " ui-state-highlight" : "") + | |
9342 (printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "") + // highlight selected day | |
9343 (otherMonth ? " ui-priority-secondary" : "") + // distinguish dates from other months | |
9344 "' href='#'>" + printDate.getDate() + "</a>")) + "</td>"; // display selectable date | |
9345 printDate.setDate(printDate.getDate() + 1); | |
9346 printDate = this._daylightSavingAdjust(printDate); | |
9347 } | |
9348 calender += tbody + "</tr>"; | |
9349 } | |
9350 drawMonth++; | |
9351 if (drawMonth > 11) { | |
9352 drawMonth = 0; | |
9353 drawYear++; | |
9354 } | |
9355 calender += "</tbody></table>" + (isMultiMonth ? "</div>" + | |
9356 ((numMonths[0] > 0 && col === numMonths[1]-1) ? "<div class='ui-datepicker-row-break'></div>" : "") : ""); | |
9357 group += calender; | |
9358 } | |
9359 html += group; | |
9360 } | |
9361 html += buttonPanel; | |
9362 inst._keyEvent = false; | |
9363 return html; | |
9364 }, | |
9365 | |
9366 /* Generate the month and year header. */ | |
9367 _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate, | |
9368 secondary, monthNames, monthNamesShort) { | |
9369 | |
9370 var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear, | |
9371 changeMonth = this._get(inst, "changeMonth"), | |
9372 changeYear = this._get(inst, "changeYear"), | |
9373 showMonthAfterYear = this._get(inst, "showMonthAfterYear"), | |
9374 html = "<div class='ui-datepicker-title'>", | |
9375 monthHtml = ""; | |
9376 | |
9377 // month selection | |
9378 if (secondary || !changeMonth) { | |
9379 monthHtml += "<span class='ui-datepicker-month'>" + monthNames[drawMonth] + "</span>"; | |
9380 } else { | |
9381 inMinYear = (minDate && minDate.getFullYear() === drawYear); | |
9382 inMaxYear = (maxDate && maxDate.getFullYear() === drawYear); | |
9383 monthHtml += "<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>"; | |
9384 for ( month = 0; month < 12; month++) { | |
9385 if ((!inMinYear || month >= minDate.getMonth()) && (!inMaxYear || month <= maxDate.getMonth())) { | |
9386 monthHtml += "<option value='" + month + "'" + | |
9387 (month === drawMonth ? " selected='selected'" : "") + | |
9388 ">" + monthNamesShort[month] + "</option>"; | |
9389 } | |
9390 } | |
9391 monthHtml += "</select>"; | |
9392 } | |
9393 | |
9394 if (!showMonthAfterYear) { | |
9395 html += monthHtml + (secondary || !(changeMonth && changeYear) ? " " : ""); | |
9396 } | |
9397 | |
9398 // year selection | |
9399 if ( !inst.yearshtml ) { | |
9400 inst.yearshtml = ""; | |
9401 if (secondary || !changeYear) { | |
9402 html += "<span class='ui-datepicker-year'>" + drawYear + "</span>"; | |
9403 } else { | |
9404 // determine range of years to display | |
9405 years = this._get(inst, "yearRange").split(":"); | |
9406 thisYear = new Date().getFullYear(); | |
9407 determineYear = function(value) { | |
9408 var year = (value.match(/c[+\-].*/) ? drawYear + parseInt(value.substring(1), 10) : | |
9409 (value.match(/[+\-].*/) ? thisYear + parseInt(value, 10) : | |
9410 parseInt(value, 10))); | |
9411 return (isNaN(year) ? thisYear : year); | |
9412 }; | |
9413 year = determineYear(years[0]); | |
9414 endYear = Math.max(year, determineYear(years[1] || "")); | |
9415 year = (minDate ? Math.max(year, minDate.getFullYear()) : year); | |
9416 endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear); | |
9417 inst.yearshtml += "<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>"; | |
9418 for (; year <= endYear; year++) { | |
9419 inst.yearshtml += "<option value='" + year + "'" + | |
9420 (year === drawYear ? " selected='selected'" : "") + | |
9421 ">" + year + "</option>"; | |
9422 } | |
9423 inst.yearshtml += "</select>"; | |
9424 | |
9425 html += inst.yearshtml; | |
9426 inst.yearshtml = null; | |
9427 } | |
9428 } | |
9429 | |
9430 html += this._get(inst, "yearSuffix"); | |
9431 if (showMonthAfterYear) { | |
9432 html += (secondary || !(changeMonth && changeYear) ? " " : "") + monthHtml; | |
9433 } | |
9434 html += "</div>"; // Close datepicker_header | |
9435 return html; | |
9436 }, | |
9437 | |
9438 /* Adjust one of the date sub-fields. */ | |
9439 _adjustInstDate: function(inst, offset, period) { | |
9440 var year = inst.drawYear + (period === "Y" ? offset : 0), | |
9441 month = inst.drawMonth + (period === "M" ? offset : 0), | |
9442 day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + (period === "D" ? offset : 0), | |
9443 date = this._restrictMinMax(inst, this._daylightSavingAdjust(new Date(year, month, day))); | |
9444 | |
9445 inst.selectedDay = date.getDate(); | |
9446 inst.drawMonth = inst.selectedMonth = date.getMonth(); | |
9447 inst.drawYear = inst.selectedYear = date.getFullYear(); | |
9448 if (period === "M" || period === "Y") { | |
9449 this._notifyChange(inst); | |
9450 } | |
9451 }, | |
9452 | |
9453 /* Ensure a date is within any min/max bounds. */ | |
9454 _restrictMinMax: function(inst, date) { | |
9455 var minDate = this._getMinMaxDate(inst, "min"), | |
9456 maxDate = this._getMinMaxDate(inst, "max"), | |
9457 newDate = (minDate && date < minDate ? minDate : date); | |
9458 return (maxDate && newDate > maxDate ? maxDate : newDate); | |
9459 }, | |
9460 | |
9461 /* Notify change of month/year. */ | |
9462 _notifyChange: function(inst) { | |
9463 var onChange = this._get(inst, "onChangeMonthYear"); | |
9464 if (onChange) { | |
9465 onChange.apply((inst.input ? inst.input[0] : null), | |
9466 [inst.selectedYear, inst.selectedMonth + 1, inst]); | |
9467 } | |
9468 }, | |
9469 | |
9470 /* Determine the number of months to show. */ | |
9471 _getNumberOfMonths: function(inst) { | |
9472 var numMonths = this._get(inst, "numberOfMonths"); | |
9473 return (numMonths == null ? [1, 1] : (typeof numMonths === "number" ? [1, numMonths] : numMonths)); | |
9474 }, | |
9475 | |
9476 /* Determine the current maximum date - ensure no time components are set. */ | |
9477 _getMinMaxDate: function(inst, minMax) { | |
9478 return this._determineDate(inst, this._get(inst, minMax + "Date"), null); | |
9479 }, | |
9480 | |
9481 /* Find the number of days in a given month. */ | |
9482 _getDaysInMonth: function(year, month) { | |
9483 return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate(); | |
9484 }, | |
9485 | |
9486 /* Find the day of the week of the first of a month. */ | |
9487 _getFirstDayOfMonth: function(year, month) { | |
9488 return new Date(year, month, 1).getDay(); | |
9489 }, | |
9490 | |
9491 /* Determines if we should allow a "next/prev" month display change. */ | |
9492 _canAdjustMonth: function(inst, offset, curYear, curMonth) { | |
9493 var numMonths = this._getNumberOfMonths(inst), | |
9494 date = this._daylightSavingAdjust(new Date(curYear, | |
9495 curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1)); | |
9496 | |
9497 if (offset < 0) { | |
9498 date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth())); | |
9499 } | |
9500 return this._isInRange(inst, date); | |
9501 }, | |
9502 | |
9503 /* Is the given date in the accepted range? */ | |
9504 _isInRange: function(inst, date) { | |
9505 var yearSplit, currentYear, | |
9506 minDate = this._getMinMaxDate(inst, "min"), | |
9507 maxDate = this._getMinMaxDate(inst, "max"), | |
9508 minYear = null, | |
9509 maxYear = null, | |
9510 years = this._get(inst, "yearRange"); | |
9511 if (years){ | |
9512 yearSplit = years.split(":"); | |
9513 currentYear = new Date().getFullYear(); | |
9514 minYear = parseInt(yearSplit[0], 10); | |
9515 maxYear = parseInt(yearSplit[1], 10); | |
9516 if ( yearSplit[0].match(/[+\-].*/) ) { | |
9517 minYear += currentYear; | |
9518 } | |
9519 if ( yearSplit[1].match(/[+\-].*/) ) { | |
9520 maxYear += currentYear; | |
9521 } | |
9522 } | |
9523 | |
9524 return ((!minDate || date.getTime() >= minDate.getTime()) && | |
9525 (!maxDate || date.getTime() <= maxDate.getTime()) && | |
9526 (!minYear || date.getFullYear() >= minYear) && | |
9527 (!maxYear || date.getFullYear() <= maxYear)); | |
9528 }, | |
9529 | |
9530 /* Provide the configuration settings for formatting/parsing. */ | |
9531 _getFormatConfig: function(inst) { | |
9532 var shortYearCutoff = this._get(inst, "shortYearCutoff"); | |
9533 shortYearCutoff = (typeof shortYearCutoff !== "string" ? shortYearCutoff : | |
9534 new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10)); | |
9535 return {shortYearCutoff: shortYearCutoff, | |
9536 dayNamesShort: this._get(inst, "dayNamesShort"), dayNames: this._get(inst, "dayNames"), | |
9537 monthNamesShort: this._get(inst, "monthNamesShort"), monthNames: this._get(inst, "monthNames")}; | |
9538 }, | |
9539 | |
9540 /* Format the given date for display. */ | |
9541 _formatDate: function(inst, day, month, year) { | |
9542 if (!day) { | |
9543 inst.currentDay = inst.selectedDay; | |
9544 inst.currentMonth = inst.selectedMonth; | |
9545 inst.currentYear = inst.selectedYear; | |
9546 } | |
9547 var date = (day ? (typeof day === "object" ? day : | |
9548 this._daylightSavingAdjust(new Date(year, month, day))) : | |
9549 this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay))); | |
9550 return this.formatDate(this._get(inst, "dateFormat"), date, this._getFormatConfig(inst)); | |
9551 } | |
9552 }); | |
9553 | |
9554 /* | |
9555 * Bind hover events for datepicker elements. | |
9556 * Done via delegate so the binding only occurs once in the lifetime of the parent div. | |
9557 * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker. | |
9558 */ | |
9559 function bindHover(dpDiv) { | |
9560 var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a"; | |
9561 return dpDiv.delegate(selector, "mouseout", function() { | |
9562 $(this).removeClass("ui-state-hover"); | |
9563 if (this.className.indexOf("ui-datepicker-prev") !== -1) { | |
9564 $(this).removeClass("ui-datepicker-prev-hover"); | |
9565 } | |
9566 if (this.className.indexOf("ui-datepicker-next") !== -1) { | |
9567 $(this).removeClass("ui-datepicker-next-hover"); | |
9568 } | |
9569 }) | |
9570 .delegate(selector, "mouseover", function(){ | |
9571 if (!$.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0])) { | |
9572 $(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"); | |
9573 $(this).addClass("ui-state-hover"); | |
9574 if (this.className.indexOf("ui-datepicker-prev") !== -1) { | |
9575 $(this).addClass("ui-datepicker-prev-hover"); | |
9576 } | |
9577 if (this.className.indexOf("ui-datepicker-next") !== -1) { | |
9578 $(this).addClass("ui-datepicker-next-hover"); | |
9579 } | |
9580 } | |
9581 }); | |
9582 } | |
9583 | |
9584 /* jQuery extend now ignores nulls! */ | |
9585 function extendRemove(target, props) { | |
9586 $.extend(target, props); | |
9587 for (var name in props) { | |
9588 if (props[name] == null) { | |
9589 target[name] = props[name]; | |
9590 } | |
9591 } | |
9592 return target; | |
9593 } | |
9594 | |
9595 /* Invoke the datepicker functionality. | |
9596 @param options string - a command, optionally followed by additional parameters or | |
9597 Object - settings for attaching new datepicker functionality | |
9598 @return jQuery object */ | |
9599 $.fn.datepicker = function(options){ | |
9600 | |
9601 /* Verify an empty collection wasn't passed - Fixes #6976 */ | |
9602 if ( !this.length ) { | |
9603 return this; | |
9604 } | |
9605 | |
9606 /* Initialise the date picker. */ | |
9607 if (!$.datepicker.initialized) { | |
9608 $(document).mousedown($.datepicker._checkExternalClick); | |
9609 $.datepicker.initialized = true; | |
9610 } | |
9611 | |
9612 /* Append datepicker main container to body if not exist. */ | |
9613 if ($("#"+$.datepicker._mainDivId).length === 0) { | |
9614 $("body").append($.datepicker.dpDiv); | |
9615 } | |
9616 | |
9617 var otherArgs = Array.prototype.slice.call(arguments, 1); | |
9618 if (typeof options === "string" && (options === "isDisabled" || options === "getDate" || options === "widget")) { | |
9619 return $.datepicker["_" + options + "Datepicker"]. | |
9620 apply($.datepicker, [this[0]].concat(otherArgs)); | |
9621 } | |
9622 if (options === "option" && arguments.length === 2 && typeof arguments[1] === "string") { | |
9623 return $.datepicker["_" + options + "Datepicker"]. | |
9624 apply($.datepicker, [this[0]].concat(otherArgs)); | |
9625 } | |
9626 return this.each(function() { | |
9627 typeof options === "string" ? | |
9628 $.datepicker["_" + options + "Datepicker"]. | |
9629 apply($.datepicker, [this].concat(otherArgs)) : | |
9630 $.datepicker._attachDatepicker(this, options); | |
9631 }); | |
9632 }; | |
9633 | |
9634 $.datepicker = new Datepicker(); // singleton instance | |
9635 $.datepicker.initialized = false; | |
9636 $.datepicker.uuid = new Date().getTime(); | |
9637 $.datepicker.version = "1.10.4"; | |
9638 | |
9639 })(jQuery); | |
9640 | |
9641 (function( $, undefined ) { | |
9642 | |
9643 var sizeRelatedOptions = { | |
9644 buttons: true, | |
9645 height: true, | |
9646 maxHeight: true, | |
9647 maxWidth: true, | |
9648 minHeight: true, | |
9649 minWidth: true, | |
9650 width: true | |
9651 }, | |
9652 resizableRelatedOptions = { | |
9653 maxHeight: true, | |
9654 maxWidth: true, | |
9655 minHeight: true, | |
9656 minWidth: true | |
9657 }; | |
9658 | |
9659 $.widget( "ui.dialog", { | |
9660 version: "1.10.4", | |
9661 options: { | |
9662 appendTo: "body", | |
9663 autoOpen: true, | |
9664 buttons: [], | |
9665 closeOnEscape: true, | |
9666 closeText: "close", | |
9667 dialogClass: "", | |
9668 draggable: true, | |
9669 hide: null, | |
9670 height: "auto", | |
9671 maxHeight: null, | |
9672 maxWidth: null, | |
9673 minHeight: 150, | |
9674 minWidth: 150, | |
9675 modal: false, | |
9676 position: { | |
9677 my: "center", | |
9678 at: "center", | |
9679 of: window, | |
9680 collision: "fit", | |
9681 // Ensure the titlebar is always visible | |
9682 using: function( pos ) { | |
9683 var topOffset = $( this ).css( pos ).offset().top; | |
9684 if ( topOffset < 0 ) { | |
9685 $( this ).css( "top", pos.top - topOffset ); | |
9686 } | |
9687 } | |
9688 }, | |
9689 resizable: true, | |
9690 show: null, | |
9691 title: null, | |
9692 width: 300, | |
9693 | |
9694 // callbacks | |
9695 beforeClose: null, | |
9696 close: null, | |
9697 drag: null, | |
9698 dragStart: null, | |
9699 dragStop: null, | |
9700 focus: null, | |
9701 open: null, | |
9702 resize: null, | |
9703 resizeStart: null, | |
9704 resizeStop: null | |
9705 }, | |
9706 | |
9707 _create: function() { | |
9708 this.originalCss = { | |
9709 display: this.element[0].style.display, | |
9710 width: this.element[0].style.width, | |
9711 minHeight: this.element[0].style.minHeight, | |
9712 maxHeight: this.element[0].style.maxHeight, | |
9713 height: this.element[0].style.height | |
9714 }; | |
9715 this.originalPosition = { | |
9716 parent: this.element.parent(), | |
9717 index: this.element.parent().children().index( this.element ) | |
9718 }; | |
9719 this.originalTitle = this.element.attr("title"); | |
9720 this.options.title = this.options.title || this.originalTitle; | |
9721 | |
9722 this._createWrapper(); | |
9723 | |
9724 this.element | |
9725 .show() | |
9726 .removeAttr("title") | |
9727 .addClass("ui-dialog-content ui-widget-content") | |
9728 .appendTo( this.uiDialog ); | |
9729 | |
9730 this._createTitlebar(); | |
9731 this._createButtonPane(); | |
9732 | |
9733 if ( this.options.draggable && $.fn.draggable ) { | |
9734 this._makeDraggable(); | |
9735 } | |
9736 if ( this.options.resizable && $.fn.resizable ) { | |
9737 this._makeResizable(); | |
9738 } | |
9739 | |
9740 this._isOpen = false; | |
9741 }, | |
9742 | |
9743 _init: function() { | |
9744 if ( this.options.autoOpen ) { | |
9745 this.open(); | |
9746 } | |
9747 }, | |
9748 | |
9749 _appendTo: function() { | |
9750 var element = this.options.appendTo; | |
9751 if ( element && (element.jquery || element.nodeType) ) { | |
9752 return $( element ); | |
9753 } | |
9754 return this.document.find( element || "body" ).eq( 0 ); | |
9755 }, | |
9756 | |
9757 _destroy: function() { | |
9758 var next, | |
9759 originalPosition = this.originalPosition; | |
9760 | |
9761 this._destroyOverlay(); | |
9762 | |
9763 this.element | |
9764 .removeUniqueId() | |
9765 .removeClass("ui-dialog-content ui-widget-content") | |
9766 .css( this.originalCss ) | |
9767 // Without detaching first, the following becomes really slow | |
9768 .detach(); | |
9769 | |
9770 this.uiDialog.stop( true, true ).remove(); | |
9771 | |
9772 if ( this.originalTitle ) { | |
9773 this.element.attr( "title", this.originalTitle ); | |
9774 } | |
9775 | |
9776 next = originalPosition.parent.children().eq( originalPosition.index ); | |
9777 // Don't try to place the dialog next to itself (#8613) | |
9778 if ( next.length && next[0] !== this.element[0] ) { | |
9779 next.before( this.element ); | |
9780 } else { | |
9781 originalPosition.parent.append( this.element ); | |
9782 } | |
9783 }, | |
9784 | |
9785 widget: function() { | |
9786 return this.uiDialog; | |
9787 }, | |
9788 | |
9789 disable: $.noop, | |
9790 enable: $.noop, | |
9791 | |
9792 close: function( event ) { | |
9793 var activeElement, | |
9794 that = this; | |
9795 | |
9796 if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) { | |
9797 return; | |
9798 } | |
9799 | |
9800 this._isOpen = false; | |
9801 this._destroyOverlay(); | |
9802 | |
9803 if ( !this.opener.filter(":focusable").focus().length ) { | |
9804 | |
9805 // support: IE9 | |
9806 // IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe> | |
9807 try { | |
9808 activeElement = this.document[ 0 ].activeElement; | |
9809 | |
9810 // Support: IE9, IE10 | |
9811 // If the <body> is blurred, IE will switch windows, see #4520 | |
9812 if ( activeElement && activeElement.nodeName.toLowerCase() !== "body" ) { | |
9813 | |
9814 // Hiding a focused element doesn't trigger blur in WebKit | |
9815 // so in case we have nothing to focus on, explicitly blur the active element | |
9816 // https://bugs.webkit.org/show_bug.cgi?id=47182 | |
9817 $( activeElement ).blur(); | |
9818 } | |
9819 } catch ( error ) {} | |
9820 } | |
9821 | |
9822 this._hide( this.uiDialog, this.options.hide, function() { | |
9823 that._trigger( "close", event ); | |
9824 }); | |
9825 }, | |
9826 | |
9827 isOpen: function() { | |
9828 return this._isOpen; | |
9829 }, | |
9830 | |
9831 moveToTop: function() { | |
9832 this._moveToTop(); | |
9833 }, | |
9834 | |
9835 _moveToTop: function( event, silent ) { | |
9836 var moved = !!this.uiDialog.nextAll(":visible").insertBefore( this.uiDialog ).length; | |
9837 if ( moved && !silent ) { | |
9838 this._trigger( "focus", event ); | |
9839 } | |
9840 return moved; | |
9841 }, | |
9842 | |
9843 open: function() { | |
9844 var that = this; | |
9845 if ( this._isOpen ) { | |
9846 if ( this._moveToTop() ) { | |
9847 this._focusTabbable(); | |
9848 } | |
9849 return; | |
9850 } | |
9851 | |
9852 this._isOpen = true; | |
9853 this.opener = $( this.document[0].activeElement ); | |
9854 | |
9855 this._size(); | |
9856 this._position(); | |
9857 this._createOverlay(); | |
9858 this._moveToTop( null, true ); | |
9859 this._show( this.uiDialog, this.options.show, function() { | |
9860 that._focusTabbable(); | |
9861 that._trigger("focus"); | |
9862 }); | |
9863 | |
9864 this._trigger("open"); | |
9865 }, | |
9866 | |
9867 _focusTabbable: function() { | |
9868 // Set focus to the first match: | |
9869 // 1. First element inside the dialog matching [autofocus] | |
9870 // 2. Tabbable element inside the content element | |
9871 // 3. Tabbable element inside the buttonpane | |
9872 // 4. The close button | |
9873 // 5. The dialog itself | |
9874 var hasFocus = this.element.find("[autofocus]"); | |
9875 if ( !hasFocus.length ) { | |
9876 hasFocus = this.element.find(":tabbable"); | |
9877 } | |
9878 if ( !hasFocus.length ) { | |
9879 hasFocus = this.uiDialogButtonPane.find(":tabbable"); | |
9880 } | |
9881 if ( !hasFocus.length ) { | |
9882 hasFocus = this.uiDialogTitlebarClose.filter(":tabbable"); | |
9883 } | |
9884 if ( !hasFocus.length ) { | |
9885 hasFocus = this.uiDialog; | |
9886 } | |
9887 hasFocus.eq( 0 ).focus(); | |
9888 }, | |
9889 | |
9890 _keepFocus: function( event ) { | |
9891 function checkFocus() { | |
9892 var activeElement = this.document[0].activeElement, | |
9893 isActive = this.uiDialog[0] === activeElement || | |
9894 $.contains( this.uiDialog[0], activeElement ); | |
9895 if ( !isActive ) { | |
9896 this._focusTabbable(); | |
9897 } | |
9898 } | |
9899 event.preventDefault(); | |
9900 checkFocus.call( this ); | |
9901 // support: IE | |
9902 // IE <= 8 doesn't prevent moving focus even with event.preventDefault() | |
9903 // so we check again later | |
9904 this._delay( checkFocus ); | |
9905 }, | |
9906 | |
9907 _createWrapper: function() { | |
9908 this.uiDialog = $("<div>") | |
9909 .addClass( "ui-dialog ui-widget ui-widget-content ui-corner-all ui-front " + | |
9910 this.options.dialogClass ) | |
9911 .hide() | |
9912 .attr({ | |
9913 // Setting tabIndex makes the div focusable | |
9914 tabIndex: -1, | |
9915 role: "dialog" | |
9916 }) | |
9917 .appendTo( this._appendTo() ); | |
9918 | |
9919 this._on( this.uiDialog, { | |
9920 keydown: function( event ) { | |
9921 if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && | |
9922 event.keyCode === $.ui.keyCode.ESCAPE ) { | |
9923 event.preventDefault(); | |
9924 this.close( event ); | |
9925 return; | |
9926 } | |
9927 | |
9928 // prevent tabbing out of dialogs | |
9929 if ( event.keyCode !== $.ui.keyCode.TAB ) { | |
9930 return; | |
9931 } | |
9932 var tabbables = this.uiDialog.find(":tabbable"), | |
9933 first = tabbables.filter(":first"), | |
9934 last = tabbables.filter(":last"); | |
9935 | |
9936 if ( ( event.target === last[0] || event.target === this.uiDialog[0] ) && !event.shiftKey ) { | |
9937 first.focus( 1 ); | |
9938 event.preventDefault(); | |
9939 } else if ( ( event.target === first[0] || event.target === this.uiDialog[0] ) && event.shiftKey ) { | |
9940 last.focus( 1 ); | |
9941 event.preventDefault(); | |
9942 } | |
9943 }, | |
9944 mousedown: function( event ) { | |
9945 if ( this._moveToTop( event ) ) { | |
9946 this._focusTabbable(); | |
9947 } | |
9948 } | |
9949 }); | |
9950 | |
9951 // We assume that any existing aria-describedby attribute means | |
9952 // that the dialog content is marked up properly | |
9953 // otherwise we brute force the content as the description | |
9954 if ( !this.element.find("[aria-describedby]").length ) { | |
9955 this.uiDialog.attr({ | |
9956 "aria-describedby": this.element.uniqueId().attr("id") | |
9957 }); | |
9958 } | |
9959 }, | |
9960 | |
9961 _createTitlebar: function() { | |
9962 var uiDialogTitle; | |
9963 | |
9964 this.uiDialogTitlebar = $("<div>") | |
9965 .addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix") | |
9966 .prependTo( this.uiDialog ); | |
9967 this._on( this.uiDialogTitlebar, { | |
9968 mousedown: function( event ) { | |
9969 // Don't prevent click on close button (#8838) | |
9970 // Focusing a dialog that is partially scrolled out of view | |
9971 // causes the browser to scroll it into view, preventing the click event | |
9972 if ( !$( event.target ).closest(".ui-dialog-titlebar-close") ) { | |
9973 // Dialog isn't getting focus when dragging (#8063) | |
9974 this.uiDialog.focus(); | |
9975 } | |
9976 } | |
9977 }); | |
9978 | |
9979 // support: IE | |
9980 // Use type="button" to prevent enter keypresses in textboxes from closing the | |
9981 // dialog in IE (#9312) | |
9982 this.uiDialogTitlebarClose = $( "<button type='button'></button>" ) | |
9983 .button({ | |
9984 label: this.options.closeText, | |
9985 icons: { | |
9986 primary: "ui-icon-closethick" | |
9987 }, | |
9988 text: false | |
9989 }) | |
9990 .addClass("ui-dialog-titlebar-close") | |
9991 .appendTo( this.uiDialogTitlebar ); | |
9992 this._on( this.uiDialogTitlebarClose, { | |
9993 click: function( event ) { | |
9994 event.preventDefault(); | |
9995 this.close( event ); | |
9996 } | |
9997 }); | |
9998 | |
9999 uiDialogTitle = $("<span>") | |
10000 .uniqueId() | |
10001 .addClass("ui-dialog-title") | |
10002 .prependTo( this.uiDialogTitlebar ); | |
10003 this._title( uiDialogTitle ); | |
10004 | |
10005 this.uiDialog.attr({ | |
10006 "aria-labelledby": uiDialogTitle.attr("id") | |
10007 }); | |
10008 }, | |
10009 | |
10010 _title: function( title ) { | |
10011 if ( !this.options.title ) { | |
10012 title.html(" "); | |
10013 } | |
10014 title.text( this.options.title ); | |
10015 }, | |
10016 | |
10017 _createButtonPane: function() { | |
10018 this.uiDialogButtonPane = $("<div>") | |
10019 .addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"); | |
10020 | |
10021 this.uiButtonSet = $("<div>") | |
10022 .addClass("ui-dialog-buttonset") | |
10023 .appendTo( this.uiDialogButtonPane ); | |
10024 | |
10025 this._createButtons(); | |
10026 }, | |
10027 | |
10028 _createButtons: function() { | |
10029 var that = this, | |
10030 buttons = this.options.buttons; | |
10031 | |
10032 // if we already have a button pane, remove it | |
10033 this.uiDialogButtonPane.remove(); | |
10034 this.uiButtonSet.empty(); | |
10035 | |
10036 if ( $.isEmptyObject( buttons ) || ($.isArray( buttons ) && !buttons.length) ) { | |
10037 this.uiDialog.removeClass("ui-dialog-buttons"); | |
10038 return; | |
10039 } | |
10040 | |
10041 $.each( buttons, function( name, props ) { | |
10042 var click, buttonOptions; | |
10043 props = $.isFunction( props ) ? | |
10044 { click: props, text: name } : | |
10045 props; | |
10046 // Default to a non-submitting button | |
10047 props = $.extend( { type: "button" }, props ); | |
10048 // Change the context for the click callback to be the main element | |
10049 click = props.click; | |
10050 props.click = function() { | |
10051 click.apply( that.element[0], arguments ); | |
10052 }; | |
10053 buttonOptions = { | |
10054 icons: props.icons, | |
10055 text: props.showText | |
10056 }; | |
10057 delete props.icons; | |
10058 delete props.showText; | |
10059 $( "<button></button>", props ) | |
10060 .button( buttonOptions ) | |
10061 .appendTo( that.uiButtonSet ); | |
10062 }); | |
10063 this.uiDialog.addClass("ui-dialog-buttons"); | |
10064 this.uiDialogButtonPane.appendTo( this.uiDialog ); | |
10065 }, | |
10066 | |
10067 _makeDraggable: function() { | |
10068 var that = this, | |
10069 options = this.options; | |
10070 | |
10071 function filteredUi( ui ) { | |
10072 return { | |
10073 position: ui.position, | |
10074 offset: ui.offset | |
10075 }; | |
10076 } | |
10077 | |
10078 this.uiDialog.draggable({ | |
10079 cancel: ".ui-dialog-content, .ui-dialog-titlebar-close", | |
10080 handle: ".ui-dialog-titlebar", | |
10081 containment: "document", | |
10082 start: function( event, ui ) { | |
10083 $( this ).addClass("ui-dialog-dragging"); | |
10084 that._blockFrames(); | |
10085 that._trigger( "dragStart", event, filteredUi( ui ) ); | |
10086 }, | |
10087 drag: function( event, ui ) { | |
10088 that._trigger( "drag", event, filteredUi( ui ) ); | |
10089 }, | |
10090 stop: function( event, ui ) { | |
10091 options.position = [ | |
10092 ui.position.left - that.document.scrollLeft(), | |
10093 ui.position.top - that.document.scrollTop() | |
10094 ]; | |
10095 $( this ).removeClass("ui-dialog-dragging"); | |
10096 that._unblockFrames(); | |
10097 that._trigger( "dragStop", event, filteredUi( ui ) ); | |
10098 } | |
10099 }); | |
10100 }, | |
10101 | |
10102 _makeResizable: function() { | |
10103 var that = this, | |
10104 options = this.options, | |
10105 handles = options.resizable, | |
10106 // .ui-resizable has position: relative defined in the stylesheet | |
10107 // but dialogs have to use absolute or fixed positioning | |
10108 position = this.uiDialog.css("position"), | |
10109 resizeHandles = typeof handles === "string" ? | |
10110 handles : | |
10111 "n,e,s,w,se,sw,ne,nw"; | |
10112 | |
10113 function filteredUi( ui ) { | |
10114 return { | |
10115 originalPosition: ui.originalPosition, | |
10116 originalSize: ui.originalSize, | |
10117 position: ui.position, | |
10118 size: ui.size | |
10119 }; | |
10120 } | |
10121 | |
10122 this.uiDialog.resizable({ | |
10123 cancel: ".ui-dialog-content", | |
10124 containment: "document", | |
10125 alsoResize: this.element, | |
10126 maxWidth: options.maxWidth, | |
10127 maxHeight: options.maxHeight, | |
10128 minWidth: options.minWidth, | |
10129 minHeight: this._minHeight(), | |
10130 handles: resizeHandles, | |
10131 start: function( event, ui ) { | |
10132 $( this ).addClass("ui-dialog-resizing"); | |
10133 that._blockFrames(); | |
10134 that._trigger( "resizeStart", event, filteredUi( ui ) ); | |
10135 }, | |
10136 resize: function( event, ui ) { | |
10137 that._trigger( "resize", event, filteredUi( ui ) ); | |
10138 }, | |
10139 stop: function( event, ui ) { | |
10140 options.height = $( this ).height(); | |
10141 options.width = $( this ).width(); | |
10142 $( this ).removeClass("ui-dialog-resizing"); | |
10143 that._unblockFrames(); | |
10144 that._trigger( "resizeStop", event, filteredUi( ui ) ); | |
10145 } | |
10146 }) | |
10147 .css( "position", position ); | |
10148 }, | |
10149 | |
10150 _minHeight: function() { | |
10151 var options = this.options; | |
10152 | |
10153 return options.height === "auto" ? | |
10154 options.minHeight : | |
10155 Math.min( options.minHeight, options.height ); | |
10156 }, | |
10157 | |
10158 _position: function() { | |
10159 // Need to show the dialog to get the actual offset in the position plugin | |
10160 var isVisible = this.uiDialog.is(":visible"); | |
10161 if ( !isVisible ) { | |
10162 this.uiDialog.show(); | |
10163 } | |
10164 this.uiDialog.position( this.options.position ); | |
10165 if ( !isVisible ) { | |
10166 this.uiDialog.hide(); | |
10167 } | |
10168 }, | |
10169 | |
10170 _setOptions: function( options ) { | |
10171 var that = this, | |
10172 resize = false, | |
10173 resizableOptions = {}; | |
10174 | |
10175 $.each( options, function( key, value ) { | |
10176 that._setOption( key, value ); | |
10177 | |
10178 if ( key in sizeRelatedOptions ) { | |
10179 resize = true; | |
10180 } | |
10181 if ( key in resizableRelatedOptions ) { | |
10182 resizableOptions[ key ] = value; | |
10183 } | |
10184 }); | |
10185 | |
10186 if ( resize ) { | |
10187 this._size(); | |
10188 this._position(); | |
10189 } | |
10190 if ( this.uiDialog.is(":data(ui-resizable)") ) { | |
10191 this.uiDialog.resizable( "option", resizableOptions ); | |
10192 } | |
10193 }, | |
10194 | |
10195 _setOption: function( key, value ) { | |
10196 var isDraggable, isResizable, | |
10197 uiDialog = this.uiDialog; | |
10198 | |
10199 if ( key === "dialogClass" ) { | |
10200 uiDialog | |
10201 .removeClass( this.options.dialogClass ) | |
10202 .addClass( value ); | |
10203 } | |
10204 | |
10205 if ( key === "disabled" ) { | |
10206 return; | |
10207 } | |
10208 | |
10209 this._super( key, value ); | |
10210 | |
10211 if ( key === "appendTo" ) { | |
10212 this.uiDialog.appendTo( this._appendTo() ); | |
10213 } | |
10214 | |
10215 if ( key === "buttons" ) { | |
10216 this._createButtons(); | |
10217 } | |
10218 | |
10219 if ( key === "closeText" ) { | |
10220 this.uiDialogTitlebarClose.button({ | |
10221 // Ensure that we always pass a string | |
10222 label: "" + value | |
10223 }); | |
10224 } | |
10225 | |
10226 if ( key === "draggable" ) { | |
10227 isDraggable = uiDialog.is(":data(ui-draggable)"); | |
10228 if ( isDraggable && !value ) { | |
10229 uiDialog.draggable("destroy"); | |
10230 } | |
10231 | |
10232 if ( !isDraggable && value ) { | |
10233 this._makeDraggable(); | |
10234 } | |
10235 } | |
10236 | |
10237 if ( key === "position" ) { | |
10238 this._position(); | |
10239 } | |
10240 | |
10241 if ( key === "resizable" ) { | |
10242 // currently resizable, becoming non-resizable | |
10243 isResizable = uiDialog.is(":data(ui-resizable)"); | |
10244 if ( isResizable && !value ) { | |
10245 uiDialog.resizable("destroy"); | |
10246 } | |
10247 | |
10248 // currently resizable, changing handles | |
10249 if ( isResizable && typeof value === "string" ) { | |
10250 uiDialog.resizable( "option", "handles", value ); | |
10251 } | |
10252 | |
10253 // currently non-resizable, becoming resizable | |
10254 if ( !isResizable && value !== false ) { | |
10255 this._makeResizable(); | |
10256 } | |
10257 } | |
10258 | |
10259 if ( key === "title" ) { | |
10260 this._title( this.uiDialogTitlebar.find(".ui-dialog-title") ); | |
10261 } | |
10262 }, | |
10263 | |
10264 _size: function() { | |
10265 // If the user has resized the dialog, the .ui-dialog and .ui-dialog-content | |
10266 // divs will both have width and height set, so we need to reset them | |
10267 var nonContentHeight, minContentHeight, maxContentHeight, | |
10268 options = this.options; | |
10269 | |
10270 // Reset content sizing | |
10271 this.element.show().css({ | |
10272 width: "auto", | |
10273 minHeight: 0, | |
10274 maxHeight: "none", | |
10275 height: 0 | |
10276 }); | |
10277 | |
10278 if ( options.minWidth > options.width ) { | |
10279 options.width = options.minWidth; | |
10280 } | |
10281 | |
10282 // reset wrapper sizing | |
10283 // determine the height of all the non-content elements | |
10284 nonContentHeight = this.uiDialog.css({ | |
10285 height: "auto", | |
10286 width: options.width | |
10287 }) | |
10288 .outerHeight(); | |
10289 minContentHeight = Math.max( 0, options.minHeight - nonContentHeight ); | |
10290 maxContentHeight = typeof options.maxHeight === "number" ? | |
10291 Math.max( 0, options.maxHeight - nonContentHeight ) : | |
10292 "none"; | |
10293 | |
10294 if ( options.height === "auto" ) { | |
10295 this.element.css({ | |
10296 minHeight: minContentHeight, | |
10297 maxHeight: maxContentHeight, | |
10298 height: "auto" | |
10299 }); | |
10300 } else { | |
10301 this.element.height( Math.max( 0, options.height - nonContentHeight ) ); | |
10302 } | |
10303 | |
10304 if (this.uiDialog.is(":data(ui-resizable)") ) { | |
10305 this.uiDialog.resizable( "option", "minHeight", this._minHeight() ); | |
10306 } | |
10307 }, | |
10308 | |
10309 _blockFrames: function() { | |
10310 this.iframeBlocks = this.document.find( "iframe" ).map(function() { | |
10311 var iframe = $( this ); | |
10312 | |
10313 return $( "<div>" ) | |
10314 .css({ | |
10315 position: "absolute", | |
10316 width: iframe.outerWidth(), | |
10317 height: iframe.outerHeight() | |
10318 }) | |
10319 .appendTo( iframe.parent() ) | |
10320 .offset( iframe.offset() )[0]; | |
10321 }); | |
10322 }, | |
10323 | |
10324 _unblockFrames: function() { | |
10325 if ( this.iframeBlocks ) { | |
10326 this.iframeBlocks.remove(); | |
10327 delete this.iframeBlocks; | |
10328 } | |
10329 }, | |
10330 | |
10331 _allowInteraction: function( event ) { | |
10332 if ( $( event.target ).closest(".ui-dialog").length ) { | |
10333 return true; | |
10334 } | |
10335 | |
10336 // TODO: Remove hack when datepicker implements | |
10337 // the .ui-front logic (#8989) | |
10338 return !!$( event.target ).closest(".ui-datepicker").length; | |
10339 }, | |
10340 | |
10341 _createOverlay: function() { | |
10342 if ( !this.options.modal ) { | |
10343 return; | |
10344 } | |
10345 | |
10346 var that = this, | |
10347 widgetFullName = this.widgetFullName; | |
10348 if ( !$.ui.dialog.overlayInstances ) { | |
10349 // Prevent use of anchors and inputs. | |
10350 // We use a delay in case the overlay is created from an | |
10351 // event that we're going to be cancelling. (#2804) | |
10352 this._delay(function() { | |
10353 // Handle .dialog().dialog("close") (#4065) | |
10354 if ( $.ui.dialog.overlayInstances ) { | |
10355 this.document.bind( "focusin.dialog", function( event ) { | |
10356 if ( !that._allowInteraction( event ) ) { | |
10357 event.preventDefault(); | |
10358 $(".ui-dialog:visible:last .ui-dialog-content") | |
10359 .data( widgetFullName )._focusTabbable(); | |
10360 } | |
10361 }); | |
10362 } | |
10363 }); | |
10364 } | |
10365 | |
10366 this.overlay = $("<div>") | |
10367 .addClass("ui-widget-overlay ui-front") | |
10368 .appendTo( this._appendTo() ); | |
10369 this._on( this.overlay, { | |
10370 mousedown: "_keepFocus" | |
10371 }); | |
10372 $.ui.dialog.overlayInstances++; | |
10373 }, | |
10374 | |
10375 _destroyOverlay: function() { | |
10376 if ( !this.options.modal ) { | |
10377 return; | |
10378 } | |
10379 | |
10380 if ( this.overlay ) { | |
10381 $.ui.dialog.overlayInstances--; | |
10382 | |
10383 if ( !$.ui.dialog.overlayInstances ) { | |
10384 this.document.unbind( "focusin.dialog" ); | |
10385 } | |
10386 this.overlay.remove(); | |
10387 this.overlay = null; | |
10388 } | |
10389 } | |
10390 }); | |
10391 | |
10392 $.ui.dialog.overlayInstances = 0; | |
10393 | |
10394 // DEPRECATED | |
10395 if ( $.uiBackCompat !== false ) { | |
10396 // position option with array notation | |
10397 // just override with old implementation | |
10398 $.widget( "ui.dialog", $.ui.dialog, { | |
10399 _position: function() { | |
10400 var position = this.options.position, | |
10401 myAt = [], | |
10402 offset = [ 0, 0 ], | |
10403 isVisible; | |
10404 | |
10405 if ( position ) { | |
10406 if ( typeof position === "string" || (typeof position === "object" && "0" in position ) ) { | |
10407 myAt = position.split ? position.split(" ") : [ position[0], position[1] ]; | |
10408 if ( myAt.length === 1 ) { | |
10409 myAt[1] = myAt[0]; | |
10410 } | |
10411 | |
10412 $.each( [ "left", "top" ], function( i, offsetPosition ) { | |
10413 if ( +myAt[ i ] === myAt[ i ] ) { | |
10414 offset[ i ] = myAt[ i ]; | |
10415 myAt[ i ] = offsetPosition; | |
10416 } | |
10417 }); | |
10418 | |
10419 position = { | |
10420 my: myAt[0] + (offset[0] < 0 ? offset[0] : "+" + offset[0]) + " " + | |
10421 myAt[1] + (offset[1] < 0 ? offset[1] : "+" + offset[1]), | |
10422 at: myAt.join(" ") | |
10423 }; | |
10424 } | |
10425 | |
10426 position = $.extend( {}, $.ui.dialog.prototype.options.position, position ); | |
10427 } else { | |
10428 position = $.ui.dialog.prototype.options.position; | |
10429 } | |
10430 | |
10431 // need to show the dialog to get the actual offset in the position plugin | |
10432 isVisible = this.uiDialog.is(":visible"); | |
10433 if ( !isVisible ) { | |
10434 this.uiDialog.show(); | |
10435 } | |
10436 this.uiDialog.position( position ); | |
10437 if ( !isVisible ) { | |
10438 this.uiDialog.hide(); | |
10439 } | |
10440 } | |
10441 }); | |
10442 } | |
10443 | |
10444 }( jQuery ) ); | |
10445 | |
10446 (function( $, undefined ) { | |
10447 | |
10448 var rvertical = /up|down|vertical/, | |
10449 rpositivemotion = /up|left|vertical|horizontal/; | |
10450 | |
10451 $.effects.effect.blind = function( o, done ) { | |
10452 // Create element | |
10453 var el = $( this ), | |
10454 props = [ "position", "top", "bottom", "left", "right", "height", "width" ], | |
10455 mode = $.effects.setMode( el, o.mode || "hide" ), | |
10456 direction = o.direction || "up", | |
10457 vertical = rvertical.test( direction ), | |
10458 ref = vertical ? "height" : "width", | |
10459 ref2 = vertical ? "top" : "left", | |
10460 motion = rpositivemotion.test( direction ), | |
10461 animation = {}, | |
10462 show = mode === "show", | |
10463 wrapper, distance, margin; | |
10464 | |
10465 // if already wrapped, the wrapper's properties are my property. #6245 | |
10466 if ( el.parent().is( ".ui-effects-wrapper" ) ) { | |
10467 $.effects.save( el.parent(), props ); | |
10468 } else { | |
10469 $.effects.save( el, props ); | |
10470 } | |
10471 el.show(); | |
10472 wrapper = $.effects.createWrapper( el ).css({ | |
10473 overflow: "hidden" | |
10474 }); | |
10475 | |
10476 distance = wrapper[ ref ](); | |
10477 margin = parseFloat( wrapper.css( ref2 ) ) || 0; | |
10478 | |
10479 animation[ ref ] = show ? distance : 0; | |
10480 if ( !motion ) { | |
10481 el | |
10482 .css( vertical ? "bottom" : "right", 0 ) | |
10483 .css( vertical ? "top" : "left", "auto" ) | |
10484 .css({ position: "absolute" }); | |
10485 | |
10486 animation[ ref2 ] = show ? margin : distance + margin; | |
10487 } | |
10488 | |
10489 // start at 0 if we are showing | |
10490 if ( show ) { | |
10491 wrapper.css( ref, 0 ); | |
10492 if ( ! motion ) { | |
10493 wrapper.css( ref2, margin + distance ); | |
10494 } | |
10495 } | |
10496 | |
10497 // Animate | |
10498 wrapper.animate( animation, { | |
10499 duration: o.duration, | |
10500 easing: o.easing, | |
10501 queue: false, | |
10502 complete: function() { | |
10503 if ( mode === "hide" ) { | |
10504 el.hide(); | |
10505 } | |
10506 $.effects.restore( el, props ); | |
10507 $.effects.removeWrapper( el ); | |
10508 done(); | |
10509 } | |
10510 }); | |
10511 | |
10512 }; | |
10513 | |
10514 })(jQuery); | |
10515 | |
10516 (function( $, undefined ) { | |
10517 | |
10518 $.effects.effect.bounce = function( o, done ) { | |
10519 var el = $( this ), | |
10520 props = [ "position", "top", "bottom", "left", "right", "height", "width" ], | |
10521 | |
10522 // defaults: | |
10523 mode = $.effects.setMode( el, o.mode || "effect" ), | |
10524 hide = mode === "hide", | |
10525 show = mode === "show", | |
10526 direction = o.direction || "up", | |
10527 distance = o.distance, | |
10528 times = o.times || 5, | |
10529 | |
10530 // number of internal animations | |
10531 anims = times * 2 + ( show || hide ? 1 : 0 ), | |
10532 speed = o.duration / anims, | |
10533 easing = o.easing, | |
10534 | |
10535 // utility: | |
10536 ref = ( direction === "up" || direction === "down" ) ? "top" : "left", | |
10537 motion = ( direction === "up" || direction === "left" ), | |
10538 i, | |
10539 upAnim, | |
10540 downAnim, | |
10541 | |
10542 // we will need to re-assemble the queue to stack our animations in place | |
10543 queue = el.queue(), | |
10544 queuelen = queue.length; | |
10545 | |
10546 // Avoid touching opacity to prevent clearType and PNG issues in IE | |
10547 if ( show || hide ) { | |
10548 props.push( "opacity" ); | |
10549 } | |
10550 | |
10551 $.effects.save( el, props ); | |
10552 el.show(); | |
10553 $.effects.createWrapper( el ); // Create Wrapper | |
10554 | |
10555 // default distance for the BIGGEST bounce is the outer Distance / 3 | |
10556 if ( !distance ) { | |
10557 distance = el[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3; | |
10558 } | |
10559 | |
10560 if ( show ) { | |
10561 downAnim = { opacity: 1 }; | |
10562 downAnim[ ref ] = 0; | |
10563 | |
10564 // if we are showing, force opacity 0 and set the initial position | |
10565 // then do the "first" animation | |
10566 el.css( "opacity", 0 ) | |
10567 .css( ref, motion ? -distance * 2 : distance * 2 ) | |
10568 .animate( downAnim, speed, easing ); | |
10569 } | |
10570 | |
10571 // start at the smallest distance if we are hiding | |
10572 if ( hide ) { | |
10573 distance = distance / Math.pow( 2, times - 1 ); | |
10574 } | |
10575 | |
10576 downAnim = {}; | |
10577 downAnim[ ref ] = 0; | |
10578 // Bounces up/down/left/right then back to 0 -- times * 2 animations happen here | |
10579 for ( i = 0; i < times; i++ ) { | |
10580 upAnim = {}; | |
10581 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance; | |
10582 | |
10583 el.animate( upAnim, speed, easing ) | |
10584 .animate( downAnim, speed, easing ); | |
10585 | |
10586 distance = hide ? distance * 2 : distance / 2; | |
10587 } | |
10588 | |
10589 // Last Bounce when Hiding | |
10590 if ( hide ) { | |
10591 upAnim = { opacity: 0 }; | |
10592 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance; | |
10593 | |
10594 el.animate( upAnim, speed, easing ); | |
10595 } | |
10596 | |
10597 el.queue(function() { | |
10598 if ( hide ) { | |
10599 el.hide(); | |
10600 } | |
10601 $.effects.restore( el, props ); | |
10602 $.effects.removeWrapper( el ); | |
10603 done(); | |
10604 }); | |
10605 | |
10606 // inject all the animations we just queued to be first in line (after "inprogress") | |
10607 if ( queuelen > 1) { | |
10608 queue.splice.apply( queue, | |
10609 [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) ); | |
10610 } | |
10611 el.dequeue(); | |
10612 | |
10613 }; | |
10614 | |
10615 })(jQuery); | |
10616 | |
10617 (function( $, undefined ) { | |
10618 | |
10619 $.effects.effect.clip = function( o, done ) { | |
10620 // Create element | |
10621 var el = $( this ), | |
10622 props = [ "position", "top", "bottom", "left", "right", "height", "width" ], | |
10623 mode = $.effects.setMode( el, o.mode || "hide" ), | |
10624 show = mode === "show", | |
10625 direction = o.direction || "vertical", | |
10626 vert = direction === "vertical", | |
10627 size = vert ? "height" : "width", | |
10628 position = vert ? "top" : "left", | |
10629 animation = {}, | |
10630 wrapper, animate, distance; | |
10631 | |
10632 // Save & Show | |
10633 $.effects.save( el, props ); | |
10634 el.show(); | |
10635 | |
10636 // Create Wrapper | |
10637 wrapper = $.effects.createWrapper( el ).css({ | |
10638 overflow: "hidden" | |
10639 }); | |
10640 animate = ( el[0].tagName === "IMG" ) ? wrapper : el; | |
10641 distance = animate[ size ](); | |
10642 | |
10643 // Shift | |
10644 if ( show ) { | |
10645 animate.css( size, 0 ); | |
10646 animate.css( position, distance / 2 ); | |
10647 } | |
10648 | |
10649 // Create Animation Object: | |
10650 animation[ size ] = show ? distance : 0; | |
10651 animation[ position ] = show ? 0 : distance / 2; | |
10652 | |
10653 // Animate | |
10654 animate.animate( animation, { | |
10655 queue: false, | |
10656 duration: o.duration, | |
10657 easing: o.easing, | |
10658 complete: function() { | |
10659 if ( !show ) { | |
10660 el.hide(); | |
10661 } | |
10662 $.effects.restore( el, props ); | |
10663 $.effects.removeWrapper( el ); | |
10664 done(); | |
10665 } | |
10666 }); | |
10667 | |
10668 }; | |
10669 | |
10670 })(jQuery); | |
10671 | |
10672 (function( $, undefined ) { | |
10673 | |
10674 $.effects.effect.drop = function( o, done ) { | |
10675 | |
10676 var el = $( this ), | |
10677 props = [ "position", "top", "bottom", "left", "right", "opacity", "height", "width" ], | |
10678 mode = $.effects.setMode( el, o.mode || "hide" ), | |
10679 show = mode === "show", | |
10680 direction = o.direction || "left", | |
10681 ref = ( direction === "up" || direction === "down" ) ? "top" : "left", | |
10682 motion = ( direction === "up" || direction === "left" ) ? "pos" : "neg", | |
10683 animation = { | |
10684 opacity: show ? 1 : 0 | |
10685 }, | |
10686 distance; | |
10687 | |
10688 // Adjust | |
10689 $.effects.save( el, props ); | |
10690 el.show(); | |
10691 $.effects.createWrapper( el ); | |
10692 | |
10693 distance = o.distance || el[ ref === "top" ? "outerHeight": "outerWidth" ]( true ) / 2; | |
10694 | |
10695 if ( show ) { | |
10696 el | |
10697 .css( "opacity", 0 ) | |
10698 .css( ref, motion === "pos" ? -distance : distance ); | |
10699 } | |
10700 | |
10701 // Animation | |
10702 animation[ ref ] = ( show ? | |
10703 ( motion === "pos" ? "+=" : "-=" ) : | |
10704 ( motion === "pos" ? "-=" : "+=" ) ) + | |
10705 distance; | |
10706 | |
10707 // Animate | |
10708 el.animate( animation, { | |
10709 queue: false, | |
10710 duration: o.duration, | |
10711 easing: o.easing, | |
10712 complete: function() { | |
10713 if ( mode === "hide" ) { | |
10714 el.hide(); | |
10715 } | |
10716 $.effects.restore( el, props ); | |
10717 $.effects.removeWrapper( el ); | |
10718 done(); | |
10719 } | |
10720 }); | |
10721 }; | |
10722 | |
10723 })(jQuery); | |
10724 | |
10725 (function( $, undefined ) { | |
10726 | |
10727 $.effects.effect.explode = function( o, done ) { | |
10728 | |
10729 var rows = o.pieces ? Math.round( Math.sqrt( o.pieces ) ) : 3, | |
10730 cells = rows, | |
10731 el = $( this ), | |
10732 mode = $.effects.setMode( el, o.mode || "hide" ), | |
10733 show = mode === "show", | |
10734 | |
10735 // show and then visibility:hidden the element before calculating offset | |
10736 offset = el.show().css( "visibility", "hidden" ).offset(), | |
10737 | |
10738 // width and height of a piece | |
10739 width = Math.ceil( el.outerWidth() / cells ), | |
10740 height = Math.ceil( el.outerHeight() / rows ), | |
10741 pieces = [], | |
10742 | |
10743 // loop | |
10744 i, j, left, top, mx, my; | |
10745 | |
10746 // children animate complete: | |
10747 function childComplete() { | |
10748 pieces.push( this ); | |
10749 if ( pieces.length === rows * cells ) { | |
10750 animComplete(); | |
10751 } | |
10752 } | |
10753 | |
10754 // clone the element for each row and cell. | |
10755 for( i = 0; i < rows ; i++ ) { // ===> | |
10756 top = offset.top + i * height; | |
10757 my = i - ( rows - 1 ) / 2 ; | |
10758 | |
10759 for( j = 0; j < cells ; j++ ) { // ||| | |
10760 left = offset.left + j * width; | |
10761 mx = j - ( cells - 1 ) / 2 ; | |
10762 | |
10763 // Create a clone of the now hidden main element that will be absolute positioned | |
10764 // within a wrapper div off the -left and -top equal to size of our pieces | |
10765 el | |
10766 .clone() | |
10767 .appendTo( "body" ) | |
10768 .wrap( "<div></div>" ) | |
10769 .css({ | |
10770 position: "absolute", | |
10771 visibility: "visible", | |
10772 left: -j * width, | |
10773 top: -i * height | |
10774 }) | |
10775 | |
10776 // select the wrapper - make it overflow: hidden and absolute positioned based on | |
10777 // where the original was located +left and +top equal to the size of pieces | |
10778 .parent() | |
10779 .addClass( "ui-effects-explode" ) | |
10780 .css({ | |
10781 position: "absolute", | |
10782 overflow: "hidden", | |
10783 width: width, | |
10784 height: height, | |
10785 left: left + ( show ? mx * width : 0 ), | |
10786 top: top + ( show ? my * height : 0 ), | |
10787 opacity: show ? 0 : 1 | |
10788 }).animate({ | |
10789 left: left + ( show ? 0 : mx * width ), | |
10790 top: top + ( show ? 0 : my * height ), | |
10791 opacity: show ? 1 : 0 | |
10792 }, o.duration || 500, o.easing, childComplete ); | |
10793 } | |
10794 } | |
10795 | |
10796 function animComplete() { | |
10797 el.css({ | |
10798 visibility: "visible" | |
10799 }); | |
10800 $( pieces ).remove(); | |
10801 if ( !show ) { | |
10802 el.hide(); | |
10803 } | |
10804 done(); | |
10805 } | |
10806 }; | |
10807 | |
10808 })(jQuery); | |
10809 | |
10810 (function( $, undefined ) { | |
10811 | |
10812 $.effects.effect.fade = function( o, done ) { | |
10813 var el = $( this ), | |
10814 mode = $.effects.setMode( el, o.mode || "toggle" ); | |
10815 | |
10816 el.animate({ | |
10817 opacity: mode | |
10818 }, { | |
10819 queue: false, | |
10820 duration: o.duration, | |
10821 easing: o.easing, | |
10822 complete: done | |
10823 }); | |
10824 }; | |
10825 | |
10826 })( jQuery ); | |
10827 | |
10828 (function( $, undefined ) { | |
10829 | |
10830 $.effects.effect.fold = function( o, done ) { | |
10831 | |
10832 // Create element | |
10833 var el = $( this ), | |
10834 props = [ "position", "top", "bottom", "left", "right", "height", "width" ], | |
10835 mode = $.effects.setMode( el, o.mode || "hide" ), | |
10836 show = mode === "show", | |
10837 hide = mode === "hide", | |
10838 size = o.size || 15, | |
10839 percent = /([0-9]+)%/.exec( size ), | |
10840 horizFirst = !!o.horizFirst, | |
10841 widthFirst = show !== horizFirst, | |
10842 ref = widthFirst ? [ "width", "height" ] : [ "height", "width" ], | |
10843 duration = o.duration / 2, | |
10844 wrapper, distance, | |
10845 animation1 = {}, | |
10846 animation2 = {}; | |
10847 | |
10848 $.effects.save( el, props ); | |
10849 el.show(); | |
10850 | |
10851 // Create Wrapper | |
10852 wrapper = $.effects.createWrapper( el ).css({ | |
10853 overflow: "hidden" | |
10854 }); | |
10855 distance = widthFirst ? | |
10856 [ wrapper.width(), wrapper.height() ] : | |
10857 [ wrapper.height(), wrapper.width() ]; | |
10858 | |
10859 if ( percent ) { | |
10860 size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ]; | |
10861 } | |
10862 if ( show ) { | |
10863 wrapper.css( horizFirst ? { | |
10864 height: 0, | |
10865 width: size | |
10866 } : { | |
10867 height: size, | |
10868 width: 0 | |
10869 }); | |
10870 } | |
10871 | |
10872 // Animation | |
10873 animation1[ ref[ 0 ] ] = show ? distance[ 0 ] : size; | |
10874 animation2[ ref[ 1 ] ] = show ? distance[ 1 ] : 0; | |
10875 | |
10876 // Animate | |
10877 wrapper | |
10878 .animate( animation1, duration, o.easing ) | |
10879 .animate( animation2, duration, o.easing, function() { | |
10880 if ( hide ) { | |
10881 el.hide(); | |
10882 } | |
10883 $.effects.restore( el, props ); | |
10884 $.effects.removeWrapper( el ); | |
10885 done(); | |
10886 }); | |
10887 | |
10888 }; | |
10889 | |
10890 })(jQuery); | |
10891 | |
10892 (function( $, undefined ) { | |
10893 | |
10894 $.effects.effect.highlight = function( o, done ) { | |
10895 var elem = $( this ), | |
10896 props = [ "backgroundImage", "backgroundColor", "opacity" ], | |
10897 mode = $.effects.setMode( elem, o.mode || "show" ), | |
10898 animation = { | |
10899 backgroundColor: elem.css( "backgroundColor" ) | |
10900 }; | |
10901 | |
10902 if (mode === "hide") { | |
10903 animation.opacity = 0; | |
10904 } | |
10905 | |
10906 $.effects.save( elem, props ); | |
10907 | |
10908 elem | |
10909 .show() | |
10910 .css({ | |
10911 backgroundImage: "none", | |
10912 backgroundColor: o.color || "#ffff99" | |
10913 }) | |
10914 .animate( animation, { | |
10915 queue: false, | |
10916 duration: o.duration, | |
10917 easing: o.easing, | |
10918 complete: function() { | |
10919 if ( mode === "hide" ) { | |
10920 elem.hide(); | |
10921 } | |
10922 $.effects.restore( elem, props ); | |
10923 done(); | |
10924 } | |
10925 }); | |
10926 }; | |
10927 | |
10928 })(jQuery); | |
10929 | |
10930 (function( $, undefined ) { | |
10931 | |
10932 $.effects.effect.pulsate = function( o, done ) { | |
10933 var elem = $( this ), | |
10934 mode = $.effects.setMode( elem, o.mode || "show" ), | |
10935 show = mode === "show", | |
10936 hide = mode === "hide", | |
10937 showhide = ( show || mode === "hide" ), | |
10938 | |
10939 // showing or hiding leaves of the "last" animation | |
10940 anims = ( ( o.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ), | |
10941 duration = o.duration / anims, | |
10942 animateTo = 0, | |
10943 queue = elem.queue(), | |
10944 queuelen = queue.length, | |
10945 i; | |
10946 | |
10947 if ( show || !elem.is(":visible")) { | |
10948 elem.css( "opacity", 0 ).show(); | |
10949 animateTo = 1; | |
10950 } | |
10951 | |
10952 // anims - 1 opacity "toggles" | |
10953 for ( i = 1; i < anims; i++ ) { | |
10954 elem.animate({ | |
10955 opacity: animateTo | |
10956 }, duration, o.easing ); | |
10957 animateTo = 1 - animateTo; | |
10958 } | |
10959 | |
10960 elem.animate({ | |
10961 opacity: animateTo | |
10962 }, duration, o.easing); | |
10963 | |
10964 elem.queue(function() { | |
10965 if ( hide ) { | |
10966 elem.hide(); | |
10967 } | |
10968 done(); | |
10969 }); | |
10970 | |
10971 // We just queued up "anims" animations, we need to put them next in the queue | |
10972 if ( queuelen > 1 ) { | |
10973 queue.splice.apply( queue, | |
10974 [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) ); | |
10975 } | |
10976 elem.dequeue(); | |
10977 }; | |
10978 | |
10979 })(jQuery); | |
10980 | |
10981 (function( $, undefined ) { | |
10982 | |
10983 $.effects.effect.puff = function( o, done ) { | |
10984 var elem = $( this ), | |
10985 mode = $.effects.setMode( elem, o.mode || "hide" ), | |
10986 hide = mode === "hide", | |
10987 percent = parseInt( o.percent, 10 ) || 150, | |
10988 factor = percent / 100, | |
10989 original = { | |
10990 height: elem.height(), | |
10991 width: elem.width(), | |
10992 outerHeight: elem.outerHeight(), | |
10993 outerWidth: elem.outerWidth() | |
10994 }; | |
10995 | |
10996 $.extend( o, { | |
10997 effect: "scale", | |
10998 queue: false, | |
10999 fade: true, | |
11000 mode: mode, | |
11001 complete: done, | |
11002 percent: hide ? percent : 100, | |
11003 from: hide ? | |
11004 original : | |
11005 { | |
11006 height: original.height * factor, | |
11007 width: original.width * factor, | |
11008 outerHeight: original.outerHeight * factor, | |
11009 outerWidth: original.outerWidth * factor | |
11010 } | |
11011 }); | |
11012 | |
11013 elem.effect( o ); | |
11014 }; | |
11015 | |
11016 $.effects.effect.scale = function( o, done ) { | |
11017 | |
11018 // Create element | |
11019 var el = $( this ), | |
11020 options = $.extend( true, {}, o ), | |
11021 mode = $.effects.setMode( el, o.mode || "effect" ), | |
11022 percent = parseInt( o.percent, 10 ) || | |
11023 ( parseInt( o.percent, 10 ) === 0 ? 0 : ( mode === "hide" ? 0 : 100 ) ), | |
11024 direction = o.direction || "both", | |
11025 origin = o.origin, | |
11026 original = { | |
11027 height: el.height(), | |
11028 width: el.width(), | |
11029 outerHeight: el.outerHeight(), | |
11030 outerWidth: el.outerWidth() | |
11031 }, | |
11032 factor = { | |
11033 y: direction !== "horizontal" ? (percent / 100) : 1, | |
11034 x: direction !== "vertical" ? (percent / 100) : 1 | |
11035 }; | |
11036 | |
11037 // We are going to pass this effect to the size effect: | |
11038 options.effect = "size"; | |
11039 options.queue = false; | |
11040 options.complete = done; | |
11041 | |
11042 // Set default origin and restore for show/hide | |
11043 if ( mode !== "effect" ) { | |
11044 options.origin = origin || ["middle","center"]; | |
11045 options.restore = true; | |
11046 } | |
11047 | |
11048 options.from = o.from || ( mode === "show" ? { | |
11049 height: 0, | |
11050 width: 0, | |
11051 outerHeight: 0, | |
11052 outerWidth: 0 | |
11053 } : original ); | |
11054 options.to = { | |
11055 height: original.height * factor.y, | |
11056 width: original.width * factor.x, | |
11057 outerHeight: original.outerHeight * factor.y, | |
11058 outerWidth: original.outerWidth * factor.x | |
11059 }; | |
11060 | |
11061 // Fade option to support puff | |
11062 if ( options.fade ) { | |
11063 if ( mode === "show" ) { | |
11064 options.from.opacity = 0; | |
11065 options.to.opacity = 1; | |
11066 } | |
11067 if ( mode === "hide" ) { | |
11068 options.from.opacity = 1; | |
11069 options.to.opacity = 0; | |
11070 } | |
11071 } | |
11072 | |
11073 // Animate | |
11074 el.effect( options ); | |
11075 | |
11076 }; | |
11077 | |
11078 $.effects.effect.size = function( o, done ) { | |
11079 | |
11080 // Create element | |
11081 var original, baseline, factor, | |
11082 el = $( this ), | |
11083 props0 = [ "position", "top", "bottom", "left", "right", "width", "height", "overflow", "opacity" ], | |
11084 | |
11085 // Always restore | |
11086 props1 = [ "position", "top", "bottom", "left", "right", "overflow", "opacity" ], | |
11087 | |
11088 // Copy for children | |
11089 props2 = [ "width", "height", "overflow" ], | |
11090 cProps = [ "fontSize" ], | |
11091 vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ], | |
11092 hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ], | |
11093 | |
11094 // Set options | |
11095 mode = $.effects.setMode( el, o.mode || "effect" ), | |
11096 restore = o.restore || mode !== "effect", | |
11097 scale = o.scale || "both", | |
11098 origin = o.origin || [ "middle", "center" ], | |
11099 position = el.css( "position" ), | |
11100 props = restore ? props0 : props1, | |
11101 zero = { | |
11102 height: 0, | |
11103 width: 0, | |
11104 outerHeight: 0, | |
11105 outerWidth: 0 | |
11106 }; | |
11107 | |
11108 if ( mode === "show" ) { | |
11109 el.show(); | |
11110 } | |
11111 original = { | |
11112 height: el.height(), | |
11113 width: el.width(), | |
11114 outerHeight: el.outerHeight(), | |
11115 outerWidth: el.outerWidth() | |
11116 }; | |
11117 | |
11118 if ( o.mode === "toggle" && mode === "show" ) { | |
11119 el.from = o.to || zero; | |
11120 el.to = o.from || original; | |
11121 } else { | |
11122 el.from = o.from || ( mode === "show" ? zero : original ); | |
11123 el.to = o.to || ( mode === "hide" ? zero : original ); | |
11124 } | |
11125 | |
11126 // Set scaling factor | |
11127 factor = { | |
11128 from: { | |
11129 y: el.from.height / original.height, | |
11130 x: el.from.width / original.width | |
11131 }, | |
11132 to: { | |
11133 y: el.to.height / original.height, | |
11134 x: el.to.width / original.width | |
11135 } | |
11136 }; | |
11137 | |
11138 // Scale the css box | |
11139 if ( scale === "box" || scale === "both" ) { | |
11140 | |
11141 // Vertical props scaling | |
11142 if ( factor.from.y !== factor.to.y ) { | |
11143 props = props.concat( vProps ); | |
11144 el.from = $.effects.setTransition( el, vProps, factor.from.y, el.from ); | |
11145 el.to = $.effects.setTransition( el, vProps, factor.to.y, el.to ); | |
11146 } | |
11147 | |
11148 // Horizontal props scaling | |
11149 if ( factor.from.x !== factor.to.x ) { | |
11150 props = props.concat( hProps ); | |
11151 el.from = $.effects.setTransition( el, hProps, factor.from.x, el.from ); | |
11152 el.to = $.effects.setTransition( el, hProps, factor.to.x, el.to ); | |
11153 } | |
11154 } | |
11155 | |
11156 // Scale the content | |
11157 if ( scale === "content" || scale === "both" ) { | |
11158 | |
11159 // Vertical props scaling | |
11160 if ( factor.from.y !== factor.to.y ) { | |
11161 props = props.concat( cProps ).concat( props2 ); | |
11162 el.from = $.effects.setTransition( el, cProps, factor.from.y, el.from ); | |
11163 el.to = $.effects.setTransition( el, cProps, factor.to.y, el.to ); | |
11164 } | |
11165 } | |
11166 | |
11167 $.effects.save( el, props ); | |
11168 el.show(); | |
11169 $.effects.createWrapper( el ); | |
11170 el.css( "overflow", "hidden" ).css( el.from ); | |
11171 | |
11172 // Adjust | |
11173 if (origin) { // Calculate baseline shifts | |
11174 baseline = $.effects.getBaseline( origin, original ); | |
11175 el.from.top = ( original.outerHeight - el.outerHeight() ) * baseline.y; | |
11176 el.from.left = ( original.outerWidth - el.outerWidth() ) * baseline.x; | |
11177 el.to.top = ( original.outerHeight - el.to.outerHeight ) * baseline.y; | |
11178 el.to.left = ( original.outerWidth - el.to.outerWidth ) * baseline.x; | |
11179 } | |
11180 el.css( el.from ); // set top & left | |
11181 | |
11182 // Animate | |
11183 if ( scale === "content" || scale === "both" ) { // Scale the children | |
11184 | |
11185 // Add margins/font-size | |
11186 vProps = vProps.concat([ "marginTop", "marginBottom" ]).concat(cProps); | |
11187 hProps = hProps.concat([ "marginLeft", "marginRight" ]); | |
11188 props2 = props0.concat(vProps).concat(hProps); | |
11189 | |
11190 el.find( "*[width]" ).each( function(){ | |
11191 var child = $( this ), | |
11192 c_original = { | |
11193 height: child.height(), | |
11194 width: child.width(), | |
11195 outerHeight: child.outerHeight(), | |
11196 outerWidth: child.outerWidth() | |
11197 }; | |
11198 if (restore) { | |
11199 $.effects.save(child, props2); | |
11200 } | |
11201 | |
11202 child.from = { | |
11203 height: c_original.height * factor.from.y, | |
11204 width: c_original.width * factor.from.x, | |
11205 outerHeight: c_original.outerHeight * factor.from.y, | |
11206 outerWidth: c_original.outerWidth * factor.from.x | |
11207 }; | |
11208 child.to = { | |
11209 height: c_original.height * factor.to.y, | |
11210 width: c_original.width * factor.to.x, | |
11211 outerHeight: c_original.height * factor.to.y, | |
11212 outerWidth: c_original.width * factor.to.x | |
11213 }; | |
11214 | |
11215 // Vertical props scaling | |
11216 if ( factor.from.y !== factor.to.y ) { | |
11217 child.from = $.effects.setTransition( child, vProps, factor.from.y, child.from ); | |
11218 child.to = $.effects.setTransition( child, vProps, factor.to.y, child.to ); | |
11219 } | |
11220 | |
11221 // Horizontal props scaling | |
11222 if ( factor.from.x !== factor.to.x ) { | |
11223 child.from = $.effects.setTransition( child, hProps, factor.from.x, child.from ); | |
11224 child.to = $.effects.setTransition( child, hProps, factor.to.x, child.to ); | |
11225 } | |
11226 | |
11227 // Animate children | |
11228 child.css( child.from ); | |
11229 child.animate( child.to, o.duration, o.easing, function() { | |
11230 | |
11231 // Restore children | |
11232 if ( restore ) { | |
11233 $.effects.restore( child, props2 ); | |
11234 } | |
11235 }); | |
11236 }); | |
11237 } | |
11238 | |
11239 // Animate | |
11240 el.animate( el.to, { | |
11241 queue: false, | |
11242 duration: o.duration, | |
11243 easing: o.easing, | |
11244 complete: function() { | |
11245 if ( el.to.opacity === 0 ) { | |
11246 el.css( "opacity", el.from.opacity ); | |
11247 } | |
11248 if( mode === "hide" ) { | |
11249 el.hide(); | |
11250 } | |
11251 $.effects.restore( el, props ); | |
11252 if ( !restore ) { | |
11253 | |
11254 // we need to calculate our new positioning based on the scaling | |
11255 if ( position === "static" ) { | |
11256 el.css({ | |
11257 position: "relative", | |
11258 top: el.to.top, | |
11259 left: el.to.left | |
11260 }); | |
11261 } else { | |
11262 $.each([ "top", "left" ], function( idx, pos ) { | |
11263 el.css( pos, function( _, str ) { | |
11264 var val = parseInt( str, 10 ), | |
11265 toRef = idx ? el.to.left : el.to.top; | |
11266 | |
11267 // if original was "auto", recalculate the new value from wrapper | |
11268 if ( str === "auto" ) { | |
11269 return toRef + "px"; | |
11270 } | |
11271 | |
11272 return val + toRef + "px"; | |
11273 }); | |
11274 }); | |
11275 } | |
11276 } | |
11277 | |
11278 $.effects.removeWrapper( el ); | |
11279 done(); | |
11280 } | |
11281 }); | |
11282 | |
11283 }; | |
11284 | |
11285 })(jQuery); | |
11286 | |
11287 (function( $, undefined ) { | |
11288 | |
11289 $.effects.effect.shake = function( o, done ) { | |
11290 | |
11291 var el = $( this ), | |
11292 props = [ "position", "top", "bottom", "left", "right", "height", "width" ], | |
11293 mode = $.effects.setMode( el, o.mode || "effect" ), | |
11294 direction = o.direction || "left", | |
11295 distance = o.distance || 20, | |
11296 times = o.times || 3, | |
11297 anims = times * 2 + 1, | |
11298 speed = Math.round(o.duration/anims), | |
11299 ref = (direction === "up" || direction === "down") ? "top" : "left", | |
11300 positiveMotion = (direction === "up" || direction === "left"), | |
11301 animation = {}, | |
11302 animation1 = {}, | |
11303 animation2 = {}, | |
11304 i, | |
11305 | |
11306 // we will need to re-assemble the queue to stack our animations in place | |
11307 queue = el.queue(), | |
11308 queuelen = queue.length; | |
11309 | |
11310 $.effects.save( el, props ); | |
11311 el.show(); | |
11312 $.effects.createWrapper( el ); | |
11313 | |
11314 // Animation | |
11315 animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance; | |
11316 animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2; | |
11317 animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2; | |
11318 | |
11319 // Animate | |
11320 el.animate( animation, speed, o.easing ); | |
11321 | |
11322 // Shakes | |
11323 for ( i = 1; i < times; i++ ) { | |
11324 el.animate( animation1, speed, o.easing ).animate( animation2, speed, o.easing ); | |
11325 } | |
11326 el | |
11327 .animate( animation1, speed, o.easing ) | |
11328 .animate( animation, speed / 2, o.easing ) | |
11329 .queue(function() { | |
11330 if ( mode === "hide" ) { | |
11331 el.hide(); | |
11332 } | |
11333 $.effects.restore( el, props ); | |
11334 $.effects.removeWrapper( el ); | |
11335 done(); | |
11336 }); | |
11337 | |
11338 // inject all the animations we just queued to be first in line (after "inprogress") | |
11339 if ( queuelen > 1) { | |
11340 queue.splice.apply( queue, | |
11341 [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) ); | |
11342 } | |
11343 el.dequeue(); | |
11344 | |
11345 }; | |
11346 | |
11347 })(jQuery); | |
11348 | |
11349 (function( $, undefined ) { | |
11350 | |
11351 $.effects.effect.slide = function( o, done ) { | |
11352 | |
11353 // Create element | |
11354 var el = $( this ), | |
11355 props = [ "position", "top", "bottom", "left", "right", "width", "height" ], | |
11356 mode = $.effects.setMode( el, o.mode || "show" ), | |
11357 show = mode === "show", | |
11358 direction = o.direction || "left", | |
11359 ref = (direction === "up" || direction === "down") ? "top" : "left", | |
11360 positiveMotion = (direction === "up" || direction === "left"), | |
11361 distance, | |
11362 animation = {}; | |
11363 | |
11364 // Adjust | |
11365 $.effects.save( el, props ); | |
11366 el.show(); | |
11367 distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ); | |
11368 | |
11369 $.effects.createWrapper( el ).css({ | |
11370 overflow: "hidden" | |
11371 }); | |
11372 | |
11373 if ( show ) { | |
11374 el.css( ref, positiveMotion ? (isNaN(distance) ? "-" + distance : -distance) : distance ); | |
11375 } | |
11376 | |
11377 // Animation | |
11378 animation[ ref ] = ( show ? | |
11379 ( positiveMotion ? "+=" : "-=") : | |
11380 ( positiveMotion ? "-=" : "+=")) + | |
11381 distance; | |
11382 | |
11383 // Animate | |
11384 el.animate( animation, { | |
11385 queue: false, | |
11386 duration: o.duration, | |
11387 easing: o.easing, | |
11388 complete: function() { | |
11389 if ( mode === "hide" ) { | |
11390 el.hide(); | |
11391 } | |
11392 $.effects.restore( el, props ); | |
11393 $.effects.removeWrapper( el ); | |
11394 done(); | |
11395 } | |
11396 }); | |
11397 }; | |
11398 | |
11399 })(jQuery); | |
11400 | |
11401 (function( $, undefined ) { | |
11402 | |
11403 $.effects.effect.transfer = function( o, done ) { | |
11404 var elem = $( this ), | |
11405 target = $( o.to ), | |
11406 targetFixed = target.css( "position" ) === "fixed", | |
11407 body = $("body"), | |
11408 fixTop = targetFixed ? body.scrollTop() : 0, | |
11409 fixLeft = targetFixed ? body.scrollLeft() : 0, | |
11410 endPosition = target.offset(), | |
11411 animation = { | |
11412 top: endPosition.top - fixTop , | |
11413 left: endPosition.left - fixLeft , | |
11414 height: target.innerHeight(), | |
11415 width: target.innerWidth() | |
11416 }, | |
11417 startPosition = elem.offset(), | |
11418 transfer = $( "<div class='ui-effects-transfer'></div>" ) | |
11419 .appendTo( document.body ) | |
11420 .addClass( o.className ) | |
11421 .css({ | |
11422 top: startPosition.top - fixTop , | |
11423 left: startPosition.left - fixLeft , | |
11424 height: elem.innerHeight(), | |
11425 width: elem.innerWidth(), | |
11426 position: targetFixed ? "fixed" : "absolute" | |
11427 }) | |
11428 .animate( animation, o.duration, o.easing, function() { | |
11429 transfer.remove(); | |
11430 done(); | |
11431 }); | |
11432 }; | |
11433 | |
11434 })(jQuery); | |
11435 | |
11436 (function( $, undefined ) { | |
11437 | |
11438 $.widget( "ui.menu", { | |
11439 version: "1.10.4", | |
11440 defaultElement: "<ul>", | |
11441 delay: 300, | |
11442 options: { | |
11443 icons: { | |
11444 submenu: "ui-icon-carat-1-e" | |
11445 }, | |
11446 menus: "ul", | |
11447 position: { | |
11448 my: "left top", | |
11449 at: "right top" | |
11450 }, | |
11451 role: "menu", | |
11452 | |
11453 // callbacks | |
11454 blur: null, | |
11455 focus: null, | |
11456 select: null | |
11457 }, | |
11458 | |
11459 _create: function() { | |
11460 this.activeMenu = this.element; | |
11461 // flag used to prevent firing of the click handler | |
11462 // as the event bubbles up through nested menus | |
11463 this.mouseHandled = false; | |
11464 this.element | |
11465 .uniqueId() | |
11466 .addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" ) | |
11467 .toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length ) | |
11468 .attr({ | |
11469 role: this.options.role, | |
11470 tabIndex: 0 | |
11471 }) | |
11472 // need to catch all clicks on disabled menu | |
11473 // not possible through _on | |
11474 .bind( "click" + this.eventNamespace, $.proxy(function( event ) { | |
11475 if ( this.options.disabled ) { | |
11476 event.preventDefault(); | |
11477 } | |
11478 }, this )); | |
11479 | |
11480 if ( this.options.disabled ) { | |
11481 this.element | |
11482 .addClass( "ui-state-disabled" ) | |
11483 .attr( "aria-disabled", "true" ); | |
11484 } | |
11485 | |
11486 this._on({ | |
11487 // Prevent focus from sticking to links inside menu after clicking | |
11488 // them (focus should always stay on UL during navigation). | |
11489 "mousedown .ui-menu-item > a": function( event ) { | |
11490 event.preventDefault(); | |
11491 }, | |
11492 "click .ui-state-disabled > a": function( event ) { | |
11493 event.preventDefault(); | |
11494 }, | |
11495 "click .ui-menu-item:has(a)": function( event ) { | |
11496 var target = $( event.target ).closest( ".ui-menu-item" ); | |
11497 if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) { | |
11498 this.select( event ); | |
11499 | |
11500 // Only set the mouseHandled flag if the event will bubble, see #9469. | |
11501 if ( !event.isPropagationStopped() ) { | |
11502 this.mouseHandled = true; | |
11503 } | |
11504 | |
11505 // Open submenu on click | |
11506 if ( target.has( ".ui-menu" ).length ) { | |
11507 this.expand( event ); | |
11508 } else if ( !this.element.is( ":focus" ) && $( this.document[ 0 ].activeElement ).closest( ".ui-menu" ).length ) { | |
11509 | |
11510 // Redirect focus to the menu | |
11511 this.element.trigger( "focus", [ true ] ); | |
11512 | |
11513 // If the active item is on the top level, let it stay active. | |
11514 // Otherwise, blur the active item since it is no longer visible. | |
11515 if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) { | |
11516 clearTimeout( this.timer ); | |
11517 } | |
11518 } | |
11519 } | |
11520 }, | |
11521 "mouseenter .ui-menu-item": function( event ) { | |
11522 var target = $( event.currentTarget ); | |
11523 // Remove ui-state-active class from siblings of the newly focused menu item | |
11524 // to avoid a jump caused by adjacent elements both having a class with a border | |
11525 target.siblings().children( ".ui-state-active" ).removeClass( "ui-state-active" ); | |
11526 this.focus( event, target ); | |
11527 }, | |
11528 mouseleave: "collapseAll", | |
11529 "mouseleave .ui-menu": "collapseAll", | |
11530 focus: function( event, keepActiveItem ) { | |
11531 // If there's already an active item, keep it active | |
11532 // If not, activate the first item | |
11533 var item = this.active || this.element.children( ".ui-menu-item" ).eq( 0 ); | |
11534 | |
11535 if ( !keepActiveItem ) { | |
11536 this.focus( event, item ); | |
11537 } | |
11538 }, | |
11539 blur: function( event ) { | |
11540 this._delay(function() { | |
11541 if ( !$.contains( this.element[0], this.document[0].activeElement ) ) { | |
11542 this.collapseAll( event ); | |
11543 } | |
11544 }); | |
11545 }, | |
11546 keydown: "_keydown" | |
11547 }); | |
11548 | |
11549 this.refresh(); | |
11550 | |
11551 // Clicks outside of a menu collapse any open menus | |
11552 this._on( this.document, { | |
11553 click: function( event ) { | |
11554 if ( !$( event.target ).closest( ".ui-menu" ).length ) { | |
11555 this.collapseAll( event ); | |
11556 } | |
11557 | |
11558 // Reset the mouseHandled flag | |
11559 this.mouseHandled = false; | |
11560 } | |
11561 }); | |
11562 }, | |
11563 | |
11564 _destroy: function() { | |
11565 // Destroy (sub)menus | |
11566 this.element | |
11567 .removeAttr( "aria-activedescendant" ) | |
11568 .find( ".ui-menu" ).addBack() | |
11569 .removeClass( "ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons" ) | |
11570 .removeAttr( "role" ) | |
11571 .removeAttr( "tabIndex" ) | |
11572 .removeAttr( "aria-labelledby" ) | |
11573 .removeAttr( "aria-expanded" ) | |
11574 .removeAttr( "aria-hidden" ) | |
11575 .removeAttr( "aria-disabled" ) | |
11576 .removeUniqueId() | |
11577 .show(); | |
11578 | |
11579 // Destroy menu items | |
11580 this.element.find( ".ui-menu-item" ) | |
11581 .removeClass( "ui-menu-item" ) | |
11582 .removeAttr( "role" ) | |
11583 .removeAttr( "aria-disabled" ) | |
11584 .children( "a" ) | |
11585 .removeUniqueId() | |
11586 .removeClass( "ui-corner-all ui-state-hover" ) | |
11587 .removeAttr( "tabIndex" ) | |
11588 .removeAttr( "role" ) | |
11589 .removeAttr( "aria-haspopup" ) | |
11590 .children().each( function() { | |
11591 var elem = $( this ); | |
11592 if ( elem.data( "ui-menu-submenu-carat" ) ) { | |
11593 elem.remove(); | |
11594 } | |
11595 }); | |
11596 | |
11597 // Destroy menu dividers | |
11598 this.element.find( ".ui-menu-divider" ).removeClass( "ui-menu-divider ui-widget-content" ); | |
11599 }, | |
11600 | |
11601 _keydown: function( event ) { | |
11602 var match, prev, character, skip, regex, | |
11603 preventDefault = true; | |
11604 | |
11605 function escape( value ) { | |
11606 return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ); | |
11607 } | |
11608 | |
11609 switch ( event.keyCode ) { | |
11610 case $.ui.keyCode.PAGE_UP: | |
11611 this.previousPage( event ); | |
11612 break; | |
11613 case $.ui.keyCode.PAGE_DOWN: | |
11614 this.nextPage( event ); | |
11615 break; | |
11616 case $.ui.keyCode.HOME: | |
11617 this._move( "first", "first", event ); | |
11618 break; | |
11619 case $.ui.keyCode.END: | |
11620 this._move( "last", "last", event ); | |
11621 break; | |
11622 case $.ui.keyCode.UP: | |
11623 this.previous( event ); | |
11624 break; | |
11625 case $.ui.keyCode.DOWN: | |
11626 this.next( event ); | |
11627 break; | |
11628 case $.ui.keyCode.LEFT: | |
11629 this.collapse( event ); | |
11630 break; | |
11631 case $.ui.keyCode.RIGHT: | |
11632 if ( this.active && !this.active.is( ".ui-state-disabled" ) ) { | |
11633 this.expand( event ); | |
11634 } | |
11635 break; | |
11636 case $.ui.keyCode.ENTER: | |
11637 case $.ui.keyCode.SPACE: | |
11638 this._activate( event ); | |
11639 break; | |
11640 case $.ui.keyCode.ESCAPE: | |
11641 this.collapse( event ); | |
11642 break; | |
11643 default: | |
11644 preventDefault = false; | |
11645 prev = this.previousFilter || ""; | |
11646 character = String.fromCharCode( event.keyCode ); | |
11647 skip = false; | |
11648 | |
11649 clearTimeout( this.filterTimer ); | |
11650 | |
11651 if ( character === prev ) { | |
11652 skip = true; | |
11653 } else { | |
11654 character = prev + character; | |
11655 } | |
11656 | |
11657 regex = new RegExp( "^" + escape( character ), "i" ); | |
11658 match = this.activeMenu.children( ".ui-menu-item" ).filter(function() { | |
11659 return regex.test( $( this ).children( "a" ).text() ); | |
11660 }); | |
11661 match = skip && match.index( this.active.next() ) !== -1 ? | |
11662 this.active.nextAll( ".ui-menu-item" ) : | |
11663 match; | |
11664 | |
11665 // If no matches on the current filter, reset to the last character pressed | |
11666 // to move down the menu to the first item that starts with that character | |
11667 if ( !match.length ) { | |
11668 character = String.fromCharCode( event.keyCode ); | |
11669 regex = new RegExp( "^" + escape( character ), "i" ); | |
11670 match = this.activeMenu.children( ".ui-menu-item" ).filter(function() { | |
11671 return regex.test( $( this ).children( "a" ).text() ); | |
11672 }); | |
11673 } | |
11674 | |
11675 if ( match.length ) { | |
11676 this.focus( event, match ); | |
11677 if ( match.length > 1 ) { | |
11678 this.previousFilter = character; | |
11679 this.filterTimer = this._delay(function() { | |
11680 delete this.previousFilter; | |
11681 }, 1000 ); | |
11682 } else { | |
11683 delete this.previousFilter; | |
11684 } | |
11685 } else { | |
11686 delete this.previousFilter; | |
11687 } | |
11688 } | |
11689 | |
11690 if ( preventDefault ) { | |
11691 event.preventDefault(); | |
11692 } | |
11693 }, | |
11694 | |
11695 _activate: function( event ) { | |
11696 if ( !this.active.is( ".ui-state-disabled" ) ) { | |
11697 if ( this.active.children( "a[aria-haspopup='true']" ).length ) { | |
11698 this.expand( event ); | |
11699 } else { | |
11700 this.select( event ); | |
11701 } | |
11702 } | |
11703 }, | |
11704 | |
11705 refresh: function() { | |
11706 var menus, | |
11707 icon = this.options.icons.submenu, | |
11708 submenus = this.element.find( this.options.menus ); | |
11709 | |
11710 this.element.toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length ); | |
11711 | |
11712 // Initialize nested menus | |
11713 submenus.filter( ":not(.ui-menu)" ) | |
11714 .addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" ) | |
11715 .hide() | |
11716 .attr({ | |
11717 role: this.options.role, | |
11718 "aria-hidden": "true", | |
11719 "aria-expanded": "false" | |
11720 }) | |
11721 .each(function() { | |
11722 var menu = $( this ), | |
11723 item = menu.prev( "a" ), | |
11724 submenuCarat = $( "<span>" ) | |
11725 .addClass( "ui-menu-icon ui-icon " + icon ) | |
11726 .data( "ui-menu-submenu-carat", true ); | |
11727 | |
11728 item | |
11729 .attr( "aria-haspopup", "true" ) | |
11730 .prepend( submenuCarat ); | |
11731 menu.attr( "aria-labelledby", item.attr( "id" ) ); | |
11732 }); | |
11733 | |
11734 menus = submenus.add( this.element ); | |
11735 | |
11736 // Don't refresh list items that are already adapted | |
11737 menus.children( ":not(.ui-menu-item):has(a)" ) | |
11738 .addClass( "ui-menu-item" ) | |
11739 .attr( "role", "presentation" ) | |
11740 .children( "a" ) | |
11741 .uniqueId() | |
11742 .addClass( "ui-corner-all" ) | |
11743 .attr({ | |
11744 tabIndex: -1, | |
11745 role: this._itemRole() | |
11746 }); | |
11747 | |
11748 // Initialize unlinked menu-items containing spaces and/or dashes only as dividers | |
11749 menus.children( ":not(.ui-menu-item)" ).each(function() { | |
11750 var item = $( this ); | |
11751 // hyphen, em dash, en dash | |
11752 if ( !/[^\-\u2014\u2013\s]/.test( item.text() ) ) { | |
11753 item.addClass( "ui-widget-content ui-menu-divider" ); | |
11754 } | |
11755 }); | |
11756 | |
11757 // Add aria-disabled attribute to any disabled menu item | |
11758 menus.children( ".ui-state-disabled" ).attr( "aria-disabled", "true" ); | |
11759 | |
11760 // If the active item has been removed, blur the menu | |
11761 if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) { | |
11762 this.blur(); | |
11763 } | |
11764 }, | |
11765 | |
11766 _itemRole: function() { | |
11767 return { | |
11768 menu: "menuitem", | |
11769 listbox: "option" | |
11770 }[ this.options.role ]; | |
11771 }, | |
11772 | |
11773 _setOption: function( key, value ) { | |
11774 if ( key === "icons" ) { | |
11775 this.element.find( ".ui-menu-icon" ) | |
11776 .removeClass( this.options.icons.submenu ) | |
11777 .addClass( value.submenu ); | |
11778 } | |
11779 this._super( key, value ); | |
11780 }, | |
11781 | |
11782 focus: function( event, item ) { | |
11783 var nested, focused; | |
11784 this.blur( event, event && event.type === "focus" ); | |
11785 | |
11786 this._scrollIntoView( item ); | |
11787 | |
11788 this.active = item.first(); | |
11789 focused = this.active.children( "a" ).addClass( "ui-state-focus" ); | |
11790 // Only update aria-activedescendant if there's a role | |
11791 // otherwise we assume focus is managed elsewhere | |
11792 if ( this.options.role ) { | |
11793 this.element.attr( "aria-activedescendant", focused.attr( "id" ) ); | |
11794 } | |
11795 | |
11796 // Highlight active parent menu item, if any | |
11797 this.active | |
11798 .parent() | |
11799 .closest( ".ui-menu-item" ) | |
11800 .children( "a:first" ) | |
11801 .addClass( "ui-state-active" ); | |
11802 | |
11803 if ( event && event.type === "keydown" ) { | |
11804 this._close(); | |
11805 } else { | |
11806 this.timer = this._delay(function() { | |
11807 this._close(); | |
11808 }, this.delay ); | |
11809 } | |
11810 | |
11811 nested = item.children( ".ui-menu" ); | |
11812 if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) { | |
11813 this._startOpening(nested); | |
11814 } | |
11815 this.activeMenu = item.parent(); | |
11816 | |
11817 this._trigger( "focus", event, { item: item } ); | |
11818 }, | |
11819 | |
11820 _scrollIntoView: function( item ) { | |
11821 var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight; | |
11822 if ( this._hasScroll() ) { | |
11823 borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0; | |
11824 paddingTop = parseFloat( $.css( this.activeMenu[0], "paddingTop" ) ) || 0; | |
11825 offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop; | |
11826 scroll = this.activeMenu.scrollTop(); | |
11827 elementHeight = this.activeMenu.height(); | |
11828 itemHeight = item.height(); | |
11829 | |
11830 if ( offset < 0 ) { | |
11831 this.activeMenu.scrollTop( scroll + offset ); | |
11832 } else if ( offset + itemHeight > elementHeight ) { | |
11833 this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight ); | |
11834 } | |
11835 } | |
11836 }, | |
11837 | |
11838 blur: function( event, fromFocus ) { | |
11839 if ( !fromFocus ) { | |
11840 clearTimeout( this.timer ); | |
11841 } | |
11842 | |
11843 if ( !this.active ) { | |
11844 return; | |
11845 } | |
11846 | |
11847 this.active.children( "a" ).removeClass( "ui-state-focus" ); | |
11848 this.active = null; | |
11849 | |
11850 this._trigger( "blur", event, { item: this.active } ); | |
11851 }, | |
11852 | |
11853 _startOpening: function( submenu ) { | |
11854 clearTimeout( this.timer ); | |
11855 | |
11856 // Don't open if already open fixes a Firefox bug that caused a .5 pixel | |
11857 // shift in the submenu position when mousing over the carat icon | |
11858 if ( submenu.attr( "aria-hidden" ) !== "true" ) { | |
11859 return; | |
11860 } | |
11861 | |
11862 this.timer = this._delay(function() { | |
11863 this._close(); | |
11864 this._open( submenu ); | |
11865 }, this.delay ); | |
11866 }, | |
11867 | |
11868 _open: function( submenu ) { | |
11869 var position = $.extend({ | |
11870 of: this.active | |
11871 }, this.options.position ); | |
11872 | |
11873 clearTimeout( this.timer ); | |
11874 this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) ) | |
11875 .hide() | |
11876 .attr( "aria-hidden", "true" ); | |
11877 | |
11878 submenu | |
11879 .show() | |
11880 .removeAttr( "aria-hidden" ) | |
11881 .attr( "aria-expanded", "true" ) | |
11882 .position( position ); | |
11883 }, | |
11884 | |
11885 collapseAll: function( event, all ) { | |
11886 clearTimeout( this.timer ); | |
11887 this.timer = this._delay(function() { | |
11888 // If we were passed an event, look for the submenu that contains the event | |
11889 var currentMenu = all ? this.element : | |
11890 $( event && event.target ).closest( this.element.find( ".ui-menu" ) ); | |
11891 | |
11892 // If we found no valid submenu ancestor, use the main menu to close all sub menus anyway | |
11893 if ( !currentMenu.length ) { | |
11894 currentMenu = this.element; | |
11895 } | |
11896 | |
11897 this._close( currentMenu ); | |
11898 | |
11899 this.blur( event ); | |
11900 this.activeMenu = currentMenu; | |
11901 }, this.delay ); | |
11902 }, | |
11903 | |
11904 // With no arguments, closes the currently active menu - if nothing is active | |
11905 // it closes all menus. If passed an argument, it will search for menus BELOW | |
11906 _close: function( startMenu ) { | |
11907 if ( !startMenu ) { | |
11908 startMenu = this.active ? this.active.parent() : this.element; | |
11909 } | |
11910 | |
11911 startMenu | |
11912 .find( ".ui-menu" ) | |
11913 .hide() | |
11914 .attr( "aria-hidden", "true" ) | |
11915 .attr( "aria-expanded", "false" ) | |
11916 .end() | |
11917 .find( "a.ui-state-active" ) | |
11918 .removeClass( "ui-state-active" ); | |
11919 }, | |
11920 | |
11921 collapse: function( event ) { | |
11922 var newItem = this.active && | |
11923 this.active.parent().closest( ".ui-menu-item", this.element ); | |
11924 if ( newItem && newItem.length ) { | |
11925 this._close(); | |
11926 this.focus( event, newItem ); | |
11927 } | |
11928 }, | |
11929 | |
11930 expand: function( event ) { | |
11931 var newItem = this.active && | |
11932 this.active | |
11933 .children( ".ui-menu " ) | |
11934 .children( ".ui-menu-item" ) | |
11935 .first(); | |
11936 | |
11937 if ( newItem && newItem.length ) { | |
11938 this._open( newItem.parent() ); | |
11939 | |
11940 // Delay so Firefox will not hide activedescendant change in expanding submenu from AT | |
11941 this._delay(function() { | |
11942 this.focus( event, newItem ); | |
11943 }); | |
11944 } | |
11945 }, | |
11946 | |
11947 next: function( event ) { | |
11948 this._move( "next", "first", event ); | |
11949 }, | |
11950 | |
11951 previous: function( event ) { | |
11952 this._move( "prev", "last", event ); | |
11953 }, | |
11954 | |
11955 isFirstItem: function() { | |
11956 return this.active && !this.active.prevAll( ".ui-menu-item" ).length; | |
11957 }, | |
11958 | |
11959 isLastItem: function() { | |
11960 return this.active && !this.active.nextAll( ".ui-menu-item" ).length; | |
11961 }, | |
11962 | |
11963 _move: function( direction, filter, event ) { | |
11964 var next; | |
11965 if ( this.active ) { | |
11966 if ( direction === "first" || direction === "last" ) { | |
11967 next = this.active | |
11968 [ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" ) | |
11969 .eq( -1 ); | |
11970 } else { | |
11971 next = this.active | |
11972 [ direction + "All" ]( ".ui-menu-item" ) | |
11973 .eq( 0 ); | |
11974 } | |
11975 } | |
11976 if ( !next || !next.length || !this.active ) { | |
11977 next = this.activeMenu.children( ".ui-menu-item" )[ filter ](); | |
11978 } | |
11979 | |
11980 this.focus( event, next ); | |
11981 }, | |
11982 | |
11983 nextPage: function( event ) { | |
11984 var item, base, height; | |
11985 | |
11986 if ( !this.active ) { | |
11987 this.next( event ); | |
11988 return; | |
11989 } | |
11990 if ( this.isLastItem() ) { | |
11991 return; | |
11992 } | |
11993 if ( this._hasScroll() ) { | |
11994 base = this.active.offset().top; | |
11995 height = this.element.height(); | |
11996 this.active.nextAll( ".ui-menu-item" ).each(function() { | |
11997 item = $( this ); | |
11998 return item.offset().top - base - height < 0; | |
11999 }); | |
12000 | |
12001 this.focus( event, item ); | |
12002 } else { | |
12003 this.focus( event, this.activeMenu.children( ".ui-menu-item" ) | |
12004 [ !this.active ? "first" : "last" ]() ); | |
12005 } | |
12006 }, | |
12007 | |
12008 previousPage: function( event ) { | |
12009 var item, base, height; | |
12010 if ( !this.active ) { | |
12011 this.next( event ); | |
12012 return; | |
12013 } | |
12014 if ( this.isFirstItem() ) { | |
12015 return; | |
12016 } | |
12017 if ( this._hasScroll() ) { | |
12018 base = this.active.offset().top; | |
12019 height = this.element.height(); | |
12020 this.active.prevAll( ".ui-menu-item" ).each(function() { | |
12021 item = $( this ); | |
12022 return item.offset().top - base + height > 0; | |
12023 }); | |
12024 | |
12025 this.focus( event, item ); | |
12026 } else { | |
12027 this.focus( event, this.activeMenu.children( ".ui-menu-item" ).first() ); | |
12028 } | |
12029 }, | |
12030 | |
12031 _hasScroll: function() { | |
12032 return this.element.outerHeight() < this.element.prop( "scrollHeight" ); | |
12033 }, | |
12034 | |
12035 select: function( event ) { | |
12036 // TODO: It should never be possible to not have an active item at this | |
12037 // point, but the tests don't trigger mouseenter before click. | |
12038 this.active = this.active || $( event.target ).closest( ".ui-menu-item" ); | |
12039 var ui = { item: this.active }; | |
12040 if ( !this.active.has( ".ui-menu" ).length ) { | |
12041 this.collapseAll( event, true ); | |
12042 } | |
12043 this._trigger( "select", event, ui ); | |
12044 } | |
12045 }); | |
12046 | |
12047 }( jQuery )); | |
12048 | |
12049 (function( $, undefined ) { | |
12050 | |
12051 $.ui = $.ui || {}; | |
12052 | |
12053 var cachedScrollbarWidth, | |
12054 max = Math.max, | |
12055 abs = Math.abs, | |
12056 round = Math.round, | |
12057 rhorizontal = /left|center|right/, | |
12058 rvertical = /top|center|bottom/, | |
12059 roffset = /[\+\-]\d+(\.[\d]+)?%?/, | |
12060 rposition = /^\w+/, | |
12061 rpercent = /%$/, | |
12062 _position = $.fn.position; | |
12063 | |
12064 function getOffsets( offsets, width, height ) { | |
12065 return [ | |
12066 parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ), | |
12067 parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 ) | |
12068 ]; | |
12069 } | |
12070 | |
12071 function parseCss( element, property ) { | |
12072 return parseInt( $.css( element, property ), 10 ) || 0; | |
12073 } | |
12074 | |
12075 function getDimensions( elem ) { | |
12076 var raw = elem[0]; | |
12077 if ( raw.nodeType === 9 ) { | |
12078 return { | |
12079 width: elem.width(), | |
12080 height: elem.height(), | |
12081 offset: { top: 0, left: 0 } | |
12082 }; | |
12083 } | |
12084 if ( $.isWindow( raw ) ) { | |
12085 return { | |
12086 width: elem.width(), | |
12087 height: elem.height(), | |
12088 offset: { top: elem.scrollTop(), left: elem.scrollLeft() } | |
12089 }; | |
12090 } | |
12091 if ( raw.preventDefault ) { | |
12092 return { | |
12093 width: 0, | |
12094 height: 0, | |
12095 offset: { top: raw.pageY, left: raw.pageX } | |
12096 }; | |
12097 } | |
12098 return { | |
12099 width: elem.outerWidth(), | |
12100 height: elem.outerHeight(), | |
12101 offset: elem.offset() | |
12102 }; | |
12103 } | |
12104 | |
12105 $.position = { | |
12106 scrollbarWidth: function() { | |
12107 if ( cachedScrollbarWidth !== undefined ) { | |
12108 return cachedScrollbarWidth; | |
12109 } | |
12110 var w1, w2, | |
12111 div = $( "<div style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>" ), | |
12112 innerDiv = div.children()[0]; | |
12113 | |
12114 $( "body" ).append( div ); | |
12115 w1 = innerDiv.offsetWidth; | |
12116 div.css( "overflow", "scroll" ); | |
12117 | |
12118 w2 = innerDiv.offsetWidth; | |
12119 | |
12120 if ( w1 === w2 ) { | |
12121 w2 = div[0].clientWidth; | |
12122 } | |
12123 | |
12124 div.remove(); | |
12125 | |
12126 return (cachedScrollbarWidth = w1 - w2); | |
12127 }, | |
12128 getScrollInfo: function( within ) { | |
12129 var overflowX = within.isWindow || within.isDocument ? "" : | |
12130 within.element.css( "overflow-x" ), | |
12131 overflowY = within.isWindow || within.isDocument ? "" : | |
12132 within.element.css( "overflow-y" ), | |
12133 hasOverflowX = overflowX === "scroll" || | |
12134 ( overflowX === "auto" && within.width < within.element[0].scrollWidth ), | |
12135 hasOverflowY = overflowY === "scroll" || | |
12136 ( overflowY === "auto" && within.height < within.element[0].scrollHeight ); | |
12137 return { | |
12138 width: hasOverflowY ? $.position.scrollbarWidth() : 0, | |
12139 height: hasOverflowX ? $.position.scrollbarWidth() : 0 | |
12140 }; | |
12141 }, | |
12142 getWithinInfo: function( element ) { | |
12143 var withinElement = $( element || window ), | |
12144 isWindow = $.isWindow( withinElement[0] ), | |
12145 isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9; | |
12146 return { | |
12147 element: withinElement, | |
12148 isWindow: isWindow, | |
12149 isDocument: isDocument, | |
12150 offset: withinElement.offset() || { left: 0, top: 0 }, | |
12151 scrollLeft: withinElement.scrollLeft(), | |
12152 scrollTop: withinElement.scrollTop(), | |
12153 width: isWindow ? withinElement.width() : withinElement.outerWidth(), | |
12154 height: isWindow ? withinElement.height() : withinElement.outerHeight() | |
12155 }; | |
12156 } | |
12157 }; | |
12158 | |
12159 $.fn.position = function( options ) { | |
12160 if ( !options || !options.of ) { | |
12161 return _position.apply( this, arguments ); | |
12162 } | |
12163 | |
12164 // make a copy, we don't want to modify arguments | |
12165 options = $.extend( {}, options ); | |
12166 | |
12167 var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions, | |
12168 target = $( options.of ), | |
12169 within = $.position.getWithinInfo( options.within ), | |
12170 scrollInfo = $.position.getScrollInfo( within ), | |
12171 collision = ( options.collision || "flip" ).split( " " ), | |
12172 offsets = {}; | |
12173 | |
12174 dimensions = getDimensions( target ); | |
12175 if ( target[0].preventDefault ) { | |
12176 // force left top to allow flipping | |
12177 options.at = "left top"; | |
12178 } | |
12179 targetWidth = dimensions.width; | |
12180 targetHeight = dimensions.height; | |
12181 targetOffset = dimensions.offset; | |
12182 // clone to reuse original targetOffset later | |
12183 basePosition = $.extend( {}, targetOffset ); | |
12184 | |
12185 // force my and at to have valid horizontal and vertical positions | |
12186 // if a value is missing or invalid, it will be converted to center | |
12187 $.each( [ "my", "at" ], function() { | |
12188 var pos = ( options[ this ] || "" ).split( " " ), | |
12189 horizontalOffset, | |
12190 verticalOffset; | |
12191 | |
12192 if ( pos.length === 1) { | |
12193 pos = rhorizontal.test( pos[ 0 ] ) ? | |
12194 pos.concat( [ "center" ] ) : | |
12195 rvertical.test( pos[ 0 ] ) ? | |
12196 [ "center" ].concat( pos ) : | |
12197 [ "center", "center" ]; | |
12198 } | |
12199 pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center"; | |
12200 pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center"; | |
12201 | |
12202 // calculate offsets | |
12203 horizontalOffset = roffset.exec( pos[ 0 ] ); | |
12204 verticalOffset = roffset.exec( pos[ 1 ] ); | |
12205 offsets[ this ] = [ | |
12206 horizontalOffset ? horizontalOffset[ 0 ] : 0, | |
12207 verticalOffset ? verticalOffset[ 0 ] : 0 | |
12208 ]; | |
12209 | |
12210 // reduce to just the positions without the offsets | |
12211 options[ this ] = [ | |
12212 rposition.exec( pos[ 0 ] )[ 0 ], | |
12213 rposition.exec( pos[ 1 ] )[ 0 ] | |
12214 ]; | |
12215 }); | |
12216 | |
12217 // normalize collision option | |
12218 if ( collision.length === 1 ) { | |
12219 collision[ 1 ] = collision[ 0 ]; | |
12220 } | |
12221 | |
12222 if ( options.at[ 0 ] === "right" ) { | |
12223 basePosition.left += targetWidth; | |
12224 } else if ( options.at[ 0 ] === "center" ) { | |
12225 basePosition.left += targetWidth / 2; | |
12226 } | |
12227 | |
12228 if ( options.at[ 1 ] === "bottom" ) { | |
12229 basePosition.top += targetHeight; | |
12230 } else if ( options.at[ 1 ] === "center" ) { | |
12231 basePosition.top += targetHeight / 2; | |
12232 } | |
12233 | |
12234 atOffset = getOffsets( offsets.at, targetWidth, targetHeight ); | |
12235 basePosition.left += atOffset[ 0 ]; | |
12236 basePosition.top += atOffset[ 1 ]; | |
12237 | |
12238 return this.each(function() { | |
12239 var collisionPosition, using, | |
12240 elem = $( this ), | |
12241 elemWidth = elem.outerWidth(), | |
12242 elemHeight = elem.outerHeight(), | |
12243 marginLeft = parseCss( this, "marginLeft" ), | |
12244 marginTop = parseCss( this, "marginTop" ), | |
12245 collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width, | |
12246 collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height, | |
12247 position = $.extend( {}, basePosition ), | |
12248 myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() ); | |
12249 | |
12250 if ( options.my[ 0 ] === "right" ) { | |
12251 position.left -= elemWidth; | |
12252 } else if ( options.my[ 0 ] === "center" ) { | |
12253 position.left -= elemWidth / 2; | |
12254 } | |
12255 | |
12256 if ( options.my[ 1 ] === "bottom" ) { | |
12257 position.top -= elemHeight; | |
12258 } else if ( options.my[ 1 ] === "center" ) { | |
12259 position.top -= elemHeight / 2; | |
12260 } | |
12261 | |
12262 position.left += myOffset[ 0 ]; | |
12263 position.top += myOffset[ 1 ]; | |
12264 | |
12265 // if the browser doesn't support fractions, then round for consistent results | |
12266 if ( !$.support.offsetFractions ) { | |
12267 position.left = round( position.left ); | |
12268 position.top = round( position.top ); | |
12269 } | |
12270 | |
12271 collisionPosition = { | |
12272 marginLeft: marginLeft, | |
12273 marginTop: marginTop | |
12274 }; | |
12275 | |
12276 $.each( [ "left", "top" ], function( i, dir ) { | |
12277 if ( $.ui.position[ collision[ i ] ] ) { | |
12278 $.ui.position[ collision[ i ] ][ dir ]( position, { | |
12279 targetWidth: targetWidth, | |
12280 targetHeight: targetHeight, | |
12281 elemWidth: elemWidth, | |
12282 elemHeight: elemHeight, | |
12283 collisionPosition: collisionPosition, | |
12284 collisionWidth: collisionWidth, | |
12285 collisionHeight: collisionHeight, | |
12286 offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ], | |
12287 my: options.my, | |
12288 at: options.at, | |
12289 within: within, | |
12290 elem : elem | |
12291 }); | |
12292 } | |
12293 }); | |
12294 | |
12295 if ( options.using ) { | |
12296 // adds feedback as second argument to using callback, if present | |
12297 using = function( props ) { | |
12298 var left = targetOffset.left - position.left, | |
12299 right = left + targetWidth - elemWidth, | |
12300 top = targetOffset.top - position.top, | |
12301 bottom = top + targetHeight - elemHeight, | |
12302 feedback = { | |
12303 target: { | |
12304 element: target, | |
12305 left: targetOffset.left, | |
12306 top: targetOffset.top, | |
12307 width: targetWidth, | |
12308 height: targetHeight | |
12309 }, | |
12310 element: { | |
12311 element: elem, | |
12312 left: position.left, | |
12313 top: position.top, | |
12314 width: elemWidth, | |
12315 height: elemHeight | |
12316 }, | |
12317 horizontal: right < 0 ? "left" : left > 0 ? "right" : "center", | |
12318 vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle" | |
12319 }; | |
12320 if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) { | |
12321 feedback.horizontal = "center"; | |
12322 } | |
12323 if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) { | |
12324 feedback.vertical = "middle"; | |
12325 } | |
12326 if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) { | |
12327 feedback.important = "horizontal"; | |
12328 } else { | |
12329 feedback.important = "vertical"; | |
12330 } | |
12331 options.using.call( this, props, feedback ); | |
12332 }; | |
12333 } | |
12334 | |
12335 elem.offset( $.extend( position, { using: using } ) ); | |
12336 }); | |
12337 }; | |
12338 | |
12339 $.ui.position = { | |
12340 fit: { | |
12341 left: function( position, data ) { | |
12342 var within = data.within, | |
12343 withinOffset = within.isWindow ? within.scrollLeft : within.offset.left, | |
12344 outerWidth = within.width, | |
12345 collisionPosLeft = position.left - data.collisionPosition.marginLeft, | |
12346 overLeft = withinOffset - collisionPosLeft, | |
12347 overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset, | |
12348 newOverRight; | |
12349 | |
12350 // element is wider than within | |
12351 if ( data.collisionWidth > outerWidth ) { | |
12352 // element is initially over the left side of within | |
12353 if ( overLeft > 0 && overRight <= 0 ) { | |
12354 newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset; | |
12355 position.left += overLeft - newOverRight; | |
12356 // element is initially over right side of within | |
12357 } else if ( overRight > 0 && overLeft <= 0 ) { | |
12358 position.left = withinOffset; | |
12359 // element is initially over both left and right sides of within | |
12360 } else { | |
12361 if ( overLeft > overRight ) { | |
12362 position.left = withinOffset + outerWidth - data.collisionWidth; | |
12363 } else { | |
12364 position.left = withinOffset; | |
12365 } | |
12366 } | |
12367 // too far left -> align with left edge | |
12368 } else if ( overLeft > 0 ) { | |
12369 position.left += overLeft; | |
12370 // too far right -> align with right edge | |
12371 } else if ( overRight > 0 ) { | |
12372 position.left -= overRight; | |
12373 // adjust based on position and margin | |
12374 } else { | |
12375 position.left = max( position.left - collisionPosLeft, position.left ); | |
12376 } | |
12377 }, | |
12378 top: function( position, data ) { | |
12379 var within = data.within, | |
12380 withinOffset = within.isWindow ? within.scrollTop : within.offset.top, | |
12381 outerHeight = data.within.height, | |
12382 collisionPosTop = position.top - data.collisionPosition.marginTop, | |
12383 overTop = withinOffset - collisionPosTop, | |
12384 overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset, | |
12385 newOverBottom; | |
12386 | |
12387 // element is taller than within | |
12388 if ( data.collisionHeight > outerHeight ) { | |
12389 // element is initially over the top of within | |
12390 if ( overTop > 0 && overBottom <= 0 ) { | |
12391 newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset; | |
12392 position.top += overTop - newOverBottom; | |
12393 // element is initially over bottom of within | |
12394 } else if ( overBottom > 0 && overTop <= 0 ) { | |
12395 position.top = withinOffset; | |
12396 // element is initially over both top and bottom of within | |
12397 } else { | |
12398 if ( overTop > overBottom ) { | |
12399 position.top = withinOffset + outerHeight - data.collisionHeight; | |
12400 } else { | |
12401 position.top = withinOffset; | |
12402 } | |
12403 } | |
12404 // too far up -> align with top | |
12405 } else if ( overTop > 0 ) { | |
12406 position.top += overTop; | |
12407 // too far down -> align with bottom edge | |
12408 } else if ( overBottom > 0 ) { | |
12409 position.top -= overBottom; | |
12410 // adjust based on position and margin | |
12411 } else { | |
12412 position.top = max( position.top - collisionPosTop, position.top ); | |
12413 } | |
12414 } | |
12415 }, | |
12416 flip: { | |
12417 left: function( position, data ) { | |
12418 var within = data.within, | |
12419 withinOffset = within.offset.left + within.scrollLeft, | |
12420 outerWidth = within.width, | |
12421 offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left, | |
12422 collisionPosLeft = position.left - data.collisionPosition.marginLeft, | |
12423 overLeft = collisionPosLeft - offsetLeft, | |
12424 overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft, | |
12425 myOffset = data.my[ 0 ] === "left" ? | |
12426 -data.elemWidth : | |
12427 data.my[ 0 ] === "right" ? | |
12428 data.elemWidth : | |
12429 0, | |
12430 atOffset = data.at[ 0 ] === "left" ? | |
12431 data.targetWidth : | |
12432 data.at[ 0 ] === "right" ? | |
12433 -data.targetWidth : | |
12434 0, | |
12435 offset = -2 * data.offset[ 0 ], | |
12436 newOverRight, | |
12437 newOverLeft; | |
12438 | |
12439 if ( overLeft < 0 ) { | |
12440 newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset; | |
12441 if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) { | |
12442 position.left += myOffset + atOffset + offset; | |
12443 } | |
12444 } | |
12445 else if ( overRight > 0 ) { | |
12446 newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft; | |
12447 if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) { | |
12448 position.left += myOffset + atOffset + offset; | |
12449 } | |
12450 } | |
12451 }, | |
12452 top: function( position, data ) { | |
12453 var within = data.within, | |
12454 withinOffset = within.offset.top + within.scrollTop, | |
12455 outerHeight = within.height, | |
12456 offsetTop = within.isWindow ? within.scrollTop : within.offset.top, | |
12457 collisionPosTop = position.top - data.collisionPosition.marginTop, | |
12458 overTop = collisionPosTop - offsetTop, | |
12459 overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop, | |
12460 top = data.my[ 1 ] === "top", | |
12461 myOffset = top ? | |
12462 -data.elemHeight : | |
12463 data.my[ 1 ] === "bottom" ? | |
12464 data.elemHeight : | |
12465 0, | |
12466 atOffset = data.at[ 1 ] === "top" ? | |
12467 data.targetHeight : | |
12468 data.at[ 1 ] === "bottom" ? | |
12469 -data.targetHeight : | |
12470 0, | |
12471 offset = -2 * data.offset[ 1 ], | |
12472 newOverTop, | |
12473 newOverBottom; | |
12474 if ( overTop < 0 ) { | |
12475 newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset; | |
12476 if ( ( position.top + myOffset + atOffset + offset) > overTop && ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) ) { | |
12477 position.top += myOffset + atOffset + offset; | |
12478 } | |
12479 } | |
12480 else if ( overBottom > 0 ) { | |
12481 newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop; | |
12482 if ( ( position.top + myOffset + atOffset + offset) > overBottom && ( newOverTop > 0 || abs( newOverTop ) < overBottom ) ) { | |
12483 position.top += myOffset + atOffset + offset; | |
12484 } | |
12485 } | |
12486 } | |
12487 }, | |
12488 flipfit: { | |
12489 left: function() { | |
12490 $.ui.position.flip.left.apply( this, arguments ); | |
12491 $.ui.position.fit.left.apply( this, arguments ); | |
12492 }, | |
12493 top: function() { | |
12494 $.ui.position.flip.top.apply( this, arguments ); | |
12495 $.ui.position.fit.top.apply( this, arguments ); | |
12496 } | |
12497 } | |
12498 }; | |
12499 | |
12500 // fraction support test | |
12501 (function () { | |
12502 var testElement, testElementParent, testElementStyle, offsetLeft, i, | |
12503 body = document.getElementsByTagName( "body" )[ 0 ], | |
12504 div = document.createElement( "div" ); | |
12505 | |
12506 //Create a "fake body" for testing based on method used in jQuery.support | |
12507 testElement = document.createElement( body ? "div" : "body" ); | |
12508 testElementStyle = { | |
12509 visibility: "hidden", | |
12510 width: 0, | |
12511 height: 0, | |
12512 border: 0, | |
12513 margin: 0, | |
12514 background: "none" | |
12515 }; | |
12516 if ( body ) { | |
12517 $.extend( testElementStyle, { | |
12518 position: "absolute", | |
12519 left: "-1000px", | |
12520 top: "-1000px" | |
12521 }); | |
12522 } | |
12523 for ( i in testElementStyle ) { | |
12524 testElement.style[ i ] = testElementStyle[ i ]; | |
12525 } | |
12526 testElement.appendChild( div ); | |
12527 testElementParent = body || document.documentElement; | |
12528 testElementParent.insertBefore( testElement, testElementParent.firstChild ); | |
12529 | |
12530 div.style.cssText = "position: absolute; left: 10.7432222px;"; | |
12531 | |
12532 offsetLeft = $( div ).offset().left; | |
12533 $.support.offsetFractions = offsetLeft > 10 && offsetLeft < 11; | |
12534 | |
12535 testElement.innerHTML = ""; | |
12536 testElementParent.removeChild( testElement ); | |
12537 })(); | |
12538 | |
12539 }( jQuery ) ); | |
12540 | |
12541 (function( $, undefined ) { | |
12542 | |
12543 $.widget( "ui.progressbar", { | |
12544 version: "1.10.4", | |
12545 options: { | |
12546 max: 100, | |
12547 value: 0, | |
12548 | |
12549 change: null, | |
12550 complete: null | |
12551 }, | |
12552 | |
12553 min: 0, | |
12554 | |
12555 _create: function() { | |
12556 // Constrain initial value | |
12557 this.oldValue = this.options.value = this._constrainedValue(); | |
12558 | |
12559 this.element | |
12560 .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" ) | |
12561 .attr({ | |
12562 // Only set static values, aria-valuenow and aria-valuemax are | |
12563 // set inside _refreshValue() | |
12564 role: "progressbar", | |
12565 "aria-valuemin": this.min | |
12566 }); | |
12567 | |
12568 this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" ) | |
12569 .appendTo( this.element ); | |
12570 | |
12571 this._refreshValue(); | |
12572 }, | |
12573 | |
12574 _destroy: function() { | |
12575 this.element | |
12576 .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" ) | |
12577 .removeAttr( "role" ) | |
12578 .removeAttr( "aria-valuemin" ) | |
12579 .removeAttr( "aria-valuemax" ) | |
12580 .removeAttr( "aria-valuenow" ); | |
12581 | |
12582 this.valueDiv.remove(); | |
12583 }, | |
12584 | |
12585 value: function( newValue ) { | |
12586 if ( newValue === undefined ) { | |
12587 return this.options.value; | |
12588 } | |
12589 | |
12590 this.options.value = this._constrainedValue( newValue ); | |
12591 this._refreshValue(); | |
12592 }, | |
12593 | |
12594 _constrainedValue: function( newValue ) { | |
12595 if ( newValue === undefined ) { | |
12596 newValue = this.options.value; | |
12597 } | |
12598 | |
12599 this.indeterminate = newValue === false; | |
12600 | |
12601 // sanitize value | |
12602 if ( typeof newValue !== "number" ) { | |
12603 newValue = 0; | |
12604 } | |
12605 | |
12606 return this.indeterminate ? false : | |
12607 Math.min( this.options.max, Math.max( this.min, newValue ) ); | |
12608 }, | |
12609 | |
12610 _setOptions: function( options ) { | |
12611 // Ensure "value" option is set after other values (like max) | |
12612 var value = options.value; | |
12613 delete options.value; | |
12614 | |
12615 this._super( options ); | |
12616 | |
12617 this.options.value = this._constrainedValue( value ); | |
12618 this._refreshValue(); | |
12619 }, | |
12620 | |
12621 _setOption: function( key, value ) { | |
12622 if ( key === "max" ) { | |
12623 // Don't allow a max less than min | |
12624 value = Math.max( this.min, value ); | |
12625 } | |
12626 | |
12627 this._super( key, value ); | |
12628 }, | |
12629 | |
12630 _percentage: function() { | |
12631 return this.indeterminate ? 100 : 100 * ( this.options.value - this.min ) / ( this.options.max - this.min ); | |
12632 }, | |
12633 | |
12634 _refreshValue: function() { | |
12635 var value = this.options.value, | |
12636 percentage = this._percentage(); | |
12637 | |
12638 this.valueDiv | |
12639 .toggle( this.indeterminate || value > this.min ) | |
12640 .toggleClass( "ui-corner-right", value === this.options.max ) | |
12641 .width( percentage.toFixed(0) + "%" ); | |
12642 | |
12643 this.element.toggleClass( "ui-progressbar-indeterminate", this.indeterminate ); | |
12644 | |
12645 if ( this.indeterminate ) { | |
12646 this.element.removeAttr( "aria-valuenow" ); | |
12647 if ( !this.overlayDiv ) { | |
12648 this.overlayDiv = $( "<div class='ui-progressbar-overlay'></div>" ).appendTo( this.valueDiv ); | |
12649 } | |
12650 } else { | |
12651 this.element.attr({ | |
12652 "aria-valuemax": this.options.max, | |
12653 "aria-valuenow": value | |
12654 }); | |
12655 if ( this.overlayDiv ) { | |
12656 this.overlayDiv.remove(); | |
12657 this.overlayDiv = null; | |
12658 } | |
12659 } | |
12660 | |
12661 if ( this.oldValue !== value ) { | |
12662 this.oldValue = value; | |
12663 this._trigger( "change" ); | |
12664 } | |
12665 if ( value === this.options.max ) { | |
12666 this._trigger( "complete" ); | |
12667 } | |
12668 } | |
12669 }); | |
12670 | |
12671 })( jQuery ); | |
12672 | |
12673 (function( $, undefined ) { | |
12674 | |
12675 // number of pages in a slider | |
12676 // (how many times can you page up/down to go through the whole range) | |
12677 var numPages = 5; | |
12678 | |
12679 $.widget( "ui.slider", $.ui.mouse, { | |
12680 version: "1.10.4", | |
12681 widgetEventPrefix: "slide", | |
12682 | |
12683 options: { | |
12684 animate: false, | |
12685 distance: 0, | |
12686 max: 100, | |
12687 min: 0, | |
12688 orientation: "horizontal", | |
12689 range: false, | |
12690 step: 1, | |
12691 value: 0, | |
12692 values: null, | |
12693 | |
12694 // callbacks | |
12695 change: null, | |
12696 slide: null, | |
12697 start: null, | |
12698 stop: null | |
12699 }, | |
12700 | |
12701 _create: function() { | |
12702 this._keySliding = false; | |
12703 this._mouseSliding = false; | |
12704 this._animateOff = true; | |
12705 this._handleIndex = null; | |
12706 this._detectOrientation(); | |
12707 this._mouseInit(); | |
12708 | |
12709 this.element | |
12710 .addClass( "ui-slider" + | |
12711 " ui-slider-" + this.orientation + | |
12712 " ui-widget" + | |
12713 " ui-widget-content" + | |
12714 " ui-corner-all"); | |
12715 | |
12716 this._refresh(); | |
12717 this._setOption( "disabled", this.options.disabled ); | |
12718 | |
12719 this._animateOff = false; | |
12720 }, | |
12721 | |
12722 _refresh: function() { | |
12723 this._createRange(); | |
12724 this._createHandles(); | |
12725 this._setupEvents(); | |
12726 this._refreshValue(); | |
12727 }, | |
12728 | |
12729 _createHandles: function() { | |
12730 var i, handleCount, | |
12731 options = this.options, | |
12732 existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ), | |
12733 handle = "<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>", | |
12734 handles = []; | |
12735 | |
12736 handleCount = ( options.values && options.values.length ) || 1; | |
12737 | |
12738 if ( existingHandles.length > handleCount ) { | |
12739 existingHandles.slice( handleCount ).remove(); | |
12740 existingHandles = existingHandles.slice( 0, handleCount ); | |
12741 } | |
12742 | |
12743 for ( i = existingHandles.length; i < handleCount; i++ ) { | |
12744 handles.push( handle ); | |
12745 } | |
12746 | |
12747 this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) ); | |
12748 | |
12749 this.handle = this.handles.eq( 0 ); | |
12750 | |
12751 this.handles.each(function( i ) { | |
12752 $( this ).data( "ui-slider-handle-index", i ); | |
12753 }); | |
12754 }, | |
12755 | |
12756 _createRange: function() { | |
12757 var options = this.options, | |
12758 classes = ""; | |
12759 | |
12760 if ( options.range ) { | |
12761 if ( options.range === true ) { | |
12762 if ( !options.values ) { | |
12763 options.values = [ this._valueMin(), this._valueMin() ]; | |
12764 } else if ( options.values.length && options.values.length !== 2 ) { | |
12765 options.values = [ options.values[0], options.values[0] ]; | |
12766 } else if ( $.isArray( options.values ) ) { | |
12767 options.values = options.values.slice(0); | |
12768 } | |
12769 } | |
12770 | |
12771 if ( !this.range || !this.range.length ) { | |
12772 this.range = $( "<div></div>" ) | |
12773 .appendTo( this.element ); | |
12774 | |
12775 classes = "ui-slider-range" + | |
12776 // note: this isn't the most fittingly semantic framework class for this element, | |
12777 // but worked best visually with a variety of themes | |
12778 " ui-widget-header ui-corner-all"; | |
12779 } else { | |
12780 this.range.removeClass( "ui-slider-range-min ui-slider-range-max" ) | |
12781 // Handle range switching from true to min/max | |
12782 .css({ | |
12783 "left": "", | |
12784 "bottom": "" | |
12785 }); | |
12786 } | |
12787 | |
12788 this.range.addClass( classes + | |
12789 ( ( options.range === "min" || options.range === "max" ) ? " ui-slider-range-" + options.range : "" ) ); | |
12790 } else { | |
12791 if ( this.range ) { | |
12792 this.range.remove(); | |
12793 } | |
12794 this.range = null; | |
12795 } | |
12796 }, | |
12797 | |
12798 _setupEvents: function() { | |
12799 var elements = this.handles.add( this.range ).filter( "a" ); | |
12800 this._off( elements ); | |
12801 this._on( elements, this._handleEvents ); | |
12802 this._hoverable( elements ); | |
12803 this._focusable( elements ); | |
12804 }, | |
12805 | |
12806 _destroy: function() { | |
12807 this.handles.remove(); | |
12808 if ( this.range ) { | |
12809 this.range.remove(); | |
12810 } | |
12811 | |
12812 this.element | |
12813 .removeClass( "ui-slider" + | |
12814 " ui-slider-horizontal" + | |
12815 " ui-slider-vertical" + | |
12816 " ui-widget" + | |
12817 " ui-widget-content" + | |
12818 " ui-corner-all" ); | |
12819 | |
12820 this._mouseDestroy(); | |
12821 }, | |
12822 | |
12823 _mouseCapture: function( event ) { | |
12824 var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle, | |
12825 that = this, | |
12826 o = this.options; | |
12827 | |
12828 if ( o.disabled ) { | |
12829 return false; | |
12830 } | |
12831 | |
12832 this.elementSize = { | |
12833 width: this.element.outerWidth(), | |
12834 height: this.element.outerHeight() | |
12835 }; | |
12836 this.elementOffset = this.element.offset(); | |
12837 | |
12838 position = { x: event.pageX, y: event.pageY }; | |
12839 normValue = this._normValueFromMouse( position ); | |
12840 distance = this._valueMax() - this._valueMin() + 1; | |
12841 this.handles.each(function( i ) { | |
12842 var thisDistance = Math.abs( normValue - that.values(i) ); | |
12843 if (( distance > thisDistance ) || | |
12844 ( distance === thisDistance && | |
12845 (i === that._lastChangedValue || that.values(i) === o.min ))) { | |
12846 distance = thisDistance; | |
12847 closestHandle = $( this ); | |
12848 index = i; | |
12849 } | |
12850 }); | |
12851 | |
12852 allowed = this._start( event, index ); | |
12853 if ( allowed === false ) { | |
12854 return false; | |
12855 } | |
12856 this._mouseSliding = true; | |
12857 | |
12858 this._handleIndex = index; | |
12859 | |
12860 closestHandle | |
12861 .addClass( "ui-state-active" ) | |
12862 .focus(); | |
12863 | |
12864 offset = closestHandle.offset(); | |
12865 mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" ); | |
12866 this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : { | |
12867 left: event.pageX - offset.left - ( closestHandle.width() / 2 ), | |
12868 top: event.pageY - offset.top - | |
12869 ( closestHandle.height() / 2 ) - | |
12870 ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) - | |
12871 ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) + | |
12872 ( parseInt( closestHandle.css("marginTop"), 10 ) || 0) | |
12873 }; | |
12874 | |
12875 if ( !this.handles.hasClass( "ui-state-hover" ) ) { | |
12876 this._slide( event, index, normValue ); | |
12877 } | |
12878 this._animateOff = true; | |
12879 return true; | |
12880 }, | |
12881 | |
12882 _mouseStart: function() { | |
12883 return true; | |
12884 }, | |
12885 | |
12886 _mouseDrag: function( event ) { | |
12887 var position = { x: event.pageX, y: event.pageY }, | |
12888 normValue = this._normValueFromMouse( position ); | |
12889 | |
12890 this._slide( event, this._handleIndex, normValue ); | |
12891 | |
12892 return false; | |
12893 }, | |
12894 | |
12895 _mouseStop: function( event ) { | |
12896 this.handles.removeClass( "ui-state-active" ); | |
12897 this._mouseSliding = false; | |
12898 | |
12899 this._stop( event, this._handleIndex ); | |
12900 this._change( event, this._handleIndex ); | |
12901 | |
12902 this._handleIndex = null; | |
12903 this._clickOffset = null; | |
12904 this._animateOff = false; | |
12905 | |
12906 return false; | |
12907 }, | |
12908 | |
12909 _detectOrientation: function() { | |
12910 this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal"; | |
12911 }, | |
12912 | |
12913 _normValueFromMouse: function( position ) { | |
12914 var pixelTotal, | |
12915 pixelMouse, | |
12916 percentMouse, | |
12917 valueTotal, | |
12918 valueMouse; | |
12919 | |
12920 if ( this.orientation === "horizontal" ) { | |
12921 pixelTotal = this.elementSize.width; | |
12922 pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 ); | |
12923 } else { | |
12924 pixelTotal = this.elementSize.height; | |
12925 pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 ); | |
12926 } | |
12927 | |
12928 percentMouse = ( pixelMouse / pixelTotal ); | |
12929 if ( percentMouse > 1 ) { | |
12930 percentMouse = 1; | |
12931 } | |
12932 if ( percentMouse < 0 ) { | |
12933 percentMouse = 0; | |
12934 } | |
12935 if ( this.orientation === "vertical" ) { | |
12936 percentMouse = 1 - percentMouse; | |
12937 } | |
12938 | |
12939 valueTotal = this._valueMax() - this._valueMin(); | |
12940 valueMouse = this._valueMin() + percentMouse * valueTotal; | |
12941 | |
12942 return this._trimAlignValue( valueMouse ); | |
12943 }, | |
12944 | |
12945 _start: function( event, index ) { | |
12946 var uiHash = { | |
12947 handle: this.handles[ index ], | |
12948 value: this.value() | |
12949 }; | |
12950 if ( this.options.values && this.options.values.length ) { | |
12951 uiHash.value = this.values( index ); | |
12952 uiHash.values = this.values(); | |
12953 } | |
12954 return this._trigger( "start", event, uiHash ); | |
12955 }, | |
12956 | |
12957 _slide: function( event, index, newVal ) { | |
12958 var otherVal, | |
12959 newValues, | |
12960 allowed; | |
12961 | |
12962 if ( this.options.values && this.options.values.length ) { | |
12963 otherVal = this.values( index ? 0 : 1 ); | |
12964 | |
12965 if ( ( this.options.values.length === 2 && this.options.range === true ) && | |
12966 ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) ) | |
12967 ) { | |
12968 newVal = otherVal; | |
12969 } | |
12970 | |
12971 if ( newVal !== this.values( index ) ) { | |
12972 newValues = this.values(); | |
12973 newValues[ index ] = newVal; | |
12974 // A slide can be canceled by returning false from the slide callback | |
12975 allowed = this._trigger( "slide", event, { | |
12976 handle: this.handles[ index ], | |
12977 value: newVal, | |
12978 values: newValues | |
12979 } ); | |
12980 otherVal = this.values( index ? 0 : 1 ); | |
12981 if ( allowed !== false ) { | |
12982 this.values( index, newVal ); | |
12983 } | |
12984 } | |
12985 } else { | |
12986 if ( newVal !== this.value() ) { | |
12987 // A slide can be canceled by returning false from the slide callback | |
12988 allowed = this._trigger( "slide", event, { | |
12989 handle: this.handles[ index ], | |
12990 value: newVal | |
12991 } ); | |
12992 if ( allowed !== false ) { | |
12993 this.value( newVal ); | |
12994 } | |
12995 } | |
12996 } | |
12997 }, | |
12998 | |
12999 _stop: function( event, index ) { | |
13000 var uiHash = { | |
13001 handle: this.handles[ index ], | |
13002 value: this.value() | |
13003 }; | |
13004 if ( this.options.values && this.options.values.length ) { | |
13005 uiHash.value = this.values( index ); | |
13006 uiHash.values = this.values(); | |
13007 } | |
13008 | |
13009 this._trigger( "stop", event, uiHash ); | |
13010 }, | |
13011 | |
13012 _change: function( event, index ) { | |
13013 if ( !this._keySliding && !this._mouseSliding ) { | |
13014 var uiHash = { | |
13015 handle: this.handles[ index ], | |
13016 value: this.value() | |
13017 }; | |
13018 if ( this.options.values && this.options.values.length ) { | |
13019 uiHash.value = this.values( index ); | |
13020 uiHash.values = this.values(); | |
13021 } | |
13022 | |
13023 //store the last changed value index for reference when handles overlap | |
13024 this._lastChangedValue = index; | |
13025 | |
13026 this._trigger( "change", event, uiHash ); | |
13027 } | |
13028 }, | |
13029 | |
13030 value: function( newValue ) { | |
13031 if ( arguments.length ) { | |
13032 this.options.value = this._trimAlignValue( newValue ); | |
13033 this._refreshValue(); | |
13034 this._change( null, 0 ); | |
13035 return; | |
13036 } | |
13037 | |
13038 return this._value(); | |
13039 }, | |
13040 | |
13041 values: function( index, newValue ) { | |
13042 var vals, | |
13043 newValues, | |
13044 i; | |
13045 | |
13046 if ( arguments.length > 1 ) { | |
13047 this.options.values[ index ] = this._trimAlignValue( newValue ); | |
13048 this._refreshValue(); | |
13049 this._change( null, index ); | |
13050 return; | |
13051 } | |
13052 | |
13053 if ( arguments.length ) { | |
13054 if ( $.isArray( arguments[ 0 ] ) ) { | |
13055 vals = this.options.values; | |
13056 newValues = arguments[ 0 ]; | |
13057 for ( i = 0; i < vals.length; i += 1 ) { | |
13058 vals[ i ] = this._trimAlignValue( newValues[ i ] ); | |
13059 this._change( null, i ); | |
13060 } | |
13061 this._refreshValue(); | |
13062 } else { | |
13063 if ( this.options.values && this.options.values.length ) { | |
13064 return this._values( index ); | |
13065 } else { | |
13066 return this.value(); | |
13067 } | |
13068 } | |
13069 } else { | |
13070 return this._values(); | |
13071 } | |
13072 }, | |
13073 | |
13074 _setOption: function( key, value ) { | |
13075 var i, | |
13076 valsLength = 0; | |
13077 | |
13078 if ( key === "range" && this.options.range === true ) { | |
13079 if ( value === "min" ) { | |
13080 this.options.value = this._values( 0 ); | |
13081 this.options.values = null; | |
13082 } else if ( value === "max" ) { | |
13083 this.options.value = this._values( this.options.values.length-1 ); | |
13084 this.options.values = null; | |
13085 } | |
13086 } | |
13087 | |
13088 if ( $.isArray( this.options.values ) ) { | |
13089 valsLength = this.options.values.length; | |
13090 } | |
13091 | |
13092 $.Widget.prototype._setOption.apply( this, arguments ); | |
13093 | |
13094 switch ( key ) { | |
13095 case "orientation": | |
13096 this._detectOrientation(); | |
13097 this.element | |
13098 .removeClass( "ui-slider-horizontal ui-slider-vertical" ) | |
13099 .addClass( "ui-slider-" + this.orientation ); | |
13100 this._refreshValue(); | |
13101 break; | |
13102 case "value": | |
13103 this._animateOff = true; | |
13104 this._refreshValue(); | |
13105 this._change( null, 0 ); | |
13106 this._animateOff = false; | |
13107 break; | |
13108 case "values": | |
13109 this._animateOff = true; | |
13110 this._refreshValue(); | |
13111 for ( i = 0; i < valsLength; i += 1 ) { | |
13112 this._change( null, i ); | |
13113 } | |
13114 this._animateOff = false; | |
13115 break; | |
13116 case "min": | |
13117 case "max": | |
13118 this._animateOff = true; | |
13119 this._refreshValue(); | |
13120 this._animateOff = false; | |
13121 break; | |
13122 case "range": | |
13123 this._animateOff = true; | |
13124 this._refresh(); | |
13125 this._animateOff = false; | |
13126 break; | |
13127 } | |
13128 }, | |
13129 | |
13130 //internal value getter | |
13131 // _value() returns value trimmed by min and max, aligned by step | |
13132 _value: function() { | |
13133 var val = this.options.value; | |
13134 val = this._trimAlignValue( val ); | |
13135 | |
13136 return val; | |
13137 }, | |
13138 | |
13139 //internal values getter | |
13140 // _values() returns array of values trimmed by min and max, aligned by step | |
13141 // _values( index ) returns single value trimmed by min and max, aligned by step | |
13142 _values: function( index ) { | |
13143 var val, | |
13144 vals, | |
13145 i; | |
13146 | |
13147 if ( arguments.length ) { | |
13148 val = this.options.values[ index ]; | |
13149 val = this._trimAlignValue( val ); | |
13150 | |
13151 return val; | |
13152 } else if ( this.options.values && this.options.values.length ) { | |
13153 // .slice() creates a copy of the array | |
13154 // this copy gets trimmed by min and max and then returned | |
13155 vals = this.options.values.slice(); | |
13156 for ( i = 0; i < vals.length; i+= 1) { | |
13157 vals[ i ] = this._trimAlignValue( vals[ i ] ); | |
13158 } | |
13159 | |
13160 return vals; | |
13161 } else { | |
13162 return []; | |
13163 } | |
13164 }, | |
13165 | |
13166 // returns the step-aligned value that val is closest to, between (inclusive) min and max | |
13167 _trimAlignValue: function( val ) { | |
13168 if ( val <= this._valueMin() ) { | |
13169 return this._valueMin(); | |
13170 } | |
13171 if ( val >= this._valueMax() ) { | |
13172 return this._valueMax(); | |
13173 } | |
13174 var step = ( this.options.step > 0 ) ? this.options.step : 1, | |
13175 valModStep = (val - this._valueMin()) % step, | |
13176 alignValue = val - valModStep; | |
13177 | |
13178 if ( Math.abs(valModStep) * 2 >= step ) { | |
13179 alignValue += ( valModStep > 0 ) ? step : ( -step ); | |
13180 } | |
13181 | |
13182 // Since JavaScript has problems with large floats, round | |
13183 // the final value to 5 digits after the decimal point (see #4124) | |
13184 return parseFloat( alignValue.toFixed(5) ); | |
13185 }, | |
13186 | |
13187 _valueMin: function() { | |
13188 return this.options.min; | |
13189 }, | |
13190 | |
13191 _valueMax: function() { | |
13192 return this.options.max; | |
13193 }, | |
13194 | |
13195 _refreshValue: function() { | |
13196 var lastValPercent, valPercent, value, valueMin, valueMax, | |
13197 oRange = this.options.range, | |
13198 o = this.options, | |
13199 that = this, | |
13200 animate = ( !this._animateOff ) ? o.animate : false, | |
13201 _set = {}; | |
13202 | |
13203 if ( this.options.values && this.options.values.length ) { | |
13204 this.handles.each(function( i ) { | |
13205 valPercent = ( that.values(i) - that._valueMin() ) / ( that._valueMax() - that._valueMin() ) * 100; | |
13206 _set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; | |
13207 $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); | |
13208 if ( that.options.range === true ) { | |
13209 if ( that.orientation === "horizontal" ) { | |
13210 if ( i === 0 ) { | |
13211 that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate ); | |
13212 } | |
13213 if ( i === 1 ) { | |
13214 that.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } ); | |
13215 } | |
13216 } else { | |
13217 if ( i === 0 ) { | |
13218 that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate ); | |
13219 } | |
13220 if ( i === 1 ) { | |
13221 that.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } ); | |
13222 } | |
13223 } | |
13224 } | |
13225 lastValPercent = valPercent; | |
13226 }); | |
13227 } else { | |
13228 value = this.value(); | |
13229 valueMin = this._valueMin(); | |
13230 valueMax = this._valueMax(); | |
13231 valPercent = ( valueMax !== valueMin ) ? | |
13232 ( value - valueMin ) / ( valueMax - valueMin ) * 100 : | |
13233 0; | |
13234 _set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; | |
13235 this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); | |
13236 | |
13237 if ( oRange === "min" && this.orientation === "horizontal" ) { | |
13238 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate ); | |
13239 } | |
13240 if ( oRange === "max" && this.orientation === "horizontal" ) { | |
13241 this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } ); | |
13242 } | |
13243 if ( oRange === "min" && this.orientation === "vertical" ) { | |
13244 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate ); | |
13245 } | |
13246 if ( oRange === "max" && this.orientation === "vertical" ) { | |
13247 this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } ); | |
13248 } | |
13249 } | |
13250 }, | |
13251 | |
13252 _handleEvents: { | |
13253 keydown: function( event ) { | |
13254 var allowed, curVal, newVal, step, | |
13255 index = $( event.target ).data( "ui-slider-handle-index" ); | |
13256 | |
13257 switch ( event.keyCode ) { | |
13258 case $.ui.keyCode.HOME: | |
13259 case $.ui.keyCode.END: | |
13260 case $.ui.keyCode.PAGE_UP: | |
13261 case $.ui.keyCode.PAGE_DOWN: | |
13262 case $.ui.keyCode.UP: | |
13263 case $.ui.keyCode.RIGHT: | |
13264 case $.ui.keyCode.DOWN: | |
13265 case $.ui.keyCode.LEFT: | |
13266 event.preventDefault(); | |
13267 if ( !this._keySliding ) { | |
13268 this._keySliding = true; | |
13269 $( event.target ).addClass( "ui-state-active" ); | |
13270 allowed = this._start( event, index ); | |
13271 if ( allowed === false ) { | |
13272 return; | |
13273 } | |
13274 } | |
13275 break; | |
13276 } | |
13277 | |
13278 step = this.options.step; | |
13279 if ( this.options.values && this.options.values.length ) { | |
13280 curVal = newVal = this.values( index ); | |
13281 } else { | |
13282 curVal = newVal = this.value(); | |
13283 } | |
13284 | |
13285 switch ( event.keyCode ) { | |
13286 case $.ui.keyCode.HOME: | |
13287 newVal = this._valueMin(); | |
13288 break; | |
13289 case $.ui.keyCode.END: | |
13290 newVal = this._valueMax(); | |
13291 break; | |
13292 case $.ui.keyCode.PAGE_UP: | |
13293 newVal = this._trimAlignValue( curVal + ( (this._valueMax() - this._valueMin()) / numPages ) ); | |
13294 break; | |
13295 case $.ui.keyCode.PAGE_DOWN: | |
13296 newVal = this._trimAlignValue( curVal - ( (this._valueMax() - this._valueMin()) / numPages ) ); | |
13297 break; | |
13298 case $.ui.keyCode.UP: | |
13299 case $.ui.keyCode.RIGHT: | |
13300 if ( curVal === this._valueMax() ) { | |
13301 return; | |
13302 } | |
13303 newVal = this._trimAlignValue( curVal + step ); | |
13304 break; | |
13305 case $.ui.keyCode.DOWN: | |
13306 case $.ui.keyCode.LEFT: | |
13307 if ( curVal === this._valueMin() ) { | |
13308 return; | |
13309 } | |
13310 newVal = this._trimAlignValue( curVal - step ); | |
13311 break; | |
13312 } | |
13313 | |
13314 this._slide( event, index, newVal ); | |
13315 }, | |
13316 click: function( event ) { | |
13317 event.preventDefault(); | |
13318 }, | |
13319 keyup: function( event ) { | |
13320 var index = $( event.target ).data( "ui-slider-handle-index" ); | |
13321 | |
13322 if ( this._keySliding ) { | |
13323 this._keySliding = false; | |
13324 this._stop( event, index ); | |
13325 this._change( event, index ); | |
13326 $( event.target ).removeClass( "ui-state-active" ); | |
13327 } | |
13328 } | |
13329 } | |
13330 | |
13331 }); | |
13332 | |
13333 }(jQuery)); | |
13334 | |
13335 (function( $ ) { | |
13336 | |
13337 function modifier( fn ) { | |
13338 return function() { | |
13339 var previous = this.element.val(); | |
13340 fn.apply( this, arguments ); | |
13341 this._refresh(); | |
13342 if ( previous !== this.element.val() ) { | |
13343 this._trigger( "change" ); | |
13344 } | |
13345 }; | |
13346 } | |
13347 | |
13348 $.widget( "ui.spinner", { | |
13349 version: "1.10.4", | |
13350 defaultElement: "<input>", | |
13351 widgetEventPrefix: "spin", | |
13352 options: { | |
13353 culture: null, | |
13354 icons: { | |
13355 down: "ui-icon-triangle-1-s", | |
13356 up: "ui-icon-triangle-1-n" | |
13357 }, | |
13358 incremental: true, | |
13359 max: null, | |
13360 min: null, | |
13361 numberFormat: null, | |
13362 page: 10, | |
13363 step: 1, | |
13364 | |
13365 change: null, | |
13366 spin: null, | |
13367 start: null, | |
13368 stop: null | |
13369 }, | |
13370 | |
13371 _create: function() { | |
13372 // handle string values that need to be parsed | |
13373 this._setOption( "max", this.options.max ); | |
13374 this._setOption( "min", this.options.min ); | |
13375 this._setOption( "step", this.options.step ); | |
13376 | |
13377 // Only format if there is a value, prevents the field from being marked | |
13378 // as invalid in Firefox, see #9573. | |
13379 if ( this.value() !== "" ) { | |
13380 // Format the value, but don't constrain. | |
13381 this._value( this.element.val(), true ); | |
13382 } | |
13383 | |
13384 this._draw(); | |
13385 this._on( this._events ); | |
13386 this._refresh(); | |
13387 | |
13388 // turning off autocomplete prevents the browser from remembering the | |
13389 // value when navigating through history, so we re-enable autocomplete | |
13390 // if the page is unloaded before the widget is destroyed. #7790 | |
13391 this._on( this.window, { | |
13392 beforeunload: function() { | |
13393 this.element.removeAttr( "autocomplete" ); | |
13394 } | |
13395 }); | |
13396 }, | |
13397 | |
13398 _getCreateOptions: function() { | |
13399 var options = {}, | |
13400 element = this.element; | |
13401 | |
13402 $.each( [ "min", "max", "step" ], function( i, option ) { | |
13403 var value = element.attr( option ); | |
13404 if ( value !== undefined && value.length ) { | |
13405 options[ option ] = value; | |
13406 } | |
13407 }); | |
13408 | |
13409 return options; | |
13410 }, | |
13411 | |
13412 _events: { | |
13413 keydown: function( event ) { | |
13414 if ( this._start( event ) && this._keydown( event ) ) { | |
13415 event.preventDefault(); | |
13416 } | |
13417 }, | |
13418 keyup: "_stop", | |
13419 focus: function() { | |
13420 this.previous = this.element.val(); | |
13421 }, | |
13422 blur: function( event ) { | |
13423 if ( this.cancelBlur ) { | |
13424 delete this.cancelBlur; | |
13425 return; | |
13426 } | |
13427 | |
13428 this._stop(); | |
13429 this._refresh(); | |
13430 if ( this.previous !== this.element.val() ) { | |
13431 this._trigger( "change", event ); | |
13432 } | |
13433 }, | |
13434 mousewheel: function( event, delta ) { | |
13435 if ( !delta ) { | |
13436 return; | |
13437 } | |
13438 if ( !this.spinning && !this._start( event ) ) { | |
13439 return false; | |
13440 } | |
13441 | |
13442 this._spin( (delta > 0 ? 1 : -1) * this.options.step, event ); | |
13443 clearTimeout( this.mousewheelTimer ); | |
13444 this.mousewheelTimer = this._delay(function() { | |
13445 if ( this.spinning ) { | |
13446 this._stop( event ); | |
13447 } | |
13448 }, 100 ); | |
13449 event.preventDefault(); | |
13450 }, | |
13451 "mousedown .ui-spinner-button": function( event ) { | |
13452 var previous; | |
13453 | |
13454 // We never want the buttons to have focus; whenever the user is | |
13455 // interacting with the spinner, the focus should be on the input. | |
13456 // If the input is focused then this.previous is properly set from | |
13457 // when the input first received focus. If the input is not focused | |
13458 // then we need to set this.previous based on the value before spinning. | |
13459 previous = this.element[0] === this.document[0].activeElement ? | |
13460 this.previous : this.element.val(); | |
13461 function checkFocus() { | |
13462 var isActive = this.element[0] === this.document[0].activeElement; | |
13463 if ( !isActive ) { | |
13464 this.element.focus(); | |
13465 this.previous = previous; | |
13466 // support: IE | |
13467 // IE sets focus asynchronously, so we need to check if focus | |
13468 // moved off of the input because the user clicked on the button. | |
13469 this._delay(function() { | |
13470 this.previous = previous; | |
13471 }); | |
13472 } | |
13473 } | |
13474 | |
13475 // ensure focus is on (or stays on) the text field | |
13476 event.preventDefault(); | |
13477 checkFocus.call( this ); | |
13478 | |
13479 // support: IE | |
13480 // IE doesn't prevent moving focus even with event.preventDefault() | |
13481 // so we set a flag to know when we should ignore the blur event | |
13482 // and check (again) if focus moved off of the input. | |
13483 this.cancelBlur = true; | |
13484 this._delay(function() { | |
13485 delete this.cancelBlur; | |
13486 checkFocus.call( this ); | |
13487 }); | |
13488 | |
13489 if ( this._start( event ) === false ) { | |
13490 return; | |
13491 } | |
13492 | |
13493 this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event ); | |
13494 }, | |
13495 "mouseup .ui-spinner-button": "_stop", | |
13496 "mouseenter .ui-spinner-button": function( event ) { | |
13497 // button will add ui-state-active if mouse was down while mouseleave and kept down | |
13498 if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) { | |
13499 return; | |
13500 } | |
13501 | |
13502 if ( this._start( event ) === false ) { | |
13503 return false; | |
13504 } | |
13505 this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event ); | |
13506 }, | |
13507 // TODO: do we really want to consider this a stop? | |
13508 // shouldn't we just stop the repeater and wait until mouseup before | |
13509 // we trigger the stop event? | |
13510 "mouseleave .ui-spinner-button": "_stop" | |
13511 }, | |
13512 | |
13513 _draw: function() { | |
13514 var uiSpinner = this.uiSpinner = this.element | |
13515 .addClass( "ui-spinner-input" ) | |
13516 .attr( "autocomplete", "off" ) | |
13517 .wrap( this._uiSpinnerHtml() ) | |
13518 .parent() | |
13519 // add buttons | |
13520 .append( this._buttonHtml() ); | |
13521 | |
13522 this.element.attr( "role", "spinbutton" ); | |
13523 | |
13524 // button bindings | |
13525 this.buttons = uiSpinner.find( ".ui-spinner-button" ) | |
13526 .attr( "tabIndex", -1 ) | |
13527 .button() | |
13528 .removeClass( "ui-corner-all" ); | |
13529 | |
13530 // IE 6 doesn't understand height: 50% for the buttons | |
13531 // unless the wrapper has an explicit height | |
13532 if ( this.buttons.height() > Math.ceil( uiSpinner.height() * 0.5 ) && | |
13533 uiSpinner.height() > 0 ) { | |
13534 uiSpinner.height( uiSpinner.height() ); | |
13535 } | |
13536 | |
13537 // disable spinner if element was already disabled | |
13538 if ( this.options.disabled ) { | |
13539 this.disable(); | |
13540 } | |
13541 }, | |
13542 | |
13543 _keydown: function( event ) { | |
13544 var options = this.options, | |
13545 keyCode = $.ui.keyCode; | |
13546 | |
13547 switch ( event.keyCode ) { | |
13548 case keyCode.UP: | |
13549 this._repeat( null, 1, event ); | |
13550 return true; | |
13551 case keyCode.DOWN: | |
13552 this._repeat( null, -1, event ); | |
13553 return true; | |
13554 case keyCode.PAGE_UP: | |
13555 this._repeat( null, options.page, event ); | |
13556 return true; | |
13557 case keyCode.PAGE_DOWN: | |
13558 this._repeat( null, -options.page, event ); | |
13559 return true; | |
13560 } | |
13561 | |
13562 return false; | |
13563 }, | |
13564 | |
13565 _uiSpinnerHtml: function() { | |
13566 return "<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>"; | |
13567 }, | |
13568 | |
13569 _buttonHtml: function() { | |
13570 return "" + | |
13571 "<a class='ui-spinner-button ui-spinner-up ui-corner-tr'>" + | |
13572 "<span class='ui-icon " + this.options.icons.up + "'>▲</span>" + | |
13573 "</a>" + | |
13574 "<a class='ui-spinner-button ui-spinner-down ui-corner-br'>" + | |
13575 "<span class='ui-icon " + this.options.icons.down + "'>▼</span>" + | |
13576 "</a>"; | |
13577 }, | |
13578 | |
13579 _start: function( event ) { | |
13580 if ( !this.spinning && this._trigger( "start", event ) === false ) { | |
13581 return false; | |
13582 } | |
13583 | |
13584 if ( !this.counter ) { | |
13585 this.counter = 1; | |
13586 } | |
13587 this.spinning = true; | |
13588 return true; | |
13589 }, | |
13590 | |
13591 _repeat: function( i, steps, event ) { | |
13592 i = i || 500; | |
13593 | |
13594 clearTimeout( this.timer ); | |
13595 this.timer = this._delay(function() { | |
13596 this._repeat( 40, steps, event ); | |
13597 }, i ); | |
13598 | |
13599 this._spin( steps * this.options.step, event ); | |
13600 }, | |
13601 | |
13602 _spin: function( step, event ) { | |
13603 var value = this.value() || 0; | |
13604 | |
13605 if ( !this.counter ) { | |
13606 this.counter = 1; | |
13607 } | |
13608 | |
13609 value = this._adjustValue( value + step * this._increment( this.counter ) ); | |
13610 | |
13611 if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false) { | |
13612 this._value( value ); | |
13613 this.counter++; | |
13614 } | |
13615 }, | |
13616 | |
13617 _increment: function( i ) { | |
13618 var incremental = this.options.incremental; | |
13619 | |
13620 if ( incremental ) { | |
13621 return $.isFunction( incremental ) ? | |
13622 incremental( i ) : | |
13623 Math.floor( i*i*i/50000 - i*i/500 + 17*i/200 + 1 ); | |
13624 } | |
13625 | |
13626 return 1; | |
13627 }, | |
13628 | |
13629 _precision: function() { | |
13630 var precision = this._precisionOf( this.options.step ); | |
13631 if ( this.options.min !== null ) { | |
13632 precision = Math.max( precision, this._precisionOf( this.options.min ) ); | |
13633 } | |
13634 return precision; | |
13635 }, | |
13636 | |
13637 _precisionOf: function( num ) { | |
13638 var str = num.toString(), | |
13639 decimal = str.indexOf( "." ); | |
13640 return decimal === -1 ? 0 : str.length - decimal - 1; | |
13641 }, | |
13642 | |
13643 _adjustValue: function( value ) { | |
13644 var base, aboveMin, | |
13645 options = this.options; | |
13646 | |
13647 // make sure we're at a valid step | |
13648 // - find out where we are relative to the base (min or 0) | |
13649 base = options.min !== null ? options.min : 0; | |
13650 aboveMin = value - base; | |
13651 // - round to the nearest step | |
13652 aboveMin = Math.round(aboveMin / options.step) * options.step; | |
13653 // - rounding is based on 0, so adjust back to our base | |
13654 value = base + aboveMin; | |
13655 | |
13656 // fix precision from bad JS floating point math | |
13657 value = parseFloat( value.toFixed( this._precision() ) ); | |
13658 | |
13659 // clamp the value | |
13660 if ( options.max !== null && value > options.max) { | |
13661 return options.max; | |
13662 } | |
13663 if ( options.min !== null && value < options.min ) { | |
13664 return options.min; | |
13665 } | |
13666 | |
13667 return value; | |
13668 }, | |
13669 | |
13670 _stop: function( event ) { | |
13671 if ( !this.spinning ) { | |
13672 return; | |
13673 } | |
13674 | |
13675 clearTimeout( this.timer ); | |
13676 clearTimeout( this.mousewheelTimer ); | |
13677 this.counter = 0; | |
13678 this.spinning = false; | |
13679 this._trigger( "stop", event ); | |
13680 }, | |
13681 | |
13682 _setOption: function( key, value ) { | |
13683 if ( key === "culture" || key === "numberFormat" ) { | |
13684 var prevValue = this._parse( this.element.val() ); | |
13685 this.options[ key ] = value; | |
13686 this.element.val( this._format( prevValue ) ); | |
13687 return; | |
13688 } | |
13689 | |
13690 if ( key === "max" || key === "min" || key === "step" ) { | |
13691 if ( typeof value === "string" ) { | |
13692 value = this._parse( value ); | |
13693 } | |
13694 } | |
13695 if ( key === "icons" ) { | |
13696 this.buttons.first().find( ".ui-icon" ) | |
13697 .removeClass( this.options.icons.up ) | |
13698 .addClass( value.up ); | |
13699 this.buttons.last().find( ".ui-icon" ) | |
13700 .removeClass( this.options.icons.down ) | |
13701 .addClass( value.down ); | |
13702 } | |
13703 | |
13704 this._super( key, value ); | |
13705 | |
13706 if ( key === "disabled" ) { | |
13707 if ( value ) { | |
13708 this.element.prop( "disabled", true ); | |
13709 this.buttons.button( "disable" ); | |
13710 } else { | |
13711 this.element.prop( "disabled", false ); | |
13712 this.buttons.button( "enable" ); | |
13713 } | |
13714 } | |
13715 }, | |
13716 | |
13717 _setOptions: modifier(function( options ) { | |
13718 this._super( options ); | |
13719 this._value( this.element.val() ); | |
13720 }), | |
13721 | |
13722 _parse: function( val ) { | |
13723 if ( typeof val === "string" && val !== "" ) { | |
13724 val = window.Globalize && this.options.numberFormat ? | |
13725 Globalize.parseFloat( val, 10, this.options.culture ) : +val; | |
13726 } | |
13727 return val === "" || isNaN( val ) ? null : val; | |
13728 }, | |
13729 | |
13730 _format: function( value ) { | |
13731 if ( value === "" ) { | |
13732 return ""; | |
13733 } | |
13734 return window.Globalize && this.options.numberFormat ? | |
13735 Globalize.format( value, this.options.numberFormat, this.options.culture ) : | |
13736 value; | |
13737 }, | |
13738 | |
13739 _refresh: function() { | |
13740 this.element.attr({ | |
13741 "aria-valuemin": this.options.min, | |
13742 "aria-valuemax": this.options.max, | |
13743 // TODO: what should we do with values that can't be parsed? | |
13744 "aria-valuenow": this._parse( this.element.val() ) | |
13745 }); | |
13746 }, | |
13747 | |
13748 // update the value without triggering change | |
13749 _value: function( value, allowAny ) { | |
13750 var parsed; | |
13751 if ( value !== "" ) { | |
13752 parsed = this._parse( value ); | |
13753 if ( parsed !== null ) { | |
13754 if ( !allowAny ) { | |
13755 parsed = this._adjustValue( parsed ); | |
13756 } | |
13757 value = this._format( parsed ); | |
13758 } | |
13759 } | |
13760 this.element.val( value ); | |
13761 this._refresh(); | |
13762 }, | |
13763 | |
13764 _destroy: function() { | |
13765 this.element | |
13766 .removeClass( "ui-spinner-input" ) | |
13767 .prop( "disabled", false ) | |
13768 .removeAttr( "autocomplete" ) | |
13769 .removeAttr( "role" ) | |
13770 .removeAttr( "aria-valuemin" ) | |
13771 .removeAttr( "aria-valuemax" ) | |
13772 .removeAttr( "aria-valuenow" ); | |
13773 this.uiSpinner.replaceWith( this.element ); | |
13774 }, | |
13775 | |
13776 stepUp: modifier(function( steps ) { | |
13777 this._stepUp( steps ); | |
13778 }), | |
13779 _stepUp: function( steps ) { | |
13780 if ( this._start() ) { | |
13781 this._spin( (steps || 1) * this.options.step ); | |
13782 this._stop(); | |
13783 } | |
13784 }, | |
13785 | |
13786 stepDown: modifier(function( steps ) { | |
13787 this._stepDown( steps ); | |
13788 }), | |
13789 _stepDown: function( steps ) { | |
13790 if ( this._start() ) { | |
13791 this._spin( (steps || 1) * -this.options.step ); | |
13792 this._stop(); | |
13793 } | |
13794 }, | |
13795 | |
13796 pageUp: modifier(function( pages ) { | |
13797 this._stepUp( (pages || 1) * this.options.page ); | |
13798 }), | |
13799 | |
13800 pageDown: modifier(function( pages ) { | |
13801 this._stepDown( (pages || 1) * this.options.page ); | |
13802 }), | |
13803 | |
13804 value: function( newVal ) { | |
13805 if ( !arguments.length ) { | |
13806 return this._parse( this.element.val() ); | |
13807 } | |
13808 modifier( this._value ).call( this, newVal ); | |
13809 }, | |
13810 | |
13811 widget: function() { | |
13812 return this.uiSpinner; | |
13813 } | |
13814 }); | |
13815 | |
13816 }( jQuery ) ); | |
13817 | |
13818 (function( $, undefined ) { | |
13819 | |
13820 var tabId = 0, | |
13821 rhash = /#.*$/; | |
13822 | |
13823 function getNextTabId() { | |
13824 return ++tabId; | |
13825 } | |
13826 | |
13827 function isLocal( anchor ) { | |
13828 // support: IE7 | |
13829 // IE7 doesn't normalize the href property when set via script (#9317) | |
13830 anchor = anchor.cloneNode( false ); | |
13831 | |
13832 return anchor.hash.length > 1 && | |
13833 decodeURIComponent( anchor.href.replace( rhash, "" ) ) === | |
13834 decodeURIComponent( location.href.replace( rhash, "" ) ); | |
13835 } | |
13836 | |
13837 $.widget( "ui.tabs", { | |
13838 version: "1.10.4", | |
13839 delay: 300, | |
13840 options: { | |
13841 active: null, | |
13842 collapsible: false, | |
13843 event: "click", | |
13844 heightStyle: "content", | |
13845 hide: null, | |
13846 show: null, | |
13847 | |
13848 // callbacks | |
13849 activate: null, | |
13850 beforeActivate: null, | |
13851 beforeLoad: null, | |
13852 load: null | |
13853 }, | |
13854 | |
13855 _create: function() { | |
13856 var that = this, | |
13857 options = this.options; | |
13858 | |
13859 this.running = false; | |
13860 | |
13861 this.element | |
13862 .addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" ) | |
13863 .toggleClass( "ui-tabs-collapsible", options.collapsible ) | |
13864 // Prevent users from focusing disabled tabs via click | |
13865 .delegate( ".ui-tabs-nav > li", "mousedown" + this.eventNamespace, function( event ) { | |
13866 if ( $( this ).is( ".ui-state-disabled" ) ) { | |
13867 event.preventDefault(); | |
13868 } | |
13869 }) | |
13870 // support: IE <9 | |
13871 // Preventing the default action in mousedown doesn't prevent IE | |
13872 // from focusing the element, so if the anchor gets focused, blur. | |
13873 // We don't have to worry about focusing the previously focused | |
13874 // element since clicking on a non-focusable element should focus | |
13875 // the body anyway. | |
13876 .delegate( ".ui-tabs-anchor", "focus" + this.eventNamespace, function() { | |
13877 if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) { | |
13878 this.blur(); | |
13879 } | |
13880 }); | |
13881 | |
13882 this._processTabs(); | |
13883 options.active = this._initialActive(); | |
13884 | |
13885 // Take disabling tabs via class attribute from HTML | |
13886 // into account and update option properly. | |
13887 if ( $.isArray( options.disabled ) ) { | |
13888 options.disabled = $.unique( options.disabled.concat( | |
13889 $.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) { | |
13890 return that.tabs.index( li ); | |
13891 }) | |
13892 ) ).sort(); | |
13893 } | |
13894 | |
13895 // check for length avoids error when initializing empty list | |
13896 if ( this.options.active !== false && this.anchors.length ) { | |
13897 this.active = this._findActive( options.active ); | |
13898 } else { | |
13899 this.active = $(); | |
13900 } | |
13901 | |
13902 this._refresh(); | |
13903 | |
13904 if ( this.active.length ) { | |
13905 this.load( options.active ); | |
13906 } | |
13907 }, | |
13908 | |
13909 _initialActive: function() { | |
13910 var active = this.options.active, | |
13911 collapsible = this.options.collapsible, | |
13912 locationHash = location.hash.substring( 1 ); | |
13913 | |
13914 if ( active === null ) { | |
13915 // check the fragment identifier in the URL | |
13916 if ( locationHash ) { | |
13917 this.tabs.each(function( i, tab ) { | |
13918 if ( $( tab ).attr( "aria-controls" ) === locationHash ) { | |
13919 active = i; | |
13920 return false; | |
13921 } | |
13922 }); | |
13923 } | |
13924 | |
13925 // check for a tab marked active via a class | |
13926 if ( active === null ) { | |
13927 active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) ); | |
13928 } | |
13929 | |
13930 // no active tab, set to false | |
13931 if ( active === null || active === -1 ) { | |
13932 active = this.tabs.length ? 0 : false; | |
13933 } | |
13934 } | |
13935 | |
13936 // handle numbers: negative, out of range | |
13937 if ( active !== false ) { | |
13938 active = this.tabs.index( this.tabs.eq( active ) ); | |
13939 if ( active === -1 ) { | |
13940 active = collapsible ? false : 0; | |
13941 } | |
13942 } | |
13943 | |
13944 // don't allow collapsible: false and active: false | |
13945 if ( !collapsible && active === false && this.anchors.length ) { | |
13946 active = 0; | |
13947 } | |
13948 | |
13949 return active; | |
13950 }, | |
13951 | |
13952 _getCreateEventData: function() { | |
13953 return { | |
13954 tab: this.active, | |
13955 panel: !this.active.length ? $() : this._getPanelForTab( this.active ) | |
13956 }; | |
13957 }, | |
13958 | |
13959 _tabKeydown: function( event ) { | |
13960 var focusedTab = $( this.document[0].activeElement ).closest( "li" ), | |
13961 selectedIndex = this.tabs.index( focusedTab ), | |
13962 goingForward = true; | |
13963 | |
13964 if ( this._handlePageNav( event ) ) { | |
13965 return; | |
13966 } | |
13967 | |
13968 switch ( event.keyCode ) { | |
13969 case $.ui.keyCode.RIGHT: | |
13970 case $.ui.keyCode.DOWN: | |
13971 selectedIndex++; | |
13972 break; | |
13973 case $.ui.keyCode.UP: | |
13974 case $.ui.keyCode.LEFT: | |
13975 goingForward = false; | |
13976 selectedIndex--; | |
13977 break; | |
13978 case $.ui.keyCode.END: | |
13979 selectedIndex = this.anchors.length - 1; | |
13980 break; | |
13981 case $.ui.keyCode.HOME: | |
13982 selectedIndex = 0; | |
13983 break; | |
13984 case $.ui.keyCode.SPACE: | |
13985 // Activate only, no collapsing | |
13986 event.preventDefault(); | |
13987 clearTimeout( this.activating ); | |
13988 this._activate( selectedIndex ); | |
13989 return; | |
13990 case $.ui.keyCode.ENTER: | |
13991 // Toggle (cancel delayed activation, allow collapsing) | |
13992 event.preventDefault(); | |
13993 clearTimeout( this.activating ); | |
13994 // Determine if we should collapse or activate | |
13995 this._activate( selectedIndex === this.options.active ? false : selectedIndex ); | |
13996 return; | |
13997 default: | |
13998 return; | |
13999 } | |
14000 | |
14001 // Focus the appropriate tab, based on which key was pressed | |
14002 event.preventDefault(); | |
14003 clearTimeout( this.activating ); | |
14004 selectedIndex = this._focusNextTab( selectedIndex, goingForward ); | |
14005 | |
14006 // Navigating with control key will prevent automatic activation | |
14007 if ( !event.ctrlKey ) { | |
14008 // Update aria-selected immediately so that AT think the tab is already selected. | |
14009 // Otherwise AT may confuse the user by stating that they need to activate the tab, | |
14010 // but the tab will already be activated by the time the announcement finishes. | |
14011 focusedTab.attr( "aria-selected", "false" ); | |
14012 this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" ); | |
14013 | |
14014 this.activating = this._delay(function() { | |
14015 this.option( "active", selectedIndex ); | |
14016 }, this.delay ); | |
14017 } | |
14018 }, | |
14019 | |
14020 _panelKeydown: function( event ) { | |
14021 if ( this._handlePageNav( event ) ) { | |
14022 return; | |
14023 } | |
14024 | |
14025 // Ctrl+up moves focus to the current tab | |
14026 if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) { | |
14027 event.preventDefault(); | |
14028 this.active.focus(); | |
14029 } | |
14030 }, | |
14031 | |
14032 // Alt+page up/down moves focus to the previous/next tab (and activates) | |
14033 _handlePageNav: function( event ) { | |
14034 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) { | |
14035 this._activate( this._focusNextTab( this.options.active - 1, false ) ); | |
14036 return true; | |
14037 } | |
14038 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) { | |
14039 this._activate( this._focusNextTab( this.options.active + 1, true ) ); | |
14040 return true; | |
14041 } | |
14042 }, | |
14043 | |
14044 _findNextTab: function( index, goingForward ) { | |
14045 var lastTabIndex = this.tabs.length - 1; | |
14046 | |
14047 function constrain() { | |
14048 if ( index > lastTabIndex ) { | |
14049 index = 0; | |
14050 } | |
14051 if ( index < 0 ) { | |
14052 index = lastTabIndex; | |
14053 } | |
14054 return index; | |
14055 } | |
14056 | |
14057 while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) { | |
14058 index = goingForward ? index + 1 : index - 1; | |
14059 } | |
14060 | |
14061 return index; | |
14062 }, | |
14063 | |
14064 _focusNextTab: function( index, goingForward ) { | |
14065 index = this._findNextTab( index, goingForward ); | |
14066 this.tabs.eq( index ).focus(); | |
14067 return index; | |
14068 }, | |
14069 | |
14070 _setOption: function( key, value ) { | |
14071 if ( key === "active" ) { | |
14072 // _activate() will handle invalid values and update this.options | |
14073 this._activate( value ); | |
14074 return; | |
14075 } | |
14076 | |
14077 if ( key === "disabled" ) { | |
14078 // don't use the widget factory's disabled handling | |
14079 this._setupDisabled( value ); | |
14080 return; | |
14081 } | |
14082 | |
14083 this._super( key, value); | |
14084 | |
14085 if ( key === "collapsible" ) { | |
14086 this.element.toggleClass( "ui-tabs-collapsible", value ); | |
14087 // Setting collapsible: false while collapsed; open first panel | |
14088 if ( !value && this.options.active === false ) { | |
14089 this._activate( 0 ); | |
14090 } | |
14091 } | |
14092 | |
14093 if ( key === "event" ) { | |
14094 this._setupEvents( value ); | |
14095 } | |
14096 | |
14097 if ( key === "heightStyle" ) { | |
14098 this._setupHeightStyle( value ); | |
14099 } | |
14100 }, | |
14101 | |
14102 _tabId: function( tab ) { | |
14103 return tab.attr( "aria-controls" ) || "ui-tabs-" + getNextTabId(); | |
14104 }, | |
14105 | |
14106 _sanitizeSelector: function( hash ) { | |
14107 return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : ""; | |
14108 }, | |
14109 | |
14110 refresh: function() { | |
14111 var options = this.options, | |
14112 lis = this.tablist.children( ":has(a[href])" ); | |
14113 | |
14114 // get disabled tabs from class attribute from HTML | |
14115 // this will get converted to a boolean if needed in _refresh() | |
14116 options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) { | |
14117 return lis.index( tab ); | |
14118 }); | |
14119 | |
14120 this._processTabs(); | |
14121 | |
14122 // was collapsed or no tabs | |
14123 if ( options.active === false || !this.anchors.length ) { | |
14124 options.active = false; | |
14125 this.active = $(); | |
14126 // was active, but active tab is gone | |
14127 } else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) { | |
14128 // all remaining tabs are disabled | |
14129 if ( this.tabs.length === options.disabled.length ) { | |
14130 options.active = false; | |
14131 this.active = $(); | |
14132 // activate previous tab | |
14133 } else { | |
14134 this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) ); | |
14135 } | |
14136 // was active, active tab still exists | |
14137 } else { | |
14138 // make sure active index is correct | |
14139 options.active = this.tabs.index( this.active ); | |
14140 } | |
14141 | |
14142 this._refresh(); | |
14143 }, | |
14144 | |
14145 _refresh: function() { | |
14146 this._setupDisabled( this.options.disabled ); | |
14147 this._setupEvents( this.options.event ); | |
14148 this._setupHeightStyle( this.options.heightStyle ); | |
14149 | |
14150 this.tabs.not( this.active ).attr({ | |
14151 "aria-selected": "false", | |
14152 tabIndex: -1 | |
14153 }); | |
14154 this.panels.not( this._getPanelForTab( this.active ) ) | |
14155 .hide() | |
14156 .attr({ | |
14157 "aria-expanded": "false", | |
14158 "aria-hidden": "true" | |
14159 }); | |
14160 | |
14161 // Make sure one tab is in the tab order | |
14162 if ( !this.active.length ) { | |
14163 this.tabs.eq( 0 ).attr( "tabIndex", 0 ); | |
14164 } else { | |
14165 this.active | |
14166 .addClass( "ui-tabs-active ui-state-active" ) | |
14167 .attr({ | |
14168 "aria-selected": "true", | |
14169 tabIndex: 0 | |
14170 }); | |
14171 this._getPanelForTab( this.active ) | |
14172 .show() | |
14173 .attr({ | |
14174 "aria-expanded": "true", | |
14175 "aria-hidden": "false" | |
14176 }); | |
14177 } | |
14178 }, | |
14179 | |
14180 _processTabs: function() { | |
14181 var that = this; | |
14182 | |
14183 this.tablist = this._getList() | |
14184 .addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ) | |
14185 .attr( "role", "tablist" ); | |
14186 | |
14187 this.tabs = this.tablist.find( "> li:has(a[href])" ) | |
14188 .addClass( "ui-state-default ui-corner-top" ) | |
14189 .attr({ | |
14190 role: "tab", | |
14191 tabIndex: -1 | |
14192 }); | |
14193 | |
14194 this.anchors = this.tabs.map(function() { | |
14195 return $( "a", this )[ 0 ]; | |
14196 }) | |
14197 .addClass( "ui-tabs-anchor" ) | |
14198 .attr({ | |
14199 role: "presentation", | |
14200 tabIndex: -1 | |
14201 }); | |
14202 | |
14203 this.panels = $(); | |
14204 | |
14205 this.anchors.each(function( i, anchor ) { | |
14206 var selector, panel, panelId, | |
14207 anchorId = $( anchor ).uniqueId().attr( "id" ), | |
14208 tab = $( anchor ).closest( "li" ), | |
14209 originalAriaControls = tab.attr( "aria-controls" ); | |
14210 | |
14211 // inline tab | |
14212 if ( isLocal( anchor ) ) { | |
14213 selector = anchor.hash; | |
14214 panel = that.element.find( that._sanitizeSelector( selector ) ); | |
14215 // remote tab | |
14216 } else { | |
14217 panelId = that._tabId( tab ); | |
14218 selector = "#" + panelId; | |
14219 panel = that.element.find( selector ); | |
14220 if ( !panel.length ) { | |
14221 panel = that._createPanel( panelId ); | |
14222 panel.insertAfter( that.panels[ i - 1 ] || that.tablist ); | |
14223 } | |
14224 panel.attr( "aria-live", "polite" ); | |
14225 } | |
14226 | |
14227 if ( panel.length) { | |
14228 that.panels = that.panels.add( panel ); | |
14229 } | |
14230 if ( originalAriaControls ) { | |
14231 tab.data( "ui-tabs-aria-controls", originalAriaControls ); | |
14232 } | |
14233 tab.attr({ | |
14234 "aria-controls": selector.substring( 1 ), | |
14235 "aria-labelledby": anchorId | |
14236 }); | |
14237 panel.attr( "aria-labelledby", anchorId ); | |
14238 }); | |
14239 | |
14240 this.panels | |
14241 .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) | |
14242 .attr( "role", "tabpanel" ); | |
14243 }, | |
14244 | |
14245 // allow overriding how to find the list for rare usage scenarios (#7715) | |
14246 _getList: function() { | |
14247 return this.tablist || this.element.find( "ol,ul" ).eq( 0 ); | |
14248 }, | |
14249 | |
14250 _createPanel: function( id ) { | |
14251 return $( "<div>" ) | |
14252 .attr( "id", id ) | |
14253 .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) | |
14254 .data( "ui-tabs-destroy", true ); | |
14255 }, | |
14256 | |
14257 _setupDisabled: function( disabled ) { | |
14258 if ( $.isArray( disabled ) ) { | |
14259 if ( !disabled.length ) { | |
14260 disabled = false; | |
14261 } else if ( disabled.length === this.anchors.length ) { | |
14262 disabled = true; | |
14263 } | |
14264 } | |
14265 | |
14266 // disable tabs | |
14267 for ( var i = 0, li; ( li = this.tabs[ i ] ); i++ ) { | |
14268 if ( disabled === true || $.inArray( i, disabled ) !== -1 ) { | |
14269 $( li ) | |
14270 .addClass( "ui-state-disabled" ) | |
14271 .attr( "aria-disabled", "true" ); | |
14272 } else { | |
14273 $( li ) | |
14274 .removeClass( "ui-state-disabled" ) | |
14275 .removeAttr( "aria-disabled" ); | |
14276 } | |
14277 } | |
14278 | |
14279 this.options.disabled = disabled; | |
14280 }, | |
14281 | |
14282 _setupEvents: function( event ) { | |
14283 var events = { | |
14284 click: function( event ) { | |
14285 event.preventDefault(); | |
14286 } | |
14287 }; | |
14288 if ( event ) { | |
14289 $.each( event.split(" "), function( index, eventName ) { | |
14290 events[ eventName ] = "_eventHandler"; | |
14291 }); | |
14292 } | |
14293 | |
14294 this._off( this.anchors.add( this.tabs ).add( this.panels ) ); | |
14295 this._on( this.anchors, events ); | |
14296 this._on( this.tabs, { keydown: "_tabKeydown" } ); | |
14297 this._on( this.panels, { keydown: "_panelKeydown" } ); | |
14298 | |
14299 this._focusable( this.tabs ); | |
14300 this._hoverable( this.tabs ); | |
14301 }, | |
14302 | |
14303 _setupHeightStyle: function( heightStyle ) { | |
14304 var maxHeight, | |
14305 parent = this.element.parent(); | |
14306 | |
14307 if ( heightStyle === "fill" ) { | |
14308 maxHeight = parent.height(); | |
14309 maxHeight -= this.element.outerHeight() - this.element.height(); | |
14310 | |
14311 this.element.siblings( ":visible" ).each(function() { | |
14312 var elem = $( this ), | |
14313 position = elem.css( "position" ); | |
14314 | |
14315 if ( position === "absolute" || position === "fixed" ) { | |
14316 return; | |
14317 } | |
14318 maxHeight -= elem.outerHeight( true ); | |
14319 }); | |
14320 | |
14321 this.element.children().not( this.panels ).each(function() { | |
14322 maxHeight -= $( this ).outerHeight( true ); | |
14323 }); | |
14324 | |
14325 this.panels.each(function() { | |
14326 $( this ).height( Math.max( 0, maxHeight - | |
14327 $( this ).innerHeight() + $( this ).height() ) ); | |
14328 }) | |
14329 .css( "overflow", "auto" ); | |
14330 } else if ( heightStyle === "auto" ) { | |
14331 maxHeight = 0; | |
14332 this.panels.each(function() { | |
14333 maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() ); | |
14334 }).height( maxHeight ); | |
14335 } | |
14336 }, | |
14337 | |
14338 _eventHandler: function( event ) { | |
14339 var options = this.options, | |
14340 active = this.active, | |
14341 anchor = $( event.currentTarget ), | |
14342 tab = anchor.closest( "li" ), | |
14343 clickedIsActive = tab[ 0 ] === active[ 0 ], | |
14344 collapsing = clickedIsActive && options.collapsible, | |
14345 toShow = collapsing ? $() : this._getPanelForTab( tab ), | |
14346 toHide = !active.length ? $() : this._getPanelForTab( active ), | |
14347 eventData = { | |
14348 oldTab: active, | |
14349 oldPanel: toHide, | |
14350 newTab: collapsing ? $() : tab, | |
14351 newPanel: toShow | |
14352 }; | |
14353 | |
14354 event.preventDefault(); | |
14355 | |
14356 if ( tab.hasClass( "ui-state-disabled" ) || | |
14357 // tab is already loading | |
14358 tab.hasClass( "ui-tabs-loading" ) || | |
14359 // can't switch durning an animation | |
14360 this.running || | |
14361 // click on active header, but not collapsible | |
14362 ( clickedIsActive && !options.collapsible ) || | |
14363 // allow canceling activation | |
14364 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { | |
14365 return; | |
14366 } | |
14367 | |
14368 options.active = collapsing ? false : this.tabs.index( tab ); | |
14369 | |
14370 this.active = clickedIsActive ? $() : tab; | |
14371 if ( this.xhr ) { | |
14372 this.xhr.abort(); | |
14373 } | |
14374 | |
14375 if ( !toHide.length && !toShow.length ) { | |
14376 $.error( "jQuery UI Tabs: Mismatching fragment identifier." ); | |
14377 } | |
14378 | |
14379 if ( toShow.length ) { | |
14380 this.load( this.tabs.index( tab ), event ); | |
14381 } | |
14382 this._toggle( event, eventData ); | |
14383 }, | |
14384 | |
14385 // handles show/hide for selecting tabs | |
14386 _toggle: function( event, eventData ) { | |
14387 var that = this, | |
14388 toShow = eventData.newPanel, | |
14389 toHide = eventData.oldPanel; | |
14390 | |
14391 this.running = true; | |
14392 | |
14393 function complete() { | |
14394 that.running = false; | |
14395 that._trigger( "activate", event, eventData ); | |
14396 } | |
14397 | |
14398 function show() { | |
14399 eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" ); | |
14400 | |
14401 if ( toShow.length && that.options.show ) { | |
14402 that._show( toShow, that.options.show, complete ); | |
14403 } else { | |
14404 toShow.show(); | |
14405 complete(); | |
14406 } | |
14407 } | |
14408 | |
14409 // start out by hiding, then showing, then completing | |
14410 if ( toHide.length && this.options.hide ) { | |
14411 this._hide( toHide, this.options.hide, function() { | |
14412 eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" ); | |
14413 show(); | |
14414 }); | |
14415 } else { | |
14416 eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" ); | |
14417 toHide.hide(); | |
14418 show(); | |
14419 } | |
14420 | |
14421 toHide.attr({ | |
14422 "aria-expanded": "false", | |
14423 "aria-hidden": "true" | |
14424 }); | |
14425 eventData.oldTab.attr( "aria-selected", "false" ); | |
14426 // If we're switching tabs, remove the old tab from the tab order. | |
14427 // If we're opening from collapsed state, remove the previous tab from the tab order. | |
14428 // If we're collapsing, then keep the collapsing tab in the tab order. | |
14429 if ( toShow.length && toHide.length ) { | |
14430 eventData.oldTab.attr( "tabIndex", -1 ); | |
14431 } else if ( toShow.length ) { | |
14432 this.tabs.filter(function() { | |
14433 return $( this ).attr( "tabIndex" ) === 0; | |
14434 }) | |
14435 .attr( "tabIndex", -1 ); | |
14436 } | |
14437 | |
14438 toShow.attr({ | |
14439 "aria-expanded": "true", | |
14440 "aria-hidden": "false" | |
14441 }); | |
14442 eventData.newTab.attr({ | |
14443 "aria-selected": "true", | |
14444 tabIndex: 0 | |
14445 }); | |
14446 }, | |
14447 | |
14448 _activate: function( index ) { | |
14449 var anchor, | |
14450 active = this._findActive( index ); | |
14451 | |
14452 // trying to activate the already active panel | |
14453 if ( active[ 0 ] === this.active[ 0 ] ) { | |
14454 return; | |
14455 } | |
14456 | |
14457 // trying to collapse, simulate a click on the current active header | |
14458 if ( !active.length ) { | |
14459 active = this.active; | |
14460 } | |
14461 | |
14462 anchor = active.find( ".ui-tabs-anchor" )[ 0 ]; | |
14463 this._eventHandler({ | |
14464 target: anchor, | |
14465 currentTarget: anchor, | |
14466 preventDefault: $.noop | |
14467 }); | |
14468 }, | |
14469 | |
14470 _findActive: function( index ) { | |
14471 return index === false ? $() : this.tabs.eq( index ); | |
14472 }, | |
14473 | |
14474 _getIndex: function( index ) { | |
14475 // meta-function to give users option to provide a href string instead of a numerical index. | |
14476 if ( typeof index === "string" ) { | |
14477 index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) ); | |
14478 } | |
14479 | |
14480 return index; | |
14481 }, | |
14482 | |
14483 _destroy: function() { | |
14484 if ( this.xhr ) { | |
14485 this.xhr.abort(); | |
14486 } | |
14487 | |
14488 this.element.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" ); | |
14489 | |
14490 this.tablist | |
14491 .removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ) | |
14492 .removeAttr( "role" ); | |
14493 | |
14494 this.anchors | |
14495 .removeClass( "ui-tabs-anchor" ) | |
14496 .removeAttr( "role" ) | |
14497 .removeAttr( "tabIndex" ) | |
14498 .removeUniqueId(); | |
14499 | |
14500 this.tabs.add( this.panels ).each(function() { | |
14501 if ( $.data( this, "ui-tabs-destroy" ) ) { | |
14502 $( this ).remove(); | |
14503 } else { | |
14504 $( this ) | |
14505 .removeClass( "ui-state-default ui-state-active ui-state-disabled " + | |
14506 "ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel" ) | |
14507 .removeAttr( "tabIndex" ) | |
14508 .removeAttr( "aria-live" ) | |
14509 .removeAttr( "aria-busy" ) | |
14510 .removeAttr( "aria-selected" ) | |
14511 .removeAttr( "aria-labelledby" ) | |
14512 .removeAttr( "aria-hidden" ) | |
14513 .removeAttr( "aria-expanded" ) | |
14514 .removeAttr( "role" ); | |
14515 } | |
14516 }); | |
14517 | |
14518 this.tabs.each(function() { | |
14519 var li = $( this ), | |
14520 prev = li.data( "ui-tabs-aria-controls" ); | |
14521 if ( prev ) { | |
14522 li | |
14523 .attr( "aria-controls", prev ) | |
14524 .removeData( "ui-tabs-aria-controls" ); | |
14525 } else { | |
14526 li.removeAttr( "aria-controls" ); | |
14527 } | |
14528 }); | |
14529 | |
14530 this.panels.show(); | |
14531 | |
14532 if ( this.options.heightStyle !== "content" ) { | |
14533 this.panels.css( "height", "" ); | |
14534 } | |
14535 }, | |
14536 | |
14537 enable: function( index ) { | |
14538 var disabled = this.options.disabled; | |
14539 if ( disabled === false ) { | |
14540 return; | |
14541 } | |
14542 | |
14543 if ( index === undefined ) { | |
14544 disabled = false; | |
14545 } else { | |
14546 index = this._getIndex( index ); | |
14547 if ( $.isArray( disabled ) ) { | |
14548 disabled = $.map( disabled, function( num ) { | |
14549 return num !== index ? num : null; | |
14550 }); | |
14551 } else { | |
14552 disabled = $.map( this.tabs, function( li, num ) { | |
14553 return num !== index ? num : null; | |
14554 }); | |
14555 } | |
14556 } | |
14557 this._setupDisabled( disabled ); | |
14558 }, | |
14559 | |
14560 disable: function( index ) { | |
14561 var disabled = this.options.disabled; | |
14562 if ( disabled === true ) { | |
14563 return; | |
14564 } | |
14565 | |
14566 if ( index === undefined ) { | |
14567 disabled = true; | |
14568 } else { | |
14569 index = this._getIndex( index ); | |
14570 if ( $.inArray( index, disabled ) !== -1 ) { | |
14571 return; | |
14572 } | |
14573 if ( $.isArray( disabled ) ) { | |
14574 disabled = $.merge( [ index ], disabled ).sort(); | |
14575 } else { | |
14576 disabled = [ index ]; | |
14577 } | |
14578 } | |
14579 this._setupDisabled( disabled ); | |
14580 }, | |
14581 | |
14582 load: function( index, event ) { | |
14583 index = this._getIndex( index ); | |
14584 var that = this, | |
14585 tab = this.tabs.eq( index ), | |
14586 anchor = tab.find( ".ui-tabs-anchor" ), | |
14587 panel = this._getPanelForTab( tab ), | |
14588 eventData = { | |
14589 tab: tab, | |
14590 panel: panel | |
14591 }; | |
14592 | |
14593 // not remote | |
14594 if ( isLocal( anchor[ 0 ] ) ) { | |
14595 return; | |
14596 } | |
14597 | |
14598 this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) ); | |
14599 | |
14600 // support: jQuery <1.8 | |
14601 // jQuery <1.8 returns false if the request is canceled in beforeSend, | |
14602 // but as of 1.8, $.ajax() always returns a jqXHR object. | |
14603 if ( this.xhr && this.xhr.statusText !== "canceled" ) { | |
14604 tab.addClass( "ui-tabs-loading" ); | |
14605 panel.attr( "aria-busy", "true" ); | |
14606 | |
14607 this.xhr | |
14608 .success(function( response ) { | |
14609 // support: jQuery <1.8 | |
14610 // http://bugs.jquery.com/ticket/11778 | |
14611 setTimeout(function() { | |
14612 panel.html( response ); | |
14613 that._trigger( "load", event, eventData ); | |
14614 }, 1 ); | |
14615 }) | |
14616 .complete(function( jqXHR, status ) { | |
14617 // support: jQuery <1.8 | |
14618 // http://bugs.jquery.com/ticket/11778 | |
14619 setTimeout(function() { | |
14620 if ( status === "abort" ) { | |
14621 that.panels.stop( false, true ); | |
14622 } | |
14623 | |
14624 tab.removeClass( "ui-tabs-loading" ); | |
14625 panel.removeAttr( "aria-busy" ); | |
14626 | |
14627 if ( jqXHR === that.xhr ) { | |
14628 delete that.xhr; | |
14629 } | |
14630 }, 1 ); | |
14631 }); | |
14632 } | |
14633 }, | |
14634 | |
14635 _ajaxSettings: function( anchor, event, eventData ) { | |
14636 var that = this; | |
14637 return { | |
14638 url: anchor.attr( "href" ), | |
14639 beforeSend: function( jqXHR, settings ) { | |
14640 return that._trigger( "beforeLoad", event, | |
14641 $.extend( { jqXHR : jqXHR, ajaxSettings: settings }, eventData ) ); | |
14642 } | |
14643 }; | |
14644 }, | |
14645 | |
14646 _getPanelForTab: function( tab ) { | |
14647 var id = $( tab ).attr( "aria-controls" ); | |
14648 return this.element.find( this._sanitizeSelector( "#" + id ) ); | |
14649 } | |
14650 }); | |
14651 | |
14652 })( jQuery ); | |
14653 | |
14654 (function( $ ) { | |
14655 | |
14656 var increments = 0; | |
14657 | |
14658 function addDescribedBy( elem, id ) { | |
14659 var describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ); | |
14660 describedby.push( id ); | |
14661 elem | |
14662 .data( "ui-tooltip-id", id ) | |
14663 .attr( "aria-describedby", $.trim( describedby.join( " " ) ) ); | |
14664 } | |
14665 | |
14666 function removeDescribedBy( elem ) { | |
14667 var id = elem.data( "ui-tooltip-id" ), | |
14668 describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ), | |
14669 index = $.inArray( id, describedby ); | |
14670 if ( index !== -1 ) { | |
14671 describedby.splice( index, 1 ); | |
14672 } | |
14673 | |
14674 elem.removeData( "ui-tooltip-id" ); | |
14675 describedby = $.trim( describedby.join( " " ) ); | |
14676 if ( describedby ) { | |
14677 elem.attr( "aria-describedby", describedby ); | |
14678 } else { | |
14679 elem.removeAttr( "aria-describedby" ); | |
14680 } | |
14681 } | |
14682 | |
14683 $.widget( "ui.tooltip", { | |
14684 version: "1.10.4", | |
14685 options: { | |
14686 content: function() { | |
14687 // support: IE<9, Opera in jQuery <1.7 | |
14688 // .text() can't accept undefined, so coerce to a string | |
14689 var title = $( this ).attr( "title" ) || ""; | |
14690 // Escape title, since we're going from an attribute to raw HTML | |
14691 return $( "<a>" ).text( title ).html(); | |
14692 }, | |
14693 hide: true, | |
14694 // Disabled elements have inconsistent behavior across browsers (#8661) | |
14695 items: "[title]:not([disabled])", | |
14696 position: { | |
14697 my: "left top+15", | |
14698 at: "left bottom", | |
14699 collision: "flipfit flip" | |
14700 }, | |
14701 show: true, | |
14702 tooltipClass: null, | |
14703 track: false, | |
14704 | |
14705 // callbacks | |
14706 close: null, | |
14707 open: null | |
14708 }, | |
14709 | |
14710 _create: function() { | |
14711 this._on({ | |
14712 mouseover: "open", | |
14713 focusin: "open" | |
14714 }); | |
14715 | |
14716 // IDs of generated tooltips, needed for destroy | |
14717 this.tooltips = {}; | |
14718 // IDs of parent tooltips where we removed the title attribute | |
14719 this.parents = {}; | |
14720 | |
14721 if ( this.options.disabled ) { | |
14722 this._disable(); | |
14723 } | |
14724 }, | |
14725 | |
14726 _setOption: function( key, value ) { | |
14727 var that = this; | |
14728 | |
14729 if ( key === "disabled" ) { | |
14730 this[ value ? "_disable" : "_enable" ](); | |
14731 this.options[ key ] = value; | |
14732 // disable element style changes | |
14733 return; | |
14734 } | |
14735 | |
14736 this._super( key, value ); | |
14737 | |
14738 if ( key === "content" ) { | |
14739 $.each( this.tooltips, function( id, element ) { | |
14740 that._updateContent( element ); | |
14741 }); | |
14742 } | |
14743 }, | |
14744 | |
14745 _disable: function() { | |
14746 var that = this; | |
14747 | |
14748 // close open tooltips | |
14749 $.each( this.tooltips, function( id, element ) { | |
14750 var event = $.Event( "blur" ); | |
14751 event.target = event.currentTarget = element[0]; | |
14752 that.close( event, true ); | |
14753 }); | |
14754 | |
14755 // remove title attributes to prevent native tooltips | |
14756 this.element.find( this.options.items ).addBack().each(function() { | |
14757 var element = $( this ); | |
14758 if ( element.is( "[title]" ) ) { | |
14759 element | |
14760 .data( "ui-tooltip-title", element.attr( "title" ) ) | |
14761 .attr( "title", "" ); | |
14762 } | |
14763 }); | |
14764 }, | |
14765 | |
14766 _enable: function() { | |
14767 // restore title attributes | |
14768 this.element.find( this.options.items ).addBack().each(function() { | |
14769 var element = $( this ); | |
14770 if ( element.data( "ui-tooltip-title" ) ) { | |
14771 element.attr( "title", element.data( "ui-tooltip-title" ) ); | |
14772 } | |
14773 }); | |
14774 }, | |
14775 | |
14776 open: function( event ) { | |
14777 var that = this, | |
14778 target = $( event ? event.target : this.element ) | |
14779 // we need closest here due to mouseover bubbling, | |
14780 // but always pointing at the same event target | |
14781 .closest( this.options.items ); | |
14782 | |
14783 // No element to show a tooltip for or the tooltip is already open | |
14784 if ( !target.length || target.data( "ui-tooltip-id" ) ) { | |
14785 return; | |
14786 } | |
14787 | |
14788 if ( target.attr( "title" ) ) { | |
14789 target.data( "ui-tooltip-title", target.attr( "title" ) ); | |
14790 } | |
14791 | |
14792 target.data( "ui-tooltip-open", true ); | |
14793 | |
14794 // kill parent tooltips, custom or native, for hover | |
14795 if ( event && event.type === "mouseover" ) { | |
14796 target.parents().each(function() { | |
14797 var parent = $( this ), | |
14798 blurEvent; | |
14799 if ( parent.data( "ui-tooltip-open" ) ) { | |
14800 blurEvent = $.Event( "blur" ); | |
14801 blurEvent.target = blurEvent.currentTarget = this; | |
14802 that.close( blurEvent, true ); | |
14803 } | |
14804 if ( parent.attr( "title" ) ) { | |
14805 parent.uniqueId(); | |
14806 that.parents[ this.id ] = { | |
14807 element: this, | |
14808 title: parent.attr( "title" ) | |
14809 }; | |
14810 parent.attr( "title", "" ); | |
14811 } | |
14812 }); | |
14813 } | |
14814 | |
14815 this._updateContent( target, event ); | |
14816 }, | |
14817 | |
14818 _updateContent: function( target, event ) { | |
14819 var content, | |
14820 contentOption = this.options.content, | |
14821 that = this, | |
14822 eventType = event ? event.type : null; | |
14823 | |
14824 if ( typeof contentOption === "string" ) { | |
14825 return this._open( event, target, contentOption ); | |
14826 } | |
14827 | |
14828 content = contentOption.call( target[0], function( response ) { | |
14829 // ignore async response if tooltip was closed already | |
14830 if ( !target.data( "ui-tooltip-open" ) ) { | |
14831 return; | |
14832 } | |
14833 // IE may instantly serve a cached response for ajax requests | |
14834 // delay this call to _open so the other call to _open runs first | |
14835 that._delay(function() { | |
14836 // jQuery creates a special event for focusin when it doesn't | |
14837 // exist natively. To improve performance, the native event | |
14838 // object is reused and the type is changed. Therefore, we can't | |
14839 // rely on the type being correct after the event finished | |
14840 // bubbling, so we set it back to the previous value. (#8740) | |
14841 if ( event ) { | |
14842 event.type = eventType; | |
14843 } | |
14844 this._open( event, target, response ); | |
14845 }); | |
14846 }); | |
14847 if ( content ) { | |
14848 this._open( event, target, content ); | |
14849 } | |
14850 }, | |
14851 | |
14852 _open: function( event, target, content ) { | |
14853 var tooltip, events, delayedShow, | |
14854 positionOption = $.extend( {}, this.options.position ); | |
14855 | |
14856 if ( !content ) { | |
14857 return; | |
14858 } | |
14859 | |
14860 // Content can be updated multiple times. If the tooltip already | |
14861 // exists, then just update the content and bail. | |
14862 tooltip = this._find( target ); | |
14863 if ( tooltip.length ) { | |
14864 tooltip.find( ".ui-tooltip-content" ).html( content ); | |
14865 return; | |
14866 } | |
14867 | |
14868 // if we have a title, clear it to prevent the native tooltip | |
14869 // we have to check first to avoid defining a title if none exists | |
14870 // (we don't want to cause an element to start matching [title]) | |
14871 // | |
14872 // We use removeAttr only for key events, to allow IE to export the correct | |
14873 // accessible attributes. For mouse events, set to empty string to avoid | |
14874 // native tooltip showing up (happens only when removing inside mouseover). | |
14875 if ( target.is( "[title]" ) ) { | |
14876 if ( event && event.type === "mouseover" ) { | |
14877 target.attr( "title", "" ); | |
14878 } else { | |
14879 target.removeAttr( "title" ); | |
14880 } | |
14881 } | |
14882 | |
14883 tooltip = this._tooltip( target ); | |
14884 addDescribedBy( target, tooltip.attr( "id" ) ); | |
14885 tooltip.find( ".ui-tooltip-content" ).html( content ); | |
14886 | |
14887 function position( event ) { | |
14888 positionOption.of = event; | |
14889 if ( tooltip.is( ":hidden" ) ) { | |
14890 return; | |
14891 } | |
14892 tooltip.position( positionOption ); | |
14893 } | |
14894 if ( this.options.track && event && /^mouse/.test( event.type ) ) { | |
14895 this._on( this.document, { | |
14896 mousemove: position | |
14897 }); | |
14898 // trigger once to override element-relative positioning | |
14899 position( event ); | |
14900 } else { | |
14901 tooltip.position( $.extend({ | |
14902 of: target | |
14903 }, this.options.position ) ); | |
14904 } | |
14905 | |
14906 tooltip.hide(); | |
14907 | |
14908 this._show( tooltip, this.options.show ); | |
14909 // Handle tracking tooltips that are shown with a delay (#8644). As soon | |
14910 // as the tooltip is visible, position the tooltip using the most recent | |
14911 // event. | |
14912 if ( this.options.show && this.options.show.delay ) { | |
14913 delayedShow = this.delayedShow = setInterval(function() { | |
14914 if ( tooltip.is( ":visible" ) ) { | |
14915 position( positionOption.of ); | |
14916 clearInterval( delayedShow ); | |
14917 } | |
14918 }, $.fx.interval ); | |
14919 } | |
14920 | |
14921 this._trigger( "open", event, { tooltip: tooltip } ); | |
14922 | |
14923 events = { | |
14924 keyup: function( event ) { | |
14925 if ( event.keyCode === $.ui.keyCode.ESCAPE ) { | |
14926 var fakeEvent = $.Event(event); | |
14927 fakeEvent.currentTarget = target[0]; | |
14928 this.close( fakeEvent, true ); | |
14929 } | |
14930 }, | |
14931 remove: function() { | |
14932 this._removeTooltip( tooltip ); | |
14933 } | |
14934 }; | |
14935 if ( !event || event.type === "mouseover" ) { | |
14936 events.mouseleave = "close"; | |
14937 } | |
14938 if ( !event || event.type === "focusin" ) { | |
14939 events.focusout = "close"; | |
14940 } | |
14941 this._on( true, target, events ); | |
14942 }, | |
14943 | |
14944 close: function( event ) { | |
14945 var that = this, | |
14946 target = $( event ? event.currentTarget : this.element ), | |
14947 tooltip = this._find( target ); | |
14948 | |
14949 // disabling closes the tooltip, so we need to track when we're closing | |
14950 // to avoid an infinite loop in case the tooltip becomes disabled on close | |
14951 if ( this.closing ) { | |
14952 return; | |
14953 } | |
14954 | |
14955 // Clear the interval for delayed tracking tooltips | |
14956 clearInterval( this.delayedShow ); | |
14957 | |
14958 // only set title if we had one before (see comment in _open()) | |
14959 if ( target.data( "ui-tooltip-title" ) ) { | |
14960 target.attr( "title", target.data( "ui-tooltip-title" ) ); | |
14961 } | |
14962 | |
14963 removeDescribedBy( target ); | |
14964 | |
14965 tooltip.stop( true ); | |
14966 this._hide( tooltip, this.options.hide, function() { | |
14967 that._removeTooltip( $( this ) ); | |
14968 }); | |
14969 | |
14970 target.removeData( "ui-tooltip-open" ); | |
14971 this._off( target, "mouseleave focusout keyup" ); | |
14972 // Remove 'remove' binding only on delegated targets | |
14973 if ( target[0] !== this.element[0] ) { | |
14974 this._off( target, "remove" ); | |
14975 } | |
14976 this._off( this.document, "mousemove" ); | |
14977 | |
14978 if ( event && event.type === "mouseleave" ) { | |
14979 $.each( this.parents, function( id, parent ) { | |
14980 $( parent.element ).attr( "title", parent.title ); | |
14981 delete that.parents[ id ]; | |
14982 }); | |
14983 } | |
14984 | |
14985 this.closing = true; | |
14986 this._trigger( "close", event, { tooltip: tooltip } ); | |
14987 this.closing = false; | |
14988 }, | |
14989 | |
14990 _tooltip: function( element ) { | |
14991 var id = "ui-tooltip-" + increments++, | |
14992 tooltip = $( "<div>" ) | |
14993 .attr({ | |
14994 id: id, | |
14995 role: "tooltip" | |
14996 }) | |
14997 .addClass( "ui-tooltip ui-widget ui-corner-all ui-widget-content " + | |
14998 ( this.options.tooltipClass || "" ) ); | |
14999 $( "<div>" ) | |
15000 .addClass( "ui-tooltip-content" ) | |
15001 .appendTo( tooltip ); | |
15002 tooltip.appendTo( this.document[0].body ); | |
15003 this.tooltips[ id ] = element; | |
15004 return tooltip; | |
15005 }, | |
15006 | |
15007 _find: function( target ) { | |
15008 var id = target.data( "ui-tooltip-id" ); | |
15009 return id ? $( "#" + id ) : $(); | |
15010 }, | |
15011 | |
15012 _removeTooltip: function( tooltip ) { | |
15013 tooltip.remove(); | |
15014 delete this.tooltips[ tooltip.attr( "id" ) ]; | |
15015 }, | |
15016 | |
15017 _destroy: function() { | |
15018 var that = this; | |
15019 | |
15020 // close open tooltips | |
15021 $.each( this.tooltips, function( id, element ) { | |
15022 // Delegate to close method to handle common cleanup | |
15023 var event = $.Event( "blur" ); | |
15024 event.target = event.currentTarget = element[0]; | |
15025 that.close( event, true ); | |
15026 | |
15027 // Remove immediately; destroying an open tooltip doesn't use the | |
15028 // hide animation | |
15029 $( "#" + id ).remove(); | |
15030 | |
15031 // Restore the title | |
15032 if ( element.data( "ui-tooltip-title" ) ) { | |
15033 element.attr( "title", element.data( "ui-tooltip-title" ) ); | |
15034 element.removeData( "ui-tooltip-title" ); | |
15035 } | |
15036 }); | |
15037 } | |
15038 }); | |
15039 | |
15040 }( jQuery ) ); |