Mercurial > repos > saskia-hiltemann > ireport
comparison jquery-ui.js @ 1:440f4aa3db97 draft
Added option to dowload iReports
author | saskia-hiltemann |
---|---|
date | Wed, 30 Jul 2014 07:03:43 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
0:ac5f9272033b | 1:440f4aa3db97 |
---|---|
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.position.js, jquery.ui.accordion.js, jquery.ui.autocomplete.js, jquery.ui.button.js, jquery.ui.datepicker.js, jquery.ui.dialog.js, jquery.ui.draggable.js, jquery.ui.droppable.js, jquery.ui.effect.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.progressbar.js, jquery.ui.resizable.js, jquery.ui.selectable.js, jquery.ui.slider.js, jquery.ui.sortable.js, jquery.ui.spinner.js, jquery.ui.tabs.js, jquery.ui.tooltip.js | |
4 * Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */ | |
5 | |
6 (function( $, undefined ) { | |
7 | |
8 var uuid = 0, | |
9 runiqueId = /^ui-id-\d+$/; | |
10 | |
11 // $.ui might exist from components with no dependencies, e.g., $.ui.position | |
12 $.ui = $.ui || {}; | |
13 | |
14 $.extend( $.ui, { | |
15 version: "1.10.4", | |
16 | |
17 keyCode: { | |
18 BACKSPACE: 8, | |
19 COMMA: 188, | |
20 DELETE: 46, | |
21 DOWN: 40, | |
22 END: 35, | |
23 ENTER: 13, | |
24 ESCAPE: 27, | |
25 HOME: 36, | |
26 LEFT: 37, | |
27 NUMPAD_ADD: 107, | |
28 NUMPAD_DECIMAL: 110, | |
29 NUMPAD_DIVIDE: 111, | |
30 NUMPAD_ENTER: 108, | |
31 NUMPAD_MULTIPLY: 106, | |
32 NUMPAD_SUBTRACT: 109, | |
33 PAGE_DOWN: 34, | |
34 PAGE_UP: 33, | |
35 PERIOD: 190, | |
36 RIGHT: 39, | |
37 SPACE: 32, | |
38 TAB: 9, | |
39 UP: 38 | |
40 } | |
41 }); | |
42 | |
43 // plugins | |
44 $.fn.extend({ | |
45 focus: (function( orig ) { | |
46 return function( delay, fn ) { | |
47 return typeof delay === "number" ? | |
48 this.each(function() { | |
49 var elem = this; | |
50 setTimeout(function() { | |
51 $( elem ).focus(); | |
52 if ( fn ) { | |
53 fn.call( elem ); | |
54 } | |
55 }, delay ); | |
56 }) : | |
57 orig.apply( this, arguments ); | |
58 }; | |
59 })( $.fn.focus ), | |
60 | |
61 scrollParent: function() { | |
62 var scrollParent; | |
63 if (($.ui.ie && (/(static|relative)/).test(this.css("position"))) || (/absolute/).test(this.css("position"))) { | |
64 scrollParent = this.parents().filter(function() { | |
65 return (/(relative|absolute|fixed)/).test($.css(this,"position")) && (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x")); | |
66 }).eq(0); | |
67 } else { | |
68 scrollParent = this.parents().filter(function() { | |
69 return (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x")); | |
70 }).eq(0); | |
71 } | |
72 | |
73 return (/fixed/).test(this.css("position")) || !scrollParent.length ? $(document) : scrollParent; | |
74 }, | |
75 | |
76 zIndex: function( zIndex ) { | |
77 if ( zIndex !== undefined ) { | |
78 return this.css( "zIndex", zIndex ); | |
79 } | |
80 | |
81 if ( this.length ) { | |
82 var elem = $( this[ 0 ] ), position, value; | |
83 while ( elem.length && elem[ 0 ] !== document ) { | |
84 // Ignore z-index if position is set to a value where z-index is ignored by the browser | |
85 // This makes behavior of this function consistent across browsers | |
86 // WebKit always returns auto if the element is positioned | |
87 position = elem.css( "position" ); | |
88 if ( position === "absolute" || position === "relative" || position === "fixed" ) { | |
89 // IE returns 0 when zIndex is not specified | |
90 // other browsers return a string | |
91 // we ignore the case of nested elements with an explicit value of 0 | |
92 // <div style="z-index: -10;"><div style="z-index: 0;"></div></div> | |
93 value = parseInt( elem.css( "zIndex" ), 10 ); | |
94 if ( !isNaN( value ) && value !== 0 ) { | |
95 return value; | |
96 } | |
97 } | |
98 elem = elem.parent(); | |
99 } | |
100 } | |
101 | |
102 return 0; | |
103 }, | |
104 | |
105 uniqueId: function() { | |
106 return this.each(function() { | |
107 if ( !this.id ) { | |
108 this.id = "ui-id-" + (++uuid); | |
109 } | |
110 }); | |
111 }, | |
112 | |
113 removeUniqueId: function() { | |
114 return this.each(function() { | |
115 if ( runiqueId.test( this.id ) ) { | |
116 $( this ).removeAttr( "id" ); | |
117 } | |
118 }); | |
119 } | |
120 }); | |
121 | |
122 // selectors | |
123 function focusable( element, isTabIndexNotNaN ) { | |
124 var map, mapName, img, | |
125 nodeName = element.nodeName.toLowerCase(); | |
126 if ( "area" === nodeName ) { | |
127 map = element.parentNode; | |
128 mapName = map.name; | |
129 if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) { | |
130 return false; | |
131 } | |
132 img = $( "img[usemap=#" + mapName + "]" )[0]; | |
133 return !!img && visible( img ); | |
134 } | |
135 return ( /input|select|textarea|button|object/.test( nodeName ) ? | |
136 !element.disabled : | |
137 "a" === nodeName ? | |
138 element.href || isTabIndexNotNaN : | |
139 isTabIndexNotNaN) && | |
140 // the element and all of its ancestors must be visible | |
141 visible( element ); | |
142 } | |
143 | |
144 function visible( element ) { | |
145 return $.expr.filters.visible( element ) && | |
146 !$( element ).parents().addBack().filter(function() { | |
147 return $.css( this, "visibility" ) === "hidden"; | |
148 }).length; | |
149 } | |
150 | |
151 $.extend( $.expr[ ":" ], { | |
152 data: $.expr.createPseudo ? | |
153 $.expr.createPseudo(function( dataName ) { | |
154 return function( elem ) { | |
155 return !!$.data( elem, dataName ); | |
156 }; | |
157 }) : | |
158 // support: jQuery <1.8 | |
159 function( elem, i, match ) { | |
160 return !!$.data( elem, match[ 3 ] ); | |
161 }, | |
162 | |
163 focusable: function( element ) { | |
164 return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) ); | |
165 }, | |
166 | |
167 tabbable: function( element ) { | |
168 var tabIndex = $.attr( element, "tabindex" ), | |
169 isTabIndexNaN = isNaN( tabIndex ); | |
170 return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN ); | |
171 } | |
172 }); | |
173 | |
174 // support: jQuery <1.8 | |
175 if ( !$( "<a>" ).outerWidth( 1 ).jquery ) { | |
176 $.each( [ "Width", "Height" ], function( i, name ) { | |
177 var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ], | |
178 type = name.toLowerCase(), | |
179 orig = { | |
180 innerWidth: $.fn.innerWidth, | |
181 innerHeight: $.fn.innerHeight, | |
182 outerWidth: $.fn.outerWidth, | |
183 outerHeight: $.fn.outerHeight | |
184 }; | |
185 | |
186 function reduce( elem, size, border, margin ) { | |
187 $.each( side, function() { | |
188 size -= parseFloat( $.css( elem, "padding" + this ) ) || 0; | |
189 if ( border ) { | |
190 size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0; | |
191 } | |
192 if ( margin ) { | |
193 size -= parseFloat( $.css( elem, "margin" + this ) ) || 0; | |
194 } | |
195 }); | |
196 return size; | |
197 } | |
198 | |
199 $.fn[ "inner" + name ] = function( size ) { | |
200 if ( size === undefined ) { | |
201 return orig[ "inner" + name ].call( this ); | |
202 } | |
203 | |
204 return this.each(function() { | |
205 $( this ).css( type, reduce( this, size ) + "px" ); | |
206 }); | |
207 }; | |
208 | |
209 $.fn[ "outer" + name] = function( size, margin ) { | |
210 if ( typeof size !== "number" ) { | |
211 return orig[ "outer" + name ].call( this, size ); | |
212 } | |
213 | |
214 return this.each(function() { | |
215 $( this).css( type, reduce( this, size, true, margin ) + "px" ); | |
216 }); | |
217 }; | |
218 }); | |
219 } | |
220 | |
221 // support: jQuery <1.8 | |
222 if ( !$.fn.addBack ) { | |
223 $.fn.addBack = function( selector ) { | |
224 return this.add( selector == null ? | |
225 this.prevObject : this.prevObject.filter( selector ) | |
226 ); | |
227 }; | |
228 } | |
229 | |
230 // support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413) | |
231 if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) { | |
232 $.fn.removeData = (function( removeData ) { | |
233 return function( key ) { | |
234 if ( arguments.length ) { | |
235 return removeData.call( this, $.camelCase( key ) ); | |
236 } else { | |
237 return removeData.call( this ); | |
238 } | |
239 }; | |
240 })( $.fn.removeData ); | |
241 } | |
242 | |
243 | |
244 | |
245 | |
246 | |
247 // deprecated | |
248 $.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() ); | |
249 | |
250 $.support.selectstart = "onselectstart" in document.createElement( "div" ); | |
251 $.fn.extend({ | |
252 disableSelection: function() { | |
253 return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) + | |
254 ".ui-disableSelection", function( event ) { | |
255 event.preventDefault(); | |
256 }); | |
257 }, | |
258 | |
259 enableSelection: function() { | |
260 return this.unbind( ".ui-disableSelection" ); | |
261 } | |
262 }); | |
263 | |
264 $.extend( $.ui, { | |
265 // $.ui.plugin is deprecated. Use $.widget() extensions instead. | |
266 plugin: { | |
267 add: function( module, option, set ) { | |
268 var i, | |
269 proto = $.ui[ module ].prototype; | |
270 for ( i in set ) { | |
271 proto.plugins[ i ] = proto.plugins[ i ] || []; | |
272 proto.plugins[ i ].push( [ option, set[ i ] ] ); | |
273 } | |
274 }, | |
275 call: function( instance, name, args ) { | |
276 var i, | |
277 set = instance.plugins[ name ]; | |
278 if ( !set || !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) { | |
279 return; | |
280 } | |
281 | |
282 for ( i = 0; i < set.length; i++ ) { | |
283 if ( instance.options[ set[ i ][ 0 ] ] ) { | |
284 set[ i ][ 1 ].apply( instance.element, args ); | |
285 } | |
286 } | |
287 } | |
288 }, | |
289 | |
290 // only used by resizable | |
291 hasScroll: function( el, a ) { | |
292 | |
293 //If overflow is hidden, the element might have extra content, but the user wants to hide it | |
294 if ( $( el ).css( "overflow" ) === "hidden") { | |
295 return false; | |
296 } | |
297 | |
298 var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop", | |
299 has = false; | |
300 | |
301 if ( el[ scroll ] > 0 ) { | |
302 return true; | |
303 } | |
304 | |
305 // TODO: determine which cases actually cause this to happen | |
306 // if the element doesn't have the scroll set, see if it's possible to | |
307 // set the scroll | |
308 el[ scroll ] = 1; | |
309 has = ( el[ scroll ] > 0 ); | |
310 el[ scroll ] = 0; | |
311 return has; | |
312 } | |
313 }); | |
314 | |
315 })( jQuery ); | |
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 (function( $, undefined ) { | |
828 | |
829 var mouseHandled = false; | |
830 $( document ).mouseup( function() { | |
831 mouseHandled = false; | |
832 }); | |
833 | |
834 $.widget("ui.mouse", { | |
835 version: "1.10.4", | |
836 options: { | |
837 cancel: "input,textarea,button,select,option", | |
838 distance: 1, | |
839 delay: 0 | |
840 }, | |
841 _mouseInit: function() { | |
842 var that = this; | |
843 | |
844 this.element | |
845 .bind("mousedown."+this.widgetName, function(event) { | |
846 return that._mouseDown(event); | |
847 }) | |
848 .bind("click."+this.widgetName, function(event) { | |
849 if (true === $.data(event.target, that.widgetName + ".preventClickEvent")) { | |
850 $.removeData(event.target, that.widgetName + ".preventClickEvent"); | |
851 event.stopImmediatePropagation(); | |
852 return false; | |
853 } | |
854 }); | |
855 | |
856 this.started = false; | |
857 }, | |
858 | |
859 // TODO: make sure destroying one instance of mouse doesn't mess with | |
860 // other instances of mouse | |
861 _mouseDestroy: function() { | |
862 this.element.unbind("."+this.widgetName); | |
863 if ( this._mouseMoveDelegate ) { | |
864 $(document) | |
865 .unbind("mousemove."+this.widgetName, this._mouseMoveDelegate) | |
866 .unbind("mouseup."+this.widgetName, this._mouseUpDelegate); | |
867 } | |
868 }, | |
869 | |
870 _mouseDown: function(event) { | |
871 // don't let more than one widget handle mouseStart | |
872 if( mouseHandled ) { return; } | |
873 | |
874 // we may have missed mouseup (out of window) | |
875 (this._mouseStarted && this._mouseUp(event)); | |
876 | |
877 this._mouseDownEvent = event; | |
878 | |
879 var that = this, | |
880 btnIsLeft = (event.which === 1), | |
881 // event.target.nodeName works around a bug in IE 8 with | |
882 // disabled inputs (#7620) | |
883 elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false); | |
884 if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) { | |
885 return true; | |
886 } | |
887 | |
888 this.mouseDelayMet = !this.options.delay; | |
889 if (!this.mouseDelayMet) { | |
890 this._mouseDelayTimer = setTimeout(function() { | |
891 that.mouseDelayMet = true; | |
892 }, this.options.delay); | |
893 } | |
894 | |
895 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { | |
896 this._mouseStarted = (this._mouseStart(event) !== false); | |
897 if (!this._mouseStarted) { | |
898 event.preventDefault(); | |
899 return true; | |
900 } | |
901 } | |
902 | |
903 // Click event may never have fired (Gecko & Opera) | |
904 if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) { | |
905 $.removeData(event.target, this.widgetName + ".preventClickEvent"); | |
906 } | |
907 | |
908 // these delegates are required to keep context | |
909 this._mouseMoveDelegate = function(event) { | |
910 return that._mouseMove(event); | |
911 }; | |
912 this._mouseUpDelegate = function(event) { | |
913 return that._mouseUp(event); | |
914 }; | |
915 $(document) | |
916 .bind("mousemove."+this.widgetName, this._mouseMoveDelegate) | |
917 .bind("mouseup."+this.widgetName, this._mouseUpDelegate); | |
918 | |
919 event.preventDefault(); | |
920 | |
921 mouseHandled = true; | |
922 return true; | |
923 }, | |
924 | |
925 _mouseMove: function(event) { | |
926 // IE mouseup check - mouseup happened when mouse was out of window | |
927 if ($.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) { | |
928 return this._mouseUp(event); | |
929 } | |
930 | |
931 if (this._mouseStarted) { | |
932 this._mouseDrag(event); | |
933 return event.preventDefault(); | |
934 } | |
935 | |
936 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { | |
937 this._mouseStarted = | |
938 (this._mouseStart(this._mouseDownEvent, event) !== false); | |
939 (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event)); | |
940 } | |
941 | |
942 return !this._mouseStarted; | |
943 }, | |
944 | |
945 _mouseUp: function(event) { | |
946 $(document) | |
947 .unbind("mousemove."+this.widgetName, this._mouseMoveDelegate) | |
948 .unbind("mouseup."+this.widgetName, this._mouseUpDelegate); | |
949 | |
950 if (this._mouseStarted) { | |
951 this._mouseStarted = false; | |
952 | |
953 if (event.target === this._mouseDownEvent.target) { | |
954 $.data(event.target, this.widgetName + ".preventClickEvent", true); | |
955 } | |
956 | |
957 this._mouseStop(event); | |
958 } | |
959 | |
960 return false; | |
961 }, | |
962 | |
963 _mouseDistanceMet: function(event) { | |
964 return (Math.max( | |
965 Math.abs(this._mouseDownEvent.pageX - event.pageX), | |
966 Math.abs(this._mouseDownEvent.pageY - event.pageY) | |
967 ) >= this.options.distance | |
968 ); | |
969 }, | |
970 | |
971 _mouseDelayMet: function(/* event */) { | |
972 return this.mouseDelayMet; | |
973 }, | |
974 | |
975 // These are placeholder methods, to be overriden by extending plugin | |
976 _mouseStart: function(/* event */) {}, | |
977 _mouseDrag: function(/* event */) {}, | |
978 _mouseStop: function(/* event */) {}, | |
979 _mouseCapture: function(/* event */) { return true; } | |
980 }); | |
981 | |
982 })(jQuery); | |
983 (function( $, undefined ) { | |
984 | |
985 $.ui = $.ui || {}; | |
986 | |
987 var cachedScrollbarWidth, | |
988 max = Math.max, | |
989 abs = Math.abs, | |
990 round = Math.round, | |
991 rhorizontal = /left|center|right/, | |
992 rvertical = /top|center|bottom/, | |
993 roffset = /[\+\-]\d+(\.[\d]+)?%?/, | |
994 rposition = /^\w+/, | |
995 rpercent = /%$/, | |
996 _position = $.fn.position; | |
997 | |
998 function getOffsets( offsets, width, height ) { | |
999 return [ | |
1000 parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ), | |
1001 parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 ) | |
1002 ]; | |
1003 } | |
1004 | |
1005 function parseCss( element, property ) { | |
1006 return parseInt( $.css( element, property ), 10 ) || 0; | |
1007 } | |
1008 | |
1009 function getDimensions( elem ) { | |
1010 var raw = elem[0]; | |
1011 if ( raw.nodeType === 9 ) { | |
1012 return { | |
1013 width: elem.width(), | |
1014 height: elem.height(), | |
1015 offset: { top: 0, left: 0 } | |
1016 }; | |
1017 } | |
1018 if ( $.isWindow( raw ) ) { | |
1019 return { | |
1020 width: elem.width(), | |
1021 height: elem.height(), | |
1022 offset: { top: elem.scrollTop(), left: elem.scrollLeft() } | |
1023 }; | |
1024 } | |
1025 if ( raw.preventDefault ) { | |
1026 return { | |
1027 width: 0, | |
1028 height: 0, | |
1029 offset: { top: raw.pageY, left: raw.pageX } | |
1030 }; | |
1031 } | |
1032 return { | |
1033 width: elem.outerWidth(), | |
1034 height: elem.outerHeight(), | |
1035 offset: elem.offset() | |
1036 }; | |
1037 } | |
1038 | |
1039 $.position = { | |
1040 scrollbarWidth: function() { | |
1041 if ( cachedScrollbarWidth !== undefined ) { | |
1042 return cachedScrollbarWidth; | |
1043 } | |
1044 var w1, w2, | |
1045 div = $( "<div style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>" ), | |
1046 innerDiv = div.children()[0]; | |
1047 | |
1048 $( "body" ).append( div ); | |
1049 w1 = innerDiv.offsetWidth; | |
1050 div.css( "overflow", "scroll" ); | |
1051 | |
1052 w2 = innerDiv.offsetWidth; | |
1053 | |
1054 if ( w1 === w2 ) { | |
1055 w2 = div[0].clientWidth; | |
1056 } | |
1057 | |
1058 div.remove(); | |
1059 | |
1060 return (cachedScrollbarWidth = w1 - w2); | |
1061 }, | |
1062 getScrollInfo: function( within ) { | |
1063 var overflowX = within.isWindow || within.isDocument ? "" : | |
1064 within.element.css( "overflow-x" ), | |
1065 overflowY = within.isWindow || within.isDocument ? "" : | |
1066 within.element.css( "overflow-y" ), | |
1067 hasOverflowX = overflowX === "scroll" || | |
1068 ( overflowX === "auto" && within.width < within.element[0].scrollWidth ), | |
1069 hasOverflowY = overflowY === "scroll" || | |
1070 ( overflowY === "auto" && within.height < within.element[0].scrollHeight ); | |
1071 return { | |
1072 width: hasOverflowY ? $.position.scrollbarWidth() : 0, | |
1073 height: hasOverflowX ? $.position.scrollbarWidth() : 0 | |
1074 }; | |
1075 }, | |
1076 getWithinInfo: function( element ) { | |
1077 var withinElement = $( element || window ), | |
1078 isWindow = $.isWindow( withinElement[0] ), | |
1079 isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9; | |
1080 return { | |
1081 element: withinElement, | |
1082 isWindow: isWindow, | |
1083 isDocument: isDocument, | |
1084 offset: withinElement.offset() || { left: 0, top: 0 }, | |
1085 scrollLeft: withinElement.scrollLeft(), | |
1086 scrollTop: withinElement.scrollTop(), | |
1087 width: isWindow ? withinElement.width() : withinElement.outerWidth(), | |
1088 height: isWindow ? withinElement.height() : withinElement.outerHeight() | |
1089 }; | |
1090 } | |
1091 }; | |
1092 | |
1093 $.fn.position = function( options ) { | |
1094 if ( !options || !options.of ) { | |
1095 return _position.apply( this, arguments ); | |
1096 } | |
1097 | |
1098 // make a copy, we don't want to modify arguments | |
1099 options = $.extend( {}, options ); | |
1100 | |
1101 var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions, | |
1102 target = $( options.of ), | |
1103 within = $.position.getWithinInfo( options.within ), | |
1104 scrollInfo = $.position.getScrollInfo( within ), | |
1105 collision = ( options.collision || "flip" ).split( " " ), | |
1106 offsets = {}; | |
1107 | |
1108 dimensions = getDimensions( target ); | |
1109 if ( target[0].preventDefault ) { | |
1110 // force left top to allow flipping | |
1111 options.at = "left top"; | |
1112 } | |
1113 targetWidth = dimensions.width; | |
1114 targetHeight = dimensions.height; | |
1115 targetOffset = dimensions.offset; | |
1116 // clone to reuse original targetOffset later | |
1117 basePosition = $.extend( {}, targetOffset ); | |
1118 | |
1119 // force my and at to have valid horizontal and vertical positions | |
1120 // if a value is missing or invalid, it will be converted to center | |
1121 $.each( [ "my", "at" ], function() { | |
1122 var pos = ( options[ this ] || "" ).split( " " ), | |
1123 horizontalOffset, | |
1124 verticalOffset; | |
1125 | |
1126 if ( pos.length === 1) { | |
1127 pos = rhorizontal.test( pos[ 0 ] ) ? | |
1128 pos.concat( [ "center" ] ) : | |
1129 rvertical.test( pos[ 0 ] ) ? | |
1130 [ "center" ].concat( pos ) : | |
1131 [ "center", "center" ]; | |
1132 } | |
1133 pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center"; | |
1134 pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center"; | |
1135 | |
1136 // calculate offsets | |
1137 horizontalOffset = roffset.exec( pos[ 0 ] ); | |
1138 verticalOffset = roffset.exec( pos[ 1 ] ); | |
1139 offsets[ this ] = [ | |
1140 horizontalOffset ? horizontalOffset[ 0 ] : 0, | |
1141 verticalOffset ? verticalOffset[ 0 ] : 0 | |
1142 ]; | |
1143 | |
1144 // reduce to just the positions without the offsets | |
1145 options[ this ] = [ | |
1146 rposition.exec( pos[ 0 ] )[ 0 ], | |
1147 rposition.exec( pos[ 1 ] )[ 0 ] | |
1148 ]; | |
1149 }); | |
1150 | |
1151 // normalize collision option | |
1152 if ( collision.length === 1 ) { | |
1153 collision[ 1 ] = collision[ 0 ]; | |
1154 } | |
1155 | |
1156 if ( options.at[ 0 ] === "right" ) { | |
1157 basePosition.left += targetWidth; | |
1158 } else if ( options.at[ 0 ] === "center" ) { | |
1159 basePosition.left += targetWidth / 2; | |
1160 } | |
1161 | |
1162 if ( options.at[ 1 ] === "bottom" ) { | |
1163 basePosition.top += targetHeight; | |
1164 } else if ( options.at[ 1 ] === "center" ) { | |
1165 basePosition.top += targetHeight / 2; | |
1166 } | |
1167 | |
1168 atOffset = getOffsets( offsets.at, targetWidth, targetHeight ); | |
1169 basePosition.left += atOffset[ 0 ]; | |
1170 basePosition.top += atOffset[ 1 ]; | |
1171 | |
1172 return this.each(function() { | |
1173 var collisionPosition, using, | |
1174 elem = $( this ), | |
1175 elemWidth = elem.outerWidth(), | |
1176 elemHeight = elem.outerHeight(), | |
1177 marginLeft = parseCss( this, "marginLeft" ), | |
1178 marginTop = parseCss( this, "marginTop" ), | |
1179 collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width, | |
1180 collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height, | |
1181 position = $.extend( {}, basePosition ), | |
1182 myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() ); | |
1183 | |
1184 if ( options.my[ 0 ] === "right" ) { | |
1185 position.left -= elemWidth; | |
1186 } else if ( options.my[ 0 ] === "center" ) { | |
1187 position.left -= elemWidth / 2; | |
1188 } | |
1189 | |
1190 if ( options.my[ 1 ] === "bottom" ) { | |
1191 position.top -= elemHeight; | |
1192 } else if ( options.my[ 1 ] === "center" ) { | |
1193 position.top -= elemHeight / 2; | |
1194 } | |
1195 | |
1196 position.left += myOffset[ 0 ]; | |
1197 position.top += myOffset[ 1 ]; | |
1198 | |
1199 // if the browser doesn't support fractions, then round for consistent results | |
1200 if ( !$.support.offsetFractions ) { | |
1201 position.left = round( position.left ); | |
1202 position.top = round( position.top ); | |
1203 } | |
1204 | |
1205 collisionPosition = { | |
1206 marginLeft: marginLeft, | |
1207 marginTop: marginTop | |
1208 }; | |
1209 | |
1210 $.each( [ "left", "top" ], function( i, dir ) { | |
1211 if ( $.ui.position[ collision[ i ] ] ) { | |
1212 $.ui.position[ collision[ i ] ][ dir ]( position, { | |
1213 targetWidth: targetWidth, | |
1214 targetHeight: targetHeight, | |
1215 elemWidth: elemWidth, | |
1216 elemHeight: elemHeight, | |
1217 collisionPosition: collisionPosition, | |
1218 collisionWidth: collisionWidth, | |
1219 collisionHeight: collisionHeight, | |
1220 offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ], | |
1221 my: options.my, | |
1222 at: options.at, | |
1223 within: within, | |
1224 elem : elem | |
1225 }); | |
1226 } | |
1227 }); | |
1228 | |
1229 if ( options.using ) { | |
1230 // adds feedback as second argument to using callback, if present | |
1231 using = function( props ) { | |
1232 var left = targetOffset.left - position.left, | |
1233 right = left + targetWidth - elemWidth, | |
1234 top = targetOffset.top - position.top, | |
1235 bottom = top + targetHeight - elemHeight, | |
1236 feedback = { | |
1237 target: { | |
1238 element: target, | |
1239 left: targetOffset.left, | |
1240 top: targetOffset.top, | |
1241 width: targetWidth, | |
1242 height: targetHeight | |
1243 }, | |
1244 element: { | |
1245 element: elem, | |
1246 left: position.left, | |
1247 top: position.top, | |
1248 width: elemWidth, | |
1249 height: elemHeight | |
1250 }, | |
1251 horizontal: right < 0 ? "left" : left > 0 ? "right" : "center", | |
1252 vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle" | |
1253 }; | |
1254 if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) { | |
1255 feedback.horizontal = "center"; | |
1256 } | |
1257 if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) { | |
1258 feedback.vertical = "middle"; | |
1259 } | |
1260 if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) { | |
1261 feedback.important = "horizontal"; | |
1262 } else { | |
1263 feedback.important = "vertical"; | |
1264 } | |
1265 options.using.call( this, props, feedback ); | |
1266 }; | |
1267 } | |
1268 | |
1269 elem.offset( $.extend( position, { using: using } ) ); | |
1270 }); | |
1271 }; | |
1272 | |
1273 $.ui.position = { | |
1274 fit: { | |
1275 left: function( position, data ) { | |
1276 var within = data.within, | |
1277 withinOffset = within.isWindow ? within.scrollLeft : within.offset.left, | |
1278 outerWidth = within.width, | |
1279 collisionPosLeft = position.left - data.collisionPosition.marginLeft, | |
1280 overLeft = withinOffset - collisionPosLeft, | |
1281 overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset, | |
1282 newOverRight; | |
1283 | |
1284 // element is wider than within | |
1285 if ( data.collisionWidth > outerWidth ) { | |
1286 // element is initially over the left side of within | |
1287 if ( overLeft > 0 && overRight <= 0 ) { | |
1288 newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset; | |
1289 position.left += overLeft - newOverRight; | |
1290 // element is initially over right side of within | |
1291 } else if ( overRight > 0 && overLeft <= 0 ) { | |
1292 position.left = withinOffset; | |
1293 // element is initially over both left and right sides of within | |
1294 } else { | |
1295 if ( overLeft > overRight ) { | |
1296 position.left = withinOffset + outerWidth - data.collisionWidth; | |
1297 } else { | |
1298 position.left = withinOffset; | |
1299 } | |
1300 } | |
1301 // too far left -> align with left edge | |
1302 } else if ( overLeft > 0 ) { | |
1303 position.left += overLeft; | |
1304 // too far right -> align with right edge | |
1305 } else if ( overRight > 0 ) { | |
1306 position.left -= overRight; | |
1307 // adjust based on position and margin | |
1308 } else { | |
1309 position.left = max( position.left - collisionPosLeft, position.left ); | |
1310 } | |
1311 }, | |
1312 top: function( position, data ) { | |
1313 var within = data.within, | |
1314 withinOffset = within.isWindow ? within.scrollTop : within.offset.top, | |
1315 outerHeight = data.within.height, | |
1316 collisionPosTop = position.top - data.collisionPosition.marginTop, | |
1317 overTop = withinOffset - collisionPosTop, | |
1318 overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset, | |
1319 newOverBottom; | |
1320 | |
1321 // element is taller than within | |
1322 if ( data.collisionHeight > outerHeight ) { | |
1323 // element is initially over the top of within | |
1324 if ( overTop > 0 && overBottom <= 0 ) { | |
1325 newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset; | |
1326 position.top += overTop - newOverBottom; | |
1327 // element is initially over bottom of within | |
1328 } else if ( overBottom > 0 && overTop <= 0 ) { | |
1329 position.top = withinOffset; | |
1330 // element is initially over both top and bottom of within | |
1331 } else { | |
1332 if ( overTop > overBottom ) { | |
1333 position.top = withinOffset + outerHeight - data.collisionHeight; | |
1334 } else { | |
1335 position.top = withinOffset; | |
1336 } | |
1337 } | |
1338 // too far up -> align with top | |
1339 } else if ( overTop > 0 ) { | |
1340 position.top += overTop; | |
1341 // too far down -> align with bottom edge | |
1342 } else if ( overBottom > 0 ) { | |
1343 position.top -= overBottom; | |
1344 // adjust based on position and margin | |
1345 } else { | |
1346 position.top = max( position.top - collisionPosTop, position.top ); | |
1347 } | |
1348 } | |
1349 }, | |
1350 flip: { | |
1351 left: function( position, data ) { | |
1352 var within = data.within, | |
1353 withinOffset = within.offset.left + within.scrollLeft, | |
1354 outerWidth = within.width, | |
1355 offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left, | |
1356 collisionPosLeft = position.left - data.collisionPosition.marginLeft, | |
1357 overLeft = collisionPosLeft - offsetLeft, | |
1358 overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft, | |
1359 myOffset = data.my[ 0 ] === "left" ? | |
1360 -data.elemWidth : | |
1361 data.my[ 0 ] === "right" ? | |
1362 data.elemWidth : | |
1363 0, | |
1364 atOffset = data.at[ 0 ] === "left" ? | |
1365 data.targetWidth : | |
1366 data.at[ 0 ] === "right" ? | |
1367 -data.targetWidth : | |
1368 0, | |
1369 offset = -2 * data.offset[ 0 ], | |
1370 newOverRight, | |
1371 newOverLeft; | |
1372 | |
1373 if ( overLeft < 0 ) { | |
1374 newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset; | |
1375 if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) { | |
1376 position.left += myOffset + atOffset + offset; | |
1377 } | |
1378 } | |
1379 else if ( overRight > 0 ) { | |
1380 newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft; | |
1381 if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) { | |
1382 position.left += myOffset + atOffset + offset; | |
1383 } | |
1384 } | |
1385 }, | |
1386 top: function( position, data ) { | |
1387 var within = data.within, | |
1388 withinOffset = within.offset.top + within.scrollTop, | |
1389 outerHeight = within.height, | |
1390 offsetTop = within.isWindow ? within.scrollTop : within.offset.top, | |
1391 collisionPosTop = position.top - data.collisionPosition.marginTop, | |
1392 overTop = collisionPosTop - offsetTop, | |
1393 overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop, | |
1394 top = data.my[ 1 ] === "top", | |
1395 myOffset = top ? | |
1396 -data.elemHeight : | |
1397 data.my[ 1 ] === "bottom" ? | |
1398 data.elemHeight : | |
1399 0, | |
1400 atOffset = data.at[ 1 ] === "top" ? | |
1401 data.targetHeight : | |
1402 data.at[ 1 ] === "bottom" ? | |
1403 -data.targetHeight : | |
1404 0, | |
1405 offset = -2 * data.offset[ 1 ], | |
1406 newOverTop, | |
1407 newOverBottom; | |
1408 if ( overTop < 0 ) { | |
1409 newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset; | |
1410 if ( ( position.top + myOffset + atOffset + offset) > overTop && ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) ) { | |
1411 position.top += myOffset + atOffset + offset; | |
1412 } | |
1413 } | |
1414 else if ( overBottom > 0 ) { | |
1415 newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop; | |
1416 if ( ( position.top + myOffset + atOffset + offset) > overBottom && ( newOverTop > 0 || abs( newOverTop ) < overBottom ) ) { | |
1417 position.top += myOffset + atOffset + offset; | |
1418 } | |
1419 } | |
1420 } | |
1421 }, | |
1422 flipfit: { | |
1423 left: function() { | |
1424 $.ui.position.flip.left.apply( this, arguments ); | |
1425 $.ui.position.fit.left.apply( this, arguments ); | |
1426 }, | |
1427 top: function() { | |
1428 $.ui.position.flip.top.apply( this, arguments ); | |
1429 $.ui.position.fit.top.apply( this, arguments ); | |
1430 } | |
1431 } | |
1432 }; | |
1433 | |
1434 // fraction support test | |
1435 (function () { | |
1436 var testElement, testElementParent, testElementStyle, offsetLeft, i, | |
1437 body = document.getElementsByTagName( "body" )[ 0 ], | |
1438 div = document.createElement( "div" ); | |
1439 | |
1440 //Create a "fake body" for testing based on method used in jQuery.support | |
1441 testElement = document.createElement( body ? "div" : "body" ); | |
1442 testElementStyle = { | |
1443 visibility: "hidden", | |
1444 width: 0, | |
1445 height: 0, | |
1446 border: 0, | |
1447 margin: 0, | |
1448 background: "none" | |
1449 }; | |
1450 if ( body ) { | |
1451 $.extend( testElementStyle, { | |
1452 position: "absolute", | |
1453 left: "-1000px", | |
1454 top: "-1000px" | |
1455 }); | |
1456 } | |
1457 for ( i in testElementStyle ) { | |
1458 testElement.style[ i ] = testElementStyle[ i ]; | |
1459 } | |
1460 testElement.appendChild( div ); | |
1461 testElementParent = body || document.documentElement; | |
1462 testElementParent.insertBefore( testElement, testElementParent.firstChild ); | |
1463 | |
1464 div.style.cssText = "position: absolute; left: 10.7432222px;"; | |
1465 | |
1466 offsetLeft = $( div ).offset().left; | |
1467 $.support.offsetFractions = offsetLeft > 10 && offsetLeft < 11; | |
1468 | |
1469 testElement.innerHTML = ""; | |
1470 testElementParent.removeChild( testElement ); | |
1471 })(); | |
1472 | |
1473 }( jQuery ) ); | |
1474 (function( $, undefined ) { | |
1475 | |
1476 var uid = 0, | |
1477 hideProps = {}, | |
1478 showProps = {}; | |
1479 | |
1480 hideProps.height = hideProps.paddingTop = hideProps.paddingBottom = | |
1481 hideProps.borderTopWidth = hideProps.borderBottomWidth = "hide"; | |
1482 showProps.height = showProps.paddingTop = showProps.paddingBottom = | |
1483 showProps.borderTopWidth = showProps.borderBottomWidth = "show"; | |
1484 | |
1485 $.widget( "ui.accordion", { | |
1486 version: "1.10.4", | |
1487 options: { | |
1488 active: 0, | |
1489 animate: {}, | |
1490 collapsible: false, | |
1491 event: "click", | |
1492 header: "> li > :first-child,> :not(li):even", | |
1493 heightStyle: "auto", | |
1494 icons: { | |
1495 activeHeader: "ui-icon-triangle-1-s", | |
1496 header: "ui-icon-triangle-1-e" | |
1497 }, | |
1498 | |
1499 // callbacks | |
1500 activate: null, | |
1501 beforeActivate: null | |
1502 }, | |
1503 | |
1504 _create: function() { | |
1505 var options = this.options; | |
1506 this.prevShow = this.prevHide = $(); | |
1507 this.element.addClass( "ui-accordion ui-widget ui-helper-reset" ) | |
1508 // ARIA | |
1509 .attr( "role", "tablist" ); | |
1510 | |
1511 // don't allow collapsible: false and active: false / null | |
1512 if ( !options.collapsible && (options.active === false || options.active == null) ) { | |
1513 options.active = 0; | |
1514 } | |
1515 | |
1516 this._processPanels(); | |
1517 // handle negative values | |
1518 if ( options.active < 0 ) { | |
1519 options.active += this.headers.length; | |
1520 } | |
1521 this._refresh(); | |
1522 }, | |
1523 | |
1524 _getCreateEventData: function() { | |
1525 return { | |
1526 header: this.active, | |
1527 panel: !this.active.length ? $() : this.active.next(), | |
1528 content: !this.active.length ? $() : this.active.next() | |
1529 }; | |
1530 }, | |
1531 | |
1532 _createIcons: function() { | |
1533 var icons = this.options.icons; | |
1534 if ( icons ) { | |
1535 $( "<span>" ) | |
1536 .addClass( "ui-accordion-header-icon ui-icon " + icons.header ) | |
1537 .prependTo( this.headers ); | |
1538 this.active.children( ".ui-accordion-header-icon" ) | |
1539 .removeClass( icons.header ) | |
1540 .addClass( icons.activeHeader ); | |
1541 this.headers.addClass( "ui-accordion-icons" ); | |
1542 } | |
1543 }, | |
1544 | |
1545 _destroyIcons: function() { | |
1546 this.headers | |
1547 .removeClass( "ui-accordion-icons" ) | |
1548 .children( ".ui-accordion-header-icon" ) | |
1549 .remove(); | |
1550 }, | |
1551 | |
1552 _destroy: function() { | |
1553 var contents; | |
1554 | |
1555 // clean up main element | |
1556 this.element | |
1557 .removeClass( "ui-accordion ui-widget ui-helper-reset" ) | |
1558 .removeAttr( "role" ); | |
1559 | |
1560 // clean up headers | |
1561 this.headers | |
1562 .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" ) | |
1563 .removeAttr( "role" ) | |
1564 .removeAttr( "aria-expanded" ) | |
1565 .removeAttr( "aria-selected" ) | |
1566 .removeAttr( "aria-controls" ) | |
1567 .removeAttr( "tabIndex" ) | |
1568 .each(function() { | |
1569 if ( /^ui-accordion/.test( this.id ) ) { | |
1570 this.removeAttribute( "id" ); | |
1571 } | |
1572 }); | |
1573 this._destroyIcons(); | |
1574 | |
1575 // clean up content panels | |
1576 contents = this.headers.next() | |
1577 .css( "display", "" ) | |
1578 .removeAttr( "role" ) | |
1579 .removeAttr( "aria-hidden" ) | |
1580 .removeAttr( "aria-labelledby" ) | |
1581 .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled" ) | |
1582 .each(function() { | |
1583 if ( /^ui-accordion/.test( this.id ) ) { | |
1584 this.removeAttribute( "id" ); | |
1585 } | |
1586 }); | |
1587 if ( this.options.heightStyle !== "content" ) { | |
1588 contents.css( "height", "" ); | |
1589 } | |
1590 }, | |
1591 | |
1592 _setOption: function( key, value ) { | |
1593 if ( key === "active" ) { | |
1594 // _activate() will handle invalid values and update this.options | |
1595 this._activate( value ); | |
1596 return; | |
1597 } | |
1598 | |
1599 if ( key === "event" ) { | |
1600 if ( this.options.event ) { | |
1601 this._off( this.headers, this.options.event ); | |
1602 } | |
1603 this._setupEvents( value ); | |
1604 } | |
1605 | |
1606 this._super( key, value ); | |
1607 | |
1608 // setting collapsible: false while collapsed; open first panel | |
1609 if ( key === "collapsible" && !value && this.options.active === false ) { | |
1610 this._activate( 0 ); | |
1611 } | |
1612 | |
1613 if ( key === "icons" ) { | |
1614 this._destroyIcons(); | |
1615 if ( value ) { | |
1616 this._createIcons(); | |
1617 } | |
1618 } | |
1619 | |
1620 // #5332 - opacity doesn't cascade to positioned elements in IE | |
1621 // so we need to add the disabled class to the headers and panels | |
1622 if ( key === "disabled" ) { | |
1623 this.headers.add( this.headers.next() ) | |
1624 .toggleClass( "ui-state-disabled", !!value ); | |
1625 } | |
1626 }, | |
1627 | |
1628 _keydown: function( event ) { | |
1629 if ( event.altKey || event.ctrlKey ) { | |
1630 return; | |
1631 } | |
1632 | |
1633 var keyCode = $.ui.keyCode, | |
1634 length = this.headers.length, | |
1635 currentIndex = this.headers.index( event.target ), | |
1636 toFocus = false; | |
1637 | |
1638 switch ( event.keyCode ) { | |
1639 case keyCode.RIGHT: | |
1640 case keyCode.DOWN: | |
1641 toFocus = this.headers[ ( currentIndex + 1 ) % length ]; | |
1642 break; | |
1643 case keyCode.LEFT: | |
1644 case keyCode.UP: | |
1645 toFocus = this.headers[ ( currentIndex - 1 + length ) % length ]; | |
1646 break; | |
1647 case keyCode.SPACE: | |
1648 case keyCode.ENTER: | |
1649 this._eventHandler( event ); | |
1650 break; | |
1651 case keyCode.HOME: | |
1652 toFocus = this.headers[ 0 ]; | |
1653 break; | |
1654 case keyCode.END: | |
1655 toFocus = this.headers[ length - 1 ]; | |
1656 break; | |
1657 } | |
1658 | |
1659 if ( toFocus ) { | |
1660 $( event.target ).attr( "tabIndex", -1 ); | |
1661 $( toFocus ).attr( "tabIndex", 0 ); | |
1662 toFocus.focus(); | |
1663 event.preventDefault(); | |
1664 } | |
1665 }, | |
1666 | |
1667 _panelKeyDown : function( event ) { | |
1668 if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) { | |
1669 $( event.currentTarget ).prev().focus(); | |
1670 } | |
1671 }, | |
1672 | |
1673 refresh: function() { | |
1674 var options = this.options; | |
1675 this._processPanels(); | |
1676 | |
1677 // was collapsed or no panel | |
1678 if ( ( options.active === false && options.collapsible === true ) || !this.headers.length ) { | |
1679 options.active = false; | |
1680 this.active = $(); | |
1681 // active false only when collapsible is true | |
1682 } else if ( options.active === false ) { | |
1683 this._activate( 0 ); | |
1684 // was active, but active panel is gone | |
1685 } else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) { | |
1686 // all remaining panel are disabled | |
1687 if ( this.headers.length === this.headers.find(".ui-state-disabled").length ) { | |
1688 options.active = false; | |
1689 this.active = $(); | |
1690 // activate previous panel | |
1691 } else { | |
1692 this._activate( Math.max( 0, options.active - 1 ) ); | |
1693 } | |
1694 // was active, active panel still exists | |
1695 } else { | |
1696 // make sure active index is correct | |
1697 options.active = this.headers.index( this.active ); | |
1698 } | |
1699 | |
1700 this._destroyIcons(); | |
1701 | |
1702 this._refresh(); | |
1703 }, | |
1704 | |
1705 _processPanels: function() { | |
1706 this.headers = this.element.find( this.options.header ) | |
1707 .addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" ); | |
1708 | |
1709 this.headers.next() | |
1710 .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" ) | |
1711 .filter(":not(.ui-accordion-content-active)") | |
1712 .hide(); | |
1713 }, | |
1714 | |
1715 _refresh: function() { | |
1716 var maxHeight, | |
1717 options = this.options, | |
1718 heightStyle = options.heightStyle, | |
1719 parent = this.element.parent(), | |
1720 accordionId = this.accordionId = "ui-accordion-" + | |
1721 (this.element.attr( "id" ) || ++uid); | |
1722 | |
1723 this.active = this._findActive( options.active ) | |
1724 .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" ) | |
1725 .removeClass( "ui-corner-all" ); | |
1726 this.active.next() | |
1727 .addClass( "ui-accordion-content-active" ) | |
1728 .show(); | |
1729 | |
1730 this.headers | |
1731 .attr( "role", "tab" ) | |
1732 .each(function( i ) { | |
1733 var header = $( this ), | |
1734 headerId = header.attr( "id" ), | |
1735 panel = header.next(), | |
1736 panelId = panel.attr( "id" ); | |
1737 if ( !headerId ) { | |
1738 headerId = accordionId + "-header-" + i; | |
1739 header.attr( "id", headerId ); | |
1740 } | |
1741 if ( !panelId ) { | |
1742 panelId = accordionId + "-panel-" + i; | |
1743 panel.attr( "id", panelId ); | |
1744 } | |
1745 header.attr( "aria-controls", panelId ); | |
1746 panel.attr( "aria-labelledby", headerId ); | |
1747 }) | |
1748 .next() | |
1749 .attr( "role", "tabpanel" ); | |
1750 | |
1751 this.headers | |
1752 .not( this.active ) | |
1753 .attr({ | |
1754 "aria-selected": "false", | |
1755 "aria-expanded": "false", | |
1756 tabIndex: -1 | |
1757 }) | |
1758 .next() | |
1759 .attr({ | |
1760 "aria-hidden": "true" | |
1761 }) | |
1762 .hide(); | |
1763 | |
1764 // make sure at least one header is in the tab order | |
1765 if ( !this.active.length ) { | |
1766 this.headers.eq( 0 ).attr( "tabIndex", 0 ); | |
1767 } else { | |
1768 this.active.attr({ | |
1769 "aria-selected": "true", | |
1770 "aria-expanded": "true", | |
1771 tabIndex: 0 | |
1772 }) | |
1773 .next() | |
1774 .attr({ | |
1775 "aria-hidden": "false" | |
1776 }); | |
1777 } | |
1778 | |
1779 this._createIcons(); | |
1780 | |
1781 this._setupEvents( options.event ); | |
1782 | |
1783 if ( heightStyle === "fill" ) { | |
1784 maxHeight = parent.height(); | |
1785 this.element.siblings( ":visible" ).each(function() { | |
1786 var elem = $( this ), | |
1787 position = elem.css( "position" ); | |
1788 | |
1789 if ( position === "absolute" || position === "fixed" ) { | |
1790 return; | |
1791 } | |
1792 maxHeight -= elem.outerHeight( true ); | |
1793 }); | |
1794 | |
1795 this.headers.each(function() { | |
1796 maxHeight -= $( this ).outerHeight( true ); | |
1797 }); | |
1798 | |
1799 this.headers.next() | |
1800 .each(function() { | |
1801 $( this ).height( Math.max( 0, maxHeight - | |
1802 $( this ).innerHeight() + $( this ).height() ) ); | |
1803 }) | |
1804 .css( "overflow", "auto" ); | |
1805 } else if ( heightStyle === "auto" ) { | |
1806 maxHeight = 0; | |
1807 this.headers.next() | |
1808 .each(function() { | |
1809 maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() ); | |
1810 }) | |
1811 .height( maxHeight ); | |
1812 } | |
1813 }, | |
1814 | |
1815 _activate: function( index ) { | |
1816 var active = this._findActive( index )[ 0 ]; | |
1817 | |
1818 // trying to activate the already active panel | |
1819 if ( active === this.active[ 0 ] ) { | |
1820 return; | |
1821 } | |
1822 | |
1823 // trying to collapse, simulate a click on the currently active header | |
1824 active = active || this.active[ 0 ]; | |
1825 | |
1826 this._eventHandler({ | |
1827 target: active, | |
1828 currentTarget: active, | |
1829 preventDefault: $.noop | |
1830 }); | |
1831 }, | |
1832 | |
1833 _findActive: function( selector ) { | |
1834 return typeof selector === "number" ? this.headers.eq( selector ) : $(); | |
1835 }, | |
1836 | |
1837 _setupEvents: function( event ) { | |
1838 var events = { | |
1839 keydown: "_keydown" | |
1840 }; | |
1841 if ( event ) { | |
1842 $.each( event.split(" "), function( index, eventName ) { | |
1843 events[ eventName ] = "_eventHandler"; | |
1844 }); | |
1845 } | |
1846 | |
1847 this._off( this.headers.add( this.headers.next() ) ); | |
1848 this._on( this.headers, events ); | |
1849 this._on( this.headers.next(), { keydown: "_panelKeyDown" }); | |
1850 this._hoverable( this.headers ); | |
1851 this._focusable( this.headers ); | |
1852 }, | |
1853 | |
1854 _eventHandler: function( event ) { | |
1855 var options = this.options, | |
1856 active = this.active, | |
1857 clicked = $( event.currentTarget ), | |
1858 clickedIsActive = clicked[ 0 ] === active[ 0 ], | |
1859 collapsing = clickedIsActive && options.collapsible, | |
1860 toShow = collapsing ? $() : clicked.next(), | |
1861 toHide = active.next(), | |
1862 eventData = { | |
1863 oldHeader: active, | |
1864 oldPanel: toHide, | |
1865 newHeader: collapsing ? $() : clicked, | |
1866 newPanel: toShow | |
1867 }; | |
1868 | |
1869 event.preventDefault(); | |
1870 | |
1871 if ( | |
1872 // click on active header, but not collapsible | |
1873 ( clickedIsActive && !options.collapsible ) || | |
1874 // allow canceling activation | |
1875 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { | |
1876 return; | |
1877 } | |
1878 | |
1879 options.active = collapsing ? false : this.headers.index( clicked ); | |
1880 | |
1881 // when the call to ._toggle() comes after the class changes | |
1882 // it causes a very odd bug in IE 8 (see #6720) | |
1883 this.active = clickedIsActive ? $() : clicked; | |
1884 this._toggle( eventData ); | |
1885 | |
1886 // switch classes | |
1887 // corner classes on the previously active header stay after the animation | |
1888 active.removeClass( "ui-accordion-header-active ui-state-active" ); | |
1889 if ( options.icons ) { | |
1890 active.children( ".ui-accordion-header-icon" ) | |
1891 .removeClass( options.icons.activeHeader ) | |
1892 .addClass( options.icons.header ); | |
1893 } | |
1894 | |
1895 if ( !clickedIsActive ) { | |
1896 clicked | |
1897 .removeClass( "ui-corner-all" ) | |
1898 .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" ); | |
1899 if ( options.icons ) { | |
1900 clicked.children( ".ui-accordion-header-icon" ) | |
1901 .removeClass( options.icons.header ) | |
1902 .addClass( options.icons.activeHeader ); | |
1903 } | |
1904 | |
1905 clicked | |
1906 .next() | |
1907 .addClass( "ui-accordion-content-active" ); | |
1908 } | |
1909 }, | |
1910 | |
1911 _toggle: function( data ) { | |
1912 var toShow = data.newPanel, | |
1913 toHide = this.prevShow.length ? this.prevShow : data.oldPanel; | |
1914 | |
1915 // handle activating a panel during the animation for another activation | |
1916 this.prevShow.add( this.prevHide ).stop( true, true ); | |
1917 this.prevShow = toShow; | |
1918 this.prevHide = toHide; | |
1919 | |
1920 if ( this.options.animate ) { | |
1921 this._animate( toShow, toHide, data ); | |
1922 } else { | |
1923 toHide.hide(); | |
1924 toShow.show(); | |
1925 this._toggleComplete( data ); | |
1926 } | |
1927 | |
1928 toHide.attr({ | |
1929 "aria-hidden": "true" | |
1930 }); | |
1931 toHide.prev().attr( "aria-selected", "false" ); | |
1932 // if we're switching panels, remove the old header from the tab order | |
1933 // if we're opening from collapsed state, remove the previous header from the tab order | |
1934 // if we're collapsing, then keep the collapsing header in the tab order | |
1935 if ( toShow.length && toHide.length ) { | |
1936 toHide.prev().attr({ | |
1937 "tabIndex": -1, | |
1938 "aria-expanded": "false" | |
1939 }); | |
1940 } else if ( toShow.length ) { | |
1941 this.headers.filter(function() { | |
1942 return $( this ).attr( "tabIndex" ) === 0; | |
1943 }) | |
1944 .attr( "tabIndex", -1 ); | |
1945 } | |
1946 | |
1947 toShow | |
1948 .attr( "aria-hidden", "false" ) | |
1949 .prev() | |
1950 .attr({ | |
1951 "aria-selected": "true", | |
1952 tabIndex: 0, | |
1953 "aria-expanded": "true" | |
1954 }); | |
1955 }, | |
1956 | |
1957 _animate: function( toShow, toHide, data ) { | |
1958 var total, easing, duration, | |
1959 that = this, | |
1960 adjust = 0, | |
1961 down = toShow.length && | |
1962 ( !toHide.length || ( toShow.index() < toHide.index() ) ), | |
1963 animate = this.options.animate || {}, | |
1964 options = down && animate.down || animate, | |
1965 complete = function() { | |
1966 that._toggleComplete( data ); | |
1967 }; | |
1968 | |
1969 if ( typeof options === "number" ) { | |
1970 duration = options; | |
1971 } | |
1972 if ( typeof options === "string" ) { | |
1973 easing = options; | |
1974 } | |
1975 // fall back from options to animation in case of partial down settings | |
1976 easing = easing || options.easing || animate.easing; | |
1977 duration = duration || options.duration || animate.duration; | |
1978 | |
1979 if ( !toHide.length ) { | |
1980 return toShow.animate( showProps, duration, easing, complete ); | |
1981 } | |
1982 if ( !toShow.length ) { | |
1983 return toHide.animate( hideProps, duration, easing, complete ); | |
1984 } | |
1985 | |
1986 total = toShow.show().outerHeight(); | |
1987 toHide.animate( hideProps, { | |
1988 duration: duration, | |
1989 easing: easing, | |
1990 step: function( now, fx ) { | |
1991 fx.now = Math.round( now ); | |
1992 } | |
1993 }); | |
1994 toShow | |
1995 .hide() | |
1996 .animate( showProps, { | |
1997 duration: duration, | |
1998 easing: easing, | |
1999 complete: complete, | |
2000 step: function( now, fx ) { | |
2001 fx.now = Math.round( now ); | |
2002 if ( fx.prop !== "height" ) { | |
2003 adjust += fx.now; | |
2004 } else if ( that.options.heightStyle !== "content" ) { | |
2005 fx.now = Math.round( total - toHide.outerHeight() - adjust ); | |
2006 adjust = 0; | |
2007 } | |
2008 } | |
2009 }); | |
2010 }, | |
2011 | |
2012 _toggleComplete: function( data ) { | |
2013 var toHide = data.oldPanel; | |
2014 | |
2015 toHide | |
2016 .removeClass( "ui-accordion-content-active" ) | |
2017 .prev() | |
2018 .removeClass( "ui-corner-top" ) | |
2019 .addClass( "ui-corner-all" ); | |
2020 | |
2021 // Work around for rendering bug in IE (#5421) | |
2022 if ( toHide.length ) { | |
2023 toHide.parent()[0].className = toHide.parent()[0].className; | |
2024 } | |
2025 this._trigger( "activate", null, data ); | |
2026 } | |
2027 }); | |
2028 | |
2029 })( jQuery ); | |
2030 (function( $, undefined ) { | |
2031 | |
2032 $.widget( "ui.autocomplete", { | |
2033 version: "1.10.4", | |
2034 defaultElement: "<input>", | |
2035 options: { | |
2036 appendTo: null, | |
2037 autoFocus: false, | |
2038 delay: 300, | |
2039 minLength: 1, | |
2040 position: { | |
2041 my: "left top", | |
2042 at: "left bottom", | |
2043 collision: "none" | |
2044 }, | |
2045 source: null, | |
2046 | |
2047 // callbacks | |
2048 change: null, | |
2049 close: null, | |
2050 focus: null, | |
2051 open: null, | |
2052 response: null, | |
2053 search: null, | |
2054 select: null | |
2055 }, | |
2056 | |
2057 requestIndex: 0, | |
2058 pending: 0, | |
2059 | |
2060 _create: function() { | |
2061 // Some browsers only repeat keydown events, not keypress events, | |
2062 // so we use the suppressKeyPress flag to determine if we've already | |
2063 // handled the keydown event. #7269 | |
2064 // Unfortunately the code for & in keypress is the same as the up arrow, | |
2065 // so we use the suppressKeyPressRepeat flag to avoid handling keypress | |
2066 // events when we know the keydown event was used to modify the | |
2067 // search term. #7799 | |
2068 var suppressKeyPress, suppressKeyPressRepeat, suppressInput, | |
2069 nodeName = this.element[0].nodeName.toLowerCase(), | |
2070 isTextarea = nodeName === "textarea", | |
2071 isInput = nodeName === "input"; | |
2072 | |
2073 this.isMultiLine = | |
2074 // Textareas are always multi-line | |
2075 isTextarea ? true : | |
2076 // Inputs are always single-line, even if inside a contentEditable element | |
2077 // IE also treats inputs as contentEditable | |
2078 isInput ? false : | |
2079 // All other element types are determined by whether or not they're contentEditable | |
2080 this.element.prop( "isContentEditable" ); | |
2081 | |
2082 this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ]; | |
2083 this.isNewMenu = true; | |
2084 | |
2085 this.element | |
2086 .addClass( "ui-autocomplete-input" ) | |
2087 .attr( "autocomplete", "off" ); | |
2088 | |
2089 this._on( this.element, { | |
2090 keydown: function( event ) { | |
2091 if ( this.element.prop( "readOnly" ) ) { | |
2092 suppressKeyPress = true; | |
2093 suppressInput = true; | |
2094 suppressKeyPressRepeat = true; | |
2095 return; | |
2096 } | |
2097 | |
2098 suppressKeyPress = false; | |
2099 suppressInput = false; | |
2100 suppressKeyPressRepeat = false; | |
2101 var keyCode = $.ui.keyCode; | |
2102 switch( event.keyCode ) { | |
2103 case keyCode.PAGE_UP: | |
2104 suppressKeyPress = true; | |
2105 this._move( "previousPage", event ); | |
2106 break; | |
2107 case keyCode.PAGE_DOWN: | |
2108 suppressKeyPress = true; | |
2109 this._move( "nextPage", event ); | |
2110 break; | |
2111 case keyCode.UP: | |
2112 suppressKeyPress = true; | |
2113 this._keyEvent( "previous", event ); | |
2114 break; | |
2115 case keyCode.DOWN: | |
2116 suppressKeyPress = true; | |
2117 this._keyEvent( "next", event ); | |
2118 break; | |
2119 case keyCode.ENTER: | |
2120 case keyCode.NUMPAD_ENTER: | |
2121 // when menu is open and has focus | |
2122 if ( this.menu.active ) { | |
2123 // #6055 - Opera still allows the keypress to occur | |
2124 // which causes forms to submit | |
2125 suppressKeyPress = true; | |
2126 event.preventDefault(); | |
2127 this.menu.select( event ); | |
2128 } | |
2129 break; | |
2130 case keyCode.TAB: | |
2131 if ( this.menu.active ) { | |
2132 this.menu.select( event ); | |
2133 } | |
2134 break; | |
2135 case keyCode.ESCAPE: | |
2136 if ( this.menu.element.is( ":visible" ) ) { | |
2137 this._value( this.term ); | |
2138 this.close( event ); | |
2139 // Different browsers have different default behavior for escape | |
2140 // Single press can mean undo or clear | |
2141 // Double press in IE means clear the whole form | |
2142 event.preventDefault(); | |
2143 } | |
2144 break; | |
2145 default: | |
2146 suppressKeyPressRepeat = true; | |
2147 // search timeout should be triggered before the input value is changed | |
2148 this._searchTimeout( event ); | |
2149 break; | |
2150 } | |
2151 }, | |
2152 keypress: function( event ) { | |
2153 if ( suppressKeyPress ) { | |
2154 suppressKeyPress = false; | |
2155 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) { | |
2156 event.preventDefault(); | |
2157 } | |
2158 return; | |
2159 } | |
2160 if ( suppressKeyPressRepeat ) { | |
2161 return; | |
2162 } | |
2163 | |
2164 // replicate some key handlers to allow them to repeat in Firefox and Opera | |
2165 var keyCode = $.ui.keyCode; | |
2166 switch( event.keyCode ) { | |
2167 case keyCode.PAGE_UP: | |
2168 this._move( "previousPage", event ); | |
2169 break; | |
2170 case keyCode.PAGE_DOWN: | |
2171 this._move( "nextPage", event ); | |
2172 break; | |
2173 case keyCode.UP: | |
2174 this._keyEvent( "previous", event ); | |
2175 break; | |
2176 case keyCode.DOWN: | |
2177 this._keyEvent( "next", event ); | |
2178 break; | |
2179 } | |
2180 }, | |
2181 input: function( event ) { | |
2182 if ( suppressInput ) { | |
2183 suppressInput = false; | |
2184 event.preventDefault(); | |
2185 return; | |
2186 } | |
2187 this._searchTimeout( event ); | |
2188 }, | |
2189 focus: function() { | |
2190 this.selectedItem = null; | |
2191 this.previous = this._value(); | |
2192 }, | |
2193 blur: function( event ) { | |
2194 if ( this.cancelBlur ) { | |
2195 delete this.cancelBlur; | |
2196 return; | |
2197 } | |
2198 | |
2199 clearTimeout( this.searching ); | |
2200 this.close( event ); | |
2201 this._change( event ); | |
2202 } | |
2203 }); | |
2204 | |
2205 this._initSource(); | |
2206 this.menu = $( "<ul>" ) | |
2207 .addClass( "ui-autocomplete ui-front" ) | |
2208 .appendTo( this._appendTo() ) | |
2209 .menu({ | |
2210 // disable ARIA support, the live region takes care of that | |
2211 role: null | |
2212 }) | |
2213 .hide() | |
2214 .data( "ui-menu" ); | |
2215 | |
2216 this._on( this.menu.element, { | |
2217 mousedown: function( event ) { | |
2218 // prevent moving focus out of the text field | |
2219 event.preventDefault(); | |
2220 | |
2221 // IE doesn't prevent moving focus even with event.preventDefault() | |
2222 // so we set a flag to know when we should ignore the blur event | |
2223 this.cancelBlur = true; | |
2224 this._delay(function() { | |
2225 delete this.cancelBlur; | |
2226 }); | |
2227 | |
2228 // clicking on the scrollbar causes focus to shift to the body | |
2229 // but we can't detect a mouseup or a click immediately afterward | |
2230 // so we have to track the next mousedown and close the menu if | |
2231 // the user clicks somewhere outside of the autocomplete | |
2232 var menuElement = this.menu.element[ 0 ]; | |
2233 if ( !$( event.target ).closest( ".ui-menu-item" ).length ) { | |
2234 this._delay(function() { | |
2235 var that = this; | |
2236 this.document.one( "mousedown", function( event ) { | |
2237 if ( event.target !== that.element[ 0 ] && | |
2238 event.target !== menuElement && | |
2239 !$.contains( menuElement, event.target ) ) { | |
2240 that.close(); | |
2241 } | |
2242 }); | |
2243 }); | |
2244 } | |
2245 }, | |
2246 menufocus: function( event, ui ) { | |
2247 // support: Firefox | |
2248 // Prevent accidental activation of menu items in Firefox (#7024 #9118) | |
2249 if ( this.isNewMenu ) { | |
2250 this.isNewMenu = false; | |
2251 if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) { | |
2252 this.menu.blur(); | |
2253 | |
2254 this.document.one( "mousemove", function() { | |
2255 $( event.target ).trigger( event.originalEvent ); | |
2256 }); | |
2257 | |
2258 return; | |
2259 } | |
2260 } | |
2261 | |
2262 var item = ui.item.data( "ui-autocomplete-item" ); | |
2263 if ( false !== this._trigger( "focus", event, { item: item } ) ) { | |
2264 // use value to match what will end up in the input, if it was a key event | |
2265 if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) { | |
2266 this._value( item.value ); | |
2267 } | |
2268 } else { | |
2269 // Normally the input is populated with the item's value as the | |
2270 // menu is navigated, causing screen readers to notice a change and | |
2271 // announce the item. Since the focus event was canceled, this doesn't | |
2272 // happen, so we update the live region so that screen readers can | |
2273 // still notice the change and announce it. | |
2274 this.liveRegion.text( item.value ); | |
2275 } | |
2276 }, | |
2277 menuselect: function( event, ui ) { | |
2278 var item = ui.item.data( "ui-autocomplete-item" ), | |
2279 previous = this.previous; | |
2280 | |
2281 // only trigger when focus was lost (click on menu) | |
2282 if ( this.element[0] !== this.document[0].activeElement ) { | |
2283 this.element.focus(); | |
2284 this.previous = previous; | |
2285 // #6109 - IE triggers two focus events and the second | |
2286 // is asynchronous, so we need to reset the previous | |
2287 // term synchronously and asynchronously :-( | |
2288 this._delay(function() { | |
2289 this.previous = previous; | |
2290 this.selectedItem = item; | |
2291 }); | |
2292 } | |
2293 | |
2294 if ( false !== this._trigger( "select", event, { item: item } ) ) { | |
2295 this._value( item.value ); | |
2296 } | |
2297 // reset the term after the select event | |
2298 // this allows custom select handling to work properly | |
2299 this.term = this._value(); | |
2300 | |
2301 this.close( event ); | |
2302 this.selectedItem = item; | |
2303 } | |
2304 }); | |
2305 | |
2306 this.liveRegion = $( "<span>", { | |
2307 role: "status", | |
2308 "aria-live": "polite" | |
2309 }) | |
2310 .addClass( "ui-helper-hidden-accessible" ) | |
2311 .insertBefore( this.element ); | |
2312 | |
2313 // turning off autocomplete prevents the browser from remembering the | |
2314 // value when navigating through history, so we re-enable autocomplete | |
2315 // if the page is unloaded before the widget is destroyed. #7790 | |
2316 this._on( this.window, { | |
2317 beforeunload: function() { | |
2318 this.element.removeAttr( "autocomplete" ); | |
2319 } | |
2320 }); | |
2321 }, | |
2322 | |
2323 _destroy: function() { | |
2324 clearTimeout( this.searching ); | |
2325 this.element | |
2326 .removeClass( "ui-autocomplete-input" ) | |
2327 .removeAttr( "autocomplete" ); | |
2328 this.menu.element.remove(); | |
2329 this.liveRegion.remove(); | |
2330 }, | |
2331 | |
2332 _setOption: function( key, value ) { | |
2333 this._super( key, value ); | |
2334 if ( key === "source" ) { | |
2335 this._initSource(); | |
2336 } | |
2337 if ( key === "appendTo" ) { | |
2338 this.menu.element.appendTo( this._appendTo() ); | |
2339 } | |
2340 if ( key === "disabled" && value && this.xhr ) { | |
2341 this.xhr.abort(); | |
2342 } | |
2343 }, | |
2344 | |
2345 _appendTo: function() { | |
2346 var element = this.options.appendTo; | |
2347 | |
2348 if ( element ) { | |
2349 element = element.jquery || element.nodeType ? | |
2350 $( element ) : | |
2351 this.document.find( element ).eq( 0 ); | |
2352 } | |
2353 | |
2354 if ( !element ) { | |
2355 element = this.element.closest( ".ui-front" ); | |
2356 } | |
2357 | |
2358 if ( !element.length ) { | |
2359 element = this.document[0].body; | |
2360 } | |
2361 | |
2362 return element; | |
2363 }, | |
2364 | |
2365 _initSource: function() { | |
2366 var array, url, | |
2367 that = this; | |
2368 if ( $.isArray(this.options.source) ) { | |
2369 array = this.options.source; | |
2370 this.source = function( request, response ) { | |
2371 response( $.ui.autocomplete.filter( array, request.term ) ); | |
2372 }; | |
2373 } else if ( typeof this.options.source === "string" ) { | |
2374 url = this.options.source; | |
2375 this.source = function( request, response ) { | |
2376 if ( that.xhr ) { | |
2377 that.xhr.abort(); | |
2378 } | |
2379 that.xhr = $.ajax({ | |
2380 url: url, | |
2381 data: request, | |
2382 dataType: "json", | |
2383 success: function( data ) { | |
2384 response( data ); | |
2385 }, | |
2386 error: function() { | |
2387 response( [] ); | |
2388 } | |
2389 }); | |
2390 }; | |
2391 } else { | |
2392 this.source = this.options.source; | |
2393 } | |
2394 }, | |
2395 | |
2396 _searchTimeout: function( event ) { | |
2397 clearTimeout( this.searching ); | |
2398 this.searching = this._delay(function() { | |
2399 // only search if the value has changed | |
2400 if ( this.term !== this._value() ) { | |
2401 this.selectedItem = null; | |
2402 this.search( null, event ); | |
2403 } | |
2404 }, this.options.delay ); | |
2405 }, | |
2406 | |
2407 search: function( value, event ) { | |
2408 value = value != null ? value : this._value(); | |
2409 | |
2410 // always save the actual value, not the one passed as an argument | |
2411 this.term = this._value(); | |
2412 | |
2413 if ( value.length < this.options.minLength ) { | |
2414 return this.close( event ); | |
2415 } | |
2416 | |
2417 if ( this._trigger( "search", event ) === false ) { | |
2418 return; | |
2419 } | |
2420 | |
2421 return this._search( value ); | |
2422 }, | |
2423 | |
2424 _search: function( value ) { | |
2425 this.pending++; | |
2426 this.element.addClass( "ui-autocomplete-loading" ); | |
2427 this.cancelSearch = false; | |
2428 | |
2429 this.source( { term: value }, this._response() ); | |
2430 }, | |
2431 | |
2432 _response: function() { | |
2433 var index = ++this.requestIndex; | |
2434 | |
2435 return $.proxy(function( content ) { | |
2436 if ( index === this.requestIndex ) { | |
2437 this.__response( content ); | |
2438 } | |
2439 | |
2440 this.pending--; | |
2441 if ( !this.pending ) { | |
2442 this.element.removeClass( "ui-autocomplete-loading" ); | |
2443 } | |
2444 }, this ); | |
2445 }, | |
2446 | |
2447 __response: function( content ) { | |
2448 if ( content ) { | |
2449 content = this._normalize( content ); | |
2450 } | |
2451 this._trigger( "response", null, { content: content } ); | |
2452 if ( !this.options.disabled && content && content.length && !this.cancelSearch ) { | |
2453 this._suggest( content ); | |
2454 this._trigger( "open" ); | |
2455 } else { | |
2456 // use ._close() instead of .close() so we don't cancel future searches | |
2457 this._close(); | |
2458 } | |
2459 }, | |
2460 | |
2461 close: function( event ) { | |
2462 this.cancelSearch = true; | |
2463 this._close( event ); | |
2464 }, | |
2465 | |
2466 _close: function( event ) { | |
2467 if ( this.menu.element.is( ":visible" ) ) { | |
2468 this.menu.element.hide(); | |
2469 this.menu.blur(); | |
2470 this.isNewMenu = true; | |
2471 this._trigger( "close", event ); | |
2472 } | |
2473 }, | |
2474 | |
2475 _change: function( event ) { | |
2476 if ( this.previous !== this._value() ) { | |
2477 this._trigger( "change", event, { item: this.selectedItem } ); | |
2478 } | |
2479 }, | |
2480 | |
2481 _normalize: function( items ) { | |
2482 // assume all items have the right format when the first item is complete | |
2483 if ( items.length && items[0].label && items[0].value ) { | |
2484 return items; | |
2485 } | |
2486 return $.map( items, function( item ) { | |
2487 if ( typeof item === "string" ) { | |
2488 return { | |
2489 label: item, | |
2490 value: item | |
2491 }; | |
2492 } | |
2493 return $.extend({ | |
2494 label: item.label || item.value, | |
2495 value: item.value || item.label | |
2496 }, item ); | |
2497 }); | |
2498 }, | |
2499 | |
2500 _suggest: function( items ) { | |
2501 var ul = this.menu.element.empty(); | |
2502 this._renderMenu( ul, items ); | |
2503 this.isNewMenu = true; | |
2504 this.menu.refresh(); | |
2505 | |
2506 // size and position menu | |
2507 ul.show(); | |
2508 this._resizeMenu(); | |
2509 ul.position( $.extend({ | |
2510 of: this.element | |
2511 }, this.options.position )); | |
2512 | |
2513 if ( this.options.autoFocus ) { | |
2514 this.menu.next(); | |
2515 } | |
2516 }, | |
2517 | |
2518 _resizeMenu: function() { | |
2519 var ul = this.menu.element; | |
2520 ul.outerWidth( Math.max( | |
2521 // Firefox wraps long text (possibly a rounding bug) | |
2522 // so we add 1px to avoid the wrapping (#7513) | |
2523 ul.width( "" ).outerWidth() + 1, | |
2524 this.element.outerWidth() | |
2525 ) ); | |
2526 }, | |
2527 | |
2528 _renderMenu: function( ul, items ) { | |
2529 var that = this; | |
2530 $.each( items, function( index, item ) { | |
2531 that._renderItemData( ul, item ); | |
2532 }); | |
2533 }, | |
2534 | |
2535 _renderItemData: function( ul, item ) { | |
2536 return this._renderItem( ul, item ).data( "ui-autocomplete-item", item ); | |
2537 }, | |
2538 | |
2539 _renderItem: function( ul, item ) { | |
2540 return $( "<li>" ) | |
2541 .append( $( "<a>" ).text( item.label ) ) | |
2542 .appendTo( ul ); | |
2543 }, | |
2544 | |
2545 _move: function( direction, event ) { | |
2546 if ( !this.menu.element.is( ":visible" ) ) { | |
2547 this.search( null, event ); | |
2548 return; | |
2549 } | |
2550 if ( this.menu.isFirstItem() && /^previous/.test( direction ) || | |
2551 this.menu.isLastItem() && /^next/.test( direction ) ) { | |
2552 this._value( this.term ); | |
2553 this.menu.blur(); | |
2554 return; | |
2555 } | |
2556 this.menu[ direction ]( event ); | |
2557 }, | |
2558 | |
2559 widget: function() { | |
2560 return this.menu.element; | |
2561 }, | |
2562 | |
2563 _value: function() { | |
2564 return this.valueMethod.apply( this.element, arguments ); | |
2565 }, | |
2566 | |
2567 _keyEvent: function( keyEvent, event ) { | |
2568 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) { | |
2569 this._move( keyEvent, event ); | |
2570 | |
2571 // prevents moving cursor to beginning/end of the text field in some browsers | |
2572 event.preventDefault(); | |
2573 } | |
2574 } | |
2575 }); | |
2576 | |
2577 $.extend( $.ui.autocomplete, { | |
2578 escapeRegex: function( value ) { | |
2579 return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&"); | |
2580 }, | |
2581 filter: function(array, term) { | |
2582 var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" ); | |
2583 return $.grep( array, function(value) { | |
2584 return matcher.test( value.label || value.value || value ); | |
2585 }); | |
2586 } | |
2587 }); | |
2588 | |
2589 | |
2590 // live region extension, adding a `messages` option | |
2591 // NOTE: This is an experimental API. We are still investigating | |
2592 // a full solution for string manipulation and internationalization. | |
2593 $.widget( "ui.autocomplete", $.ui.autocomplete, { | |
2594 options: { | |
2595 messages: { | |
2596 noResults: "No search results.", | |
2597 results: function( amount ) { | |
2598 return amount + ( amount > 1 ? " results are" : " result is" ) + | |
2599 " available, use up and down arrow keys to navigate."; | |
2600 } | |
2601 } | |
2602 }, | |
2603 | |
2604 __response: function( content ) { | |
2605 var message; | |
2606 this._superApply( arguments ); | |
2607 if ( this.options.disabled || this.cancelSearch ) { | |
2608 return; | |
2609 } | |
2610 if ( content && content.length ) { | |
2611 message = this.options.messages.results( content.length ); | |
2612 } else { | |
2613 message = this.options.messages.noResults; | |
2614 } | |
2615 this.liveRegion.text( message ); | |
2616 } | |
2617 }); | |
2618 | |
2619 }( jQuery )); | |
2620 (function( $, undefined ) { | |
2621 | |
2622 var lastActive, | |
2623 baseClasses = "ui-button ui-widget ui-state-default ui-corner-all", | |
2624 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", | |
2625 formResetHandler = function() { | |
2626 var form = $( this ); | |
2627 setTimeout(function() { | |
2628 form.find( ":ui-button" ).button( "refresh" ); | |
2629 }, 1 ); | |
2630 }, | |
2631 radioGroup = function( radio ) { | |
2632 var name = radio.name, | |
2633 form = radio.form, | |
2634 radios = $( [] ); | |
2635 if ( name ) { | |
2636 name = name.replace( /'/g, "\\'" ); | |
2637 if ( form ) { | |
2638 radios = $( form ).find( "[name='" + name + "']" ); | |
2639 } else { | |
2640 radios = $( "[name='" + name + "']", radio.ownerDocument ) | |
2641 .filter(function() { | |
2642 return !this.form; | |
2643 }); | |
2644 } | |
2645 } | |
2646 return radios; | |
2647 }; | |
2648 | |
2649 $.widget( "ui.button", { | |
2650 version: "1.10.4", | |
2651 defaultElement: "<button>", | |
2652 options: { | |
2653 disabled: null, | |
2654 text: true, | |
2655 label: null, | |
2656 icons: { | |
2657 primary: null, | |
2658 secondary: null | |
2659 } | |
2660 }, | |
2661 _create: function() { | |
2662 this.element.closest( "form" ) | |
2663 .unbind( "reset" + this.eventNamespace ) | |
2664 .bind( "reset" + this.eventNamespace, formResetHandler ); | |
2665 | |
2666 if ( typeof this.options.disabled !== "boolean" ) { | |
2667 this.options.disabled = !!this.element.prop( "disabled" ); | |
2668 } else { | |
2669 this.element.prop( "disabled", this.options.disabled ); | |
2670 } | |
2671 | |
2672 this._determineButtonType(); | |
2673 this.hasTitle = !!this.buttonElement.attr( "title" ); | |
2674 | |
2675 var that = this, | |
2676 options = this.options, | |
2677 toggleButton = this.type === "checkbox" || this.type === "radio", | |
2678 activeClass = !toggleButton ? "ui-state-active" : ""; | |
2679 | |
2680 if ( options.label === null ) { | |
2681 options.label = (this.type === "input" ? this.buttonElement.val() : this.buttonElement.html()); | |
2682 } | |
2683 | |
2684 this._hoverable( this.buttonElement ); | |
2685 | |
2686 this.buttonElement | |
2687 .addClass( baseClasses ) | |
2688 .attr( "role", "button" ) | |
2689 .bind( "mouseenter" + this.eventNamespace, function() { | |
2690 if ( options.disabled ) { | |
2691 return; | |
2692 } | |
2693 if ( this === lastActive ) { | |
2694 $( this ).addClass( "ui-state-active" ); | |
2695 } | |
2696 }) | |
2697 .bind( "mouseleave" + this.eventNamespace, function() { | |
2698 if ( options.disabled ) { | |
2699 return; | |
2700 } | |
2701 $( this ).removeClass( activeClass ); | |
2702 }) | |
2703 .bind( "click" + this.eventNamespace, function( event ) { | |
2704 if ( options.disabled ) { | |
2705 event.preventDefault(); | |
2706 event.stopImmediatePropagation(); | |
2707 } | |
2708 }); | |
2709 | |
2710 // Can't use _focusable() because the element that receives focus | |
2711 // and the element that gets the ui-state-focus class are different | |
2712 this._on({ | |
2713 focus: function() { | |
2714 this.buttonElement.addClass( "ui-state-focus" ); | |
2715 }, | |
2716 blur: function() { | |
2717 this.buttonElement.removeClass( "ui-state-focus" ); | |
2718 } | |
2719 }); | |
2720 | |
2721 if ( toggleButton ) { | |
2722 this.element.bind( "change" + this.eventNamespace, function() { | |
2723 that.refresh(); | |
2724 }); | |
2725 } | |
2726 | |
2727 if ( this.type === "checkbox" ) { | |
2728 this.buttonElement.bind( "click" + this.eventNamespace, function() { | |
2729 if ( options.disabled ) { | |
2730 return false; | |
2731 } | |
2732 }); | |
2733 } else if ( this.type === "radio" ) { | |
2734 this.buttonElement.bind( "click" + this.eventNamespace, function() { | |
2735 if ( options.disabled ) { | |
2736 return false; | |
2737 } | |
2738 $( this ).addClass( "ui-state-active" ); | |
2739 that.buttonElement.attr( "aria-pressed", "true" ); | |
2740 | |
2741 var radio = that.element[ 0 ]; | |
2742 radioGroup( radio ) | |
2743 .not( radio ) | |
2744 .map(function() { | |
2745 return $( this ).button( "widget" )[ 0 ]; | |
2746 }) | |
2747 .removeClass( "ui-state-active" ) | |
2748 .attr( "aria-pressed", "false" ); | |
2749 }); | |
2750 } else { | |
2751 this.buttonElement | |
2752 .bind( "mousedown" + this.eventNamespace, function() { | |
2753 if ( options.disabled ) { | |
2754 return false; | |
2755 } | |
2756 $( this ).addClass( "ui-state-active" ); | |
2757 lastActive = this; | |
2758 that.document.one( "mouseup", function() { | |
2759 lastActive = null; | |
2760 }); | |
2761 }) | |
2762 .bind( "mouseup" + this.eventNamespace, function() { | |
2763 if ( options.disabled ) { | |
2764 return false; | |
2765 } | |
2766 $( this ).removeClass( "ui-state-active" ); | |
2767 }) | |
2768 .bind( "keydown" + this.eventNamespace, function(event) { | |
2769 if ( options.disabled ) { | |
2770 return false; | |
2771 } | |
2772 if ( event.keyCode === $.ui.keyCode.SPACE || event.keyCode === $.ui.keyCode.ENTER ) { | |
2773 $( this ).addClass( "ui-state-active" ); | |
2774 } | |
2775 }) | |
2776 // see #8559, we bind to blur here in case the button element loses | |
2777 // focus between keydown and keyup, it would be left in an "active" state | |
2778 .bind( "keyup" + this.eventNamespace + " blur" + this.eventNamespace, function() { | |
2779 $( this ).removeClass( "ui-state-active" ); | |
2780 }); | |
2781 | |
2782 if ( this.buttonElement.is("a") ) { | |
2783 this.buttonElement.keyup(function(event) { | |
2784 if ( event.keyCode === $.ui.keyCode.SPACE ) { | |
2785 // TODO pass through original event correctly (just as 2nd argument doesn't work) | |
2786 $( this ).click(); | |
2787 } | |
2788 }); | |
2789 } | |
2790 } | |
2791 | |
2792 // TODO: pull out $.Widget's handling for the disabled option into | |
2793 // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can | |
2794 // be overridden by individual plugins | |
2795 this._setOption( "disabled", options.disabled ); | |
2796 this._resetButton(); | |
2797 }, | |
2798 | |
2799 _determineButtonType: function() { | |
2800 var ancestor, labelSelector, checked; | |
2801 | |
2802 if ( this.element.is("[type=checkbox]") ) { | |
2803 this.type = "checkbox"; | |
2804 } else if ( this.element.is("[type=radio]") ) { | |
2805 this.type = "radio"; | |
2806 } else if ( this.element.is("input") ) { | |
2807 this.type = "input"; | |
2808 } else { | |
2809 this.type = "button"; | |
2810 } | |
2811 | |
2812 if ( this.type === "checkbox" || this.type === "radio" ) { | |
2813 // we don't search against the document in case the element | |
2814 // is disconnected from the DOM | |
2815 ancestor = this.element.parents().last(); | |
2816 labelSelector = "label[for='" + this.element.attr("id") + "']"; | |
2817 this.buttonElement = ancestor.find( labelSelector ); | |
2818 if ( !this.buttonElement.length ) { | |
2819 ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings(); | |
2820 this.buttonElement = ancestor.filter( labelSelector ); | |
2821 if ( !this.buttonElement.length ) { | |
2822 this.buttonElement = ancestor.find( labelSelector ); | |
2823 } | |
2824 } | |
2825 this.element.addClass( "ui-helper-hidden-accessible" ); | |
2826 | |
2827 checked = this.element.is( ":checked" ); | |
2828 if ( checked ) { | |
2829 this.buttonElement.addClass( "ui-state-active" ); | |
2830 } | |
2831 this.buttonElement.prop( "aria-pressed", checked ); | |
2832 } else { | |
2833 this.buttonElement = this.element; | |
2834 } | |
2835 }, | |
2836 | |
2837 widget: function() { | |
2838 return this.buttonElement; | |
2839 }, | |
2840 | |
2841 _destroy: function() { | |
2842 this.element | |
2843 .removeClass( "ui-helper-hidden-accessible" ); | |
2844 this.buttonElement | |
2845 .removeClass( baseClasses + " ui-state-active " + typeClasses ) | |
2846 .removeAttr( "role" ) | |
2847 .removeAttr( "aria-pressed" ) | |
2848 .html( this.buttonElement.find(".ui-button-text").html() ); | |
2849 | |
2850 if ( !this.hasTitle ) { | |
2851 this.buttonElement.removeAttr( "title" ); | |
2852 } | |
2853 }, | |
2854 | |
2855 _setOption: function( key, value ) { | |
2856 this._super( key, value ); | |
2857 if ( key === "disabled" ) { | |
2858 this.element.prop( "disabled", !!value ); | |
2859 if ( value ) { | |
2860 this.buttonElement.removeClass( "ui-state-focus" ); | |
2861 } | |
2862 return; | |
2863 } | |
2864 this._resetButton(); | |
2865 }, | |
2866 | |
2867 refresh: function() { | |
2868 //See #8237 & #8828 | |
2869 var isDisabled = this.element.is( "input, button" ) ? this.element.is( ":disabled" ) : this.element.hasClass( "ui-button-disabled" ); | |
2870 | |
2871 if ( isDisabled !== this.options.disabled ) { | |
2872 this._setOption( "disabled", isDisabled ); | |
2873 } | |
2874 if ( this.type === "radio" ) { | |
2875 radioGroup( this.element[0] ).each(function() { | |
2876 if ( $( this ).is( ":checked" ) ) { | |
2877 $( this ).button( "widget" ) | |
2878 .addClass( "ui-state-active" ) | |
2879 .attr( "aria-pressed", "true" ); | |
2880 } else { | |
2881 $( this ).button( "widget" ) | |
2882 .removeClass( "ui-state-active" ) | |
2883 .attr( "aria-pressed", "false" ); | |
2884 } | |
2885 }); | |
2886 } else if ( this.type === "checkbox" ) { | |
2887 if ( this.element.is( ":checked" ) ) { | |
2888 this.buttonElement | |
2889 .addClass( "ui-state-active" ) | |
2890 .attr( "aria-pressed", "true" ); | |
2891 } else { | |
2892 this.buttonElement | |
2893 .removeClass( "ui-state-active" ) | |
2894 .attr( "aria-pressed", "false" ); | |
2895 } | |
2896 } | |
2897 }, | |
2898 | |
2899 _resetButton: function() { | |
2900 if ( this.type === "input" ) { | |
2901 if ( this.options.label ) { | |
2902 this.element.val( this.options.label ); | |
2903 } | |
2904 return; | |
2905 } | |
2906 var buttonElement = this.buttonElement.removeClass( typeClasses ), | |
2907 buttonText = $( "<span></span>", this.document[0] ) | |
2908 .addClass( "ui-button-text" ) | |
2909 .html( this.options.label ) | |
2910 .appendTo( buttonElement.empty() ) | |
2911 .text(), | |
2912 icons = this.options.icons, | |
2913 multipleIcons = icons.primary && icons.secondary, | |
2914 buttonClasses = []; | |
2915 | |
2916 if ( icons.primary || icons.secondary ) { | |
2917 if ( this.options.text ) { | |
2918 buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) ); | |
2919 } | |
2920 | |
2921 if ( icons.primary ) { | |
2922 buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" ); | |
2923 } | |
2924 | |
2925 if ( icons.secondary ) { | |
2926 buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" ); | |
2927 } | |
2928 | |
2929 if ( !this.options.text ) { | |
2930 buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" ); | |
2931 | |
2932 if ( !this.hasTitle ) { | |
2933 buttonElement.attr( "title", $.trim( buttonText ) ); | |
2934 } | |
2935 } | |
2936 } else { | |
2937 buttonClasses.push( "ui-button-text-only" ); | |
2938 } | |
2939 buttonElement.addClass( buttonClasses.join( " " ) ); | |
2940 } | |
2941 }); | |
2942 | |
2943 $.widget( "ui.buttonset", { | |
2944 version: "1.10.4", | |
2945 options: { | |
2946 items: "button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)" | |
2947 }, | |
2948 | |
2949 _create: function() { | |
2950 this.element.addClass( "ui-buttonset" ); | |
2951 }, | |
2952 | |
2953 _init: function() { | |
2954 this.refresh(); | |
2955 }, | |
2956 | |
2957 _setOption: function( key, value ) { | |
2958 if ( key === "disabled" ) { | |
2959 this.buttons.button( "option", key, value ); | |
2960 } | |
2961 | |
2962 this._super( key, value ); | |
2963 }, | |
2964 | |
2965 refresh: function() { | |
2966 var rtl = this.element.css( "direction" ) === "rtl"; | |
2967 | |
2968 this.buttons = this.element.find( this.options.items ) | |
2969 .filter( ":ui-button" ) | |
2970 .button( "refresh" ) | |
2971 .end() | |
2972 .not( ":ui-button" ) | |
2973 .button() | |
2974 .end() | |
2975 .map(function() { | |
2976 return $( this ).button( "widget" )[ 0 ]; | |
2977 }) | |
2978 .removeClass( "ui-corner-all ui-corner-left ui-corner-right" ) | |
2979 .filter( ":first" ) | |
2980 .addClass( rtl ? "ui-corner-right" : "ui-corner-left" ) | |
2981 .end() | |
2982 .filter( ":last" ) | |
2983 .addClass( rtl ? "ui-corner-left" : "ui-corner-right" ) | |
2984 .end() | |
2985 .end(); | |
2986 }, | |
2987 | |
2988 _destroy: function() { | |
2989 this.element.removeClass( "ui-buttonset" ); | |
2990 this.buttons | |
2991 .map(function() { | |
2992 return $( this ).button( "widget" )[ 0 ]; | |
2993 }) | |
2994 .removeClass( "ui-corner-left ui-corner-right" ) | |
2995 .end() | |
2996 .button( "destroy" ); | |
2997 } | |
2998 }); | |
2999 | |
3000 }( jQuery ) ); | |
3001 (function( $, undefined ) { | |
3002 | |
3003 $.extend($.ui, { datepicker: { version: "1.10.4" } }); | |
3004 | |
3005 var PROP_NAME = "datepicker", | |
3006 instActive; | |
3007 | |
3008 /* Date picker manager. | |
3009 Use the singleton instance of this class, $.datepicker, to interact with the date picker. | |
3010 Settings for (groups of) date pickers are maintained in an instance object, | |
3011 allowing multiple different settings on the same page. */ | |
3012 | |
3013 function Datepicker() { | |
3014 this._curInst = null; // The current instance in use | |
3015 this._keyEvent = false; // If the last event was a key event | |
3016 this._disabledInputs = []; // List of date picker inputs that have been disabled | |
3017 this._datepickerShowing = false; // True if the popup picker is showing , false if not | |
3018 this._inDialog = false; // True if showing within a "dialog", false if not | |
3019 this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division | |
3020 this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class | |
3021 this._appendClass = "ui-datepicker-append"; // The name of the append marker class | |
3022 this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class | |
3023 this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class | |
3024 this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class | |
3025 this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class | |
3026 this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class | |
3027 this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class | |
3028 this.regional = []; // Available regional settings, indexed by language code | |
3029 this.regional[""] = { // Default regional settings | |
3030 closeText: "Done", // Display text for close link | |
3031 prevText: "Prev", // Display text for previous month link | |
3032 nextText: "Next", // Display text for next month link | |
3033 currentText: "Today", // Display text for current month link | |
3034 monthNames: ["January","February","March","April","May","June", | |
3035 "July","August","September","October","November","December"], // Names of months for drop-down and formatting | |
3036 monthNamesShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], // For formatting | |
3037 dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], // For formatting | |
3038 dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], // For formatting | |
3039 dayNamesMin: ["Su","Mo","Tu","We","Th","Fr","Sa"], // Column headings for days starting at Sunday | |
3040 weekHeader: "Wk", // Column header for week of the year | |
3041 dateFormat: "mm/dd/yy", // See format options on parseDate | |
3042 firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ... | |
3043 isRTL: false, // True if right-to-left language, false if left-to-right | |
3044 showMonthAfterYear: false, // True if the year select precedes month, false for month then year | |
3045 yearSuffix: "" // Additional text to append to the year in the month headers | |
3046 }; | |
3047 this._defaults = { // Global defaults for all the date picker instances | |
3048 showOn: "focus", // "focus" for popup on focus, | |
3049 // "button" for trigger button, or "both" for either | |
3050 showAnim: "fadeIn", // Name of jQuery animation for popup | |
3051 showOptions: {}, // Options for enhanced animations | |
3052 defaultDate: null, // Used when field is blank: actual date, | |
3053 // +/-number for offset from today, null for today | |
3054 appendText: "", // Display text following the input box, e.g. showing the format | |
3055 buttonText: "...", // Text for trigger button | |
3056 buttonImage: "", // URL for trigger button image | |
3057 buttonImageOnly: false, // True if the image appears alone, false if it appears on a button | |
3058 hideIfNoPrevNext: false, // True to hide next/previous month links | |
3059 // if not applicable, false to just disable them | |
3060 navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links | |
3061 gotoCurrent: false, // True if today link goes back to current selection instead | |
3062 changeMonth: false, // True if month can be selected directly, false if only prev/next | |
3063 changeYear: false, // True if year can be selected directly, false if only prev/next | |
3064 yearRange: "c-10:c+10", // Range of years to display in drop-down, | |
3065 // either relative to today's year (-nn:+nn), relative to currently displayed year | |
3066 // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n) | |
3067 showOtherMonths: false, // True to show dates in other months, false to leave blank | |
3068 selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable | |
3069 showWeek: false, // True to show week of the year, false to not show it | |
3070 calculateWeek: this.iso8601Week, // How to calculate the week of the year, | |
3071 // takes a Date and returns the number of the week for it | |
3072 shortYearCutoff: "+10", // Short year values < this are in the current century, | |
3073 // > this are in the previous century, | |
3074 // string value starting with "+" for current year + value | |
3075 minDate: null, // The earliest selectable date, or null for no limit | |
3076 maxDate: null, // The latest selectable date, or null for no limit | |
3077 duration: "fast", // Duration of display/closure | |
3078 beforeShowDay: null, // Function that takes a date and returns an array with | |
3079 // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "", | |
3080 // [2] = cell title (optional), e.g. $.datepicker.noWeekends | |
3081 beforeShow: null, // Function that takes an input field and | |
3082 // returns a set of custom settings for the date picker | |
3083 onSelect: null, // Define a callback function when a date is selected | |
3084 onChangeMonthYear: null, // Define a callback function when the month or year is changed | |
3085 onClose: null, // Define a callback function when the datepicker is closed | |
3086 numberOfMonths: 1, // Number of months to show at a time | |
3087 showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0) | |
3088 stepMonths: 1, // Number of months to step back/forward | |
3089 stepBigMonths: 12, // Number of months to step back/forward for the big links | |
3090 altField: "", // Selector for an alternate field to store selected dates into | |
3091 altFormat: "", // The date format to use for the alternate field | |
3092 constrainInput: true, // The input is constrained by the current date format | |
3093 showButtonPanel: false, // True to show button panel, false to not show it | |
3094 autoSize: false, // True to size the input for the date format, false to leave as is | |
3095 disabled: false // The initial disabled state | |
3096 }; | |
3097 $.extend(this._defaults, this.regional[""]); | |
3098 this.dpDiv = bindHover($("<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")); | |
3099 } | |
3100 | |
3101 $.extend(Datepicker.prototype, { | |
3102 /* Class name added to elements to indicate already configured with a date picker. */ | |
3103 markerClassName: "hasDatepicker", | |
3104 | |
3105 //Keep track of the maximum number of rows displayed (see #7043) | |
3106 maxRows: 4, | |
3107 | |
3108 // TODO rename to "widget" when switching to widget factory | |
3109 _widgetDatepicker: function() { | |
3110 return this.dpDiv; | |
3111 }, | |
3112 | |
3113 /* Override the default settings for all instances of the date picker. | |
3114 * @param settings object - the new settings to use as defaults (anonymous object) | |
3115 * @return the manager object | |
3116 */ | |
3117 setDefaults: function(settings) { | |
3118 extendRemove(this._defaults, settings || {}); | |
3119 return this; | |
3120 }, | |
3121 | |
3122 /* Attach the date picker to a jQuery selection. | |
3123 * @param target element - the target input field or division or span | |
3124 * @param settings object - the new settings to use for this date picker instance (anonymous) | |
3125 */ | |
3126 _attachDatepicker: function(target, settings) { | |
3127 var nodeName, inline, inst; | |
3128 nodeName = target.nodeName.toLowerCase(); | |
3129 inline = (nodeName === "div" || nodeName === "span"); | |
3130 if (!target.id) { | |
3131 this.uuid += 1; | |
3132 target.id = "dp" + this.uuid; | |
3133 } | |
3134 inst = this._newInst($(target), inline); | |
3135 inst.settings = $.extend({}, settings || {}); | |
3136 if (nodeName === "input") { | |
3137 this._connectDatepicker(target, inst); | |
3138 } else if (inline) { | |
3139 this._inlineDatepicker(target, inst); | |
3140 } | |
3141 }, | |
3142 | |
3143 /* Create a new instance object. */ | |
3144 _newInst: function(target, inline) { | |
3145 var id = target[0].id.replace(/([^A-Za-z0-9_\-])/g, "\\\\$1"); // escape jQuery meta chars | |
3146 return {id: id, input: target, // associated target | |
3147 selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection | |
3148 drawMonth: 0, drawYear: 0, // month being drawn | |
3149 inline: inline, // is datepicker inline or not | |
3150 dpDiv: (!inline ? this.dpDiv : // presentation div | |
3151 bindHover($("<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")))}; | |
3152 }, | |
3153 | |
3154 /* Attach the date picker to an input field. */ | |
3155 _connectDatepicker: function(target, inst) { | |
3156 var input = $(target); | |
3157 inst.append = $([]); | |
3158 inst.trigger = $([]); | |
3159 if (input.hasClass(this.markerClassName)) { | |
3160 return; | |
3161 } | |
3162 this._attachments(input, inst); | |
3163 input.addClass(this.markerClassName).keydown(this._doKeyDown). | |
3164 keypress(this._doKeyPress).keyup(this._doKeyUp); | |
3165 this._autoSize(inst); | |
3166 $.data(target, PROP_NAME, inst); | |
3167 //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665) | |
3168 if( inst.settings.disabled ) { | |
3169 this._disableDatepicker( target ); | |
3170 } | |
3171 }, | |
3172 | |
3173 /* Make attachments based on settings. */ | |
3174 _attachments: function(input, inst) { | |
3175 var showOn, buttonText, buttonImage, | |
3176 appendText = this._get(inst, "appendText"), | |
3177 isRTL = this._get(inst, "isRTL"); | |
3178 | |
3179 if (inst.append) { | |
3180 inst.append.remove(); | |
3181 } | |
3182 if (appendText) { | |
3183 inst.append = $("<span class='" + this._appendClass + "'>" + appendText + "</span>"); | |
3184 input[isRTL ? "before" : "after"](inst.append); | |
3185 } | |
3186 | |
3187 input.unbind("focus", this._showDatepicker); | |
3188 | |
3189 if (inst.trigger) { | |
3190 inst.trigger.remove(); | |
3191 } | |
3192 | |
3193 showOn = this._get(inst, "showOn"); | |
3194 if (showOn === "focus" || showOn === "both") { // pop-up date picker when in the marked field | |
3195 input.focus(this._showDatepicker); | |
3196 } | |
3197 if (showOn === "button" || showOn === "both") { // pop-up date picker when button clicked | |
3198 buttonText = this._get(inst, "buttonText"); | |
3199 buttonImage = this._get(inst, "buttonImage"); | |
3200 inst.trigger = $(this._get(inst, "buttonImageOnly") ? | |
3201 $("<img/>").addClass(this._triggerClass). | |
3202 attr({ src: buttonImage, alt: buttonText, title: buttonText }) : | |
3203 $("<button type='button'></button>").addClass(this._triggerClass). | |
3204 html(!buttonImage ? buttonText : $("<img/>").attr( | |
3205 { src:buttonImage, alt:buttonText, title:buttonText }))); | |
3206 input[isRTL ? "before" : "after"](inst.trigger); | |
3207 inst.trigger.click(function() { | |
3208 if ($.datepicker._datepickerShowing && $.datepicker._lastInput === input[0]) { | |
3209 $.datepicker._hideDatepicker(); | |
3210 } else if ($.datepicker._datepickerShowing && $.datepicker._lastInput !== input[0]) { | |
3211 $.datepicker._hideDatepicker(); | |
3212 $.datepicker._showDatepicker(input[0]); | |
3213 } else { | |
3214 $.datepicker._showDatepicker(input[0]); | |
3215 } | |
3216 return false; | |
3217 }); | |
3218 } | |
3219 }, | |
3220 | |
3221 /* Apply the maximum length for the date format. */ | |
3222 _autoSize: function(inst) { | |
3223 if (this._get(inst, "autoSize") && !inst.inline) { | |
3224 var findMax, max, maxI, i, | |
3225 date = new Date(2009, 12 - 1, 20), // Ensure double digits | |
3226 dateFormat = this._get(inst, "dateFormat"); | |
3227 | |
3228 if (dateFormat.match(/[DM]/)) { | |
3229 findMax = function(names) { | |
3230 max = 0; | |
3231 maxI = 0; | |
3232 for (i = 0; i < names.length; i++) { | |
3233 if (names[i].length > max) { | |
3234 max = names[i].length; | |
3235 maxI = i; | |
3236 } | |
3237 } | |
3238 return maxI; | |
3239 }; | |
3240 date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ? | |
3241 "monthNames" : "monthNamesShort")))); | |
3242 date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ? | |
3243 "dayNames" : "dayNamesShort"))) + 20 - date.getDay()); | |
3244 } | |
3245 inst.input.attr("size", this._formatDate(inst, date).length); | |
3246 } | |
3247 }, | |
3248 | |
3249 /* Attach an inline date picker to a div. */ | |
3250 _inlineDatepicker: function(target, inst) { | |
3251 var divSpan = $(target); | |
3252 if (divSpan.hasClass(this.markerClassName)) { | |
3253 return; | |
3254 } | |
3255 divSpan.addClass(this.markerClassName).append(inst.dpDiv); | |
3256 $.data(target, PROP_NAME, inst); | |
3257 this._setDate(inst, this._getDefaultDate(inst), true); | |
3258 this._updateDatepicker(inst); | |
3259 this._updateAlternate(inst); | |
3260 //If disabled option is true, disable the datepicker before showing it (see ticket #5665) | |
3261 if( inst.settings.disabled ) { | |
3262 this._disableDatepicker( target ); | |
3263 } | |
3264 // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements | |
3265 // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height | |
3266 inst.dpDiv.css( "display", "block" ); | |
3267 }, | |
3268 | |
3269 /* Pop-up the date picker in a "dialog" box. | |
3270 * @param input element - ignored | |
3271 * @param date string or Date - the initial date to display | |
3272 * @param onSelect function - the function to call when a date is selected | |
3273 * @param settings object - update the dialog date picker instance's settings (anonymous object) | |
3274 * @param pos int[2] - coordinates for the dialog's position within the screen or | |
3275 * event - with x/y coordinates or | |
3276 * leave empty for default (screen centre) | |
3277 * @return the manager object | |
3278 */ | |
3279 _dialogDatepicker: function(input, date, onSelect, settings, pos) { | |
3280 var id, browserWidth, browserHeight, scrollX, scrollY, | |
3281 inst = this._dialogInst; // internal instance | |
3282 | |
3283 if (!inst) { | |
3284 this.uuid += 1; | |
3285 id = "dp" + this.uuid; | |
3286 this._dialogInput = $("<input type='text' id='" + id + | |
3287 "' style='position: absolute; top: -100px; width: 0px;'/>"); | |
3288 this._dialogInput.keydown(this._doKeyDown); | |
3289 $("body").append(this._dialogInput); | |
3290 inst = this._dialogInst = this._newInst(this._dialogInput, false); | |
3291 inst.settings = {}; | |
3292 $.data(this._dialogInput[0], PROP_NAME, inst); | |
3293 } | |
3294 extendRemove(inst.settings, settings || {}); | |
3295 date = (date && date.constructor === Date ? this._formatDate(inst, date) : date); | |
3296 this._dialogInput.val(date); | |
3297 | |
3298 this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null); | |
3299 if (!this._pos) { | |
3300 browserWidth = document.documentElement.clientWidth; | |
3301 browserHeight = document.documentElement.clientHeight; | |
3302 scrollX = document.documentElement.scrollLeft || document.body.scrollLeft; | |
3303 scrollY = document.documentElement.scrollTop || document.body.scrollTop; | |
3304 this._pos = // should use actual width/height below | |
3305 [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY]; | |
3306 } | |
3307 | |
3308 // move input on screen for focus, but hidden behind dialog | |
3309 this._dialogInput.css("left", (this._pos[0] + 20) + "px").css("top", this._pos[1] + "px"); | |
3310 inst.settings.onSelect = onSelect; | |
3311 this._inDialog = true; | |
3312 this.dpDiv.addClass(this._dialogClass); | |
3313 this._showDatepicker(this._dialogInput[0]); | |
3314 if ($.blockUI) { | |
3315 $.blockUI(this.dpDiv); | |
3316 } | |
3317 $.data(this._dialogInput[0], PROP_NAME, inst); | |
3318 return this; | |
3319 }, | |
3320 | |
3321 /* Detach a datepicker from its control. | |
3322 * @param target element - the target input field or division or span | |
3323 */ | |
3324 _destroyDatepicker: function(target) { | |
3325 var nodeName, | |
3326 $target = $(target), | |
3327 inst = $.data(target, PROP_NAME); | |
3328 | |
3329 if (!$target.hasClass(this.markerClassName)) { | |
3330 return; | |
3331 } | |
3332 | |
3333 nodeName = target.nodeName.toLowerCase(); | |
3334 $.removeData(target, PROP_NAME); | |
3335 if (nodeName === "input") { | |
3336 inst.append.remove(); | |
3337 inst.trigger.remove(); | |
3338 $target.removeClass(this.markerClassName). | |
3339 unbind("focus", this._showDatepicker). | |
3340 unbind("keydown", this._doKeyDown). | |
3341 unbind("keypress", this._doKeyPress). | |
3342 unbind("keyup", this._doKeyUp); | |
3343 } else if (nodeName === "div" || nodeName === "span") { | |
3344 $target.removeClass(this.markerClassName).empty(); | |
3345 } | |
3346 }, | |
3347 | |
3348 /* Enable the date picker to a jQuery selection. | |
3349 * @param target element - the target input field or division or span | |
3350 */ | |
3351 _enableDatepicker: function(target) { | |
3352 var nodeName, inline, | |
3353 $target = $(target), | |
3354 inst = $.data(target, PROP_NAME); | |
3355 | |
3356 if (!$target.hasClass(this.markerClassName)) { | |
3357 return; | |
3358 } | |
3359 | |
3360 nodeName = target.nodeName.toLowerCase(); | |
3361 if (nodeName === "input") { | |
3362 target.disabled = false; | |
3363 inst.trigger.filter("button"). | |
3364 each(function() { this.disabled = false; }).end(). | |
3365 filter("img").css({opacity: "1.0", cursor: ""}); | |
3366 } else if (nodeName === "div" || nodeName === "span") { | |
3367 inline = $target.children("." + this._inlineClass); | |
3368 inline.children().removeClass("ui-state-disabled"); | |
3369 inline.find("select.ui-datepicker-month, select.ui-datepicker-year"). | |
3370 prop("disabled", false); | |
3371 } | |
3372 this._disabledInputs = $.map(this._disabledInputs, | |
3373 function(value) { return (value === target ? null : value); }); // delete entry | |
3374 }, | |
3375 | |
3376 /* Disable the date picker to a jQuery selection. | |
3377 * @param target element - the target input field or division or span | |
3378 */ | |
3379 _disableDatepicker: function(target) { | |
3380 var nodeName, inline, | |
3381 $target = $(target), | |
3382 inst = $.data(target, PROP_NAME); | |
3383 | |
3384 if (!$target.hasClass(this.markerClassName)) { | |
3385 return; | |
3386 } | |
3387 | |
3388 nodeName = target.nodeName.toLowerCase(); | |
3389 if (nodeName === "input") { | |
3390 target.disabled = true; | |
3391 inst.trigger.filter("button"). | |
3392 each(function() { this.disabled = true; }).end(). | |
3393 filter("img").css({opacity: "0.5", cursor: "default"}); | |
3394 } else if (nodeName === "div" || nodeName === "span") { | |
3395 inline = $target.children("." + this._inlineClass); | |
3396 inline.children().addClass("ui-state-disabled"); | |
3397 inline.find("select.ui-datepicker-month, select.ui-datepicker-year"). | |
3398 prop("disabled", true); | |
3399 } | |
3400 this._disabledInputs = $.map(this._disabledInputs, | |
3401 function(value) { return (value === target ? null : value); }); // delete entry | |
3402 this._disabledInputs[this._disabledInputs.length] = target; | |
3403 }, | |
3404 | |
3405 /* Is the first field in a jQuery collection disabled as a datepicker? | |
3406 * @param target element - the target input field or division or span | |
3407 * @return boolean - true if disabled, false if enabled | |
3408 */ | |
3409 _isDisabledDatepicker: function(target) { | |
3410 if (!target) { | |
3411 return false; | |
3412 } | |
3413 for (var i = 0; i < this._disabledInputs.length; i++) { | |
3414 if (this._disabledInputs[i] === target) { | |
3415 return true; | |
3416 } | |
3417 } | |
3418 return false; | |
3419 }, | |
3420 | |
3421 /* Retrieve the instance data for the target control. | |
3422 * @param target element - the target input field or division or span | |
3423 * @return object - the associated instance data | |
3424 * @throws error if a jQuery problem getting data | |
3425 */ | |
3426 _getInst: function(target) { | |
3427 try { | |
3428 return $.data(target, PROP_NAME); | |
3429 } | |
3430 catch (err) { | |
3431 throw "Missing instance data for this datepicker"; | |
3432 } | |
3433 }, | |
3434 | |
3435 /* Update or retrieve the settings for a date picker attached to an input field or division. | |
3436 * @param target element - the target input field or division or span | |
3437 * @param name object - the new settings to update or | |
3438 * string - the name of the setting to change or retrieve, | |
3439 * when retrieving also "all" for all instance settings or | |
3440 * "defaults" for all global defaults | |
3441 * @param value any - the new value for the setting | |
3442 * (omit if above is an object or to retrieve a value) | |
3443 */ | |
3444 _optionDatepicker: function(target, name, value) { | |
3445 var settings, date, minDate, maxDate, | |
3446 inst = this._getInst(target); | |
3447 | |
3448 if (arguments.length === 2 && typeof name === "string") { | |
3449 return (name === "defaults" ? $.extend({}, $.datepicker._defaults) : | |
3450 (inst ? (name === "all" ? $.extend({}, inst.settings) : | |
3451 this._get(inst, name)) : null)); | |
3452 } | |
3453 | |
3454 settings = name || {}; | |
3455 if (typeof name === "string") { | |
3456 settings = {}; | |
3457 settings[name] = value; | |
3458 } | |
3459 | |
3460 if (inst) { | |
3461 if (this._curInst === inst) { | |
3462 this._hideDatepicker(); | |
3463 } | |
3464 | |
3465 date = this._getDateDatepicker(target, true); | |
3466 minDate = this._getMinMaxDate(inst, "min"); | |
3467 maxDate = this._getMinMaxDate(inst, "max"); | |
3468 extendRemove(inst.settings, settings); | |
3469 // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided | |
3470 if (minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined) { | |
3471 inst.settings.minDate = this._formatDate(inst, minDate); | |
3472 } | |
3473 if (maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined) { | |
3474 inst.settings.maxDate = this._formatDate(inst, maxDate); | |
3475 } | |
3476 if ( "disabled" in settings ) { | |
3477 if ( settings.disabled ) { | |
3478 this._disableDatepicker(target); | |
3479 } else { | |
3480 this._enableDatepicker(target); | |
3481 } | |
3482 } | |
3483 this._attachments($(target), inst); | |
3484 this._autoSize(inst); | |
3485 this._setDate(inst, date); | |
3486 this._updateAlternate(inst); | |
3487 this._updateDatepicker(inst); | |
3488 } | |
3489 }, | |
3490 | |
3491 // change method deprecated | |
3492 _changeDatepicker: function(target, name, value) { | |
3493 this._optionDatepicker(target, name, value); | |
3494 }, | |
3495 | |
3496 /* Redraw the date picker attached to an input field or division. | |
3497 * @param target element - the target input field or division or span | |
3498 */ | |
3499 _refreshDatepicker: function(target) { | |
3500 var inst = this._getInst(target); | |
3501 if (inst) { | |
3502 this._updateDatepicker(inst); | |
3503 } | |
3504 }, | |
3505 | |
3506 /* Set the dates for a jQuery selection. | |
3507 * @param target element - the target input field or division or span | |
3508 * @param date Date - the new date | |
3509 */ | |
3510 _setDateDatepicker: function(target, date) { | |
3511 var inst = this._getInst(target); | |
3512 if (inst) { | |
3513 this._setDate(inst, date); | |
3514 this._updateDatepicker(inst); | |
3515 this._updateAlternate(inst); | |
3516 } | |
3517 }, | |
3518 | |
3519 /* Get the date(s) for the first entry in a jQuery selection. | |
3520 * @param target element - the target input field or division or span | |
3521 * @param noDefault boolean - true if no default date is to be used | |
3522 * @return Date - the current date | |
3523 */ | |
3524 _getDateDatepicker: function(target, noDefault) { | |
3525 var inst = this._getInst(target); | |
3526 if (inst && !inst.inline) { | |
3527 this._setDateFromField(inst, noDefault); | |
3528 } | |
3529 return (inst ? this._getDate(inst) : null); | |
3530 }, | |
3531 | |
3532 /* Handle keystrokes. */ | |
3533 _doKeyDown: function(event) { | |
3534 var onSelect, dateStr, sel, | |
3535 inst = $.datepicker._getInst(event.target), | |
3536 handled = true, | |
3537 isRTL = inst.dpDiv.is(".ui-datepicker-rtl"); | |
3538 | |
3539 inst._keyEvent = true; | |
3540 if ($.datepicker._datepickerShowing) { | |
3541 switch (event.keyCode) { | |
3542 case 9: $.datepicker._hideDatepicker(); | |
3543 handled = false; | |
3544 break; // hide on tab out | |
3545 case 13: sel = $("td." + $.datepicker._dayOverClass + ":not(." + | |
3546 $.datepicker._currentClass + ")", inst.dpDiv); | |
3547 if (sel[0]) { | |
3548 $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]); | |
3549 } | |
3550 | |
3551 onSelect = $.datepicker._get(inst, "onSelect"); | |
3552 if (onSelect) { | |
3553 dateStr = $.datepicker._formatDate(inst); | |
3554 | |
3555 // trigger custom callback | |
3556 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); | |
3557 } else { | |
3558 $.datepicker._hideDatepicker(); | |
3559 } | |
3560 | |
3561 return false; // don't submit the form | |
3562 case 27: $.datepicker._hideDatepicker(); | |
3563 break; // hide on escape | |
3564 case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ? | |
3565 -$.datepicker._get(inst, "stepBigMonths") : | |
3566 -$.datepicker._get(inst, "stepMonths")), "M"); | |
3567 break; // previous month/year on page up/+ ctrl | |
3568 case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ? | |
3569 +$.datepicker._get(inst, "stepBigMonths") : | |
3570 +$.datepicker._get(inst, "stepMonths")), "M"); | |
3571 break; // next month/year on page down/+ ctrl | |
3572 case 35: if (event.ctrlKey || event.metaKey) { | |
3573 $.datepicker._clearDate(event.target); | |
3574 } | |
3575 handled = event.ctrlKey || event.metaKey; | |
3576 break; // clear on ctrl or command +end | |
3577 case 36: if (event.ctrlKey || event.metaKey) { | |
3578 $.datepicker._gotoToday(event.target); | |
3579 } | |
3580 handled = event.ctrlKey || event.metaKey; | |
3581 break; // current on ctrl or command +home | |
3582 case 37: if (event.ctrlKey || event.metaKey) { | |
3583 $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), "D"); | |
3584 } | |
3585 handled = event.ctrlKey || event.metaKey; | |
3586 // -1 day on ctrl or command +left | |
3587 if (event.originalEvent.altKey) { | |
3588 $.datepicker._adjustDate(event.target, (event.ctrlKey ? | |
3589 -$.datepicker._get(inst, "stepBigMonths") : | |
3590 -$.datepicker._get(inst, "stepMonths")), "M"); | |
3591 } | |
3592 // next month/year on alt +left on Mac | |
3593 break; | |
3594 case 38: if (event.ctrlKey || event.metaKey) { | |
3595 $.datepicker._adjustDate(event.target, -7, "D"); | |
3596 } | |
3597 handled = event.ctrlKey || event.metaKey; | |
3598 break; // -1 week on ctrl or command +up | |
3599 case 39: if (event.ctrlKey || event.metaKey) { | |
3600 $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), "D"); | |
3601 } | |
3602 handled = event.ctrlKey || event.metaKey; | |
3603 // +1 day on ctrl or command +right | |
3604 if (event.originalEvent.altKey) { | |
3605 $.datepicker._adjustDate(event.target, (event.ctrlKey ? | |
3606 +$.datepicker._get(inst, "stepBigMonths") : | |
3607 +$.datepicker._get(inst, "stepMonths")), "M"); | |
3608 } | |
3609 // next month/year on alt +right | |
3610 break; | |
3611 case 40: if (event.ctrlKey || event.metaKey) { | |
3612 $.datepicker._adjustDate(event.target, +7, "D"); | |
3613 } | |
3614 handled = event.ctrlKey || event.metaKey; | |
3615 break; // +1 week on ctrl or command +down | |
3616 default: handled = false; | |
3617 } | |
3618 } else if (event.keyCode === 36 && event.ctrlKey) { // display the date picker on ctrl+home | |
3619 $.datepicker._showDatepicker(this); | |
3620 } else { | |
3621 handled = false; | |
3622 } | |
3623 | |
3624 if (handled) { | |
3625 event.preventDefault(); | |
3626 event.stopPropagation(); | |
3627 } | |
3628 }, | |
3629 | |
3630 /* Filter entered characters - based on date format. */ | |
3631 _doKeyPress: function(event) { | |
3632 var chars, chr, | |
3633 inst = $.datepicker._getInst(event.target); | |
3634 | |
3635 if ($.datepicker._get(inst, "constrainInput")) { | |
3636 chars = $.datepicker._possibleChars($.datepicker._get(inst, "dateFormat")); | |
3637 chr = String.fromCharCode(event.charCode == null ? event.keyCode : event.charCode); | |
3638 return event.ctrlKey || event.metaKey || (chr < " " || !chars || chars.indexOf(chr) > -1); | |
3639 } | |
3640 }, | |
3641 | |
3642 /* Synchronise manual entry and field/alternate field. */ | |
3643 _doKeyUp: function(event) { | |
3644 var date, | |
3645 inst = $.datepicker._getInst(event.target); | |
3646 | |
3647 if (inst.input.val() !== inst.lastVal) { | |
3648 try { | |
3649 date = $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"), | |
3650 (inst.input ? inst.input.val() : null), | |
3651 $.datepicker._getFormatConfig(inst)); | |
3652 | |
3653 if (date) { // only if valid | |
3654 $.datepicker._setDateFromField(inst); | |
3655 $.datepicker._updateAlternate(inst); | |
3656 $.datepicker._updateDatepicker(inst); | |
3657 } | |
3658 } | |
3659 catch (err) { | |
3660 } | |
3661 } | |
3662 return true; | |
3663 }, | |
3664 | |
3665 /* Pop-up the date picker for a given input field. | |
3666 * If false returned from beforeShow event handler do not show. | |
3667 * @param input element - the input field attached to the date picker or | |
3668 * event - if triggered by focus | |
3669 */ | |
3670 _showDatepicker: function(input) { | |
3671 input = input.target || input; | |
3672 if (input.nodeName.toLowerCase() !== "input") { // find from button/image trigger | |
3673 input = $("input", input.parentNode)[0]; | |
3674 } | |
3675 | |
3676 if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput === input) { // already here | |
3677 return; | |
3678 } | |
3679 | |
3680 var inst, beforeShow, beforeShowSettings, isFixed, | |
3681 offset, showAnim, duration; | |
3682 | |
3683 inst = $.datepicker._getInst(input); | |
3684 if ($.datepicker._curInst && $.datepicker._curInst !== inst) { | |
3685 $.datepicker._curInst.dpDiv.stop(true, true); | |
3686 if ( inst && $.datepicker._datepickerShowing ) { | |
3687 $.datepicker._hideDatepicker( $.datepicker._curInst.input[0] ); | |
3688 } | |
3689 } | |
3690 | |
3691 beforeShow = $.datepicker._get(inst, "beforeShow"); | |
3692 beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {}; | |
3693 if(beforeShowSettings === false){ | |
3694 return; | |
3695 } | |
3696 extendRemove(inst.settings, beforeShowSettings); | |
3697 | |
3698 inst.lastVal = null; | |
3699 $.datepicker._lastInput = input; | |
3700 $.datepicker._setDateFromField(inst); | |
3701 | |
3702 if ($.datepicker._inDialog) { // hide cursor | |
3703 input.value = ""; | |
3704 } | |
3705 if (!$.datepicker._pos) { // position below input | |
3706 $.datepicker._pos = $.datepicker._findPos(input); | |
3707 $.datepicker._pos[1] += input.offsetHeight; // add the height | |
3708 } | |
3709 | |
3710 isFixed = false; | |
3711 $(input).parents().each(function() { | |
3712 isFixed |= $(this).css("position") === "fixed"; | |
3713 return !isFixed; | |
3714 }); | |
3715 | |
3716 offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]}; | |
3717 $.datepicker._pos = null; | |
3718 //to avoid flashes on Firefox | |
3719 inst.dpDiv.empty(); | |
3720 // determine sizing offscreen | |
3721 inst.dpDiv.css({position: "absolute", display: "block", top: "-1000px"}); | |
3722 $.datepicker._updateDatepicker(inst); | |
3723 // fix width for dynamic number of date pickers | |
3724 // and adjust position before showing | |
3725 offset = $.datepicker._checkOffset(inst, offset, isFixed); | |
3726 inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ? | |
3727 "static" : (isFixed ? "fixed" : "absolute")), display: "none", | |
3728 left: offset.left + "px", top: offset.top + "px"}); | |
3729 | |
3730 if (!inst.inline) { | |
3731 showAnim = $.datepicker._get(inst, "showAnim"); | |
3732 duration = $.datepicker._get(inst, "duration"); | |
3733 inst.dpDiv.zIndex($(input).zIndex()+1); | |
3734 $.datepicker._datepickerShowing = true; | |
3735 | |
3736 if ( $.effects && $.effects.effect[ showAnim ] ) { | |
3737 inst.dpDiv.show(showAnim, $.datepicker._get(inst, "showOptions"), duration); | |
3738 } else { | |
3739 inst.dpDiv[showAnim || "show"](showAnim ? duration : null); | |
3740 } | |
3741 | |
3742 if ( $.datepicker._shouldFocusInput( inst ) ) { | |
3743 inst.input.focus(); | |
3744 } | |
3745 | |
3746 $.datepicker._curInst = inst; | |
3747 } | |
3748 }, | |
3749 | |
3750 /* Generate the date picker content. */ | |
3751 _updateDatepicker: function(inst) { | |
3752 this.maxRows = 4; //Reset the max number of rows being displayed (see #7043) | |
3753 instActive = inst; // for delegate hover events | |
3754 inst.dpDiv.empty().append(this._generateHTML(inst)); | |
3755 this._attachHandlers(inst); | |
3756 inst.dpDiv.find("." + this._dayOverClass + " a").mouseover(); | |
3757 | |
3758 var origyearshtml, | |
3759 numMonths = this._getNumberOfMonths(inst), | |
3760 cols = numMonths[1], | |
3761 width = 17; | |
3762 | |
3763 inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""); | |
3764 if (cols > 1) { | |
3765 inst.dpDiv.addClass("ui-datepicker-multi-" + cols).css("width", (width * cols) + "em"); | |
3766 } | |
3767 inst.dpDiv[(numMonths[0] !== 1 || numMonths[1] !== 1 ? "add" : "remove") + | |
3768 "Class"]("ui-datepicker-multi"); | |
3769 inst.dpDiv[(this._get(inst, "isRTL") ? "add" : "remove") + | |
3770 "Class"]("ui-datepicker-rtl"); | |
3771 | |
3772 if (inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) { | |
3773 inst.input.focus(); | |
3774 } | |
3775 | |
3776 // deffered render of the years select (to avoid flashes on Firefox) | |
3777 if( inst.yearshtml ){ | |
3778 origyearshtml = inst.yearshtml; | |
3779 setTimeout(function(){ | |
3780 //assure that inst.yearshtml didn't change. | |
3781 if( origyearshtml === inst.yearshtml && inst.yearshtml ){ | |
3782 inst.dpDiv.find("select.ui-datepicker-year:first").replaceWith(inst.yearshtml); | |
3783 } | |
3784 origyearshtml = inst.yearshtml = null; | |
3785 }, 0); | |
3786 } | |
3787 }, | |
3788 | |
3789 // #6694 - don't focus the input if it's already focused | |
3790 // this breaks the change event in IE | |
3791 // Support: IE and jQuery <1.9 | |
3792 _shouldFocusInput: function( inst ) { | |
3793 return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" ); | |
3794 }, | |
3795 | |
3796 /* Check positioning to remain on screen. */ | |
3797 _checkOffset: function(inst, offset, isFixed) { | |
3798 var dpWidth = inst.dpDiv.outerWidth(), | |
3799 dpHeight = inst.dpDiv.outerHeight(), | |
3800 inputWidth = inst.input ? inst.input.outerWidth() : 0, | |
3801 inputHeight = inst.input ? inst.input.outerHeight() : 0, | |
3802 viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft()), | |
3803 viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop()); | |
3804 | |
3805 offset.left -= (this._get(inst, "isRTL") ? (dpWidth - inputWidth) : 0); | |
3806 offset.left -= (isFixed && offset.left === inst.input.offset().left) ? $(document).scrollLeft() : 0; | |
3807 offset.top -= (isFixed && offset.top === (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0; | |
3808 | |
3809 // now check if datepicker is showing outside window viewport - move to a better place if so. | |
3810 offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ? | |
3811 Math.abs(offset.left + dpWidth - viewWidth) : 0); | |
3812 offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ? | |
3813 Math.abs(dpHeight + inputHeight) : 0); | |
3814 | |
3815 return offset; | |
3816 }, | |
3817 | |
3818 /* Find an object's position on the screen. */ | |
3819 _findPos: function(obj) { | |
3820 var position, | |
3821 inst = this._getInst(obj), | |
3822 isRTL = this._get(inst, "isRTL"); | |
3823 | |
3824 while (obj && (obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden(obj))) { | |
3825 obj = obj[isRTL ? "previousSibling" : "nextSibling"]; | |
3826 } | |
3827 | |
3828 position = $(obj).offset(); | |
3829 return [position.left, position.top]; | |
3830 }, | |
3831 | |
3832 /* Hide the date picker from view. | |
3833 * @param input element - the input field attached to the date picker | |
3834 */ | |
3835 _hideDatepicker: function(input) { | |
3836 var showAnim, duration, postProcess, onClose, | |
3837 inst = this._curInst; | |
3838 | |
3839 if (!inst || (input && inst !== $.data(input, PROP_NAME))) { | |
3840 return; | |
3841 } | |
3842 | |
3843 if (this._datepickerShowing) { | |
3844 showAnim = this._get(inst, "showAnim"); | |
3845 duration = this._get(inst, "duration"); | |
3846 postProcess = function() { | |
3847 $.datepicker._tidyDialog(inst); | |
3848 }; | |
3849 | |
3850 // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed | |
3851 if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) { | |
3852 inst.dpDiv.hide(showAnim, $.datepicker._get(inst, "showOptions"), duration, postProcess); | |
3853 } else { | |
3854 inst.dpDiv[(showAnim === "slideDown" ? "slideUp" : | |
3855 (showAnim === "fadeIn" ? "fadeOut" : "hide"))]((showAnim ? duration : null), postProcess); | |
3856 } | |
3857 | |
3858 if (!showAnim) { | |
3859 postProcess(); | |
3860 } | |
3861 this._datepickerShowing = false; | |
3862 | |
3863 onClose = this._get(inst, "onClose"); | |
3864 if (onClose) { | |
3865 onClose.apply((inst.input ? inst.input[0] : null), [(inst.input ? inst.input.val() : ""), inst]); | |
3866 } | |
3867 | |
3868 this._lastInput = null; | |
3869 if (this._inDialog) { | |
3870 this._dialogInput.css({ position: "absolute", left: "0", top: "-100px" }); | |
3871 if ($.blockUI) { | |
3872 $.unblockUI(); | |
3873 $("body").append(this.dpDiv); | |
3874 } | |
3875 } | |
3876 this._inDialog = false; | |
3877 } | |
3878 }, | |
3879 | |
3880 /* Tidy up after a dialog display. */ | |
3881 _tidyDialog: function(inst) { | |
3882 inst.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar"); | |
3883 }, | |
3884 | |
3885 /* Close date picker if clicked elsewhere. */ | |
3886 _checkExternalClick: function(event) { | |
3887 if (!$.datepicker._curInst) { | |
3888 return; | |
3889 } | |
3890 | |
3891 var $target = $(event.target), | |
3892 inst = $.datepicker._getInst($target[0]); | |
3893 | |
3894 if ( ( ( $target[0].id !== $.datepicker._mainDivId && | |
3895 $target.parents("#" + $.datepicker._mainDivId).length === 0 && | |
3896 !$target.hasClass($.datepicker.markerClassName) && | |
3897 !$target.closest("." + $.datepicker._triggerClass).length && | |
3898 $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) || | |
3899 ( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst !== inst ) ) { | |
3900 $.datepicker._hideDatepicker(); | |
3901 } | |
3902 }, | |
3903 | |
3904 /* Adjust one of the date sub-fields. */ | |
3905 _adjustDate: function(id, offset, period) { | |
3906 var target = $(id), | |
3907 inst = this._getInst(target[0]); | |
3908 | |
3909 if (this._isDisabledDatepicker(target[0])) { | |
3910 return; | |
3911 } | |
3912 this._adjustInstDate(inst, offset + | |
3913 (period === "M" ? this._get(inst, "showCurrentAtPos") : 0), // undo positioning | |
3914 period); | |
3915 this._updateDatepicker(inst); | |
3916 }, | |
3917 | |
3918 /* Action for current link. */ | |
3919 _gotoToday: function(id) { | |
3920 var date, | |
3921 target = $(id), | |
3922 inst = this._getInst(target[0]); | |
3923 | |
3924 if (this._get(inst, "gotoCurrent") && inst.currentDay) { | |
3925 inst.selectedDay = inst.currentDay; | |
3926 inst.drawMonth = inst.selectedMonth = inst.currentMonth; | |
3927 inst.drawYear = inst.selectedYear = inst.currentYear; | |
3928 } else { | |
3929 date = new Date(); | |
3930 inst.selectedDay = date.getDate(); | |
3931 inst.drawMonth = inst.selectedMonth = date.getMonth(); | |
3932 inst.drawYear = inst.selectedYear = date.getFullYear(); | |
3933 } | |
3934 this._notifyChange(inst); | |
3935 this._adjustDate(target); | |
3936 }, | |
3937 | |
3938 /* Action for selecting a new month/year. */ | |
3939 _selectMonthYear: function(id, select, period) { | |
3940 var target = $(id), | |
3941 inst = this._getInst(target[0]); | |
3942 | |
3943 inst["selected" + (period === "M" ? "Month" : "Year")] = | |
3944 inst["draw" + (period === "M" ? "Month" : "Year")] = | |
3945 parseInt(select.options[select.selectedIndex].value,10); | |
3946 | |
3947 this._notifyChange(inst); | |
3948 this._adjustDate(target); | |
3949 }, | |
3950 | |
3951 /* Action for selecting a day. */ | |
3952 _selectDay: function(id, month, year, td) { | |
3953 var inst, | |
3954 target = $(id); | |
3955 | |
3956 if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) { | |
3957 return; | |
3958 } | |
3959 | |
3960 inst = this._getInst(target[0]); | |
3961 inst.selectedDay = inst.currentDay = $("a", td).html(); | |
3962 inst.selectedMonth = inst.currentMonth = month; | |
3963 inst.selectedYear = inst.currentYear = year; | |
3964 this._selectDate(id, this._formatDate(inst, | |
3965 inst.currentDay, inst.currentMonth, inst.currentYear)); | |
3966 }, | |
3967 | |
3968 /* Erase the input field and hide the date picker. */ | |
3969 _clearDate: function(id) { | |
3970 var target = $(id); | |
3971 this._selectDate(target, ""); | |
3972 }, | |
3973 | |
3974 /* Update the input field with the selected date. */ | |
3975 _selectDate: function(id, dateStr) { | |
3976 var onSelect, | |
3977 target = $(id), | |
3978 inst = this._getInst(target[0]); | |
3979 | |
3980 dateStr = (dateStr != null ? dateStr : this._formatDate(inst)); | |
3981 if (inst.input) { | |
3982 inst.input.val(dateStr); | |
3983 } | |
3984 this._updateAlternate(inst); | |
3985 | |
3986 onSelect = this._get(inst, "onSelect"); | |
3987 if (onSelect) { | |
3988 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback | |
3989 } else if (inst.input) { | |
3990 inst.input.trigger("change"); // fire the change event | |
3991 } | |
3992 | |
3993 if (inst.inline){ | |
3994 this._updateDatepicker(inst); | |
3995 } else { | |
3996 this._hideDatepicker(); | |
3997 this._lastInput = inst.input[0]; | |
3998 if (typeof(inst.input[0]) !== "object") { | |
3999 inst.input.focus(); // restore focus | |
4000 } | |
4001 this._lastInput = null; | |
4002 } | |
4003 }, | |
4004 | |
4005 /* Update any alternate field to synchronise with the main field. */ | |
4006 _updateAlternate: function(inst) { | |
4007 var altFormat, date, dateStr, | |
4008 altField = this._get(inst, "altField"); | |
4009 | |
4010 if (altField) { // update alternate field too | |
4011 altFormat = this._get(inst, "altFormat") || this._get(inst, "dateFormat"); | |
4012 date = this._getDate(inst); | |
4013 dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst)); | |
4014 $(altField).each(function() { $(this).val(dateStr); }); | |
4015 } | |
4016 }, | |
4017 | |
4018 /* Set as beforeShowDay function to prevent selection of weekends. | |
4019 * @param date Date - the date to customise | |
4020 * @return [boolean, string] - is this date selectable?, what is its CSS class? | |
4021 */ | |
4022 noWeekends: function(date) { | |
4023 var day = date.getDay(); | |
4024 return [(day > 0 && day < 6), ""]; | |
4025 }, | |
4026 | |
4027 /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition. | |
4028 * @param date Date - the date to get the week for | |
4029 * @return number - the number of the week within the year that contains this date | |
4030 */ | |
4031 iso8601Week: function(date) { | |
4032 var time, | |
4033 checkDate = new Date(date.getTime()); | |
4034 | |
4035 // Find Thursday of this week starting on Monday | |
4036 checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); | |
4037 | |
4038 time = checkDate.getTime(); | |
4039 checkDate.setMonth(0); // Compare with Jan 1 | |
4040 checkDate.setDate(1); | |
4041 return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1; | |
4042 }, | |
4043 | |
4044 /* Parse a string value into a date object. | |
4045 * See formatDate below for the possible formats. | |
4046 * | |
4047 * @param format string - the expected format of the date | |
4048 * @param value string - the date in the above format | |
4049 * @param settings Object - attributes include: | |
4050 * shortYearCutoff number - the cutoff year for determining the century (optional) | |
4051 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) | |
4052 * dayNames string[7] - names of the days from Sunday (optional) | |
4053 * monthNamesShort string[12] - abbreviated names of the months (optional) | |
4054 * monthNames string[12] - names of the months (optional) | |
4055 * @return Date - the extracted date value or null if value is blank | |
4056 */ | |
4057 parseDate: function (format, value, settings) { | |
4058 if (format == null || value == null) { | |
4059 throw "Invalid arguments"; | |
4060 } | |
4061 | |
4062 value = (typeof value === "object" ? value.toString() : value + ""); | |
4063 if (value === "") { | |
4064 return null; | |
4065 } | |
4066 | |
4067 var iFormat, dim, extra, | |
4068 iValue = 0, | |
4069 shortYearCutoffTemp = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff, | |
4070 shortYearCutoff = (typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp : | |
4071 new Date().getFullYear() % 100 + parseInt(shortYearCutoffTemp, 10)), | |
4072 dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort, | |
4073 dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames, | |
4074 monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort, | |
4075 monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames, | |
4076 year = -1, | |
4077 month = -1, | |
4078 day = -1, | |
4079 doy = -1, | |
4080 literal = false, | |
4081 date, | |
4082 // Check whether a format character is doubled | |
4083 lookAhead = function(match) { | |
4084 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match); | |
4085 if (matches) { | |
4086 iFormat++; | |
4087 } | |
4088 return matches; | |
4089 }, | |
4090 // Extract a number from the string value | |
4091 getNumber = function(match) { | |
4092 var isDoubled = lookAhead(match), | |
4093 size = (match === "@" ? 14 : (match === "!" ? 20 : | |
4094 (match === "y" && isDoubled ? 4 : (match === "o" ? 3 : 2)))), | |
4095 digits = new RegExp("^\\d{1," + size + "}"), | |
4096 num = value.substring(iValue).match(digits); | |
4097 if (!num) { | |
4098 throw "Missing number at position " + iValue; | |
4099 } | |
4100 iValue += num[0].length; | |
4101 return parseInt(num[0], 10); | |
4102 }, | |
4103 // Extract a name from the string value and convert to an index | |
4104 getName = function(match, shortNames, longNames) { | |
4105 var index = -1, | |
4106 names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) { | |
4107 return [ [k, v] ]; | |
4108 }).sort(function (a, b) { | |
4109 return -(a[1].length - b[1].length); | |
4110 }); | |
4111 | |
4112 $.each(names, function (i, pair) { | |
4113 var name = pair[1]; | |
4114 if (value.substr(iValue, name.length).toLowerCase() === name.toLowerCase()) { | |
4115 index = pair[0]; | |
4116 iValue += name.length; | |
4117 return false; | |
4118 } | |
4119 }); | |
4120 if (index !== -1) { | |
4121 return index + 1; | |
4122 } else { | |
4123 throw "Unknown name at position " + iValue; | |
4124 } | |
4125 }, | |
4126 // Confirm that a literal character matches the string value | |
4127 checkLiteral = function() { | |
4128 if (value.charAt(iValue) !== format.charAt(iFormat)) { | |
4129 throw "Unexpected literal at position " + iValue; | |
4130 } | |
4131 iValue++; | |
4132 }; | |
4133 | |
4134 for (iFormat = 0; iFormat < format.length; iFormat++) { | |
4135 if (literal) { | |
4136 if (format.charAt(iFormat) === "'" && !lookAhead("'")) { | |
4137 literal = false; | |
4138 } else { | |
4139 checkLiteral(); | |
4140 } | |
4141 } else { | |
4142 switch (format.charAt(iFormat)) { | |
4143 case "d": | |
4144 day = getNumber("d"); | |
4145 break; | |
4146 case "D": | |
4147 getName("D", dayNamesShort, dayNames); | |
4148 break; | |
4149 case "o": | |
4150 doy = getNumber("o"); | |
4151 break; | |
4152 case "m": | |
4153 month = getNumber("m"); | |
4154 break; | |
4155 case "M": | |
4156 month = getName("M", monthNamesShort, monthNames); | |
4157 break; | |
4158 case "y": | |
4159 year = getNumber("y"); | |
4160 break; | |
4161 case "@": | |
4162 date = new Date(getNumber("@")); | |
4163 year = date.getFullYear(); | |
4164 month = date.getMonth() + 1; | |
4165 day = date.getDate(); | |
4166 break; | |
4167 case "!": | |
4168 date = new Date((getNumber("!") - this._ticksTo1970) / 10000); | |
4169 year = date.getFullYear(); | |
4170 month = date.getMonth() + 1; | |
4171 day = date.getDate(); | |
4172 break; | |
4173 case "'": | |
4174 if (lookAhead("'")){ | |
4175 checkLiteral(); | |
4176 } else { | |
4177 literal = true; | |
4178 } | |
4179 break; | |
4180 default: | |
4181 checkLiteral(); | |
4182 } | |
4183 } | |
4184 } | |
4185 | |
4186 if (iValue < value.length){ | |
4187 extra = value.substr(iValue); | |
4188 if (!/^\s+/.test(extra)) { | |
4189 throw "Extra/unparsed characters found in date: " + extra; | |
4190 } | |
4191 } | |
4192 | |
4193 if (year === -1) { | |
4194 year = new Date().getFullYear(); | |
4195 } else if (year < 100) { | |
4196 year += new Date().getFullYear() - new Date().getFullYear() % 100 + | |
4197 (year <= shortYearCutoff ? 0 : -100); | |
4198 } | |
4199 | |
4200 if (doy > -1) { | |
4201 month = 1; | |
4202 day = doy; | |
4203 do { | |
4204 dim = this._getDaysInMonth(year, month - 1); | |
4205 if (day <= dim) { | |
4206 break; | |
4207 } | |
4208 month++; | |
4209 day -= dim; | |
4210 } while (true); | |
4211 } | |
4212 | |
4213 date = this._daylightSavingAdjust(new Date(year, month - 1, day)); | |
4214 if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) { | |
4215 throw "Invalid date"; // E.g. 31/02/00 | |
4216 } | |
4217 return date; | |
4218 }, | |
4219 | |
4220 /* Standard date formats. */ | |
4221 ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601) | |
4222 COOKIE: "D, dd M yy", | |
4223 ISO_8601: "yy-mm-dd", | |
4224 RFC_822: "D, d M y", | |
4225 RFC_850: "DD, dd-M-y", | |
4226 RFC_1036: "D, d M y", | |
4227 RFC_1123: "D, d M yy", | |
4228 RFC_2822: "D, d M yy", | |
4229 RSS: "D, d M y", // RFC 822 | |
4230 TICKS: "!", | |
4231 TIMESTAMP: "@", | |
4232 W3C: "yy-mm-dd", // ISO 8601 | |
4233 | |
4234 _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) + | |
4235 Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000), | |
4236 | |
4237 /* Format a date object into a string value. | |
4238 * The format can be combinations of the following: | |
4239 * d - day of month (no leading zero) | |
4240 * dd - day of month (two digit) | |
4241 * o - day of year (no leading zeros) | |
4242 * oo - day of year (three digit) | |
4243 * D - day name short | |
4244 * DD - day name long | |
4245 * m - month of year (no leading zero) | |
4246 * mm - month of year (two digit) | |
4247 * M - month name short | |
4248 * MM - month name long | |
4249 * y - year (two digit) | |
4250 * yy - year (four digit) | |
4251 * @ - Unix timestamp (ms since 01/01/1970) | |
4252 * ! - Windows ticks (100ns since 01/01/0001) | |
4253 * "..." - literal text | |
4254 * '' - single quote | |
4255 * | |
4256 * @param format string - the desired format of the date | |
4257 * @param date Date - the date value to format | |
4258 * @param settings Object - attributes include: | |
4259 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) | |
4260 * dayNames string[7] - names of the days from Sunday (optional) | |
4261 * monthNamesShort string[12] - abbreviated names of the months (optional) | |
4262 * monthNames string[12] - names of the months (optional) | |
4263 * @return string - the date in the above format | |
4264 */ | |
4265 formatDate: function (format, date, settings) { | |
4266 if (!date) { | |
4267 return ""; | |
4268 } | |
4269 | |
4270 var iFormat, | |
4271 dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort, | |
4272 dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames, | |
4273 monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort, | |
4274 monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames, | |
4275 // Check whether a format character is doubled | |
4276 lookAhead = function(match) { | |
4277 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match); | |
4278 if (matches) { | |
4279 iFormat++; | |
4280 } | |
4281 return matches; | |
4282 }, | |
4283 // Format a number, with leading zero if necessary | |
4284 formatNumber = function(match, value, len) { | |
4285 var num = "" + value; | |
4286 if (lookAhead(match)) { | |
4287 while (num.length < len) { | |
4288 num = "0" + num; | |
4289 } | |
4290 } | |
4291 return num; | |
4292 }, | |
4293 // Format a name, short or long as requested | |
4294 formatName = function(match, value, shortNames, longNames) { | |
4295 return (lookAhead(match) ? longNames[value] : shortNames[value]); | |
4296 }, | |
4297 output = "", | |
4298 literal = false; | |
4299 | |
4300 if (date) { | |
4301 for (iFormat = 0; iFormat < format.length; iFormat++) { | |
4302 if (literal) { | |
4303 if (format.charAt(iFormat) === "'" && !lookAhead("'")) { | |
4304 literal = false; | |
4305 } else { | |
4306 output += format.charAt(iFormat); | |
4307 } | |
4308 } else { | |
4309 switch (format.charAt(iFormat)) { | |
4310 case "d": | |
4311 output += formatNumber("d", date.getDate(), 2); | |
4312 break; | |
4313 case "D": | |
4314 output += formatName("D", date.getDay(), dayNamesShort, dayNames); | |
4315 break; | |
4316 case "o": | |
4317 output += formatNumber("o", | |
4318 Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3); | |
4319 break; | |
4320 case "m": | |
4321 output += formatNumber("m", date.getMonth() + 1, 2); | |
4322 break; | |
4323 case "M": | |
4324 output += formatName("M", date.getMonth(), monthNamesShort, monthNames); | |
4325 break; | |
4326 case "y": | |
4327 output += (lookAhead("y") ? date.getFullYear() : | |
4328 (date.getYear() % 100 < 10 ? "0" : "") + date.getYear() % 100); | |
4329 break; | |
4330 case "@": | |
4331 output += date.getTime(); | |
4332 break; | |
4333 case "!": | |
4334 output += date.getTime() * 10000 + this._ticksTo1970; | |
4335 break; | |
4336 case "'": | |
4337 if (lookAhead("'")) { | |
4338 output += "'"; | |
4339 } else { | |
4340 literal = true; | |
4341 } | |
4342 break; | |
4343 default: | |
4344 output += format.charAt(iFormat); | |
4345 } | |
4346 } | |
4347 } | |
4348 } | |
4349 return output; | |
4350 }, | |
4351 | |
4352 /* Extract all possible characters from the date format. */ | |
4353 _possibleChars: function (format) { | |
4354 var iFormat, | |
4355 chars = "", | |
4356 literal = false, | |
4357 // Check whether a format character is doubled | |
4358 lookAhead = function(match) { | |
4359 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match); | |
4360 if (matches) { | |
4361 iFormat++; | |
4362 } | |
4363 return matches; | |
4364 }; | |
4365 | |
4366 for (iFormat = 0; iFormat < format.length; iFormat++) { | |
4367 if (literal) { | |
4368 if (format.charAt(iFormat) === "'" && !lookAhead("'")) { | |
4369 literal = false; | |
4370 } else { | |
4371 chars += format.charAt(iFormat); | |
4372 } | |
4373 } else { | |
4374 switch (format.charAt(iFormat)) { | |
4375 case "d": case "m": case "y": case "@": | |
4376 chars += "0123456789"; | |
4377 break; | |
4378 case "D": case "M": | |
4379 return null; // Accept anything | |
4380 case "'": | |
4381 if (lookAhead("'")) { | |
4382 chars += "'"; | |
4383 } else { | |
4384 literal = true; | |
4385 } | |
4386 break; | |
4387 default: | |
4388 chars += format.charAt(iFormat); | |
4389 } | |
4390 } | |
4391 } | |
4392 return chars; | |
4393 }, | |
4394 | |
4395 /* Get a setting value, defaulting if necessary. */ | |
4396 _get: function(inst, name) { | |
4397 return inst.settings[name] !== undefined ? | |
4398 inst.settings[name] : this._defaults[name]; | |
4399 }, | |
4400 | |
4401 /* Parse existing date and initialise date picker. */ | |
4402 _setDateFromField: function(inst, noDefault) { | |
4403 if (inst.input.val() === inst.lastVal) { | |
4404 return; | |
4405 } | |
4406 | |
4407 var dateFormat = this._get(inst, "dateFormat"), | |
4408 dates = inst.lastVal = inst.input ? inst.input.val() : null, | |
4409 defaultDate = this._getDefaultDate(inst), | |
4410 date = defaultDate, | |
4411 settings = this._getFormatConfig(inst); | |
4412 | |
4413 try { | |
4414 date = this.parseDate(dateFormat, dates, settings) || defaultDate; | |
4415 } catch (event) { | |
4416 dates = (noDefault ? "" : dates); | |
4417 } | |
4418 inst.selectedDay = date.getDate(); | |
4419 inst.drawMonth = inst.selectedMonth = date.getMonth(); | |
4420 inst.drawYear = inst.selectedYear = date.getFullYear(); | |
4421 inst.currentDay = (dates ? date.getDate() : 0); | |
4422 inst.currentMonth = (dates ? date.getMonth() : 0); | |
4423 inst.currentYear = (dates ? date.getFullYear() : 0); | |
4424 this._adjustInstDate(inst); | |
4425 }, | |
4426 | |
4427 /* Retrieve the default date shown on opening. */ | |
4428 _getDefaultDate: function(inst) { | |
4429 return this._restrictMinMax(inst, | |
4430 this._determineDate(inst, this._get(inst, "defaultDate"), new Date())); | |
4431 }, | |
4432 | |
4433 /* A date may be specified as an exact value or a relative one. */ | |
4434 _determineDate: function(inst, date, defaultDate) { | |
4435 var offsetNumeric = function(offset) { | |
4436 var date = new Date(); | |
4437 date.setDate(date.getDate() + offset); | |
4438 return date; | |
4439 }, | |
4440 offsetString = function(offset) { | |
4441 try { | |
4442 return $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"), | |
4443 offset, $.datepicker._getFormatConfig(inst)); | |
4444 } | |
4445 catch (e) { | |
4446 // Ignore | |
4447 } | |
4448 | |
4449 var date = (offset.toLowerCase().match(/^c/) ? | |
4450 $.datepicker._getDate(inst) : null) || new Date(), | |
4451 year = date.getFullYear(), | |
4452 month = date.getMonth(), | |
4453 day = date.getDate(), | |
4454 pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g, | |
4455 matches = pattern.exec(offset); | |
4456 | |
4457 while (matches) { | |
4458 switch (matches[2] || "d") { | |
4459 case "d" : case "D" : | |
4460 day += parseInt(matches[1],10); break; | |
4461 case "w" : case "W" : | |
4462 day += parseInt(matches[1],10) * 7; break; | |
4463 case "m" : case "M" : | |
4464 month += parseInt(matches[1],10); | |
4465 day = Math.min(day, $.datepicker._getDaysInMonth(year, month)); | |
4466 break; | |
4467 case "y": case "Y" : | |
4468 year += parseInt(matches[1],10); | |
4469 day = Math.min(day, $.datepicker._getDaysInMonth(year, month)); | |
4470 break; | |
4471 } | |
4472 matches = pattern.exec(offset); | |
4473 } | |
4474 return new Date(year, month, day); | |
4475 }, | |
4476 newDate = (date == null || date === "" ? defaultDate : (typeof date === "string" ? offsetString(date) : | |
4477 (typeof date === "number" ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime())))); | |
4478 | |
4479 newDate = (newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate); | |
4480 if (newDate) { | |
4481 newDate.setHours(0); | |
4482 newDate.setMinutes(0); | |
4483 newDate.setSeconds(0); | |
4484 newDate.setMilliseconds(0); | |
4485 } | |
4486 return this._daylightSavingAdjust(newDate); | |
4487 }, | |
4488 | |
4489 /* Handle switch to/from daylight saving. | |
4490 * Hours may be non-zero on daylight saving cut-over: | |
4491 * > 12 when midnight changeover, but then cannot generate | |
4492 * midnight datetime, so jump to 1AM, otherwise reset. | |
4493 * @param date (Date) the date to check | |
4494 * @return (Date) the corrected date | |
4495 */ | |
4496 _daylightSavingAdjust: function(date) { | |
4497 if (!date) { | |
4498 return null; | |
4499 } | |
4500 date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0); | |
4501 return date; | |
4502 }, | |
4503 | |
4504 /* Set the date(s) directly. */ | |
4505 _setDate: function(inst, date, noChange) { | |
4506 var clear = !date, | |
4507 origMonth = inst.selectedMonth, | |
4508 origYear = inst.selectedYear, | |
4509 newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date())); | |
4510 | |
4511 inst.selectedDay = inst.currentDay = newDate.getDate(); | |
4512 inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth(); | |
4513 inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear(); | |
4514 if ((origMonth !== inst.selectedMonth || origYear !== inst.selectedYear) && !noChange) { | |
4515 this._notifyChange(inst); | |
4516 } | |
4517 this._adjustInstDate(inst); | |
4518 if (inst.input) { | |
4519 inst.input.val(clear ? "" : this._formatDate(inst)); | |
4520 } | |
4521 }, | |
4522 | |
4523 /* Retrieve the date(s) directly. */ | |
4524 _getDate: function(inst) { | |
4525 var startDate = (!inst.currentYear || (inst.input && inst.input.val() === "") ? null : | |
4526 this._daylightSavingAdjust(new Date( | |
4527 inst.currentYear, inst.currentMonth, inst.currentDay))); | |
4528 return startDate; | |
4529 }, | |
4530 | |
4531 /* Attach the onxxx handlers. These are declared statically so | |
4532 * they work with static code transformers like Caja. | |
4533 */ | |
4534 _attachHandlers: function(inst) { | |
4535 var stepMonths = this._get(inst, "stepMonths"), | |
4536 id = "#" + inst.id.replace( /\\\\/g, "\\" ); | |
4537 inst.dpDiv.find("[data-handler]").map(function () { | |
4538 var handler = { | |
4539 prev: function () { | |
4540 $.datepicker._adjustDate(id, -stepMonths, "M"); | |
4541 }, | |
4542 next: function () { | |
4543 $.datepicker._adjustDate(id, +stepMonths, "M"); | |
4544 }, | |
4545 hide: function () { | |
4546 $.datepicker._hideDatepicker(); | |
4547 }, | |
4548 today: function () { | |
4549 $.datepicker._gotoToday(id); | |
4550 }, | |
4551 selectDay: function () { | |
4552 $.datepicker._selectDay(id, +this.getAttribute("data-month"), +this.getAttribute("data-year"), this); | |
4553 return false; | |
4554 }, | |
4555 selectMonth: function () { | |
4556 $.datepicker._selectMonthYear(id, this, "M"); | |
4557 return false; | |
4558 }, | |
4559 selectYear: function () { | |
4560 $.datepicker._selectMonthYear(id, this, "Y"); | |
4561 return false; | |
4562 } | |
4563 }; | |
4564 $(this).bind(this.getAttribute("data-event"), handler[this.getAttribute("data-handler")]); | |
4565 }); | |
4566 }, | |
4567 | |
4568 /* Generate the HTML for the current state of the date picker. */ | |
4569 _generateHTML: function(inst) { | |
4570 var maxDraw, prevText, prev, nextText, next, currentText, gotoDate, | |
4571 controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin, | |
4572 monthNames, monthNamesShort, beforeShowDay, showOtherMonths, | |
4573 selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate, | |
4574 cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows, | |
4575 printDate, dRow, tbody, daySettings, otherMonth, unselectable, | |
4576 tempDate = new Date(), | |
4577 today = this._daylightSavingAdjust( | |
4578 new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate())), // clear time | |
4579 isRTL = this._get(inst, "isRTL"), | |
4580 showButtonPanel = this._get(inst, "showButtonPanel"), | |
4581 hideIfNoPrevNext = this._get(inst, "hideIfNoPrevNext"), | |
4582 navigationAsDateFormat = this._get(inst, "navigationAsDateFormat"), | |
4583 numMonths = this._getNumberOfMonths(inst), | |
4584 showCurrentAtPos = this._get(inst, "showCurrentAtPos"), | |
4585 stepMonths = this._get(inst, "stepMonths"), | |
4586 isMultiMonth = (numMonths[0] !== 1 || numMonths[1] !== 1), | |
4587 currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) : | |
4588 new Date(inst.currentYear, inst.currentMonth, inst.currentDay))), | |
4589 minDate = this._getMinMaxDate(inst, "min"), | |
4590 maxDate = this._getMinMaxDate(inst, "max"), | |
4591 drawMonth = inst.drawMonth - showCurrentAtPos, | |
4592 drawYear = inst.drawYear; | |
4593 | |
4594 if (drawMonth < 0) { | |
4595 drawMonth += 12; | |
4596 drawYear--; | |
4597 } | |
4598 if (maxDate) { | |
4599 maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(), | |
4600 maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate())); | |
4601 maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw); | |
4602 while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) { | |
4603 drawMonth--; | |
4604 if (drawMonth < 0) { | |
4605 drawMonth = 11; | |
4606 drawYear--; | |
4607 } | |
4608 } | |
4609 } | |
4610 inst.drawMonth = drawMonth; | |
4611 inst.drawYear = drawYear; | |
4612 | |
4613 prevText = this._get(inst, "prevText"); | |
4614 prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText, | |
4615 this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)), | |
4616 this._getFormatConfig(inst))); | |
4617 | |
4618 prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ? | |
4619 "<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'" + | |
4620 " title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>" : | |
4621 (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>")); | |
4622 | |
4623 nextText = this._get(inst, "nextText"); | |
4624 nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText, | |
4625 this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)), | |
4626 this._getFormatConfig(inst))); | |
4627 | |
4628 next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ? | |
4629 "<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'" + | |
4630 " title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>" : | |
4631 (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>")); | |
4632 | |
4633 currentText = this._get(inst, "currentText"); | |
4634 gotoDate = (this._get(inst, "gotoCurrent") && inst.currentDay ? currentDate : today); | |
4635 currentText = (!navigationAsDateFormat ? currentText : | |
4636 this.formatDate(currentText, gotoDate, this._getFormatConfig(inst))); | |
4637 | |
4638 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'>" + | |
4639 this._get(inst, "closeText") + "</button>" : ""); | |
4640 | |
4641 buttonPanel = (showButtonPanel) ? "<div class='ui-datepicker-buttonpane ui-widget-content'>" + (isRTL ? controls : "") + | |
4642 (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'" + | |
4643 ">" + currentText + "</button>" : "") + (isRTL ? "" : controls) + "</div>" : ""; | |
4644 | |
4645 firstDay = parseInt(this._get(inst, "firstDay"),10); | |
4646 firstDay = (isNaN(firstDay) ? 0 : firstDay); | |
4647 | |
4648 showWeek = this._get(inst, "showWeek"); | |
4649 dayNames = this._get(inst, "dayNames"); | |
4650 dayNamesMin = this._get(inst, "dayNamesMin"); | |
4651 monthNames = this._get(inst, "monthNames"); | |
4652 monthNamesShort = this._get(inst, "monthNamesShort"); | |
4653 beforeShowDay = this._get(inst, "beforeShowDay"); | |
4654 showOtherMonths = this._get(inst, "showOtherMonths"); | |
4655 selectOtherMonths = this._get(inst, "selectOtherMonths"); | |
4656 defaultDate = this._getDefaultDate(inst); | |
4657 html = ""; | |
4658 dow; | |
4659 for (row = 0; row < numMonths[0]; row++) { | |
4660 group = ""; | |
4661 this.maxRows = 4; | |
4662 for (col = 0; col < numMonths[1]; col++) { | |
4663 selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay)); | |
4664 cornerClass = " ui-corner-all"; | |
4665 calender = ""; | |
4666 if (isMultiMonth) { | |
4667 calender += "<div class='ui-datepicker-group"; | |
4668 if (numMonths[1] > 1) { | |
4669 switch (col) { | |
4670 case 0: calender += " ui-datepicker-group-first"; | |
4671 cornerClass = " ui-corner-" + (isRTL ? "right" : "left"); break; | |
4672 case numMonths[1]-1: calender += " ui-datepicker-group-last"; | |
4673 cornerClass = " ui-corner-" + (isRTL ? "left" : "right"); break; | |
4674 default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break; | |
4675 } | |
4676 } | |
4677 calender += "'>"; | |
4678 } | |
4679 calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" + | |
4680 (/all|left/.test(cornerClass) && row === 0 ? (isRTL ? next : prev) : "") + | |
4681 (/all|right/.test(cornerClass) && row === 0 ? (isRTL ? prev : next) : "") + | |
4682 this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate, | |
4683 row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers | |
4684 "</div><table class='ui-datepicker-calendar'><thead>" + | |
4685 "<tr>"; | |
4686 thead = (showWeek ? "<th class='ui-datepicker-week-col'>" + this._get(inst, "weekHeader") + "</th>" : ""); | |
4687 for (dow = 0; dow < 7; dow++) { // days of the week | |
4688 day = (dow + firstDay) % 7; | |
4689 thead += "<th" + ((dow + firstDay + 6) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "") + ">" + | |
4690 "<span title='" + dayNames[day] + "'>" + dayNamesMin[day] + "</span></th>"; | |
4691 } | |
4692 calender += thead + "</tr></thead><tbody>"; | |
4693 daysInMonth = this._getDaysInMonth(drawYear, drawMonth); | |
4694 if (drawYear === inst.selectedYear && drawMonth === inst.selectedMonth) { | |
4695 inst.selectedDay = Math.min(inst.selectedDay, daysInMonth); | |
4696 } | |
4697 leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7; | |
4698 curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate | |
4699 numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043) | |
4700 this.maxRows = numRows; | |
4701 printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays)); | |
4702 for (dRow = 0; dRow < numRows; dRow++) { // create date picker rows | |
4703 calender += "<tr>"; | |
4704 tbody = (!showWeek ? "" : "<td class='ui-datepicker-week-col'>" + | |
4705 this._get(inst, "calculateWeek")(printDate) + "</td>"); | |
4706 for (dow = 0; dow < 7; dow++) { // create date picker days | |
4707 daySettings = (beforeShowDay ? | |
4708 beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, ""]); | |
4709 otherMonth = (printDate.getMonth() !== drawMonth); | |
4710 unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] || | |
4711 (minDate && printDate < minDate) || (maxDate && printDate > maxDate); | |
4712 tbody += "<td class='" + | |
4713 ((dow + firstDay + 6) % 7 >= 5 ? " ui-datepicker-week-end" : "") + // highlight weekends | |
4714 (otherMonth ? " ui-datepicker-other-month" : "") + // highlight days from other months | |
4715 ((printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent) || // user pressed key | |
4716 (defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime()) ? | |
4717 // or defaultDate is current printedDate and defaultDate is selectedDate | |
4718 " " + this._dayOverClass : "") + // highlight selected day | |
4719 (unselectable ? " " + this._unselectableClass + " ui-state-disabled": "") + // highlight unselectable days | |
4720 (otherMonth && !showOtherMonths ? "" : " " + daySettings[1] + // highlight custom dates | |
4721 (printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "") + // highlight selected day | |
4722 (printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "")) + "'" + // highlight today (if different) | |
4723 ((!otherMonth || showOtherMonths) && daySettings[2] ? " title='" + daySettings[2].replace(/'/g, "'") + "'" : "") + // cell title | |
4724 (unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'") + ">" + // actions | |
4725 (otherMonth && !showOtherMonths ? " " : // display for other months | |
4726 (unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" + | |
4727 (printDate.getTime() === today.getTime() ? " ui-state-highlight" : "") + | |
4728 (printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "") + // highlight selected day | |
4729 (otherMonth ? " ui-priority-secondary" : "") + // distinguish dates from other months | |
4730 "' href='#'>" + printDate.getDate() + "</a>")) + "</td>"; // display selectable date | |
4731 printDate.setDate(printDate.getDate() + 1); | |
4732 printDate = this._daylightSavingAdjust(printDate); | |
4733 } | |
4734 calender += tbody + "</tr>"; | |
4735 } | |
4736 drawMonth++; | |
4737 if (drawMonth > 11) { | |
4738 drawMonth = 0; | |
4739 drawYear++; | |
4740 } | |
4741 calender += "</tbody></table>" + (isMultiMonth ? "</div>" + | |
4742 ((numMonths[0] > 0 && col === numMonths[1]-1) ? "<div class='ui-datepicker-row-break'></div>" : "") : ""); | |
4743 group += calender; | |
4744 } | |
4745 html += group; | |
4746 } | |
4747 html += buttonPanel; | |
4748 inst._keyEvent = false; | |
4749 return html; | |
4750 }, | |
4751 | |
4752 /* Generate the month and year header. */ | |
4753 _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate, | |
4754 secondary, monthNames, monthNamesShort) { | |
4755 | |
4756 var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear, | |
4757 changeMonth = this._get(inst, "changeMonth"), | |
4758 changeYear = this._get(inst, "changeYear"), | |
4759 showMonthAfterYear = this._get(inst, "showMonthAfterYear"), | |
4760 html = "<div class='ui-datepicker-title'>", | |
4761 monthHtml = ""; | |
4762 | |
4763 // month selection | |
4764 if (secondary || !changeMonth) { | |
4765 monthHtml += "<span class='ui-datepicker-month'>" + monthNames[drawMonth] + "</span>"; | |
4766 } else { | |
4767 inMinYear = (minDate && minDate.getFullYear() === drawYear); | |
4768 inMaxYear = (maxDate && maxDate.getFullYear() === drawYear); | |
4769 monthHtml += "<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>"; | |
4770 for ( month = 0; month < 12; month++) { | |
4771 if ((!inMinYear || month >= minDate.getMonth()) && (!inMaxYear || month <= maxDate.getMonth())) { | |
4772 monthHtml += "<option value='" + month + "'" + | |
4773 (month === drawMonth ? " selected='selected'" : "") + | |
4774 ">" + monthNamesShort[month] + "</option>"; | |
4775 } | |
4776 } | |
4777 monthHtml += "</select>"; | |
4778 } | |
4779 | |
4780 if (!showMonthAfterYear) { | |
4781 html += monthHtml + (secondary || !(changeMonth && changeYear) ? " " : ""); | |
4782 } | |
4783 | |
4784 // year selection | |
4785 if ( !inst.yearshtml ) { | |
4786 inst.yearshtml = ""; | |
4787 if (secondary || !changeYear) { | |
4788 html += "<span class='ui-datepicker-year'>" + drawYear + "</span>"; | |
4789 } else { | |
4790 // determine range of years to display | |
4791 years = this._get(inst, "yearRange").split(":"); | |
4792 thisYear = new Date().getFullYear(); | |
4793 determineYear = function(value) { | |
4794 var year = (value.match(/c[+\-].*/) ? drawYear + parseInt(value.substring(1), 10) : | |
4795 (value.match(/[+\-].*/) ? thisYear + parseInt(value, 10) : | |
4796 parseInt(value, 10))); | |
4797 return (isNaN(year) ? thisYear : year); | |
4798 }; | |
4799 year = determineYear(years[0]); | |
4800 endYear = Math.max(year, determineYear(years[1] || "")); | |
4801 year = (minDate ? Math.max(year, minDate.getFullYear()) : year); | |
4802 endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear); | |
4803 inst.yearshtml += "<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>"; | |
4804 for (; year <= endYear; year++) { | |
4805 inst.yearshtml += "<option value='" + year + "'" + | |
4806 (year === drawYear ? " selected='selected'" : "") + | |
4807 ">" + year + "</option>"; | |
4808 } | |
4809 inst.yearshtml += "</select>"; | |
4810 | |
4811 html += inst.yearshtml; | |
4812 inst.yearshtml = null; | |
4813 } | |
4814 } | |
4815 | |
4816 html += this._get(inst, "yearSuffix"); | |
4817 if (showMonthAfterYear) { | |
4818 html += (secondary || !(changeMonth && changeYear) ? " " : "") + monthHtml; | |
4819 } | |
4820 html += "</div>"; // Close datepicker_header | |
4821 return html; | |
4822 }, | |
4823 | |
4824 /* Adjust one of the date sub-fields. */ | |
4825 _adjustInstDate: function(inst, offset, period) { | |
4826 var year = inst.drawYear + (period === "Y" ? offset : 0), | |
4827 month = inst.drawMonth + (period === "M" ? offset : 0), | |
4828 day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + (period === "D" ? offset : 0), | |
4829 date = this._restrictMinMax(inst, this._daylightSavingAdjust(new Date(year, month, day))); | |
4830 | |
4831 inst.selectedDay = date.getDate(); | |
4832 inst.drawMonth = inst.selectedMonth = date.getMonth(); | |
4833 inst.drawYear = inst.selectedYear = date.getFullYear(); | |
4834 if (period === "M" || period === "Y") { | |
4835 this._notifyChange(inst); | |
4836 } | |
4837 }, | |
4838 | |
4839 /* Ensure a date is within any min/max bounds. */ | |
4840 _restrictMinMax: function(inst, date) { | |
4841 var minDate = this._getMinMaxDate(inst, "min"), | |
4842 maxDate = this._getMinMaxDate(inst, "max"), | |
4843 newDate = (minDate && date < minDate ? minDate : date); | |
4844 return (maxDate && newDate > maxDate ? maxDate : newDate); | |
4845 }, | |
4846 | |
4847 /* Notify change of month/year. */ | |
4848 _notifyChange: function(inst) { | |
4849 var onChange = this._get(inst, "onChangeMonthYear"); | |
4850 if (onChange) { | |
4851 onChange.apply((inst.input ? inst.input[0] : null), | |
4852 [inst.selectedYear, inst.selectedMonth + 1, inst]); | |
4853 } | |
4854 }, | |
4855 | |
4856 /* Determine the number of months to show. */ | |
4857 _getNumberOfMonths: function(inst) { | |
4858 var numMonths = this._get(inst, "numberOfMonths"); | |
4859 return (numMonths == null ? [1, 1] : (typeof numMonths === "number" ? [1, numMonths] : numMonths)); | |
4860 }, | |
4861 | |
4862 /* Determine the current maximum date - ensure no time components are set. */ | |
4863 _getMinMaxDate: function(inst, minMax) { | |
4864 return this._determineDate(inst, this._get(inst, minMax + "Date"), null); | |
4865 }, | |
4866 | |
4867 /* Find the number of days in a given month. */ | |
4868 _getDaysInMonth: function(year, month) { | |
4869 return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate(); | |
4870 }, | |
4871 | |
4872 /* Find the day of the week of the first of a month. */ | |
4873 _getFirstDayOfMonth: function(year, month) { | |
4874 return new Date(year, month, 1).getDay(); | |
4875 }, | |
4876 | |
4877 /* Determines if we should allow a "next/prev" month display change. */ | |
4878 _canAdjustMonth: function(inst, offset, curYear, curMonth) { | |
4879 var numMonths = this._getNumberOfMonths(inst), | |
4880 date = this._daylightSavingAdjust(new Date(curYear, | |
4881 curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1)); | |
4882 | |
4883 if (offset < 0) { | |
4884 date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth())); | |
4885 } | |
4886 return this._isInRange(inst, date); | |
4887 }, | |
4888 | |
4889 /* Is the given date in the accepted range? */ | |
4890 _isInRange: function(inst, date) { | |
4891 var yearSplit, currentYear, | |
4892 minDate = this._getMinMaxDate(inst, "min"), | |
4893 maxDate = this._getMinMaxDate(inst, "max"), | |
4894 minYear = null, | |
4895 maxYear = null, | |
4896 years = this._get(inst, "yearRange"); | |
4897 if (years){ | |
4898 yearSplit = years.split(":"); | |
4899 currentYear = new Date().getFullYear(); | |
4900 minYear = parseInt(yearSplit[0], 10); | |
4901 maxYear = parseInt(yearSplit[1], 10); | |
4902 if ( yearSplit[0].match(/[+\-].*/) ) { | |
4903 minYear += currentYear; | |
4904 } | |
4905 if ( yearSplit[1].match(/[+\-].*/) ) { | |
4906 maxYear += currentYear; | |
4907 } | |
4908 } | |
4909 | |
4910 return ((!minDate || date.getTime() >= minDate.getTime()) && | |
4911 (!maxDate || date.getTime() <= maxDate.getTime()) && | |
4912 (!minYear || date.getFullYear() >= minYear) && | |
4913 (!maxYear || date.getFullYear() <= maxYear)); | |
4914 }, | |
4915 | |
4916 /* Provide the configuration settings for formatting/parsing. */ | |
4917 _getFormatConfig: function(inst) { | |
4918 var shortYearCutoff = this._get(inst, "shortYearCutoff"); | |
4919 shortYearCutoff = (typeof shortYearCutoff !== "string" ? shortYearCutoff : | |
4920 new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10)); | |
4921 return {shortYearCutoff: shortYearCutoff, | |
4922 dayNamesShort: this._get(inst, "dayNamesShort"), dayNames: this._get(inst, "dayNames"), | |
4923 monthNamesShort: this._get(inst, "monthNamesShort"), monthNames: this._get(inst, "monthNames")}; | |
4924 }, | |
4925 | |
4926 /* Format the given date for display. */ | |
4927 _formatDate: function(inst, day, month, year) { | |
4928 if (!day) { | |
4929 inst.currentDay = inst.selectedDay; | |
4930 inst.currentMonth = inst.selectedMonth; | |
4931 inst.currentYear = inst.selectedYear; | |
4932 } | |
4933 var date = (day ? (typeof day === "object" ? day : | |
4934 this._daylightSavingAdjust(new Date(year, month, day))) : | |
4935 this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay))); | |
4936 return this.formatDate(this._get(inst, "dateFormat"), date, this._getFormatConfig(inst)); | |
4937 } | |
4938 }); | |
4939 | |
4940 /* | |
4941 * Bind hover events for datepicker elements. | |
4942 * Done via delegate so the binding only occurs once in the lifetime of the parent div. | |
4943 * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker. | |
4944 */ | |
4945 function bindHover(dpDiv) { | |
4946 var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a"; | |
4947 return dpDiv.delegate(selector, "mouseout", function() { | |
4948 $(this).removeClass("ui-state-hover"); | |
4949 if (this.className.indexOf("ui-datepicker-prev") !== -1) { | |
4950 $(this).removeClass("ui-datepicker-prev-hover"); | |
4951 } | |
4952 if (this.className.indexOf("ui-datepicker-next") !== -1) { | |
4953 $(this).removeClass("ui-datepicker-next-hover"); | |
4954 } | |
4955 }) | |
4956 .delegate(selector, "mouseover", function(){ | |
4957 if (!$.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0])) { | |
4958 $(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"); | |
4959 $(this).addClass("ui-state-hover"); | |
4960 if (this.className.indexOf("ui-datepicker-prev") !== -1) { | |
4961 $(this).addClass("ui-datepicker-prev-hover"); | |
4962 } | |
4963 if (this.className.indexOf("ui-datepicker-next") !== -1) { | |
4964 $(this).addClass("ui-datepicker-next-hover"); | |
4965 } | |
4966 } | |
4967 }); | |
4968 } | |
4969 | |
4970 /* jQuery extend now ignores nulls! */ | |
4971 function extendRemove(target, props) { | |
4972 $.extend(target, props); | |
4973 for (var name in props) { | |
4974 if (props[name] == null) { | |
4975 target[name] = props[name]; | |
4976 } | |
4977 } | |
4978 return target; | |
4979 } | |
4980 | |
4981 /* Invoke the datepicker functionality. | |
4982 @param options string - a command, optionally followed by additional parameters or | |
4983 Object - settings for attaching new datepicker functionality | |
4984 @return jQuery object */ | |
4985 $.fn.datepicker = function(options){ | |
4986 | |
4987 /* Verify an empty collection wasn't passed - Fixes #6976 */ | |
4988 if ( !this.length ) { | |
4989 return this; | |
4990 } | |
4991 | |
4992 /* Initialise the date picker. */ | |
4993 if (!$.datepicker.initialized) { | |
4994 $(document).mousedown($.datepicker._checkExternalClick); | |
4995 $.datepicker.initialized = true; | |
4996 } | |
4997 | |
4998 /* Append datepicker main container to body if not exist. */ | |
4999 if ($("#"+$.datepicker._mainDivId).length === 0) { | |
5000 $("body").append($.datepicker.dpDiv); | |
5001 } | |
5002 | |
5003 var otherArgs = Array.prototype.slice.call(arguments, 1); | |
5004 if (typeof options === "string" && (options === "isDisabled" || options === "getDate" || options === "widget")) { | |
5005 return $.datepicker["_" + options + "Datepicker"]. | |
5006 apply($.datepicker, [this[0]].concat(otherArgs)); | |
5007 } | |
5008 if (options === "option" && arguments.length === 2 && typeof arguments[1] === "string") { | |
5009 return $.datepicker["_" + options + "Datepicker"]. | |
5010 apply($.datepicker, [this[0]].concat(otherArgs)); | |
5011 } | |
5012 return this.each(function() { | |
5013 typeof options === "string" ? | |
5014 $.datepicker["_" + options + "Datepicker"]. | |
5015 apply($.datepicker, [this].concat(otherArgs)) : | |
5016 $.datepicker._attachDatepicker(this, options); | |
5017 }); | |
5018 }; | |
5019 | |
5020 $.datepicker = new Datepicker(); // singleton instance | |
5021 $.datepicker.initialized = false; | |
5022 $.datepicker.uuid = new Date().getTime(); | |
5023 $.datepicker.version = "1.10.4"; | |
5024 | |
5025 })(jQuery); | |
5026 (function( $, undefined ) { | |
5027 | |
5028 var sizeRelatedOptions = { | |
5029 buttons: true, | |
5030 height: true, | |
5031 maxHeight: true, | |
5032 maxWidth: true, | |
5033 minHeight: true, | |
5034 minWidth: true, | |
5035 width: true | |
5036 }, | |
5037 resizableRelatedOptions = { | |
5038 maxHeight: true, | |
5039 maxWidth: true, | |
5040 minHeight: true, | |
5041 minWidth: true | |
5042 }; | |
5043 | |
5044 $.widget( "ui.dialog", { | |
5045 version: "1.10.4", | |
5046 options: { | |
5047 appendTo: "body", | |
5048 autoOpen: true, | |
5049 buttons: [], | |
5050 closeOnEscape: true, | |
5051 closeText: "close", | |
5052 dialogClass: "", | |
5053 draggable: true, | |
5054 hide: null, | |
5055 height: "auto", | |
5056 maxHeight: null, | |
5057 maxWidth: null, | |
5058 minHeight: 150, | |
5059 minWidth: 150, | |
5060 modal: false, | |
5061 position: { | |
5062 my: "center", | |
5063 at: "center", | |
5064 of: window, | |
5065 collision: "fit", | |
5066 // Ensure the titlebar is always visible | |
5067 using: function( pos ) { | |
5068 var topOffset = $( this ).css( pos ).offset().top; | |
5069 if ( topOffset < 0 ) { | |
5070 $( this ).css( "top", pos.top - topOffset ); | |
5071 } | |
5072 } | |
5073 }, | |
5074 resizable: true, | |
5075 show: null, | |
5076 title: null, | |
5077 width: 300, | |
5078 | |
5079 // callbacks | |
5080 beforeClose: null, | |
5081 close: null, | |
5082 drag: null, | |
5083 dragStart: null, | |
5084 dragStop: null, | |
5085 focus: null, | |
5086 open: null, | |
5087 resize: null, | |
5088 resizeStart: null, | |
5089 resizeStop: null | |
5090 }, | |
5091 | |
5092 _create: function() { | |
5093 this.originalCss = { | |
5094 display: this.element[0].style.display, | |
5095 width: this.element[0].style.width, | |
5096 minHeight: this.element[0].style.minHeight, | |
5097 maxHeight: this.element[0].style.maxHeight, | |
5098 height: this.element[0].style.height | |
5099 }; | |
5100 this.originalPosition = { | |
5101 parent: this.element.parent(), | |
5102 index: this.element.parent().children().index( this.element ) | |
5103 }; | |
5104 this.originalTitle = this.element.attr("title"); | |
5105 this.options.title = this.options.title || this.originalTitle; | |
5106 | |
5107 this._createWrapper(); | |
5108 | |
5109 this.element | |
5110 .show() | |
5111 .removeAttr("title") | |
5112 .addClass("ui-dialog-content ui-widget-content") | |
5113 .appendTo( this.uiDialog ); | |
5114 | |
5115 this._createTitlebar(); | |
5116 this._createButtonPane(); | |
5117 | |
5118 if ( this.options.draggable && $.fn.draggable ) { | |
5119 this._makeDraggable(); | |
5120 } | |
5121 if ( this.options.resizable && $.fn.resizable ) { | |
5122 this._makeResizable(); | |
5123 } | |
5124 | |
5125 this._isOpen = false; | |
5126 }, | |
5127 | |
5128 _init: function() { | |
5129 if ( this.options.autoOpen ) { | |
5130 this.open(); | |
5131 } | |
5132 }, | |
5133 | |
5134 _appendTo: function() { | |
5135 var element = this.options.appendTo; | |
5136 if ( element && (element.jquery || element.nodeType) ) { | |
5137 return $( element ); | |
5138 } | |
5139 return this.document.find( element || "body" ).eq( 0 ); | |
5140 }, | |
5141 | |
5142 _destroy: function() { | |
5143 var next, | |
5144 originalPosition = this.originalPosition; | |
5145 | |
5146 this._destroyOverlay(); | |
5147 | |
5148 this.element | |
5149 .removeUniqueId() | |
5150 .removeClass("ui-dialog-content ui-widget-content") | |
5151 .css( this.originalCss ) | |
5152 // Without detaching first, the following becomes really slow | |
5153 .detach(); | |
5154 | |
5155 this.uiDialog.stop( true, true ).remove(); | |
5156 | |
5157 if ( this.originalTitle ) { | |
5158 this.element.attr( "title", this.originalTitle ); | |
5159 } | |
5160 | |
5161 next = originalPosition.parent.children().eq( originalPosition.index ); | |
5162 // Don't try to place the dialog next to itself (#8613) | |
5163 if ( next.length && next[0] !== this.element[0] ) { | |
5164 next.before( this.element ); | |
5165 } else { | |
5166 originalPosition.parent.append( this.element ); | |
5167 } | |
5168 }, | |
5169 | |
5170 widget: function() { | |
5171 return this.uiDialog; | |
5172 }, | |
5173 | |
5174 disable: $.noop, | |
5175 enable: $.noop, | |
5176 | |
5177 close: function( event ) { | |
5178 var activeElement, | |
5179 that = this; | |
5180 | |
5181 if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) { | |
5182 return; | |
5183 } | |
5184 | |
5185 this._isOpen = false; | |
5186 this._destroyOverlay(); | |
5187 | |
5188 if ( !this.opener.filter(":focusable").focus().length ) { | |
5189 | |
5190 // support: IE9 | |
5191 // IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe> | |
5192 try { | |
5193 activeElement = this.document[ 0 ].activeElement; | |
5194 | |
5195 // Support: IE9, IE10 | |
5196 // If the <body> is blurred, IE will switch windows, see #4520 | |
5197 if ( activeElement && activeElement.nodeName.toLowerCase() !== "body" ) { | |
5198 | |
5199 // Hiding a focused element doesn't trigger blur in WebKit | |
5200 // so in case we have nothing to focus on, explicitly blur the active element | |
5201 // https://bugs.webkit.org/show_bug.cgi?id=47182 | |
5202 $( activeElement ).blur(); | |
5203 } | |
5204 } catch ( error ) {} | |
5205 } | |
5206 | |
5207 this._hide( this.uiDialog, this.options.hide, function() { | |
5208 that._trigger( "close", event ); | |
5209 }); | |
5210 }, | |
5211 | |
5212 isOpen: function() { | |
5213 return this._isOpen; | |
5214 }, | |
5215 | |
5216 moveToTop: function() { | |
5217 this._moveToTop(); | |
5218 }, | |
5219 | |
5220 _moveToTop: function( event, silent ) { | |
5221 var moved = !!this.uiDialog.nextAll(":visible").insertBefore( this.uiDialog ).length; | |
5222 if ( moved && !silent ) { | |
5223 this._trigger( "focus", event ); | |
5224 } | |
5225 return moved; | |
5226 }, | |
5227 | |
5228 open: function() { | |
5229 var that = this; | |
5230 if ( this._isOpen ) { | |
5231 if ( this._moveToTop() ) { | |
5232 this._focusTabbable(); | |
5233 } | |
5234 return; | |
5235 } | |
5236 | |
5237 this._isOpen = true; | |
5238 this.opener = $( this.document[0].activeElement ); | |
5239 | |
5240 this._size(); | |
5241 this._position(); | |
5242 this._createOverlay(); | |
5243 this._moveToTop( null, true ); | |
5244 this._show( this.uiDialog, this.options.show, function() { | |
5245 that._focusTabbable(); | |
5246 that._trigger("focus"); | |
5247 }); | |
5248 | |
5249 this._trigger("open"); | |
5250 }, | |
5251 | |
5252 _focusTabbable: function() { | |
5253 // Set focus to the first match: | |
5254 // 1. First element inside the dialog matching [autofocus] | |
5255 // 2. Tabbable element inside the content element | |
5256 // 3. Tabbable element inside the buttonpane | |
5257 // 4. The close button | |
5258 // 5. The dialog itself | |
5259 var hasFocus = this.element.find("[autofocus]"); | |
5260 if ( !hasFocus.length ) { | |
5261 hasFocus = this.element.find(":tabbable"); | |
5262 } | |
5263 if ( !hasFocus.length ) { | |
5264 hasFocus = this.uiDialogButtonPane.find(":tabbable"); | |
5265 } | |
5266 if ( !hasFocus.length ) { | |
5267 hasFocus = this.uiDialogTitlebarClose.filter(":tabbable"); | |
5268 } | |
5269 if ( !hasFocus.length ) { | |
5270 hasFocus = this.uiDialog; | |
5271 } | |
5272 hasFocus.eq( 0 ).focus(); | |
5273 }, | |
5274 | |
5275 _keepFocus: function( event ) { | |
5276 function checkFocus() { | |
5277 var activeElement = this.document[0].activeElement, | |
5278 isActive = this.uiDialog[0] === activeElement || | |
5279 $.contains( this.uiDialog[0], activeElement ); | |
5280 if ( !isActive ) { | |
5281 this._focusTabbable(); | |
5282 } | |
5283 } | |
5284 event.preventDefault(); | |
5285 checkFocus.call( this ); | |
5286 // support: IE | |
5287 // IE <= 8 doesn't prevent moving focus even with event.preventDefault() | |
5288 // so we check again later | |
5289 this._delay( checkFocus ); | |
5290 }, | |
5291 | |
5292 _createWrapper: function() { | |
5293 this.uiDialog = $("<div>") | |
5294 .addClass( "ui-dialog ui-widget ui-widget-content ui-corner-all ui-front " + | |
5295 this.options.dialogClass ) | |
5296 .hide() | |
5297 .attr({ | |
5298 // Setting tabIndex makes the div focusable | |
5299 tabIndex: -1, | |
5300 role: "dialog" | |
5301 }) | |
5302 .appendTo( this._appendTo() ); | |
5303 | |
5304 this._on( this.uiDialog, { | |
5305 keydown: function( event ) { | |
5306 if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && | |
5307 event.keyCode === $.ui.keyCode.ESCAPE ) { | |
5308 event.preventDefault(); | |
5309 this.close( event ); | |
5310 return; | |
5311 } | |
5312 | |
5313 // prevent tabbing out of dialogs | |
5314 if ( event.keyCode !== $.ui.keyCode.TAB ) { | |
5315 return; | |
5316 } | |
5317 var tabbables = this.uiDialog.find(":tabbable"), | |
5318 first = tabbables.filter(":first"), | |
5319 last = tabbables.filter(":last"); | |
5320 | |
5321 if ( ( event.target === last[0] || event.target === this.uiDialog[0] ) && !event.shiftKey ) { | |
5322 first.focus( 1 ); | |
5323 event.preventDefault(); | |
5324 } else if ( ( event.target === first[0] || event.target === this.uiDialog[0] ) && event.shiftKey ) { | |
5325 last.focus( 1 ); | |
5326 event.preventDefault(); | |
5327 } | |
5328 }, | |
5329 mousedown: function( event ) { | |
5330 if ( this._moveToTop( event ) ) { | |
5331 this._focusTabbable(); | |
5332 } | |
5333 } | |
5334 }); | |
5335 | |
5336 // We assume that any existing aria-describedby attribute means | |
5337 // that the dialog content is marked up properly | |
5338 // otherwise we brute force the content as the description | |
5339 if ( !this.element.find("[aria-describedby]").length ) { | |
5340 this.uiDialog.attr({ | |
5341 "aria-describedby": this.element.uniqueId().attr("id") | |
5342 }); | |
5343 } | |
5344 }, | |
5345 | |
5346 _createTitlebar: function() { | |
5347 var uiDialogTitle; | |
5348 | |
5349 this.uiDialogTitlebar = $("<div>") | |
5350 .addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix") | |
5351 .prependTo( this.uiDialog ); | |
5352 this._on( this.uiDialogTitlebar, { | |
5353 mousedown: function( event ) { | |
5354 // Don't prevent click on close button (#8838) | |
5355 // Focusing a dialog that is partially scrolled out of view | |
5356 // causes the browser to scroll it into view, preventing the click event | |
5357 if ( !$( event.target ).closest(".ui-dialog-titlebar-close") ) { | |
5358 // Dialog isn't getting focus when dragging (#8063) | |
5359 this.uiDialog.focus(); | |
5360 } | |
5361 } | |
5362 }); | |
5363 | |
5364 // support: IE | |
5365 // Use type="button" to prevent enter keypresses in textboxes from closing the | |
5366 // dialog in IE (#9312) | |
5367 this.uiDialogTitlebarClose = $( "<button type='button'></button>" ) | |
5368 .button({ | |
5369 label: this.options.closeText, | |
5370 icons: { | |
5371 primary: "ui-icon-closethick" | |
5372 }, | |
5373 text: false | |
5374 }) | |
5375 .addClass("ui-dialog-titlebar-close") | |
5376 .appendTo( this.uiDialogTitlebar ); | |
5377 this._on( this.uiDialogTitlebarClose, { | |
5378 click: function( event ) { | |
5379 event.preventDefault(); | |
5380 this.close( event ); | |
5381 } | |
5382 }); | |
5383 | |
5384 uiDialogTitle = $("<span>") | |
5385 .uniqueId() | |
5386 .addClass("ui-dialog-title") | |
5387 .prependTo( this.uiDialogTitlebar ); | |
5388 this._title( uiDialogTitle ); | |
5389 | |
5390 this.uiDialog.attr({ | |
5391 "aria-labelledby": uiDialogTitle.attr("id") | |
5392 }); | |
5393 }, | |
5394 | |
5395 _title: function( title ) { | |
5396 if ( !this.options.title ) { | |
5397 title.html(" "); | |
5398 } | |
5399 title.text( this.options.title ); | |
5400 }, | |
5401 | |
5402 _createButtonPane: function() { | |
5403 this.uiDialogButtonPane = $("<div>") | |
5404 .addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"); | |
5405 | |
5406 this.uiButtonSet = $("<div>") | |
5407 .addClass("ui-dialog-buttonset") | |
5408 .appendTo( this.uiDialogButtonPane ); | |
5409 | |
5410 this._createButtons(); | |
5411 }, | |
5412 | |
5413 _createButtons: function() { | |
5414 var that = this, | |
5415 buttons = this.options.buttons; | |
5416 | |
5417 // if we already have a button pane, remove it | |
5418 this.uiDialogButtonPane.remove(); | |
5419 this.uiButtonSet.empty(); | |
5420 | |
5421 if ( $.isEmptyObject( buttons ) || ($.isArray( buttons ) && !buttons.length) ) { | |
5422 this.uiDialog.removeClass("ui-dialog-buttons"); | |
5423 return; | |
5424 } | |
5425 | |
5426 $.each( buttons, function( name, props ) { | |
5427 var click, buttonOptions; | |
5428 props = $.isFunction( props ) ? | |
5429 { click: props, text: name } : | |
5430 props; | |
5431 // Default to a non-submitting button | |
5432 props = $.extend( { type: "button" }, props ); | |
5433 // Change the context for the click callback to be the main element | |
5434 click = props.click; | |
5435 props.click = function() { | |
5436 click.apply( that.element[0], arguments ); | |
5437 }; | |
5438 buttonOptions = { | |
5439 icons: props.icons, | |
5440 text: props.showText | |
5441 }; | |
5442 delete props.icons; | |
5443 delete props.showText; | |
5444 $( "<button></button>", props ) | |
5445 .button( buttonOptions ) | |
5446 .appendTo( that.uiButtonSet ); | |
5447 }); | |
5448 this.uiDialog.addClass("ui-dialog-buttons"); | |
5449 this.uiDialogButtonPane.appendTo( this.uiDialog ); | |
5450 }, | |
5451 | |
5452 _makeDraggable: function() { | |
5453 var that = this, | |
5454 options = this.options; | |
5455 | |
5456 function filteredUi( ui ) { | |
5457 return { | |
5458 position: ui.position, | |
5459 offset: ui.offset | |
5460 }; | |
5461 } | |
5462 | |
5463 this.uiDialog.draggable({ | |
5464 cancel: ".ui-dialog-content, .ui-dialog-titlebar-close", | |
5465 handle: ".ui-dialog-titlebar", | |
5466 containment: "document", | |
5467 start: function( event, ui ) { | |
5468 $( this ).addClass("ui-dialog-dragging"); | |
5469 that._blockFrames(); | |
5470 that._trigger( "dragStart", event, filteredUi( ui ) ); | |
5471 }, | |
5472 drag: function( event, ui ) { | |
5473 that._trigger( "drag", event, filteredUi( ui ) ); | |
5474 }, | |
5475 stop: function( event, ui ) { | |
5476 options.position = [ | |
5477 ui.position.left - that.document.scrollLeft(), | |
5478 ui.position.top - that.document.scrollTop() | |
5479 ]; | |
5480 $( this ).removeClass("ui-dialog-dragging"); | |
5481 that._unblockFrames(); | |
5482 that._trigger( "dragStop", event, filteredUi( ui ) ); | |
5483 } | |
5484 }); | |
5485 }, | |
5486 | |
5487 _makeResizable: function() { | |
5488 var that = this, | |
5489 options = this.options, | |
5490 handles = options.resizable, | |
5491 // .ui-resizable has position: relative defined in the stylesheet | |
5492 // but dialogs have to use absolute or fixed positioning | |
5493 position = this.uiDialog.css("position"), | |
5494 resizeHandles = typeof handles === "string" ? | |
5495 handles : | |
5496 "n,e,s,w,se,sw,ne,nw"; | |
5497 | |
5498 function filteredUi( ui ) { | |
5499 return { | |
5500 originalPosition: ui.originalPosition, | |
5501 originalSize: ui.originalSize, | |
5502 position: ui.position, | |
5503 size: ui.size | |
5504 }; | |
5505 } | |
5506 | |
5507 this.uiDialog.resizable({ | |
5508 cancel: ".ui-dialog-content", | |
5509 containment: "document", | |
5510 alsoResize: this.element, | |
5511 maxWidth: options.maxWidth, | |
5512 maxHeight: options.maxHeight, | |
5513 minWidth: options.minWidth, | |
5514 minHeight: this._minHeight(), | |
5515 handles: resizeHandles, | |
5516 start: function( event, ui ) { | |
5517 $( this ).addClass("ui-dialog-resizing"); | |
5518 that._blockFrames(); | |
5519 that._trigger( "resizeStart", event, filteredUi( ui ) ); | |
5520 }, | |
5521 resize: function( event, ui ) { | |
5522 that._trigger( "resize", event, filteredUi( ui ) ); | |
5523 }, | |
5524 stop: function( event, ui ) { | |
5525 options.height = $( this ).height(); | |
5526 options.width = $( this ).width(); | |
5527 $( this ).removeClass("ui-dialog-resizing"); | |
5528 that._unblockFrames(); | |
5529 that._trigger( "resizeStop", event, filteredUi( ui ) ); | |
5530 } | |
5531 }) | |
5532 .css( "position", position ); | |
5533 }, | |
5534 | |
5535 _minHeight: function() { | |
5536 var options = this.options; | |
5537 | |
5538 return options.height === "auto" ? | |
5539 options.minHeight : | |
5540 Math.min( options.minHeight, options.height ); | |
5541 }, | |
5542 | |
5543 _position: function() { | |
5544 // Need to show the dialog to get the actual offset in the position plugin | |
5545 var isVisible = this.uiDialog.is(":visible"); | |
5546 if ( !isVisible ) { | |
5547 this.uiDialog.show(); | |
5548 } | |
5549 this.uiDialog.position( this.options.position ); | |
5550 if ( !isVisible ) { | |
5551 this.uiDialog.hide(); | |
5552 } | |
5553 }, | |
5554 | |
5555 _setOptions: function( options ) { | |
5556 var that = this, | |
5557 resize = false, | |
5558 resizableOptions = {}; | |
5559 | |
5560 $.each( options, function( key, value ) { | |
5561 that._setOption( key, value ); | |
5562 | |
5563 if ( key in sizeRelatedOptions ) { | |
5564 resize = true; | |
5565 } | |
5566 if ( key in resizableRelatedOptions ) { | |
5567 resizableOptions[ key ] = value; | |
5568 } | |
5569 }); | |
5570 | |
5571 if ( resize ) { | |
5572 this._size(); | |
5573 this._position(); | |
5574 } | |
5575 if ( this.uiDialog.is(":data(ui-resizable)") ) { | |
5576 this.uiDialog.resizable( "option", resizableOptions ); | |
5577 } | |
5578 }, | |
5579 | |
5580 _setOption: function( key, value ) { | |
5581 var isDraggable, isResizable, | |
5582 uiDialog = this.uiDialog; | |
5583 | |
5584 if ( key === "dialogClass" ) { | |
5585 uiDialog | |
5586 .removeClass( this.options.dialogClass ) | |
5587 .addClass( value ); | |
5588 } | |
5589 | |
5590 if ( key === "disabled" ) { | |
5591 return; | |
5592 } | |
5593 | |
5594 this._super( key, value ); | |
5595 | |
5596 if ( key === "appendTo" ) { | |
5597 this.uiDialog.appendTo( this._appendTo() ); | |
5598 } | |
5599 | |
5600 if ( key === "buttons" ) { | |
5601 this._createButtons(); | |
5602 } | |
5603 | |
5604 if ( key === "closeText" ) { | |
5605 this.uiDialogTitlebarClose.button({ | |
5606 // Ensure that we always pass a string | |
5607 label: "" + value | |
5608 }); | |
5609 } | |
5610 | |
5611 if ( key === "draggable" ) { | |
5612 isDraggable = uiDialog.is(":data(ui-draggable)"); | |
5613 if ( isDraggable && !value ) { | |
5614 uiDialog.draggable("destroy"); | |
5615 } | |
5616 | |
5617 if ( !isDraggable && value ) { | |
5618 this._makeDraggable(); | |
5619 } | |
5620 } | |
5621 | |
5622 if ( key === "position" ) { | |
5623 this._position(); | |
5624 } | |
5625 | |
5626 if ( key === "resizable" ) { | |
5627 // currently resizable, becoming non-resizable | |
5628 isResizable = uiDialog.is(":data(ui-resizable)"); | |
5629 if ( isResizable && !value ) { | |
5630 uiDialog.resizable("destroy"); | |
5631 } | |
5632 | |
5633 // currently resizable, changing handles | |
5634 if ( isResizable && typeof value === "string" ) { | |
5635 uiDialog.resizable( "option", "handles", value ); | |
5636 } | |
5637 | |
5638 // currently non-resizable, becoming resizable | |
5639 if ( !isResizable && value !== false ) { | |
5640 this._makeResizable(); | |
5641 } | |
5642 } | |
5643 | |
5644 if ( key === "title" ) { | |
5645 this._title( this.uiDialogTitlebar.find(".ui-dialog-title") ); | |
5646 } | |
5647 }, | |
5648 | |
5649 _size: function() { | |
5650 // If the user has resized the dialog, the .ui-dialog and .ui-dialog-content | |
5651 // divs will both have width and height set, so we need to reset them | |
5652 var nonContentHeight, minContentHeight, maxContentHeight, | |
5653 options = this.options; | |
5654 | |
5655 // Reset content sizing | |
5656 this.element.show().css({ | |
5657 width: "auto", | |
5658 minHeight: 0, | |
5659 maxHeight: "none", | |
5660 height: 0 | |
5661 }); | |
5662 | |
5663 if ( options.minWidth > options.width ) { | |
5664 options.width = options.minWidth; | |
5665 } | |
5666 | |
5667 // reset wrapper sizing | |
5668 // determine the height of all the non-content elements | |
5669 nonContentHeight = this.uiDialog.css({ | |
5670 height: "auto", | |
5671 width: options.width | |
5672 }) | |
5673 .outerHeight(); | |
5674 minContentHeight = Math.max( 0, options.minHeight - nonContentHeight ); | |
5675 maxContentHeight = typeof options.maxHeight === "number" ? | |
5676 Math.max( 0, options.maxHeight - nonContentHeight ) : | |
5677 "none"; | |
5678 | |
5679 if ( options.height === "auto" ) { | |
5680 this.element.css({ | |
5681 minHeight: minContentHeight, | |
5682 maxHeight: maxContentHeight, | |
5683 height: "auto" | |
5684 }); | |
5685 } else { | |
5686 this.element.height( Math.max( 0, options.height - nonContentHeight ) ); | |
5687 } | |
5688 | |
5689 if (this.uiDialog.is(":data(ui-resizable)") ) { | |
5690 this.uiDialog.resizable( "option", "minHeight", this._minHeight() ); | |
5691 } | |
5692 }, | |
5693 | |
5694 _blockFrames: function() { | |
5695 this.iframeBlocks = this.document.find( "iframe" ).map(function() { | |
5696 var iframe = $( this ); | |
5697 | |
5698 return $( "<div>" ) | |
5699 .css({ | |
5700 position: "absolute", | |
5701 width: iframe.outerWidth(), | |
5702 height: iframe.outerHeight() | |
5703 }) | |
5704 .appendTo( iframe.parent() ) | |
5705 .offset( iframe.offset() )[0]; | |
5706 }); | |
5707 }, | |
5708 | |
5709 _unblockFrames: function() { | |
5710 if ( this.iframeBlocks ) { | |
5711 this.iframeBlocks.remove(); | |
5712 delete this.iframeBlocks; | |
5713 } | |
5714 }, | |
5715 | |
5716 _allowInteraction: function( event ) { | |
5717 if ( $( event.target ).closest(".ui-dialog").length ) { | |
5718 return true; | |
5719 } | |
5720 | |
5721 // TODO: Remove hack when datepicker implements | |
5722 // the .ui-front logic (#8989) | |
5723 return !!$( event.target ).closest(".ui-datepicker").length; | |
5724 }, | |
5725 | |
5726 _createOverlay: function() { | |
5727 if ( !this.options.modal ) { | |
5728 return; | |
5729 } | |
5730 | |
5731 var that = this, | |
5732 widgetFullName = this.widgetFullName; | |
5733 if ( !$.ui.dialog.overlayInstances ) { | |
5734 // Prevent use of anchors and inputs. | |
5735 // We use a delay in case the overlay is created from an | |
5736 // event that we're going to be cancelling. (#2804) | |
5737 this._delay(function() { | |
5738 // Handle .dialog().dialog("close") (#4065) | |
5739 if ( $.ui.dialog.overlayInstances ) { | |
5740 this.document.bind( "focusin.dialog", function( event ) { | |
5741 if ( !that._allowInteraction( event ) ) { | |
5742 event.preventDefault(); | |
5743 $(".ui-dialog:visible:last .ui-dialog-content") | |
5744 .data( widgetFullName )._focusTabbable(); | |
5745 } | |
5746 }); | |
5747 } | |
5748 }); | |
5749 } | |
5750 | |
5751 this.overlay = $("<div>") | |
5752 .addClass("ui-widget-overlay ui-front") | |
5753 .appendTo( this._appendTo() ); | |
5754 this._on( this.overlay, { | |
5755 mousedown: "_keepFocus" | |
5756 }); | |
5757 $.ui.dialog.overlayInstances++; | |
5758 }, | |
5759 | |
5760 _destroyOverlay: function() { | |
5761 if ( !this.options.modal ) { | |
5762 return; | |
5763 } | |
5764 | |
5765 if ( this.overlay ) { | |
5766 $.ui.dialog.overlayInstances--; | |
5767 | |
5768 if ( !$.ui.dialog.overlayInstances ) { | |
5769 this.document.unbind( "focusin.dialog" ); | |
5770 } | |
5771 this.overlay.remove(); | |
5772 this.overlay = null; | |
5773 } | |
5774 } | |
5775 }); | |
5776 | |
5777 $.ui.dialog.overlayInstances = 0; | |
5778 | |
5779 // DEPRECATED | |
5780 if ( $.uiBackCompat !== false ) { | |
5781 // position option with array notation | |
5782 // just override with old implementation | |
5783 $.widget( "ui.dialog", $.ui.dialog, { | |
5784 _position: function() { | |
5785 var position = this.options.position, | |
5786 myAt = [], | |
5787 offset = [ 0, 0 ], | |
5788 isVisible; | |
5789 | |
5790 if ( position ) { | |
5791 if ( typeof position === "string" || (typeof position === "object" && "0" in position ) ) { | |
5792 myAt = position.split ? position.split(" ") : [ position[0], position[1] ]; | |
5793 if ( myAt.length === 1 ) { | |
5794 myAt[1] = myAt[0]; | |
5795 } | |
5796 | |
5797 $.each( [ "left", "top" ], function( i, offsetPosition ) { | |
5798 if ( +myAt[ i ] === myAt[ i ] ) { | |
5799 offset[ i ] = myAt[ i ]; | |
5800 myAt[ i ] = offsetPosition; | |
5801 } | |
5802 }); | |
5803 | |
5804 position = { | |
5805 my: myAt[0] + (offset[0] < 0 ? offset[0] : "+" + offset[0]) + " " + | |
5806 myAt[1] + (offset[1] < 0 ? offset[1] : "+" + offset[1]), | |
5807 at: myAt.join(" ") | |
5808 }; | |
5809 } | |
5810 | |
5811 position = $.extend( {}, $.ui.dialog.prototype.options.position, position ); | |
5812 } else { | |
5813 position = $.ui.dialog.prototype.options.position; | |
5814 } | |
5815 | |
5816 // need to show the dialog to get the actual offset in the position plugin | |
5817 isVisible = this.uiDialog.is(":visible"); | |
5818 if ( !isVisible ) { | |
5819 this.uiDialog.show(); | |
5820 } | |
5821 this.uiDialog.position( position ); | |
5822 if ( !isVisible ) { | |
5823 this.uiDialog.hide(); | |
5824 } | |
5825 } | |
5826 }); | |
5827 } | |
5828 | |
5829 }( jQuery ) ); | |
5830 (function( $, undefined ) { | |
5831 | |
5832 $.widget("ui.draggable", $.ui.mouse, { | |
5833 version: "1.10.4", | |
5834 widgetEventPrefix: "drag", | |
5835 options: { | |
5836 addClasses: true, | |
5837 appendTo: "parent", | |
5838 axis: false, | |
5839 connectToSortable: false, | |
5840 containment: false, | |
5841 cursor: "auto", | |
5842 cursorAt: false, | |
5843 grid: false, | |
5844 handle: false, | |
5845 helper: "original", | |
5846 iframeFix: false, | |
5847 opacity: false, | |
5848 refreshPositions: false, | |
5849 revert: false, | |
5850 revertDuration: 500, | |
5851 scope: "default", | |
5852 scroll: true, | |
5853 scrollSensitivity: 20, | |
5854 scrollSpeed: 20, | |
5855 snap: false, | |
5856 snapMode: "both", | |
5857 snapTolerance: 20, | |
5858 stack: false, | |
5859 zIndex: false, | |
5860 | |
5861 // callbacks | |
5862 drag: null, | |
5863 start: null, | |
5864 stop: null | |
5865 }, | |
5866 _create: function() { | |
5867 | |
5868 if (this.options.helper === "original" && !(/^(?:r|a|f)/).test(this.element.css("position"))) { | |
5869 this.element[0].style.position = "relative"; | |
5870 } | |
5871 if (this.options.addClasses){ | |
5872 this.element.addClass("ui-draggable"); | |
5873 } | |
5874 if (this.options.disabled){ | |
5875 this.element.addClass("ui-draggable-disabled"); | |
5876 } | |
5877 | |
5878 this._mouseInit(); | |
5879 | |
5880 }, | |
5881 | |
5882 _destroy: function() { | |
5883 this.element.removeClass( "ui-draggable ui-draggable-dragging ui-draggable-disabled" ); | |
5884 this._mouseDestroy(); | |
5885 }, | |
5886 | |
5887 _mouseCapture: function(event) { | |
5888 | |
5889 var o = this.options; | |
5890 | |
5891 // among others, prevent a drag on a resizable-handle | |
5892 if (this.helper || o.disabled || $(event.target).closest(".ui-resizable-handle").length > 0) { | |
5893 return false; | |
5894 } | |
5895 | |
5896 //Quit if we're not on a valid handle | |
5897 this.handle = this._getHandle(event); | |
5898 if (!this.handle) { | |
5899 return false; | |
5900 } | |
5901 | |
5902 $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() { | |
5903 $("<div class='ui-draggable-iframeFix' style='background: #fff;'></div>") | |
5904 .css({ | |
5905 width: this.offsetWidth+"px", height: this.offsetHeight+"px", | |
5906 position: "absolute", opacity: "0.001", zIndex: 1000 | |
5907 }) | |
5908 .css($(this).offset()) | |
5909 .appendTo("body"); | |
5910 }); | |
5911 | |
5912 return true; | |
5913 | |
5914 }, | |
5915 | |
5916 _mouseStart: function(event) { | |
5917 | |
5918 var o = this.options; | |
5919 | |
5920 //Create and append the visible helper | |
5921 this.helper = this._createHelper(event); | |
5922 | |
5923 this.helper.addClass("ui-draggable-dragging"); | |
5924 | |
5925 //Cache the helper size | |
5926 this._cacheHelperProportions(); | |
5927 | |
5928 //If ddmanager is used for droppables, set the global draggable | |
5929 if($.ui.ddmanager) { | |
5930 $.ui.ddmanager.current = this; | |
5931 } | |
5932 | |
5933 /* | |
5934 * - Position generation - | |
5935 * This block generates everything position related - it's the core of draggables. | |
5936 */ | |
5937 | |
5938 //Cache the margins of the original element | |
5939 this._cacheMargins(); | |
5940 | |
5941 //Store the helper's css position | |
5942 this.cssPosition = this.helper.css( "position" ); | |
5943 this.scrollParent = this.helper.scrollParent(); | |
5944 this.offsetParent = this.helper.offsetParent(); | |
5945 this.offsetParentCssPosition = this.offsetParent.css( "position" ); | |
5946 | |
5947 //The element's absolute position on the page minus margins | |
5948 this.offset = this.positionAbs = this.element.offset(); | |
5949 this.offset = { | |
5950 top: this.offset.top - this.margins.top, | |
5951 left: this.offset.left - this.margins.left | |
5952 }; | |
5953 | |
5954 //Reset scroll cache | |
5955 this.offset.scroll = false; | |
5956 | |
5957 $.extend(this.offset, { | |
5958 click: { //Where the click happened, relative to the element | |
5959 left: event.pageX - this.offset.left, | |
5960 top: event.pageY - this.offset.top | |
5961 }, | |
5962 parent: this._getParentOffset(), | |
5963 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper | |
5964 }); | |
5965 | |
5966 //Generate the original position | |
5967 this.originalPosition = this.position = this._generatePosition(event); | |
5968 this.originalPageX = event.pageX; | |
5969 this.originalPageY = event.pageY; | |
5970 | |
5971 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied | |
5972 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)); | |
5973 | |
5974 //Set a containment if given in the options | |
5975 this._setContainment(); | |
5976 | |
5977 //Trigger event + callbacks | |
5978 if(this._trigger("start", event) === false) { | |
5979 this._clear(); | |
5980 return false; | |
5981 } | |
5982 | |
5983 //Recache the helper size | |
5984 this._cacheHelperProportions(); | |
5985 | |
5986 //Prepare the droppable offsets | |
5987 if ($.ui.ddmanager && !o.dropBehaviour) { | |
5988 $.ui.ddmanager.prepareOffsets(this, event); | |
5989 } | |
5990 | |
5991 | |
5992 this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position | |
5993 | |
5994 //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003) | |
5995 if ( $.ui.ddmanager ) { | |
5996 $.ui.ddmanager.dragStart(this, event); | |
5997 } | |
5998 | |
5999 return true; | |
6000 }, | |
6001 | |
6002 _mouseDrag: function(event, noPropagation) { | |
6003 // reset any necessary cached properties (see #5009) | |
6004 if ( this.offsetParentCssPosition === "fixed" ) { | |
6005 this.offset.parent = this._getParentOffset(); | |
6006 } | |
6007 | |
6008 //Compute the helpers position | |
6009 this.position = this._generatePosition(event); | |
6010 this.positionAbs = this._convertPositionTo("absolute"); | |
6011 | |
6012 //Call plugins and callbacks and use the resulting position if something is returned | |
6013 if (!noPropagation) { | |
6014 var ui = this._uiHash(); | |
6015 if(this._trigger("drag", event, ui) === false) { | |
6016 this._mouseUp({}); | |
6017 return false; | |
6018 } | |
6019 this.position = ui.position; | |
6020 } | |
6021 | |
6022 if(!this.options.axis || this.options.axis !== "y") { | |
6023 this.helper[0].style.left = this.position.left+"px"; | |
6024 } | |
6025 if(!this.options.axis || this.options.axis !== "x") { | |
6026 this.helper[0].style.top = this.position.top+"px"; | |
6027 } | |
6028 if($.ui.ddmanager) { | |
6029 $.ui.ddmanager.drag(this, event); | |
6030 } | |
6031 | |
6032 return false; | |
6033 }, | |
6034 | |
6035 _mouseStop: function(event) { | |
6036 | |
6037 //If we are using droppables, inform the manager about the drop | |
6038 var that = this, | |
6039 dropped = false; | |
6040 if ($.ui.ddmanager && !this.options.dropBehaviour) { | |
6041 dropped = $.ui.ddmanager.drop(this, event); | |
6042 } | |
6043 | |
6044 //if a drop comes from outside (a sortable) | |
6045 if(this.dropped) { | |
6046 dropped = this.dropped; | |
6047 this.dropped = false; | |
6048 } | |
6049 | |
6050 //if the original element is no longer in the DOM don't bother to continue (see #8269) | |
6051 if ( this.options.helper === "original" && !$.contains( this.element[ 0 ].ownerDocument, this.element[ 0 ] ) ) { | |
6052 return false; | |
6053 } | |
6054 | |
6055 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))) { | |
6056 $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() { | |
6057 if(that._trigger("stop", event) !== false) { | |
6058 that._clear(); | |
6059 } | |
6060 }); | |
6061 } else { | |
6062 if(this._trigger("stop", event) !== false) { | |
6063 this._clear(); | |
6064 } | |
6065 } | |
6066 | |
6067 return false; | |
6068 }, | |
6069 | |
6070 _mouseUp: function(event) { | |
6071 //Remove frame helpers | |
6072 $("div.ui-draggable-iframeFix").each(function() { | |
6073 this.parentNode.removeChild(this); | |
6074 }); | |
6075 | |
6076 //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003) | |
6077 if( $.ui.ddmanager ) { | |
6078 $.ui.ddmanager.dragStop(this, event); | |
6079 } | |
6080 | |
6081 return $.ui.mouse.prototype._mouseUp.call(this, event); | |
6082 }, | |
6083 | |
6084 cancel: function() { | |
6085 | |
6086 if(this.helper.is(".ui-draggable-dragging")) { | |
6087 this._mouseUp({}); | |
6088 } else { | |
6089 this._clear(); | |
6090 } | |
6091 | |
6092 return this; | |
6093 | |
6094 }, | |
6095 | |
6096 _getHandle: function(event) { | |
6097 return this.options.handle ? | |
6098 !!$( event.target ).closest( this.element.find( this.options.handle ) ).length : | |
6099 true; | |
6100 }, | |
6101 | |
6102 _createHelper: function(event) { | |
6103 | |
6104 var o = this.options, | |
6105 helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper === "clone" ? this.element.clone().removeAttr("id") : this.element); | |
6106 | |
6107 if(!helper.parents("body").length) { | |
6108 helper.appendTo((o.appendTo === "parent" ? this.element[0].parentNode : o.appendTo)); | |
6109 } | |
6110 | |
6111 if(helper[0] !== this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) { | |
6112 helper.css("position", "absolute"); | |
6113 } | |
6114 | |
6115 return helper; | |
6116 | |
6117 }, | |
6118 | |
6119 _adjustOffsetFromHelper: function(obj) { | |
6120 if (typeof obj === "string") { | |
6121 obj = obj.split(" "); | |
6122 } | |
6123 if ($.isArray(obj)) { | |
6124 obj = {left: +obj[0], top: +obj[1] || 0}; | |
6125 } | |
6126 if ("left" in obj) { | |
6127 this.offset.click.left = obj.left + this.margins.left; | |
6128 } | |
6129 if ("right" in obj) { | |
6130 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; | |
6131 } | |
6132 if ("top" in obj) { | |
6133 this.offset.click.top = obj.top + this.margins.top; | |
6134 } | |
6135 if ("bottom" in obj) { | |
6136 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; | |
6137 } | |
6138 }, | |
6139 | |
6140 _getParentOffset: function() { | |
6141 | |
6142 //Get the offsetParent and cache its position | |
6143 var po = this.offsetParent.offset(); | |
6144 | |
6145 // This is a special case where we need to modify a offset calculated on start, since the following happened: | |
6146 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent | |
6147 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that | |
6148 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag | |
6149 if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) { | |
6150 po.left += this.scrollParent.scrollLeft(); | |
6151 po.top += this.scrollParent.scrollTop(); | |
6152 } | |
6153 | |
6154 //This needs to be actually done for all browsers, since pageX/pageY includes this information | |
6155 //Ugly IE fix | |
6156 if((this.offsetParent[0] === document.body) || | |
6157 (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) { | |
6158 po = { top: 0, left: 0 }; | |
6159 } | |
6160 | |
6161 return { | |
6162 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0), | |
6163 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0) | |
6164 }; | |
6165 | |
6166 }, | |
6167 | |
6168 _getRelativeOffset: function() { | |
6169 | |
6170 if(this.cssPosition === "relative") { | |
6171 var p = this.element.position(); | |
6172 return { | |
6173 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(), | |
6174 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft() | |
6175 }; | |
6176 } else { | |
6177 return { top: 0, left: 0 }; | |
6178 } | |
6179 | |
6180 }, | |
6181 | |
6182 _cacheMargins: function() { | |
6183 this.margins = { | |
6184 left: (parseInt(this.element.css("marginLeft"),10) || 0), | |
6185 top: (parseInt(this.element.css("marginTop"),10) || 0), | |
6186 right: (parseInt(this.element.css("marginRight"),10) || 0), | |
6187 bottom: (parseInt(this.element.css("marginBottom"),10) || 0) | |
6188 }; | |
6189 }, | |
6190 | |
6191 _cacheHelperProportions: function() { | |
6192 this.helperProportions = { | |
6193 width: this.helper.outerWidth(), | |
6194 height: this.helper.outerHeight() | |
6195 }; | |
6196 }, | |
6197 | |
6198 _setContainment: function() { | |
6199 | |
6200 var over, c, ce, | |
6201 o = this.options; | |
6202 | |
6203 if ( !o.containment ) { | |
6204 this.containment = null; | |
6205 return; | |
6206 } | |
6207 | |
6208 if ( o.containment === "window" ) { | |
6209 this.containment = [ | |
6210 $( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left, | |
6211 $( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top, | |
6212 $( window ).scrollLeft() + $( window ).width() - this.helperProportions.width - this.margins.left, | |
6213 $( window ).scrollTop() + ( $( window ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top | |
6214 ]; | |
6215 return; | |
6216 } | |
6217 | |
6218 if ( o.containment === "document") { | |
6219 this.containment = [ | |
6220 0, | |
6221 0, | |
6222 $( document ).width() - this.helperProportions.width - this.margins.left, | |
6223 ( $( document ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top | |
6224 ]; | |
6225 return; | |
6226 } | |
6227 | |
6228 if ( o.containment.constructor === Array ) { | |
6229 this.containment = o.containment; | |
6230 return; | |
6231 } | |
6232 | |
6233 if ( o.containment === "parent" ) { | |
6234 o.containment = this.helper[ 0 ].parentNode; | |
6235 } | |
6236 | |
6237 c = $( o.containment ); | |
6238 ce = c[ 0 ]; | |
6239 | |
6240 if( !ce ) { | |
6241 return; | |
6242 } | |
6243 | |
6244 over = c.css( "overflow" ) !== "hidden"; | |
6245 | |
6246 this.containment = [ | |
6247 ( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ), | |
6248 ( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingTop" ), 10 ) || 0 ) , | |
6249 ( 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, | |
6250 ( 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 | |
6251 ]; | |
6252 this.relative_container = c; | |
6253 }, | |
6254 | |
6255 _convertPositionTo: function(d, pos) { | |
6256 | |
6257 if(!pos) { | |
6258 pos = this.position; | |
6259 } | |
6260 | |
6261 var mod = d === "absolute" ? 1 : -1, | |
6262 scroll = this.cssPosition === "absolute" && !( this.scrollParent[ 0 ] !== document && $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ? this.offsetParent : this.scrollParent; | |
6263 | |
6264 //Cache the scroll | |
6265 if (!this.offset.scroll) { | |
6266 this.offset.scroll = {top : scroll.scrollTop(), left : scroll.scrollLeft()}; | |
6267 } | |
6268 | |
6269 return { | |
6270 top: ( | |
6271 pos.top + // The absolute mouse position | |
6272 this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent | |
6273 this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border) | |
6274 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : this.offset.scroll.top ) * mod ) | |
6275 ), | |
6276 left: ( | |
6277 pos.left + // The absolute mouse position | |
6278 this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent | |
6279 this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border) | |
6280 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : this.offset.scroll.left ) * mod ) | |
6281 ) | |
6282 }; | |
6283 | |
6284 }, | |
6285 | |
6286 _generatePosition: function(event) { | |
6287 | |
6288 var containment, co, top, left, | |
6289 o = this.options, | |
6290 scroll = this.cssPosition === "absolute" && !( this.scrollParent[ 0 ] !== document && $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ? this.offsetParent : this.scrollParent, | |
6291 pageX = event.pageX, | |
6292 pageY = event.pageY; | |
6293 | |
6294 //Cache the scroll | |
6295 if (!this.offset.scroll) { | |
6296 this.offset.scroll = {top : scroll.scrollTop(), left : scroll.scrollLeft()}; | |
6297 } | |
6298 | |
6299 /* | |
6300 * - Position constraining - | |
6301 * Constrain the position to a mix of grid, containment. | |
6302 */ | |
6303 | |
6304 // If we are not dragging yet, we won't check for options | |
6305 if ( this.originalPosition ) { | |
6306 if ( this.containment ) { | |
6307 if ( this.relative_container ){ | |
6308 co = this.relative_container.offset(); | |
6309 containment = [ | |
6310 this.containment[ 0 ] + co.left, | |
6311 this.containment[ 1 ] + co.top, | |
6312 this.containment[ 2 ] + co.left, | |
6313 this.containment[ 3 ] + co.top | |
6314 ]; | |
6315 } | |
6316 else { | |
6317 containment = this.containment; | |
6318 } | |
6319 | |
6320 if(event.pageX - this.offset.click.left < containment[0]) { | |
6321 pageX = containment[0] + this.offset.click.left; | |
6322 } | |
6323 if(event.pageY - this.offset.click.top < containment[1]) { | |
6324 pageY = containment[1] + this.offset.click.top; | |
6325 } | |
6326 if(event.pageX - this.offset.click.left > containment[2]) { | |
6327 pageX = containment[2] + this.offset.click.left; | |
6328 } | |
6329 if(event.pageY - this.offset.click.top > containment[3]) { | |
6330 pageY = containment[3] + this.offset.click.top; | |
6331 } | |
6332 } | |
6333 | |
6334 if(o.grid) { | |
6335 //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950) | |
6336 top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY; | |
6337 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; | |
6338 | |
6339 left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX; | |
6340 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; | |
6341 } | |
6342 | |
6343 } | |
6344 | |
6345 return { | |
6346 top: ( | |
6347 pageY - // The absolute mouse position | |
6348 this.offset.click.top - // Click offset (relative to the element) | |
6349 this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent | |
6350 this.offset.parent.top + // The offsetParent's offset without borders (offset + border) | |
6351 ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : this.offset.scroll.top ) | |
6352 ), | |
6353 left: ( | |
6354 pageX - // The absolute mouse position | |
6355 this.offset.click.left - // Click offset (relative to the element) | |
6356 this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent | |
6357 this.offset.parent.left + // The offsetParent's offset without borders (offset + border) | |
6358 ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : this.offset.scroll.left ) | |
6359 ) | |
6360 }; | |
6361 | |
6362 }, | |
6363 | |
6364 _clear: function() { | |
6365 this.helper.removeClass("ui-draggable-dragging"); | |
6366 if(this.helper[0] !== this.element[0] && !this.cancelHelperRemoval) { | |
6367 this.helper.remove(); | |
6368 } | |
6369 this.helper = null; | |
6370 this.cancelHelperRemoval = false; | |
6371 }, | |
6372 | |
6373 // From now on bulk stuff - mainly helpers | |
6374 | |
6375 _trigger: function(type, event, ui) { | |
6376 ui = ui || this._uiHash(); | |
6377 $.ui.plugin.call(this, type, [event, ui]); | |
6378 //The absolute position has to be recalculated after plugins | |
6379 if(type === "drag") { | |
6380 this.positionAbs = this._convertPositionTo("absolute"); | |
6381 } | |
6382 return $.Widget.prototype._trigger.call(this, type, event, ui); | |
6383 }, | |
6384 | |
6385 plugins: {}, | |
6386 | |
6387 _uiHash: function() { | |
6388 return { | |
6389 helper: this.helper, | |
6390 position: this.position, | |
6391 originalPosition: this.originalPosition, | |
6392 offset: this.positionAbs | |
6393 }; | |
6394 } | |
6395 | |
6396 }); | |
6397 | |
6398 $.ui.plugin.add("draggable", "connectToSortable", { | |
6399 start: function(event, ui) { | |
6400 | |
6401 var inst = $(this).data("ui-draggable"), o = inst.options, | |
6402 uiSortable = $.extend({}, ui, { item: inst.element }); | |
6403 inst.sortables = []; | |
6404 $(o.connectToSortable).each(function() { | |
6405 var sortable = $.data(this, "ui-sortable"); | |
6406 if (sortable && !sortable.options.disabled) { | |
6407 inst.sortables.push({ | |
6408 instance: sortable, | |
6409 shouldRevert: sortable.options.revert | |
6410 }); | |
6411 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). | |
6412 sortable._trigger("activate", event, uiSortable); | |
6413 } | |
6414 }); | |
6415 | |
6416 }, | |
6417 stop: function(event, ui) { | |
6418 | |
6419 //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper | |
6420 var inst = $(this).data("ui-draggable"), | |
6421 uiSortable = $.extend({}, ui, { item: inst.element }); | |
6422 | |
6423 $.each(inst.sortables, function() { | |
6424 if(this.instance.isOver) { | |
6425 | |
6426 this.instance.isOver = 0; | |
6427 | |
6428 inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance | |
6429 this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work) | |
6430 | |
6431 //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: "valid/invalid" | |
6432 if(this.shouldRevert) { | |
6433 this.instance.options.revert = this.shouldRevert; | |
6434 } | |
6435 | |
6436 //Trigger the stop of the sortable | |
6437 this.instance._mouseStop(event); | |
6438 | |
6439 this.instance.options.helper = this.instance.options._helper; | |
6440 | |
6441 //If the helper has been the original item, restore properties in the sortable | |
6442 if(inst.options.helper === "original") { | |
6443 this.instance.currentItem.css({ top: "auto", left: "auto" }); | |
6444 } | |
6445 | |
6446 } else { | |
6447 this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance | |
6448 this.instance._trigger("deactivate", event, uiSortable); | |
6449 } | |
6450 | |
6451 }); | |
6452 | |
6453 }, | |
6454 drag: function(event, ui) { | |
6455 | |
6456 var inst = $(this).data("ui-draggable"), that = this; | |
6457 | |
6458 $.each(inst.sortables, function() { | |
6459 | |
6460 var innermostIntersecting = false, | |
6461 thisSortable = this; | |
6462 | |
6463 //Copy over some variables to allow calling the sortable's native _intersectsWith | |
6464 this.instance.positionAbs = inst.positionAbs; | |
6465 this.instance.helperProportions = inst.helperProportions; | |
6466 this.instance.offset.click = inst.offset.click; | |
6467 | |
6468 if(this.instance._intersectsWith(this.instance.containerCache)) { | |
6469 innermostIntersecting = true; | |
6470 $.each(inst.sortables, function () { | |
6471 this.instance.positionAbs = inst.positionAbs; | |
6472 this.instance.helperProportions = inst.helperProportions; | |
6473 this.instance.offset.click = inst.offset.click; | |
6474 if (this !== thisSortable && | |
6475 this.instance._intersectsWith(this.instance.containerCache) && | |
6476 $.contains(thisSortable.instance.element[0], this.instance.element[0]) | |
6477 ) { | |
6478 innermostIntersecting = false; | |
6479 } | |
6480 return innermostIntersecting; | |
6481 }); | |
6482 } | |
6483 | |
6484 | |
6485 if(innermostIntersecting) { | |
6486 //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once | |
6487 if(!this.instance.isOver) { | |
6488 | |
6489 this.instance.isOver = 1; | |
6490 //Now we fake the start of dragging for the sortable instance, | |
6491 //by cloning the list group item, appending it to the sortable and using it as inst.currentItem | |
6492 //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) | |
6493 this.instance.currentItem = $(that).clone().removeAttr("id").appendTo(this.instance.element).data("ui-sortable-item", true); | |
6494 this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it | |
6495 this.instance.options.helper = function() { return ui.helper[0]; }; | |
6496 | |
6497 event.target = this.instance.currentItem[0]; | |
6498 this.instance._mouseCapture(event, true); | |
6499 this.instance._mouseStart(event, true, true); | |
6500 | |
6501 //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes | |
6502 this.instance.offset.click.top = inst.offset.click.top; | |
6503 this.instance.offset.click.left = inst.offset.click.left; | |
6504 this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left; | |
6505 this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top; | |
6506 | |
6507 inst._trigger("toSortable", event); | |
6508 inst.dropped = this.instance.element; //draggable revert needs that | |
6509 //hack so receive/update callbacks work (mostly) | |
6510 inst.currentItem = inst.element; | |
6511 this.instance.fromOutside = inst; | |
6512 | |
6513 } | |
6514 | |
6515 //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 | |
6516 if(this.instance.currentItem) { | |
6517 this.instance._mouseDrag(event); | |
6518 } | |
6519 | |
6520 } else { | |
6521 | |
6522 //If it doesn't intersect with the sortable, and it intersected before, | |
6523 //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval | |
6524 if(this.instance.isOver) { | |
6525 | |
6526 this.instance.isOver = 0; | |
6527 this.instance.cancelHelperRemoval = true; | |
6528 | |
6529 //Prevent reverting on this forced stop | |
6530 this.instance.options.revert = false; | |
6531 | |
6532 // The out event needs to be triggered independently | |
6533 this.instance._trigger("out", event, this.instance._uiHash(this.instance)); | |
6534 | |
6535 this.instance._mouseStop(event, true); | |
6536 this.instance.options.helper = this.instance.options._helper; | |
6537 | |
6538 //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size | |
6539 this.instance.currentItem.remove(); | |
6540 if(this.instance.placeholder) { | |
6541 this.instance.placeholder.remove(); | |
6542 } | |
6543 | |
6544 inst._trigger("fromSortable", event); | |
6545 inst.dropped = false; //draggable revert needs that | |
6546 } | |
6547 | |
6548 } | |
6549 | |
6550 }); | |
6551 | |
6552 } | |
6553 }); | |
6554 | |
6555 $.ui.plugin.add("draggable", "cursor", { | |
6556 start: function() { | |
6557 var t = $("body"), o = $(this).data("ui-draggable").options; | |
6558 if (t.css("cursor")) { | |
6559 o._cursor = t.css("cursor"); | |
6560 } | |
6561 t.css("cursor", o.cursor); | |
6562 }, | |
6563 stop: function() { | |
6564 var o = $(this).data("ui-draggable").options; | |
6565 if (o._cursor) { | |
6566 $("body").css("cursor", o._cursor); | |
6567 } | |
6568 } | |
6569 }); | |
6570 | |
6571 $.ui.plugin.add("draggable", "opacity", { | |
6572 start: function(event, ui) { | |
6573 var t = $(ui.helper), o = $(this).data("ui-draggable").options; | |
6574 if(t.css("opacity")) { | |
6575 o._opacity = t.css("opacity"); | |
6576 } | |
6577 t.css("opacity", o.opacity); | |
6578 }, | |
6579 stop: function(event, ui) { | |
6580 var o = $(this).data("ui-draggable").options; | |
6581 if(o._opacity) { | |
6582 $(ui.helper).css("opacity", o._opacity); | |
6583 } | |
6584 } | |
6585 }); | |
6586 | |
6587 $.ui.plugin.add("draggable", "scroll", { | |
6588 start: function() { | |
6589 var i = $(this).data("ui-draggable"); | |
6590 if(i.scrollParent[0] !== document && i.scrollParent[0].tagName !== "HTML") { | |
6591 i.overflowOffset = i.scrollParent.offset(); | |
6592 } | |
6593 }, | |
6594 drag: function( event ) { | |
6595 | |
6596 var i = $(this).data("ui-draggable"), o = i.options, scrolled = false; | |
6597 | |
6598 if(i.scrollParent[0] !== document && i.scrollParent[0].tagName !== "HTML") { | |
6599 | |
6600 if(!o.axis || o.axis !== "x") { | |
6601 if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) { | |
6602 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed; | |
6603 } else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity) { | |
6604 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed; | |
6605 } | |
6606 } | |
6607 | |
6608 if(!o.axis || o.axis !== "y") { | |
6609 if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) { | |
6610 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed; | |
6611 } else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity) { | |
6612 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed; | |
6613 } | |
6614 } | |
6615 | |
6616 } else { | |
6617 | |
6618 if(!o.axis || o.axis !== "x") { | |
6619 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) { | |
6620 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); | |
6621 } else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) { | |
6622 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); | |
6623 } | |
6624 } | |
6625 | |
6626 if(!o.axis || o.axis !== "y") { | |
6627 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) { | |
6628 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); | |
6629 } else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) { | |
6630 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); | |
6631 } | |
6632 } | |
6633 | |
6634 } | |
6635 | |
6636 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) { | |
6637 $.ui.ddmanager.prepareOffsets(i, event); | |
6638 } | |
6639 | |
6640 } | |
6641 }); | |
6642 | |
6643 $.ui.plugin.add("draggable", "snap", { | |
6644 start: function() { | |
6645 | |
6646 var i = $(this).data("ui-draggable"), | |
6647 o = i.options; | |
6648 | |
6649 i.snapElements = []; | |
6650 | |
6651 $(o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap).each(function() { | |
6652 var $t = $(this), | |
6653 $o = $t.offset(); | |
6654 if(this !== i.element[0]) { | |
6655 i.snapElements.push({ | |
6656 item: this, | |
6657 width: $t.outerWidth(), height: $t.outerHeight(), | |
6658 top: $o.top, left: $o.left | |
6659 }); | |
6660 } | |
6661 }); | |
6662 | |
6663 }, | |
6664 drag: function(event, ui) { | |
6665 | |
6666 var ts, bs, ls, rs, l, r, t, b, i, first, | |
6667 inst = $(this).data("ui-draggable"), | |
6668 o = inst.options, | |
6669 d = o.snapTolerance, | |
6670 x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width, | |
6671 y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height; | |
6672 | |
6673 for (i = inst.snapElements.length - 1; i >= 0; i--){ | |
6674 | |
6675 l = inst.snapElements[i].left; | |
6676 r = l + inst.snapElements[i].width; | |
6677 t = inst.snapElements[i].top; | |
6678 b = t + inst.snapElements[i].height; | |
6679 | |
6680 if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d || !$.contains( inst.snapElements[ i ].item.ownerDocument, inst.snapElements[ i ].item ) ) { | |
6681 if(inst.snapElements[i].snapping) { | |
6682 (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); | |
6683 } | |
6684 inst.snapElements[i].snapping = false; | |
6685 continue; | |
6686 } | |
6687 | |
6688 if(o.snapMode !== "inner") { | |
6689 ts = Math.abs(t - y2) <= d; | |
6690 bs = Math.abs(b - y1) <= d; | |
6691 ls = Math.abs(l - x2) <= d; | |
6692 rs = Math.abs(r - x1) <= d; | |
6693 if(ts) { | |
6694 ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top; | |
6695 } | |
6696 if(bs) { | |
6697 ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top; | |
6698 } | |
6699 if(ls) { | |
6700 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left; | |
6701 } | |
6702 if(rs) { | |
6703 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left; | |
6704 } | |
6705 } | |
6706 | |
6707 first = (ts || bs || ls || rs); | |
6708 | |
6709 if(o.snapMode !== "outer") { | |
6710 ts = Math.abs(t - y1) <= d; | |
6711 bs = Math.abs(b - y2) <= d; | |
6712 ls = Math.abs(l - x1) <= d; | |
6713 rs = Math.abs(r - x2) <= d; | |
6714 if(ts) { | |
6715 ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top; | |
6716 } | |
6717 if(bs) { | |
6718 ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top; | |
6719 } | |
6720 if(ls) { | |
6721 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left; | |
6722 } | |
6723 if(rs) { | |
6724 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left; | |
6725 } | |
6726 } | |
6727 | |
6728 if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) { | |
6729 (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); | |
6730 } | |
6731 inst.snapElements[i].snapping = (ts || bs || ls || rs || first); | |
6732 | |
6733 } | |
6734 | |
6735 } | |
6736 }); | |
6737 | |
6738 $.ui.plugin.add("draggable", "stack", { | |
6739 start: function() { | |
6740 var min, | |
6741 o = this.data("ui-draggable").options, | |
6742 group = $.makeArray($(o.stack)).sort(function(a,b) { | |
6743 return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0); | |
6744 }); | |
6745 | |
6746 if (!group.length) { return; } | |
6747 | |
6748 min = parseInt($(group[0]).css("zIndex"), 10) || 0; | |
6749 $(group).each(function(i) { | |
6750 $(this).css("zIndex", min + i); | |
6751 }); | |
6752 this.css("zIndex", (min + group.length)); | |
6753 } | |
6754 }); | |
6755 | |
6756 $.ui.plugin.add("draggable", "zIndex", { | |
6757 start: function(event, ui) { | |
6758 var t = $(ui.helper), o = $(this).data("ui-draggable").options; | |
6759 if(t.css("zIndex")) { | |
6760 o._zIndex = t.css("zIndex"); | |
6761 } | |
6762 t.css("zIndex", o.zIndex); | |
6763 }, | |
6764 stop: function(event, ui) { | |
6765 var o = $(this).data("ui-draggable").options; | |
6766 if(o._zIndex) { | |
6767 $(ui.helper).css("zIndex", o._zIndex); | |
6768 } | |
6769 } | |
6770 }); | |
6771 | |
6772 })(jQuery); | |
6773 (function( $, undefined ) { | |
6774 | |
6775 function isOverAxis( x, reference, size ) { | |
6776 return ( x > reference ) && ( x < ( reference + size ) ); | |
6777 } | |
6778 | |
6779 $.widget("ui.droppable", { | |
6780 version: "1.10.4", | |
6781 widgetEventPrefix: "drop", | |
6782 options: { | |
6783 accept: "*", | |
6784 activeClass: false, | |
6785 addClasses: true, | |
6786 greedy: false, | |
6787 hoverClass: false, | |
6788 scope: "default", | |
6789 tolerance: "intersect", | |
6790 | |
6791 // callbacks | |
6792 activate: null, | |
6793 deactivate: null, | |
6794 drop: null, | |
6795 out: null, | |
6796 over: null | |
6797 }, | |
6798 _create: function() { | |
6799 | |
6800 var proportions, | |
6801 o = this.options, | |
6802 accept = o.accept; | |
6803 | |
6804 this.isover = false; | |
6805 this.isout = true; | |
6806 | |
6807 this.accept = $.isFunction(accept) ? accept : function(d) { | |
6808 return d.is(accept); | |
6809 }; | |
6810 | |
6811 this.proportions = function( /* valueToWrite */ ) { | |
6812 if ( arguments.length ) { | |
6813 // Store the droppable's proportions | |
6814 proportions = arguments[ 0 ]; | |
6815 } else { | |
6816 // Retrieve or derive the droppable's proportions | |
6817 return proportions ? | |
6818 proportions : | |
6819 proportions = { | |
6820 width: this.element[ 0 ].offsetWidth, | |
6821 height: this.element[ 0 ].offsetHeight | |
6822 }; | |
6823 } | |
6824 }; | |
6825 | |
6826 // Add the reference and positions to the manager | |
6827 $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || []; | |
6828 $.ui.ddmanager.droppables[o.scope].push(this); | |
6829 | |
6830 (o.addClasses && this.element.addClass("ui-droppable")); | |
6831 | |
6832 }, | |
6833 | |
6834 _destroy: function() { | |
6835 var i = 0, | |
6836 drop = $.ui.ddmanager.droppables[this.options.scope]; | |
6837 | |
6838 for ( ; i < drop.length; i++ ) { | |
6839 if ( drop[i] === this ) { | |
6840 drop.splice(i, 1); | |
6841 } | |
6842 } | |
6843 | |
6844 this.element.removeClass("ui-droppable ui-droppable-disabled"); | |
6845 }, | |
6846 | |
6847 _setOption: function(key, value) { | |
6848 | |
6849 if(key === "accept") { | |
6850 this.accept = $.isFunction(value) ? value : function(d) { | |
6851 return d.is(value); | |
6852 }; | |
6853 } | |
6854 $.Widget.prototype._setOption.apply(this, arguments); | |
6855 }, | |
6856 | |
6857 _activate: function(event) { | |
6858 var draggable = $.ui.ddmanager.current; | |
6859 if(this.options.activeClass) { | |
6860 this.element.addClass(this.options.activeClass); | |
6861 } | |
6862 if(draggable){ | |
6863 this._trigger("activate", event, this.ui(draggable)); | |
6864 } | |
6865 }, | |
6866 | |
6867 _deactivate: function(event) { | |
6868 var draggable = $.ui.ddmanager.current; | |
6869 if(this.options.activeClass) { | |
6870 this.element.removeClass(this.options.activeClass); | |
6871 } | |
6872 if(draggable){ | |
6873 this._trigger("deactivate", event, this.ui(draggable)); | |
6874 } | |
6875 }, | |
6876 | |
6877 _over: function(event) { | |
6878 | |
6879 var draggable = $.ui.ddmanager.current; | |
6880 | |
6881 // Bail if draggable and droppable are same element | |
6882 if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) { | |
6883 return; | |
6884 } | |
6885 | |
6886 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { | |
6887 if(this.options.hoverClass) { | |
6888 this.element.addClass(this.options.hoverClass); | |
6889 } | |
6890 this._trigger("over", event, this.ui(draggable)); | |
6891 } | |
6892 | |
6893 }, | |
6894 | |
6895 _out: function(event) { | |
6896 | |
6897 var draggable = $.ui.ddmanager.current; | |
6898 | |
6899 // Bail if draggable and droppable are same element | |
6900 if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) { | |
6901 return; | |
6902 } | |
6903 | |
6904 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { | |
6905 if(this.options.hoverClass) { | |
6906 this.element.removeClass(this.options.hoverClass); | |
6907 } | |
6908 this._trigger("out", event, this.ui(draggable)); | |
6909 } | |
6910 | |
6911 }, | |
6912 | |
6913 _drop: function(event,custom) { | |
6914 | |
6915 var draggable = custom || $.ui.ddmanager.current, | |
6916 childrenIntersection = false; | |
6917 | |
6918 // Bail if draggable and droppable are same element | |
6919 if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) { | |
6920 return false; | |
6921 } | |
6922 | |
6923 this.element.find(":data(ui-droppable)").not(".ui-draggable-dragging").each(function() { | |
6924 var inst = $.data(this, "ui-droppable"); | |
6925 if( | |
6926 inst.options.greedy && | |
6927 !inst.options.disabled && | |
6928 inst.options.scope === draggable.options.scope && | |
6929 inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element)) && | |
6930 $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance) | |
6931 ) { childrenIntersection = true; return false; } | |
6932 }); | |
6933 if(childrenIntersection) { | |
6934 return false; | |
6935 } | |
6936 | |
6937 if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { | |
6938 if(this.options.activeClass) { | |
6939 this.element.removeClass(this.options.activeClass); | |
6940 } | |
6941 if(this.options.hoverClass) { | |
6942 this.element.removeClass(this.options.hoverClass); | |
6943 } | |
6944 this._trigger("drop", event, this.ui(draggable)); | |
6945 return this.element; | |
6946 } | |
6947 | |
6948 return false; | |
6949 | |
6950 }, | |
6951 | |
6952 ui: function(c) { | |
6953 return { | |
6954 draggable: (c.currentItem || c.element), | |
6955 helper: c.helper, | |
6956 position: c.position, | |
6957 offset: c.positionAbs | |
6958 }; | |
6959 } | |
6960 | |
6961 }); | |
6962 | |
6963 $.ui.intersect = function(draggable, droppable, toleranceMode) { | |
6964 | |
6965 if (!droppable.offset) { | |
6966 return false; | |
6967 } | |
6968 | |
6969 var draggableLeft, draggableTop, | |
6970 x1 = (draggable.positionAbs || draggable.position.absolute).left, | |
6971 y1 = (draggable.positionAbs || draggable.position.absolute).top, | |
6972 x2 = x1 + draggable.helperProportions.width, | |
6973 y2 = y1 + draggable.helperProportions.height, | |
6974 l = droppable.offset.left, | |
6975 t = droppable.offset.top, | |
6976 r = l + droppable.proportions().width, | |
6977 b = t + droppable.proportions().height; | |
6978 | |
6979 switch (toleranceMode) { | |
6980 case "fit": | |
6981 return (l <= x1 && x2 <= r && t <= y1 && y2 <= b); | |
6982 case "intersect": | |
6983 return (l < x1 + (draggable.helperProportions.width / 2) && // Right Half | |
6984 x2 - (draggable.helperProportions.width / 2) < r && // Left Half | |
6985 t < y1 + (draggable.helperProportions.height / 2) && // Bottom Half | |
6986 y2 - (draggable.helperProportions.height / 2) < b ); // Top Half | |
6987 case "pointer": | |
6988 draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left); | |
6989 draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top); | |
6990 return isOverAxis( draggableTop, t, droppable.proportions().height ) && isOverAxis( draggableLeft, l, droppable.proportions().width ); | |
6991 case "touch": | |
6992 return ( | |
6993 (y1 >= t && y1 <= b) || // Top edge touching | |
6994 (y2 >= t && y2 <= b) || // Bottom edge touching | |
6995 (y1 < t && y2 > b) // Surrounded vertically | |
6996 ) && ( | |
6997 (x1 >= l && x1 <= r) || // Left edge touching | |
6998 (x2 >= l && x2 <= r) || // Right edge touching | |
6999 (x1 < l && x2 > r) // Surrounded horizontally | |
7000 ); | |
7001 default: | |
7002 return false; | |
7003 } | |
7004 | |
7005 }; | |
7006 | |
7007 /* | |
7008 This manager tracks offsets of draggables and droppables | |
7009 */ | |
7010 $.ui.ddmanager = { | |
7011 current: null, | |
7012 droppables: { "default": [] }, | |
7013 prepareOffsets: function(t, event) { | |
7014 | |
7015 var i, j, | |
7016 m = $.ui.ddmanager.droppables[t.options.scope] || [], | |
7017 type = event ? event.type : null, // workaround for #2317 | |
7018 list = (t.currentItem || t.element).find(":data(ui-droppable)").addBack(); | |
7019 | |
7020 droppablesLoop: for (i = 0; i < m.length; i++) { | |
7021 | |
7022 //No disabled and non-accepted | |
7023 if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) { | |
7024 continue; | |
7025 } | |
7026 | |
7027 // Filter out elements in the current dragged item | |
7028 for (j=0; j < list.length; j++) { | |
7029 if(list[j] === m[i].element[0]) { | |
7030 m[i].proportions().height = 0; | |
7031 continue droppablesLoop; | |
7032 } | |
7033 } | |
7034 | |
7035 m[i].visible = m[i].element.css("display") !== "none"; | |
7036 if(!m[i].visible) { | |
7037 continue; | |
7038 } | |
7039 | |
7040 //Activate the droppable if used directly from draggables | |
7041 if(type === "mousedown") { | |
7042 m[i]._activate.call(m[i], event); | |
7043 } | |
7044 | |
7045 m[ i ].offset = m[ i ].element.offset(); | |
7046 m[ i ].proportions({ width: m[ i ].element[ 0 ].offsetWidth, height: m[ i ].element[ 0 ].offsetHeight }); | |
7047 | |
7048 } | |
7049 | |
7050 }, | |
7051 drop: function(draggable, event) { | |
7052 | |
7053 var dropped = false; | |
7054 // Create a copy of the droppables in case the list changes during the drop (#9116) | |
7055 $.each(($.ui.ddmanager.droppables[draggable.options.scope] || []).slice(), function() { | |
7056 | |
7057 if(!this.options) { | |
7058 return; | |
7059 } | |
7060 if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance)) { | |
7061 dropped = this._drop.call(this, event) || dropped; | |
7062 } | |
7063 | |
7064 if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { | |
7065 this.isout = true; | |
7066 this.isover = false; | |
7067 this._deactivate.call(this, event); | |
7068 } | |
7069 | |
7070 }); | |
7071 return dropped; | |
7072 | |
7073 }, | |
7074 dragStart: function( draggable, event ) { | |
7075 //Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003) | |
7076 draggable.element.parentsUntil( "body" ).bind( "scroll.droppable", function() { | |
7077 if( !draggable.options.refreshPositions ) { | |
7078 $.ui.ddmanager.prepareOffsets( draggable, event ); | |
7079 } | |
7080 }); | |
7081 }, | |
7082 drag: function(draggable, event) { | |
7083 | |
7084 //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse. | |
7085 if(draggable.options.refreshPositions) { | |
7086 $.ui.ddmanager.prepareOffsets(draggable, event); | |
7087 } | |
7088 | |
7089 //Run through all droppables and check their positions based on specific tolerance options | |
7090 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() { | |
7091 | |
7092 if(this.options.disabled || this.greedyChild || !this.visible) { | |
7093 return; | |
7094 } | |
7095 | |
7096 var parentInstance, scope, parent, | |
7097 intersects = $.ui.intersect(draggable, this, this.options.tolerance), | |
7098 c = !intersects && this.isover ? "isout" : (intersects && !this.isover ? "isover" : null); | |
7099 if(!c) { | |
7100 return; | |
7101 } | |
7102 | |
7103 if (this.options.greedy) { | |
7104 // find droppable parents with same scope | |
7105 scope = this.options.scope; | |
7106 parent = this.element.parents(":data(ui-droppable)").filter(function () { | |
7107 return $.data(this, "ui-droppable").options.scope === scope; | |
7108 }); | |
7109 | |
7110 if (parent.length) { | |
7111 parentInstance = $.data(parent[0], "ui-droppable"); | |
7112 parentInstance.greedyChild = (c === "isover"); | |
7113 } | |
7114 } | |
7115 | |
7116 // we just moved into a greedy child | |
7117 if (parentInstance && c === "isover") { | |
7118 parentInstance.isover = false; | |
7119 parentInstance.isout = true; | |
7120 parentInstance._out.call(parentInstance, event); | |
7121 } | |
7122 | |
7123 this[c] = true; | |
7124 this[c === "isout" ? "isover" : "isout"] = false; | |
7125 this[c === "isover" ? "_over" : "_out"].call(this, event); | |
7126 | |
7127 // we just moved out of a greedy child | |
7128 if (parentInstance && c === "isout") { | |
7129 parentInstance.isout = false; | |
7130 parentInstance.isover = true; | |
7131 parentInstance._over.call(parentInstance, event); | |
7132 } | |
7133 }); | |
7134 | |
7135 }, | |
7136 dragStop: function( draggable, event ) { | |
7137 draggable.element.parentsUntil( "body" ).unbind( "scroll.droppable" ); | |
7138 //Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003) | |
7139 if( !draggable.options.refreshPositions ) { | |
7140 $.ui.ddmanager.prepareOffsets( draggable, event ); | |
7141 } | |
7142 } | |
7143 }; | |
7144 | |
7145 })(jQuery); | |
7146 (function($, undefined) { | |
7147 | |
7148 var dataSpace = "ui-effects-"; | |
7149 | |
7150 $.effects = { | |
7151 effect: {} | |
7152 }; | |
7153 | |
7154 /*! | |
7155 * jQuery Color Animations v2.1.2 | |
7156 * https://github.com/jquery/jquery-color | |
7157 * | |
7158 * Copyright 2013 jQuery Foundation and other contributors | |
7159 * Released under the MIT license. | |
7160 * http://jquery.org/license | |
7161 * | |
7162 * Date: Wed Jan 16 08:47:09 2013 -0600 | |
7163 */ | |
7164 (function( jQuery, undefined ) { | |
7165 | |
7166 var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor", | |
7167 | |
7168 // plusequals test for += 100 -= 100 | |
7169 rplusequals = /^([\-+])=\s*(\d+\.?\d*)/, | |
7170 // a set of RE's that can match strings and generate color tuples. | |
7171 stringParsers = [{ | |
7172 re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, | |
7173 parse: function( execResult ) { | |
7174 return [ | |
7175 execResult[ 1 ], | |
7176 execResult[ 2 ], | |
7177 execResult[ 3 ], | |
7178 execResult[ 4 ] | |
7179 ]; | |
7180 } | |
7181 }, { | |
7182 re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, | |
7183 parse: function( execResult ) { | |
7184 return [ | |
7185 execResult[ 1 ] * 2.55, | |
7186 execResult[ 2 ] * 2.55, | |
7187 execResult[ 3 ] * 2.55, | |
7188 execResult[ 4 ] | |
7189 ]; | |
7190 } | |
7191 }, { | |
7192 // this regex ignores A-F because it's compared against an already lowercased string | |
7193 re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/, | |
7194 parse: function( execResult ) { | |
7195 return [ | |
7196 parseInt( execResult[ 1 ], 16 ), | |
7197 parseInt( execResult[ 2 ], 16 ), | |
7198 parseInt( execResult[ 3 ], 16 ) | |
7199 ]; | |
7200 } | |
7201 }, { | |
7202 // this regex ignores A-F because it's compared against an already lowercased string | |
7203 re: /#([a-f0-9])([a-f0-9])([a-f0-9])/, | |
7204 parse: function( execResult ) { | |
7205 return [ | |
7206 parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ), | |
7207 parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ), | |
7208 parseInt( execResult[ 3 ] + execResult[ 3 ], 16 ) | |
7209 ]; | |
7210 } | |
7211 }, { | |
7212 re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, | |
7213 space: "hsla", | |
7214 parse: function( execResult ) { | |
7215 return [ | |
7216 execResult[ 1 ], | |
7217 execResult[ 2 ] / 100, | |
7218 execResult[ 3 ] / 100, | |
7219 execResult[ 4 ] | |
7220 ]; | |
7221 } | |
7222 }], | |
7223 | |
7224 // jQuery.Color( ) | |
7225 color = jQuery.Color = function( color, green, blue, alpha ) { | |
7226 return new jQuery.Color.fn.parse( color, green, blue, alpha ); | |
7227 }, | |
7228 spaces = { | |
7229 rgba: { | |
7230 props: { | |
7231 red: { | |
7232 idx: 0, | |
7233 type: "byte" | |
7234 }, | |
7235 green: { | |
7236 idx: 1, | |
7237 type: "byte" | |
7238 }, | |
7239 blue: { | |
7240 idx: 2, | |
7241 type: "byte" | |
7242 } | |
7243 } | |
7244 }, | |
7245 | |
7246 hsla: { | |
7247 props: { | |
7248 hue: { | |
7249 idx: 0, | |
7250 type: "degrees" | |
7251 }, | |
7252 saturation: { | |
7253 idx: 1, | |
7254 type: "percent" | |
7255 }, | |
7256 lightness: { | |
7257 idx: 2, | |
7258 type: "percent" | |
7259 } | |
7260 } | |
7261 } | |
7262 }, | |
7263 propTypes = { | |
7264 "byte": { | |
7265 floor: true, | |
7266 max: 255 | |
7267 }, | |
7268 "percent": { | |
7269 max: 1 | |
7270 }, | |
7271 "degrees": { | |
7272 mod: 360, | |
7273 floor: true | |
7274 } | |
7275 }, | |
7276 support = color.support = {}, | |
7277 | |
7278 // element for support tests | |
7279 supportElem = jQuery( "<p>" )[ 0 ], | |
7280 | |
7281 // colors = jQuery.Color.names | |
7282 colors, | |
7283 | |
7284 // local aliases of functions called often | |
7285 each = jQuery.each; | |
7286 | |
7287 // determine rgba support immediately | |
7288 supportElem.style.cssText = "background-color:rgba(1,1,1,.5)"; | |
7289 support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1; | |
7290 | |
7291 // define cache name and alpha properties | |
7292 // for rgba and hsla spaces | |
7293 each( spaces, function( spaceName, space ) { | |
7294 space.cache = "_" + spaceName; | |
7295 space.props.alpha = { | |
7296 idx: 3, | |
7297 type: "percent", | |
7298 def: 1 | |
7299 }; | |
7300 }); | |
7301 | |
7302 function clamp( value, prop, allowEmpty ) { | |
7303 var type = propTypes[ prop.type ] || {}; | |
7304 | |
7305 if ( value == null ) { | |
7306 return (allowEmpty || !prop.def) ? null : prop.def; | |
7307 } | |
7308 | |
7309 // ~~ is an short way of doing floor for positive numbers | |
7310 value = type.floor ? ~~value : parseFloat( value ); | |
7311 | |
7312 // IE will pass in empty strings as value for alpha, | |
7313 // which will hit this case | |
7314 if ( isNaN( value ) ) { | |
7315 return prop.def; | |
7316 } | |
7317 | |
7318 if ( type.mod ) { | |
7319 // we add mod before modding to make sure that negatives values | |
7320 // get converted properly: -10 -> 350 | |
7321 return (value + type.mod) % type.mod; | |
7322 } | |
7323 | |
7324 // for now all property types without mod have min and max | |
7325 return 0 > value ? 0 : type.max < value ? type.max : value; | |
7326 } | |
7327 | |
7328 function stringParse( string ) { | |
7329 var inst = color(), | |
7330 rgba = inst._rgba = []; | |
7331 | |
7332 string = string.toLowerCase(); | |
7333 | |
7334 each( stringParsers, function( i, parser ) { | |
7335 var parsed, | |
7336 match = parser.re.exec( string ), | |
7337 values = match && parser.parse( match ), | |
7338 spaceName = parser.space || "rgba"; | |
7339 | |
7340 if ( values ) { | |
7341 parsed = inst[ spaceName ]( values ); | |
7342 | |
7343 // if this was an rgba parse the assignment might happen twice | |
7344 // oh well.... | |
7345 inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ]; | |
7346 rgba = inst._rgba = parsed._rgba; | |
7347 | |
7348 // exit each( stringParsers ) here because we matched | |
7349 return false; | |
7350 } | |
7351 }); | |
7352 | |
7353 // Found a stringParser that handled it | |
7354 if ( rgba.length ) { | |
7355 | |
7356 // if this came from a parsed string, force "transparent" when alpha is 0 | |
7357 // chrome, (and maybe others) return "transparent" as rgba(0,0,0,0) | |
7358 if ( rgba.join() === "0,0,0,0" ) { | |
7359 jQuery.extend( rgba, colors.transparent ); | |
7360 } | |
7361 return inst; | |
7362 } | |
7363 | |
7364 // named colors | |
7365 return colors[ string ]; | |
7366 } | |
7367 | |
7368 color.fn = jQuery.extend( color.prototype, { | |
7369 parse: function( red, green, blue, alpha ) { | |
7370 if ( red === undefined ) { | |
7371 this._rgba = [ null, null, null, null ]; | |
7372 return this; | |
7373 } | |
7374 if ( red.jquery || red.nodeType ) { | |
7375 red = jQuery( red ).css( green ); | |
7376 green = undefined; | |
7377 } | |
7378 | |
7379 var inst = this, | |
7380 type = jQuery.type( red ), | |
7381 rgba = this._rgba = []; | |
7382 | |
7383 // more than 1 argument specified - assume ( red, green, blue, alpha ) | |
7384 if ( green !== undefined ) { | |
7385 red = [ red, green, blue, alpha ]; | |
7386 type = "array"; | |
7387 } | |
7388 | |
7389 if ( type === "string" ) { | |
7390 return this.parse( stringParse( red ) || colors._default ); | |
7391 } | |
7392 | |
7393 if ( type === "array" ) { | |
7394 each( spaces.rgba.props, function( key, prop ) { | |
7395 rgba[ prop.idx ] = clamp( red[ prop.idx ], prop ); | |
7396 }); | |
7397 return this; | |
7398 } | |
7399 | |
7400 if ( type === "object" ) { | |
7401 if ( red instanceof color ) { | |
7402 each( spaces, function( spaceName, space ) { | |
7403 if ( red[ space.cache ] ) { | |
7404 inst[ space.cache ] = red[ space.cache ].slice(); | |
7405 } | |
7406 }); | |
7407 } else { | |
7408 each( spaces, function( spaceName, space ) { | |
7409 var cache = space.cache; | |
7410 each( space.props, function( key, prop ) { | |
7411 | |
7412 // if the cache doesn't exist, and we know how to convert | |
7413 if ( !inst[ cache ] && space.to ) { | |
7414 | |
7415 // if the value was null, we don't need to copy it | |
7416 // if the key was alpha, we don't need to copy it either | |
7417 if ( key === "alpha" || red[ key ] == null ) { | |
7418 return; | |
7419 } | |
7420 inst[ cache ] = space.to( inst._rgba ); | |
7421 } | |
7422 | |
7423 // this is the only case where we allow nulls for ALL properties. | |
7424 // call clamp with alwaysAllowEmpty | |
7425 inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true ); | |
7426 }); | |
7427 | |
7428 // everything defined but alpha? | |
7429 if ( inst[ cache ] && jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) { | |
7430 // use the default of 1 | |
7431 inst[ cache ][ 3 ] = 1; | |
7432 if ( space.from ) { | |
7433 inst._rgba = space.from( inst[ cache ] ); | |
7434 } | |
7435 } | |
7436 }); | |
7437 } | |
7438 return this; | |
7439 } | |
7440 }, | |
7441 is: function( compare ) { | |
7442 var is = color( compare ), | |
7443 same = true, | |
7444 inst = this; | |
7445 | |
7446 each( spaces, function( _, space ) { | |
7447 var localCache, | |
7448 isCache = is[ space.cache ]; | |
7449 if (isCache) { | |
7450 localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || []; | |
7451 each( space.props, function( _, prop ) { | |
7452 if ( isCache[ prop.idx ] != null ) { | |
7453 same = ( isCache[ prop.idx ] === localCache[ prop.idx ] ); | |
7454 return same; | |
7455 } | |
7456 }); | |
7457 } | |
7458 return same; | |
7459 }); | |
7460 return same; | |
7461 }, | |
7462 _space: function() { | |
7463 var used = [], | |
7464 inst = this; | |
7465 each( spaces, function( spaceName, space ) { | |
7466 if ( inst[ space.cache ] ) { | |
7467 used.push( spaceName ); | |
7468 } | |
7469 }); | |
7470 return used.pop(); | |
7471 }, | |
7472 transition: function( other, distance ) { | |
7473 var end = color( other ), | |
7474 spaceName = end._space(), | |
7475 space = spaces[ spaceName ], | |
7476 startColor = this.alpha() === 0 ? color( "transparent" ) : this, | |
7477 start = startColor[ space.cache ] || space.to( startColor._rgba ), | |
7478 result = start.slice(); | |
7479 | |
7480 end = end[ space.cache ]; | |
7481 each( space.props, function( key, prop ) { | |
7482 var index = prop.idx, | |
7483 startValue = start[ index ], | |
7484 endValue = end[ index ], | |
7485 type = propTypes[ prop.type ] || {}; | |
7486 | |
7487 // if null, don't override start value | |
7488 if ( endValue === null ) { | |
7489 return; | |
7490 } | |
7491 // if null - use end | |
7492 if ( startValue === null ) { | |
7493 result[ index ] = endValue; | |
7494 } else { | |
7495 if ( type.mod ) { | |
7496 if ( endValue - startValue > type.mod / 2 ) { | |
7497 startValue += type.mod; | |
7498 } else if ( startValue - endValue > type.mod / 2 ) { | |
7499 startValue -= type.mod; | |
7500 } | |
7501 } | |
7502 result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop ); | |
7503 } | |
7504 }); | |
7505 return this[ spaceName ]( result ); | |
7506 }, | |
7507 blend: function( opaque ) { | |
7508 // if we are already opaque - return ourself | |
7509 if ( this._rgba[ 3 ] === 1 ) { | |
7510 return this; | |
7511 } | |
7512 | |
7513 var rgb = this._rgba.slice(), | |
7514 a = rgb.pop(), | |
7515 blend = color( opaque )._rgba; | |
7516 | |
7517 return color( jQuery.map( rgb, function( v, i ) { | |
7518 return ( 1 - a ) * blend[ i ] + a * v; | |
7519 })); | |
7520 }, | |
7521 toRgbaString: function() { | |
7522 var prefix = "rgba(", | |
7523 rgba = jQuery.map( this._rgba, function( v, i ) { | |
7524 return v == null ? ( i > 2 ? 1 : 0 ) : v; | |
7525 }); | |
7526 | |
7527 if ( rgba[ 3 ] === 1 ) { | |
7528 rgba.pop(); | |
7529 prefix = "rgb("; | |
7530 } | |
7531 | |
7532 return prefix + rgba.join() + ")"; | |
7533 }, | |
7534 toHslaString: function() { | |
7535 var prefix = "hsla(", | |
7536 hsla = jQuery.map( this.hsla(), function( v, i ) { | |
7537 if ( v == null ) { | |
7538 v = i > 2 ? 1 : 0; | |
7539 } | |
7540 | |
7541 // catch 1 and 2 | |
7542 if ( i && i < 3 ) { | |
7543 v = Math.round( v * 100 ) + "%"; | |
7544 } | |
7545 return v; | |
7546 }); | |
7547 | |
7548 if ( hsla[ 3 ] === 1 ) { | |
7549 hsla.pop(); | |
7550 prefix = "hsl("; | |
7551 } | |
7552 return prefix + hsla.join() + ")"; | |
7553 }, | |
7554 toHexString: function( includeAlpha ) { | |
7555 var rgba = this._rgba.slice(), | |
7556 alpha = rgba.pop(); | |
7557 | |
7558 if ( includeAlpha ) { | |
7559 rgba.push( ~~( alpha * 255 ) ); | |
7560 } | |
7561 | |
7562 return "#" + jQuery.map( rgba, function( v ) { | |
7563 | |
7564 // default to 0 when nulls exist | |
7565 v = ( v || 0 ).toString( 16 ); | |
7566 return v.length === 1 ? "0" + v : v; | |
7567 }).join(""); | |
7568 }, | |
7569 toString: function() { | |
7570 return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString(); | |
7571 } | |
7572 }); | |
7573 color.fn.parse.prototype = color.fn; | |
7574 | |
7575 // hsla conversions adapted from: | |
7576 // https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021 | |
7577 | |
7578 function hue2rgb( p, q, h ) { | |
7579 h = ( h + 1 ) % 1; | |
7580 if ( h * 6 < 1 ) { | |
7581 return p + (q - p) * h * 6; | |
7582 } | |
7583 if ( h * 2 < 1) { | |
7584 return q; | |
7585 } | |
7586 if ( h * 3 < 2 ) { | |
7587 return p + (q - p) * ((2/3) - h) * 6; | |
7588 } | |
7589 return p; | |
7590 } | |
7591 | |
7592 spaces.hsla.to = function ( rgba ) { | |
7593 if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) { | |
7594 return [ null, null, null, rgba[ 3 ] ]; | |
7595 } | |
7596 var r = rgba[ 0 ] / 255, | |
7597 g = rgba[ 1 ] / 255, | |
7598 b = rgba[ 2 ] / 255, | |
7599 a = rgba[ 3 ], | |
7600 max = Math.max( r, g, b ), | |
7601 min = Math.min( r, g, b ), | |
7602 diff = max - min, | |
7603 add = max + min, | |
7604 l = add * 0.5, | |
7605 h, s; | |
7606 | |
7607 if ( min === max ) { | |
7608 h = 0; | |
7609 } else if ( r === max ) { | |
7610 h = ( 60 * ( g - b ) / diff ) + 360; | |
7611 } else if ( g === max ) { | |
7612 h = ( 60 * ( b - r ) / diff ) + 120; | |
7613 } else { | |
7614 h = ( 60 * ( r - g ) / diff ) + 240; | |
7615 } | |
7616 | |
7617 // chroma (diff) == 0 means greyscale which, by definition, saturation = 0% | |
7618 // otherwise, saturation is based on the ratio of chroma (diff) to lightness (add) | |
7619 if ( diff === 0 ) { | |
7620 s = 0; | |
7621 } else if ( l <= 0.5 ) { | |
7622 s = diff / add; | |
7623 } else { | |
7624 s = diff / ( 2 - add ); | |
7625 } | |
7626 return [ Math.round(h) % 360, s, l, a == null ? 1 : a ]; | |
7627 }; | |
7628 | |
7629 spaces.hsla.from = function ( hsla ) { | |
7630 if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) { | |
7631 return [ null, null, null, hsla[ 3 ] ]; | |
7632 } | |
7633 var h = hsla[ 0 ] / 360, | |
7634 s = hsla[ 1 ], | |
7635 l = hsla[ 2 ], | |
7636 a = hsla[ 3 ], | |
7637 q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s, | |
7638 p = 2 * l - q; | |
7639 | |
7640 return [ | |
7641 Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ), | |
7642 Math.round( hue2rgb( p, q, h ) * 255 ), | |
7643 Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ), | |
7644 a | |
7645 ]; | |
7646 }; | |
7647 | |
7648 | |
7649 each( spaces, function( spaceName, space ) { | |
7650 var props = space.props, | |
7651 cache = space.cache, | |
7652 to = space.to, | |
7653 from = space.from; | |
7654 | |
7655 // makes rgba() and hsla() | |
7656 color.fn[ spaceName ] = function( value ) { | |
7657 | |
7658 // generate a cache for this space if it doesn't exist | |
7659 if ( to && !this[ cache ] ) { | |
7660 this[ cache ] = to( this._rgba ); | |
7661 } | |
7662 if ( value === undefined ) { | |
7663 return this[ cache ].slice(); | |
7664 } | |
7665 | |
7666 var ret, | |
7667 type = jQuery.type( value ), | |
7668 arr = ( type === "array" || type === "object" ) ? value : arguments, | |
7669 local = this[ cache ].slice(); | |
7670 | |
7671 each( props, function( key, prop ) { | |
7672 var val = arr[ type === "object" ? key : prop.idx ]; | |
7673 if ( val == null ) { | |
7674 val = local[ prop.idx ]; | |
7675 } | |
7676 local[ prop.idx ] = clamp( val, prop ); | |
7677 }); | |
7678 | |
7679 if ( from ) { | |
7680 ret = color( from( local ) ); | |
7681 ret[ cache ] = local; | |
7682 return ret; | |
7683 } else { | |
7684 return color( local ); | |
7685 } | |
7686 }; | |
7687 | |
7688 // makes red() green() blue() alpha() hue() saturation() lightness() | |
7689 each( props, function( key, prop ) { | |
7690 // alpha is included in more than one space | |
7691 if ( color.fn[ key ] ) { | |
7692 return; | |
7693 } | |
7694 color.fn[ key ] = function( value ) { | |
7695 var vtype = jQuery.type( value ), | |
7696 fn = ( key === "alpha" ? ( this._hsla ? "hsla" : "rgba" ) : spaceName ), | |
7697 local = this[ fn ](), | |
7698 cur = local[ prop.idx ], | |
7699 match; | |
7700 | |
7701 if ( vtype === "undefined" ) { | |
7702 return cur; | |
7703 } | |
7704 | |
7705 if ( vtype === "function" ) { | |
7706 value = value.call( this, cur ); | |
7707 vtype = jQuery.type( value ); | |
7708 } | |
7709 if ( value == null && prop.empty ) { | |
7710 return this; | |
7711 } | |
7712 if ( vtype === "string" ) { | |
7713 match = rplusequals.exec( value ); | |
7714 if ( match ) { | |
7715 value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 ); | |
7716 } | |
7717 } | |
7718 local[ prop.idx ] = value; | |
7719 return this[ fn ]( local ); | |
7720 }; | |
7721 }); | |
7722 }); | |
7723 | |
7724 // add cssHook and .fx.step function for each named hook. | |
7725 // accept a space separated string of properties | |
7726 color.hook = function( hook ) { | |
7727 var hooks = hook.split( " " ); | |
7728 each( hooks, function( i, hook ) { | |
7729 jQuery.cssHooks[ hook ] = { | |
7730 set: function( elem, value ) { | |
7731 var parsed, curElem, | |
7732 backgroundColor = ""; | |
7733 | |
7734 if ( value !== "transparent" && ( jQuery.type( value ) !== "string" || ( parsed = stringParse( value ) ) ) ) { | |
7735 value = color( parsed || value ); | |
7736 if ( !support.rgba && value._rgba[ 3 ] !== 1 ) { | |
7737 curElem = hook === "backgroundColor" ? elem.parentNode : elem; | |
7738 while ( | |
7739 (backgroundColor === "" || backgroundColor === "transparent") && | |
7740 curElem && curElem.style | |
7741 ) { | |
7742 try { | |
7743 backgroundColor = jQuery.css( curElem, "backgroundColor" ); | |
7744 curElem = curElem.parentNode; | |
7745 } catch ( e ) { | |
7746 } | |
7747 } | |
7748 | |
7749 value = value.blend( backgroundColor && backgroundColor !== "transparent" ? | |
7750 backgroundColor : | |
7751 "_default" ); | |
7752 } | |
7753 | |
7754 value = value.toRgbaString(); | |
7755 } | |
7756 try { | |
7757 elem.style[ hook ] = value; | |
7758 } catch( e ) { | |
7759 // wrapped to prevent IE from throwing errors on "invalid" values like 'auto' or 'inherit' | |
7760 } | |
7761 } | |
7762 }; | |
7763 jQuery.fx.step[ hook ] = function( fx ) { | |
7764 if ( !fx.colorInit ) { | |
7765 fx.start = color( fx.elem, hook ); | |
7766 fx.end = color( fx.end ); | |
7767 fx.colorInit = true; | |
7768 } | |
7769 jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) ); | |
7770 }; | |
7771 }); | |
7772 | |
7773 }; | |
7774 | |
7775 color.hook( stepHooks ); | |
7776 | |
7777 jQuery.cssHooks.borderColor = { | |
7778 expand: function( value ) { | |
7779 var expanded = {}; | |
7780 | |
7781 each( [ "Top", "Right", "Bottom", "Left" ], function( i, part ) { | |
7782 expanded[ "border" + part + "Color" ] = value; | |
7783 }); | |
7784 return expanded; | |
7785 } | |
7786 }; | |
7787 | |
7788 // Basic color names only. | |
7789 // Usage of any of the other color names requires adding yourself or including | |
7790 // jquery.color.svg-names.js. | |
7791 colors = jQuery.Color.names = { | |
7792 // 4.1. Basic color keywords | |
7793 aqua: "#00ffff", | |
7794 black: "#000000", | |
7795 blue: "#0000ff", | |
7796 fuchsia: "#ff00ff", | |
7797 gray: "#808080", | |
7798 green: "#008000", | |
7799 lime: "#00ff00", | |
7800 maroon: "#800000", | |
7801 navy: "#000080", | |
7802 olive: "#808000", | |
7803 purple: "#800080", | |
7804 red: "#ff0000", | |
7805 silver: "#c0c0c0", | |
7806 teal: "#008080", | |
7807 white: "#ffffff", | |
7808 yellow: "#ffff00", | |
7809 | |
7810 // 4.2.3. "transparent" color keyword | |
7811 transparent: [ null, null, null, 0 ], | |
7812 | |
7813 _default: "#ffffff" | |
7814 }; | |
7815 | |
7816 })( jQuery ); | |
7817 | |
7818 | |
7819 /******************************************************************************/ | |
7820 /****************************** CLASS ANIMATIONS ******************************/ | |
7821 /******************************************************************************/ | |
7822 (function() { | |
7823 | |
7824 var classAnimationActions = [ "add", "remove", "toggle" ], | |
7825 shorthandStyles = { | |
7826 border: 1, | |
7827 borderBottom: 1, | |
7828 borderColor: 1, | |
7829 borderLeft: 1, | |
7830 borderRight: 1, | |
7831 borderTop: 1, | |
7832 borderWidth: 1, | |
7833 margin: 1, | |
7834 padding: 1 | |
7835 }; | |
7836 | |
7837 $.each([ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], function( _, prop ) { | |
7838 $.fx.step[ prop ] = function( fx ) { | |
7839 if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) { | |
7840 jQuery.style( fx.elem, prop, fx.end ); | |
7841 fx.setAttr = true; | |
7842 } | |
7843 }; | |
7844 }); | |
7845 | |
7846 function getElementStyles( elem ) { | |
7847 var key, len, | |
7848 style = elem.ownerDocument.defaultView ? | |
7849 elem.ownerDocument.defaultView.getComputedStyle( elem, null ) : | |
7850 elem.currentStyle, | |
7851 styles = {}; | |
7852 | |
7853 if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) { | |
7854 len = style.length; | |
7855 while ( len-- ) { | |
7856 key = style[ len ]; | |
7857 if ( typeof style[ key ] === "string" ) { | |
7858 styles[ $.camelCase( key ) ] = style[ key ]; | |
7859 } | |
7860 } | |
7861 // support: Opera, IE <9 | |
7862 } else { | |
7863 for ( key in style ) { | |
7864 if ( typeof style[ key ] === "string" ) { | |
7865 styles[ key ] = style[ key ]; | |
7866 } | |
7867 } | |
7868 } | |
7869 | |
7870 return styles; | |
7871 } | |
7872 | |
7873 | |
7874 function styleDifference( oldStyle, newStyle ) { | |
7875 var diff = {}, | |
7876 name, value; | |
7877 | |
7878 for ( name in newStyle ) { | |
7879 value = newStyle[ name ]; | |
7880 if ( oldStyle[ name ] !== value ) { | |
7881 if ( !shorthandStyles[ name ] ) { | |
7882 if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) { | |
7883 diff[ name ] = value; | |
7884 } | |
7885 } | |
7886 } | |
7887 } | |
7888 | |
7889 return diff; | |
7890 } | |
7891 | |
7892 // support: jQuery <1.8 | |
7893 if ( !$.fn.addBack ) { | |
7894 $.fn.addBack = function( selector ) { | |
7895 return this.add( selector == null ? | |
7896 this.prevObject : this.prevObject.filter( selector ) | |
7897 ); | |
7898 }; | |
7899 } | |
7900 | |
7901 $.effects.animateClass = function( value, duration, easing, callback ) { | |
7902 var o = $.speed( duration, easing, callback ); | |
7903 | |
7904 return this.queue( function() { | |
7905 var animated = $( this ), | |
7906 baseClass = animated.attr( "class" ) || "", | |
7907 applyClassChange, | |
7908 allAnimations = o.children ? animated.find( "*" ).addBack() : animated; | |
7909 | |
7910 // map the animated objects to store the original styles. | |
7911 allAnimations = allAnimations.map(function() { | |
7912 var el = $( this ); | |
7913 return { | |
7914 el: el, | |
7915 start: getElementStyles( this ) | |
7916 }; | |
7917 }); | |
7918 | |
7919 // apply class change | |
7920 applyClassChange = function() { | |
7921 $.each( classAnimationActions, function(i, action) { | |
7922 if ( value[ action ] ) { | |
7923 animated[ action + "Class" ]( value[ action ] ); | |
7924 } | |
7925 }); | |
7926 }; | |
7927 applyClassChange(); | |
7928 | |
7929 // map all animated objects again - calculate new styles and diff | |
7930 allAnimations = allAnimations.map(function() { | |
7931 this.end = getElementStyles( this.el[ 0 ] ); | |
7932 this.diff = styleDifference( this.start, this.end ); | |
7933 return this; | |
7934 }); | |
7935 | |
7936 // apply original class | |
7937 animated.attr( "class", baseClass ); | |
7938 | |
7939 // map all animated objects again - this time collecting a promise | |
7940 allAnimations = allAnimations.map(function() { | |
7941 var styleInfo = this, | |
7942 dfd = $.Deferred(), | |
7943 opts = $.extend({}, o, { | |
7944 queue: false, | |
7945 complete: function() { | |
7946 dfd.resolve( styleInfo ); | |
7947 } | |
7948 }); | |
7949 | |
7950 this.el.animate( this.diff, opts ); | |
7951 return dfd.promise(); | |
7952 }); | |
7953 | |
7954 // once all animations have completed: | |
7955 $.when.apply( $, allAnimations.get() ).done(function() { | |
7956 | |
7957 // set the final class | |
7958 applyClassChange(); | |
7959 | |
7960 // for each animated element, | |
7961 // clear all css properties that were animated | |
7962 $.each( arguments, function() { | |
7963 var el = this.el; | |
7964 $.each( this.diff, function(key) { | |
7965 el.css( key, "" ); | |
7966 }); | |
7967 }); | |
7968 | |
7969 // this is guarnteed to be there if you use jQuery.speed() | |
7970 // it also handles dequeuing the next anim... | |
7971 o.complete.call( animated[ 0 ] ); | |
7972 }); | |
7973 }); | |
7974 }; | |
7975 | |
7976 $.fn.extend({ | |
7977 addClass: (function( orig ) { | |
7978 return function( classNames, speed, easing, callback ) { | |
7979 return speed ? | |
7980 $.effects.animateClass.call( this, | |
7981 { add: classNames }, speed, easing, callback ) : | |
7982 orig.apply( this, arguments ); | |
7983 }; | |
7984 })( $.fn.addClass ), | |
7985 | |
7986 removeClass: (function( orig ) { | |
7987 return function( classNames, speed, easing, callback ) { | |
7988 return arguments.length > 1 ? | |
7989 $.effects.animateClass.call( this, | |
7990 { remove: classNames }, speed, easing, callback ) : | |
7991 orig.apply( this, arguments ); | |
7992 }; | |
7993 })( $.fn.removeClass ), | |
7994 | |
7995 toggleClass: (function( orig ) { | |
7996 return function( classNames, force, speed, easing, callback ) { | |
7997 if ( typeof force === "boolean" || force === undefined ) { | |
7998 if ( !speed ) { | |
7999 // without speed parameter | |
8000 return orig.apply( this, arguments ); | |
8001 } else { | |
8002 return $.effects.animateClass.call( this, | |
8003 (force ? { add: classNames } : { remove: classNames }), | |
8004 speed, easing, callback ); | |
8005 } | |
8006 } else { | |
8007 // without force parameter | |
8008 return $.effects.animateClass.call( this, | |
8009 { toggle: classNames }, force, speed, easing ); | |
8010 } | |
8011 }; | |
8012 })( $.fn.toggleClass ), | |
8013 | |
8014 switchClass: function( remove, add, speed, easing, callback) { | |
8015 return $.effects.animateClass.call( this, { | |
8016 add: add, | |
8017 remove: remove | |
8018 }, speed, easing, callback ); | |
8019 } | |
8020 }); | |
8021 | |
8022 })(); | |
8023 | |
8024 /******************************************************************************/ | |
8025 /*********************************** EFFECTS **********************************/ | |
8026 /******************************************************************************/ | |
8027 | |
8028 (function() { | |
8029 | |
8030 $.extend( $.effects, { | |
8031 version: "1.10.4", | |
8032 | |
8033 // Saves a set of properties in a data storage | |
8034 save: function( element, set ) { | |
8035 for( var i=0; i < set.length; i++ ) { | |
8036 if ( set[ i ] !== null ) { | |
8037 element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] ); | |
8038 } | |
8039 } | |
8040 }, | |
8041 | |
8042 // Restores a set of previously saved properties from a data storage | |
8043 restore: function( element, set ) { | |
8044 var val, i; | |
8045 for( i=0; i < set.length; i++ ) { | |
8046 if ( set[ i ] !== null ) { | |
8047 val = element.data( dataSpace + set[ i ] ); | |
8048 // support: jQuery 1.6.2 | |
8049 // http://bugs.jquery.com/ticket/9917 | |
8050 // jQuery 1.6.2 incorrectly returns undefined for any falsy value. | |
8051 // We can't differentiate between "" and 0 here, so we just assume | |
8052 // empty string since it's likely to be a more common value... | |
8053 if ( val === undefined ) { | |
8054 val = ""; | |
8055 } | |
8056 element.css( set[ i ], val ); | |
8057 } | |
8058 } | |
8059 }, | |
8060 | |
8061 setMode: function( el, mode ) { | |
8062 if (mode === "toggle") { | |
8063 mode = el.is( ":hidden" ) ? "show" : "hide"; | |
8064 } | |
8065 return mode; | |
8066 }, | |
8067 | |
8068 // Translates a [top,left] array into a baseline value | |
8069 // this should be a little more flexible in the future to handle a string & hash | |
8070 getBaseline: function( origin, original ) { | |
8071 var y, x; | |
8072 switch ( origin[ 0 ] ) { | |
8073 case "top": y = 0; break; | |
8074 case "middle": y = 0.5; break; | |
8075 case "bottom": y = 1; break; | |
8076 default: y = origin[ 0 ] / original.height; | |
8077 } | |
8078 switch ( origin[ 1 ] ) { | |
8079 case "left": x = 0; break; | |
8080 case "center": x = 0.5; break; | |
8081 case "right": x = 1; break; | |
8082 default: x = origin[ 1 ] / original.width; | |
8083 } | |
8084 return { | |
8085 x: x, | |
8086 y: y | |
8087 }; | |
8088 }, | |
8089 | |
8090 // Wraps the element around a wrapper that copies position properties | |
8091 createWrapper: function( element ) { | |
8092 | |
8093 // if the element is already wrapped, return it | |
8094 if ( element.parent().is( ".ui-effects-wrapper" )) { | |
8095 return element.parent(); | |
8096 } | |
8097 | |
8098 // wrap the element | |
8099 var props = { | |
8100 width: element.outerWidth(true), | |
8101 height: element.outerHeight(true), | |
8102 "float": element.css( "float" ) | |
8103 }, | |
8104 wrapper = $( "<div></div>" ) | |
8105 .addClass( "ui-effects-wrapper" ) | |
8106 .css({ | |
8107 fontSize: "100%", | |
8108 background: "transparent", | |
8109 border: "none", | |
8110 margin: 0, | |
8111 padding: 0 | |
8112 }), | |
8113 // Store the size in case width/height are defined in % - Fixes #5245 | |
8114 size = { | |
8115 width: element.width(), | |
8116 height: element.height() | |
8117 }, | |
8118 active = document.activeElement; | |
8119 | |
8120 // support: Firefox | |
8121 // Firefox incorrectly exposes anonymous content | |
8122 // https://bugzilla.mozilla.org/show_bug.cgi?id=561664 | |
8123 try { | |
8124 active.id; | |
8125 } catch( e ) { | |
8126 active = document.body; | |
8127 } | |
8128 | |
8129 element.wrap( wrapper ); | |
8130 | |
8131 // Fixes #7595 - Elements lose focus when wrapped. | |
8132 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { | |
8133 $( active ).focus(); | |
8134 } | |
8135 | |
8136 wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually lose the reference to the wrapped element | |
8137 | |
8138 // transfer positioning properties to the wrapper | |
8139 if ( element.css( "position" ) === "static" ) { | |
8140 wrapper.css({ position: "relative" }); | |
8141 element.css({ position: "relative" }); | |
8142 } else { | |
8143 $.extend( props, { | |
8144 position: element.css( "position" ), | |
8145 zIndex: element.css( "z-index" ) | |
8146 }); | |
8147 $.each([ "top", "left", "bottom", "right" ], function(i, pos) { | |
8148 props[ pos ] = element.css( pos ); | |
8149 if ( isNaN( parseInt( props[ pos ], 10 ) ) ) { | |
8150 props[ pos ] = "auto"; | |
8151 } | |
8152 }); | |
8153 element.css({ | |
8154 position: "relative", | |
8155 top: 0, | |
8156 left: 0, | |
8157 right: "auto", | |
8158 bottom: "auto" | |
8159 }); | |
8160 } | |
8161 element.css(size); | |
8162 | |
8163 return wrapper.css( props ).show(); | |
8164 }, | |
8165 | |
8166 removeWrapper: function( element ) { | |
8167 var active = document.activeElement; | |
8168 | |
8169 if ( element.parent().is( ".ui-effects-wrapper" ) ) { | |
8170 element.parent().replaceWith( element ); | |
8171 | |
8172 // Fixes #7595 - Elements lose focus when wrapped. | |
8173 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { | |
8174 $( active ).focus(); | |
8175 } | |
8176 } | |
8177 | |
8178 | |
8179 return element; | |
8180 }, | |
8181 | |
8182 setTransition: function( element, list, factor, value ) { | |
8183 value = value || {}; | |
8184 $.each( list, function( i, x ) { | |
8185 var unit = element.cssUnit( x ); | |
8186 if ( unit[ 0 ] > 0 ) { | |
8187 value[ x ] = unit[ 0 ] * factor + unit[ 1 ]; | |
8188 } | |
8189 }); | |
8190 return value; | |
8191 } | |
8192 }); | |
8193 | |
8194 // return an effect options object for the given parameters: | |
8195 function _normalizeArguments( effect, options, speed, callback ) { | |
8196 | |
8197 // allow passing all options as the first parameter | |
8198 if ( $.isPlainObject( effect ) ) { | |
8199 options = effect; | |
8200 effect = effect.effect; | |
8201 } | |
8202 | |
8203 // convert to an object | |
8204 effect = { effect: effect }; | |
8205 | |
8206 // catch (effect, null, ...) | |
8207 if ( options == null ) { | |
8208 options = {}; | |
8209 } | |
8210 | |
8211 // catch (effect, callback) | |
8212 if ( $.isFunction( options ) ) { | |
8213 callback = options; | |
8214 speed = null; | |
8215 options = {}; | |
8216 } | |
8217 | |
8218 // catch (effect, speed, ?) | |
8219 if ( typeof options === "number" || $.fx.speeds[ options ] ) { | |
8220 callback = speed; | |
8221 speed = options; | |
8222 options = {}; | |
8223 } | |
8224 | |
8225 // catch (effect, options, callback) | |
8226 if ( $.isFunction( speed ) ) { | |
8227 callback = speed; | |
8228 speed = null; | |
8229 } | |
8230 | |
8231 // add options to effect | |
8232 if ( options ) { | |
8233 $.extend( effect, options ); | |
8234 } | |
8235 | |
8236 speed = speed || options.duration; | |
8237 effect.duration = $.fx.off ? 0 : | |
8238 typeof speed === "number" ? speed : | |
8239 speed in $.fx.speeds ? $.fx.speeds[ speed ] : | |
8240 $.fx.speeds._default; | |
8241 | |
8242 effect.complete = callback || options.complete; | |
8243 | |
8244 return effect; | |
8245 } | |
8246 | |
8247 function standardAnimationOption( option ) { | |
8248 // Valid standard speeds (nothing, number, named speed) | |
8249 if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) { | |
8250 return true; | |
8251 } | |
8252 | |
8253 // Invalid strings - treat as "normal" speed | |
8254 if ( typeof option === "string" && !$.effects.effect[ option ] ) { | |
8255 return true; | |
8256 } | |
8257 | |
8258 // Complete callback | |
8259 if ( $.isFunction( option ) ) { | |
8260 return true; | |
8261 } | |
8262 | |
8263 // Options hash (but not naming an effect) | |
8264 if ( typeof option === "object" && !option.effect ) { | |
8265 return true; | |
8266 } | |
8267 | |
8268 // Didn't match any standard API | |
8269 return false; | |
8270 } | |
8271 | |
8272 $.fn.extend({ | |
8273 effect: function( /* effect, options, speed, callback */ ) { | |
8274 var args = _normalizeArguments.apply( this, arguments ), | |
8275 mode = args.mode, | |
8276 queue = args.queue, | |
8277 effectMethod = $.effects.effect[ args.effect ]; | |
8278 | |
8279 if ( $.fx.off || !effectMethod ) { | |
8280 // delegate to the original method (e.g., .show()) if possible | |
8281 if ( mode ) { | |
8282 return this[ mode ]( args.duration, args.complete ); | |
8283 } else { | |
8284 return this.each( function() { | |
8285 if ( args.complete ) { | |
8286 args.complete.call( this ); | |
8287 } | |
8288 }); | |
8289 } | |
8290 } | |
8291 | |
8292 function run( next ) { | |
8293 var elem = $( this ), | |
8294 complete = args.complete, | |
8295 mode = args.mode; | |
8296 | |
8297 function done() { | |
8298 if ( $.isFunction( complete ) ) { | |
8299 complete.call( elem[0] ); | |
8300 } | |
8301 if ( $.isFunction( next ) ) { | |
8302 next(); | |
8303 } | |
8304 } | |
8305 | |
8306 // If the element already has the correct final state, delegate to | |
8307 // the core methods so the internal tracking of "olddisplay" works. | |
8308 if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) { | |
8309 elem[ mode ](); | |
8310 done(); | |
8311 } else { | |
8312 effectMethod.call( elem[0], args, done ); | |
8313 } | |
8314 } | |
8315 | |
8316 return queue === false ? this.each( run ) : this.queue( queue || "fx", run ); | |
8317 }, | |
8318 | |
8319 show: (function( orig ) { | |
8320 return function( option ) { | |
8321 if ( standardAnimationOption( option ) ) { | |
8322 return orig.apply( this, arguments ); | |
8323 } else { | |
8324 var args = _normalizeArguments.apply( this, arguments ); | |
8325 args.mode = "show"; | |
8326 return this.effect.call( this, args ); | |
8327 } | |
8328 }; | |
8329 })( $.fn.show ), | |
8330 | |
8331 hide: (function( orig ) { | |
8332 return function( option ) { | |
8333 if ( standardAnimationOption( option ) ) { | |
8334 return orig.apply( this, arguments ); | |
8335 } else { | |
8336 var args = _normalizeArguments.apply( this, arguments ); | |
8337 args.mode = "hide"; | |
8338 return this.effect.call( this, args ); | |
8339 } | |
8340 }; | |
8341 })( $.fn.hide ), | |
8342 | |
8343 toggle: (function( orig ) { | |
8344 return function( option ) { | |
8345 if ( standardAnimationOption( option ) || typeof option === "boolean" ) { | |
8346 return orig.apply( this, arguments ); | |
8347 } else { | |
8348 var args = _normalizeArguments.apply( this, arguments ); | |
8349 args.mode = "toggle"; | |
8350 return this.effect.call( this, args ); | |
8351 } | |
8352 }; | |
8353 })( $.fn.toggle ), | |
8354 | |
8355 // helper functions | |
8356 cssUnit: function(key) { | |
8357 var style = this.css( key ), | |
8358 val = []; | |
8359 | |
8360 $.each( [ "em", "px", "%", "pt" ], function( i, unit ) { | |
8361 if ( style.indexOf( unit ) > 0 ) { | |
8362 val = [ parseFloat( style ), unit ]; | |
8363 } | |
8364 }); | |
8365 return val; | |
8366 } | |
8367 }); | |
8368 | |
8369 })(); | |
8370 | |
8371 /******************************************************************************/ | |
8372 /*********************************** EASING ***********************************/ | |
8373 /******************************************************************************/ | |
8374 | |
8375 (function() { | |
8376 | |
8377 // based on easing equations from Robert Penner (http://www.robertpenner.com/easing) | |
8378 | |
8379 var baseEasings = {}; | |
8380 | |
8381 $.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) { | |
8382 baseEasings[ name ] = function( p ) { | |
8383 return Math.pow( p, i + 2 ); | |
8384 }; | |
8385 }); | |
8386 | |
8387 $.extend( baseEasings, { | |
8388 Sine: function ( p ) { | |
8389 return 1 - Math.cos( p * Math.PI / 2 ); | |
8390 }, | |
8391 Circ: function ( p ) { | |
8392 return 1 - Math.sqrt( 1 - p * p ); | |
8393 }, | |
8394 Elastic: function( p ) { | |
8395 return p === 0 || p === 1 ? p : | |
8396 -Math.pow( 2, 8 * (p - 1) ) * Math.sin( ( (p - 1) * 80 - 7.5 ) * Math.PI / 15 ); | |
8397 }, | |
8398 Back: function( p ) { | |
8399 return p * p * ( 3 * p - 2 ); | |
8400 }, | |
8401 Bounce: function ( p ) { | |
8402 var pow2, | |
8403 bounce = 4; | |
8404 | |
8405 while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {} | |
8406 return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 ); | |
8407 } | |
8408 }); | |
8409 | |
8410 $.each( baseEasings, function( name, easeIn ) { | |
8411 $.easing[ "easeIn" + name ] = easeIn; | |
8412 $.easing[ "easeOut" + name ] = function( p ) { | |
8413 return 1 - easeIn( 1 - p ); | |
8414 }; | |
8415 $.easing[ "easeInOut" + name ] = function( p ) { | |
8416 return p < 0.5 ? | |
8417 easeIn( p * 2 ) / 2 : | |
8418 1 - easeIn( p * -2 + 2 ) / 2; | |
8419 }; | |
8420 }); | |
8421 | |
8422 })(); | |
8423 | |
8424 })(jQuery); | |
8425 (function( $, undefined ) { | |
8426 | |
8427 var rvertical = /up|down|vertical/, | |
8428 rpositivemotion = /up|left|vertical|horizontal/; | |
8429 | |
8430 $.effects.effect.blind = function( o, done ) { | |
8431 // Create element | |
8432 var el = $( this ), | |
8433 props = [ "position", "top", "bottom", "left", "right", "height", "width" ], | |
8434 mode = $.effects.setMode( el, o.mode || "hide" ), | |
8435 direction = o.direction || "up", | |
8436 vertical = rvertical.test( direction ), | |
8437 ref = vertical ? "height" : "width", | |
8438 ref2 = vertical ? "top" : "left", | |
8439 motion = rpositivemotion.test( direction ), | |
8440 animation = {}, | |
8441 show = mode === "show", | |
8442 wrapper, distance, margin; | |
8443 | |
8444 // if already wrapped, the wrapper's properties are my property. #6245 | |
8445 if ( el.parent().is( ".ui-effects-wrapper" ) ) { | |
8446 $.effects.save( el.parent(), props ); | |
8447 } else { | |
8448 $.effects.save( el, props ); | |
8449 } | |
8450 el.show(); | |
8451 wrapper = $.effects.createWrapper( el ).css({ | |
8452 overflow: "hidden" | |
8453 }); | |
8454 | |
8455 distance = wrapper[ ref ](); | |
8456 margin = parseFloat( wrapper.css( ref2 ) ) || 0; | |
8457 | |
8458 animation[ ref ] = show ? distance : 0; | |
8459 if ( !motion ) { | |
8460 el | |
8461 .css( vertical ? "bottom" : "right", 0 ) | |
8462 .css( vertical ? "top" : "left", "auto" ) | |
8463 .css({ position: "absolute" }); | |
8464 | |
8465 animation[ ref2 ] = show ? margin : distance + margin; | |
8466 } | |
8467 | |
8468 // start at 0 if we are showing | |
8469 if ( show ) { | |
8470 wrapper.css( ref, 0 ); | |
8471 if ( ! motion ) { | |
8472 wrapper.css( ref2, margin + distance ); | |
8473 } | |
8474 } | |
8475 | |
8476 // Animate | |
8477 wrapper.animate( animation, { | |
8478 duration: o.duration, | |
8479 easing: o.easing, | |
8480 queue: false, | |
8481 complete: function() { | |
8482 if ( mode === "hide" ) { | |
8483 el.hide(); | |
8484 } | |
8485 $.effects.restore( el, props ); | |
8486 $.effects.removeWrapper( el ); | |
8487 done(); | |
8488 } | |
8489 }); | |
8490 | |
8491 }; | |
8492 | |
8493 })(jQuery); | |
8494 (function( $, undefined ) { | |
8495 | |
8496 $.effects.effect.bounce = function( o, done ) { | |
8497 var el = $( this ), | |
8498 props = [ "position", "top", "bottom", "left", "right", "height", "width" ], | |
8499 | |
8500 // defaults: | |
8501 mode = $.effects.setMode( el, o.mode || "effect" ), | |
8502 hide = mode === "hide", | |
8503 show = mode === "show", | |
8504 direction = o.direction || "up", | |
8505 distance = o.distance, | |
8506 times = o.times || 5, | |
8507 | |
8508 // number of internal animations | |
8509 anims = times * 2 + ( show || hide ? 1 : 0 ), | |
8510 speed = o.duration / anims, | |
8511 easing = o.easing, | |
8512 | |
8513 // utility: | |
8514 ref = ( direction === "up" || direction === "down" ) ? "top" : "left", | |
8515 motion = ( direction === "up" || direction === "left" ), | |
8516 i, | |
8517 upAnim, | |
8518 downAnim, | |
8519 | |
8520 // we will need to re-assemble the queue to stack our animations in place | |
8521 queue = el.queue(), | |
8522 queuelen = queue.length; | |
8523 | |
8524 // Avoid touching opacity to prevent clearType and PNG issues in IE | |
8525 if ( show || hide ) { | |
8526 props.push( "opacity" ); | |
8527 } | |
8528 | |
8529 $.effects.save( el, props ); | |
8530 el.show(); | |
8531 $.effects.createWrapper( el ); // Create Wrapper | |
8532 | |
8533 // default distance for the BIGGEST bounce is the outer Distance / 3 | |
8534 if ( !distance ) { | |
8535 distance = el[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3; | |
8536 } | |
8537 | |
8538 if ( show ) { | |
8539 downAnim = { opacity: 1 }; | |
8540 downAnim[ ref ] = 0; | |
8541 | |
8542 // if we are showing, force opacity 0 and set the initial position | |
8543 // then do the "first" animation | |
8544 el.css( "opacity", 0 ) | |
8545 .css( ref, motion ? -distance * 2 : distance * 2 ) | |
8546 .animate( downAnim, speed, easing ); | |
8547 } | |
8548 | |
8549 // start at the smallest distance if we are hiding | |
8550 if ( hide ) { | |
8551 distance = distance / Math.pow( 2, times - 1 ); | |
8552 } | |
8553 | |
8554 downAnim = {}; | |
8555 downAnim[ ref ] = 0; | |
8556 // Bounces up/down/left/right then back to 0 -- times * 2 animations happen here | |
8557 for ( i = 0; i < times; i++ ) { | |
8558 upAnim = {}; | |
8559 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance; | |
8560 | |
8561 el.animate( upAnim, speed, easing ) | |
8562 .animate( downAnim, speed, easing ); | |
8563 | |
8564 distance = hide ? distance * 2 : distance / 2; | |
8565 } | |
8566 | |
8567 // Last Bounce when Hiding | |
8568 if ( hide ) { | |
8569 upAnim = { opacity: 0 }; | |
8570 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance; | |
8571 | |
8572 el.animate( upAnim, speed, easing ); | |
8573 } | |
8574 | |
8575 el.queue(function() { | |
8576 if ( hide ) { | |
8577 el.hide(); | |
8578 } | |
8579 $.effects.restore( el, props ); | |
8580 $.effects.removeWrapper( el ); | |
8581 done(); | |
8582 }); | |
8583 | |
8584 // inject all the animations we just queued to be first in line (after "inprogress") | |
8585 if ( queuelen > 1) { | |
8586 queue.splice.apply( queue, | |
8587 [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) ); | |
8588 } | |
8589 el.dequeue(); | |
8590 | |
8591 }; | |
8592 | |
8593 })(jQuery); | |
8594 (function( $, undefined ) { | |
8595 | |
8596 $.effects.effect.clip = function( o, done ) { | |
8597 // Create element | |
8598 var el = $( this ), | |
8599 props = [ "position", "top", "bottom", "left", "right", "height", "width" ], | |
8600 mode = $.effects.setMode( el, o.mode || "hide" ), | |
8601 show = mode === "show", | |
8602 direction = o.direction || "vertical", | |
8603 vert = direction === "vertical", | |
8604 size = vert ? "height" : "width", | |
8605 position = vert ? "top" : "left", | |
8606 animation = {}, | |
8607 wrapper, animate, distance; | |
8608 | |
8609 // Save & Show | |
8610 $.effects.save( el, props ); | |
8611 el.show(); | |
8612 | |
8613 // Create Wrapper | |
8614 wrapper = $.effects.createWrapper( el ).css({ | |
8615 overflow: "hidden" | |
8616 }); | |
8617 animate = ( el[0].tagName === "IMG" ) ? wrapper : el; | |
8618 distance = animate[ size ](); | |
8619 | |
8620 // Shift | |
8621 if ( show ) { | |
8622 animate.css( size, 0 ); | |
8623 animate.css( position, distance / 2 ); | |
8624 } | |
8625 | |
8626 // Create Animation Object: | |
8627 animation[ size ] = show ? distance : 0; | |
8628 animation[ position ] = show ? 0 : distance / 2; | |
8629 | |
8630 // Animate | |
8631 animate.animate( animation, { | |
8632 queue: false, | |
8633 duration: o.duration, | |
8634 easing: o.easing, | |
8635 complete: function() { | |
8636 if ( !show ) { | |
8637 el.hide(); | |
8638 } | |
8639 $.effects.restore( el, props ); | |
8640 $.effects.removeWrapper( el ); | |
8641 done(); | |
8642 } | |
8643 }); | |
8644 | |
8645 }; | |
8646 | |
8647 })(jQuery); | |
8648 (function( $, undefined ) { | |
8649 | |
8650 $.effects.effect.drop = function( o, done ) { | |
8651 | |
8652 var el = $( this ), | |
8653 props = [ "position", "top", "bottom", "left", "right", "opacity", "height", "width" ], | |
8654 mode = $.effects.setMode( el, o.mode || "hide" ), | |
8655 show = mode === "show", | |
8656 direction = o.direction || "left", | |
8657 ref = ( direction === "up" || direction === "down" ) ? "top" : "left", | |
8658 motion = ( direction === "up" || direction === "left" ) ? "pos" : "neg", | |
8659 animation = { | |
8660 opacity: show ? 1 : 0 | |
8661 }, | |
8662 distance; | |
8663 | |
8664 // Adjust | |
8665 $.effects.save( el, props ); | |
8666 el.show(); | |
8667 $.effects.createWrapper( el ); | |
8668 | |
8669 distance = o.distance || el[ ref === "top" ? "outerHeight": "outerWidth" ]( true ) / 2; | |
8670 | |
8671 if ( show ) { | |
8672 el | |
8673 .css( "opacity", 0 ) | |
8674 .css( ref, motion === "pos" ? -distance : distance ); | |
8675 } | |
8676 | |
8677 // Animation | |
8678 animation[ ref ] = ( show ? | |
8679 ( motion === "pos" ? "+=" : "-=" ) : | |
8680 ( motion === "pos" ? "-=" : "+=" ) ) + | |
8681 distance; | |
8682 | |
8683 // Animate | |
8684 el.animate( animation, { | |
8685 queue: false, | |
8686 duration: o.duration, | |
8687 easing: o.easing, | |
8688 complete: function() { | |
8689 if ( mode === "hide" ) { | |
8690 el.hide(); | |
8691 } | |
8692 $.effects.restore( el, props ); | |
8693 $.effects.removeWrapper( el ); | |
8694 done(); | |
8695 } | |
8696 }); | |
8697 }; | |
8698 | |
8699 })(jQuery); | |
8700 (function( $, undefined ) { | |
8701 | |
8702 $.effects.effect.explode = function( o, done ) { | |
8703 | |
8704 var rows = o.pieces ? Math.round( Math.sqrt( o.pieces ) ) : 3, | |
8705 cells = rows, | |
8706 el = $( this ), | |
8707 mode = $.effects.setMode( el, o.mode || "hide" ), | |
8708 show = mode === "show", | |
8709 | |
8710 // show and then visibility:hidden the element before calculating offset | |
8711 offset = el.show().css( "visibility", "hidden" ).offset(), | |
8712 | |
8713 // width and height of a piece | |
8714 width = Math.ceil( el.outerWidth() / cells ), | |
8715 height = Math.ceil( el.outerHeight() / rows ), | |
8716 pieces = [], | |
8717 | |
8718 // loop | |
8719 i, j, left, top, mx, my; | |
8720 | |
8721 // children animate complete: | |
8722 function childComplete() { | |
8723 pieces.push( this ); | |
8724 if ( pieces.length === rows * cells ) { | |
8725 animComplete(); | |
8726 } | |
8727 } | |
8728 | |
8729 // clone the element for each row and cell. | |
8730 for( i = 0; i < rows ; i++ ) { // ===> | |
8731 top = offset.top + i * height; | |
8732 my = i - ( rows - 1 ) / 2 ; | |
8733 | |
8734 for( j = 0; j < cells ; j++ ) { // ||| | |
8735 left = offset.left + j * width; | |
8736 mx = j - ( cells - 1 ) / 2 ; | |
8737 | |
8738 // Create a clone of the now hidden main element that will be absolute positioned | |
8739 // within a wrapper div off the -left and -top equal to size of our pieces | |
8740 el | |
8741 .clone() | |
8742 .appendTo( "body" ) | |
8743 .wrap( "<div></div>" ) | |
8744 .css({ | |
8745 position: "absolute", | |
8746 visibility: "visible", | |
8747 left: -j * width, | |
8748 top: -i * height | |
8749 }) | |
8750 | |
8751 // select the wrapper - make it overflow: hidden and absolute positioned based on | |
8752 // where the original was located +left and +top equal to the size of pieces | |
8753 .parent() | |
8754 .addClass( "ui-effects-explode" ) | |
8755 .css({ | |
8756 position: "absolute", | |
8757 overflow: "hidden", | |
8758 width: width, | |
8759 height: height, | |
8760 left: left + ( show ? mx * width : 0 ), | |
8761 top: top + ( show ? my * height : 0 ), | |
8762 opacity: show ? 0 : 1 | |
8763 }).animate({ | |
8764 left: left + ( show ? 0 : mx * width ), | |
8765 top: top + ( show ? 0 : my * height ), | |
8766 opacity: show ? 1 : 0 | |
8767 }, o.duration || 500, o.easing, childComplete ); | |
8768 } | |
8769 } | |
8770 | |
8771 function animComplete() { | |
8772 el.css({ | |
8773 visibility: "visible" | |
8774 }); | |
8775 $( pieces ).remove(); | |
8776 if ( !show ) { | |
8777 el.hide(); | |
8778 } | |
8779 done(); | |
8780 } | |
8781 }; | |
8782 | |
8783 })(jQuery); | |
8784 (function( $, undefined ) { | |
8785 | |
8786 $.effects.effect.fade = function( o, done ) { | |
8787 var el = $( this ), | |
8788 mode = $.effects.setMode( el, o.mode || "toggle" ); | |
8789 | |
8790 el.animate({ | |
8791 opacity: mode | |
8792 }, { | |
8793 queue: false, | |
8794 duration: o.duration, | |
8795 easing: o.easing, | |
8796 complete: done | |
8797 }); | |
8798 }; | |
8799 | |
8800 })( jQuery ); | |
8801 (function( $, undefined ) { | |
8802 | |
8803 $.effects.effect.fold = function( o, done ) { | |
8804 | |
8805 // Create element | |
8806 var el = $( this ), | |
8807 props = [ "position", "top", "bottom", "left", "right", "height", "width" ], | |
8808 mode = $.effects.setMode( el, o.mode || "hide" ), | |
8809 show = mode === "show", | |
8810 hide = mode === "hide", | |
8811 size = o.size || 15, | |
8812 percent = /([0-9]+)%/.exec( size ), | |
8813 horizFirst = !!o.horizFirst, | |
8814 widthFirst = show !== horizFirst, | |
8815 ref = widthFirst ? [ "width", "height" ] : [ "height", "width" ], | |
8816 duration = o.duration / 2, | |
8817 wrapper, distance, | |
8818 animation1 = {}, | |
8819 animation2 = {}; | |
8820 | |
8821 $.effects.save( el, props ); | |
8822 el.show(); | |
8823 | |
8824 // Create Wrapper | |
8825 wrapper = $.effects.createWrapper( el ).css({ | |
8826 overflow: "hidden" | |
8827 }); | |
8828 distance = widthFirst ? | |
8829 [ wrapper.width(), wrapper.height() ] : | |
8830 [ wrapper.height(), wrapper.width() ]; | |
8831 | |
8832 if ( percent ) { | |
8833 size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ]; | |
8834 } | |
8835 if ( show ) { | |
8836 wrapper.css( horizFirst ? { | |
8837 height: 0, | |
8838 width: size | |
8839 } : { | |
8840 height: size, | |
8841 width: 0 | |
8842 }); | |
8843 } | |
8844 | |
8845 // Animation | |
8846 animation1[ ref[ 0 ] ] = show ? distance[ 0 ] : size; | |
8847 animation2[ ref[ 1 ] ] = show ? distance[ 1 ] : 0; | |
8848 | |
8849 // Animate | |
8850 wrapper | |
8851 .animate( animation1, duration, o.easing ) | |
8852 .animate( animation2, duration, o.easing, function() { | |
8853 if ( hide ) { | |
8854 el.hide(); | |
8855 } | |
8856 $.effects.restore( el, props ); | |
8857 $.effects.removeWrapper( el ); | |
8858 done(); | |
8859 }); | |
8860 | |
8861 }; | |
8862 | |
8863 })(jQuery); | |
8864 (function( $, undefined ) { | |
8865 | |
8866 $.effects.effect.highlight = function( o, done ) { | |
8867 var elem = $( this ), | |
8868 props = [ "backgroundImage", "backgroundColor", "opacity" ], | |
8869 mode = $.effects.setMode( elem, o.mode || "show" ), | |
8870 animation = { | |
8871 backgroundColor: elem.css( "backgroundColor" ) | |
8872 }; | |
8873 | |
8874 if (mode === "hide") { | |
8875 animation.opacity = 0; | |
8876 } | |
8877 | |
8878 $.effects.save( elem, props ); | |
8879 | |
8880 elem | |
8881 .show() | |
8882 .css({ | |
8883 backgroundImage: "none", | |
8884 backgroundColor: o.color || "#ffff99" | |
8885 }) | |
8886 .animate( animation, { | |
8887 queue: false, | |
8888 duration: o.duration, | |
8889 easing: o.easing, | |
8890 complete: function() { | |
8891 if ( mode === "hide" ) { | |
8892 elem.hide(); | |
8893 } | |
8894 $.effects.restore( elem, props ); | |
8895 done(); | |
8896 } | |
8897 }); | |
8898 }; | |
8899 | |
8900 })(jQuery); | |
8901 (function( $, undefined ) { | |
8902 | |
8903 $.effects.effect.pulsate = function( o, done ) { | |
8904 var elem = $( this ), | |
8905 mode = $.effects.setMode( elem, o.mode || "show" ), | |
8906 show = mode === "show", | |
8907 hide = mode === "hide", | |
8908 showhide = ( show || mode === "hide" ), | |
8909 | |
8910 // showing or hiding leaves of the "last" animation | |
8911 anims = ( ( o.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ), | |
8912 duration = o.duration / anims, | |
8913 animateTo = 0, | |
8914 queue = elem.queue(), | |
8915 queuelen = queue.length, | |
8916 i; | |
8917 | |
8918 if ( show || !elem.is(":visible")) { | |
8919 elem.css( "opacity", 0 ).show(); | |
8920 animateTo = 1; | |
8921 } | |
8922 | |
8923 // anims - 1 opacity "toggles" | |
8924 for ( i = 1; i < anims; i++ ) { | |
8925 elem.animate({ | |
8926 opacity: animateTo | |
8927 }, duration, o.easing ); | |
8928 animateTo = 1 - animateTo; | |
8929 } | |
8930 | |
8931 elem.animate({ | |
8932 opacity: animateTo | |
8933 }, duration, o.easing); | |
8934 | |
8935 elem.queue(function() { | |
8936 if ( hide ) { | |
8937 elem.hide(); | |
8938 } | |
8939 done(); | |
8940 }); | |
8941 | |
8942 // We just queued up "anims" animations, we need to put them next in the queue | |
8943 if ( queuelen > 1 ) { | |
8944 queue.splice.apply( queue, | |
8945 [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) ); | |
8946 } | |
8947 elem.dequeue(); | |
8948 }; | |
8949 | |
8950 })(jQuery); | |
8951 (function( $, undefined ) { | |
8952 | |
8953 $.effects.effect.puff = function( o, done ) { | |
8954 var elem = $( this ), | |
8955 mode = $.effects.setMode( elem, o.mode || "hide" ), | |
8956 hide = mode === "hide", | |
8957 percent = parseInt( o.percent, 10 ) || 150, | |
8958 factor = percent / 100, | |
8959 original = { | |
8960 height: elem.height(), | |
8961 width: elem.width(), | |
8962 outerHeight: elem.outerHeight(), | |
8963 outerWidth: elem.outerWidth() | |
8964 }; | |
8965 | |
8966 $.extend( o, { | |
8967 effect: "scale", | |
8968 queue: false, | |
8969 fade: true, | |
8970 mode: mode, | |
8971 complete: done, | |
8972 percent: hide ? percent : 100, | |
8973 from: hide ? | |
8974 original : | |
8975 { | |
8976 height: original.height * factor, | |
8977 width: original.width * factor, | |
8978 outerHeight: original.outerHeight * factor, | |
8979 outerWidth: original.outerWidth * factor | |
8980 } | |
8981 }); | |
8982 | |
8983 elem.effect( o ); | |
8984 }; | |
8985 | |
8986 $.effects.effect.scale = function( o, done ) { | |
8987 | |
8988 // Create element | |
8989 var el = $( this ), | |
8990 options = $.extend( true, {}, o ), | |
8991 mode = $.effects.setMode( el, o.mode || "effect" ), | |
8992 percent = parseInt( o.percent, 10 ) || | |
8993 ( parseInt( o.percent, 10 ) === 0 ? 0 : ( mode === "hide" ? 0 : 100 ) ), | |
8994 direction = o.direction || "both", | |
8995 origin = o.origin, | |
8996 original = { | |
8997 height: el.height(), | |
8998 width: el.width(), | |
8999 outerHeight: el.outerHeight(), | |
9000 outerWidth: el.outerWidth() | |
9001 }, | |
9002 factor = { | |
9003 y: direction !== "horizontal" ? (percent / 100) : 1, | |
9004 x: direction !== "vertical" ? (percent / 100) : 1 | |
9005 }; | |
9006 | |
9007 // We are going to pass this effect to the size effect: | |
9008 options.effect = "size"; | |
9009 options.queue = false; | |
9010 options.complete = done; | |
9011 | |
9012 // Set default origin and restore for show/hide | |
9013 if ( mode !== "effect" ) { | |
9014 options.origin = origin || ["middle","center"]; | |
9015 options.restore = true; | |
9016 } | |
9017 | |
9018 options.from = o.from || ( mode === "show" ? { | |
9019 height: 0, | |
9020 width: 0, | |
9021 outerHeight: 0, | |
9022 outerWidth: 0 | |
9023 } : original ); | |
9024 options.to = { | |
9025 height: original.height * factor.y, | |
9026 width: original.width * factor.x, | |
9027 outerHeight: original.outerHeight * factor.y, | |
9028 outerWidth: original.outerWidth * factor.x | |
9029 }; | |
9030 | |
9031 // Fade option to support puff | |
9032 if ( options.fade ) { | |
9033 if ( mode === "show" ) { | |
9034 options.from.opacity = 0; | |
9035 options.to.opacity = 1; | |
9036 } | |
9037 if ( mode === "hide" ) { | |
9038 options.from.opacity = 1; | |
9039 options.to.opacity = 0; | |
9040 } | |
9041 } | |
9042 | |
9043 // Animate | |
9044 el.effect( options ); | |
9045 | |
9046 }; | |
9047 | |
9048 $.effects.effect.size = function( o, done ) { | |
9049 | |
9050 // Create element | |
9051 var original, baseline, factor, | |
9052 el = $( this ), | |
9053 props0 = [ "position", "top", "bottom", "left", "right", "width", "height", "overflow", "opacity" ], | |
9054 | |
9055 // Always restore | |
9056 props1 = [ "position", "top", "bottom", "left", "right", "overflow", "opacity" ], | |
9057 | |
9058 // Copy for children | |
9059 props2 = [ "width", "height", "overflow" ], | |
9060 cProps = [ "fontSize" ], | |
9061 vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ], | |
9062 hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ], | |
9063 | |
9064 // Set options | |
9065 mode = $.effects.setMode( el, o.mode || "effect" ), | |
9066 restore = o.restore || mode !== "effect", | |
9067 scale = o.scale || "both", | |
9068 origin = o.origin || [ "middle", "center" ], | |
9069 position = el.css( "position" ), | |
9070 props = restore ? props0 : props1, | |
9071 zero = { | |
9072 height: 0, | |
9073 width: 0, | |
9074 outerHeight: 0, | |
9075 outerWidth: 0 | |
9076 }; | |
9077 | |
9078 if ( mode === "show" ) { | |
9079 el.show(); | |
9080 } | |
9081 original = { | |
9082 height: el.height(), | |
9083 width: el.width(), | |
9084 outerHeight: el.outerHeight(), | |
9085 outerWidth: el.outerWidth() | |
9086 }; | |
9087 | |
9088 if ( o.mode === "toggle" && mode === "show" ) { | |
9089 el.from = o.to || zero; | |
9090 el.to = o.from || original; | |
9091 } else { | |
9092 el.from = o.from || ( mode === "show" ? zero : original ); | |
9093 el.to = o.to || ( mode === "hide" ? zero : original ); | |
9094 } | |
9095 | |
9096 // Set scaling factor | |
9097 factor = { | |
9098 from: { | |
9099 y: el.from.height / original.height, | |
9100 x: el.from.width / original.width | |
9101 }, | |
9102 to: { | |
9103 y: el.to.height / original.height, | |
9104 x: el.to.width / original.width | |
9105 } | |
9106 }; | |
9107 | |
9108 // Scale the css box | |
9109 if ( scale === "box" || scale === "both" ) { | |
9110 | |
9111 // Vertical props scaling | |
9112 if ( factor.from.y !== factor.to.y ) { | |
9113 props = props.concat( vProps ); | |
9114 el.from = $.effects.setTransition( el, vProps, factor.from.y, el.from ); | |
9115 el.to = $.effects.setTransition( el, vProps, factor.to.y, el.to ); | |
9116 } | |
9117 | |
9118 // Horizontal props scaling | |
9119 if ( factor.from.x !== factor.to.x ) { | |
9120 props = props.concat( hProps ); | |
9121 el.from = $.effects.setTransition( el, hProps, factor.from.x, el.from ); | |
9122 el.to = $.effects.setTransition( el, hProps, factor.to.x, el.to ); | |
9123 } | |
9124 } | |
9125 | |
9126 // Scale the content | |
9127 if ( scale === "content" || scale === "both" ) { | |
9128 | |
9129 // Vertical props scaling | |
9130 if ( factor.from.y !== factor.to.y ) { | |
9131 props = props.concat( cProps ).concat( props2 ); | |
9132 el.from = $.effects.setTransition( el, cProps, factor.from.y, el.from ); | |
9133 el.to = $.effects.setTransition( el, cProps, factor.to.y, el.to ); | |
9134 } | |
9135 } | |
9136 | |
9137 $.effects.save( el, props ); | |
9138 el.show(); | |
9139 $.effects.createWrapper( el ); | |
9140 el.css( "overflow", "hidden" ).css( el.from ); | |
9141 | |
9142 // Adjust | |
9143 if (origin) { // Calculate baseline shifts | |
9144 baseline = $.effects.getBaseline( origin, original ); | |
9145 el.from.top = ( original.outerHeight - el.outerHeight() ) * baseline.y; | |
9146 el.from.left = ( original.outerWidth - el.outerWidth() ) * baseline.x; | |
9147 el.to.top = ( original.outerHeight - el.to.outerHeight ) * baseline.y; | |
9148 el.to.left = ( original.outerWidth - el.to.outerWidth ) * baseline.x; | |
9149 } | |
9150 el.css( el.from ); // set top & left | |
9151 | |
9152 // Animate | |
9153 if ( scale === "content" || scale === "both" ) { // Scale the children | |
9154 | |
9155 // Add margins/font-size | |
9156 vProps = vProps.concat([ "marginTop", "marginBottom" ]).concat(cProps); | |
9157 hProps = hProps.concat([ "marginLeft", "marginRight" ]); | |
9158 props2 = props0.concat(vProps).concat(hProps); | |
9159 | |
9160 el.find( "*[width]" ).each( function(){ | |
9161 var child = $( this ), | |
9162 c_original = { | |
9163 height: child.height(), | |
9164 width: child.width(), | |
9165 outerHeight: child.outerHeight(), | |
9166 outerWidth: child.outerWidth() | |
9167 }; | |
9168 if (restore) { | |
9169 $.effects.save(child, props2); | |
9170 } | |
9171 | |
9172 child.from = { | |
9173 height: c_original.height * factor.from.y, | |
9174 width: c_original.width * factor.from.x, | |
9175 outerHeight: c_original.outerHeight * factor.from.y, | |
9176 outerWidth: c_original.outerWidth * factor.from.x | |
9177 }; | |
9178 child.to = { | |
9179 height: c_original.height * factor.to.y, | |
9180 width: c_original.width * factor.to.x, | |
9181 outerHeight: c_original.height * factor.to.y, | |
9182 outerWidth: c_original.width * factor.to.x | |
9183 }; | |
9184 | |
9185 // Vertical props scaling | |
9186 if ( factor.from.y !== factor.to.y ) { | |
9187 child.from = $.effects.setTransition( child, vProps, factor.from.y, child.from ); | |
9188 child.to = $.effects.setTransition( child, vProps, factor.to.y, child.to ); | |
9189 } | |
9190 | |
9191 // Horizontal props scaling | |
9192 if ( factor.from.x !== factor.to.x ) { | |
9193 child.from = $.effects.setTransition( child, hProps, factor.from.x, child.from ); | |
9194 child.to = $.effects.setTransition( child, hProps, factor.to.x, child.to ); | |
9195 } | |
9196 | |
9197 // Animate children | |
9198 child.css( child.from ); | |
9199 child.animate( child.to, o.duration, o.easing, function() { | |
9200 | |
9201 // Restore children | |
9202 if ( restore ) { | |
9203 $.effects.restore( child, props2 ); | |
9204 } | |
9205 }); | |
9206 }); | |
9207 } | |
9208 | |
9209 // Animate | |
9210 el.animate( el.to, { | |
9211 queue: false, | |
9212 duration: o.duration, | |
9213 easing: o.easing, | |
9214 complete: function() { | |
9215 if ( el.to.opacity === 0 ) { | |
9216 el.css( "opacity", el.from.opacity ); | |
9217 } | |
9218 if( mode === "hide" ) { | |
9219 el.hide(); | |
9220 } | |
9221 $.effects.restore( el, props ); | |
9222 if ( !restore ) { | |
9223 | |
9224 // we need to calculate our new positioning based on the scaling | |
9225 if ( position === "static" ) { | |
9226 el.css({ | |
9227 position: "relative", | |
9228 top: el.to.top, | |
9229 left: el.to.left | |
9230 }); | |
9231 } else { | |
9232 $.each([ "top", "left" ], function( idx, pos ) { | |
9233 el.css( pos, function( _, str ) { | |
9234 var val = parseInt( str, 10 ), | |
9235 toRef = idx ? el.to.left : el.to.top; | |
9236 | |
9237 // if original was "auto", recalculate the new value from wrapper | |
9238 if ( str === "auto" ) { | |
9239 return toRef + "px"; | |
9240 } | |
9241 | |
9242 return val + toRef + "px"; | |
9243 }); | |
9244 }); | |
9245 } | |
9246 } | |
9247 | |
9248 $.effects.removeWrapper( el ); | |
9249 done(); | |
9250 } | |
9251 }); | |
9252 | |
9253 }; | |
9254 | |
9255 })(jQuery); | |
9256 (function( $, undefined ) { | |
9257 | |
9258 $.effects.effect.shake = function( o, done ) { | |
9259 | |
9260 var el = $( this ), | |
9261 props = [ "position", "top", "bottom", "left", "right", "height", "width" ], | |
9262 mode = $.effects.setMode( el, o.mode || "effect" ), | |
9263 direction = o.direction || "left", | |
9264 distance = o.distance || 20, | |
9265 times = o.times || 3, | |
9266 anims = times * 2 + 1, | |
9267 speed = Math.round(o.duration/anims), | |
9268 ref = (direction === "up" || direction === "down") ? "top" : "left", | |
9269 positiveMotion = (direction === "up" || direction === "left"), | |
9270 animation = {}, | |
9271 animation1 = {}, | |
9272 animation2 = {}, | |
9273 i, | |
9274 | |
9275 // we will need to re-assemble the queue to stack our animations in place | |
9276 queue = el.queue(), | |
9277 queuelen = queue.length; | |
9278 | |
9279 $.effects.save( el, props ); | |
9280 el.show(); | |
9281 $.effects.createWrapper( el ); | |
9282 | |
9283 // Animation | |
9284 animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance; | |
9285 animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2; | |
9286 animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2; | |
9287 | |
9288 // Animate | |
9289 el.animate( animation, speed, o.easing ); | |
9290 | |
9291 // Shakes | |
9292 for ( i = 1; i < times; i++ ) { | |
9293 el.animate( animation1, speed, o.easing ).animate( animation2, speed, o.easing ); | |
9294 } | |
9295 el | |
9296 .animate( animation1, speed, o.easing ) | |
9297 .animate( animation, speed / 2, o.easing ) | |
9298 .queue(function() { | |
9299 if ( mode === "hide" ) { | |
9300 el.hide(); | |
9301 } | |
9302 $.effects.restore( el, props ); | |
9303 $.effects.removeWrapper( el ); | |
9304 done(); | |
9305 }); | |
9306 | |
9307 // inject all the animations we just queued to be first in line (after "inprogress") | |
9308 if ( queuelen > 1) { | |
9309 queue.splice.apply( queue, | |
9310 [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) ); | |
9311 } | |
9312 el.dequeue(); | |
9313 | |
9314 }; | |
9315 | |
9316 })(jQuery); | |
9317 (function( $, undefined ) { | |
9318 | |
9319 $.effects.effect.slide = function( o, done ) { | |
9320 | |
9321 // Create element | |
9322 var el = $( this ), | |
9323 props = [ "position", "top", "bottom", "left", "right", "width", "height" ], | |
9324 mode = $.effects.setMode( el, o.mode || "show" ), | |
9325 show = mode === "show", | |
9326 direction = o.direction || "left", | |
9327 ref = (direction === "up" || direction === "down") ? "top" : "left", | |
9328 positiveMotion = (direction === "up" || direction === "left"), | |
9329 distance, | |
9330 animation = {}; | |
9331 | |
9332 // Adjust | |
9333 $.effects.save( el, props ); | |
9334 el.show(); | |
9335 distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ); | |
9336 | |
9337 $.effects.createWrapper( el ).css({ | |
9338 overflow: "hidden" | |
9339 }); | |
9340 | |
9341 if ( show ) { | |
9342 el.css( ref, positiveMotion ? (isNaN(distance) ? "-" + distance : -distance) : distance ); | |
9343 } | |
9344 | |
9345 // Animation | |
9346 animation[ ref ] = ( show ? | |
9347 ( positiveMotion ? "+=" : "-=") : | |
9348 ( positiveMotion ? "-=" : "+=")) + | |
9349 distance; | |
9350 | |
9351 // Animate | |
9352 el.animate( animation, { | |
9353 queue: false, | |
9354 duration: o.duration, | |
9355 easing: o.easing, | |
9356 complete: function() { | |
9357 if ( mode === "hide" ) { | |
9358 el.hide(); | |
9359 } | |
9360 $.effects.restore( el, props ); | |
9361 $.effects.removeWrapper( el ); | |
9362 done(); | |
9363 } | |
9364 }); | |
9365 }; | |
9366 | |
9367 })(jQuery); | |
9368 (function( $, undefined ) { | |
9369 | |
9370 $.effects.effect.transfer = function( o, done ) { | |
9371 var elem = $( this ), | |
9372 target = $( o.to ), | |
9373 targetFixed = target.css( "position" ) === "fixed", | |
9374 body = $("body"), | |
9375 fixTop = targetFixed ? body.scrollTop() : 0, | |
9376 fixLeft = targetFixed ? body.scrollLeft() : 0, | |
9377 endPosition = target.offset(), | |
9378 animation = { | |
9379 top: endPosition.top - fixTop , | |
9380 left: endPosition.left - fixLeft , | |
9381 height: target.innerHeight(), | |
9382 width: target.innerWidth() | |
9383 }, | |
9384 startPosition = elem.offset(), | |
9385 transfer = $( "<div class='ui-effects-transfer'></div>" ) | |
9386 .appendTo( document.body ) | |
9387 .addClass( o.className ) | |
9388 .css({ | |
9389 top: startPosition.top - fixTop , | |
9390 left: startPosition.left - fixLeft , | |
9391 height: elem.innerHeight(), | |
9392 width: elem.innerWidth(), | |
9393 position: targetFixed ? "fixed" : "absolute" | |
9394 }) | |
9395 .animate( animation, o.duration, o.easing, function() { | |
9396 transfer.remove(); | |
9397 done(); | |
9398 }); | |
9399 }; | |
9400 | |
9401 })(jQuery); | |
9402 (function( $, undefined ) { | |
9403 | |
9404 $.widget( "ui.menu", { | |
9405 version: "1.10.4", | |
9406 defaultElement: "<ul>", | |
9407 delay: 300, | |
9408 options: { | |
9409 icons: { | |
9410 submenu: "ui-icon-carat-1-e" | |
9411 }, | |
9412 menus: "ul", | |
9413 position: { | |
9414 my: "left top", | |
9415 at: "right top" | |
9416 }, | |
9417 role: "menu", | |
9418 | |
9419 // callbacks | |
9420 blur: null, | |
9421 focus: null, | |
9422 select: null | |
9423 }, | |
9424 | |
9425 _create: function() { | |
9426 this.activeMenu = this.element; | |
9427 // flag used to prevent firing of the click handler | |
9428 // as the event bubbles up through nested menus | |
9429 this.mouseHandled = false; | |
9430 this.element | |
9431 .uniqueId() | |
9432 .addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" ) | |
9433 .toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length ) | |
9434 .attr({ | |
9435 role: this.options.role, | |
9436 tabIndex: 0 | |
9437 }) | |
9438 // need to catch all clicks on disabled menu | |
9439 // not possible through _on | |
9440 .bind( "click" + this.eventNamespace, $.proxy(function( event ) { | |
9441 if ( this.options.disabled ) { | |
9442 event.preventDefault(); | |
9443 } | |
9444 }, this )); | |
9445 | |
9446 if ( this.options.disabled ) { | |
9447 this.element | |
9448 .addClass( "ui-state-disabled" ) | |
9449 .attr( "aria-disabled", "true" ); | |
9450 } | |
9451 | |
9452 this._on({ | |
9453 // Prevent focus from sticking to links inside menu after clicking | |
9454 // them (focus should always stay on UL during navigation). | |
9455 "mousedown .ui-menu-item > a": function( event ) { | |
9456 event.preventDefault(); | |
9457 }, | |
9458 "click .ui-state-disabled > a": function( event ) { | |
9459 event.preventDefault(); | |
9460 }, | |
9461 "click .ui-menu-item:has(a)": function( event ) { | |
9462 var target = $( event.target ).closest( ".ui-menu-item" ); | |
9463 if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) { | |
9464 this.select( event ); | |
9465 | |
9466 // Only set the mouseHandled flag if the event will bubble, see #9469. | |
9467 if ( !event.isPropagationStopped() ) { | |
9468 this.mouseHandled = true; | |
9469 } | |
9470 | |
9471 // Open submenu on click | |
9472 if ( target.has( ".ui-menu" ).length ) { | |
9473 this.expand( event ); | |
9474 } else if ( !this.element.is( ":focus" ) && $( this.document[ 0 ].activeElement ).closest( ".ui-menu" ).length ) { | |
9475 | |
9476 // Redirect focus to the menu | |
9477 this.element.trigger( "focus", [ true ] ); | |
9478 | |
9479 // If the active item is on the top level, let it stay active. | |
9480 // Otherwise, blur the active item since it is no longer visible. | |
9481 if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) { | |
9482 clearTimeout( this.timer ); | |
9483 } | |
9484 } | |
9485 } | |
9486 }, | |
9487 "mouseenter .ui-menu-item": function( event ) { | |
9488 var target = $( event.currentTarget ); | |
9489 // Remove ui-state-active class from siblings of the newly focused menu item | |
9490 // to avoid a jump caused by adjacent elements both having a class with a border | |
9491 target.siblings().children( ".ui-state-active" ).removeClass( "ui-state-active" ); | |
9492 this.focus( event, target ); | |
9493 }, | |
9494 mouseleave: "collapseAll", | |
9495 "mouseleave .ui-menu": "collapseAll", | |
9496 focus: function( event, keepActiveItem ) { | |
9497 // If there's already an active item, keep it active | |
9498 // If not, activate the first item | |
9499 var item = this.active || this.element.children( ".ui-menu-item" ).eq( 0 ); | |
9500 | |
9501 if ( !keepActiveItem ) { | |
9502 this.focus( event, item ); | |
9503 } | |
9504 }, | |
9505 blur: function( event ) { | |
9506 this._delay(function() { | |
9507 if ( !$.contains( this.element[0], this.document[0].activeElement ) ) { | |
9508 this.collapseAll( event ); | |
9509 } | |
9510 }); | |
9511 }, | |
9512 keydown: "_keydown" | |
9513 }); | |
9514 | |
9515 this.refresh(); | |
9516 | |
9517 // Clicks outside of a menu collapse any open menus | |
9518 this._on( this.document, { | |
9519 click: function( event ) { | |
9520 if ( !$( event.target ).closest( ".ui-menu" ).length ) { | |
9521 this.collapseAll( event ); | |
9522 } | |
9523 | |
9524 // Reset the mouseHandled flag | |
9525 this.mouseHandled = false; | |
9526 } | |
9527 }); | |
9528 }, | |
9529 | |
9530 _destroy: function() { | |
9531 // Destroy (sub)menus | |
9532 this.element | |
9533 .removeAttr( "aria-activedescendant" ) | |
9534 .find( ".ui-menu" ).addBack() | |
9535 .removeClass( "ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons" ) | |
9536 .removeAttr( "role" ) | |
9537 .removeAttr( "tabIndex" ) | |
9538 .removeAttr( "aria-labelledby" ) | |
9539 .removeAttr( "aria-expanded" ) | |
9540 .removeAttr( "aria-hidden" ) | |
9541 .removeAttr( "aria-disabled" ) | |
9542 .removeUniqueId() | |
9543 .show(); | |
9544 | |
9545 // Destroy menu items | |
9546 this.element.find( ".ui-menu-item" ) | |
9547 .removeClass( "ui-menu-item" ) | |
9548 .removeAttr( "role" ) | |
9549 .removeAttr( "aria-disabled" ) | |
9550 .children( "a" ) | |
9551 .removeUniqueId() | |
9552 .removeClass( "ui-corner-all ui-state-hover" ) | |
9553 .removeAttr( "tabIndex" ) | |
9554 .removeAttr( "role" ) | |
9555 .removeAttr( "aria-haspopup" ) | |
9556 .children().each( function() { | |
9557 var elem = $( this ); | |
9558 if ( elem.data( "ui-menu-submenu-carat" ) ) { | |
9559 elem.remove(); | |
9560 } | |
9561 }); | |
9562 | |
9563 // Destroy menu dividers | |
9564 this.element.find( ".ui-menu-divider" ).removeClass( "ui-menu-divider ui-widget-content" ); | |
9565 }, | |
9566 | |
9567 _keydown: function( event ) { | |
9568 var match, prev, character, skip, regex, | |
9569 preventDefault = true; | |
9570 | |
9571 function escape( value ) { | |
9572 return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ); | |
9573 } | |
9574 | |
9575 switch ( event.keyCode ) { | |
9576 case $.ui.keyCode.PAGE_UP: | |
9577 this.previousPage( event ); | |
9578 break; | |
9579 case $.ui.keyCode.PAGE_DOWN: | |
9580 this.nextPage( event ); | |
9581 break; | |
9582 case $.ui.keyCode.HOME: | |
9583 this._move( "first", "first", event ); | |
9584 break; | |
9585 case $.ui.keyCode.END: | |
9586 this._move( "last", "last", event ); | |
9587 break; | |
9588 case $.ui.keyCode.UP: | |
9589 this.previous( event ); | |
9590 break; | |
9591 case $.ui.keyCode.DOWN: | |
9592 this.next( event ); | |
9593 break; | |
9594 case $.ui.keyCode.LEFT: | |
9595 this.collapse( event ); | |
9596 break; | |
9597 case $.ui.keyCode.RIGHT: | |
9598 if ( this.active && !this.active.is( ".ui-state-disabled" ) ) { | |
9599 this.expand( event ); | |
9600 } | |
9601 break; | |
9602 case $.ui.keyCode.ENTER: | |
9603 case $.ui.keyCode.SPACE: | |
9604 this._activate( event ); | |
9605 break; | |
9606 case $.ui.keyCode.ESCAPE: | |
9607 this.collapse( event ); | |
9608 break; | |
9609 default: | |
9610 preventDefault = false; | |
9611 prev = this.previousFilter || ""; | |
9612 character = String.fromCharCode( event.keyCode ); | |
9613 skip = false; | |
9614 | |
9615 clearTimeout( this.filterTimer ); | |
9616 | |
9617 if ( character === prev ) { | |
9618 skip = true; | |
9619 } else { | |
9620 character = prev + character; | |
9621 } | |
9622 | |
9623 regex = new RegExp( "^" + escape( character ), "i" ); | |
9624 match = this.activeMenu.children( ".ui-menu-item" ).filter(function() { | |
9625 return regex.test( $( this ).children( "a" ).text() ); | |
9626 }); | |
9627 match = skip && match.index( this.active.next() ) !== -1 ? | |
9628 this.active.nextAll( ".ui-menu-item" ) : | |
9629 match; | |
9630 | |
9631 // If no matches on the current filter, reset to the last character pressed | |
9632 // to move down the menu to the first item that starts with that character | |
9633 if ( !match.length ) { | |
9634 character = String.fromCharCode( event.keyCode ); | |
9635 regex = new RegExp( "^" + escape( character ), "i" ); | |
9636 match = this.activeMenu.children( ".ui-menu-item" ).filter(function() { | |
9637 return regex.test( $( this ).children( "a" ).text() ); | |
9638 }); | |
9639 } | |
9640 | |
9641 if ( match.length ) { | |
9642 this.focus( event, match ); | |
9643 if ( match.length > 1 ) { | |
9644 this.previousFilter = character; | |
9645 this.filterTimer = this._delay(function() { | |
9646 delete this.previousFilter; | |
9647 }, 1000 ); | |
9648 } else { | |
9649 delete this.previousFilter; | |
9650 } | |
9651 } else { | |
9652 delete this.previousFilter; | |
9653 } | |
9654 } | |
9655 | |
9656 if ( preventDefault ) { | |
9657 event.preventDefault(); | |
9658 } | |
9659 }, | |
9660 | |
9661 _activate: function( event ) { | |
9662 if ( !this.active.is( ".ui-state-disabled" ) ) { | |
9663 if ( this.active.children( "a[aria-haspopup='true']" ).length ) { | |
9664 this.expand( event ); | |
9665 } else { | |
9666 this.select( event ); | |
9667 } | |
9668 } | |
9669 }, | |
9670 | |
9671 refresh: function() { | |
9672 var menus, | |
9673 icon = this.options.icons.submenu, | |
9674 submenus = this.element.find( this.options.menus ); | |
9675 | |
9676 this.element.toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length ); | |
9677 | |
9678 // Initialize nested menus | |
9679 submenus.filter( ":not(.ui-menu)" ) | |
9680 .addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" ) | |
9681 .hide() | |
9682 .attr({ | |
9683 role: this.options.role, | |
9684 "aria-hidden": "true", | |
9685 "aria-expanded": "false" | |
9686 }) | |
9687 .each(function() { | |
9688 var menu = $( this ), | |
9689 item = menu.prev( "a" ), | |
9690 submenuCarat = $( "<span>" ) | |
9691 .addClass( "ui-menu-icon ui-icon " + icon ) | |
9692 .data( "ui-menu-submenu-carat", true ); | |
9693 | |
9694 item | |
9695 .attr( "aria-haspopup", "true" ) | |
9696 .prepend( submenuCarat ); | |
9697 menu.attr( "aria-labelledby", item.attr( "id" ) ); | |
9698 }); | |
9699 | |
9700 menus = submenus.add( this.element ); | |
9701 | |
9702 // Don't refresh list items that are already adapted | |
9703 menus.children( ":not(.ui-menu-item):has(a)" ) | |
9704 .addClass( "ui-menu-item" ) | |
9705 .attr( "role", "presentation" ) | |
9706 .children( "a" ) | |
9707 .uniqueId() | |
9708 .addClass( "ui-corner-all" ) | |
9709 .attr({ | |
9710 tabIndex: -1, | |
9711 role: this._itemRole() | |
9712 }); | |
9713 | |
9714 // Initialize unlinked menu-items containing spaces and/or dashes only as dividers | |
9715 menus.children( ":not(.ui-menu-item)" ).each(function() { | |
9716 var item = $( this ); | |
9717 // hyphen, em dash, en dash | |
9718 if ( !/[^\-\u2014\u2013\s]/.test( item.text() ) ) { | |
9719 item.addClass( "ui-widget-content ui-menu-divider" ); | |
9720 } | |
9721 }); | |
9722 | |
9723 // Add aria-disabled attribute to any disabled menu item | |
9724 menus.children( ".ui-state-disabled" ).attr( "aria-disabled", "true" ); | |
9725 | |
9726 // If the active item has been removed, blur the menu | |
9727 if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) { | |
9728 this.blur(); | |
9729 } | |
9730 }, | |
9731 | |
9732 _itemRole: function() { | |
9733 return { | |
9734 menu: "menuitem", | |
9735 listbox: "option" | |
9736 }[ this.options.role ]; | |
9737 }, | |
9738 | |
9739 _setOption: function( key, value ) { | |
9740 if ( key === "icons" ) { | |
9741 this.element.find( ".ui-menu-icon" ) | |
9742 .removeClass( this.options.icons.submenu ) | |
9743 .addClass( value.submenu ); | |
9744 } | |
9745 this._super( key, value ); | |
9746 }, | |
9747 | |
9748 focus: function( event, item ) { | |
9749 var nested, focused; | |
9750 this.blur( event, event && event.type === "focus" ); | |
9751 | |
9752 this._scrollIntoView( item ); | |
9753 | |
9754 this.active = item.first(); | |
9755 focused = this.active.children( "a" ).addClass( "ui-state-focus" ); | |
9756 // Only update aria-activedescendant if there's a role | |
9757 // otherwise we assume focus is managed elsewhere | |
9758 if ( this.options.role ) { | |
9759 this.element.attr( "aria-activedescendant", focused.attr( "id" ) ); | |
9760 } | |
9761 | |
9762 // Highlight active parent menu item, if any | |
9763 this.active | |
9764 .parent() | |
9765 .closest( ".ui-menu-item" ) | |
9766 .children( "a:first" ) | |
9767 .addClass( "ui-state-active" ); | |
9768 | |
9769 if ( event && event.type === "keydown" ) { | |
9770 this._close(); | |
9771 } else { | |
9772 this.timer = this._delay(function() { | |
9773 this._close(); | |
9774 }, this.delay ); | |
9775 } | |
9776 | |
9777 nested = item.children( ".ui-menu" ); | |
9778 if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) { | |
9779 this._startOpening(nested); | |
9780 } | |
9781 this.activeMenu = item.parent(); | |
9782 | |
9783 this._trigger( "focus", event, { item: item } ); | |
9784 }, | |
9785 | |
9786 _scrollIntoView: function( item ) { | |
9787 var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight; | |
9788 if ( this._hasScroll() ) { | |
9789 borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0; | |
9790 paddingTop = parseFloat( $.css( this.activeMenu[0], "paddingTop" ) ) || 0; | |
9791 offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop; | |
9792 scroll = this.activeMenu.scrollTop(); | |
9793 elementHeight = this.activeMenu.height(); | |
9794 itemHeight = item.height(); | |
9795 | |
9796 if ( offset < 0 ) { | |
9797 this.activeMenu.scrollTop( scroll + offset ); | |
9798 } else if ( offset + itemHeight > elementHeight ) { | |
9799 this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight ); | |
9800 } | |
9801 } | |
9802 }, | |
9803 | |
9804 blur: function( event, fromFocus ) { | |
9805 if ( !fromFocus ) { | |
9806 clearTimeout( this.timer ); | |
9807 } | |
9808 | |
9809 if ( !this.active ) { | |
9810 return; | |
9811 } | |
9812 | |
9813 this.active.children( "a" ).removeClass( "ui-state-focus" ); | |
9814 this.active = null; | |
9815 | |
9816 this._trigger( "blur", event, { item: this.active } ); | |
9817 }, | |
9818 | |
9819 _startOpening: function( submenu ) { | |
9820 clearTimeout( this.timer ); | |
9821 | |
9822 // Don't open if already open fixes a Firefox bug that caused a .5 pixel | |
9823 // shift in the submenu position when mousing over the carat icon | |
9824 if ( submenu.attr( "aria-hidden" ) !== "true" ) { | |
9825 return; | |
9826 } | |
9827 | |
9828 this.timer = this._delay(function() { | |
9829 this._close(); | |
9830 this._open( submenu ); | |
9831 }, this.delay ); | |
9832 }, | |
9833 | |
9834 _open: function( submenu ) { | |
9835 var position = $.extend({ | |
9836 of: this.active | |
9837 }, this.options.position ); | |
9838 | |
9839 clearTimeout( this.timer ); | |
9840 this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) ) | |
9841 .hide() | |
9842 .attr( "aria-hidden", "true" ); | |
9843 | |
9844 submenu | |
9845 .show() | |
9846 .removeAttr( "aria-hidden" ) | |
9847 .attr( "aria-expanded", "true" ) | |
9848 .position( position ); | |
9849 }, | |
9850 | |
9851 collapseAll: function( event, all ) { | |
9852 clearTimeout( this.timer ); | |
9853 this.timer = this._delay(function() { | |
9854 // If we were passed an event, look for the submenu that contains the event | |
9855 var currentMenu = all ? this.element : | |
9856 $( event && event.target ).closest( this.element.find( ".ui-menu" ) ); | |
9857 | |
9858 // If we found no valid submenu ancestor, use the main menu to close all sub menus anyway | |
9859 if ( !currentMenu.length ) { | |
9860 currentMenu = this.element; | |
9861 } | |
9862 | |
9863 this._close( currentMenu ); | |
9864 | |
9865 this.blur( event ); | |
9866 this.activeMenu = currentMenu; | |
9867 }, this.delay ); | |
9868 }, | |
9869 | |
9870 // With no arguments, closes the currently active menu - if nothing is active | |
9871 // it closes all menus. If passed an argument, it will search for menus BELOW | |
9872 _close: function( startMenu ) { | |
9873 if ( !startMenu ) { | |
9874 startMenu = this.active ? this.active.parent() : this.element; | |
9875 } | |
9876 | |
9877 startMenu | |
9878 .find( ".ui-menu" ) | |
9879 .hide() | |
9880 .attr( "aria-hidden", "true" ) | |
9881 .attr( "aria-expanded", "false" ) | |
9882 .end() | |
9883 .find( "a.ui-state-active" ) | |
9884 .removeClass( "ui-state-active" ); | |
9885 }, | |
9886 | |
9887 collapse: function( event ) { | |
9888 var newItem = this.active && | |
9889 this.active.parent().closest( ".ui-menu-item", this.element ); | |
9890 if ( newItem && newItem.length ) { | |
9891 this._close(); | |
9892 this.focus( event, newItem ); | |
9893 } | |
9894 }, | |
9895 | |
9896 expand: function( event ) { | |
9897 var newItem = this.active && | |
9898 this.active | |
9899 .children( ".ui-menu " ) | |
9900 .children( ".ui-menu-item" ) | |
9901 .first(); | |
9902 | |
9903 if ( newItem && newItem.length ) { | |
9904 this._open( newItem.parent() ); | |
9905 | |
9906 // Delay so Firefox will not hide activedescendant change in expanding submenu from AT | |
9907 this._delay(function() { | |
9908 this.focus( event, newItem ); | |
9909 }); | |
9910 } | |
9911 }, | |
9912 | |
9913 next: function( event ) { | |
9914 this._move( "next", "first", event ); | |
9915 }, | |
9916 | |
9917 previous: function( event ) { | |
9918 this._move( "prev", "last", event ); | |
9919 }, | |
9920 | |
9921 isFirstItem: function() { | |
9922 return this.active && !this.active.prevAll( ".ui-menu-item" ).length; | |
9923 }, | |
9924 | |
9925 isLastItem: function() { | |
9926 return this.active && !this.active.nextAll( ".ui-menu-item" ).length; | |
9927 }, | |
9928 | |
9929 _move: function( direction, filter, event ) { | |
9930 var next; | |
9931 if ( this.active ) { | |
9932 if ( direction === "first" || direction === "last" ) { | |
9933 next = this.active | |
9934 [ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" ) | |
9935 .eq( -1 ); | |
9936 } else { | |
9937 next = this.active | |
9938 [ direction + "All" ]( ".ui-menu-item" ) | |
9939 .eq( 0 ); | |
9940 } | |
9941 } | |
9942 if ( !next || !next.length || !this.active ) { | |
9943 next = this.activeMenu.children( ".ui-menu-item" )[ filter ](); | |
9944 } | |
9945 | |
9946 this.focus( event, next ); | |
9947 }, | |
9948 | |
9949 nextPage: function( event ) { | |
9950 var item, base, height; | |
9951 | |
9952 if ( !this.active ) { | |
9953 this.next( event ); | |
9954 return; | |
9955 } | |
9956 if ( this.isLastItem() ) { | |
9957 return; | |
9958 } | |
9959 if ( this._hasScroll() ) { | |
9960 base = this.active.offset().top; | |
9961 height = this.element.height(); | |
9962 this.active.nextAll( ".ui-menu-item" ).each(function() { | |
9963 item = $( this ); | |
9964 return item.offset().top - base - height < 0; | |
9965 }); | |
9966 | |
9967 this.focus( event, item ); | |
9968 } else { | |
9969 this.focus( event, this.activeMenu.children( ".ui-menu-item" ) | |
9970 [ !this.active ? "first" : "last" ]() ); | |
9971 } | |
9972 }, | |
9973 | |
9974 previousPage: function( event ) { | |
9975 var item, base, height; | |
9976 if ( !this.active ) { | |
9977 this.next( event ); | |
9978 return; | |
9979 } | |
9980 if ( this.isFirstItem() ) { | |
9981 return; | |
9982 } | |
9983 if ( this._hasScroll() ) { | |
9984 base = this.active.offset().top; | |
9985 height = this.element.height(); | |
9986 this.active.prevAll( ".ui-menu-item" ).each(function() { | |
9987 item = $( this ); | |
9988 return item.offset().top - base + height > 0; | |
9989 }); | |
9990 | |
9991 this.focus( event, item ); | |
9992 } else { | |
9993 this.focus( event, this.activeMenu.children( ".ui-menu-item" ).first() ); | |
9994 } | |
9995 }, | |
9996 | |
9997 _hasScroll: function() { | |
9998 return this.element.outerHeight() < this.element.prop( "scrollHeight" ); | |
9999 }, | |
10000 | |
10001 select: function( event ) { | |
10002 // TODO: It should never be possible to not have an active item at this | |
10003 // point, but the tests don't trigger mouseenter before click. | |
10004 this.active = this.active || $( event.target ).closest( ".ui-menu-item" ); | |
10005 var ui = { item: this.active }; | |
10006 if ( !this.active.has( ".ui-menu" ).length ) { | |
10007 this.collapseAll( event, true ); | |
10008 } | |
10009 this._trigger( "select", event, ui ); | |
10010 } | |
10011 }); | |
10012 | |
10013 }( jQuery )); | |
10014 (function( $, undefined ) { | |
10015 | |
10016 $.widget( "ui.progressbar", { | |
10017 version: "1.10.4", | |
10018 options: { | |
10019 max: 100, | |
10020 value: 0, | |
10021 | |
10022 change: null, | |
10023 complete: null | |
10024 }, | |
10025 | |
10026 min: 0, | |
10027 | |
10028 _create: function() { | |
10029 // Constrain initial value | |
10030 this.oldValue = this.options.value = this._constrainedValue(); | |
10031 | |
10032 this.element | |
10033 .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" ) | |
10034 .attr({ | |
10035 // Only set static values, aria-valuenow and aria-valuemax are | |
10036 // set inside _refreshValue() | |
10037 role: "progressbar", | |
10038 "aria-valuemin": this.min | |
10039 }); | |
10040 | |
10041 this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" ) | |
10042 .appendTo( this.element ); | |
10043 | |
10044 this._refreshValue(); | |
10045 }, | |
10046 | |
10047 _destroy: function() { | |
10048 this.element | |
10049 .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" ) | |
10050 .removeAttr( "role" ) | |
10051 .removeAttr( "aria-valuemin" ) | |
10052 .removeAttr( "aria-valuemax" ) | |
10053 .removeAttr( "aria-valuenow" ); | |
10054 | |
10055 this.valueDiv.remove(); | |
10056 }, | |
10057 | |
10058 value: function( newValue ) { | |
10059 if ( newValue === undefined ) { | |
10060 return this.options.value; | |
10061 } | |
10062 | |
10063 this.options.value = this._constrainedValue( newValue ); | |
10064 this._refreshValue(); | |
10065 }, | |
10066 | |
10067 _constrainedValue: function( newValue ) { | |
10068 if ( newValue === undefined ) { | |
10069 newValue = this.options.value; | |
10070 } | |
10071 | |
10072 this.indeterminate = newValue === false; | |
10073 | |
10074 // sanitize value | |
10075 if ( typeof newValue !== "number" ) { | |
10076 newValue = 0; | |
10077 } | |
10078 | |
10079 return this.indeterminate ? false : | |
10080 Math.min( this.options.max, Math.max( this.min, newValue ) ); | |
10081 }, | |
10082 | |
10083 _setOptions: function( options ) { | |
10084 // Ensure "value" option is set after other values (like max) | |
10085 var value = options.value; | |
10086 delete options.value; | |
10087 | |
10088 this._super( options ); | |
10089 | |
10090 this.options.value = this._constrainedValue( value ); | |
10091 this._refreshValue(); | |
10092 }, | |
10093 | |
10094 _setOption: function( key, value ) { | |
10095 if ( key === "max" ) { | |
10096 // Don't allow a max less than min | |
10097 value = Math.max( this.min, value ); | |
10098 } | |
10099 | |
10100 this._super( key, value ); | |
10101 }, | |
10102 | |
10103 _percentage: function() { | |
10104 return this.indeterminate ? 100 : 100 * ( this.options.value - this.min ) / ( this.options.max - this.min ); | |
10105 }, | |
10106 | |
10107 _refreshValue: function() { | |
10108 var value = this.options.value, | |
10109 percentage = this._percentage(); | |
10110 | |
10111 this.valueDiv | |
10112 .toggle( this.indeterminate || value > this.min ) | |
10113 .toggleClass( "ui-corner-right", value === this.options.max ) | |
10114 .width( percentage.toFixed(0) + "%" ); | |
10115 | |
10116 this.element.toggleClass( "ui-progressbar-indeterminate", this.indeterminate ); | |
10117 | |
10118 if ( this.indeterminate ) { | |
10119 this.element.removeAttr( "aria-valuenow" ); | |
10120 if ( !this.overlayDiv ) { | |
10121 this.overlayDiv = $( "<div class='ui-progressbar-overlay'></div>" ).appendTo( this.valueDiv ); | |
10122 } | |
10123 } else { | |
10124 this.element.attr({ | |
10125 "aria-valuemax": this.options.max, | |
10126 "aria-valuenow": value | |
10127 }); | |
10128 if ( this.overlayDiv ) { | |
10129 this.overlayDiv.remove(); | |
10130 this.overlayDiv = null; | |
10131 } | |
10132 } | |
10133 | |
10134 if ( this.oldValue !== value ) { | |
10135 this.oldValue = value; | |
10136 this._trigger( "change" ); | |
10137 } | |
10138 if ( value === this.options.max ) { | |
10139 this._trigger( "complete" ); | |
10140 } | |
10141 } | |
10142 }); | |
10143 | |
10144 })( jQuery ); | |
10145 (function( $, undefined ) { | |
10146 | |
10147 function num(v) { | |
10148 return parseInt(v, 10) || 0; | |
10149 } | |
10150 | |
10151 function isNumber(value) { | |
10152 return !isNaN(parseInt(value, 10)); | |
10153 } | |
10154 | |
10155 $.widget("ui.resizable", $.ui.mouse, { | |
10156 version: "1.10.4", | |
10157 widgetEventPrefix: "resize", | |
10158 options: { | |
10159 alsoResize: false, | |
10160 animate: false, | |
10161 animateDuration: "slow", | |
10162 animateEasing: "swing", | |
10163 aspectRatio: false, | |
10164 autoHide: false, | |
10165 containment: false, | |
10166 ghost: false, | |
10167 grid: false, | |
10168 handles: "e,s,se", | |
10169 helper: false, | |
10170 maxHeight: null, | |
10171 maxWidth: null, | |
10172 minHeight: 10, | |
10173 minWidth: 10, | |
10174 // See #7960 | |
10175 zIndex: 90, | |
10176 | |
10177 // callbacks | |
10178 resize: null, | |
10179 start: null, | |
10180 stop: null | |
10181 }, | |
10182 _create: function() { | |
10183 | |
10184 var n, i, handle, axis, hname, | |
10185 that = this, | |
10186 o = this.options; | |
10187 this.element.addClass("ui-resizable"); | |
10188 | |
10189 $.extend(this, { | |
10190 _aspectRatio: !!(o.aspectRatio), | |
10191 aspectRatio: o.aspectRatio, | |
10192 originalElement: this.element, | |
10193 _proportionallyResizeElements: [], | |
10194 _helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null | |
10195 }); | |
10196 | |
10197 //Wrap the element if it cannot hold child nodes | |
10198 if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) { | |
10199 | |
10200 //Create a wrapper element and set the wrapper to the new current internal element | |
10201 this.element.wrap( | |
10202 $("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({ | |
10203 position: this.element.css("position"), | |
10204 width: this.element.outerWidth(), | |
10205 height: this.element.outerHeight(), | |
10206 top: this.element.css("top"), | |
10207 left: this.element.css("left") | |
10208 }) | |
10209 ); | |
10210 | |
10211 //Overwrite the original this.element | |
10212 this.element = this.element.parent().data( | |
10213 "ui-resizable", this.element.data("ui-resizable") | |
10214 ); | |
10215 | |
10216 this.elementIsWrapper = true; | |
10217 | |
10218 //Move margins to the wrapper | |
10219 this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") }); | |
10220 this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0}); | |
10221 | |
10222 //Prevent Safari textarea resize | |
10223 this.originalResizeStyle = this.originalElement.css("resize"); | |
10224 this.originalElement.css("resize", "none"); | |
10225 | |
10226 //Push the actual element to our proportionallyResize internal array | |
10227 this._proportionallyResizeElements.push(this.originalElement.css({ position: "static", zoom: 1, display: "block" })); | |
10228 | |
10229 // avoid IE jump (hard set the margin) | |
10230 this.originalElement.css({ margin: this.originalElement.css("margin") }); | |
10231 | |
10232 // fix handlers offset | |
10233 this._proportionallyResize(); | |
10234 | |
10235 } | |
10236 | |
10237 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" }); | |
10238 if(this.handles.constructor === String) { | |
10239 | |
10240 if ( this.handles === "all") { | |
10241 this.handles = "n,e,s,w,se,sw,ne,nw"; | |
10242 } | |
10243 | |
10244 n = this.handles.split(","); | |
10245 this.handles = {}; | |
10246 | |
10247 for(i = 0; i < n.length; i++) { | |
10248 | |
10249 handle = $.trim(n[i]); | |
10250 hname = "ui-resizable-"+handle; | |
10251 axis = $("<div class='ui-resizable-handle " + hname + "'></div>"); | |
10252 | |
10253 // Apply zIndex to all handles - see #7960 | |
10254 axis.css({ zIndex: o.zIndex }); | |
10255 | |
10256 //TODO : What's going on here? | |
10257 if ("se" === handle) { | |
10258 axis.addClass("ui-icon ui-icon-gripsmall-diagonal-se"); | |
10259 } | |
10260 | |
10261 //Insert into internal handles object and append to element | |
10262 this.handles[handle] = ".ui-resizable-"+handle; | |
10263 this.element.append(axis); | |
10264 } | |
10265 | |
10266 } | |
10267 | |
10268 this._renderAxis = function(target) { | |
10269 | |
10270 var i, axis, padPos, padWrapper; | |
10271 | |
10272 target = target || this.element; | |
10273 | |
10274 for(i in this.handles) { | |
10275 | |
10276 if(this.handles[i].constructor === String) { | |
10277 this.handles[i] = $(this.handles[i], this.element).show(); | |
10278 } | |
10279 | |
10280 //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls) | |
10281 if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) { | |
10282 | |
10283 axis = $(this.handles[i], this.element); | |
10284 | |
10285 //Checking the correct pad and border | |
10286 padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth(); | |
10287 | |
10288 //The padding type i have to apply... | |
10289 padPos = [ "padding", | |
10290 /ne|nw|n/.test(i) ? "Top" : | |
10291 /se|sw|s/.test(i) ? "Bottom" : | |
10292 /^e$/.test(i) ? "Right" : "Left" ].join(""); | |
10293 | |
10294 target.css(padPos, padWrapper); | |
10295 | |
10296 this._proportionallyResize(); | |
10297 | |
10298 } | |
10299 | |
10300 //TODO: What's that good for? There's not anything to be executed left | |
10301 if(!$(this.handles[i]).length) { | |
10302 continue; | |
10303 } | |
10304 } | |
10305 }; | |
10306 | |
10307 //TODO: make renderAxis a prototype function | |
10308 this._renderAxis(this.element); | |
10309 | |
10310 this._handles = $(".ui-resizable-handle", this.element) | |
10311 .disableSelection(); | |
10312 | |
10313 //Matching axis name | |
10314 this._handles.mouseover(function() { | |
10315 if (!that.resizing) { | |
10316 if (this.className) { | |
10317 axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i); | |
10318 } | |
10319 //Axis, default = se | |
10320 that.axis = axis && axis[1] ? axis[1] : "se"; | |
10321 } | |
10322 }); | |
10323 | |
10324 //If we want to auto hide the elements | |
10325 if (o.autoHide) { | |
10326 this._handles.hide(); | |
10327 $(this.element) | |
10328 .addClass("ui-resizable-autohide") | |
10329 .mouseenter(function() { | |
10330 if (o.disabled) { | |
10331 return; | |
10332 } | |
10333 $(this).removeClass("ui-resizable-autohide"); | |
10334 that._handles.show(); | |
10335 }) | |
10336 .mouseleave(function(){ | |
10337 if (o.disabled) { | |
10338 return; | |
10339 } | |
10340 if (!that.resizing) { | |
10341 $(this).addClass("ui-resizable-autohide"); | |
10342 that._handles.hide(); | |
10343 } | |
10344 }); | |
10345 } | |
10346 | |
10347 //Initialize the mouse interaction | |
10348 this._mouseInit(); | |
10349 | |
10350 }, | |
10351 | |
10352 _destroy: function() { | |
10353 | |
10354 this._mouseDestroy(); | |
10355 | |
10356 var wrapper, | |
10357 _destroy = function(exp) { | |
10358 $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing") | |
10359 .removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove(); | |
10360 }; | |
10361 | |
10362 //TODO: Unwrap at same DOM position | |
10363 if (this.elementIsWrapper) { | |
10364 _destroy(this.element); | |
10365 wrapper = this.element; | |
10366 this.originalElement.css({ | |
10367 position: wrapper.css("position"), | |
10368 width: wrapper.outerWidth(), | |
10369 height: wrapper.outerHeight(), | |
10370 top: wrapper.css("top"), | |
10371 left: wrapper.css("left") | |
10372 }).insertAfter( wrapper ); | |
10373 wrapper.remove(); | |
10374 } | |
10375 | |
10376 this.originalElement.css("resize", this.originalResizeStyle); | |
10377 _destroy(this.originalElement); | |
10378 | |
10379 return this; | |
10380 }, | |
10381 | |
10382 _mouseCapture: function(event) { | |
10383 var i, handle, | |
10384 capture = false; | |
10385 | |
10386 for (i in this.handles) { | |
10387 handle = $(this.handles[i])[0]; | |
10388 if (handle === event.target || $.contains(handle, event.target)) { | |
10389 capture = true; | |
10390 } | |
10391 } | |
10392 | |
10393 return !this.options.disabled && capture; | |
10394 }, | |
10395 | |
10396 _mouseStart: function(event) { | |
10397 | |
10398 var curleft, curtop, cursor, | |
10399 o = this.options, | |
10400 iniPos = this.element.position(), | |
10401 el = this.element; | |
10402 | |
10403 this.resizing = true; | |
10404 | |
10405 // bugfix for http://dev.jquery.com/ticket/1749 | |
10406 if ( (/absolute/).test( el.css("position") ) ) { | |
10407 el.css({ position: "absolute", top: el.css("top"), left: el.css("left") }); | |
10408 } else if (el.is(".ui-draggable")) { | |
10409 el.css({ position: "absolute", top: iniPos.top, left: iniPos.left }); | |
10410 } | |
10411 | |
10412 this._renderProxy(); | |
10413 | |
10414 curleft = num(this.helper.css("left")); | |
10415 curtop = num(this.helper.css("top")); | |
10416 | |
10417 if (o.containment) { | |
10418 curleft += $(o.containment).scrollLeft() || 0; | |
10419 curtop += $(o.containment).scrollTop() || 0; | |
10420 } | |
10421 | |
10422 //Store needed variables | |
10423 this.offset = this.helper.offset(); | |
10424 this.position = { left: curleft, top: curtop }; | |
10425 this.size = this._helper ? { width: this.helper.width(), height: this.helper.height() } : { width: el.width(), height: el.height() }; | |
10426 this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() }; | |
10427 this.originalPosition = { left: curleft, top: curtop }; | |
10428 this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() }; | |
10429 this.originalMousePosition = { left: event.pageX, top: event.pageY }; | |
10430 | |
10431 //Aspect Ratio | |
10432 this.aspectRatio = (typeof o.aspectRatio === "number") ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1); | |
10433 | |
10434 cursor = $(".ui-resizable-" + this.axis).css("cursor"); | |
10435 $("body").css("cursor", cursor === "auto" ? this.axis + "-resize" : cursor); | |
10436 | |
10437 el.addClass("ui-resizable-resizing"); | |
10438 this._propagate("start", event); | |
10439 return true; | |
10440 }, | |
10441 | |
10442 _mouseDrag: function(event) { | |
10443 | |
10444 //Increase performance, avoid regex | |
10445 var data, | |
10446 el = this.helper, props = {}, | |
10447 smp = this.originalMousePosition, | |
10448 a = this.axis, | |
10449 prevTop = this.position.top, | |
10450 prevLeft = this.position.left, | |
10451 prevWidth = this.size.width, | |
10452 prevHeight = this.size.height, | |
10453 dx = (event.pageX-smp.left)||0, | |
10454 dy = (event.pageY-smp.top)||0, | |
10455 trigger = this._change[a]; | |
10456 | |
10457 if (!trigger) { | |
10458 return false; | |
10459 } | |
10460 | |
10461 // Calculate the attrs that will be change | |
10462 data = trigger.apply(this, [event, dx, dy]); | |
10463 | |
10464 // Put this in the mouseDrag handler since the user can start pressing shift while resizing | |
10465 this._updateVirtualBoundaries(event.shiftKey); | |
10466 if (this._aspectRatio || event.shiftKey) { | |
10467 data = this._updateRatio(data, event); | |
10468 } | |
10469 | |
10470 data = this._respectSize(data, event); | |
10471 | |
10472 this._updateCache(data); | |
10473 | |
10474 // plugins callbacks need to be called first | |
10475 this._propagate("resize", event); | |
10476 | |
10477 if (this.position.top !== prevTop) { | |
10478 props.top = this.position.top + "px"; | |
10479 } | |
10480 if (this.position.left !== prevLeft) { | |
10481 props.left = this.position.left + "px"; | |
10482 } | |
10483 if (this.size.width !== prevWidth) { | |
10484 props.width = this.size.width + "px"; | |
10485 } | |
10486 if (this.size.height !== prevHeight) { | |
10487 props.height = this.size.height + "px"; | |
10488 } | |
10489 el.css(props); | |
10490 | |
10491 if (!this._helper && this._proportionallyResizeElements.length) { | |
10492 this._proportionallyResize(); | |
10493 } | |
10494 | |
10495 // Call the user callback if the element was resized | |
10496 if ( ! $.isEmptyObject(props) ) { | |
10497 this._trigger("resize", event, this.ui()); | |
10498 } | |
10499 | |
10500 return false; | |
10501 }, | |
10502 | |
10503 _mouseStop: function(event) { | |
10504 | |
10505 this.resizing = false; | |
10506 var pr, ista, soffseth, soffsetw, s, left, top, | |
10507 o = this.options, that = this; | |
10508 | |
10509 if(this._helper) { | |
10510 | |
10511 pr = this._proportionallyResizeElements; | |
10512 ista = pr.length && (/textarea/i).test(pr[0].nodeName); | |
10513 soffseth = ista && $.ui.hasScroll(pr[0], "left") /* TODO - jump height */ ? 0 : that.sizeDiff.height; | |
10514 soffsetw = ista ? 0 : that.sizeDiff.width; | |
10515 | |
10516 s = { width: (that.helper.width() - soffsetw), height: (that.helper.height() - soffseth) }; | |
10517 left = (parseInt(that.element.css("left"), 10) + (that.position.left - that.originalPosition.left)) || null; | |
10518 top = (parseInt(that.element.css("top"), 10) + (that.position.top - that.originalPosition.top)) || null; | |
10519 | |
10520 if (!o.animate) { | |
10521 this.element.css($.extend(s, { top: top, left: left })); | |
10522 } | |
10523 | |
10524 that.helper.height(that.size.height); | |
10525 that.helper.width(that.size.width); | |
10526 | |
10527 if (this._helper && !o.animate) { | |
10528 this._proportionallyResize(); | |
10529 } | |
10530 } | |
10531 | |
10532 $("body").css("cursor", "auto"); | |
10533 | |
10534 this.element.removeClass("ui-resizable-resizing"); | |
10535 | |
10536 this._propagate("stop", event); | |
10537 | |
10538 if (this._helper) { | |
10539 this.helper.remove(); | |
10540 } | |
10541 | |
10542 return false; | |
10543 | |
10544 }, | |
10545 | |
10546 _updateVirtualBoundaries: function(forceAspectRatio) { | |
10547 var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b, | |
10548 o = this.options; | |
10549 | |
10550 b = { | |
10551 minWidth: isNumber(o.minWidth) ? o.minWidth : 0, | |
10552 maxWidth: isNumber(o.maxWidth) ? o.maxWidth : Infinity, | |
10553 minHeight: isNumber(o.minHeight) ? o.minHeight : 0, | |
10554 maxHeight: isNumber(o.maxHeight) ? o.maxHeight : Infinity | |
10555 }; | |
10556 | |
10557 if(this._aspectRatio || forceAspectRatio) { | |
10558 // We want to create an enclosing box whose aspect ration is the requested one | |
10559 // First, compute the "projected" size for each dimension based on the aspect ratio and other dimension | |
10560 pMinWidth = b.minHeight * this.aspectRatio; | |
10561 pMinHeight = b.minWidth / this.aspectRatio; | |
10562 pMaxWidth = b.maxHeight * this.aspectRatio; | |
10563 pMaxHeight = b.maxWidth / this.aspectRatio; | |
10564 | |
10565 if(pMinWidth > b.minWidth) { | |
10566 b.minWidth = pMinWidth; | |
10567 } | |
10568 if(pMinHeight > b.minHeight) { | |
10569 b.minHeight = pMinHeight; | |
10570 } | |
10571 if(pMaxWidth < b.maxWidth) { | |
10572 b.maxWidth = pMaxWidth; | |
10573 } | |
10574 if(pMaxHeight < b.maxHeight) { | |
10575 b.maxHeight = pMaxHeight; | |
10576 } | |
10577 } | |
10578 this._vBoundaries = b; | |
10579 }, | |
10580 | |
10581 _updateCache: function(data) { | |
10582 this.offset = this.helper.offset(); | |
10583 if (isNumber(data.left)) { | |
10584 this.position.left = data.left; | |
10585 } | |
10586 if (isNumber(data.top)) { | |
10587 this.position.top = data.top; | |
10588 } | |
10589 if (isNumber(data.height)) { | |
10590 this.size.height = data.height; | |
10591 } | |
10592 if (isNumber(data.width)) { | |
10593 this.size.width = data.width; | |
10594 } | |
10595 }, | |
10596 | |
10597 _updateRatio: function( data ) { | |
10598 | |
10599 var cpos = this.position, | |
10600 csize = this.size, | |
10601 a = this.axis; | |
10602 | |
10603 if (isNumber(data.height)) { | |
10604 data.width = (data.height * this.aspectRatio); | |
10605 } else if (isNumber(data.width)) { | |
10606 data.height = (data.width / this.aspectRatio); | |
10607 } | |
10608 | |
10609 if (a === "sw") { | |
10610 data.left = cpos.left + (csize.width - data.width); | |
10611 data.top = null; | |
10612 } | |
10613 if (a === "nw") { | |
10614 data.top = cpos.top + (csize.height - data.height); | |
10615 data.left = cpos.left + (csize.width - data.width); | |
10616 } | |
10617 | |
10618 return data; | |
10619 }, | |
10620 | |
10621 _respectSize: function( data ) { | |
10622 | |
10623 var o = this._vBoundaries, | |
10624 a = this.axis, | |
10625 ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height), | |
10626 isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height), | |
10627 dw = this.originalPosition.left + this.originalSize.width, | |
10628 dh = this.position.top + this.size.height, | |
10629 cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a); | |
10630 if (isminw) { | |
10631 data.width = o.minWidth; | |
10632 } | |
10633 if (isminh) { | |
10634 data.height = o.minHeight; | |
10635 } | |
10636 if (ismaxw) { | |
10637 data.width = o.maxWidth; | |
10638 } | |
10639 if (ismaxh) { | |
10640 data.height = o.maxHeight; | |
10641 } | |
10642 | |
10643 if (isminw && cw) { | |
10644 data.left = dw - o.minWidth; | |
10645 } | |
10646 if (ismaxw && cw) { | |
10647 data.left = dw - o.maxWidth; | |
10648 } | |
10649 if (isminh && ch) { | |
10650 data.top = dh - o.minHeight; | |
10651 } | |
10652 if (ismaxh && ch) { | |
10653 data.top = dh - o.maxHeight; | |
10654 } | |
10655 | |
10656 // fixing jump error on top/left - bug #2330 | |
10657 if (!data.width && !data.height && !data.left && data.top) { | |
10658 data.top = null; | |
10659 } else if (!data.width && !data.height && !data.top && data.left) { | |
10660 data.left = null; | |
10661 } | |
10662 | |
10663 return data; | |
10664 }, | |
10665 | |
10666 _proportionallyResize: function() { | |
10667 | |
10668 if (!this._proportionallyResizeElements.length) { | |
10669 return; | |
10670 } | |
10671 | |
10672 var i, j, borders, paddings, prel, | |
10673 element = this.helper || this.element; | |
10674 | |
10675 for ( i=0; i < this._proportionallyResizeElements.length; i++) { | |
10676 | |
10677 prel = this._proportionallyResizeElements[i]; | |
10678 | |
10679 if (!this.borderDif) { | |
10680 this.borderDif = []; | |
10681 borders = [prel.css("borderTopWidth"), prel.css("borderRightWidth"), prel.css("borderBottomWidth"), prel.css("borderLeftWidth")]; | |
10682 paddings = [prel.css("paddingTop"), prel.css("paddingRight"), prel.css("paddingBottom"), prel.css("paddingLeft")]; | |
10683 | |
10684 for ( j = 0; j < borders.length; j++ ) { | |
10685 this.borderDif[ j ] = ( parseInt( borders[ j ], 10 ) || 0 ) + ( parseInt( paddings[ j ], 10 ) || 0 ); | |
10686 } | |
10687 } | |
10688 | |
10689 prel.css({ | |
10690 height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0, | |
10691 width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0 | |
10692 }); | |
10693 | |
10694 } | |
10695 | |
10696 }, | |
10697 | |
10698 _renderProxy: function() { | |
10699 | |
10700 var el = this.element, o = this.options; | |
10701 this.elementOffset = el.offset(); | |
10702 | |
10703 if(this._helper) { | |
10704 | |
10705 this.helper = this.helper || $("<div style='overflow:hidden;'></div>"); | |
10706 | |
10707 this.helper.addClass(this._helper).css({ | |
10708 width: this.element.outerWidth() - 1, | |
10709 height: this.element.outerHeight() - 1, | |
10710 position: "absolute", | |
10711 left: this.elementOffset.left +"px", | |
10712 top: this.elementOffset.top +"px", | |
10713 zIndex: ++o.zIndex //TODO: Don't modify option | |
10714 }); | |
10715 | |
10716 this.helper | |
10717 .appendTo("body") | |
10718 .disableSelection(); | |
10719 | |
10720 } else { | |
10721 this.helper = this.element; | |
10722 } | |
10723 | |
10724 }, | |
10725 | |
10726 _change: { | |
10727 e: function(event, dx) { | |
10728 return { width: this.originalSize.width + dx }; | |
10729 }, | |
10730 w: function(event, dx) { | |
10731 var cs = this.originalSize, sp = this.originalPosition; | |
10732 return { left: sp.left + dx, width: cs.width - dx }; | |
10733 }, | |
10734 n: function(event, dx, dy) { | |
10735 var cs = this.originalSize, sp = this.originalPosition; | |
10736 return { top: sp.top + dy, height: cs.height - dy }; | |
10737 }, | |
10738 s: function(event, dx, dy) { | |
10739 return { height: this.originalSize.height + dy }; | |
10740 }, | |
10741 se: function(event, dx, dy) { | |
10742 return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy])); | |
10743 }, | |
10744 sw: function(event, dx, dy) { | |
10745 return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy])); | |
10746 }, | |
10747 ne: function(event, dx, dy) { | |
10748 return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy])); | |
10749 }, | |
10750 nw: function(event, dx, dy) { | |
10751 return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy])); | |
10752 } | |
10753 }, | |
10754 | |
10755 _propagate: function(n, event) { | |
10756 $.ui.plugin.call(this, n, [event, this.ui()]); | |
10757 (n !== "resize" && this._trigger(n, event, this.ui())); | |
10758 }, | |
10759 | |
10760 plugins: {}, | |
10761 | |
10762 ui: function() { | |
10763 return { | |
10764 originalElement: this.originalElement, | |
10765 element: this.element, | |
10766 helper: this.helper, | |
10767 position: this.position, | |
10768 size: this.size, | |
10769 originalSize: this.originalSize, | |
10770 originalPosition: this.originalPosition | |
10771 }; | |
10772 } | |
10773 | |
10774 }); | |
10775 | |
10776 /* | |
10777 * Resizable Extensions | |
10778 */ | |
10779 | |
10780 $.ui.plugin.add("resizable", "animate", { | |
10781 | |
10782 stop: function( event ) { | |
10783 var that = $(this).data("ui-resizable"), | |
10784 o = that.options, | |
10785 pr = that._proportionallyResizeElements, | |
10786 ista = pr.length && (/textarea/i).test(pr[0].nodeName), | |
10787 soffseth = ista && $.ui.hasScroll(pr[0], "left") /* TODO - jump height */ ? 0 : that.sizeDiff.height, | |
10788 soffsetw = ista ? 0 : that.sizeDiff.width, | |
10789 style = { width: (that.size.width - soffsetw), height: (that.size.height - soffseth) }, | |
10790 left = (parseInt(that.element.css("left"), 10) + (that.position.left - that.originalPosition.left)) || null, | |
10791 top = (parseInt(that.element.css("top"), 10) + (that.position.top - that.originalPosition.top)) || null; | |
10792 | |
10793 that.element.animate( | |
10794 $.extend(style, top && left ? { top: top, left: left } : {}), { | |
10795 duration: o.animateDuration, | |
10796 easing: o.animateEasing, | |
10797 step: function() { | |
10798 | |
10799 var data = { | |
10800 width: parseInt(that.element.css("width"), 10), | |
10801 height: parseInt(that.element.css("height"), 10), | |
10802 top: parseInt(that.element.css("top"), 10), | |
10803 left: parseInt(that.element.css("left"), 10) | |
10804 }; | |
10805 | |
10806 if (pr && pr.length) { | |
10807 $(pr[0]).css({ width: data.width, height: data.height }); | |
10808 } | |
10809 | |
10810 // propagating resize, and updating values for each animation step | |
10811 that._updateCache(data); | |
10812 that._propagate("resize", event); | |
10813 | |
10814 } | |
10815 } | |
10816 ); | |
10817 } | |
10818 | |
10819 }); | |
10820 | |
10821 $.ui.plugin.add("resizable", "containment", { | |
10822 | |
10823 start: function() { | |
10824 var element, p, co, ch, cw, width, height, | |
10825 that = $(this).data("ui-resizable"), | |
10826 o = that.options, | |
10827 el = that.element, | |
10828 oc = o.containment, | |
10829 ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc; | |
10830 | |
10831 if (!ce) { | |
10832 return; | |
10833 } | |
10834 | |
10835 that.containerElement = $(ce); | |
10836 | |
10837 if (/document/.test(oc) || oc === document) { | |
10838 that.containerOffset = { left: 0, top: 0 }; | |
10839 that.containerPosition = { left: 0, top: 0 }; | |
10840 | |
10841 that.parentData = { | |
10842 element: $(document), left: 0, top: 0, | |
10843 width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight | |
10844 }; | |
10845 } | |
10846 | |
10847 // i'm a node, so compute top, left, right, bottom | |
10848 else { | |
10849 element = $(ce); | |
10850 p = []; | |
10851 $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); }); | |
10852 | |
10853 that.containerOffset = element.offset(); | |
10854 that.containerPosition = element.position(); | |
10855 that.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) }; | |
10856 | |
10857 co = that.containerOffset; | |
10858 ch = that.containerSize.height; | |
10859 cw = that.containerSize.width; | |
10860 width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ); | |
10861 height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch); | |
10862 | |
10863 that.parentData = { | |
10864 element: ce, left: co.left, top: co.top, width: width, height: height | |
10865 }; | |
10866 } | |
10867 }, | |
10868 | |
10869 resize: function( event ) { | |
10870 var woset, hoset, isParent, isOffsetRelative, | |
10871 that = $(this).data("ui-resizable"), | |
10872 o = that.options, | |
10873 co = that.containerOffset, cp = that.position, | |
10874 pRatio = that._aspectRatio || event.shiftKey, | |
10875 cop = { top:0, left:0 }, ce = that.containerElement; | |
10876 | |
10877 if (ce[0] !== document && (/static/).test(ce.css("position"))) { | |
10878 cop = co; | |
10879 } | |
10880 | |
10881 if (cp.left < (that._helper ? co.left : 0)) { | |
10882 that.size.width = that.size.width + (that._helper ? (that.position.left - co.left) : (that.position.left - cop.left)); | |
10883 if (pRatio) { | |
10884 that.size.height = that.size.width / that.aspectRatio; | |
10885 } | |
10886 that.position.left = o.helper ? co.left : 0; | |
10887 } | |
10888 | |
10889 if (cp.top < (that._helper ? co.top : 0)) { | |
10890 that.size.height = that.size.height + (that._helper ? (that.position.top - co.top) : that.position.top); | |
10891 if (pRatio) { | |
10892 that.size.width = that.size.height * that.aspectRatio; | |
10893 } | |
10894 that.position.top = that._helper ? co.top : 0; | |
10895 } | |
10896 | |
10897 that.offset.left = that.parentData.left+that.position.left; | |
10898 that.offset.top = that.parentData.top+that.position.top; | |
10899 | |
10900 woset = Math.abs( (that._helper ? that.offset.left - cop.left : (that.offset.left - cop.left)) + that.sizeDiff.width ); | |
10901 hoset = Math.abs( (that._helper ? that.offset.top - cop.top : (that.offset.top - co.top)) + that.sizeDiff.height ); | |
10902 | |
10903 isParent = that.containerElement.get(0) === that.element.parent().get(0); | |
10904 isOffsetRelative = /relative|absolute/.test(that.containerElement.css("position")); | |
10905 | |
10906 if ( isParent && isOffsetRelative ) { | |
10907 woset -= Math.abs( that.parentData.left ); | |
10908 } | |
10909 | |
10910 if (woset + that.size.width >= that.parentData.width) { | |
10911 that.size.width = that.parentData.width - woset; | |
10912 if (pRatio) { | |
10913 that.size.height = that.size.width / that.aspectRatio; | |
10914 } | |
10915 } | |
10916 | |
10917 if (hoset + that.size.height >= that.parentData.height) { | |
10918 that.size.height = that.parentData.height - hoset; | |
10919 if (pRatio) { | |
10920 that.size.width = that.size.height * that.aspectRatio; | |
10921 } | |
10922 } | |
10923 }, | |
10924 | |
10925 stop: function(){ | |
10926 var that = $(this).data("ui-resizable"), | |
10927 o = that.options, | |
10928 co = that.containerOffset, | |
10929 cop = that.containerPosition, | |
10930 ce = that.containerElement, | |
10931 helper = $(that.helper), | |
10932 ho = helper.offset(), | |
10933 w = helper.outerWidth() - that.sizeDiff.width, | |
10934 h = helper.outerHeight() - that.sizeDiff.height; | |
10935 | |
10936 if (that._helper && !o.animate && (/relative/).test(ce.css("position"))) { | |
10937 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h }); | |
10938 } | |
10939 | |
10940 if (that._helper && !o.animate && (/static/).test(ce.css("position"))) { | |
10941 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h }); | |
10942 } | |
10943 | |
10944 } | |
10945 }); | |
10946 | |
10947 $.ui.plugin.add("resizable", "alsoResize", { | |
10948 | |
10949 start: function () { | |
10950 var that = $(this).data("ui-resizable"), | |
10951 o = that.options, | |
10952 _store = function (exp) { | |
10953 $(exp).each(function() { | |
10954 var el = $(this); | |
10955 el.data("ui-resizable-alsoresize", { | |
10956 width: parseInt(el.width(), 10), height: parseInt(el.height(), 10), | |
10957 left: parseInt(el.css("left"), 10), top: parseInt(el.css("top"), 10) | |
10958 }); | |
10959 }); | |
10960 }; | |
10961 | |
10962 if (typeof(o.alsoResize) === "object" && !o.alsoResize.parentNode) { | |
10963 if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); } | |
10964 else { $.each(o.alsoResize, function (exp) { _store(exp); }); } | |
10965 }else{ | |
10966 _store(o.alsoResize); | |
10967 } | |
10968 }, | |
10969 | |
10970 resize: function (event, ui) { | |
10971 var that = $(this).data("ui-resizable"), | |
10972 o = that.options, | |
10973 os = that.originalSize, | |
10974 op = that.originalPosition, | |
10975 delta = { | |
10976 height: (that.size.height - os.height) || 0, width: (that.size.width - os.width) || 0, | |
10977 top: (that.position.top - op.top) || 0, left: (that.position.left - op.left) || 0 | |
10978 }, | |
10979 | |
10980 _alsoResize = function (exp, c) { | |
10981 $(exp).each(function() { | |
10982 var el = $(this), start = $(this).data("ui-resizable-alsoresize"), style = {}, | |
10983 css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ["width", "height"] : ["width", "height", "top", "left"]; | |
10984 | |
10985 $.each(css, function (i, prop) { | |
10986 var sum = (start[prop]||0) + (delta[prop]||0); | |
10987 if (sum && sum >= 0) { | |
10988 style[prop] = sum || null; | |
10989 } | |
10990 }); | |
10991 | |
10992 el.css(style); | |
10993 }); | |
10994 }; | |
10995 | |
10996 if (typeof(o.alsoResize) === "object" && !o.alsoResize.nodeType) { | |
10997 $.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); }); | |
10998 }else{ | |
10999 _alsoResize(o.alsoResize); | |
11000 } | |
11001 }, | |
11002 | |
11003 stop: function () { | |
11004 $(this).removeData("resizable-alsoresize"); | |
11005 } | |
11006 }); | |
11007 | |
11008 $.ui.plugin.add("resizable", "ghost", { | |
11009 | |
11010 start: function() { | |
11011 | |
11012 var that = $(this).data("ui-resizable"), o = that.options, cs = that.size; | |
11013 | |
11014 that.ghost = that.originalElement.clone(); | |
11015 that.ghost | |
11016 .css({ opacity: 0.25, display: "block", position: "relative", height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 }) | |
11017 .addClass("ui-resizable-ghost") | |
11018 .addClass(typeof o.ghost === "string" ? o.ghost : ""); | |
11019 | |
11020 that.ghost.appendTo(that.helper); | |
11021 | |
11022 }, | |
11023 | |
11024 resize: function(){ | |
11025 var that = $(this).data("ui-resizable"); | |
11026 if (that.ghost) { | |
11027 that.ghost.css({ position: "relative", height: that.size.height, width: that.size.width }); | |
11028 } | |
11029 }, | |
11030 | |
11031 stop: function() { | |
11032 var that = $(this).data("ui-resizable"); | |
11033 if (that.ghost && that.helper) { | |
11034 that.helper.get(0).removeChild(that.ghost.get(0)); | |
11035 } | |
11036 } | |
11037 | |
11038 }); | |
11039 | |
11040 $.ui.plugin.add("resizable", "grid", { | |
11041 | |
11042 resize: function() { | |
11043 var that = $(this).data("ui-resizable"), | |
11044 o = that.options, | |
11045 cs = that.size, | |
11046 os = that.originalSize, | |
11047 op = that.originalPosition, | |
11048 a = that.axis, | |
11049 grid = typeof o.grid === "number" ? [o.grid, o.grid] : o.grid, | |
11050 gridX = (grid[0]||1), | |
11051 gridY = (grid[1]||1), | |
11052 ox = Math.round((cs.width - os.width) / gridX) * gridX, | |
11053 oy = Math.round((cs.height - os.height) / gridY) * gridY, | |
11054 newWidth = os.width + ox, | |
11055 newHeight = os.height + oy, | |
11056 isMaxWidth = o.maxWidth && (o.maxWidth < newWidth), | |
11057 isMaxHeight = o.maxHeight && (o.maxHeight < newHeight), | |
11058 isMinWidth = o.minWidth && (o.minWidth > newWidth), | |
11059 isMinHeight = o.minHeight && (o.minHeight > newHeight); | |
11060 | |
11061 o.grid = grid; | |
11062 | |
11063 if (isMinWidth) { | |
11064 newWidth = newWidth + gridX; | |
11065 } | |
11066 if (isMinHeight) { | |
11067 newHeight = newHeight + gridY; | |
11068 } | |
11069 if (isMaxWidth) { | |
11070 newWidth = newWidth - gridX; | |
11071 } | |
11072 if (isMaxHeight) { | |
11073 newHeight = newHeight - gridY; | |
11074 } | |
11075 | |
11076 if (/^(se|s|e)$/.test(a)) { | |
11077 that.size.width = newWidth; | |
11078 that.size.height = newHeight; | |
11079 } else if (/^(ne)$/.test(a)) { | |
11080 that.size.width = newWidth; | |
11081 that.size.height = newHeight; | |
11082 that.position.top = op.top - oy; | |
11083 } else if (/^(sw)$/.test(a)) { | |
11084 that.size.width = newWidth; | |
11085 that.size.height = newHeight; | |
11086 that.position.left = op.left - ox; | |
11087 } else { | |
11088 if ( newHeight - gridY > 0 ) { | |
11089 that.size.height = newHeight; | |
11090 that.position.top = op.top - oy; | |
11091 } else { | |
11092 that.size.height = gridY; | |
11093 that.position.top = op.top + os.height - gridY; | |
11094 } | |
11095 if ( newWidth - gridX > 0 ) { | |
11096 that.size.width = newWidth; | |
11097 that.position.left = op.left - ox; | |
11098 } else { | |
11099 that.size.width = gridX; | |
11100 that.position.left = op.left + os.width - gridX; | |
11101 } | |
11102 } | |
11103 } | |
11104 | |
11105 }); | |
11106 | |
11107 })(jQuery); | |
11108 (function( $, undefined ) { | |
11109 | |
11110 $.widget("ui.selectable", $.ui.mouse, { | |
11111 version: "1.10.4", | |
11112 options: { | |
11113 appendTo: "body", | |
11114 autoRefresh: true, | |
11115 distance: 0, | |
11116 filter: "*", | |
11117 tolerance: "touch", | |
11118 | |
11119 // callbacks | |
11120 selected: null, | |
11121 selecting: null, | |
11122 start: null, | |
11123 stop: null, | |
11124 unselected: null, | |
11125 unselecting: null | |
11126 }, | |
11127 _create: function() { | |
11128 var selectees, | |
11129 that = this; | |
11130 | |
11131 this.element.addClass("ui-selectable"); | |
11132 | |
11133 this.dragged = false; | |
11134 | |
11135 // cache selectee children based on filter | |
11136 this.refresh = function() { | |
11137 selectees = $(that.options.filter, that.element[0]); | |
11138 selectees.addClass("ui-selectee"); | |
11139 selectees.each(function() { | |
11140 var $this = $(this), | |
11141 pos = $this.offset(); | |
11142 $.data(this, "selectable-item", { | |
11143 element: this, | |
11144 $element: $this, | |
11145 left: pos.left, | |
11146 top: pos.top, | |
11147 right: pos.left + $this.outerWidth(), | |
11148 bottom: pos.top + $this.outerHeight(), | |
11149 startselected: false, | |
11150 selected: $this.hasClass("ui-selected"), | |
11151 selecting: $this.hasClass("ui-selecting"), | |
11152 unselecting: $this.hasClass("ui-unselecting") | |
11153 }); | |
11154 }); | |
11155 }; | |
11156 this.refresh(); | |
11157 | |
11158 this.selectees = selectees.addClass("ui-selectee"); | |
11159 | |
11160 this._mouseInit(); | |
11161 | |
11162 this.helper = $("<div class='ui-selectable-helper'></div>"); | |
11163 }, | |
11164 | |
11165 _destroy: function() { | |
11166 this.selectees | |
11167 .removeClass("ui-selectee") | |
11168 .removeData("selectable-item"); | |
11169 this.element | |
11170 .removeClass("ui-selectable ui-selectable-disabled"); | |
11171 this._mouseDestroy(); | |
11172 }, | |
11173 | |
11174 _mouseStart: function(event) { | |
11175 var that = this, | |
11176 options = this.options; | |
11177 | |
11178 this.opos = [event.pageX, event.pageY]; | |
11179 | |
11180 if (this.options.disabled) { | |
11181 return; | |
11182 } | |
11183 | |
11184 this.selectees = $(options.filter, this.element[0]); | |
11185 | |
11186 this._trigger("start", event); | |
11187 | |
11188 $(options.appendTo).append(this.helper); | |
11189 // position helper (lasso) | |
11190 this.helper.css({ | |
11191 "left": event.pageX, | |
11192 "top": event.pageY, | |
11193 "width": 0, | |
11194 "height": 0 | |
11195 }); | |
11196 | |
11197 if (options.autoRefresh) { | |
11198 this.refresh(); | |
11199 } | |
11200 | |
11201 this.selectees.filter(".ui-selected").each(function() { | |
11202 var selectee = $.data(this, "selectable-item"); | |
11203 selectee.startselected = true; | |
11204 if (!event.metaKey && !event.ctrlKey) { | |
11205 selectee.$element.removeClass("ui-selected"); | |
11206 selectee.selected = false; | |
11207 selectee.$element.addClass("ui-unselecting"); | |
11208 selectee.unselecting = true; | |
11209 // selectable UNSELECTING callback | |
11210 that._trigger("unselecting", event, { | |
11211 unselecting: selectee.element | |
11212 }); | |
11213 } | |
11214 }); | |
11215 | |
11216 $(event.target).parents().addBack().each(function() { | |
11217 var doSelect, | |
11218 selectee = $.data(this, "selectable-item"); | |
11219 if (selectee) { | |
11220 doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass("ui-selected"); | |
11221 selectee.$element | |
11222 .removeClass(doSelect ? "ui-unselecting" : "ui-selected") | |
11223 .addClass(doSelect ? "ui-selecting" : "ui-unselecting"); | |
11224 selectee.unselecting = !doSelect; | |
11225 selectee.selecting = doSelect; | |
11226 selectee.selected = doSelect; | |
11227 // selectable (UN)SELECTING callback | |
11228 if (doSelect) { | |
11229 that._trigger("selecting", event, { | |
11230 selecting: selectee.element | |
11231 }); | |
11232 } else { | |
11233 that._trigger("unselecting", event, { | |
11234 unselecting: selectee.element | |
11235 }); | |
11236 } | |
11237 return false; | |
11238 } | |
11239 }); | |
11240 | |
11241 }, | |
11242 | |
11243 _mouseDrag: function(event) { | |
11244 | |
11245 this.dragged = true; | |
11246 | |
11247 if (this.options.disabled) { | |
11248 return; | |
11249 } | |
11250 | |
11251 var tmp, | |
11252 that = this, | |
11253 options = this.options, | |
11254 x1 = this.opos[0], | |
11255 y1 = this.opos[1], | |
11256 x2 = event.pageX, | |
11257 y2 = event.pageY; | |
11258 | |
11259 if (x1 > x2) { tmp = x2; x2 = x1; x1 = tmp; } | |
11260 if (y1 > y2) { tmp = y2; y2 = y1; y1 = tmp; } | |
11261 this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1}); | |
11262 | |
11263 this.selectees.each(function() { | |
11264 var selectee = $.data(this, "selectable-item"), | |
11265 hit = false; | |
11266 | |
11267 //prevent helper from being selected if appendTo: selectable | |
11268 if (!selectee || selectee.element === that.element[0]) { | |
11269 return; | |
11270 } | |
11271 | |
11272 if (options.tolerance === "touch") { | |
11273 hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) ); | |
11274 } else if (options.tolerance === "fit") { | |
11275 hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2); | |
11276 } | |
11277 | |
11278 if (hit) { | |
11279 // SELECT | |
11280 if (selectee.selected) { | |
11281 selectee.$element.removeClass("ui-selected"); | |
11282 selectee.selected = false; | |
11283 } | |
11284 if (selectee.unselecting) { | |
11285 selectee.$element.removeClass("ui-unselecting"); | |
11286 selectee.unselecting = false; | |
11287 } | |
11288 if (!selectee.selecting) { | |
11289 selectee.$element.addClass("ui-selecting"); | |
11290 selectee.selecting = true; | |
11291 // selectable SELECTING callback | |
11292 that._trigger("selecting", event, { | |
11293 selecting: selectee.element | |
11294 }); | |
11295 } | |
11296 } else { | |
11297 // UNSELECT | |
11298 if (selectee.selecting) { | |
11299 if ((event.metaKey || event.ctrlKey) && selectee.startselected) { | |
11300 selectee.$element.removeClass("ui-selecting"); | |
11301 selectee.selecting = false; | |
11302 selectee.$element.addClass("ui-selected"); | |
11303 selectee.selected = true; | |
11304 } else { | |
11305 selectee.$element.removeClass("ui-selecting"); | |
11306 selectee.selecting = false; | |
11307 if (selectee.startselected) { | |
11308 selectee.$element.addClass("ui-unselecting"); | |
11309 selectee.unselecting = true; | |
11310 } | |
11311 // selectable UNSELECTING callback | |
11312 that._trigger("unselecting", event, { | |
11313 unselecting: selectee.element | |
11314 }); | |
11315 } | |
11316 } | |
11317 if (selectee.selected) { | |
11318 if (!event.metaKey && !event.ctrlKey && !selectee.startselected) { | |
11319 selectee.$element.removeClass("ui-selected"); | |
11320 selectee.selected = false; | |
11321 | |
11322 selectee.$element.addClass("ui-unselecting"); | |
11323 selectee.unselecting = true; | |
11324 // selectable UNSELECTING callback | |
11325 that._trigger("unselecting", event, { | |
11326 unselecting: selectee.element | |
11327 }); | |
11328 } | |
11329 } | |
11330 } | |
11331 }); | |
11332 | |
11333 return false; | |
11334 }, | |
11335 | |
11336 _mouseStop: function(event) { | |
11337 var that = this; | |
11338 | |
11339 this.dragged = false; | |
11340 | |
11341 $(".ui-unselecting", this.element[0]).each(function() { | |
11342 var selectee = $.data(this, "selectable-item"); | |
11343 selectee.$element.removeClass("ui-unselecting"); | |
11344 selectee.unselecting = false; | |
11345 selectee.startselected = false; | |
11346 that._trigger("unselected", event, { | |
11347 unselected: selectee.element | |
11348 }); | |
11349 }); | |
11350 $(".ui-selecting", this.element[0]).each(function() { | |
11351 var selectee = $.data(this, "selectable-item"); | |
11352 selectee.$element.removeClass("ui-selecting").addClass("ui-selected"); | |
11353 selectee.selecting = false; | |
11354 selectee.selected = true; | |
11355 selectee.startselected = true; | |
11356 that._trigger("selected", event, { | |
11357 selected: selectee.element | |
11358 }); | |
11359 }); | |
11360 this._trigger("stop", event); | |
11361 | |
11362 this.helper.remove(); | |
11363 | |
11364 return false; | |
11365 } | |
11366 | |
11367 }); | |
11368 | |
11369 })(jQuery); | |
11370 (function( $, undefined ) { | |
11371 | |
11372 // number of pages in a slider | |
11373 // (how many times can you page up/down to go through the whole range) | |
11374 var numPages = 5; | |
11375 | |
11376 $.widget( "ui.slider", $.ui.mouse, { | |
11377 version: "1.10.4", | |
11378 widgetEventPrefix: "slide", | |
11379 | |
11380 options: { | |
11381 animate: false, | |
11382 distance: 0, | |
11383 max: 100, | |
11384 min: 0, | |
11385 orientation: "horizontal", | |
11386 range: false, | |
11387 step: 1, | |
11388 value: 0, | |
11389 values: null, | |
11390 | |
11391 // callbacks | |
11392 change: null, | |
11393 slide: null, | |
11394 start: null, | |
11395 stop: null | |
11396 }, | |
11397 | |
11398 _create: function() { | |
11399 this._keySliding = false; | |
11400 this._mouseSliding = false; | |
11401 this._animateOff = true; | |
11402 this._handleIndex = null; | |
11403 this._detectOrientation(); | |
11404 this._mouseInit(); | |
11405 | |
11406 this.element | |
11407 .addClass( "ui-slider" + | |
11408 " ui-slider-" + this.orientation + | |
11409 " ui-widget" + | |
11410 " ui-widget-content" + | |
11411 " ui-corner-all"); | |
11412 | |
11413 this._refresh(); | |
11414 this._setOption( "disabled", this.options.disabled ); | |
11415 | |
11416 this._animateOff = false; | |
11417 }, | |
11418 | |
11419 _refresh: function() { | |
11420 this._createRange(); | |
11421 this._createHandles(); | |
11422 this._setupEvents(); | |
11423 this._refreshValue(); | |
11424 }, | |
11425 | |
11426 _createHandles: function() { | |
11427 var i, handleCount, | |
11428 options = this.options, | |
11429 existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ), | |
11430 handle = "<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>", | |
11431 handles = []; | |
11432 | |
11433 handleCount = ( options.values && options.values.length ) || 1; | |
11434 | |
11435 if ( existingHandles.length > handleCount ) { | |
11436 existingHandles.slice( handleCount ).remove(); | |
11437 existingHandles = existingHandles.slice( 0, handleCount ); | |
11438 } | |
11439 | |
11440 for ( i = existingHandles.length; i < handleCount; i++ ) { | |
11441 handles.push( handle ); | |
11442 } | |
11443 | |
11444 this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) ); | |
11445 | |
11446 this.handle = this.handles.eq( 0 ); | |
11447 | |
11448 this.handles.each(function( i ) { | |
11449 $( this ).data( "ui-slider-handle-index", i ); | |
11450 }); | |
11451 }, | |
11452 | |
11453 _createRange: function() { | |
11454 var options = this.options, | |
11455 classes = ""; | |
11456 | |
11457 if ( options.range ) { | |
11458 if ( options.range === true ) { | |
11459 if ( !options.values ) { | |
11460 options.values = [ this._valueMin(), this._valueMin() ]; | |
11461 } else if ( options.values.length && options.values.length !== 2 ) { | |
11462 options.values = [ options.values[0], options.values[0] ]; | |
11463 } else if ( $.isArray( options.values ) ) { | |
11464 options.values = options.values.slice(0); | |
11465 } | |
11466 } | |
11467 | |
11468 if ( !this.range || !this.range.length ) { | |
11469 this.range = $( "<div></div>" ) | |
11470 .appendTo( this.element ); | |
11471 | |
11472 classes = "ui-slider-range" + | |
11473 // note: this isn't the most fittingly semantic framework class for this element, | |
11474 // but worked best visually with a variety of themes | |
11475 " ui-widget-header ui-corner-all"; | |
11476 } else { | |
11477 this.range.removeClass( "ui-slider-range-min ui-slider-range-max" ) | |
11478 // Handle range switching from true to min/max | |
11479 .css({ | |
11480 "left": "", | |
11481 "bottom": "" | |
11482 }); | |
11483 } | |
11484 | |
11485 this.range.addClass( classes + | |
11486 ( ( options.range === "min" || options.range === "max" ) ? " ui-slider-range-" + options.range : "" ) ); | |
11487 } else { | |
11488 if ( this.range ) { | |
11489 this.range.remove(); | |
11490 } | |
11491 this.range = null; | |
11492 } | |
11493 }, | |
11494 | |
11495 _setupEvents: function() { | |
11496 var elements = this.handles.add( this.range ).filter( "a" ); | |
11497 this._off( elements ); | |
11498 this._on( elements, this._handleEvents ); | |
11499 this._hoverable( elements ); | |
11500 this._focusable( elements ); | |
11501 }, | |
11502 | |
11503 _destroy: function() { | |
11504 this.handles.remove(); | |
11505 if ( this.range ) { | |
11506 this.range.remove(); | |
11507 } | |
11508 | |
11509 this.element | |
11510 .removeClass( "ui-slider" + | |
11511 " ui-slider-horizontal" + | |
11512 " ui-slider-vertical" + | |
11513 " ui-widget" + | |
11514 " ui-widget-content" + | |
11515 " ui-corner-all" ); | |
11516 | |
11517 this._mouseDestroy(); | |
11518 }, | |
11519 | |
11520 _mouseCapture: function( event ) { | |
11521 var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle, | |
11522 that = this, | |
11523 o = this.options; | |
11524 | |
11525 if ( o.disabled ) { | |
11526 return false; | |
11527 } | |
11528 | |
11529 this.elementSize = { | |
11530 width: this.element.outerWidth(), | |
11531 height: this.element.outerHeight() | |
11532 }; | |
11533 this.elementOffset = this.element.offset(); | |
11534 | |
11535 position = { x: event.pageX, y: event.pageY }; | |
11536 normValue = this._normValueFromMouse( position ); | |
11537 distance = this._valueMax() - this._valueMin() + 1; | |
11538 this.handles.each(function( i ) { | |
11539 var thisDistance = Math.abs( normValue - that.values(i) ); | |
11540 if (( distance > thisDistance ) || | |
11541 ( distance === thisDistance && | |
11542 (i === that._lastChangedValue || that.values(i) === o.min ))) { | |
11543 distance = thisDistance; | |
11544 closestHandle = $( this ); | |
11545 index = i; | |
11546 } | |
11547 }); | |
11548 | |
11549 allowed = this._start( event, index ); | |
11550 if ( allowed === false ) { | |
11551 return false; | |
11552 } | |
11553 this._mouseSliding = true; | |
11554 | |
11555 this._handleIndex = index; | |
11556 | |
11557 closestHandle | |
11558 .addClass( "ui-state-active" ) | |
11559 .focus(); | |
11560 | |
11561 offset = closestHandle.offset(); | |
11562 mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" ); | |
11563 this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : { | |
11564 left: event.pageX - offset.left - ( closestHandle.width() / 2 ), | |
11565 top: event.pageY - offset.top - | |
11566 ( closestHandle.height() / 2 ) - | |
11567 ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) - | |
11568 ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) + | |
11569 ( parseInt( closestHandle.css("marginTop"), 10 ) || 0) | |
11570 }; | |
11571 | |
11572 if ( !this.handles.hasClass( "ui-state-hover" ) ) { | |
11573 this._slide( event, index, normValue ); | |
11574 } | |
11575 this._animateOff = true; | |
11576 return true; | |
11577 }, | |
11578 | |
11579 _mouseStart: function() { | |
11580 return true; | |
11581 }, | |
11582 | |
11583 _mouseDrag: function( event ) { | |
11584 var position = { x: event.pageX, y: event.pageY }, | |
11585 normValue = this._normValueFromMouse( position ); | |
11586 | |
11587 this._slide( event, this._handleIndex, normValue ); | |
11588 | |
11589 return false; | |
11590 }, | |
11591 | |
11592 _mouseStop: function( event ) { | |
11593 this.handles.removeClass( "ui-state-active" ); | |
11594 this._mouseSliding = false; | |
11595 | |
11596 this._stop( event, this._handleIndex ); | |
11597 this._change( event, this._handleIndex ); | |
11598 | |
11599 this._handleIndex = null; | |
11600 this._clickOffset = null; | |
11601 this._animateOff = false; | |
11602 | |
11603 return false; | |
11604 }, | |
11605 | |
11606 _detectOrientation: function() { | |
11607 this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal"; | |
11608 }, | |
11609 | |
11610 _normValueFromMouse: function( position ) { | |
11611 var pixelTotal, | |
11612 pixelMouse, | |
11613 percentMouse, | |
11614 valueTotal, | |
11615 valueMouse; | |
11616 | |
11617 if ( this.orientation === "horizontal" ) { | |
11618 pixelTotal = this.elementSize.width; | |
11619 pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 ); | |
11620 } else { | |
11621 pixelTotal = this.elementSize.height; | |
11622 pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 ); | |
11623 } | |
11624 | |
11625 percentMouse = ( pixelMouse / pixelTotal ); | |
11626 if ( percentMouse > 1 ) { | |
11627 percentMouse = 1; | |
11628 } | |
11629 if ( percentMouse < 0 ) { | |
11630 percentMouse = 0; | |
11631 } | |
11632 if ( this.orientation === "vertical" ) { | |
11633 percentMouse = 1 - percentMouse; | |
11634 } | |
11635 | |
11636 valueTotal = this._valueMax() - this._valueMin(); | |
11637 valueMouse = this._valueMin() + percentMouse * valueTotal; | |
11638 | |
11639 return this._trimAlignValue( valueMouse ); | |
11640 }, | |
11641 | |
11642 _start: function( event, index ) { | |
11643 var uiHash = { | |
11644 handle: this.handles[ index ], | |
11645 value: this.value() | |
11646 }; | |
11647 if ( this.options.values && this.options.values.length ) { | |
11648 uiHash.value = this.values( index ); | |
11649 uiHash.values = this.values(); | |
11650 } | |
11651 return this._trigger( "start", event, uiHash ); | |
11652 }, | |
11653 | |
11654 _slide: function( event, index, newVal ) { | |
11655 var otherVal, | |
11656 newValues, | |
11657 allowed; | |
11658 | |
11659 if ( this.options.values && this.options.values.length ) { | |
11660 otherVal = this.values( index ? 0 : 1 ); | |
11661 | |
11662 if ( ( this.options.values.length === 2 && this.options.range === true ) && | |
11663 ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) ) | |
11664 ) { | |
11665 newVal = otherVal; | |
11666 } | |
11667 | |
11668 if ( newVal !== this.values( index ) ) { | |
11669 newValues = this.values(); | |
11670 newValues[ index ] = newVal; | |
11671 // A slide can be canceled by returning false from the slide callback | |
11672 allowed = this._trigger( "slide", event, { | |
11673 handle: this.handles[ index ], | |
11674 value: newVal, | |
11675 values: newValues | |
11676 } ); | |
11677 otherVal = this.values( index ? 0 : 1 ); | |
11678 if ( allowed !== false ) { | |
11679 this.values( index, newVal ); | |
11680 } | |
11681 } | |
11682 } else { | |
11683 if ( newVal !== this.value() ) { | |
11684 // A slide can be canceled by returning false from the slide callback | |
11685 allowed = this._trigger( "slide", event, { | |
11686 handle: this.handles[ index ], | |
11687 value: newVal | |
11688 } ); | |
11689 if ( allowed !== false ) { | |
11690 this.value( newVal ); | |
11691 } | |
11692 } | |
11693 } | |
11694 }, | |
11695 | |
11696 _stop: function( event, index ) { | |
11697 var uiHash = { | |
11698 handle: this.handles[ index ], | |
11699 value: this.value() | |
11700 }; | |
11701 if ( this.options.values && this.options.values.length ) { | |
11702 uiHash.value = this.values( index ); | |
11703 uiHash.values = this.values(); | |
11704 } | |
11705 | |
11706 this._trigger( "stop", event, uiHash ); | |
11707 }, | |
11708 | |
11709 _change: function( event, index ) { | |
11710 if ( !this._keySliding && !this._mouseSliding ) { | |
11711 var uiHash = { | |
11712 handle: this.handles[ index ], | |
11713 value: this.value() | |
11714 }; | |
11715 if ( this.options.values && this.options.values.length ) { | |
11716 uiHash.value = this.values( index ); | |
11717 uiHash.values = this.values(); | |
11718 } | |
11719 | |
11720 //store the last changed value index for reference when handles overlap | |
11721 this._lastChangedValue = index; | |
11722 | |
11723 this._trigger( "change", event, uiHash ); | |
11724 } | |
11725 }, | |
11726 | |
11727 value: function( newValue ) { | |
11728 if ( arguments.length ) { | |
11729 this.options.value = this._trimAlignValue( newValue ); | |
11730 this._refreshValue(); | |
11731 this._change( null, 0 ); | |
11732 return; | |
11733 } | |
11734 | |
11735 return this._value(); | |
11736 }, | |
11737 | |
11738 values: function( index, newValue ) { | |
11739 var vals, | |
11740 newValues, | |
11741 i; | |
11742 | |
11743 if ( arguments.length > 1 ) { | |
11744 this.options.values[ index ] = this._trimAlignValue( newValue ); | |
11745 this._refreshValue(); | |
11746 this._change( null, index ); | |
11747 return; | |
11748 } | |
11749 | |
11750 if ( arguments.length ) { | |
11751 if ( $.isArray( arguments[ 0 ] ) ) { | |
11752 vals = this.options.values; | |
11753 newValues = arguments[ 0 ]; | |
11754 for ( i = 0; i < vals.length; i += 1 ) { | |
11755 vals[ i ] = this._trimAlignValue( newValues[ i ] ); | |
11756 this._change( null, i ); | |
11757 } | |
11758 this._refreshValue(); | |
11759 } else { | |
11760 if ( this.options.values && this.options.values.length ) { | |
11761 return this._values( index ); | |
11762 } else { | |
11763 return this.value(); | |
11764 } | |
11765 } | |
11766 } else { | |
11767 return this._values(); | |
11768 } | |
11769 }, | |
11770 | |
11771 _setOption: function( key, value ) { | |
11772 var i, | |
11773 valsLength = 0; | |
11774 | |
11775 if ( key === "range" && this.options.range === true ) { | |
11776 if ( value === "min" ) { | |
11777 this.options.value = this._values( 0 ); | |
11778 this.options.values = null; | |
11779 } else if ( value === "max" ) { | |
11780 this.options.value = this._values( this.options.values.length-1 ); | |
11781 this.options.values = null; | |
11782 } | |
11783 } | |
11784 | |
11785 if ( $.isArray( this.options.values ) ) { | |
11786 valsLength = this.options.values.length; | |
11787 } | |
11788 | |
11789 $.Widget.prototype._setOption.apply( this, arguments ); | |
11790 | |
11791 switch ( key ) { | |
11792 case "orientation": | |
11793 this._detectOrientation(); | |
11794 this.element | |
11795 .removeClass( "ui-slider-horizontal ui-slider-vertical" ) | |
11796 .addClass( "ui-slider-" + this.orientation ); | |
11797 this._refreshValue(); | |
11798 break; | |
11799 case "value": | |
11800 this._animateOff = true; | |
11801 this._refreshValue(); | |
11802 this._change( null, 0 ); | |
11803 this._animateOff = false; | |
11804 break; | |
11805 case "values": | |
11806 this._animateOff = true; | |
11807 this._refreshValue(); | |
11808 for ( i = 0; i < valsLength; i += 1 ) { | |
11809 this._change( null, i ); | |
11810 } | |
11811 this._animateOff = false; | |
11812 break; | |
11813 case "min": | |
11814 case "max": | |
11815 this._animateOff = true; | |
11816 this._refreshValue(); | |
11817 this._animateOff = false; | |
11818 break; | |
11819 case "range": | |
11820 this._animateOff = true; | |
11821 this._refresh(); | |
11822 this._animateOff = false; | |
11823 break; | |
11824 } | |
11825 }, | |
11826 | |
11827 //internal value getter | |
11828 // _value() returns value trimmed by min and max, aligned by step | |
11829 _value: function() { | |
11830 var val = this.options.value; | |
11831 val = this._trimAlignValue( val ); | |
11832 | |
11833 return val; | |
11834 }, | |
11835 | |
11836 //internal values getter | |
11837 // _values() returns array of values trimmed by min and max, aligned by step | |
11838 // _values( index ) returns single value trimmed by min and max, aligned by step | |
11839 _values: function( index ) { | |
11840 var val, | |
11841 vals, | |
11842 i; | |
11843 | |
11844 if ( arguments.length ) { | |
11845 val = this.options.values[ index ]; | |
11846 val = this._trimAlignValue( val ); | |
11847 | |
11848 return val; | |
11849 } else if ( this.options.values && this.options.values.length ) { | |
11850 // .slice() creates a copy of the array | |
11851 // this copy gets trimmed by min and max and then returned | |
11852 vals = this.options.values.slice(); | |
11853 for ( i = 0; i < vals.length; i+= 1) { | |
11854 vals[ i ] = this._trimAlignValue( vals[ i ] ); | |
11855 } | |
11856 | |
11857 return vals; | |
11858 } else { | |
11859 return []; | |
11860 } | |
11861 }, | |
11862 | |
11863 // returns the step-aligned value that val is closest to, between (inclusive) min and max | |
11864 _trimAlignValue: function( val ) { | |
11865 if ( val <= this._valueMin() ) { | |
11866 return this._valueMin(); | |
11867 } | |
11868 if ( val >= this._valueMax() ) { | |
11869 return this._valueMax(); | |
11870 } | |
11871 var step = ( this.options.step > 0 ) ? this.options.step : 1, | |
11872 valModStep = (val - this._valueMin()) % step, | |
11873 alignValue = val - valModStep; | |
11874 | |
11875 if ( Math.abs(valModStep) * 2 >= step ) { | |
11876 alignValue += ( valModStep > 0 ) ? step : ( -step ); | |
11877 } | |
11878 | |
11879 // Since JavaScript has problems with large floats, round | |
11880 // the final value to 5 digits after the decimal point (see #4124) | |
11881 return parseFloat( alignValue.toFixed(5) ); | |
11882 }, | |
11883 | |
11884 _valueMin: function() { | |
11885 return this.options.min; | |
11886 }, | |
11887 | |
11888 _valueMax: function() { | |
11889 return this.options.max; | |
11890 }, | |
11891 | |
11892 _refreshValue: function() { | |
11893 var lastValPercent, valPercent, value, valueMin, valueMax, | |
11894 oRange = this.options.range, | |
11895 o = this.options, | |
11896 that = this, | |
11897 animate = ( !this._animateOff ) ? o.animate : false, | |
11898 _set = {}; | |
11899 | |
11900 if ( this.options.values && this.options.values.length ) { | |
11901 this.handles.each(function( i ) { | |
11902 valPercent = ( that.values(i) - that._valueMin() ) / ( that._valueMax() - that._valueMin() ) * 100; | |
11903 _set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; | |
11904 $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); | |
11905 if ( that.options.range === true ) { | |
11906 if ( that.orientation === "horizontal" ) { | |
11907 if ( i === 0 ) { | |
11908 that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate ); | |
11909 } | |
11910 if ( i === 1 ) { | |
11911 that.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } ); | |
11912 } | |
11913 } else { | |
11914 if ( i === 0 ) { | |
11915 that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate ); | |
11916 } | |
11917 if ( i === 1 ) { | |
11918 that.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } ); | |
11919 } | |
11920 } | |
11921 } | |
11922 lastValPercent = valPercent; | |
11923 }); | |
11924 } else { | |
11925 value = this.value(); | |
11926 valueMin = this._valueMin(); | |
11927 valueMax = this._valueMax(); | |
11928 valPercent = ( valueMax !== valueMin ) ? | |
11929 ( value - valueMin ) / ( valueMax - valueMin ) * 100 : | |
11930 0; | |
11931 _set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; | |
11932 this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); | |
11933 | |
11934 if ( oRange === "min" && this.orientation === "horizontal" ) { | |
11935 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate ); | |
11936 } | |
11937 if ( oRange === "max" && this.orientation === "horizontal" ) { | |
11938 this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } ); | |
11939 } | |
11940 if ( oRange === "min" && this.orientation === "vertical" ) { | |
11941 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate ); | |
11942 } | |
11943 if ( oRange === "max" && this.orientation === "vertical" ) { | |
11944 this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } ); | |
11945 } | |
11946 } | |
11947 }, | |
11948 | |
11949 _handleEvents: { | |
11950 keydown: function( event ) { | |
11951 var allowed, curVal, newVal, step, | |
11952 index = $( event.target ).data( "ui-slider-handle-index" ); | |
11953 | |
11954 switch ( event.keyCode ) { | |
11955 case $.ui.keyCode.HOME: | |
11956 case $.ui.keyCode.END: | |
11957 case $.ui.keyCode.PAGE_UP: | |
11958 case $.ui.keyCode.PAGE_DOWN: | |
11959 case $.ui.keyCode.UP: | |
11960 case $.ui.keyCode.RIGHT: | |
11961 case $.ui.keyCode.DOWN: | |
11962 case $.ui.keyCode.LEFT: | |
11963 event.preventDefault(); | |
11964 if ( !this._keySliding ) { | |
11965 this._keySliding = true; | |
11966 $( event.target ).addClass( "ui-state-active" ); | |
11967 allowed = this._start( event, index ); | |
11968 if ( allowed === false ) { | |
11969 return; | |
11970 } | |
11971 } | |
11972 break; | |
11973 } | |
11974 | |
11975 step = this.options.step; | |
11976 if ( this.options.values && this.options.values.length ) { | |
11977 curVal = newVal = this.values( index ); | |
11978 } else { | |
11979 curVal = newVal = this.value(); | |
11980 } | |
11981 | |
11982 switch ( event.keyCode ) { | |
11983 case $.ui.keyCode.HOME: | |
11984 newVal = this._valueMin(); | |
11985 break; | |
11986 case $.ui.keyCode.END: | |
11987 newVal = this._valueMax(); | |
11988 break; | |
11989 case $.ui.keyCode.PAGE_UP: | |
11990 newVal = this._trimAlignValue( curVal + ( (this._valueMax() - this._valueMin()) / numPages ) ); | |
11991 break; | |
11992 case $.ui.keyCode.PAGE_DOWN: | |
11993 newVal = this._trimAlignValue( curVal - ( (this._valueMax() - this._valueMin()) / numPages ) ); | |
11994 break; | |
11995 case $.ui.keyCode.UP: | |
11996 case $.ui.keyCode.RIGHT: | |
11997 if ( curVal === this._valueMax() ) { | |
11998 return; | |
11999 } | |
12000 newVal = this._trimAlignValue( curVal + step ); | |
12001 break; | |
12002 case $.ui.keyCode.DOWN: | |
12003 case $.ui.keyCode.LEFT: | |
12004 if ( curVal === this._valueMin() ) { | |
12005 return; | |
12006 } | |
12007 newVal = this._trimAlignValue( curVal - step ); | |
12008 break; | |
12009 } | |
12010 | |
12011 this._slide( event, index, newVal ); | |
12012 }, | |
12013 click: function( event ) { | |
12014 event.preventDefault(); | |
12015 }, | |
12016 keyup: function( event ) { | |
12017 var index = $( event.target ).data( "ui-slider-handle-index" ); | |
12018 | |
12019 if ( this._keySliding ) { | |
12020 this._keySliding = false; | |
12021 this._stop( event, index ); | |
12022 this._change( event, index ); | |
12023 $( event.target ).removeClass( "ui-state-active" ); | |
12024 } | |
12025 } | |
12026 } | |
12027 | |
12028 }); | |
12029 | |
12030 }(jQuery)); | |
12031 (function( $, undefined ) { | |
12032 | |
12033 function isOverAxis( x, reference, size ) { | |
12034 return ( x > reference ) && ( x < ( reference + size ) ); | |
12035 } | |
12036 | |
12037 function isFloating(item) { | |
12038 return (/left|right/).test(item.css("float")) || (/inline|table-cell/).test(item.css("display")); | |
12039 } | |
12040 | |
12041 $.widget("ui.sortable", $.ui.mouse, { | |
12042 version: "1.10.4", | |
12043 widgetEventPrefix: "sort", | |
12044 ready: false, | |
12045 options: { | |
12046 appendTo: "parent", | |
12047 axis: false, | |
12048 connectWith: false, | |
12049 containment: false, | |
12050 cursor: "auto", | |
12051 cursorAt: false, | |
12052 dropOnEmpty: true, | |
12053 forcePlaceholderSize: false, | |
12054 forceHelperSize: false, | |
12055 grid: false, | |
12056 handle: false, | |
12057 helper: "original", | |
12058 items: "> *", | |
12059 opacity: false, | |
12060 placeholder: false, | |
12061 revert: false, | |
12062 scroll: true, | |
12063 scrollSensitivity: 20, | |
12064 scrollSpeed: 20, | |
12065 scope: "default", | |
12066 tolerance: "intersect", | |
12067 zIndex: 1000, | |
12068 | |
12069 // callbacks | |
12070 activate: null, | |
12071 beforeStop: null, | |
12072 change: null, | |
12073 deactivate: null, | |
12074 out: null, | |
12075 over: null, | |
12076 receive: null, | |
12077 remove: null, | |
12078 sort: null, | |
12079 start: null, | |
12080 stop: null, | |
12081 update: null | |
12082 }, | |
12083 _create: function() { | |
12084 | |
12085 var o = this.options; | |
12086 this.containerCache = {}; | |
12087 this.element.addClass("ui-sortable"); | |
12088 | |
12089 //Get the items | |
12090 this.refresh(); | |
12091 | |
12092 //Let's determine if the items are being displayed horizontally | |
12093 this.floating = this.items.length ? o.axis === "x" || isFloating(this.items[0].item) : false; | |
12094 | |
12095 //Let's determine the parent's offset | |
12096 this.offset = this.element.offset(); | |
12097 | |
12098 //Initialize mouse events for interaction | |
12099 this._mouseInit(); | |
12100 | |
12101 //We're ready to go | |
12102 this.ready = true; | |
12103 | |
12104 }, | |
12105 | |
12106 _destroy: function() { | |
12107 this.element | |
12108 .removeClass("ui-sortable ui-sortable-disabled"); | |
12109 this._mouseDestroy(); | |
12110 | |
12111 for ( var i = this.items.length - 1; i >= 0; i-- ) { | |
12112 this.items[i].item.removeData(this.widgetName + "-item"); | |
12113 } | |
12114 | |
12115 return this; | |
12116 }, | |
12117 | |
12118 _setOption: function(key, value){ | |
12119 if ( key === "disabled" ) { | |
12120 this.options[ key ] = value; | |
12121 | |
12122 this.widget().toggleClass( "ui-sortable-disabled", !!value ); | |
12123 } else { | |
12124 // Don't call widget base _setOption for disable as it adds ui-state-disabled class | |
12125 $.Widget.prototype._setOption.apply(this, arguments); | |
12126 } | |
12127 }, | |
12128 | |
12129 _mouseCapture: function(event, overrideHandle) { | |
12130 var currentItem = null, | |
12131 validHandle = false, | |
12132 that = this; | |
12133 | |
12134 if (this.reverting) { | |
12135 return false; | |
12136 } | |
12137 | |
12138 if(this.options.disabled || this.options.type === "static") { | |
12139 return false; | |
12140 } | |
12141 | |
12142 //We have to refresh the items data once first | |
12143 this._refreshItems(event); | |
12144 | |
12145 //Find out if the clicked node (or one of its parents) is a actual item in this.items | |
12146 $(event.target).parents().each(function() { | |
12147 if($.data(this, that.widgetName + "-item") === that) { | |
12148 currentItem = $(this); | |
12149 return false; | |
12150 } | |
12151 }); | |
12152 if($.data(event.target, that.widgetName + "-item") === that) { | |
12153 currentItem = $(event.target); | |
12154 } | |
12155 | |
12156 if(!currentItem) { | |
12157 return false; | |
12158 } | |
12159 if(this.options.handle && !overrideHandle) { | |
12160 $(this.options.handle, currentItem).find("*").addBack().each(function() { | |
12161 if(this === event.target) { | |
12162 validHandle = true; | |
12163 } | |
12164 }); | |
12165 if(!validHandle) { | |
12166 return false; | |
12167 } | |
12168 } | |
12169 | |
12170 this.currentItem = currentItem; | |
12171 this._removeCurrentsFromItems(); | |
12172 return true; | |
12173 | |
12174 }, | |
12175 | |
12176 _mouseStart: function(event, overrideHandle, noActivation) { | |
12177 | |
12178 var i, body, | |
12179 o = this.options; | |
12180 | |
12181 this.currentContainer = this; | |
12182 | |
12183 //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture | |
12184 this.refreshPositions(); | |
12185 | |
12186 //Create and append the visible helper | |
12187 this.helper = this._createHelper(event); | |
12188 | |
12189 //Cache the helper size | |
12190 this._cacheHelperProportions(); | |
12191 | |
12192 /* | |
12193 * - Position generation - | |
12194 * This block generates everything position related - it's the core of draggables. | |
12195 */ | |
12196 | |
12197 //Cache the margins of the original element | |
12198 this._cacheMargins(); | |
12199 | |
12200 //Get the next scrolling parent | |
12201 this.scrollParent = this.helper.scrollParent(); | |
12202 | |
12203 //The element's absolute position on the page minus margins | |
12204 this.offset = this.currentItem.offset(); | |
12205 this.offset = { | |
12206 top: this.offset.top - this.margins.top, | |
12207 left: this.offset.left - this.margins.left | |
12208 }; | |
12209 | |
12210 $.extend(this.offset, { | |
12211 click: { //Where the click happened, relative to the element | |
12212 left: event.pageX - this.offset.left, | |
12213 top: event.pageY - this.offset.top | |
12214 }, | |
12215 parent: this._getParentOffset(), | |
12216 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper | |
12217 }); | |
12218 | |
12219 // Only after we got the offset, we can change the helper's position to absolute | |
12220 // TODO: Still need to figure out a way to make relative sorting possible | |
12221 this.helper.css("position", "absolute"); | |
12222 this.cssPosition = this.helper.css("position"); | |
12223 | |
12224 //Generate the original position | |
12225 this.originalPosition = this._generatePosition(event); | |
12226 this.originalPageX = event.pageX; | |
12227 this.originalPageY = event.pageY; | |
12228 | |
12229 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied | |
12230 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)); | |
12231 | |
12232 //Cache the former DOM position | |
12233 this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] }; | |
12234 | |
12235 //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 | |
12236 if(this.helper[0] !== this.currentItem[0]) { | |
12237 this.currentItem.hide(); | |
12238 } | |
12239 | |
12240 //Create the placeholder | |
12241 this._createPlaceholder(); | |
12242 | |
12243 //Set a containment if given in the options | |
12244 if(o.containment) { | |
12245 this._setContainment(); | |
12246 } | |
12247 | |
12248 if( o.cursor && o.cursor !== "auto" ) { // cursor option | |
12249 body = this.document.find( "body" ); | |
12250 | |
12251 // support: IE | |
12252 this.storedCursor = body.css( "cursor" ); | |
12253 body.css( "cursor", o.cursor ); | |
12254 | |
12255 this.storedStylesheet = $( "<style>*{ cursor: "+o.cursor+" !important; }</style>" ).appendTo( body ); | |
12256 } | |
12257 | |
12258 if(o.opacity) { // opacity option | |
12259 if (this.helper.css("opacity")) { | |
12260 this._storedOpacity = this.helper.css("opacity"); | |
12261 } | |
12262 this.helper.css("opacity", o.opacity); | |
12263 } | |
12264 | |
12265 if(o.zIndex) { // zIndex option | |
12266 if (this.helper.css("zIndex")) { | |
12267 this._storedZIndex = this.helper.css("zIndex"); | |
12268 } | |
12269 this.helper.css("zIndex", o.zIndex); | |
12270 } | |
12271 | |
12272 //Prepare scrolling | |
12273 if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") { | |
12274 this.overflowOffset = this.scrollParent.offset(); | |
12275 } | |
12276 | |
12277 //Call callbacks | |
12278 this._trigger("start", event, this._uiHash()); | |
12279 | |
12280 //Recache the helper size | |
12281 if(!this._preserveHelperProportions) { | |
12282 this._cacheHelperProportions(); | |
12283 } | |
12284 | |
12285 | |
12286 //Post "activate" events to possible containers | |
12287 if( !noActivation ) { | |
12288 for ( i = this.containers.length - 1; i >= 0; i-- ) { | |
12289 this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) ); | |
12290 } | |
12291 } | |
12292 | |
12293 //Prepare possible droppables | |
12294 if($.ui.ddmanager) { | |
12295 $.ui.ddmanager.current = this; | |
12296 } | |
12297 | |
12298 if ($.ui.ddmanager && !o.dropBehaviour) { | |
12299 $.ui.ddmanager.prepareOffsets(this, event); | |
12300 } | |
12301 | |
12302 this.dragging = true; | |
12303 | |
12304 this.helper.addClass("ui-sortable-helper"); | |
12305 this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position | |
12306 return true; | |
12307 | |
12308 }, | |
12309 | |
12310 _mouseDrag: function(event) { | |
12311 var i, item, itemElement, intersection, | |
12312 o = this.options, | |
12313 scrolled = false; | |
12314 | |
12315 //Compute the helpers position | |
12316 this.position = this._generatePosition(event); | |
12317 this.positionAbs = this._convertPositionTo("absolute"); | |
12318 | |
12319 if (!this.lastPositionAbs) { | |
12320 this.lastPositionAbs = this.positionAbs; | |
12321 } | |
12322 | |
12323 //Do scrolling | |
12324 if(this.options.scroll) { | |
12325 if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") { | |
12326 | |
12327 if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) { | |
12328 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed; | |
12329 } else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) { | |
12330 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed; | |
12331 } | |
12332 | |
12333 if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) { | |
12334 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed; | |
12335 } else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) { | |
12336 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed; | |
12337 } | |
12338 | |
12339 } else { | |
12340 | |
12341 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) { | |
12342 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); | |
12343 } else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) { | |
12344 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); | |
12345 } | |
12346 | |
12347 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) { | |
12348 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); | |
12349 } else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) { | |
12350 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); | |
12351 } | |
12352 | |
12353 } | |
12354 | |
12355 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) { | |
12356 $.ui.ddmanager.prepareOffsets(this, event); | |
12357 } | |
12358 } | |
12359 | |
12360 //Regenerate the absolute position used for position checks | |
12361 this.positionAbs = this._convertPositionTo("absolute"); | |
12362 | |
12363 //Set the helper position | |
12364 if(!this.options.axis || this.options.axis !== "y") { | |
12365 this.helper[0].style.left = this.position.left+"px"; | |
12366 } | |
12367 if(!this.options.axis || this.options.axis !== "x") { | |
12368 this.helper[0].style.top = this.position.top+"px"; | |
12369 } | |
12370 | |
12371 //Rearrange | |
12372 for (i = this.items.length - 1; i >= 0; i--) { | |
12373 | |
12374 //Cache variables and intersection, continue if no intersection | |
12375 item = this.items[i]; | |
12376 itemElement = item.item[0]; | |
12377 intersection = this._intersectsWithPointer(item); | |
12378 if (!intersection) { | |
12379 continue; | |
12380 } | |
12381 | |
12382 // Only put the placeholder inside the current Container, skip all | |
12383 // items from other containers. This works because when moving | |
12384 // an item from one container to another the | |
12385 // currentContainer is switched before the placeholder is moved. | |
12386 // | |
12387 // Without this, moving items in "sub-sortables" can cause | |
12388 // the placeholder to jitter beetween the outer and inner container. | |
12389 if (item.instance !== this.currentContainer) { | |
12390 continue; | |
12391 } | |
12392 | |
12393 // cannot intersect with itself | |
12394 // no useless actions that have been done before | |
12395 // no action if the item moved is the parent of the item checked | |
12396 if (itemElement !== this.currentItem[0] && | |
12397 this.placeholder[intersection === 1 ? "next" : "prev"]()[0] !== itemElement && | |
12398 !$.contains(this.placeholder[0], itemElement) && | |
12399 (this.options.type === "semi-dynamic" ? !$.contains(this.element[0], itemElement) : true) | |
12400 ) { | |
12401 | |
12402 this.direction = intersection === 1 ? "down" : "up"; | |
12403 | |
12404 if (this.options.tolerance === "pointer" || this._intersectsWithSides(item)) { | |
12405 this._rearrange(event, item); | |
12406 } else { | |
12407 break; | |
12408 } | |
12409 | |
12410 this._trigger("change", event, this._uiHash()); | |
12411 break; | |
12412 } | |
12413 } | |
12414 | |
12415 //Post events to containers | |
12416 this._contactContainers(event); | |
12417 | |
12418 //Interconnect with droppables | |
12419 if($.ui.ddmanager) { | |
12420 $.ui.ddmanager.drag(this, event); | |
12421 } | |
12422 | |
12423 //Call callbacks | |
12424 this._trigger("sort", event, this._uiHash()); | |
12425 | |
12426 this.lastPositionAbs = this.positionAbs; | |
12427 return false; | |
12428 | |
12429 }, | |
12430 | |
12431 _mouseStop: function(event, noPropagation) { | |
12432 | |
12433 if(!event) { | |
12434 return; | |
12435 } | |
12436 | |
12437 //If we are using droppables, inform the manager about the drop | |
12438 if ($.ui.ddmanager && !this.options.dropBehaviour) { | |
12439 $.ui.ddmanager.drop(this, event); | |
12440 } | |
12441 | |
12442 if(this.options.revert) { | |
12443 var that = this, | |
12444 cur = this.placeholder.offset(), | |
12445 axis = this.options.axis, | |
12446 animation = {}; | |
12447 | |
12448 if ( !axis || axis === "x" ) { | |
12449 animation.left = cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollLeft); | |
12450 } | |
12451 if ( !axis || axis === "y" ) { | |
12452 animation.top = cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollTop); | |
12453 } | |
12454 this.reverting = true; | |
12455 $(this.helper).animate( animation, parseInt(this.options.revert, 10) || 500, function() { | |
12456 that._clear(event); | |
12457 }); | |
12458 } else { | |
12459 this._clear(event, noPropagation); | |
12460 } | |
12461 | |
12462 return false; | |
12463 | |
12464 }, | |
12465 | |
12466 cancel: function() { | |
12467 | |
12468 if(this.dragging) { | |
12469 | |
12470 this._mouseUp({ target: null }); | |
12471 | |
12472 if(this.options.helper === "original") { | |
12473 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); | |
12474 } else { | |
12475 this.currentItem.show(); | |
12476 } | |
12477 | |
12478 //Post deactivating events to containers | |
12479 for (var i = this.containers.length - 1; i >= 0; i--){ | |
12480 this.containers[i]._trigger("deactivate", null, this._uiHash(this)); | |
12481 if(this.containers[i].containerCache.over) { | |
12482 this.containers[i]._trigger("out", null, this._uiHash(this)); | |
12483 this.containers[i].containerCache.over = 0; | |
12484 } | |
12485 } | |
12486 | |
12487 } | |
12488 | |
12489 if (this.placeholder) { | |
12490 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! | |
12491 if(this.placeholder[0].parentNode) { | |
12492 this.placeholder[0].parentNode.removeChild(this.placeholder[0]); | |
12493 } | |
12494 if(this.options.helper !== "original" && this.helper && this.helper[0].parentNode) { | |
12495 this.helper.remove(); | |
12496 } | |
12497 | |
12498 $.extend(this, { | |
12499 helper: null, | |
12500 dragging: false, | |
12501 reverting: false, | |
12502 _noFinalSort: null | |
12503 }); | |
12504 | |
12505 if(this.domPosition.prev) { | |
12506 $(this.domPosition.prev).after(this.currentItem); | |
12507 } else { | |
12508 $(this.domPosition.parent).prepend(this.currentItem); | |
12509 } | |
12510 } | |
12511 | |
12512 return this; | |
12513 | |
12514 }, | |
12515 | |
12516 serialize: function(o) { | |
12517 | |
12518 var items = this._getItemsAsjQuery(o && o.connected), | |
12519 str = []; | |
12520 o = o || {}; | |
12521 | |
12522 $(items).each(function() { | |
12523 var res = ($(o.item || this).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[\-=_](.+)/)); | |
12524 if (res) { | |
12525 str.push((o.key || res[1]+"[]")+"="+(o.key && o.expression ? res[1] : res[2])); | |
12526 } | |
12527 }); | |
12528 | |
12529 if(!str.length && o.key) { | |
12530 str.push(o.key + "="); | |
12531 } | |
12532 | |
12533 return str.join("&"); | |
12534 | |
12535 }, | |
12536 | |
12537 toArray: function(o) { | |
12538 | |
12539 var items = this._getItemsAsjQuery(o && o.connected), | |
12540 ret = []; | |
12541 | |
12542 o = o || {}; | |
12543 | |
12544 items.each(function() { ret.push($(o.item || this).attr(o.attribute || "id") || ""); }); | |
12545 return ret; | |
12546 | |
12547 }, | |
12548 | |
12549 /* Be careful with the following core functions */ | |
12550 _intersectsWith: function(item) { | |
12551 | |
12552 var x1 = this.positionAbs.left, | |
12553 x2 = x1 + this.helperProportions.width, | |
12554 y1 = this.positionAbs.top, | |
12555 y2 = y1 + this.helperProportions.height, | |
12556 l = item.left, | |
12557 r = l + item.width, | |
12558 t = item.top, | |
12559 b = t + item.height, | |
12560 dyClick = this.offset.click.top, | |
12561 dxClick = this.offset.click.left, | |
12562 isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t && ( y1 + dyClick ) < b ), | |
12563 isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l && ( x1 + dxClick ) < r ), | |
12564 isOverElement = isOverElementHeight && isOverElementWidth; | |
12565 | |
12566 if ( this.options.tolerance === "pointer" || | |
12567 this.options.forcePointerForContainers || | |
12568 (this.options.tolerance !== "pointer" && this.helperProportions[this.floating ? "width" : "height"] > item[this.floating ? "width" : "height"]) | |
12569 ) { | |
12570 return isOverElement; | |
12571 } else { | |
12572 | |
12573 return (l < x1 + (this.helperProportions.width / 2) && // Right Half | |
12574 x2 - (this.helperProportions.width / 2) < r && // Left Half | |
12575 t < y1 + (this.helperProportions.height / 2) && // Bottom Half | |
12576 y2 - (this.helperProportions.height / 2) < b ); // Top Half | |
12577 | |
12578 } | |
12579 }, | |
12580 | |
12581 _intersectsWithPointer: function(item) { | |
12582 | |
12583 var isOverElementHeight = (this.options.axis === "x") || isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height), | |
12584 isOverElementWidth = (this.options.axis === "y") || isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width), | |
12585 isOverElement = isOverElementHeight && isOverElementWidth, | |
12586 verticalDirection = this._getDragVerticalDirection(), | |
12587 horizontalDirection = this._getDragHorizontalDirection(); | |
12588 | |
12589 if (!isOverElement) { | |
12590 return false; | |
12591 } | |
12592 | |
12593 return this.floating ? | |
12594 ( ((horizontalDirection && horizontalDirection === "right") || verticalDirection === "down") ? 2 : 1 ) | |
12595 : ( verticalDirection && (verticalDirection === "down" ? 2 : 1) ); | |
12596 | |
12597 }, | |
12598 | |
12599 _intersectsWithSides: function(item) { | |
12600 | |
12601 var isOverBottomHalf = isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height), | |
12602 isOverRightHalf = isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width), | |
12603 verticalDirection = this._getDragVerticalDirection(), | |
12604 horizontalDirection = this._getDragHorizontalDirection(); | |
12605 | |
12606 if (this.floating && horizontalDirection) { | |
12607 return ((horizontalDirection === "right" && isOverRightHalf) || (horizontalDirection === "left" && !isOverRightHalf)); | |
12608 } else { | |
12609 return verticalDirection && ((verticalDirection === "down" && isOverBottomHalf) || (verticalDirection === "up" && !isOverBottomHalf)); | |
12610 } | |
12611 | |
12612 }, | |
12613 | |
12614 _getDragVerticalDirection: function() { | |
12615 var delta = this.positionAbs.top - this.lastPositionAbs.top; | |
12616 return delta !== 0 && (delta > 0 ? "down" : "up"); | |
12617 }, | |
12618 | |
12619 _getDragHorizontalDirection: function() { | |
12620 var delta = this.positionAbs.left - this.lastPositionAbs.left; | |
12621 return delta !== 0 && (delta > 0 ? "right" : "left"); | |
12622 }, | |
12623 | |
12624 refresh: function(event) { | |
12625 this._refreshItems(event); | |
12626 this.refreshPositions(); | |
12627 return this; | |
12628 }, | |
12629 | |
12630 _connectWith: function() { | |
12631 var options = this.options; | |
12632 return options.connectWith.constructor === String ? [options.connectWith] : options.connectWith; | |
12633 }, | |
12634 | |
12635 _getItemsAsjQuery: function(connected) { | |
12636 | |
12637 var i, j, cur, inst, | |
12638 items = [], | |
12639 queries = [], | |
12640 connectWith = this._connectWith(); | |
12641 | |
12642 if(connectWith && connected) { | |
12643 for (i = connectWith.length - 1; i >= 0; i--){ | |
12644 cur = $(connectWith[i]); | |
12645 for ( j = cur.length - 1; j >= 0; j--){ | |
12646 inst = $.data(cur[j], this.widgetFullName); | |
12647 if(inst && inst !== this && !inst.options.disabled) { | |
12648 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]); | |
12649 } | |
12650 } | |
12651 } | |
12652 } | |
12653 | |
12654 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]); | |
12655 | |
12656 function addItems() { | |
12657 items.push( this ); | |
12658 } | |
12659 for (i = queries.length - 1; i >= 0; i--){ | |
12660 queries[i][0].each( addItems ); | |
12661 } | |
12662 | |
12663 return $(items); | |
12664 | |
12665 }, | |
12666 | |
12667 _removeCurrentsFromItems: function() { | |
12668 | |
12669 var list = this.currentItem.find(":data(" + this.widgetName + "-item)"); | |
12670 | |
12671 this.items = $.grep(this.items, function (item) { | |
12672 for (var j=0; j < list.length; j++) { | |
12673 if(list[j] === item.item[0]) { | |
12674 return false; | |
12675 } | |
12676 } | |
12677 return true; | |
12678 }); | |
12679 | |
12680 }, | |
12681 | |
12682 _refreshItems: function(event) { | |
12683 | |
12684 this.items = []; | |
12685 this.containers = [this]; | |
12686 | |
12687 var i, j, cur, inst, targetData, _queries, item, queriesLength, | |
12688 items = this.items, | |
12689 queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]], | |
12690 connectWith = this._connectWith(); | |
12691 | |
12692 if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down | |
12693 for (i = connectWith.length - 1; i >= 0; i--){ | |
12694 cur = $(connectWith[i]); | |
12695 for (j = cur.length - 1; j >= 0; j--){ | |
12696 inst = $.data(cur[j], this.widgetFullName); | |
12697 if(inst && inst !== this && !inst.options.disabled) { | |
12698 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]); | |
12699 this.containers.push(inst); | |
12700 } | |
12701 } | |
12702 } | |
12703 } | |
12704 | |
12705 for (i = queries.length - 1; i >= 0; i--) { | |
12706 targetData = queries[i][1]; | |
12707 _queries = queries[i][0]; | |
12708 | |
12709 for (j=0, queriesLength = _queries.length; j < queriesLength; j++) { | |
12710 item = $(_queries[j]); | |
12711 | |
12712 item.data(this.widgetName + "-item", targetData); // Data for target checking (mouse manager) | |
12713 | |
12714 items.push({ | |
12715 item: item, | |
12716 instance: targetData, | |
12717 width: 0, height: 0, | |
12718 left: 0, top: 0 | |
12719 }); | |
12720 } | |
12721 } | |
12722 | |
12723 }, | |
12724 | |
12725 refreshPositions: function(fast) { | |
12726 | |
12727 //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change | |
12728 if(this.offsetParent && this.helper) { | |
12729 this.offset.parent = this._getParentOffset(); | |
12730 } | |
12731 | |
12732 var i, item, t, p; | |
12733 | |
12734 for (i = this.items.length - 1; i >= 0; i--){ | |
12735 item = this.items[i]; | |
12736 | |
12737 //We ignore calculating positions of all connected containers when we're not over them | |
12738 if(item.instance !== this.currentContainer && this.currentContainer && item.item[0] !== this.currentItem[0]) { | |
12739 continue; | |
12740 } | |
12741 | |
12742 t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item; | |
12743 | |
12744 if (!fast) { | |
12745 item.width = t.outerWidth(); | |
12746 item.height = t.outerHeight(); | |
12747 } | |
12748 | |
12749 p = t.offset(); | |
12750 item.left = p.left; | |
12751 item.top = p.top; | |
12752 } | |
12753 | |
12754 if(this.options.custom && this.options.custom.refreshContainers) { | |
12755 this.options.custom.refreshContainers.call(this); | |
12756 } else { | |
12757 for (i = this.containers.length - 1; i >= 0; i--){ | |
12758 p = this.containers[i].element.offset(); | |
12759 this.containers[i].containerCache.left = p.left; | |
12760 this.containers[i].containerCache.top = p.top; | |
12761 this.containers[i].containerCache.width = this.containers[i].element.outerWidth(); | |
12762 this.containers[i].containerCache.height = this.containers[i].element.outerHeight(); | |
12763 } | |
12764 } | |
12765 | |
12766 return this; | |
12767 }, | |
12768 | |
12769 _createPlaceholder: function(that) { | |
12770 that = that || this; | |
12771 var className, | |
12772 o = that.options; | |
12773 | |
12774 if(!o.placeholder || o.placeholder.constructor === String) { | |
12775 className = o.placeholder; | |
12776 o.placeholder = { | |
12777 element: function() { | |
12778 | |
12779 var nodeName = that.currentItem[0].nodeName.toLowerCase(), | |
12780 element = $( "<" + nodeName + ">", that.document[0] ) | |
12781 .addClass(className || that.currentItem[0].className+" ui-sortable-placeholder") | |
12782 .removeClass("ui-sortable-helper"); | |
12783 | |
12784 if ( nodeName === "tr" ) { | |
12785 that.currentItem.children().each(function() { | |
12786 $( "<td> </td>", that.document[0] ) | |
12787 .attr( "colspan", $( this ).attr( "colspan" ) || 1 ) | |
12788 .appendTo( element ); | |
12789 }); | |
12790 } else if ( nodeName === "img" ) { | |
12791 element.attr( "src", that.currentItem.attr( "src" ) ); | |
12792 } | |
12793 | |
12794 if ( !className ) { | |
12795 element.css( "visibility", "hidden" ); | |
12796 } | |
12797 | |
12798 return element; | |
12799 }, | |
12800 update: function(container, p) { | |
12801 | |
12802 // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that | |
12803 // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified | |
12804 if(className && !o.forcePlaceholderSize) { | |
12805 return; | |
12806 } | |
12807 | |
12808 //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 | |
12809 if(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css("paddingTop")||0, 10) - parseInt(that.currentItem.css("paddingBottom")||0, 10)); } | |
12810 if(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css("paddingLeft")||0, 10) - parseInt(that.currentItem.css("paddingRight")||0, 10)); } | |
12811 } | |
12812 }; | |
12813 } | |
12814 | |
12815 //Create the placeholder | |
12816 that.placeholder = $(o.placeholder.element.call(that.element, that.currentItem)); | |
12817 | |
12818 //Append it after the actual current item | |
12819 that.currentItem.after(that.placeholder); | |
12820 | |
12821 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317) | |
12822 o.placeholder.update(that, that.placeholder); | |
12823 | |
12824 }, | |
12825 | |
12826 _contactContainers: function(event) { | |
12827 var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, base, cur, nearBottom, floating, | |
12828 innermostContainer = null, | |
12829 innermostIndex = null; | |
12830 | |
12831 // get innermost container that intersects with item | |
12832 for (i = this.containers.length - 1; i >= 0; i--) { | |
12833 | |
12834 // never consider a container that's located within the item itself | |
12835 if($.contains(this.currentItem[0], this.containers[i].element[0])) { | |
12836 continue; | |
12837 } | |
12838 | |
12839 if(this._intersectsWith(this.containers[i].containerCache)) { | |
12840 | |
12841 // if we've already found a container and it's more "inner" than this, then continue | |
12842 if(innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0])) { | |
12843 continue; | |
12844 } | |
12845 | |
12846 innermostContainer = this.containers[i]; | |
12847 innermostIndex = i; | |
12848 | |
12849 } else { | |
12850 // container doesn't intersect. trigger "out" event if necessary | |
12851 if(this.containers[i].containerCache.over) { | |
12852 this.containers[i]._trigger("out", event, this._uiHash(this)); | |
12853 this.containers[i].containerCache.over = 0; | |
12854 } | |
12855 } | |
12856 | |
12857 } | |
12858 | |
12859 // if no intersecting containers found, return | |
12860 if(!innermostContainer) { | |
12861 return; | |
12862 } | |
12863 | |
12864 // move the item into the container if it's not there already | |
12865 if(this.containers.length === 1) { | |
12866 if (!this.containers[innermostIndex].containerCache.over) { | |
12867 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); | |
12868 this.containers[innermostIndex].containerCache.over = 1; | |
12869 } | |
12870 } else { | |
12871 | |
12872 //When entering a new container, we will find the item with the least distance and append our item near it | |
12873 dist = 10000; | |
12874 itemWithLeastDistance = null; | |
12875 floating = innermostContainer.floating || isFloating(this.currentItem); | |
12876 posProperty = floating ? "left" : "top"; | |
12877 sizeProperty = floating ? "width" : "height"; | |
12878 base = this.positionAbs[posProperty] + this.offset.click[posProperty]; | |
12879 for (j = this.items.length - 1; j >= 0; j--) { | |
12880 if(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) { | |
12881 continue; | |
12882 } | |
12883 if(this.items[j].item[0] === this.currentItem[0]) { | |
12884 continue; | |
12885 } | |
12886 if (floating && !isOverAxis(this.positionAbs.top + this.offset.click.top, this.items[j].top, this.items[j].height)) { | |
12887 continue; | |
12888 } | |
12889 cur = this.items[j].item.offset()[posProperty]; | |
12890 nearBottom = false; | |
12891 if(Math.abs(cur - base) > Math.abs(cur + this.items[j][sizeProperty] - base)){ | |
12892 nearBottom = true; | |
12893 cur += this.items[j][sizeProperty]; | |
12894 } | |
12895 | |
12896 if(Math.abs(cur - base) < dist) { | |
12897 dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j]; | |
12898 this.direction = nearBottom ? "up": "down"; | |
12899 } | |
12900 } | |
12901 | |
12902 //Check if dropOnEmpty is enabled | |
12903 if(!itemWithLeastDistance && !this.options.dropOnEmpty) { | |
12904 return; | |
12905 } | |
12906 | |
12907 if(this.currentContainer === this.containers[innermostIndex]) { | |
12908 return; | |
12909 } | |
12910 | |
12911 itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true); | |
12912 this._trigger("change", event, this._uiHash()); | |
12913 this.containers[innermostIndex]._trigger("change", event, this._uiHash(this)); | |
12914 this.currentContainer = this.containers[innermostIndex]; | |
12915 | |
12916 //Update the placeholder | |
12917 this.options.placeholder.update(this.currentContainer, this.placeholder); | |
12918 | |
12919 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); | |
12920 this.containers[innermostIndex].containerCache.over = 1; | |
12921 } | |
12922 | |
12923 | |
12924 }, | |
12925 | |
12926 _createHelper: function(event) { | |
12927 | |
12928 var o = this.options, | |
12929 helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper === "clone" ? this.currentItem.clone() : this.currentItem); | |
12930 | |
12931 //Add the helper to the DOM if that didn't happen already | |
12932 if(!helper.parents("body").length) { | |
12933 $(o.appendTo !== "parent" ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]); | |
12934 } | |
12935 | |
12936 if(helper[0] === this.currentItem[0]) { | |
12937 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") }; | |
12938 } | |
12939 | |
12940 if(!helper[0].style.width || o.forceHelperSize) { | |
12941 helper.width(this.currentItem.width()); | |
12942 } | |
12943 if(!helper[0].style.height || o.forceHelperSize) { | |
12944 helper.height(this.currentItem.height()); | |
12945 } | |
12946 | |
12947 return helper; | |
12948 | |
12949 }, | |
12950 | |
12951 _adjustOffsetFromHelper: function(obj) { | |
12952 if (typeof obj === "string") { | |
12953 obj = obj.split(" "); | |
12954 } | |
12955 if ($.isArray(obj)) { | |
12956 obj = {left: +obj[0], top: +obj[1] || 0}; | |
12957 } | |
12958 if ("left" in obj) { | |
12959 this.offset.click.left = obj.left + this.margins.left; | |
12960 } | |
12961 if ("right" in obj) { | |
12962 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; | |
12963 } | |
12964 if ("top" in obj) { | |
12965 this.offset.click.top = obj.top + this.margins.top; | |
12966 } | |
12967 if ("bottom" in obj) { | |
12968 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; | |
12969 } | |
12970 }, | |
12971 | |
12972 _getParentOffset: function() { | |
12973 | |
12974 | |
12975 //Get the offsetParent and cache its position | |
12976 this.offsetParent = this.helper.offsetParent(); | |
12977 var po = this.offsetParent.offset(); | |
12978 | |
12979 // This is a special case where we need to modify a offset calculated on start, since the following happened: | |
12980 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent | |
12981 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that | |
12982 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag | |
12983 if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) { | |
12984 po.left += this.scrollParent.scrollLeft(); | |
12985 po.top += this.scrollParent.scrollTop(); | |
12986 } | |
12987 | |
12988 // This needs to be actually done for all browsers, since pageX/pageY includes this information | |
12989 // with an ugly IE fix | |
12990 if( this.offsetParent[0] === document.body || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) { | |
12991 po = { top: 0, left: 0 }; | |
12992 } | |
12993 | |
12994 return { | |
12995 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0), | |
12996 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0) | |
12997 }; | |
12998 | |
12999 }, | |
13000 | |
13001 _getRelativeOffset: function() { | |
13002 | |
13003 if(this.cssPosition === "relative") { | |
13004 var p = this.currentItem.position(); | |
13005 return { | |
13006 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(), | |
13007 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft() | |
13008 }; | |
13009 } else { | |
13010 return { top: 0, left: 0 }; | |
13011 } | |
13012 | |
13013 }, | |
13014 | |
13015 _cacheMargins: function() { | |
13016 this.margins = { | |
13017 left: (parseInt(this.currentItem.css("marginLeft"),10) || 0), | |
13018 top: (parseInt(this.currentItem.css("marginTop"),10) || 0) | |
13019 }; | |
13020 }, | |
13021 | |
13022 _cacheHelperProportions: function() { | |
13023 this.helperProportions = { | |
13024 width: this.helper.outerWidth(), | |
13025 height: this.helper.outerHeight() | |
13026 }; | |
13027 }, | |
13028 | |
13029 _setContainment: function() { | |
13030 | |
13031 var ce, co, over, | |
13032 o = this.options; | |
13033 if(o.containment === "parent") { | |
13034 o.containment = this.helper[0].parentNode; | |
13035 } | |
13036 if(o.containment === "document" || o.containment === "window") { | |
13037 this.containment = [ | |
13038 0 - this.offset.relative.left - this.offset.parent.left, | |
13039 0 - this.offset.relative.top - this.offset.parent.top, | |
13040 $(o.containment === "document" ? document : window).width() - this.helperProportions.width - this.margins.left, | |
13041 ($(o.containment === "document" ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top | |
13042 ]; | |
13043 } | |
13044 | |
13045 if(!(/^(document|window|parent)$/).test(o.containment)) { | |
13046 ce = $(o.containment)[0]; | |
13047 co = $(o.containment).offset(); | |
13048 over = ($(ce).css("overflow") !== "hidden"); | |
13049 | |
13050 this.containment = [ | |
13051 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left, | |
13052 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top, | |
13053 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, | |
13054 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 | |
13055 ]; | |
13056 } | |
13057 | |
13058 }, | |
13059 | |
13060 _convertPositionTo: function(d, pos) { | |
13061 | |
13062 if(!pos) { | |
13063 pos = this.position; | |
13064 } | |
13065 var mod = d === "absolute" ? 1 : -1, | |
13066 scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, | |
13067 scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); | |
13068 | |
13069 return { | |
13070 top: ( | |
13071 pos.top + // The absolute mouse position | |
13072 this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent | |
13073 this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border) | |
13074 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod) | |
13075 ), | |
13076 left: ( | |
13077 pos.left + // The absolute mouse position | |
13078 this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent | |
13079 this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border) | |
13080 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod) | |
13081 ) | |
13082 }; | |
13083 | |
13084 }, | |
13085 | |
13086 _generatePosition: function(event) { | |
13087 | |
13088 var top, left, | |
13089 o = this.options, | |
13090 pageX = event.pageX, | |
13091 pageY = event.pageY, | |
13092 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); | |
13093 | |
13094 // This is another very weird special case that only happens for relative elements: | |
13095 // 1. If the css position is relative | |
13096 // 2. and the scroll parent is the document or similar to the offset parent | |
13097 // we have to refresh the relative offset during the scroll so there are no jumps | |
13098 if(this.cssPosition === "relative" && !(this.scrollParent[0] !== document && this.scrollParent[0] !== this.offsetParent[0])) { | |
13099 this.offset.relative = this._getRelativeOffset(); | |
13100 } | |
13101 | |
13102 /* | |
13103 * - Position constraining - | |
13104 * Constrain the position to a mix of grid, containment. | |
13105 */ | |
13106 | |
13107 if(this.originalPosition) { //If we are not dragging yet, we won't check for options | |
13108 | |
13109 if(this.containment) { | |
13110 if(event.pageX - this.offset.click.left < this.containment[0]) { | |
13111 pageX = this.containment[0] + this.offset.click.left; | |
13112 } | |
13113 if(event.pageY - this.offset.click.top < this.containment[1]) { | |
13114 pageY = this.containment[1] + this.offset.click.top; | |
13115 } | |
13116 if(event.pageX - this.offset.click.left > this.containment[2]) { | |
13117 pageX = this.containment[2] + this.offset.click.left; | |
13118 } | |
13119 if(event.pageY - this.offset.click.top > this.containment[3]) { | |
13120 pageY = this.containment[3] + this.offset.click.top; | |
13121 } | |
13122 } | |
13123 | |
13124 if(o.grid) { | |
13125 top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1]; | |
13126 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; | |
13127 | |
13128 left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0]; | |
13129 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; | |
13130 } | |
13131 | |
13132 } | |
13133 | |
13134 return { | |
13135 top: ( | |
13136 pageY - // The absolute mouse position | |
13137 this.offset.click.top - // Click offset (relative to the element) | |
13138 this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent | |
13139 this.offset.parent.top + // The offsetParent's offset without borders (offset + border) | |
13140 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) )) | |
13141 ), | |
13142 left: ( | |
13143 pageX - // The absolute mouse position | |
13144 this.offset.click.left - // Click offset (relative to the element) | |
13145 this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent | |
13146 this.offset.parent.left + // The offsetParent's offset without borders (offset + border) | |
13147 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() )) | |
13148 ) | |
13149 }; | |
13150 | |
13151 }, | |
13152 | |
13153 _rearrange: function(event, i, a, hardRefresh) { | |
13154 | |
13155 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)); | |
13156 | |
13157 //Various things done here to improve the performance: | |
13158 // 1. we create a setTimeout, that calls refreshPositions | |
13159 // 2. on the instance, we have a counter variable, that get's higher after every append | |
13160 // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same | |
13161 // 4. this lets only the last addition to the timeout stack through | |
13162 this.counter = this.counter ? ++this.counter : 1; | |
13163 var counter = this.counter; | |
13164 | |
13165 this._delay(function() { | |
13166 if(counter === this.counter) { | |
13167 this.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove | |
13168 } | |
13169 }); | |
13170 | |
13171 }, | |
13172 | |
13173 _clear: function(event, noPropagation) { | |
13174 | |
13175 this.reverting = false; | |
13176 // We delay all events that have to be triggered to after the point where the placeholder has been removed and | |
13177 // everything else normalized again | |
13178 var i, | |
13179 delayedTriggers = []; | |
13180 | |
13181 // We first have to update the dom position of the actual currentItem | |
13182 // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088) | |
13183 if(!this._noFinalSort && this.currentItem.parent().length) { | |
13184 this.placeholder.before(this.currentItem); | |
13185 } | |
13186 this._noFinalSort = null; | |
13187 | |
13188 if(this.helper[0] === this.currentItem[0]) { | |
13189 for(i in this._storedCSS) { | |
13190 if(this._storedCSS[i] === "auto" || this._storedCSS[i] === "static") { | |
13191 this._storedCSS[i] = ""; | |
13192 } | |
13193 } | |
13194 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); | |
13195 } else { | |
13196 this.currentItem.show(); | |
13197 } | |
13198 | |
13199 if(this.fromOutside && !noPropagation) { | |
13200 delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); }); | |
13201 } | |
13202 if((this.fromOutside || this.domPosition.prev !== this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent !== this.currentItem.parent()[0]) && !noPropagation) { | |
13203 delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed | |
13204 } | |
13205 | |
13206 // Check if the items Container has Changed and trigger appropriate | |
13207 // events. | |
13208 if (this !== this.currentContainer) { | |
13209 if(!noPropagation) { | |
13210 delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); }); | |
13211 delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.currentContainer)); | |
13212 delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.currentContainer)); | |
13213 } | |
13214 } | |
13215 | |
13216 | |
13217 //Post events to containers | |
13218 function delayEvent( type, instance, container ) { | |
13219 return function( event ) { | |
13220 container._trigger( type, event, instance._uiHash( instance ) ); | |
13221 }; | |
13222 } | |
13223 for (i = this.containers.length - 1; i >= 0; i--){ | |
13224 if (!noPropagation) { | |
13225 delayedTriggers.push( delayEvent( "deactivate", this, this.containers[ i ] ) ); | |
13226 } | |
13227 if(this.containers[i].containerCache.over) { | |
13228 delayedTriggers.push( delayEvent( "out", this, this.containers[ i ] ) ); | |
13229 this.containers[i].containerCache.over = 0; | |
13230 } | |
13231 } | |
13232 | |
13233 //Do what was originally in plugins | |
13234 if ( this.storedCursor ) { | |
13235 this.document.find( "body" ).css( "cursor", this.storedCursor ); | |
13236 this.storedStylesheet.remove(); | |
13237 } | |
13238 if(this._storedOpacity) { | |
13239 this.helper.css("opacity", this._storedOpacity); | |
13240 } | |
13241 if(this._storedZIndex) { | |
13242 this.helper.css("zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex); | |
13243 } | |
13244 | |
13245 this.dragging = false; | |
13246 if(this.cancelHelperRemoval) { | |
13247 if(!noPropagation) { | |
13248 this._trigger("beforeStop", event, this._uiHash()); | |
13249 for (i=0; i < delayedTriggers.length; i++) { | |
13250 delayedTriggers[i].call(this, event); | |
13251 } //Trigger all delayed events | |
13252 this._trigger("stop", event, this._uiHash()); | |
13253 } | |
13254 | |
13255 this.fromOutside = false; | |
13256 return false; | |
13257 } | |
13258 | |
13259 if(!noPropagation) { | |
13260 this._trigger("beforeStop", event, this._uiHash()); | |
13261 } | |
13262 | |
13263 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! | |
13264 this.placeholder[0].parentNode.removeChild(this.placeholder[0]); | |
13265 | |
13266 if(this.helper[0] !== this.currentItem[0]) { | |
13267 this.helper.remove(); | |
13268 } | |
13269 this.helper = null; | |
13270 | |
13271 if(!noPropagation) { | |
13272 for (i=0; i < delayedTriggers.length; i++) { | |
13273 delayedTriggers[i].call(this, event); | |
13274 } //Trigger all delayed events | |
13275 this._trigger("stop", event, this._uiHash()); | |
13276 } | |
13277 | |
13278 this.fromOutside = false; | |
13279 return true; | |
13280 | |
13281 }, | |
13282 | |
13283 _trigger: function() { | |
13284 if ($.Widget.prototype._trigger.apply(this, arguments) === false) { | |
13285 this.cancel(); | |
13286 } | |
13287 }, | |
13288 | |
13289 _uiHash: function(_inst) { | |
13290 var inst = _inst || this; | |
13291 return { | |
13292 helper: inst.helper, | |
13293 placeholder: inst.placeholder || $([]), | |
13294 position: inst.position, | |
13295 originalPosition: inst.originalPosition, | |
13296 offset: inst.positionAbs, | |
13297 item: inst.currentItem, | |
13298 sender: _inst ? _inst.element : null | |
13299 }; | |
13300 } | |
13301 | |
13302 }); | |
13303 | |
13304 })(jQuery); | |
13305 (function( $ ) { | |
13306 | |
13307 function modifier( fn ) { | |
13308 return function() { | |
13309 var previous = this.element.val(); | |
13310 fn.apply( this, arguments ); | |
13311 this._refresh(); | |
13312 if ( previous !== this.element.val() ) { | |
13313 this._trigger( "change" ); | |
13314 } | |
13315 }; | |
13316 } | |
13317 | |
13318 $.widget( "ui.spinner", { | |
13319 version: "1.10.4", | |
13320 defaultElement: "<input>", | |
13321 widgetEventPrefix: "spin", | |
13322 options: { | |
13323 culture: null, | |
13324 icons: { | |
13325 down: "ui-icon-triangle-1-s", | |
13326 up: "ui-icon-triangle-1-n" | |
13327 }, | |
13328 incremental: true, | |
13329 max: null, | |
13330 min: null, | |
13331 numberFormat: null, | |
13332 page: 10, | |
13333 step: 1, | |
13334 | |
13335 change: null, | |
13336 spin: null, | |
13337 start: null, | |
13338 stop: null | |
13339 }, | |
13340 | |
13341 _create: function() { | |
13342 // handle string values that need to be parsed | |
13343 this._setOption( "max", this.options.max ); | |
13344 this._setOption( "min", this.options.min ); | |
13345 this._setOption( "step", this.options.step ); | |
13346 | |
13347 // Only format if there is a value, prevents the field from being marked | |
13348 // as invalid in Firefox, see #9573. | |
13349 if ( this.value() !== "" ) { | |
13350 // Format the value, but don't constrain. | |
13351 this._value( this.element.val(), true ); | |
13352 } | |
13353 | |
13354 this._draw(); | |
13355 this._on( this._events ); | |
13356 this._refresh(); | |
13357 | |
13358 // turning off autocomplete prevents the browser from remembering the | |
13359 // value when navigating through history, so we re-enable autocomplete | |
13360 // if the page is unloaded before the widget is destroyed. #7790 | |
13361 this._on( this.window, { | |
13362 beforeunload: function() { | |
13363 this.element.removeAttr( "autocomplete" ); | |
13364 } | |
13365 }); | |
13366 }, | |
13367 | |
13368 _getCreateOptions: function() { | |
13369 var options = {}, | |
13370 element = this.element; | |
13371 | |
13372 $.each( [ "min", "max", "step" ], function( i, option ) { | |
13373 var value = element.attr( option ); | |
13374 if ( value !== undefined && value.length ) { | |
13375 options[ option ] = value; | |
13376 } | |
13377 }); | |
13378 | |
13379 return options; | |
13380 }, | |
13381 | |
13382 _events: { | |
13383 keydown: function( event ) { | |
13384 if ( this._start( event ) && this._keydown( event ) ) { | |
13385 event.preventDefault(); | |
13386 } | |
13387 }, | |
13388 keyup: "_stop", | |
13389 focus: function() { | |
13390 this.previous = this.element.val(); | |
13391 }, | |
13392 blur: function( event ) { | |
13393 if ( this.cancelBlur ) { | |
13394 delete this.cancelBlur; | |
13395 return; | |
13396 } | |
13397 | |
13398 this._stop(); | |
13399 this._refresh(); | |
13400 if ( this.previous !== this.element.val() ) { | |
13401 this._trigger( "change", event ); | |
13402 } | |
13403 }, | |
13404 mousewheel: function( event, delta ) { | |
13405 if ( !delta ) { | |
13406 return; | |
13407 } | |
13408 if ( !this.spinning && !this._start( event ) ) { | |
13409 return false; | |
13410 } | |
13411 | |
13412 this._spin( (delta > 0 ? 1 : -1) * this.options.step, event ); | |
13413 clearTimeout( this.mousewheelTimer ); | |
13414 this.mousewheelTimer = this._delay(function() { | |
13415 if ( this.spinning ) { | |
13416 this._stop( event ); | |
13417 } | |
13418 }, 100 ); | |
13419 event.preventDefault(); | |
13420 }, | |
13421 "mousedown .ui-spinner-button": function( event ) { | |
13422 var previous; | |
13423 | |
13424 // We never want the buttons to have focus; whenever the user is | |
13425 // interacting with the spinner, the focus should be on the input. | |
13426 // If the input is focused then this.previous is properly set from | |
13427 // when the input first received focus. If the input is not focused | |
13428 // then we need to set this.previous based on the value before spinning. | |
13429 previous = this.element[0] === this.document[0].activeElement ? | |
13430 this.previous : this.element.val(); | |
13431 function checkFocus() { | |
13432 var isActive = this.element[0] === this.document[0].activeElement; | |
13433 if ( !isActive ) { | |
13434 this.element.focus(); | |
13435 this.previous = previous; | |
13436 // support: IE | |
13437 // IE sets focus asynchronously, so we need to check if focus | |
13438 // moved off of the input because the user clicked on the button. | |
13439 this._delay(function() { | |
13440 this.previous = previous; | |
13441 }); | |
13442 } | |
13443 } | |
13444 | |
13445 // ensure focus is on (or stays on) the text field | |
13446 event.preventDefault(); | |
13447 checkFocus.call( this ); | |
13448 | |
13449 // support: IE | |
13450 // IE doesn't prevent moving focus even with event.preventDefault() | |
13451 // so we set a flag to know when we should ignore the blur event | |
13452 // and check (again) if focus moved off of the input. | |
13453 this.cancelBlur = true; | |
13454 this._delay(function() { | |
13455 delete this.cancelBlur; | |
13456 checkFocus.call( this ); | |
13457 }); | |
13458 | |
13459 if ( this._start( event ) === false ) { | |
13460 return; | |
13461 } | |
13462 | |
13463 this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event ); | |
13464 }, | |
13465 "mouseup .ui-spinner-button": "_stop", | |
13466 "mouseenter .ui-spinner-button": function( event ) { | |
13467 // button will add ui-state-active if mouse was down while mouseleave and kept down | |
13468 if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) { | |
13469 return; | |
13470 } | |
13471 | |
13472 if ( this._start( event ) === false ) { | |
13473 return false; | |
13474 } | |
13475 this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event ); | |
13476 }, | |
13477 // TODO: do we really want to consider this a stop? | |
13478 // shouldn't we just stop the repeater and wait until mouseup before | |
13479 // we trigger the stop event? | |
13480 "mouseleave .ui-spinner-button": "_stop" | |
13481 }, | |
13482 | |
13483 _draw: function() { | |
13484 var uiSpinner = this.uiSpinner = this.element | |
13485 .addClass( "ui-spinner-input" ) | |
13486 .attr( "autocomplete", "off" ) | |
13487 .wrap( this._uiSpinnerHtml() ) | |
13488 .parent() | |
13489 // add buttons | |
13490 .append( this._buttonHtml() ); | |
13491 | |
13492 this.element.attr( "role", "spinbutton" ); | |
13493 | |
13494 // button bindings | |
13495 this.buttons = uiSpinner.find( ".ui-spinner-button" ) | |
13496 .attr( "tabIndex", -1 ) | |
13497 .button() | |
13498 .removeClass( "ui-corner-all" ); | |
13499 | |
13500 // IE 6 doesn't understand height: 50% for the buttons | |
13501 // unless the wrapper has an explicit height | |
13502 if ( this.buttons.height() > Math.ceil( uiSpinner.height() * 0.5 ) && | |
13503 uiSpinner.height() > 0 ) { | |
13504 uiSpinner.height( uiSpinner.height() ); | |
13505 } | |
13506 | |
13507 // disable spinner if element was already disabled | |
13508 if ( this.options.disabled ) { | |
13509 this.disable(); | |
13510 } | |
13511 }, | |
13512 | |
13513 _keydown: function( event ) { | |
13514 var options = this.options, | |
13515 keyCode = $.ui.keyCode; | |
13516 | |
13517 switch ( event.keyCode ) { | |
13518 case keyCode.UP: | |
13519 this._repeat( null, 1, event ); | |
13520 return true; | |
13521 case keyCode.DOWN: | |
13522 this._repeat( null, -1, event ); | |
13523 return true; | |
13524 case keyCode.PAGE_UP: | |
13525 this._repeat( null, options.page, event ); | |
13526 return true; | |
13527 case keyCode.PAGE_DOWN: | |
13528 this._repeat( null, -options.page, event ); | |
13529 return true; | |
13530 } | |
13531 | |
13532 return false; | |
13533 }, | |
13534 | |
13535 _uiSpinnerHtml: function() { | |
13536 return "<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>"; | |
13537 }, | |
13538 | |
13539 _buttonHtml: function() { | |
13540 return "" + | |
13541 "<a class='ui-spinner-button ui-spinner-up ui-corner-tr'>" + | |
13542 "<span class='ui-icon " + this.options.icons.up + "'>▲</span>" + | |
13543 "</a>" + | |
13544 "<a class='ui-spinner-button ui-spinner-down ui-corner-br'>" + | |
13545 "<span class='ui-icon " + this.options.icons.down + "'>▼</span>" + | |
13546 "</a>"; | |
13547 }, | |
13548 | |
13549 _start: function( event ) { | |
13550 if ( !this.spinning && this._trigger( "start", event ) === false ) { | |
13551 return false; | |
13552 } | |
13553 | |
13554 if ( !this.counter ) { | |
13555 this.counter = 1; | |
13556 } | |
13557 this.spinning = true; | |
13558 return true; | |
13559 }, | |
13560 | |
13561 _repeat: function( i, steps, event ) { | |
13562 i = i || 500; | |
13563 | |
13564 clearTimeout( this.timer ); | |
13565 this.timer = this._delay(function() { | |
13566 this._repeat( 40, steps, event ); | |
13567 }, i ); | |
13568 | |
13569 this._spin( steps * this.options.step, event ); | |
13570 }, | |
13571 | |
13572 _spin: function( step, event ) { | |
13573 var value = this.value() || 0; | |
13574 | |
13575 if ( !this.counter ) { | |
13576 this.counter = 1; | |
13577 } | |
13578 | |
13579 value = this._adjustValue( value + step * this._increment( this.counter ) ); | |
13580 | |
13581 if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false) { | |
13582 this._value( value ); | |
13583 this.counter++; | |
13584 } | |
13585 }, | |
13586 | |
13587 _increment: function( i ) { | |
13588 var incremental = this.options.incremental; | |
13589 | |
13590 if ( incremental ) { | |
13591 return $.isFunction( incremental ) ? | |
13592 incremental( i ) : | |
13593 Math.floor( i*i*i/50000 - i*i/500 + 17*i/200 + 1 ); | |
13594 } | |
13595 | |
13596 return 1; | |
13597 }, | |
13598 | |
13599 _precision: function() { | |
13600 var precision = this._precisionOf( this.options.step ); | |
13601 if ( this.options.min !== null ) { | |
13602 precision = Math.max( precision, this._precisionOf( this.options.min ) ); | |
13603 } | |
13604 return precision; | |
13605 }, | |
13606 | |
13607 _precisionOf: function( num ) { | |
13608 var str = num.toString(), | |
13609 decimal = str.indexOf( "." ); | |
13610 return decimal === -1 ? 0 : str.length - decimal - 1; | |
13611 }, | |
13612 | |
13613 _adjustValue: function( value ) { | |
13614 var base, aboveMin, | |
13615 options = this.options; | |
13616 | |
13617 // make sure we're at a valid step | |
13618 // - find out where we are relative to the base (min or 0) | |
13619 base = options.min !== null ? options.min : 0; | |
13620 aboveMin = value - base; | |
13621 // - round to the nearest step | |
13622 aboveMin = Math.round(aboveMin / options.step) * options.step; | |
13623 // - rounding is based on 0, so adjust back to our base | |
13624 value = base + aboveMin; | |
13625 | |
13626 // fix precision from bad JS floating point math | |
13627 value = parseFloat( value.toFixed( this._precision() ) ); | |
13628 | |
13629 // clamp the value | |
13630 if ( options.max !== null && value > options.max) { | |
13631 return options.max; | |
13632 } | |
13633 if ( options.min !== null && value < options.min ) { | |
13634 return options.min; | |
13635 } | |
13636 | |
13637 return value; | |
13638 }, | |
13639 | |
13640 _stop: function( event ) { | |
13641 if ( !this.spinning ) { | |
13642 return; | |
13643 } | |
13644 | |
13645 clearTimeout( this.timer ); | |
13646 clearTimeout( this.mousewheelTimer ); | |
13647 this.counter = 0; | |
13648 this.spinning = false; | |
13649 this._trigger( "stop", event ); | |
13650 }, | |
13651 | |
13652 _setOption: function( key, value ) { | |
13653 if ( key === "culture" || key === "numberFormat" ) { | |
13654 var prevValue = this._parse( this.element.val() ); | |
13655 this.options[ key ] = value; | |
13656 this.element.val( this._format( prevValue ) ); | |
13657 return; | |
13658 } | |
13659 | |
13660 if ( key === "max" || key === "min" || key === "step" ) { | |
13661 if ( typeof value === "string" ) { | |
13662 value = this._parse( value ); | |
13663 } | |
13664 } | |
13665 if ( key === "icons" ) { | |
13666 this.buttons.first().find( ".ui-icon" ) | |
13667 .removeClass( this.options.icons.up ) | |
13668 .addClass( value.up ); | |
13669 this.buttons.last().find( ".ui-icon" ) | |
13670 .removeClass( this.options.icons.down ) | |
13671 .addClass( value.down ); | |
13672 } | |
13673 | |
13674 this._super( key, value ); | |
13675 | |
13676 if ( key === "disabled" ) { | |
13677 if ( value ) { | |
13678 this.element.prop( "disabled", true ); | |
13679 this.buttons.button( "disable" ); | |
13680 } else { | |
13681 this.element.prop( "disabled", false ); | |
13682 this.buttons.button( "enable" ); | |
13683 } | |
13684 } | |
13685 }, | |
13686 | |
13687 _setOptions: modifier(function( options ) { | |
13688 this._super( options ); | |
13689 this._value( this.element.val() ); | |
13690 }), | |
13691 | |
13692 _parse: function( val ) { | |
13693 if ( typeof val === "string" && val !== "" ) { | |
13694 val = window.Globalize && this.options.numberFormat ? | |
13695 Globalize.parseFloat( val, 10, this.options.culture ) : +val; | |
13696 } | |
13697 return val === "" || isNaN( val ) ? null : val; | |
13698 }, | |
13699 | |
13700 _format: function( value ) { | |
13701 if ( value === "" ) { | |
13702 return ""; | |
13703 } | |
13704 return window.Globalize && this.options.numberFormat ? | |
13705 Globalize.format( value, this.options.numberFormat, this.options.culture ) : | |
13706 value; | |
13707 }, | |
13708 | |
13709 _refresh: function() { | |
13710 this.element.attr({ | |
13711 "aria-valuemin": this.options.min, | |
13712 "aria-valuemax": this.options.max, | |
13713 // TODO: what should we do with values that can't be parsed? | |
13714 "aria-valuenow": this._parse( this.element.val() ) | |
13715 }); | |
13716 }, | |
13717 | |
13718 // update the value without triggering change | |
13719 _value: function( value, allowAny ) { | |
13720 var parsed; | |
13721 if ( value !== "" ) { | |
13722 parsed = this._parse( value ); | |
13723 if ( parsed !== null ) { | |
13724 if ( !allowAny ) { | |
13725 parsed = this._adjustValue( parsed ); | |
13726 } | |
13727 value = this._format( parsed ); | |
13728 } | |
13729 } | |
13730 this.element.val( value ); | |
13731 this._refresh(); | |
13732 }, | |
13733 | |
13734 _destroy: function() { | |
13735 this.element | |
13736 .removeClass( "ui-spinner-input" ) | |
13737 .prop( "disabled", false ) | |
13738 .removeAttr( "autocomplete" ) | |
13739 .removeAttr( "role" ) | |
13740 .removeAttr( "aria-valuemin" ) | |
13741 .removeAttr( "aria-valuemax" ) | |
13742 .removeAttr( "aria-valuenow" ); | |
13743 this.uiSpinner.replaceWith( this.element ); | |
13744 }, | |
13745 | |
13746 stepUp: modifier(function( steps ) { | |
13747 this._stepUp( steps ); | |
13748 }), | |
13749 _stepUp: function( steps ) { | |
13750 if ( this._start() ) { | |
13751 this._spin( (steps || 1) * this.options.step ); | |
13752 this._stop(); | |
13753 } | |
13754 }, | |
13755 | |
13756 stepDown: modifier(function( steps ) { | |
13757 this._stepDown( steps ); | |
13758 }), | |
13759 _stepDown: function( steps ) { | |
13760 if ( this._start() ) { | |
13761 this._spin( (steps || 1) * -this.options.step ); | |
13762 this._stop(); | |
13763 } | |
13764 }, | |
13765 | |
13766 pageUp: modifier(function( pages ) { | |
13767 this._stepUp( (pages || 1) * this.options.page ); | |
13768 }), | |
13769 | |
13770 pageDown: modifier(function( pages ) { | |
13771 this._stepDown( (pages || 1) * this.options.page ); | |
13772 }), | |
13773 | |
13774 value: function( newVal ) { | |
13775 if ( !arguments.length ) { | |
13776 return this._parse( this.element.val() ); | |
13777 } | |
13778 modifier( this._value ).call( this, newVal ); | |
13779 }, | |
13780 | |
13781 widget: function() { | |
13782 return this.uiSpinner; | |
13783 } | |
13784 }); | |
13785 | |
13786 }( jQuery ) ); | |
13787 (function( $, undefined ) { | |
13788 | |
13789 var tabId = 0, | |
13790 rhash = /#.*$/; | |
13791 | |
13792 function getNextTabId() { | |
13793 return ++tabId; | |
13794 } | |
13795 | |
13796 function isLocal( anchor ) { | |
13797 // support: IE7 | |
13798 // IE7 doesn't normalize the href property when set via script (#9317) | |
13799 anchor = anchor.cloneNode( false ); | |
13800 | |
13801 return anchor.hash.length > 1 && | |
13802 decodeURIComponent( anchor.href.replace( rhash, "" ) ) === | |
13803 decodeURIComponent( location.href.replace( rhash, "" ) ); | |
13804 } | |
13805 | |
13806 $.widget( "ui.tabs", { | |
13807 version: "1.10.4", | |
13808 delay: 300, | |
13809 options: { | |
13810 active: null, | |
13811 collapsible: false, | |
13812 event: "click", | |
13813 heightStyle: "content", | |
13814 hide: null, | |
13815 show: null, | |
13816 | |
13817 // callbacks | |
13818 activate: null, | |
13819 beforeActivate: null, | |
13820 beforeLoad: null, | |
13821 load: null | |
13822 }, | |
13823 | |
13824 _create: function() { | |
13825 var that = this, | |
13826 options = this.options; | |
13827 | |
13828 this.running = false; | |
13829 | |
13830 this.element | |
13831 .addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" ) | |
13832 .toggleClass( "ui-tabs-collapsible", options.collapsible ) | |
13833 // Prevent users from focusing disabled tabs via click | |
13834 .delegate( ".ui-tabs-nav > li", "mousedown" + this.eventNamespace, function( event ) { | |
13835 if ( $( this ).is( ".ui-state-disabled" ) ) { | |
13836 event.preventDefault(); | |
13837 } | |
13838 }) | |
13839 // support: IE <9 | |
13840 // Preventing the default action in mousedown doesn't prevent IE | |
13841 // from focusing the element, so if the anchor gets focused, blur. | |
13842 // We don't have to worry about focusing the previously focused | |
13843 // element since clicking on a non-focusable element should focus | |
13844 // the body anyway. | |
13845 .delegate( ".ui-tabs-anchor", "focus" + this.eventNamespace, function() { | |
13846 if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) { | |
13847 this.blur(); | |
13848 } | |
13849 }); | |
13850 | |
13851 this._processTabs(); | |
13852 options.active = this._initialActive(); | |
13853 | |
13854 // Take disabling tabs via class attribute from HTML | |
13855 // into account and update option properly. | |
13856 if ( $.isArray( options.disabled ) ) { | |
13857 options.disabled = $.unique( options.disabled.concat( | |
13858 $.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) { | |
13859 return that.tabs.index( li ); | |
13860 }) | |
13861 ) ).sort(); | |
13862 } | |
13863 | |
13864 // check for length avoids error when initializing empty list | |
13865 if ( this.options.active !== false && this.anchors.length ) { | |
13866 this.active = this._findActive( options.active ); | |
13867 } else { | |
13868 this.active = $(); | |
13869 } | |
13870 | |
13871 this._refresh(); | |
13872 | |
13873 if ( this.active.length ) { | |
13874 this.load( options.active ); | |
13875 } | |
13876 }, | |
13877 | |
13878 _initialActive: function() { | |
13879 var active = this.options.active, | |
13880 collapsible = this.options.collapsible, | |
13881 locationHash = location.hash.substring( 1 ); | |
13882 | |
13883 if ( active === null ) { | |
13884 // check the fragment identifier in the URL | |
13885 if ( locationHash ) { | |
13886 this.tabs.each(function( i, tab ) { | |
13887 if ( $( tab ).attr( "aria-controls" ) === locationHash ) { | |
13888 active = i; | |
13889 return false; | |
13890 } | |
13891 }); | |
13892 } | |
13893 | |
13894 // check for a tab marked active via a class | |
13895 if ( active === null ) { | |
13896 active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) ); | |
13897 } | |
13898 | |
13899 // no active tab, set to false | |
13900 if ( active === null || active === -1 ) { | |
13901 active = this.tabs.length ? 0 : false; | |
13902 } | |
13903 } | |
13904 | |
13905 // handle numbers: negative, out of range | |
13906 if ( active !== false ) { | |
13907 active = this.tabs.index( this.tabs.eq( active ) ); | |
13908 if ( active === -1 ) { | |
13909 active = collapsible ? false : 0; | |
13910 } | |
13911 } | |
13912 | |
13913 // don't allow collapsible: false and active: false | |
13914 if ( !collapsible && active === false && this.anchors.length ) { | |
13915 active = 0; | |
13916 } | |
13917 | |
13918 return active; | |
13919 }, | |
13920 | |
13921 _getCreateEventData: function() { | |
13922 return { | |
13923 tab: this.active, | |
13924 panel: !this.active.length ? $() : this._getPanelForTab( this.active ) | |
13925 }; | |
13926 }, | |
13927 | |
13928 _tabKeydown: function( event ) { | |
13929 var focusedTab = $( this.document[0].activeElement ).closest( "li" ), | |
13930 selectedIndex = this.tabs.index( focusedTab ), | |
13931 goingForward = true; | |
13932 | |
13933 if ( this._handlePageNav( event ) ) { | |
13934 return; | |
13935 } | |
13936 | |
13937 switch ( event.keyCode ) { | |
13938 case $.ui.keyCode.RIGHT: | |
13939 case $.ui.keyCode.DOWN: | |
13940 selectedIndex++; | |
13941 break; | |
13942 case $.ui.keyCode.UP: | |
13943 case $.ui.keyCode.LEFT: | |
13944 goingForward = false; | |
13945 selectedIndex--; | |
13946 break; | |
13947 case $.ui.keyCode.END: | |
13948 selectedIndex = this.anchors.length - 1; | |
13949 break; | |
13950 case $.ui.keyCode.HOME: | |
13951 selectedIndex = 0; | |
13952 break; | |
13953 case $.ui.keyCode.SPACE: | |
13954 // Activate only, no collapsing | |
13955 event.preventDefault(); | |
13956 clearTimeout( this.activating ); | |
13957 this._activate( selectedIndex ); | |
13958 return; | |
13959 case $.ui.keyCode.ENTER: | |
13960 // Toggle (cancel delayed activation, allow collapsing) | |
13961 event.preventDefault(); | |
13962 clearTimeout( this.activating ); | |
13963 // Determine if we should collapse or activate | |
13964 this._activate( selectedIndex === this.options.active ? false : selectedIndex ); | |
13965 return; | |
13966 default: | |
13967 return; | |
13968 } | |
13969 | |
13970 // Focus the appropriate tab, based on which key was pressed | |
13971 event.preventDefault(); | |
13972 clearTimeout( this.activating ); | |
13973 selectedIndex = this._focusNextTab( selectedIndex, goingForward ); | |
13974 | |
13975 // Navigating with control key will prevent automatic activation | |
13976 if ( !event.ctrlKey ) { | |
13977 // Update aria-selected immediately so that AT think the tab is already selected. | |
13978 // Otherwise AT may confuse the user by stating that they need to activate the tab, | |
13979 // but the tab will already be activated by the time the announcement finishes. | |
13980 focusedTab.attr( "aria-selected", "false" ); | |
13981 this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" ); | |
13982 | |
13983 this.activating = this._delay(function() { | |
13984 this.option( "active", selectedIndex ); | |
13985 }, this.delay ); | |
13986 } | |
13987 }, | |
13988 | |
13989 _panelKeydown: function( event ) { | |
13990 if ( this._handlePageNav( event ) ) { | |
13991 return; | |
13992 } | |
13993 | |
13994 // Ctrl+up moves focus to the current tab | |
13995 if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) { | |
13996 event.preventDefault(); | |
13997 this.active.focus(); | |
13998 } | |
13999 }, | |
14000 | |
14001 // Alt+page up/down moves focus to the previous/next tab (and activates) | |
14002 _handlePageNav: function( event ) { | |
14003 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) { | |
14004 this._activate( this._focusNextTab( this.options.active - 1, false ) ); | |
14005 return true; | |
14006 } | |
14007 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) { | |
14008 this._activate( this._focusNextTab( this.options.active + 1, true ) ); | |
14009 return true; | |
14010 } | |
14011 }, | |
14012 | |
14013 _findNextTab: function( index, goingForward ) { | |
14014 var lastTabIndex = this.tabs.length - 1; | |
14015 | |
14016 function constrain() { | |
14017 if ( index > lastTabIndex ) { | |
14018 index = 0; | |
14019 } | |
14020 if ( index < 0 ) { | |
14021 index = lastTabIndex; | |
14022 } | |
14023 return index; | |
14024 } | |
14025 | |
14026 while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) { | |
14027 index = goingForward ? index + 1 : index - 1; | |
14028 } | |
14029 | |
14030 return index; | |
14031 }, | |
14032 | |
14033 _focusNextTab: function( index, goingForward ) { | |
14034 index = this._findNextTab( index, goingForward ); | |
14035 this.tabs.eq( index ).focus(); | |
14036 return index; | |
14037 }, | |
14038 | |
14039 _setOption: function( key, value ) { | |
14040 if ( key === "active" ) { | |
14041 // _activate() will handle invalid values and update this.options | |
14042 this._activate( value ); | |
14043 return; | |
14044 } | |
14045 | |
14046 if ( key === "disabled" ) { | |
14047 // don't use the widget factory's disabled handling | |
14048 this._setupDisabled( value ); | |
14049 return; | |
14050 } | |
14051 | |
14052 this._super( key, value); | |
14053 | |
14054 if ( key === "collapsible" ) { | |
14055 this.element.toggleClass( "ui-tabs-collapsible", value ); | |
14056 // Setting collapsible: false while collapsed; open first panel | |
14057 if ( !value && this.options.active === false ) { | |
14058 this._activate( 0 ); | |
14059 } | |
14060 } | |
14061 | |
14062 if ( key === "event" ) { | |
14063 this._setupEvents( value ); | |
14064 } | |
14065 | |
14066 if ( key === "heightStyle" ) { | |
14067 this._setupHeightStyle( value ); | |
14068 } | |
14069 }, | |
14070 | |
14071 _tabId: function( tab ) { | |
14072 return tab.attr( "aria-controls" ) || "ui-tabs-" + getNextTabId(); | |
14073 }, | |
14074 | |
14075 _sanitizeSelector: function( hash ) { | |
14076 return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : ""; | |
14077 }, | |
14078 | |
14079 refresh: function() { | |
14080 var options = this.options, | |
14081 lis = this.tablist.children( ":has(a[href])" ); | |
14082 | |
14083 // get disabled tabs from class attribute from HTML | |
14084 // this will get converted to a boolean if needed in _refresh() | |
14085 options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) { | |
14086 return lis.index( tab ); | |
14087 }); | |
14088 | |
14089 this._processTabs(); | |
14090 | |
14091 // was collapsed or no tabs | |
14092 if ( options.active === false || !this.anchors.length ) { | |
14093 options.active = false; | |
14094 this.active = $(); | |
14095 // was active, but active tab is gone | |
14096 } else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) { | |
14097 // all remaining tabs are disabled | |
14098 if ( this.tabs.length === options.disabled.length ) { | |
14099 options.active = false; | |
14100 this.active = $(); | |
14101 // activate previous tab | |
14102 } else { | |
14103 this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) ); | |
14104 } | |
14105 // was active, active tab still exists | |
14106 } else { | |
14107 // make sure active index is correct | |
14108 options.active = this.tabs.index( this.active ); | |
14109 } | |
14110 | |
14111 this._refresh(); | |
14112 }, | |
14113 | |
14114 _refresh: function() { | |
14115 this._setupDisabled( this.options.disabled ); | |
14116 this._setupEvents( this.options.event ); | |
14117 this._setupHeightStyle( this.options.heightStyle ); | |
14118 | |
14119 this.tabs.not( this.active ).attr({ | |
14120 "aria-selected": "false", | |
14121 tabIndex: -1 | |
14122 }); | |
14123 this.panels.not( this._getPanelForTab( this.active ) ) | |
14124 .hide() | |
14125 .attr({ | |
14126 "aria-expanded": "false", | |
14127 "aria-hidden": "true" | |
14128 }); | |
14129 | |
14130 // Make sure one tab is in the tab order | |
14131 if ( !this.active.length ) { | |
14132 this.tabs.eq( 0 ).attr( "tabIndex", 0 ); | |
14133 } else { | |
14134 this.active | |
14135 .addClass( "ui-tabs-active ui-state-active" ) | |
14136 .attr({ | |
14137 "aria-selected": "true", | |
14138 tabIndex: 0 | |
14139 }); | |
14140 this._getPanelForTab( this.active ) | |
14141 .show() | |
14142 .attr({ | |
14143 "aria-expanded": "true", | |
14144 "aria-hidden": "false" | |
14145 }); | |
14146 } | |
14147 }, | |
14148 | |
14149 _processTabs: function() { | |
14150 var that = this; | |
14151 | |
14152 this.tablist = this._getList() | |
14153 .addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ) | |
14154 .attr( "role", "tablist" ); | |
14155 | |
14156 this.tabs = this.tablist.find( "> li:has(a[href])" ) | |
14157 .addClass( "ui-state-default ui-corner-top" ) | |
14158 .attr({ | |
14159 role: "tab", | |
14160 tabIndex: -1 | |
14161 }); | |
14162 | |
14163 this.anchors = this.tabs.map(function() { | |
14164 return $( "a", this )[ 0 ]; | |
14165 }) | |
14166 .addClass( "ui-tabs-anchor" ) | |
14167 .attr({ | |
14168 role: "presentation", | |
14169 tabIndex: -1 | |
14170 }); | |
14171 | |
14172 this.panels = $(); | |
14173 | |
14174 this.anchors.each(function( i, anchor ) { | |
14175 var selector, panel, panelId, | |
14176 anchorId = $( anchor ).uniqueId().attr( "id" ), | |
14177 tab = $( anchor ).closest( "li" ), | |
14178 originalAriaControls = tab.attr( "aria-controls" ); | |
14179 | |
14180 // inline tab | |
14181 if ( isLocal( anchor ) ) { | |
14182 selector = anchor.hash; | |
14183 panel = that.element.find( that._sanitizeSelector( selector ) ); | |
14184 // remote tab | |
14185 } else { | |
14186 panelId = that._tabId( tab ); | |
14187 selector = "#" + panelId; | |
14188 panel = that.element.find( selector ); | |
14189 if ( !panel.length ) { | |
14190 panel = that._createPanel( panelId ); | |
14191 panel.insertAfter( that.panels[ i - 1 ] || that.tablist ); | |
14192 } | |
14193 panel.attr( "aria-live", "polite" ); | |
14194 } | |
14195 | |
14196 if ( panel.length) { | |
14197 that.panels = that.panels.add( panel ); | |
14198 } | |
14199 if ( originalAriaControls ) { | |
14200 tab.data( "ui-tabs-aria-controls", originalAriaControls ); | |
14201 } | |
14202 tab.attr({ | |
14203 "aria-controls": selector.substring( 1 ), | |
14204 "aria-labelledby": anchorId | |
14205 }); | |
14206 panel.attr( "aria-labelledby", anchorId ); | |
14207 }); | |
14208 | |
14209 this.panels | |
14210 .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) | |
14211 .attr( "role", "tabpanel" ); | |
14212 }, | |
14213 | |
14214 // allow overriding how to find the list for rare usage scenarios (#7715) | |
14215 _getList: function() { | |
14216 return this.tablist || this.element.find( "ol,ul" ).eq( 0 ); | |
14217 }, | |
14218 | |
14219 _createPanel: function( id ) { | |
14220 return $( "<div>" ) | |
14221 .attr( "id", id ) | |
14222 .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) | |
14223 .data( "ui-tabs-destroy", true ); | |
14224 }, | |
14225 | |
14226 _setupDisabled: function( disabled ) { | |
14227 if ( $.isArray( disabled ) ) { | |
14228 if ( !disabled.length ) { | |
14229 disabled = false; | |
14230 } else if ( disabled.length === this.anchors.length ) { | |
14231 disabled = true; | |
14232 } | |
14233 } | |
14234 | |
14235 // disable tabs | |
14236 for ( var i = 0, li; ( li = this.tabs[ i ] ); i++ ) { | |
14237 if ( disabled === true || $.inArray( i, disabled ) !== -1 ) { | |
14238 $( li ) | |
14239 .addClass( "ui-state-disabled" ) | |
14240 .attr( "aria-disabled", "true" ); | |
14241 } else { | |
14242 $( li ) | |
14243 .removeClass( "ui-state-disabled" ) | |
14244 .removeAttr( "aria-disabled" ); | |
14245 } | |
14246 } | |
14247 | |
14248 this.options.disabled = disabled; | |
14249 }, | |
14250 | |
14251 _setupEvents: function( event ) { | |
14252 var events = { | |
14253 click: function( event ) { | |
14254 event.preventDefault(); | |
14255 } | |
14256 }; | |
14257 if ( event ) { | |
14258 $.each( event.split(" "), function( index, eventName ) { | |
14259 events[ eventName ] = "_eventHandler"; | |
14260 }); | |
14261 } | |
14262 | |
14263 this._off( this.anchors.add( this.tabs ).add( this.panels ) ); | |
14264 this._on( this.anchors, events ); | |
14265 this._on( this.tabs, { keydown: "_tabKeydown" } ); | |
14266 this._on( this.panels, { keydown: "_panelKeydown" } ); | |
14267 | |
14268 this._focusable( this.tabs ); | |
14269 this._hoverable( this.tabs ); | |
14270 }, | |
14271 | |
14272 _setupHeightStyle: function( heightStyle ) { | |
14273 var maxHeight, | |
14274 parent = this.element.parent(); | |
14275 | |
14276 if ( heightStyle === "fill" ) { | |
14277 maxHeight = parent.height(); | |
14278 maxHeight -= this.element.outerHeight() - this.element.height(); | |
14279 | |
14280 this.element.siblings( ":visible" ).each(function() { | |
14281 var elem = $( this ), | |
14282 position = elem.css( "position" ); | |
14283 | |
14284 if ( position === "absolute" || position === "fixed" ) { | |
14285 return; | |
14286 } | |
14287 maxHeight -= elem.outerHeight( true ); | |
14288 }); | |
14289 | |
14290 this.element.children().not( this.panels ).each(function() { | |
14291 maxHeight -= $( this ).outerHeight( true ); | |
14292 }); | |
14293 | |
14294 this.panels.each(function() { | |
14295 $( this ).height( Math.max( 0, maxHeight - | |
14296 $( this ).innerHeight() + $( this ).height() ) ); | |
14297 }) | |
14298 .css( "overflow", "auto" ); | |
14299 } else if ( heightStyle === "auto" ) { | |
14300 maxHeight = 0; | |
14301 this.panels.each(function() { | |
14302 maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() ); | |
14303 }).height( maxHeight ); | |
14304 } | |
14305 }, | |
14306 | |
14307 _eventHandler: function( event ) { | |
14308 var options = this.options, | |
14309 active = this.active, | |
14310 anchor = $( event.currentTarget ), | |
14311 tab = anchor.closest( "li" ), | |
14312 clickedIsActive = tab[ 0 ] === active[ 0 ], | |
14313 collapsing = clickedIsActive && options.collapsible, | |
14314 toShow = collapsing ? $() : this._getPanelForTab( tab ), | |
14315 toHide = !active.length ? $() : this._getPanelForTab( active ), | |
14316 eventData = { | |
14317 oldTab: active, | |
14318 oldPanel: toHide, | |
14319 newTab: collapsing ? $() : tab, | |
14320 newPanel: toShow | |
14321 }; | |
14322 | |
14323 event.preventDefault(); | |
14324 | |
14325 if ( tab.hasClass( "ui-state-disabled" ) || | |
14326 // tab is already loading | |
14327 tab.hasClass( "ui-tabs-loading" ) || | |
14328 // can't switch durning an animation | |
14329 this.running || | |
14330 // click on active header, but not collapsible | |
14331 ( clickedIsActive && !options.collapsible ) || | |
14332 // allow canceling activation | |
14333 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { | |
14334 return; | |
14335 } | |
14336 | |
14337 options.active = collapsing ? false : this.tabs.index( tab ); | |
14338 | |
14339 this.active = clickedIsActive ? $() : tab; | |
14340 if ( this.xhr ) { | |
14341 this.xhr.abort(); | |
14342 } | |
14343 | |
14344 if ( !toHide.length && !toShow.length ) { | |
14345 $.error( "jQuery UI Tabs: Mismatching fragment identifier." ); | |
14346 } | |
14347 | |
14348 if ( toShow.length ) { | |
14349 this.load( this.tabs.index( tab ), event ); | |
14350 } | |
14351 this._toggle( event, eventData ); | |
14352 }, | |
14353 | |
14354 // handles show/hide for selecting tabs | |
14355 _toggle: function( event, eventData ) { | |
14356 var that = this, | |
14357 toShow = eventData.newPanel, | |
14358 toHide = eventData.oldPanel; | |
14359 | |
14360 this.running = true; | |
14361 | |
14362 function complete() { | |
14363 that.running = false; | |
14364 that._trigger( "activate", event, eventData ); | |
14365 } | |
14366 | |
14367 function show() { | |
14368 eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" ); | |
14369 | |
14370 if ( toShow.length && that.options.show ) { | |
14371 that._show( toShow, that.options.show, complete ); | |
14372 } else { | |
14373 toShow.show(); | |
14374 complete(); | |
14375 } | |
14376 } | |
14377 | |
14378 // start out by hiding, then showing, then completing | |
14379 if ( toHide.length && this.options.hide ) { | |
14380 this._hide( toHide, this.options.hide, function() { | |
14381 eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" ); | |
14382 show(); | |
14383 }); | |
14384 } else { | |
14385 eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" ); | |
14386 toHide.hide(); | |
14387 show(); | |
14388 } | |
14389 | |
14390 toHide.attr({ | |
14391 "aria-expanded": "false", | |
14392 "aria-hidden": "true" | |
14393 }); | |
14394 eventData.oldTab.attr( "aria-selected", "false" ); | |
14395 // If we're switching tabs, remove the old tab from the tab order. | |
14396 // If we're opening from collapsed state, remove the previous tab from the tab order. | |
14397 // If we're collapsing, then keep the collapsing tab in the tab order. | |
14398 if ( toShow.length && toHide.length ) { | |
14399 eventData.oldTab.attr( "tabIndex", -1 ); | |
14400 } else if ( toShow.length ) { | |
14401 this.tabs.filter(function() { | |
14402 return $( this ).attr( "tabIndex" ) === 0; | |
14403 }) | |
14404 .attr( "tabIndex", -1 ); | |
14405 } | |
14406 | |
14407 toShow.attr({ | |
14408 "aria-expanded": "true", | |
14409 "aria-hidden": "false" | |
14410 }); | |
14411 eventData.newTab.attr({ | |
14412 "aria-selected": "true", | |
14413 tabIndex: 0 | |
14414 }); | |
14415 }, | |
14416 | |
14417 _activate: function( index ) { | |
14418 var anchor, | |
14419 active = this._findActive( index ); | |
14420 | |
14421 // trying to activate the already active panel | |
14422 if ( active[ 0 ] === this.active[ 0 ] ) { | |
14423 return; | |
14424 } | |
14425 | |
14426 // trying to collapse, simulate a click on the current active header | |
14427 if ( !active.length ) { | |
14428 active = this.active; | |
14429 } | |
14430 | |
14431 anchor = active.find( ".ui-tabs-anchor" )[ 0 ]; | |
14432 this._eventHandler({ | |
14433 target: anchor, | |
14434 currentTarget: anchor, | |
14435 preventDefault: $.noop | |
14436 }); | |
14437 }, | |
14438 | |
14439 _findActive: function( index ) { | |
14440 return index === false ? $() : this.tabs.eq( index ); | |
14441 }, | |
14442 | |
14443 _getIndex: function( index ) { | |
14444 // meta-function to give users option to provide a href string instead of a numerical index. | |
14445 if ( typeof index === "string" ) { | |
14446 index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) ); | |
14447 } | |
14448 | |
14449 return index; | |
14450 }, | |
14451 | |
14452 _destroy: function() { | |
14453 if ( this.xhr ) { | |
14454 this.xhr.abort(); | |
14455 } | |
14456 | |
14457 this.element.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" ); | |
14458 | |
14459 this.tablist | |
14460 .removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ) | |
14461 .removeAttr( "role" ); | |
14462 | |
14463 this.anchors | |
14464 .removeClass( "ui-tabs-anchor" ) | |
14465 .removeAttr( "role" ) | |
14466 .removeAttr( "tabIndex" ) | |
14467 .removeUniqueId(); | |
14468 | |
14469 this.tabs.add( this.panels ).each(function() { | |
14470 if ( $.data( this, "ui-tabs-destroy" ) ) { | |
14471 $( this ).remove(); | |
14472 } else { | |
14473 $( this ) | |
14474 .removeClass( "ui-state-default ui-state-active ui-state-disabled " + | |
14475 "ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel" ) | |
14476 .removeAttr( "tabIndex" ) | |
14477 .removeAttr( "aria-live" ) | |
14478 .removeAttr( "aria-busy" ) | |
14479 .removeAttr( "aria-selected" ) | |
14480 .removeAttr( "aria-labelledby" ) | |
14481 .removeAttr( "aria-hidden" ) | |
14482 .removeAttr( "aria-expanded" ) | |
14483 .removeAttr( "role" ); | |
14484 } | |
14485 }); | |
14486 | |
14487 this.tabs.each(function() { | |
14488 var li = $( this ), | |
14489 prev = li.data( "ui-tabs-aria-controls" ); | |
14490 if ( prev ) { | |
14491 li | |
14492 .attr( "aria-controls", prev ) | |
14493 .removeData( "ui-tabs-aria-controls" ); | |
14494 } else { | |
14495 li.removeAttr( "aria-controls" ); | |
14496 } | |
14497 }); | |
14498 | |
14499 this.panels.show(); | |
14500 | |
14501 if ( this.options.heightStyle !== "content" ) { | |
14502 this.panels.css( "height", "" ); | |
14503 } | |
14504 }, | |
14505 | |
14506 enable: function( index ) { | |
14507 var disabled = this.options.disabled; | |
14508 if ( disabled === false ) { | |
14509 return; | |
14510 } | |
14511 | |
14512 if ( index === undefined ) { | |
14513 disabled = false; | |
14514 } else { | |
14515 index = this._getIndex( index ); | |
14516 if ( $.isArray( disabled ) ) { | |
14517 disabled = $.map( disabled, function( num ) { | |
14518 return num !== index ? num : null; | |
14519 }); | |
14520 } else { | |
14521 disabled = $.map( this.tabs, function( li, num ) { | |
14522 return num !== index ? num : null; | |
14523 }); | |
14524 } | |
14525 } | |
14526 this._setupDisabled( disabled ); | |
14527 }, | |
14528 | |
14529 disable: function( index ) { | |
14530 var disabled = this.options.disabled; | |
14531 if ( disabled === true ) { | |
14532 return; | |
14533 } | |
14534 | |
14535 if ( index === undefined ) { | |
14536 disabled = true; | |
14537 } else { | |
14538 index = this._getIndex( index ); | |
14539 if ( $.inArray( index, disabled ) !== -1 ) { | |
14540 return; | |
14541 } | |
14542 if ( $.isArray( disabled ) ) { | |
14543 disabled = $.merge( [ index ], disabled ).sort(); | |
14544 } else { | |
14545 disabled = [ index ]; | |
14546 } | |
14547 } | |
14548 this._setupDisabled( disabled ); | |
14549 }, | |
14550 | |
14551 load: function( index, event ) { | |
14552 index = this._getIndex( index ); | |
14553 var that = this, | |
14554 tab = this.tabs.eq( index ), | |
14555 anchor = tab.find( ".ui-tabs-anchor" ), | |
14556 panel = this._getPanelForTab( tab ), | |
14557 eventData = { | |
14558 tab: tab, | |
14559 panel: panel | |
14560 }; | |
14561 | |
14562 // not remote | |
14563 if ( isLocal( anchor[ 0 ] ) ) { | |
14564 return; | |
14565 } | |
14566 | |
14567 this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) ); | |
14568 | |
14569 // support: jQuery <1.8 | |
14570 // jQuery <1.8 returns false if the request is canceled in beforeSend, | |
14571 // but as of 1.8, $.ajax() always returns a jqXHR object. | |
14572 if ( this.xhr && this.xhr.statusText !== "canceled" ) { | |
14573 tab.addClass( "ui-tabs-loading" ); | |
14574 panel.attr( "aria-busy", "true" ); | |
14575 | |
14576 this.xhr | |
14577 .success(function( response ) { | |
14578 // support: jQuery <1.8 | |
14579 // http://bugs.jquery.com/ticket/11778 | |
14580 setTimeout(function() { | |
14581 panel.html( response ); | |
14582 that._trigger( "load", event, eventData ); | |
14583 }, 1 ); | |
14584 }) | |
14585 .complete(function( jqXHR, status ) { | |
14586 // support: jQuery <1.8 | |
14587 // http://bugs.jquery.com/ticket/11778 | |
14588 setTimeout(function() { | |
14589 if ( status === "abort" ) { | |
14590 that.panels.stop( false, true ); | |
14591 } | |
14592 | |
14593 tab.removeClass( "ui-tabs-loading" ); | |
14594 panel.removeAttr( "aria-busy" ); | |
14595 | |
14596 if ( jqXHR === that.xhr ) { | |
14597 delete that.xhr; | |
14598 } | |
14599 }, 1 ); | |
14600 }); | |
14601 } | |
14602 }, | |
14603 | |
14604 _ajaxSettings: function( anchor, event, eventData ) { | |
14605 var that = this; | |
14606 return { | |
14607 url: anchor.attr( "href" ), | |
14608 beforeSend: function( jqXHR, settings ) { | |
14609 return that._trigger( "beforeLoad", event, | |
14610 $.extend( { jqXHR : jqXHR, ajaxSettings: settings }, eventData ) ); | |
14611 } | |
14612 }; | |
14613 }, | |
14614 | |
14615 _getPanelForTab: function( tab ) { | |
14616 var id = $( tab ).attr( "aria-controls" ); | |
14617 return this.element.find( this._sanitizeSelector( "#" + id ) ); | |
14618 } | |
14619 }); | |
14620 | |
14621 })( jQuery ); | |
14622 (function( $ ) { | |
14623 | |
14624 var increments = 0; | |
14625 | |
14626 function addDescribedBy( elem, id ) { | |
14627 var describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ); | |
14628 describedby.push( id ); | |
14629 elem | |
14630 .data( "ui-tooltip-id", id ) | |
14631 .attr( "aria-describedby", $.trim( describedby.join( " " ) ) ); | |
14632 } | |
14633 | |
14634 function removeDescribedBy( elem ) { | |
14635 var id = elem.data( "ui-tooltip-id" ), | |
14636 describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ), | |
14637 index = $.inArray( id, describedby ); | |
14638 if ( index !== -1 ) { | |
14639 describedby.splice( index, 1 ); | |
14640 } | |
14641 | |
14642 elem.removeData( "ui-tooltip-id" ); | |
14643 describedby = $.trim( describedby.join( " " ) ); | |
14644 if ( describedby ) { | |
14645 elem.attr( "aria-describedby", describedby ); | |
14646 } else { | |
14647 elem.removeAttr( "aria-describedby" ); | |
14648 } | |
14649 } | |
14650 | |
14651 $.widget( "ui.tooltip", { | |
14652 version: "1.10.4", | |
14653 options: { | |
14654 content: function() { | |
14655 // support: IE<9, Opera in jQuery <1.7 | |
14656 // .text() can't accept undefined, so coerce to a string | |
14657 var title = $( this ).attr( "title" ) || ""; | |
14658 // Escape title, since we're going from an attribute to raw HTML | |
14659 return $( "<a>" ).text( title ).html(); | |
14660 }, | |
14661 hide: true, | |
14662 // Disabled elements have inconsistent behavior across browsers (#8661) | |
14663 items: "[title]:not([disabled])", | |
14664 position: { | |
14665 my: "left top+15", | |
14666 at: "left bottom", | |
14667 collision: "flipfit flip" | |
14668 }, | |
14669 show: true, | |
14670 tooltipClass: null, | |
14671 track: false, | |
14672 | |
14673 // callbacks | |
14674 close: null, | |
14675 open: null | |
14676 }, | |
14677 | |
14678 _create: function() { | |
14679 this._on({ | |
14680 mouseover: "open", | |
14681 focusin: "open" | |
14682 }); | |
14683 | |
14684 // IDs of generated tooltips, needed for destroy | |
14685 this.tooltips = {}; | |
14686 // IDs of parent tooltips where we removed the title attribute | |
14687 this.parents = {}; | |
14688 | |
14689 if ( this.options.disabled ) { | |
14690 this._disable(); | |
14691 } | |
14692 }, | |
14693 | |
14694 _setOption: function( key, value ) { | |
14695 var that = this; | |
14696 | |
14697 if ( key === "disabled" ) { | |
14698 this[ value ? "_disable" : "_enable" ](); | |
14699 this.options[ key ] = value; | |
14700 // disable element style changes | |
14701 return; | |
14702 } | |
14703 | |
14704 this._super( key, value ); | |
14705 | |
14706 if ( key === "content" ) { | |
14707 $.each( this.tooltips, function( id, element ) { | |
14708 that._updateContent( element ); | |
14709 }); | |
14710 } | |
14711 }, | |
14712 | |
14713 _disable: function() { | |
14714 var that = this; | |
14715 | |
14716 // close open tooltips | |
14717 $.each( this.tooltips, function( id, element ) { | |
14718 var event = $.Event( "blur" ); | |
14719 event.target = event.currentTarget = element[0]; | |
14720 that.close( event, true ); | |
14721 }); | |
14722 | |
14723 // remove title attributes to prevent native tooltips | |
14724 this.element.find( this.options.items ).addBack().each(function() { | |
14725 var element = $( this ); | |
14726 if ( element.is( "[title]" ) ) { | |
14727 element | |
14728 .data( "ui-tooltip-title", element.attr( "title" ) ) | |
14729 .attr( "title", "" ); | |
14730 } | |
14731 }); | |
14732 }, | |
14733 | |
14734 _enable: function() { | |
14735 // restore title attributes | |
14736 this.element.find( this.options.items ).addBack().each(function() { | |
14737 var element = $( this ); | |
14738 if ( element.data( "ui-tooltip-title" ) ) { | |
14739 element.attr( "title", element.data( "ui-tooltip-title" ) ); | |
14740 } | |
14741 }); | |
14742 }, | |
14743 | |
14744 open: function( event ) { | |
14745 var that = this, | |
14746 target = $( event ? event.target : this.element ) | |
14747 // we need closest here due to mouseover bubbling, | |
14748 // but always pointing at the same event target | |
14749 .closest( this.options.items ); | |
14750 | |
14751 // No element to show a tooltip for or the tooltip is already open | |
14752 if ( !target.length || target.data( "ui-tooltip-id" ) ) { | |
14753 return; | |
14754 } | |
14755 | |
14756 if ( target.attr( "title" ) ) { | |
14757 target.data( "ui-tooltip-title", target.attr( "title" ) ); | |
14758 } | |
14759 | |
14760 target.data( "ui-tooltip-open", true ); | |
14761 | |
14762 // kill parent tooltips, custom or native, for hover | |
14763 if ( event && event.type === "mouseover" ) { | |
14764 target.parents().each(function() { | |
14765 var parent = $( this ), | |
14766 blurEvent; | |
14767 if ( parent.data( "ui-tooltip-open" ) ) { | |
14768 blurEvent = $.Event( "blur" ); | |
14769 blurEvent.target = blurEvent.currentTarget = this; | |
14770 that.close( blurEvent, true ); | |
14771 } | |
14772 if ( parent.attr( "title" ) ) { | |
14773 parent.uniqueId(); | |
14774 that.parents[ this.id ] = { | |
14775 element: this, | |
14776 title: parent.attr( "title" ) | |
14777 }; | |
14778 parent.attr( "title", "" ); | |
14779 } | |
14780 }); | |
14781 } | |
14782 | |
14783 this._updateContent( target, event ); | |
14784 }, | |
14785 | |
14786 _updateContent: function( target, event ) { | |
14787 var content, | |
14788 contentOption = this.options.content, | |
14789 that = this, | |
14790 eventType = event ? event.type : null; | |
14791 | |
14792 if ( typeof contentOption === "string" ) { | |
14793 return this._open( event, target, contentOption ); | |
14794 } | |
14795 | |
14796 content = contentOption.call( target[0], function( response ) { | |
14797 // ignore async response if tooltip was closed already | |
14798 if ( !target.data( "ui-tooltip-open" ) ) { | |
14799 return; | |
14800 } | |
14801 // IE may instantly serve a cached response for ajax requests | |
14802 // delay this call to _open so the other call to _open runs first | |
14803 that._delay(function() { | |
14804 // jQuery creates a special event for focusin when it doesn't | |
14805 // exist natively. To improve performance, the native event | |
14806 // object is reused and the type is changed. Therefore, we can't | |
14807 // rely on the type being correct after the event finished | |
14808 // bubbling, so we set it back to the previous value. (#8740) | |
14809 if ( event ) { | |
14810 event.type = eventType; | |
14811 } | |
14812 this._open( event, target, response ); | |
14813 }); | |
14814 }); | |
14815 if ( content ) { | |
14816 this._open( event, target, content ); | |
14817 } | |
14818 }, | |
14819 | |
14820 _open: function( event, target, content ) { | |
14821 var tooltip, events, delayedShow, | |
14822 positionOption = $.extend( {}, this.options.position ); | |
14823 | |
14824 if ( !content ) { | |
14825 return; | |
14826 } | |
14827 | |
14828 // Content can be updated multiple times. If the tooltip already | |
14829 // exists, then just update the content and bail. | |
14830 tooltip = this._find( target ); | |
14831 if ( tooltip.length ) { | |
14832 tooltip.find( ".ui-tooltip-content" ).html( content ); | |
14833 return; | |
14834 } | |
14835 | |
14836 // if we have a title, clear it to prevent the native tooltip | |
14837 // we have to check first to avoid defining a title if none exists | |
14838 // (we don't want to cause an element to start matching [title]) | |
14839 // | |
14840 // We use removeAttr only for key events, to allow IE to export the correct | |
14841 // accessible attributes. For mouse events, set to empty string to avoid | |
14842 // native tooltip showing up (happens only when removing inside mouseover). | |
14843 if ( target.is( "[title]" ) ) { | |
14844 if ( event && event.type === "mouseover" ) { | |
14845 target.attr( "title", "" ); | |
14846 } else { | |
14847 target.removeAttr( "title" ); | |
14848 } | |
14849 } | |
14850 | |
14851 tooltip = this._tooltip( target ); | |
14852 addDescribedBy( target, tooltip.attr( "id" ) ); | |
14853 tooltip.find( ".ui-tooltip-content" ).html( content ); | |
14854 | |
14855 function position( event ) { | |
14856 positionOption.of = event; | |
14857 if ( tooltip.is( ":hidden" ) ) { | |
14858 return; | |
14859 } | |
14860 tooltip.position( positionOption ); | |
14861 } | |
14862 if ( this.options.track && event && /^mouse/.test( event.type ) ) { | |
14863 this._on( this.document, { | |
14864 mousemove: position | |
14865 }); | |
14866 // trigger once to override element-relative positioning | |
14867 position( event ); | |
14868 } else { | |
14869 tooltip.position( $.extend({ | |
14870 of: target | |
14871 }, this.options.position ) ); | |
14872 } | |
14873 | |
14874 tooltip.hide(); | |
14875 | |
14876 this._show( tooltip, this.options.show ); | |
14877 // Handle tracking tooltips that are shown with a delay (#8644). As soon | |
14878 // as the tooltip is visible, position the tooltip using the most recent | |
14879 // event. | |
14880 if ( this.options.show && this.options.show.delay ) { | |
14881 delayedShow = this.delayedShow = setInterval(function() { | |
14882 if ( tooltip.is( ":visible" ) ) { | |
14883 position( positionOption.of ); | |
14884 clearInterval( delayedShow ); | |
14885 } | |
14886 }, $.fx.interval ); | |
14887 } | |
14888 | |
14889 this._trigger( "open", event, { tooltip: tooltip } ); | |
14890 | |
14891 events = { | |
14892 keyup: function( event ) { | |
14893 if ( event.keyCode === $.ui.keyCode.ESCAPE ) { | |
14894 var fakeEvent = $.Event(event); | |
14895 fakeEvent.currentTarget = target[0]; | |
14896 this.close( fakeEvent, true ); | |
14897 } | |
14898 }, | |
14899 remove: function() { | |
14900 this._removeTooltip( tooltip ); | |
14901 } | |
14902 }; | |
14903 if ( !event || event.type === "mouseover" ) { | |
14904 events.mouseleave = "close"; | |
14905 } | |
14906 if ( !event || event.type === "focusin" ) { | |
14907 events.focusout = "close"; | |
14908 } | |
14909 this._on( true, target, events ); | |
14910 }, | |
14911 | |
14912 close: function( event ) { | |
14913 var that = this, | |
14914 target = $( event ? event.currentTarget : this.element ), | |
14915 tooltip = this._find( target ); | |
14916 | |
14917 // disabling closes the tooltip, so we need to track when we're closing | |
14918 // to avoid an infinite loop in case the tooltip becomes disabled on close | |
14919 if ( this.closing ) { | |
14920 return; | |
14921 } | |
14922 | |
14923 // Clear the interval for delayed tracking tooltips | |
14924 clearInterval( this.delayedShow ); | |
14925 | |
14926 // only set title if we had one before (see comment in _open()) | |
14927 if ( target.data( "ui-tooltip-title" ) ) { | |
14928 target.attr( "title", target.data( "ui-tooltip-title" ) ); | |
14929 } | |
14930 | |
14931 removeDescribedBy( target ); | |
14932 | |
14933 tooltip.stop( true ); | |
14934 this._hide( tooltip, this.options.hide, function() { | |
14935 that._removeTooltip( $( this ) ); | |
14936 }); | |
14937 | |
14938 target.removeData( "ui-tooltip-open" ); | |
14939 this._off( target, "mouseleave focusout keyup" ); | |
14940 // Remove 'remove' binding only on delegated targets | |
14941 if ( target[0] !== this.element[0] ) { | |
14942 this._off( target, "remove" ); | |
14943 } | |
14944 this._off( this.document, "mousemove" ); | |
14945 | |
14946 if ( event && event.type === "mouseleave" ) { | |
14947 $.each( this.parents, function( id, parent ) { | |
14948 $( parent.element ).attr( "title", parent.title ); | |
14949 delete that.parents[ id ]; | |
14950 }); | |
14951 } | |
14952 | |
14953 this.closing = true; | |
14954 this._trigger( "close", event, { tooltip: tooltip } ); | |
14955 this.closing = false; | |
14956 }, | |
14957 | |
14958 _tooltip: function( element ) { | |
14959 var id = "ui-tooltip-" + increments++, | |
14960 tooltip = $( "<div>" ) | |
14961 .attr({ | |
14962 id: id, | |
14963 role: "tooltip" | |
14964 }) | |
14965 .addClass( "ui-tooltip ui-widget ui-corner-all ui-widget-content " + | |
14966 ( this.options.tooltipClass || "" ) ); | |
14967 $( "<div>" ) | |
14968 .addClass( "ui-tooltip-content" ) | |
14969 .appendTo( tooltip ); | |
14970 tooltip.appendTo( this.document[0].body ); | |
14971 this.tooltips[ id ] = element; | |
14972 return tooltip; | |
14973 }, | |
14974 | |
14975 _find: function( target ) { | |
14976 var id = target.data( "ui-tooltip-id" ); | |
14977 return id ? $( "#" + id ) : $(); | |
14978 }, | |
14979 | |
14980 _removeTooltip: function( tooltip ) { | |
14981 tooltip.remove(); | |
14982 delete this.tooltips[ tooltip.attr( "id" ) ]; | |
14983 }, | |
14984 | |
14985 _destroy: function() { | |
14986 var that = this; | |
14987 | |
14988 // close open tooltips | |
14989 $.each( this.tooltips, function( id, element ) { | |
14990 // Delegate to close method to handle common cleanup | |
14991 var event = $.Event( "blur" ); | |
14992 event.target = event.currentTarget = element[0]; | |
14993 that.close( event, true ); | |
14994 | |
14995 // Remove immediately; destroying an open tooltip doesn't use the | |
14996 // hide animation | |
14997 $( "#" + id ).remove(); | |
14998 | |
14999 // Restore the title | |
15000 if ( element.data( "ui-tooltip-title" ) ) { | |
15001 element.attr( "title", element.data( "ui-tooltip-title" ) ); | |
15002 element.removeData( "ui-tooltip-title" ); | |
15003 } | |
15004 }); | |
15005 } | |
15006 }); | |
15007 | |
15008 }( jQuery ) ); |