1 /*! jQuery UI - v1.10.4 - 2014-02-09 |
|
2 * http://jqueryui.com |
|
3 * Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.position.js, jquery.ui.draggable.js, jquery.ui.droppable.js, jquery.ui.resizable.js, jquery.ui.selectable.js, jquery.ui.sortable.js, jquery.ui.accordion.js, jquery.ui.autocomplete.js, jquery.ui.button.js, jquery.ui.datepicker.js, jquery.ui.dialog.js, jquery.ui.menu.js, jquery.ui.progressbar.js, jquery.ui.slider.js, jquery.ui.spinner.js, jquery.ui.tabs.js, jquery.ui.tooltip.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 |
|
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 $.widget("ui.draggable", $.ui.mouse, { |
|
1477 version: "1.10.4", |
|
1478 widgetEventPrefix: "drag", |
|
1479 options: { |
|
1480 addClasses: true, |
|
1481 appendTo: "parent", |
|
1482 axis: false, |
|
1483 connectToSortable: false, |
|
1484 containment: false, |
|
1485 cursor: "auto", |
|
1486 cursorAt: false, |
|
1487 grid: false, |
|
1488 handle: false, |
|
1489 helper: "original", |
|
1490 iframeFix: false, |
|
1491 opacity: false, |
|
1492 refreshPositions: false, |
|
1493 revert: false, |
|
1494 revertDuration: 500, |
|
1495 scope: "default", |
|
1496 scroll: true, |
|
1497 scrollSensitivity: 20, |
|
1498 scrollSpeed: 20, |
|
1499 snap: false, |
|
1500 snapMode: "both", |
|
1501 snapTolerance: 20, |
|
1502 stack: false, |
|
1503 zIndex: false, |
|
1504 |
|
1505 // callbacks |
|
1506 drag: null, |
|
1507 start: null, |
|
1508 stop: null |
|
1509 }, |
|
1510 _create: function() { |
|
1511 |
|
1512 if (this.options.helper === "original" && !(/^(?:r|a|f)/).test(this.element.css("position"))) { |
|
1513 this.element[0].style.position = "relative"; |
|
1514 } |
|
1515 if (this.options.addClasses){ |
|
1516 this.element.addClass("ui-draggable"); |
|
1517 } |
|
1518 if (this.options.disabled){ |
|
1519 this.element.addClass("ui-draggable-disabled"); |
|
1520 } |
|
1521 |
|
1522 this._mouseInit(); |
|
1523 |
|
1524 }, |
|
1525 |
|
1526 _destroy: function() { |
|
1527 this.element.removeClass( "ui-draggable ui-draggable-dragging ui-draggable-disabled" ); |
|
1528 this._mouseDestroy(); |
|
1529 }, |
|
1530 |
|
1531 _mouseCapture: function(event) { |
|
1532 |
|
1533 var o = this.options; |
|
1534 |
|
1535 // among others, prevent a drag on a resizable-handle |
|
1536 if (this.helper || o.disabled || $(event.target).closest(".ui-resizable-handle").length > 0) { |
|
1537 return false; |
|
1538 } |
|
1539 |
|
1540 //Quit if we're not on a valid handle |
|
1541 this.handle = this._getHandle(event); |
|
1542 if (!this.handle) { |
|
1543 return false; |
|
1544 } |
|
1545 |
|
1546 $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() { |
|
1547 $("<div class='ui-draggable-iframeFix' style='background: #fff;'></div>") |
|
1548 .css({ |
|
1549 width: this.offsetWidth+"px", height: this.offsetHeight+"px", |
|
1550 position: "absolute", opacity: "0.001", zIndex: 1000 |
|
1551 }) |
|
1552 .css($(this).offset()) |
|
1553 .appendTo("body"); |
|
1554 }); |
|
1555 |
|
1556 return true; |
|
1557 |
|
1558 }, |
|
1559 |
|
1560 _mouseStart: function(event) { |
|
1561 |
|
1562 var o = this.options; |
|
1563 |
|
1564 //Create and append the visible helper |
|
1565 this.helper = this._createHelper(event); |
|
1566 |
|
1567 this.helper.addClass("ui-draggable-dragging"); |
|
1568 |
|
1569 //Cache the helper size |
|
1570 this._cacheHelperProportions(); |
|
1571 |
|
1572 //If ddmanager is used for droppables, set the global draggable |
|
1573 if($.ui.ddmanager) { |
|
1574 $.ui.ddmanager.current = this; |
|
1575 } |
|
1576 |
|
1577 /* |
|
1578 * - Position generation - |
|
1579 * This block generates everything position related - it's the core of draggables. |
|
1580 */ |
|
1581 |
|
1582 //Cache the margins of the original element |
|
1583 this._cacheMargins(); |
|
1584 |
|
1585 //Store the helper's css position |
|
1586 this.cssPosition = this.helper.css( "position" ); |
|
1587 this.scrollParent = this.helper.scrollParent(); |
|
1588 this.offsetParent = this.helper.offsetParent(); |
|
1589 this.offsetParentCssPosition = this.offsetParent.css( "position" ); |
|
1590 |
|
1591 //The element's absolute position on the page minus margins |
|
1592 this.offset = this.positionAbs = this.element.offset(); |
|
1593 this.offset = { |
|
1594 top: this.offset.top - this.margins.top, |
|
1595 left: this.offset.left - this.margins.left |
|
1596 }; |
|
1597 |
|
1598 //Reset scroll cache |
|
1599 this.offset.scroll = false; |
|
1600 |
|
1601 $.extend(this.offset, { |
|
1602 click: { //Where the click happened, relative to the element |
|
1603 left: event.pageX - this.offset.left, |
|
1604 top: event.pageY - this.offset.top |
|
1605 }, |
|
1606 parent: this._getParentOffset(), |
|
1607 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper |
|
1608 }); |
|
1609 |
|
1610 //Generate the original position |
|
1611 this.originalPosition = this.position = this._generatePosition(event); |
|
1612 this.originalPageX = event.pageX; |
|
1613 this.originalPageY = event.pageY; |
|
1614 |
|
1615 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied |
|
1616 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)); |
|
1617 |
|
1618 //Set a containment if given in the options |
|
1619 this._setContainment(); |
|
1620 |
|
1621 //Trigger event + callbacks |
|
1622 if(this._trigger("start", event) === false) { |
|
1623 this._clear(); |
|
1624 return false; |
|
1625 } |
|
1626 |
|
1627 //Recache the helper size |
|
1628 this._cacheHelperProportions(); |
|
1629 |
|
1630 //Prepare the droppable offsets |
|
1631 if ($.ui.ddmanager && !o.dropBehaviour) { |
|
1632 $.ui.ddmanager.prepareOffsets(this, event); |
|
1633 } |
|
1634 |
|
1635 |
|
1636 this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position |
|
1637 |
|
1638 //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003) |
|
1639 if ( $.ui.ddmanager ) { |
|
1640 $.ui.ddmanager.dragStart(this, event); |
|
1641 } |
|
1642 |
|
1643 return true; |
|
1644 }, |
|
1645 |
|
1646 _mouseDrag: function(event, noPropagation) { |
|
1647 // reset any necessary cached properties (see #5009) |
|
1648 if ( this.offsetParentCssPosition === "fixed" ) { |
|
1649 this.offset.parent = this._getParentOffset(); |
|
1650 } |
|
1651 |
|
1652 //Compute the helpers position |
|
1653 this.position = this._generatePosition(event); |
|
1654 this.positionAbs = this._convertPositionTo("absolute"); |
|
1655 |
|
1656 //Call plugins and callbacks and use the resulting position if something is returned |
|
1657 if (!noPropagation) { |
|
1658 var ui = this._uiHash(); |
|
1659 if(this._trigger("drag", event, ui) === false) { |
|
1660 this._mouseUp({}); |
|
1661 return false; |
|
1662 } |
|
1663 this.position = ui.position; |
|
1664 } |
|
1665 |
|
1666 if(!this.options.axis || this.options.axis !== "y") { |
|
1667 this.helper[0].style.left = this.position.left+"px"; |
|
1668 } |
|
1669 if(!this.options.axis || this.options.axis !== "x") { |
|
1670 this.helper[0].style.top = this.position.top+"px"; |
|
1671 } |
|
1672 if($.ui.ddmanager) { |
|
1673 $.ui.ddmanager.drag(this, event); |
|
1674 } |
|
1675 |
|
1676 return false; |
|
1677 }, |
|
1678 |
|
1679 _mouseStop: function(event) { |
|
1680 |
|
1681 //If we are using droppables, inform the manager about the drop |
|
1682 var that = this, |
|
1683 dropped = false; |
|
1684 if ($.ui.ddmanager && !this.options.dropBehaviour) { |
|
1685 dropped = $.ui.ddmanager.drop(this, event); |
|
1686 } |
|
1687 |
|
1688 //if a drop comes from outside (a sortable) |
|
1689 if(this.dropped) { |
|
1690 dropped = this.dropped; |
|
1691 this.dropped = false; |
|
1692 } |
|
1693 |
|
1694 //if the original element is no longer in the DOM don't bother to continue (see #8269) |
|
1695 if ( this.options.helper === "original" && !$.contains( this.element[ 0 ].ownerDocument, this.element[ 0 ] ) ) { |
|
1696 return false; |
|
1697 } |
|
1698 |
|
1699 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))) { |
|
1700 $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() { |
|
1701 if(that._trigger("stop", event) !== false) { |
|
1702 that._clear(); |
|
1703 } |
|
1704 }); |
|
1705 } else { |
|
1706 if(this._trigger("stop", event) !== false) { |
|
1707 this._clear(); |
|
1708 } |
|
1709 } |
|
1710 |
|
1711 return false; |
|
1712 }, |
|
1713 |
|
1714 _mouseUp: function(event) { |
|
1715 //Remove frame helpers |
|
1716 $("div.ui-draggable-iframeFix").each(function() { |
|
1717 this.parentNode.removeChild(this); |
|
1718 }); |
|
1719 |
|
1720 //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003) |
|
1721 if( $.ui.ddmanager ) { |
|
1722 $.ui.ddmanager.dragStop(this, event); |
|
1723 } |
|
1724 |
|
1725 return $.ui.mouse.prototype._mouseUp.call(this, event); |
|
1726 }, |
|
1727 |
|
1728 cancel: function() { |
|
1729 |
|
1730 if(this.helper.is(".ui-draggable-dragging")) { |
|
1731 this._mouseUp({}); |
|
1732 } else { |
|
1733 this._clear(); |
|
1734 } |
|
1735 |
|
1736 return this; |
|
1737 |
|
1738 }, |
|
1739 |
|
1740 _getHandle: function(event) { |
|
1741 return this.options.handle ? |
|
1742 !!$( event.target ).closest( this.element.find( this.options.handle ) ).length : |
|
1743 true; |
|
1744 }, |
|
1745 |
|
1746 _createHelper: function(event) { |
|
1747 |
|
1748 var o = this.options, |
|
1749 helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper === "clone" ? this.element.clone().removeAttr("id") : this.element); |
|
1750 |
|
1751 if(!helper.parents("body").length) { |
|
1752 helper.appendTo((o.appendTo === "parent" ? this.element[0].parentNode : o.appendTo)); |
|
1753 } |
|
1754 |
|
1755 if(helper[0] !== this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) { |
|
1756 helper.css("position", "absolute"); |
|
1757 } |
|
1758 |
|
1759 return helper; |
|
1760 |
|
1761 }, |
|
1762 |
|
1763 _adjustOffsetFromHelper: function(obj) { |
|
1764 if (typeof obj === "string") { |
|
1765 obj = obj.split(" "); |
|
1766 } |
|
1767 if ($.isArray(obj)) { |
|
1768 obj = {left: +obj[0], top: +obj[1] || 0}; |
|
1769 } |
|
1770 if ("left" in obj) { |
|
1771 this.offset.click.left = obj.left + this.margins.left; |
|
1772 } |
|
1773 if ("right" in obj) { |
|
1774 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; |
|
1775 } |
|
1776 if ("top" in obj) { |
|
1777 this.offset.click.top = obj.top + this.margins.top; |
|
1778 } |
|
1779 if ("bottom" in obj) { |
|
1780 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; |
|
1781 } |
|
1782 }, |
|
1783 |
|
1784 _getParentOffset: function() { |
|
1785 |
|
1786 //Get the offsetParent and cache its position |
|
1787 var po = this.offsetParent.offset(); |
|
1788 |
|
1789 // This is a special case where we need to modify a offset calculated on start, since the following happened: |
|
1790 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent |
|
1791 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that |
|
1792 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag |
|
1793 if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) { |
|
1794 po.left += this.scrollParent.scrollLeft(); |
|
1795 po.top += this.scrollParent.scrollTop(); |
|
1796 } |
|
1797 |
|
1798 //This needs to be actually done for all browsers, since pageX/pageY includes this information |
|
1799 //Ugly IE fix |
|
1800 if((this.offsetParent[0] === document.body) || |
|
1801 (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) { |
|
1802 po = { top: 0, left: 0 }; |
|
1803 } |
|
1804 |
|
1805 return { |
|
1806 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0), |
|
1807 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0) |
|
1808 }; |
|
1809 |
|
1810 }, |
|
1811 |
|
1812 _getRelativeOffset: function() { |
|
1813 |
|
1814 if(this.cssPosition === "relative") { |
|
1815 var p = this.element.position(); |
|
1816 return { |
|
1817 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(), |
|
1818 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft() |
|
1819 }; |
|
1820 } else { |
|
1821 return { top: 0, left: 0 }; |
|
1822 } |
|
1823 |
|
1824 }, |
|
1825 |
|
1826 _cacheMargins: function() { |
|
1827 this.margins = { |
|
1828 left: (parseInt(this.element.css("marginLeft"),10) || 0), |
|
1829 top: (parseInt(this.element.css("marginTop"),10) || 0), |
|
1830 right: (parseInt(this.element.css("marginRight"),10) || 0), |
|
1831 bottom: (parseInt(this.element.css("marginBottom"),10) || 0) |
|
1832 }; |
|
1833 }, |
|
1834 |
|
1835 _cacheHelperProportions: function() { |
|
1836 this.helperProportions = { |
|
1837 width: this.helper.outerWidth(), |
|
1838 height: this.helper.outerHeight() |
|
1839 }; |
|
1840 }, |
|
1841 |
|
1842 _setContainment: function() { |
|
1843 |
|
1844 var over, c, ce, |
|
1845 o = this.options; |
|
1846 |
|
1847 if ( !o.containment ) { |
|
1848 this.containment = null; |
|
1849 return; |
|
1850 } |
|
1851 |
|
1852 if ( o.containment === "window" ) { |
|
1853 this.containment = [ |
|
1854 $( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left, |
|
1855 $( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top, |
|
1856 $( window ).scrollLeft() + $( window ).width() - this.helperProportions.width - this.margins.left, |
|
1857 $( window ).scrollTop() + ( $( window ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top |
|
1858 ]; |
|
1859 return; |
|
1860 } |
|
1861 |
|
1862 if ( o.containment === "document") { |
|
1863 this.containment = [ |
|
1864 0, |
|
1865 0, |
|
1866 $( document ).width() - this.helperProportions.width - this.margins.left, |
|
1867 ( $( document ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top |
|
1868 ]; |
|
1869 return; |
|
1870 } |
|
1871 |
|
1872 if ( o.containment.constructor === Array ) { |
|
1873 this.containment = o.containment; |
|
1874 return; |
|
1875 } |
|
1876 |
|
1877 if ( o.containment === "parent" ) { |
|
1878 o.containment = this.helper[ 0 ].parentNode; |
|
1879 } |
|
1880 |
|
1881 c = $( o.containment ); |
|
1882 ce = c[ 0 ]; |
|
1883 |
|
1884 if( !ce ) { |
|
1885 return; |
|
1886 } |
|
1887 |
|
1888 over = c.css( "overflow" ) !== "hidden"; |
|
1889 |
|
1890 this.containment = [ |
|
1891 ( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ), |
|
1892 ( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingTop" ), 10 ) || 0 ) , |
|
1893 ( 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, |
|
1894 ( 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 |
|
1895 ]; |
|
1896 this.relative_container = c; |
|
1897 }, |
|
1898 |
|
1899 _convertPositionTo: function(d, pos) { |
|
1900 |
|
1901 if(!pos) { |
|
1902 pos = this.position; |
|
1903 } |
|
1904 |
|
1905 var mod = d === "absolute" ? 1 : -1, |
|
1906 scroll = this.cssPosition === "absolute" && !( this.scrollParent[ 0 ] !== document && $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ? this.offsetParent : this.scrollParent; |
|
1907 |
|
1908 //Cache the scroll |
|
1909 if (!this.offset.scroll) { |
|
1910 this.offset.scroll = {top : scroll.scrollTop(), left : scroll.scrollLeft()}; |
|
1911 } |
|
1912 |
|
1913 return { |
|
1914 top: ( |
|
1915 pos.top + // The absolute mouse position |
|
1916 this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent |
|
1917 this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border) |
|
1918 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : this.offset.scroll.top ) * mod ) |
|
1919 ), |
|
1920 left: ( |
|
1921 pos.left + // The absolute mouse position |
|
1922 this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent |
|
1923 this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border) |
|
1924 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : this.offset.scroll.left ) * mod ) |
|
1925 ) |
|
1926 }; |
|
1927 |
|
1928 }, |
|
1929 |
|
1930 _generatePosition: function(event) { |
|
1931 |
|
1932 var containment, co, top, left, |
|
1933 o = this.options, |
|
1934 scroll = this.cssPosition === "absolute" && !( this.scrollParent[ 0 ] !== document && $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ? this.offsetParent : this.scrollParent, |
|
1935 pageX = event.pageX, |
|
1936 pageY = event.pageY; |
|
1937 |
|
1938 //Cache the scroll |
|
1939 if (!this.offset.scroll) { |
|
1940 this.offset.scroll = {top : scroll.scrollTop(), left : scroll.scrollLeft()}; |
|
1941 } |
|
1942 |
|
1943 /* |
|
1944 * - Position constraining - |
|
1945 * Constrain the position to a mix of grid, containment. |
|
1946 */ |
|
1947 |
|
1948 // If we are not dragging yet, we won't check for options |
|
1949 if ( this.originalPosition ) { |
|
1950 if ( this.containment ) { |
|
1951 if ( this.relative_container ){ |
|
1952 co = this.relative_container.offset(); |
|
1953 containment = [ |
|
1954 this.containment[ 0 ] + co.left, |
|
1955 this.containment[ 1 ] + co.top, |
|
1956 this.containment[ 2 ] + co.left, |
|
1957 this.containment[ 3 ] + co.top |
|
1958 ]; |
|
1959 } |
|
1960 else { |
|
1961 containment = this.containment; |
|
1962 } |
|
1963 |
|
1964 if(event.pageX - this.offset.click.left < containment[0]) { |
|
1965 pageX = containment[0] + this.offset.click.left; |
|
1966 } |
|
1967 if(event.pageY - this.offset.click.top < containment[1]) { |
|
1968 pageY = containment[1] + this.offset.click.top; |
|
1969 } |
|
1970 if(event.pageX - this.offset.click.left > containment[2]) { |
|
1971 pageX = containment[2] + this.offset.click.left; |
|
1972 } |
|
1973 if(event.pageY - this.offset.click.top > containment[3]) { |
|
1974 pageY = containment[3] + this.offset.click.top; |
|
1975 } |
|
1976 } |
|
1977 |
|
1978 if(o.grid) { |
|
1979 //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950) |
|
1980 top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY; |
|
1981 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; |
|
1982 |
|
1983 left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX; |
|
1984 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; |
|
1985 } |
|
1986 |
|
1987 } |
|
1988 |
|
1989 return { |
|
1990 top: ( |
|
1991 pageY - // The absolute mouse position |
|
1992 this.offset.click.top - // Click offset (relative to the element) |
|
1993 this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent |
|
1994 this.offset.parent.top + // The offsetParent's offset without borders (offset + border) |
|
1995 ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : this.offset.scroll.top ) |
|
1996 ), |
|
1997 left: ( |
|
1998 pageX - // The absolute mouse position |
|
1999 this.offset.click.left - // Click offset (relative to the element) |
|
2000 this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent |
|
2001 this.offset.parent.left + // The offsetParent's offset without borders (offset + border) |
|
2002 ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : this.offset.scroll.left ) |
|
2003 ) |
|
2004 }; |
|
2005 |
|
2006 }, |
|
2007 |
|
2008 _clear: function() { |
|
2009 this.helper.removeClass("ui-draggable-dragging"); |
|
2010 if(this.helper[0] !== this.element[0] && !this.cancelHelperRemoval) { |
|
2011 this.helper.remove(); |
|
2012 } |
|
2013 this.helper = null; |
|
2014 this.cancelHelperRemoval = false; |
|
2015 }, |
|
2016 |
|
2017 // From now on bulk stuff - mainly helpers |
|
2018 |
|
2019 _trigger: function(type, event, ui) { |
|
2020 ui = ui || this._uiHash(); |
|
2021 $.ui.plugin.call(this, type, [event, ui]); |
|
2022 //The absolute position has to be recalculated after plugins |
|
2023 if(type === "drag") { |
|
2024 this.positionAbs = this._convertPositionTo("absolute"); |
|
2025 } |
|
2026 return $.Widget.prototype._trigger.call(this, type, event, ui); |
|
2027 }, |
|
2028 |
|
2029 plugins: {}, |
|
2030 |
|
2031 _uiHash: function() { |
|
2032 return { |
|
2033 helper: this.helper, |
|
2034 position: this.position, |
|
2035 originalPosition: this.originalPosition, |
|
2036 offset: this.positionAbs |
|
2037 }; |
|
2038 } |
|
2039 |
|
2040 }); |
|
2041 |
|
2042 $.ui.plugin.add("draggable", "connectToSortable", { |
|
2043 start: function(event, ui) { |
|
2044 |
|
2045 var inst = $(this).data("ui-draggable"), o = inst.options, |
|
2046 uiSortable = $.extend({}, ui, { item: inst.element }); |
|
2047 inst.sortables = []; |
|
2048 $(o.connectToSortable).each(function() { |
|
2049 var sortable = $.data(this, "ui-sortable"); |
|
2050 if (sortable && !sortable.options.disabled) { |
|
2051 inst.sortables.push({ |
|
2052 instance: sortable, |
|
2053 shouldRevert: sortable.options.revert |
|
2054 }); |
|
2055 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). |
|
2056 sortable._trigger("activate", event, uiSortable); |
|
2057 } |
|
2058 }); |
|
2059 |
|
2060 }, |
|
2061 stop: function(event, ui) { |
|
2062 |
|
2063 //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper |
|
2064 var inst = $(this).data("ui-draggable"), |
|
2065 uiSortable = $.extend({}, ui, { item: inst.element }); |
|
2066 |
|
2067 $.each(inst.sortables, function() { |
|
2068 if(this.instance.isOver) { |
|
2069 |
|
2070 this.instance.isOver = 0; |
|
2071 |
|
2072 inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance |
|
2073 this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work) |
|
2074 |
|
2075 //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: "valid/invalid" |
|
2076 if(this.shouldRevert) { |
|
2077 this.instance.options.revert = this.shouldRevert; |
|
2078 } |
|
2079 |
|
2080 //Trigger the stop of the sortable |
|
2081 this.instance._mouseStop(event); |
|
2082 |
|
2083 this.instance.options.helper = this.instance.options._helper; |
|
2084 |
|
2085 //If the helper has been the original item, restore properties in the sortable |
|
2086 if(inst.options.helper === "original") { |
|
2087 this.instance.currentItem.css({ top: "auto", left: "auto" }); |
|
2088 } |
|
2089 |
|
2090 } else { |
|
2091 this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance |
|
2092 this.instance._trigger("deactivate", event, uiSortable); |
|
2093 } |
|
2094 |
|
2095 }); |
|
2096 |
|
2097 }, |
|
2098 drag: function(event, ui) { |
|
2099 |
|
2100 var inst = $(this).data("ui-draggable"), that = this; |
|
2101 |
|
2102 $.each(inst.sortables, function() { |
|
2103 |
|
2104 var innermostIntersecting = false, |
|
2105 thisSortable = this; |
|
2106 |
|
2107 //Copy over some variables to allow calling the sortable's native _intersectsWith |
|
2108 this.instance.positionAbs = inst.positionAbs; |
|
2109 this.instance.helperProportions = inst.helperProportions; |
|
2110 this.instance.offset.click = inst.offset.click; |
|
2111 |
|
2112 if(this.instance._intersectsWith(this.instance.containerCache)) { |
|
2113 innermostIntersecting = true; |
|
2114 $.each(inst.sortables, function () { |
|
2115 this.instance.positionAbs = inst.positionAbs; |
|
2116 this.instance.helperProportions = inst.helperProportions; |
|
2117 this.instance.offset.click = inst.offset.click; |
|
2118 if (this !== thisSortable && |
|
2119 this.instance._intersectsWith(this.instance.containerCache) && |
|
2120 $.contains(thisSortable.instance.element[0], this.instance.element[0]) |
|
2121 ) { |
|
2122 innermostIntersecting = false; |
|
2123 } |
|
2124 return innermostIntersecting; |
|
2125 }); |
|
2126 } |
|
2127 |
|
2128 |
|
2129 if(innermostIntersecting) { |
|
2130 //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once |
|
2131 if(!this.instance.isOver) { |
|
2132 |
|
2133 this.instance.isOver = 1; |
|
2134 //Now we fake the start of dragging for the sortable instance, |
|
2135 //by cloning the list group item, appending it to the sortable and using it as inst.currentItem |
|
2136 //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) |
|
2137 this.instance.currentItem = $(that).clone().removeAttr("id").appendTo(this.instance.element).data("ui-sortable-item", true); |
|
2138 this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it |
|
2139 this.instance.options.helper = function() { return ui.helper[0]; }; |
|
2140 |
|
2141 event.target = this.instance.currentItem[0]; |
|
2142 this.instance._mouseCapture(event, true); |
|
2143 this.instance._mouseStart(event, true, true); |
|
2144 |
|
2145 //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes |
|
2146 this.instance.offset.click.top = inst.offset.click.top; |
|
2147 this.instance.offset.click.left = inst.offset.click.left; |
|
2148 this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left; |
|
2149 this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top; |
|
2150 |
|
2151 inst._trigger("toSortable", event); |
|
2152 inst.dropped = this.instance.element; //draggable revert needs that |
|
2153 //hack so receive/update callbacks work (mostly) |
|
2154 inst.currentItem = inst.element; |
|
2155 this.instance.fromOutside = inst; |
|
2156 |
|
2157 } |
|
2158 |
|
2159 //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 |
|
2160 if(this.instance.currentItem) { |
|
2161 this.instance._mouseDrag(event); |
|
2162 } |
|
2163 |
|
2164 } else { |
|
2165 |
|
2166 //If it doesn't intersect with the sortable, and it intersected before, |
|
2167 //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval |
|
2168 if(this.instance.isOver) { |
|
2169 |
|
2170 this.instance.isOver = 0; |
|
2171 this.instance.cancelHelperRemoval = true; |
|
2172 |
|
2173 //Prevent reverting on this forced stop |
|
2174 this.instance.options.revert = false; |
|
2175 |
|
2176 // The out event needs to be triggered independently |
|
2177 this.instance._trigger("out", event, this.instance._uiHash(this.instance)); |
|
2178 |
|
2179 this.instance._mouseStop(event, true); |
|
2180 this.instance.options.helper = this.instance.options._helper; |
|
2181 |
|
2182 //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size |
|
2183 this.instance.currentItem.remove(); |
|
2184 if(this.instance.placeholder) { |
|
2185 this.instance.placeholder.remove(); |
|
2186 } |
|
2187 |
|
2188 inst._trigger("fromSortable", event); |
|
2189 inst.dropped = false; //draggable revert needs that |
|
2190 } |
|
2191 |
|
2192 } |
|
2193 |
|
2194 }); |
|
2195 |
|
2196 } |
|
2197 }); |
|
2198 |
|
2199 $.ui.plugin.add("draggable", "cursor", { |
|
2200 start: function() { |
|
2201 var t = $("body"), o = $(this).data("ui-draggable").options; |
|
2202 if (t.css("cursor")) { |
|
2203 o._cursor = t.css("cursor"); |
|
2204 } |
|
2205 t.css("cursor", o.cursor); |
|
2206 }, |
|
2207 stop: function() { |
|
2208 var o = $(this).data("ui-draggable").options; |
|
2209 if (o._cursor) { |
|
2210 $("body").css("cursor", o._cursor); |
|
2211 } |
|
2212 } |
|
2213 }); |
|
2214 |
|
2215 $.ui.plugin.add("draggable", "opacity", { |
|
2216 start: function(event, ui) { |
|
2217 var t = $(ui.helper), o = $(this).data("ui-draggable").options; |
|
2218 if(t.css("opacity")) { |
|
2219 o._opacity = t.css("opacity"); |
|
2220 } |
|
2221 t.css("opacity", o.opacity); |
|
2222 }, |
|
2223 stop: function(event, ui) { |
|
2224 var o = $(this).data("ui-draggable").options; |
|
2225 if(o._opacity) { |
|
2226 $(ui.helper).css("opacity", o._opacity); |
|
2227 } |
|
2228 } |
|
2229 }); |
|
2230 |
|
2231 $.ui.plugin.add("draggable", "scroll", { |
|
2232 start: function() { |
|
2233 var i = $(this).data("ui-draggable"); |
|
2234 if(i.scrollParent[0] !== document && i.scrollParent[0].tagName !== "HTML") { |
|
2235 i.overflowOffset = i.scrollParent.offset(); |
|
2236 } |
|
2237 }, |
|
2238 drag: function( event ) { |
|
2239 |
|
2240 var i = $(this).data("ui-draggable"), o = i.options, scrolled = false; |
|
2241 |
|
2242 if(i.scrollParent[0] !== document && i.scrollParent[0].tagName !== "HTML") { |
|
2243 |
|
2244 if(!o.axis || o.axis !== "x") { |
|
2245 if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) { |
|
2246 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed; |
|
2247 } else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity) { |
|
2248 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed; |
|
2249 } |
|
2250 } |
|
2251 |
|
2252 if(!o.axis || o.axis !== "y") { |
|
2253 if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) { |
|
2254 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed; |
|
2255 } else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity) { |
|
2256 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed; |
|
2257 } |
|
2258 } |
|
2259 |
|
2260 } else { |
|
2261 |
|
2262 if(!o.axis || o.axis !== "x") { |
|
2263 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) { |
|
2264 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); |
|
2265 } else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) { |
|
2266 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); |
|
2267 } |
|
2268 } |
|
2269 |
|
2270 if(!o.axis || o.axis !== "y") { |
|
2271 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) { |
|
2272 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); |
|
2273 } else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) { |
|
2274 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); |
|
2275 } |
|
2276 } |
|
2277 |
|
2278 } |
|
2279 |
|
2280 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) { |
|
2281 $.ui.ddmanager.prepareOffsets(i, event); |
|
2282 } |
|
2283 |
|
2284 } |
|
2285 }); |
|
2286 |
|
2287 $.ui.plugin.add("draggable", "snap", { |
|
2288 start: function() { |
|
2289 |
|
2290 var i = $(this).data("ui-draggable"), |
|
2291 o = i.options; |
|
2292 |
|
2293 i.snapElements = []; |
|
2294 |
|
2295 $(o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap).each(function() { |
|
2296 var $t = $(this), |
|
2297 $o = $t.offset(); |
|
2298 if(this !== i.element[0]) { |
|
2299 i.snapElements.push({ |
|
2300 item: this, |
|
2301 width: $t.outerWidth(), height: $t.outerHeight(), |
|
2302 top: $o.top, left: $o.left |
|
2303 }); |
|
2304 } |
|
2305 }); |
|
2306 |
|
2307 }, |
|
2308 drag: function(event, ui) { |
|
2309 |
|
2310 var ts, bs, ls, rs, l, r, t, b, i, first, |
|
2311 inst = $(this).data("ui-draggable"), |
|
2312 o = inst.options, |
|
2313 d = o.snapTolerance, |
|
2314 x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width, |
|
2315 y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height; |
|
2316 |
|
2317 for (i = inst.snapElements.length - 1; i >= 0; i--){ |
|
2318 |
|
2319 l = inst.snapElements[i].left; |
|
2320 r = l + inst.snapElements[i].width; |
|
2321 t = inst.snapElements[i].top; |
|
2322 b = t + inst.snapElements[i].height; |
|
2323 |
|
2324 if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d || !$.contains( inst.snapElements[ i ].item.ownerDocument, inst.snapElements[ i ].item ) ) { |
|
2325 if(inst.snapElements[i].snapping) { |
|
2326 (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); |
|
2327 } |
|
2328 inst.snapElements[i].snapping = false; |
|
2329 continue; |
|
2330 } |
|
2331 |
|
2332 if(o.snapMode !== "inner") { |
|
2333 ts = Math.abs(t - y2) <= d; |
|
2334 bs = Math.abs(b - y1) <= d; |
|
2335 ls = Math.abs(l - x2) <= d; |
|
2336 rs = Math.abs(r - x1) <= d; |
|
2337 if(ts) { |
|
2338 ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top; |
|
2339 } |
|
2340 if(bs) { |
|
2341 ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top; |
|
2342 } |
|
2343 if(ls) { |
|
2344 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left; |
|
2345 } |
|
2346 if(rs) { |
|
2347 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left; |
|
2348 } |
|
2349 } |
|
2350 |
|
2351 first = (ts || bs || ls || rs); |
|
2352 |
|
2353 if(o.snapMode !== "outer") { |
|
2354 ts = Math.abs(t - y1) <= d; |
|
2355 bs = Math.abs(b - y2) <= d; |
|
2356 ls = Math.abs(l - x1) <= d; |
|
2357 rs = Math.abs(r - x2) <= d; |
|
2358 if(ts) { |
|
2359 ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top; |
|
2360 } |
|
2361 if(bs) { |
|
2362 ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top; |
|
2363 } |
|
2364 if(ls) { |
|
2365 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left; |
|
2366 } |
|
2367 if(rs) { |
|
2368 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left; |
|
2369 } |
|
2370 } |
|
2371 |
|
2372 if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) { |
|
2373 (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); |
|
2374 } |
|
2375 inst.snapElements[i].snapping = (ts || bs || ls || rs || first); |
|
2376 |
|
2377 } |
|
2378 |
|
2379 } |
|
2380 }); |
|
2381 |
|
2382 $.ui.plugin.add("draggable", "stack", { |
|
2383 start: function() { |
|
2384 var min, |
|
2385 o = this.data("ui-draggable").options, |
|
2386 group = $.makeArray($(o.stack)).sort(function(a,b) { |
|
2387 return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0); |
|
2388 }); |
|
2389 |
|
2390 if (!group.length) { return; } |
|
2391 |
|
2392 min = parseInt($(group[0]).css("zIndex"), 10) || 0; |
|
2393 $(group).each(function(i) { |
|
2394 $(this).css("zIndex", min + i); |
|
2395 }); |
|
2396 this.css("zIndex", (min + group.length)); |
|
2397 } |
|
2398 }); |
|
2399 |
|
2400 $.ui.plugin.add("draggable", "zIndex", { |
|
2401 start: function(event, ui) { |
|
2402 var t = $(ui.helper), o = $(this).data("ui-draggable").options; |
|
2403 if(t.css("zIndex")) { |
|
2404 o._zIndex = t.css("zIndex"); |
|
2405 } |
|
2406 t.css("zIndex", o.zIndex); |
|
2407 }, |
|
2408 stop: function(event, ui) { |
|
2409 var o = $(this).data("ui-draggable").options; |
|
2410 if(o._zIndex) { |
|
2411 $(ui.helper).css("zIndex", o._zIndex); |
|
2412 } |
|
2413 } |
|
2414 }); |
|
2415 |
|
2416 })(jQuery); |
|
2417 (function( $, undefined ) { |
|
2418 |
|
2419 function isOverAxis( x, reference, size ) { |
|
2420 return ( x > reference ) && ( x < ( reference + size ) ); |
|
2421 } |
|
2422 |
|
2423 $.widget("ui.droppable", { |
|
2424 version: "1.10.4", |
|
2425 widgetEventPrefix: "drop", |
|
2426 options: { |
|
2427 accept: "*", |
|
2428 activeClass: false, |
|
2429 addClasses: true, |
|
2430 greedy: false, |
|
2431 hoverClass: false, |
|
2432 scope: "default", |
|
2433 tolerance: "intersect", |
|
2434 |
|
2435 // callbacks |
|
2436 activate: null, |
|
2437 deactivate: null, |
|
2438 drop: null, |
|
2439 out: null, |
|
2440 over: null |
|
2441 }, |
|
2442 _create: function() { |
|
2443 |
|
2444 var proportions, |
|
2445 o = this.options, |
|
2446 accept = o.accept; |
|
2447 |
|
2448 this.isover = false; |
|
2449 this.isout = true; |
|
2450 |
|
2451 this.accept = $.isFunction(accept) ? accept : function(d) { |
|
2452 return d.is(accept); |
|
2453 }; |
|
2454 |
|
2455 this.proportions = function( /* valueToWrite */ ) { |
|
2456 if ( arguments.length ) { |
|
2457 // Store the droppable's proportions |
|
2458 proportions = arguments[ 0 ]; |
|
2459 } else { |
|
2460 // Retrieve or derive the droppable's proportions |
|
2461 return proportions ? |
|
2462 proportions : |
|
2463 proportions = { |
|
2464 width: this.element[ 0 ].offsetWidth, |
|
2465 height: this.element[ 0 ].offsetHeight |
|
2466 }; |
|
2467 } |
|
2468 }; |
|
2469 |
|
2470 // Add the reference and positions to the manager |
|
2471 $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || []; |
|
2472 $.ui.ddmanager.droppables[o.scope].push(this); |
|
2473 |
|
2474 (o.addClasses && this.element.addClass("ui-droppable")); |
|
2475 |
|
2476 }, |
|
2477 |
|
2478 _destroy: function() { |
|
2479 var i = 0, |
|
2480 drop = $.ui.ddmanager.droppables[this.options.scope]; |
|
2481 |
|
2482 for ( ; i < drop.length; i++ ) { |
|
2483 if ( drop[i] === this ) { |
|
2484 drop.splice(i, 1); |
|
2485 } |
|
2486 } |
|
2487 |
|
2488 this.element.removeClass("ui-droppable ui-droppable-disabled"); |
|
2489 }, |
|
2490 |
|
2491 _setOption: function(key, value) { |
|
2492 |
|
2493 if(key === "accept") { |
|
2494 this.accept = $.isFunction(value) ? value : function(d) { |
|
2495 return d.is(value); |
|
2496 }; |
|
2497 } |
|
2498 $.Widget.prototype._setOption.apply(this, arguments); |
|
2499 }, |
|
2500 |
|
2501 _activate: function(event) { |
|
2502 var draggable = $.ui.ddmanager.current; |
|
2503 if(this.options.activeClass) { |
|
2504 this.element.addClass(this.options.activeClass); |
|
2505 } |
|
2506 if(draggable){ |
|
2507 this._trigger("activate", event, this.ui(draggable)); |
|
2508 } |
|
2509 }, |
|
2510 |
|
2511 _deactivate: function(event) { |
|
2512 var draggable = $.ui.ddmanager.current; |
|
2513 if(this.options.activeClass) { |
|
2514 this.element.removeClass(this.options.activeClass); |
|
2515 } |
|
2516 if(draggable){ |
|
2517 this._trigger("deactivate", event, this.ui(draggable)); |
|
2518 } |
|
2519 }, |
|
2520 |
|
2521 _over: function(event) { |
|
2522 |
|
2523 var draggable = $.ui.ddmanager.current; |
|
2524 |
|
2525 // Bail if draggable and droppable are same element |
|
2526 if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) { |
|
2527 return; |
|
2528 } |
|
2529 |
|
2530 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { |
|
2531 if(this.options.hoverClass) { |
|
2532 this.element.addClass(this.options.hoverClass); |
|
2533 } |
|
2534 this._trigger("over", event, this.ui(draggable)); |
|
2535 } |
|
2536 |
|
2537 }, |
|
2538 |
|
2539 _out: function(event) { |
|
2540 |
|
2541 var draggable = $.ui.ddmanager.current; |
|
2542 |
|
2543 // Bail if draggable and droppable are same element |
|
2544 if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) { |
|
2545 return; |
|
2546 } |
|
2547 |
|
2548 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { |
|
2549 if(this.options.hoverClass) { |
|
2550 this.element.removeClass(this.options.hoverClass); |
|
2551 } |
|
2552 this._trigger("out", event, this.ui(draggable)); |
|
2553 } |
|
2554 |
|
2555 }, |
|
2556 |
|
2557 _drop: function(event,custom) { |
|
2558 |
|
2559 var draggable = custom || $.ui.ddmanager.current, |
|
2560 childrenIntersection = false; |
|
2561 |
|
2562 // Bail if draggable and droppable are same element |
|
2563 if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) { |
|
2564 return false; |
|
2565 } |
|
2566 |
|
2567 this.element.find(":data(ui-droppable)").not(".ui-draggable-dragging").each(function() { |
|
2568 var inst = $.data(this, "ui-droppable"); |
|
2569 if( |
|
2570 inst.options.greedy && |
|
2571 !inst.options.disabled && |
|
2572 inst.options.scope === draggable.options.scope && |
|
2573 inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element)) && |
|
2574 $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance) |
|
2575 ) { childrenIntersection = true; return false; } |
|
2576 }); |
|
2577 if(childrenIntersection) { |
|
2578 return false; |
|
2579 } |
|
2580 |
|
2581 if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { |
|
2582 if(this.options.activeClass) { |
|
2583 this.element.removeClass(this.options.activeClass); |
|
2584 } |
|
2585 if(this.options.hoverClass) { |
|
2586 this.element.removeClass(this.options.hoverClass); |
|
2587 } |
|
2588 this._trigger("drop", event, this.ui(draggable)); |
|
2589 return this.element; |
|
2590 } |
|
2591 |
|
2592 return false; |
|
2593 |
|
2594 }, |
|
2595 |
|
2596 ui: function(c) { |
|
2597 return { |
|
2598 draggable: (c.currentItem || c.element), |
|
2599 helper: c.helper, |
|
2600 position: c.position, |
|
2601 offset: c.positionAbs |
|
2602 }; |
|
2603 } |
|
2604 |
|
2605 }); |
|
2606 |
|
2607 $.ui.intersect = function(draggable, droppable, toleranceMode) { |
|
2608 |
|
2609 if (!droppable.offset) { |
|
2610 return false; |
|
2611 } |
|
2612 |
|
2613 var draggableLeft, draggableTop, |
|
2614 x1 = (draggable.positionAbs || draggable.position.absolute).left, |
|
2615 y1 = (draggable.positionAbs || draggable.position.absolute).top, |
|
2616 x2 = x1 + draggable.helperProportions.width, |
|
2617 y2 = y1 + draggable.helperProportions.height, |
|
2618 l = droppable.offset.left, |
|
2619 t = droppable.offset.top, |
|
2620 r = l + droppable.proportions().width, |
|
2621 b = t + droppable.proportions().height; |
|
2622 |
|
2623 switch (toleranceMode) { |
|
2624 case "fit": |
|
2625 return (l <= x1 && x2 <= r && t <= y1 && y2 <= b); |
|
2626 case "intersect": |
|
2627 return (l < x1 + (draggable.helperProportions.width / 2) && // Right Half |
|
2628 x2 - (draggable.helperProportions.width / 2) < r && // Left Half |
|
2629 t < y1 + (draggable.helperProportions.height / 2) && // Bottom Half |
|
2630 y2 - (draggable.helperProportions.height / 2) < b ); // Top Half |
|
2631 case "pointer": |
|
2632 draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left); |
|
2633 draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top); |
|
2634 return isOverAxis( draggableTop, t, droppable.proportions().height ) && isOverAxis( draggableLeft, l, droppable.proportions().width ); |
|
2635 case "touch": |
|
2636 return ( |
|
2637 (y1 >= t && y1 <= b) || // Top edge touching |
|
2638 (y2 >= t && y2 <= b) || // Bottom edge touching |
|
2639 (y1 < t && y2 > b) // Surrounded vertically |
|
2640 ) && ( |
|
2641 (x1 >= l && x1 <= r) || // Left edge touching |
|
2642 (x2 >= l && x2 <= r) || // Right edge touching |
|
2643 (x1 < l && x2 > r) // Surrounded horizontally |
|
2644 ); |
|
2645 default: |
|
2646 return false; |
|
2647 } |
|
2648 |
|
2649 }; |
|
2650 |
|
2651 /* |
|
2652 This manager tracks offsets of draggables and droppables |
|
2653 */ |
|
2654 $.ui.ddmanager = { |
|
2655 current: null, |
|
2656 droppables: { "default": [] }, |
|
2657 prepareOffsets: function(t, event) { |
|
2658 |
|
2659 var i, j, |
|
2660 m = $.ui.ddmanager.droppables[t.options.scope] || [], |
|
2661 type = event ? event.type : null, // workaround for #2317 |
|
2662 list = (t.currentItem || t.element).find(":data(ui-droppable)").addBack(); |
|
2663 |
|
2664 droppablesLoop: for (i = 0; i < m.length; i++) { |
|
2665 |
|
2666 //No disabled and non-accepted |
|
2667 if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) { |
|
2668 continue; |
|
2669 } |
|
2670 |
|
2671 // Filter out elements in the current dragged item |
|
2672 for (j=0; j < list.length; j++) { |
|
2673 if(list[j] === m[i].element[0]) { |
|
2674 m[i].proportions().height = 0; |
|
2675 continue droppablesLoop; |
|
2676 } |
|
2677 } |
|
2678 |
|
2679 m[i].visible = m[i].element.css("display") !== "none"; |
|
2680 if(!m[i].visible) { |
|
2681 continue; |
|
2682 } |
|
2683 |
|
2684 //Activate the droppable if used directly from draggables |
|
2685 if(type === "mousedown") { |
|
2686 m[i]._activate.call(m[i], event); |
|
2687 } |
|
2688 |
|
2689 m[ i ].offset = m[ i ].element.offset(); |
|
2690 m[ i ].proportions({ width: m[ i ].element[ 0 ].offsetWidth, height: m[ i ].element[ 0 ].offsetHeight }); |
|
2691 |
|
2692 } |
|
2693 |
|
2694 }, |
|
2695 drop: function(draggable, event) { |
|
2696 |
|
2697 var dropped = false; |
|
2698 // Create a copy of the droppables in case the list changes during the drop (#9116) |
|
2699 $.each(($.ui.ddmanager.droppables[draggable.options.scope] || []).slice(), function() { |
|
2700 |
|
2701 if(!this.options) { |
|
2702 return; |
|
2703 } |
|
2704 if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance)) { |
|
2705 dropped = this._drop.call(this, event) || dropped; |
|
2706 } |
|
2707 |
|
2708 if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { |
|
2709 this.isout = true; |
|
2710 this.isover = false; |
|
2711 this._deactivate.call(this, event); |
|
2712 } |
|
2713 |
|
2714 }); |
|
2715 return dropped; |
|
2716 |
|
2717 }, |
|
2718 dragStart: function( draggable, event ) { |
|
2719 //Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003) |
|
2720 draggable.element.parentsUntil( "body" ).bind( "scroll.droppable", function() { |
|
2721 if( !draggable.options.refreshPositions ) { |
|
2722 $.ui.ddmanager.prepareOffsets( draggable, event ); |
|
2723 } |
|
2724 }); |
|
2725 }, |
|
2726 drag: function(draggable, event) { |
|
2727 |
|
2728 //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse. |
|
2729 if(draggable.options.refreshPositions) { |
|
2730 $.ui.ddmanager.prepareOffsets(draggable, event); |
|
2731 } |
|
2732 |
|
2733 //Run through all droppables and check their positions based on specific tolerance options |
|
2734 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() { |
|
2735 |
|
2736 if(this.options.disabled || this.greedyChild || !this.visible) { |
|
2737 return; |
|
2738 } |
|
2739 |
|
2740 var parentInstance, scope, parent, |
|
2741 intersects = $.ui.intersect(draggable, this, this.options.tolerance), |
|
2742 c = !intersects && this.isover ? "isout" : (intersects && !this.isover ? "isover" : null); |
|
2743 if(!c) { |
|
2744 return; |
|
2745 } |
|
2746 |
|
2747 if (this.options.greedy) { |
|
2748 // find droppable parents with same scope |
|
2749 scope = this.options.scope; |
|
2750 parent = this.element.parents(":data(ui-droppable)").filter(function () { |
|
2751 return $.data(this, "ui-droppable").options.scope === scope; |
|
2752 }); |
|
2753 |
|
2754 if (parent.length) { |
|
2755 parentInstance = $.data(parent[0], "ui-droppable"); |
|
2756 parentInstance.greedyChild = (c === "isover"); |
|
2757 } |
|
2758 } |
|
2759 |
|
2760 // we just moved into a greedy child |
|
2761 if (parentInstance && c === "isover") { |
|
2762 parentInstance.isover = false; |
|
2763 parentInstance.isout = true; |
|
2764 parentInstance._out.call(parentInstance, event); |
|
2765 } |
|
2766 |
|
2767 this[c] = true; |
|
2768 this[c === "isout" ? "isover" : "isout"] = false; |
|
2769 this[c === "isover" ? "_over" : "_out"].call(this, event); |
|
2770 |
|
2771 // we just moved out of a greedy child |
|
2772 if (parentInstance && c === "isout") { |
|
2773 parentInstance.isout = false; |
|
2774 parentInstance.isover = true; |
|
2775 parentInstance._over.call(parentInstance, event); |
|
2776 } |
|
2777 }); |
|
2778 |
|
2779 }, |
|
2780 dragStop: function( draggable, event ) { |
|
2781 draggable.element.parentsUntil( "body" ).unbind( "scroll.droppable" ); |
|
2782 //Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003) |
|
2783 if( !draggable.options.refreshPositions ) { |
|
2784 $.ui.ddmanager.prepareOffsets( draggable, event ); |
|
2785 } |
|
2786 } |
|
2787 }; |
|
2788 |
|
2789 })(jQuery); |
|
2790 (function( $, undefined ) { |
|
2791 |
|
2792 function num(v) { |
|
2793 return parseInt(v, 10) || 0; |
|
2794 } |
|
2795 |
|
2796 function isNumber(value) { |
|
2797 return !isNaN(parseInt(value, 10)); |
|
2798 } |
|
2799 |
|
2800 $.widget("ui.resizable", $.ui.mouse, { |
|
2801 version: "1.10.4", |
|
2802 widgetEventPrefix: "resize", |
|
2803 options: { |
|
2804 alsoResize: false, |
|
2805 animate: false, |
|
2806 animateDuration: "slow", |
|
2807 animateEasing: "swing", |
|
2808 aspectRatio: false, |
|
2809 autoHide: false, |
|
2810 containment: false, |
|
2811 ghost: false, |
|
2812 grid: false, |
|
2813 handles: "e,s,se", |
|
2814 helper: false, |
|
2815 maxHeight: null, |
|
2816 maxWidth: null, |
|
2817 minHeight: 10, |
|
2818 minWidth: 10, |
|
2819 // See #7960 |
|
2820 zIndex: 90, |
|
2821 |
|
2822 // callbacks |
|
2823 resize: null, |
|
2824 start: null, |
|
2825 stop: null |
|
2826 }, |
|
2827 _create: function() { |
|
2828 |
|
2829 var n, i, handle, axis, hname, |
|
2830 that = this, |
|
2831 o = this.options; |
|
2832 this.element.addClass("ui-resizable"); |
|
2833 |
|
2834 $.extend(this, { |
|
2835 _aspectRatio: !!(o.aspectRatio), |
|
2836 aspectRatio: o.aspectRatio, |
|
2837 originalElement: this.element, |
|
2838 _proportionallyResizeElements: [], |
|
2839 _helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null |
|
2840 }); |
|
2841 |
|
2842 //Wrap the element if it cannot hold child nodes |
|
2843 if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) { |
|
2844 |
|
2845 //Create a wrapper element and set the wrapper to the new current internal element |
|
2846 this.element.wrap( |
|
2847 $("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({ |
|
2848 position: this.element.css("position"), |
|
2849 width: this.element.outerWidth(), |
|
2850 height: this.element.outerHeight(), |
|
2851 top: this.element.css("top"), |
|
2852 left: this.element.css("left") |
|
2853 }) |
|
2854 ); |
|
2855 |
|
2856 //Overwrite the original this.element |
|
2857 this.element = this.element.parent().data( |
|
2858 "ui-resizable", this.element.data("ui-resizable") |
|
2859 ); |
|
2860 |
|
2861 this.elementIsWrapper = true; |
|
2862 |
|
2863 //Move margins to the wrapper |
|
2864 this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") }); |
|
2865 this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0}); |
|
2866 |
|
2867 //Prevent Safari textarea resize |
|
2868 this.originalResizeStyle = this.originalElement.css("resize"); |
|
2869 this.originalElement.css("resize", "none"); |
|
2870 |
|
2871 //Push the actual element to our proportionallyResize internal array |
|
2872 this._proportionallyResizeElements.push(this.originalElement.css({ position: "static", zoom: 1, display: "block" })); |
|
2873 |
|
2874 // avoid IE jump (hard set the margin) |
|
2875 this.originalElement.css({ margin: this.originalElement.css("margin") }); |
|
2876 |
|
2877 // fix handlers offset |
|
2878 this._proportionallyResize(); |
|
2879 |
|
2880 } |
|
2881 |
|
2882 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" }); |
|
2883 if(this.handles.constructor === String) { |
|
2884 |
|
2885 if ( this.handles === "all") { |
|
2886 this.handles = "n,e,s,w,se,sw,ne,nw"; |
|
2887 } |
|
2888 |
|
2889 n = this.handles.split(","); |
|
2890 this.handles = {}; |
|
2891 |
|
2892 for(i = 0; i < n.length; i++) { |
|
2893 |
|
2894 handle = $.trim(n[i]); |
|
2895 hname = "ui-resizable-"+handle; |
|
2896 axis = $("<div class='ui-resizable-handle " + hname + "'></div>"); |
|
2897 |
|
2898 // Apply zIndex to all handles - see #7960 |
|
2899 axis.css({ zIndex: o.zIndex }); |
|
2900 |
|
2901 //TODO : What's going on here? |
|
2902 if ("se" === handle) { |
|
2903 axis.addClass("ui-icon ui-icon-gripsmall-diagonal-se"); |
|
2904 } |
|
2905 |
|
2906 //Insert into internal handles object and append to element |
|
2907 this.handles[handle] = ".ui-resizable-"+handle; |
|
2908 this.element.append(axis); |
|
2909 } |
|
2910 |
|
2911 } |
|
2912 |
|
2913 this._renderAxis = function(target) { |
|
2914 |
|
2915 var i, axis, padPos, padWrapper; |
|
2916 |
|
2917 target = target || this.element; |
|
2918 |
|
2919 for(i in this.handles) { |
|
2920 |
|
2921 if(this.handles[i].constructor === String) { |
|
2922 this.handles[i] = $(this.handles[i], this.element).show(); |
|
2923 } |
|
2924 |
|
2925 //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls) |
|
2926 if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) { |
|
2927 |
|
2928 axis = $(this.handles[i], this.element); |
|
2929 |
|
2930 //Checking the correct pad and border |
|
2931 padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth(); |
|
2932 |
|
2933 //The padding type i have to apply... |
|
2934 padPos = [ "padding", |
|
2935 /ne|nw|n/.test(i) ? "Top" : |
|
2936 /se|sw|s/.test(i) ? "Bottom" : |
|
2937 /^e$/.test(i) ? "Right" : "Left" ].join(""); |
|
2938 |
|
2939 target.css(padPos, padWrapper); |
|
2940 |
|
2941 this._proportionallyResize(); |
|
2942 |
|
2943 } |
|
2944 |
|
2945 //TODO: What's that good for? There's not anything to be executed left |
|
2946 if(!$(this.handles[i]).length) { |
|
2947 continue; |
|
2948 } |
|
2949 } |
|
2950 }; |
|
2951 |
|
2952 //TODO: make renderAxis a prototype function |
|
2953 this._renderAxis(this.element); |
|
2954 |
|
2955 this._handles = $(".ui-resizable-handle", this.element) |
|
2956 .disableSelection(); |
|
2957 |
|
2958 //Matching axis name |
|
2959 this._handles.mouseover(function() { |
|
2960 if (!that.resizing) { |
|
2961 if (this.className) { |
|
2962 axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i); |
|
2963 } |
|
2964 //Axis, default = se |
|
2965 that.axis = axis && axis[1] ? axis[1] : "se"; |
|
2966 } |
|
2967 }); |
|
2968 |
|
2969 //If we want to auto hide the elements |
|
2970 if (o.autoHide) { |
|
2971 this._handles.hide(); |
|
2972 $(this.element) |
|
2973 .addClass("ui-resizable-autohide") |
|
2974 .mouseenter(function() { |
|
2975 if (o.disabled) { |
|
2976 return; |
|
2977 } |
|
2978 $(this).removeClass("ui-resizable-autohide"); |
|
2979 that._handles.show(); |
|
2980 }) |
|
2981 .mouseleave(function(){ |
|
2982 if (o.disabled) { |
|
2983 return; |
|
2984 } |
|
2985 if (!that.resizing) { |
|
2986 $(this).addClass("ui-resizable-autohide"); |
|
2987 that._handles.hide(); |
|
2988 } |
|
2989 }); |
|
2990 } |
|
2991 |
|
2992 //Initialize the mouse interaction |
|
2993 this._mouseInit(); |
|
2994 |
|
2995 }, |
|
2996 |
|
2997 _destroy: function() { |
|
2998 |
|
2999 this._mouseDestroy(); |
|
3000 |
|
3001 var wrapper, |
|
3002 _destroy = function(exp) { |
|
3003 $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing") |
|
3004 .removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove(); |
|
3005 }; |
|
3006 |
|
3007 //TODO: Unwrap at same DOM position |
|
3008 if (this.elementIsWrapper) { |
|
3009 _destroy(this.element); |
|
3010 wrapper = this.element; |
|
3011 this.originalElement.css({ |
|
3012 position: wrapper.css("position"), |
|
3013 width: wrapper.outerWidth(), |
|
3014 height: wrapper.outerHeight(), |
|
3015 top: wrapper.css("top"), |
|
3016 left: wrapper.css("left") |
|
3017 }).insertAfter( wrapper ); |
|
3018 wrapper.remove(); |
|
3019 } |
|
3020 |
|
3021 this.originalElement.css("resize", this.originalResizeStyle); |
|
3022 _destroy(this.originalElement); |
|
3023 |
|
3024 return this; |
|
3025 }, |
|
3026 |
|
3027 _mouseCapture: function(event) { |
|
3028 var i, handle, |
|
3029 capture = false; |
|
3030 |
|
3031 for (i in this.handles) { |
|
3032 handle = $(this.handles[i])[0]; |
|
3033 if (handle === event.target || $.contains(handle, event.target)) { |
|
3034 capture = true; |
|
3035 } |
|
3036 } |
|
3037 |
|
3038 return !this.options.disabled && capture; |
|
3039 }, |
|
3040 |
|
3041 _mouseStart: function(event) { |
|
3042 |
|
3043 var curleft, curtop, cursor, |
|
3044 o = this.options, |
|
3045 iniPos = this.element.position(), |
|
3046 el = this.element; |
|
3047 |
|
3048 this.resizing = true; |
|
3049 |
|
3050 // bugfix for http://dev.jquery.com/ticket/1749 |
|
3051 if ( (/absolute/).test( el.css("position") ) ) { |
|
3052 el.css({ position: "absolute", top: el.css("top"), left: el.css("left") }); |
|
3053 } else if (el.is(".ui-draggable")) { |
|
3054 el.css({ position: "absolute", top: iniPos.top, left: iniPos.left }); |
|
3055 } |
|
3056 |
|
3057 this._renderProxy(); |
|
3058 |
|
3059 curleft = num(this.helper.css("left")); |
|
3060 curtop = num(this.helper.css("top")); |
|
3061 |
|
3062 if (o.containment) { |
|
3063 curleft += $(o.containment).scrollLeft() || 0; |
|
3064 curtop += $(o.containment).scrollTop() || 0; |
|
3065 } |
|
3066 |
|
3067 //Store needed variables |
|
3068 this.offset = this.helper.offset(); |
|
3069 this.position = { left: curleft, top: curtop }; |
|
3070 this.size = this._helper ? { width: this.helper.width(), height: this.helper.height() } : { width: el.width(), height: el.height() }; |
|
3071 this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() }; |
|
3072 this.originalPosition = { left: curleft, top: curtop }; |
|
3073 this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() }; |
|
3074 this.originalMousePosition = { left: event.pageX, top: event.pageY }; |
|
3075 |
|
3076 //Aspect Ratio |
|
3077 this.aspectRatio = (typeof o.aspectRatio === "number") ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1); |
|
3078 |
|
3079 cursor = $(".ui-resizable-" + this.axis).css("cursor"); |
|
3080 $("body").css("cursor", cursor === "auto" ? this.axis + "-resize" : cursor); |
|
3081 |
|
3082 el.addClass("ui-resizable-resizing"); |
|
3083 this._propagate("start", event); |
|
3084 return true; |
|
3085 }, |
|
3086 |
|
3087 _mouseDrag: function(event) { |
|
3088 |
|
3089 //Increase performance, avoid regex |
|
3090 var data, |
|
3091 el = this.helper, props = {}, |
|
3092 smp = this.originalMousePosition, |
|
3093 a = this.axis, |
|
3094 prevTop = this.position.top, |
|
3095 prevLeft = this.position.left, |
|
3096 prevWidth = this.size.width, |
|
3097 prevHeight = this.size.height, |
|
3098 dx = (event.pageX-smp.left)||0, |
|
3099 dy = (event.pageY-smp.top)||0, |
|
3100 trigger = this._change[a]; |
|
3101 |
|
3102 if (!trigger) { |
|
3103 return false; |
|
3104 } |
|
3105 |
|
3106 // Calculate the attrs that will be change |
|
3107 data = trigger.apply(this, [event, dx, dy]); |
|
3108 |
|
3109 // Put this in the mouseDrag handler since the user can start pressing shift while resizing |
|
3110 this._updateVirtualBoundaries(event.shiftKey); |
|
3111 if (this._aspectRatio || event.shiftKey) { |
|
3112 data = this._updateRatio(data, event); |
|
3113 } |
|
3114 |
|
3115 data = this._respectSize(data, event); |
|
3116 |
|
3117 this._updateCache(data); |
|
3118 |
|
3119 // plugins callbacks need to be called first |
|
3120 this._propagate("resize", event); |
|
3121 |
|
3122 if (this.position.top !== prevTop) { |
|
3123 props.top = this.position.top + "px"; |
|
3124 } |
|
3125 if (this.position.left !== prevLeft) { |
|
3126 props.left = this.position.left + "px"; |
|
3127 } |
|
3128 if (this.size.width !== prevWidth) { |
|
3129 props.width = this.size.width + "px"; |
|
3130 } |
|
3131 if (this.size.height !== prevHeight) { |
|
3132 props.height = this.size.height + "px"; |
|
3133 } |
|
3134 el.css(props); |
|
3135 |
|
3136 if (!this._helper && this._proportionallyResizeElements.length) { |
|
3137 this._proportionallyResize(); |
|
3138 } |
|
3139 |
|
3140 // Call the user callback if the element was resized |
|
3141 if ( ! $.isEmptyObject(props) ) { |
|
3142 this._trigger("resize", event, this.ui()); |
|
3143 } |
|
3144 |
|
3145 return false; |
|
3146 }, |
|
3147 |
|
3148 _mouseStop: function(event) { |
|
3149 |
|
3150 this.resizing = false; |
|
3151 var pr, ista, soffseth, soffsetw, s, left, top, |
|
3152 o = this.options, that = this; |
|
3153 |
|
3154 if(this._helper) { |
|
3155 |
|
3156 pr = this._proportionallyResizeElements; |
|
3157 ista = pr.length && (/textarea/i).test(pr[0].nodeName); |
|
3158 soffseth = ista && $.ui.hasScroll(pr[0], "left") /* TODO - jump height */ ? 0 : that.sizeDiff.height; |
|
3159 soffsetw = ista ? 0 : that.sizeDiff.width; |
|
3160 |
|
3161 s = { width: (that.helper.width() - soffsetw), height: (that.helper.height() - soffseth) }; |
|
3162 left = (parseInt(that.element.css("left"), 10) + (that.position.left - that.originalPosition.left)) || null; |
|
3163 top = (parseInt(that.element.css("top"), 10) + (that.position.top - that.originalPosition.top)) || null; |
|
3164 |
|
3165 if (!o.animate) { |
|
3166 this.element.css($.extend(s, { top: top, left: left })); |
|
3167 } |
|
3168 |
|
3169 that.helper.height(that.size.height); |
|
3170 that.helper.width(that.size.width); |
|
3171 |
|
3172 if (this._helper && !o.animate) { |
|
3173 this._proportionallyResize(); |
|
3174 } |
|
3175 } |
|
3176 |
|
3177 $("body").css("cursor", "auto"); |
|
3178 |
|
3179 this.element.removeClass("ui-resizable-resizing"); |
|
3180 |
|
3181 this._propagate("stop", event); |
|
3182 |
|
3183 if (this._helper) { |
|
3184 this.helper.remove(); |
|
3185 } |
|
3186 |
|
3187 return false; |
|
3188 |
|
3189 }, |
|
3190 |
|
3191 _updateVirtualBoundaries: function(forceAspectRatio) { |
|
3192 var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b, |
|
3193 o = this.options; |
|
3194 |
|
3195 b = { |
|
3196 minWidth: isNumber(o.minWidth) ? o.minWidth : 0, |
|
3197 maxWidth: isNumber(o.maxWidth) ? o.maxWidth : Infinity, |
|
3198 minHeight: isNumber(o.minHeight) ? o.minHeight : 0, |
|
3199 maxHeight: isNumber(o.maxHeight) ? o.maxHeight : Infinity |
|
3200 }; |
|
3201 |
|
3202 if(this._aspectRatio || forceAspectRatio) { |
|
3203 // We want to create an enclosing box whose aspect ration is the requested one |
|
3204 // First, compute the "projected" size for each dimension based on the aspect ratio and other dimension |
|
3205 pMinWidth = b.minHeight * this.aspectRatio; |
|
3206 pMinHeight = b.minWidth / this.aspectRatio; |
|
3207 pMaxWidth = b.maxHeight * this.aspectRatio; |
|
3208 pMaxHeight = b.maxWidth / this.aspectRatio; |
|
3209 |
|
3210 if(pMinWidth > b.minWidth) { |
|
3211 b.minWidth = pMinWidth; |
|
3212 } |
|
3213 if(pMinHeight > b.minHeight) { |
|
3214 b.minHeight = pMinHeight; |
|
3215 } |
|
3216 if(pMaxWidth < b.maxWidth) { |
|
3217 b.maxWidth = pMaxWidth; |
|
3218 } |
|
3219 if(pMaxHeight < b.maxHeight) { |
|
3220 b.maxHeight = pMaxHeight; |
|
3221 } |
|
3222 } |
|
3223 this._vBoundaries = b; |
|
3224 }, |
|
3225 |
|
3226 _updateCache: function(data) { |
|
3227 this.offset = this.helper.offset(); |
|
3228 if (isNumber(data.left)) { |
|
3229 this.position.left = data.left; |
|
3230 } |
|
3231 if (isNumber(data.top)) { |
|
3232 this.position.top = data.top; |
|
3233 } |
|
3234 if (isNumber(data.height)) { |
|
3235 this.size.height = data.height; |
|
3236 } |
|
3237 if (isNumber(data.width)) { |
|
3238 this.size.width = data.width; |
|
3239 } |
|
3240 }, |
|
3241 |
|
3242 _updateRatio: function( data ) { |
|
3243 |
|
3244 var cpos = this.position, |
|
3245 csize = this.size, |
|
3246 a = this.axis; |
|
3247 |
|
3248 if (isNumber(data.height)) { |
|
3249 data.width = (data.height * this.aspectRatio); |
|
3250 } else if (isNumber(data.width)) { |
|
3251 data.height = (data.width / this.aspectRatio); |
|
3252 } |
|
3253 |
|
3254 if (a === "sw") { |
|
3255 data.left = cpos.left + (csize.width - data.width); |
|
3256 data.top = null; |
|
3257 } |
|
3258 if (a === "nw") { |
|
3259 data.top = cpos.top + (csize.height - data.height); |
|
3260 data.left = cpos.left + (csize.width - data.width); |
|
3261 } |
|
3262 |
|
3263 return data; |
|
3264 }, |
|
3265 |
|
3266 _respectSize: function( data ) { |
|
3267 |
|
3268 var o = this._vBoundaries, |
|
3269 a = this.axis, |
|
3270 ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height), |
|
3271 isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height), |
|
3272 dw = this.originalPosition.left + this.originalSize.width, |
|
3273 dh = this.position.top + this.size.height, |
|
3274 cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a); |
|
3275 if (isminw) { |
|
3276 data.width = o.minWidth; |
|
3277 } |
|
3278 if (isminh) { |
|
3279 data.height = o.minHeight; |
|
3280 } |
|
3281 if (ismaxw) { |
|
3282 data.width = o.maxWidth; |
|
3283 } |
|
3284 if (ismaxh) { |
|
3285 data.height = o.maxHeight; |
|
3286 } |
|
3287 |
|
3288 if (isminw && cw) { |
|
3289 data.left = dw - o.minWidth; |
|
3290 } |
|
3291 if (ismaxw && cw) { |
|
3292 data.left = dw - o.maxWidth; |
|
3293 } |
|
3294 if (isminh && ch) { |
|
3295 data.top = dh - o.minHeight; |
|
3296 } |
|
3297 if (ismaxh && ch) { |
|
3298 data.top = dh - o.maxHeight; |
|
3299 } |
|
3300 |
|
3301 // fixing jump error on top/left - bug #2330 |
|
3302 if (!data.width && !data.height && !data.left && data.top) { |
|
3303 data.top = null; |
|
3304 } else if (!data.width && !data.height && !data.top && data.left) { |
|
3305 data.left = null; |
|
3306 } |
|
3307 |
|
3308 return data; |
|
3309 }, |
|
3310 |
|
3311 _proportionallyResize: function() { |
|
3312 |
|
3313 if (!this._proportionallyResizeElements.length) { |
|
3314 return; |
|
3315 } |
|
3316 |
|
3317 var i, j, borders, paddings, prel, |
|
3318 element = this.helper || this.element; |
|
3319 |
|
3320 for ( i=0; i < this._proportionallyResizeElements.length; i++) { |
|
3321 |
|
3322 prel = this._proportionallyResizeElements[i]; |
|
3323 |
|
3324 if (!this.borderDif) { |
|
3325 this.borderDif = []; |
|
3326 borders = [prel.css("borderTopWidth"), prel.css("borderRightWidth"), prel.css("borderBottomWidth"), prel.css("borderLeftWidth")]; |
|
3327 paddings = [prel.css("paddingTop"), prel.css("paddingRight"), prel.css("paddingBottom"), prel.css("paddingLeft")]; |
|
3328 |
|
3329 for ( j = 0; j < borders.length; j++ ) { |
|
3330 this.borderDif[ j ] = ( parseInt( borders[ j ], 10 ) || 0 ) + ( parseInt( paddings[ j ], 10 ) || 0 ); |
|
3331 } |
|
3332 } |
|
3333 |
|
3334 prel.css({ |
|
3335 height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0, |
|
3336 width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0 |
|
3337 }); |
|
3338 |
|
3339 } |
|
3340 |
|
3341 }, |
|
3342 |
|
3343 _renderProxy: function() { |
|
3344 |
|
3345 var el = this.element, o = this.options; |
|
3346 this.elementOffset = el.offset(); |
|
3347 |
|
3348 if(this._helper) { |
|
3349 |
|
3350 this.helper = this.helper || $("<div style='overflow:hidden;'></div>"); |
|
3351 |
|
3352 this.helper.addClass(this._helper).css({ |
|
3353 width: this.element.outerWidth() - 1, |
|
3354 height: this.element.outerHeight() - 1, |
|
3355 position: "absolute", |
|
3356 left: this.elementOffset.left +"px", |
|
3357 top: this.elementOffset.top +"px", |
|
3358 zIndex: ++o.zIndex //TODO: Don't modify option |
|
3359 }); |
|
3360 |
|
3361 this.helper |
|
3362 .appendTo("body") |
|
3363 .disableSelection(); |
|
3364 |
|
3365 } else { |
|
3366 this.helper = this.element; |
|
3367 } |
|
3368 |
|
3369 }, |
|
3370 |
|
3371 _change: { |
|
3372 e: function(event, dx) { |
|
3373 return { width: this.originalSize.width + dx }; |
|
3374 }, |
|
3375 w: function(event, dx) { |
|
3376 var cs = this.originalSize, sp = this.originalPosition; |
|
3377 return { left: sp.left + dx, width: cs.width - dx }; |
|
3378 }, |
|
3379 n: function(event, dx, dy) { |
|
3380 var cs = this.originalSize, sp = this.originalPosition; |
|
3381 return { top: sp.top + dy, height: cs.height - dy }; |
|
3382 }, |
|
3383 s: function(event, dx, dy) { |
|
3384 return { height: this.originalSize.height + dy }; |
|
3385 }, |
|
3386 se: function(event, dx, dy) { |
|
3387 return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy])); |
|
3388 }, |
|
3389 sw: function(event, dx, dy) { |
|
3390 return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy])); |
|
3391 }, |
|
3392 ne: function(event, dx, dy) { |
|
3393 return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy])); |
|
3394 }, |
|
3395 nw: function(event, dx, dy) { |
|
3396 return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy])); |
|
3397 } |
|
3398 }, |
|
3399 |
|
3400 _propagate: function(n, event) { |
|
3401 $.ui.plugin.call(this, n, [event, this.ui()]); |
|
3402 (n !== "resize" && this._trigger(n, event, this.ui())); |
|
3403 }, |
|
3404 |
|
3405 plugins: {}, |
|
3406 |
|
3407 ui: function() { |
|
3408 return { |
|
3409 originalElement: this.originalElement, |
|
3410 element: this.element, |
|
3411 helper: this.helper, |
|
3412 position: this.position, |
|
3413 size: this.size, |
|
3414 originalSize: this.originalSize, |
|
3415 originalPosition: this.originalPosition |
|
3416 }; |
|
3417 } |
|
3418 |
|
3419 }); |
|
3420 |
|
3421 /* |
|
3422 * Resizable Extensions |
|
3423 */ |
|
3424 |
|
3425 $.ui.plugin.add("resizable", "animate", { |
|
3426 |
|
3427 stop: function( event ) { |
|
3428 var that = $(this).data("ui-resizable"), |
|
3429 o = that.options, |
|
3430 pr = that._proportionallyResizeElements, |
|
3431 ista = pr.length && (/textarea/i).test(pr[0].nodeName), |
|
3432 soffseth = ista && $.ui.hasScroll(pr[0], "left") /* TODO - jump height */ ? 0 : that.sizeDiff.height, |
|
3433 soffsetw = ista ? 0 : that.sizeDiff.width, |
|
3434 style = { width: (that.size.width - soffsetw), height: (that.size.height - soffseth) }, |
|
3435 left = (parseInt(that.element.css("left"), 10) + (that.position.left - that.originalPosition.left)) || null, |
|
3436 top = (parseInt(that.element.css("top"), 10) + (that.position.top - that.originalPosition.top)) || null; |
|
3437 |
|
3438 that.element.animate( |
|
3439 $.extend(style, top && left ? { top: top, left: left } : {}), { |
|
3440 duration: o.animateDuration, |
|
3441 easing: o.animateEasing, |
|
3442 step: function() { |
|
3443 |
|
3444 var data = { |
|
3445 width: parseInt(that.element.css("width"), 10), |
|
3446 height: parseInt(that.element.css("height"), 10), |
|
3447 top: parseInt(that.element.css("top"), 10), |
|
3448 left: parseInt(that.element.css("left"), 10) |
|
3449 }; |
|
3450 |
|
3451 if (pr && pr.length) { |
|
3452 $(pr[0]).css({ width: data.width, height: data.height }); |
|
3453 } |
|
3454 |
|
3455 // propagating resize, and updating values for each animation step |
|
3456 that._updateCache(data); |
|
3457 that._propagate("resize", event); |
|
3458 |
|
3459 } |
|
3460 } |
|
3461 ); |
|
3462 } |
|
3463 |
|
3464 }); |
|
3465 |
|
3466 $.ui.plugin.add("resizable", "containment", { |
|
3467 |
|
3468 start: function() { |
|
3469 var element, p, co, ch, cw, width, height, |
|
3470 that = $(this).data("ui-resizable"), |
|
3471 o = that.options, |
|
3472 el = that.element, |
|
3473 oc = o.containment, |
|
3474 ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc; |
|
3475 |
|
3476 if (!ce) { |
|
3477 return; |
|
3478 } |
|
3479 |
|
3480 that.containerElement = $(ce); |
|
3481 |
|
3482 if (/document/.test(oc) || oc === document) { |
|
3483 that.containerOffset = { left: 0, top: 0 }; |
|
3484 that.containerPosition = { left: 0, top: 0 }; |
|
3485 |
|
3486 that.parentData = { |
|
3487 element: $(document), left: 0, top: 0, |
|
3488 width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight |
|
3489 }; |
|
3490 } |
|
3491 |
|
3492 // i'm a node, so compute top, left, right, bottom |
|
3493 else { |
|
3494 element = $(ce); |
|
3495 p = []; |
|
3496 $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); }); |
|
3497 |
|
3498 that.containerOffset = element.offset(); |
|
3499 that.containerPosition = element.position(); |
|
3500 that.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) }; |
|
3501 |
|
3502 co = that.containerOffset; |
|
3503 ch = that.containerSize.height; |
|
3504 cw = that.containerSize.width; |
|
3505 width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ); |
|
3506 height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch); |
|
3507 |
|
3508 that.parentData = { |
|
3509 element: ce, left: co.left, top: co.top, width: width, height: height |
|
3510 }; |
|
3511 } |
|
3512 }, |
|
3513 |
|
3514 resize: function( event ) { |
|
3515 var woset, hoset, isParent, isOffsetRelative, |
|
3516 that = $(this).data("ui-resizable"), |
|
3517 o = that.options, |
|
3518 co = that.containerOffset, cp = that.position, |
|
3519 pRatio = that._aspectRatio || event.shiftKey, |
|
3520 cop = { top:0, left:0 }, ce = that.containerElement; |
|
3521 |
|
3522 if (ce[0] !== document && (/static/).test(ce.css("position"))) { |
|
3523 cop = co; |
|
3524 } |
|
3525 |
|
3526 if (cp.left < (that._helper ? co.left : 0)) { |
|
3527 that.size.width = that.size.width + (that._helper ? (that.position.left - co.left) : (that.position.left - cop.left)); |
|
3528 if (pRatio) { |
|
3529 that.size.height = that.size.width / that.aspectRatio; |
|
3530 } |
|
3531 that.position.left = o.helper ? co.left : 0; |
|
3532 } |
|
3533 |
|
3534 if (cp.top < (that._helper ? co.top : 0)) { |
|
3535 that.size.height = that.size.height + (that._helper ? (that.position.top - co.top) : that.position.top); |
|
3536 if (pRatio) { |
|
3537 that.size.width = that.size.height * that.aspectRatio; |
|
3538 } |
|
3539 that.position.top = that._helper ? co.top : 0; |
|
3540 } |
|
3541 |
|
3542 that.offset.left = that.parentData.left+that.position.left; |
|
3543 that.offset.top = that.parentData.top+that.position.top; |
|
3544 |
|
3545 woset = Math.abs( (that._helper ? that.offset.left - cop.left : (that.offset.left - cop.left)) + that.sizeDiff.width ); |
|
3546 hoset = Math.abs( (that._helper ? that.offset.top - cop.top : (that.offset.top - co.top)) + that.sizeDiff.height ); |
|
3547 |
|
3548 isParent = that.containerElement.get(0) === that.element.parent().get(0); |
|
3549 isOffsetRelative = /relative|absolute/.test(that.containerElement.css("position")); |
|
3550 |
|
3551 if ( isParent && isOffsetRelative ) { |
|
3552 woset -= Math.abs( that.parentData.left ); |
|
3553 } |
|
3554 |
|
3555 if (woset + that.size.width >= that.parentData.width) { |
|
3556 that.size.width = that.parentData.width - woset; |
|
3557 if (pRatio) { |
|
3558 that.size.height = that.size.width / that.aspectRatio; |
|
3559 } |
|
3560 } |
|
3561 |
|
3562 if (hoset + that.size.height >= that.parentData.height) { |
|
3563 that.size.height = that.parentData.height - hoset; |
|
3564 if (pRatio) { |
|
3565 that.size.width = that.size.height * that.aspectRatio; |
|
3566 } |
|
3567 } |
|
3568 }, |
|
3569 |
|
3570 stop: function(){ |
|
3571 var that = $(this).data("ui-resizable"), |
|
3572 o = that.options, |
|
3573 co = that.containerOffset, |
|
3574 cop = that.containerPosition, |
|
3575 ce = that.containerElement, |
|
3576 helper = $(that.helper), |
|
3577 ho = helper.offset(), |
|
3578 w = helper.outerWidth() - that.sizeDiff.width, |
|
3579 h = helper.outerHeight() - that.sizeDiff.height; |
|
3580 |
|
3581 if (that._helper && !o.animate && (/relative/).test(ce.css("position"))) { |
|
3582 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h }); |
|
3583 } |
|
3584 |
|
3585 if (that._helper && !o.animate && (/static/).test(ce.css("position"))) { |
|
3586 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h }); |
|
3587 } |
|
3588 |
|
3589 } |
|
3590 }); |
|
3591 |
|
3592 $.ui.plugin.add("resizable", "alsoResize", { |
|
3593 |
|
3594 start: function () { |
|
3595 var that = $(this).data("ui-resizable"), |
|
3596 o = that.options, |
|
3597 _store = function (exp) { |
|
3598 $(exp).each(function() { |
|
3599 var el = $(this); |
|
3600 el.data("ui-resizable-alsoresize", { |
|
3601 width: parseInt(el.width(), 10), height: parseInt(el.height(), 10), |
|
3602 left: parseInt(el.css("left"), 10), top: parseInt(el.css("top"), 10) |
|
3603 }); |
|
3604 }); |
|
3605 }; |
|
3606 |
|
3607 if (typeof(o.alsoResize) === "object" && !o.alsoResize.parentNode) { |
|
3608 if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); } |
|
3609 else { $.each(o.alsoResize, function (exp) { _store(exp); }); } |
|
3610 }else{ |
|
3611 _store(o.alsoResize); |
|
3612 } |
|
3613 }, |
|
3614 |
|
3615 resize: function (event, ui) { |
|
3616 var that = $(this).data("ui-resizable"), |
|
3617 o = that.options, |
|
3618 os = that.originalSize, |
|
3619 op = that.originalPosition, |
|
3620 delta = { |
|
3621 height: (that.size.height - os.height) || 0, width: (that.size.width - os.width) || 0, |
|
3622 top: (that.position.top - op.top) || 0, left: (that.position.left - op.left) || 0 |
|
3623 }, |
|
3624 |
|
3625 _alsoResize = function (exp, c) { |
|
3626 $(exp).each(function() { |
|
3627 var el = $(this), start = $(this).data("ui-resizable-alsoresize"), style = {}, |
|
3628 css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ["width", "height"] : ["width", "height", "top", "left"]; |
|
3629 |
|
3630 $.each(css, function (i, prop) { |
|
3631 var sum = (start[prop]||0) + (delta[prop]||0); |
|
3632 if (sum && sum >= 0) { |
|
3633 style[prop] = sum || null; |
|
3634 } |
|
3635 }); |
|
3636 |
|
3637 el.css(style); |
|
3638 }); |
|
3639 }; |
|
3640 |
|
3641 if (typeof(o.alsoResize) === "object" && !o.alsoResize.nodeType) { |
|
3642 $.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); }); |
|
3643 }else{ |
|
3644 _alsoResize(o.alsoResize); |
|
3645 } |
|
3646 }, |
|
3647 |
|
3648 stop: function () { |
|
3649 $(this).removeData("resizable-alsoresize"); |
|
3650 } |
|
3651 }); |
|
3652 |
|
3653 $.ui.plugin.add("resizable", "ghost", { |
|
3654 |
|
3655 start: function() { |
|
3656 |
|
3657 var that = $(this).data("ui-resizable"), o = that.options, cs = that.size; |
|
3658 |
|
3659 that.ghost = that.originalElement.clone(); |
|
3660 that.ghost |
|
3661 .css({ opacity: 0.25, display: "block", position: "relative", height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 }) |
|
3662 .addClass("ui-resizable-ghost") |
|
3663 .addClass(typeof o.ghost === "string" ? o.ghost : ""); |
|
3664 |
|
3665 that.ghost.appendTo(that.helper); |
|
3666 |
|
3667 }, |
|
3668 |
|
3669 resize: function(){ |
|
3670 var that = $(this).data("ui-resizable"); |
|
3671 if (that.ghost) { |
|
3672 that.ghost.css({ position: "relative", height: that.size.height, width: that.size.width }); |
|
3673 } |
|
3674 }, |
|
3675 |
|
3676 stop: function() { |
|
3677 var that = $(this).data("ui-resizable"); |
|
3678 if (that.ghost && that.helper) { |
|
3679 that.helper.get(0).removeChild(that.ghost.get(0)); |
|
3680 } |
|
3681 } |
|
3682 |
|
3683 }); |
|
3684 |
|
3685 $.ui.plugin.add("resizable", "grid", { |
|
3686 |
|
3687 resize: function() { |
|
3688 var that = $(this).data("ui-resizable"), |
|
3689 o = that.options, |
|
3690 cs = that.size, |
|
3691 os = that.originalSize, |
|
3692 op = that.originalPosition, |
|
3693 a = that.axis, |
|
3694 grid = typeof o.grid === "number" ? [o.grid, o.grid] : o.grid, |
|
3695 gridX = (grid[0]||1), |
|
3696 gridY = (grid[1]||1), |
|
3697 ox = Math.round((cs.width - os.width) / gridX) * gridX, |
|
3698 oy = Math.round((cs.height - os.height) / gridY) * gridY, |
|
3699 newWidth = os.width + ox, |
|
3700 newHeight = os.height + oy, |
|
3701 isMaxWidth = o.maxWidth && (o.maxWidth < newWidth), |
|
3702 isMaxHeight = o.maxHeight && (o.maxHeight < newHeight), |
|
3703 isMinWidth = o.minWidth && (o.minWidth > newWidth), |
|
3704 isMinHeight = o.minHeight && (o.minHeight > newHeight); |
|
3705 |
|
3706 o.grid = grid; |
|
3707 |
|
3708 if (isMinWidth) { |
|
3709 newWidth = newWidth + gridX; |
|
3710 } |
|
3711 if (isMinHeight) { |
|
3712 newHeight = newHeight + gridY; |
|
3713 } |
|
3714 if (isMaxWidth) { |
|
3715 newWidth = newWidth - gridX; |
|
3716 } |
|
3717 if (isMaxHeight) { |
|
3718 newHeight = newHeight - gridY; |
|
3719 } |
|
3720 |
|
3721 if (/^(se|s|e)$/.test(a)) { |
|
3722 that.size.width = newWidth; |
|
3723 that.size.height = newHeight; |
|
3724 } else if (/^(ne)$/.test(a)) { |
|
3725 that.size.width = newWidth; |
|
3726 that.size.height = newHeight; |
|
3727 that.position.top = op.top - oy; |
|
3728 } else if (/^(sw)$/.test(a)) { |
|
3729 that.size.width = newWidth; |
|
3730 that.size.height = newHeight; |
|
3731 that.position.left = op.left - ox; |
|
3732 } else { |
|
3733 if ( newHeight - gridY > 0 ) { |
|
3734 that.size.height = newHeight; |
|
3735 that.position.top = op.top - oy; |
|
3736 } else { |
|
3737 that.size.height = gridY; |
|
3738 that.position.top = op.top + os.height - gridY; |
|
3739 } |
|
3740 if ( newWidth - gridX > 0 ) { |
|
3741 that.size.width = newWidth; |
|
3742 that.position.left = op.left - ox; |
|
3743 } else { |
|
3744 that.size.width = gridX; |
|
3745 that.position.left = op.left + os.width - gridX; |
|
3746 } |
|
3747 } |
|
3748 } |
|
3749 |
|
3750 }); |
|
3751 |
|
3752 })(jQuery); |
|
3753 (function( $, undefined ) { |
|
3754 |
|
3755 $.widget("ui.selectable", $.ui.mouse, { |
|
3756 version: "1.10.4", |
|
3757 options: { |
|
3758 appendTo: "body", |
|
3759 autoRefresh: true, |
|
3760 distance: 0, |
|
3761 filter: "*", |
|
3762 tolerance: "touch", |
|
3763 |
|
3764 // callbacks |
|
3765 selected: null, |
|
3766 selecting: null, |
|
3767 start: null, |
|
3768 stop: null, |
|
3769 unselected: null, |
|
3770 unselecting: null |
|
3771 }, |
|
3772 _create: function() { |
|
3773 var selectees, |
|
3774 that = this; |
|
3775 |
|
3776 this.element.addClass("ui-selectable"); |
|
3777 |
|
3778 this.dragged = false; |
|
3779 |
|
3780 // cache selectee children based on filter |
|
3781 this.refresh = function() { |
|
3782 selectees = $(that.options.filter, that.element[0]); |
|
3783 selectees.addClass("ui-selectee"); |
|
3784 selectees.each(function() { |
|
3785 var $this = $(this), |
|
3786 pos = $this.offset(); |
|
3787 $.data(this, "selectable-item", { |
|
3788 element: this, |
|
3789 $element: $this, |
|
3790 left: pos.left, |
|
3791 top: pos.top, |
|
3792 right: pos.left + $this.outerWidth(), |
|
3793 bottom: pos.top + $this.outerHeight(), |
|
3794 startselected: false, |
|
3795 selected: $this.hasClass("ui-selected"), |
|
3796 selecting: $this.hasClass("ui-selecting"), |
|
3797 unselecting: $this.hasClass("ui-unselecting") |
|
3798 }); |
|
3799 }); |
|
3800 }; |
|
3801 this.refresh(); |
|
3802 |
|
3803 this.selectees = selectees.addClass("ui-selectee"); |
|
3804 |
|
3805 this._mouseInit(); |
|
3806 |
|
3807 this.helper = $("<div class='ui-selectable-helper'></div>"); |
|
3808 }, |
|
3809 |
|
3810 _destroy: function() { |
|
3811 this.selectees |
|
3812 .removeClass("ui-selectee") |
|
3813 .removeData("selectable-item"); |
|
3814 this.element |
|
3815 .removeClass("ui-selectable ui-selectable-disabled"); |
|
3816 this._mouseDestroy(); |
|
3817 }, |
|
3818 |
|
3819 _mouseStart: function(event) { |
|
3820 var that = this, |
|
3821 options = this.options; |
|
3822 |
|
3823 this.opos = [event.pageX, event.pageY]; |
|
3824 |
|
3825 if (this.options.disabled) { |
|
3826 return; |
|
3827 } |
|
3828 |
|
3829 this.selectees = $(options.filter, this.element[0]); |
|
3830 |
|
3831 this._trigger("start", event); |
|
3832 |
|
3833 $(options.appendTo).append(this.helper); |
|
3834 // position helper (lasso) |
|
3835 this.helper.css({ |
|
3836 "left": event.pageX, |
|
3837 "top": event.pageY, |
|
3838 "width": 0, |
|
3839 "height": 0 |
|
3840 }); |
|
3841 |
|
3842 if (options.autoRefresh) { |
|
3843 this.refresh(); |
|
3844 } |
|
3845 |
|
3846 this.selectees.filter(".ui-selected").each(function() { |
|
3847 var selectee = $.data(this, "selectable-item"); |
|
3848 selectee.startselected = true; |
|
3849 if (!event.metaKey && !event.ctrlKey) { |
|
3850 selectee.$element.removeClass("ui-selected"); |
|
3851 selectee.selected = false; |
|
3852 selectee.$element.addClass("ui-unselecting"); |
|
3853 selectee.unselecting = true; |
|
3854 // selectable UNSELECTING callback |
|
3855 that._trigger("unselecting", event, { |
|
3856 unselecting: selectee.element |
|
3857 }); |
|
3858 } |
|
3859 }); |
|
3860 |
|
3861 $(event.target).parents().addBack().each(function() { |
|
3862 var doSelect, |
|
3863 selectee = $.data(this, "selectable-item"); |
|
3864 if (selectee) { |
|
3865 doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass("ui-selected"); |
|
3866 selectee.$element |
|
3867 .removeClass(doSelect ? "ui-unselecting" : "ui-selected") |
|
3868 .addClass(doSelect ? "ui-selecting" : "ui-unselecting"); |
|
3869 selectee.unselecting = !doSelect; |
|
3870 selectee.selecting = doSelect; |
|
3871 selectee.selected = doSelect; |
|
3872 // selectable (UN)SELECTING callback |
|
3873 if (doSelect) { |
|
3874 that._trigger("selecting", event, { |
|
3875 selecting: selectee.element |
|
3876 }); |
|
3877 } else { |
|
3878 that._trigger("unselecting", event, { |
|
3879 unselecting: selectee.element |
|
3880 }); |
|
3881 } |
|
3882 return false; |
|
3883 } |
|
3884 }); |
|
3885 |
|
3886 }, |
|
3887 |
|
3888 _mouseDrag: function(event) { |
|
3889 |
|
3890 this.dragged = true; |
|
3891 |
|
3892 if (this.options.disabled) { |
|
3893 return; |
|
3894 } |
|
3895 |
|
3896 var tmp, |
|
3897 that = this, |
|
3898 options = this.options, |
|
3899 x1 = this.opos[0], |
|
3900 y1 = this.opos[1], |
|
3901 x2 = event.pageX, |
|
3902 y2 = event.pageY; |
|
3903 |
|
3904 if (x1 > x2) { tmp = x2; x2 = x1; x1 = tmp; } |
|
3905 if (y1 > y2) { tmp = y2; y2 = y1; y1 = tmp; } |
|
3906 this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1}); |
|
3907 |
|
3908 this.selectees.each(function() { |
|
3909 var selectee = $.data(this, "selectable-item"), |
|
3910 hit = false; |
|
3911 |
|
3912 //prevent helper from being selected if appendTo: selectable |
|
3913 if (!selectee || selectee.element === that.element[0]) { |
|
3914 return; |
|
3915 } |
|
3916 |
|
3917 if (options.tolerance === "touch") { |
|
3918 hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) ); |
|
3919 } else if (options.tolerance === "fit") { |
|
3920 hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2); |
|
3921 } |
|
3922 |
|
3923 if (hit) { |
|
3924 // SELECT |
|
3925 if (selectee.selected) { |
|
3926 selectee.$element.removeClass("ui-selected"); |
|
3927 selectee.selected = false; |
|
3928 } |
|
3929 if (selectee.unselecting) { |
|
3930 selectee.$element.removeClass("ui-unselecting"); |
|
3931 selectee.unselecting = false; |
|
3932 } |
|
3933 if (!selectee.selecting) { |
|
3934 selectee.$element.addClass("ui-selecting"); |
|
3935 selectee.selecting = true; |
|
3936 // selectable SELECTING callback |
|
3937 that._trigger("selecting", event, { |
|
3938 selecting: selectee.element |
|
3939 }); |
|
3940 } |
|
3941 } else { |
|
3942 // UNSELECT |
|
3943 if (selectee.selecting) { |
|
3944 if ((event.metaKey || event.ctrlKey) && selectee.startselected) { |
|
3945 selectee.$element.removeClass("ui-selecting"); |
|
3946 selectee.selecting = false; |
|
3947 selectee.$element.addClass("ui-selected"); |
|
3948 selectee.selected = true; |
|
3949 } else { |
|
3950 selectee.$element.removeClass("ui-selecting"); |
|
3951 selectee.selecting = false; |
|
3952 if (selectee.startselected) { |
|
3953 selectee.$element.addClass("ui-unselecting"); |
|
3954 selectee.unselecting = true; |
|
3955 } |
|
3956 // selectable UNSELECTING callback |
|
3957 that._trigger("unselecting", event, { |
|
3958 unselecting: selectee.element |
|
3959 }); |
|
3960 } |
|
3961 } |
|
3962 if (selectee.selected) { |
|
3963 if (!event.metaKey && !event.ctrlKey && !selectee.startselected) { |
|
3964 selectee.$element.removeClass("ui-selected"); |
|
3965 selectee.selected = false; |
|
3966 |
|
3967 selectee.$element.addClass("ui-unselecting"); |
|
3968 selectee.unselecting = true; |
|
3969 // selectable UNSELECTING callback |
|
3970 that._trigger("unselecting", event, { |
|
3971 unselecting: selectee.element |
|
3972 }); |
|
3973 } |
|
3974 } |
|
3975 } |
|
3976 }); |
|
3977 |
|
3978 return false; |
|
3979 }, |
|
3980 |
|
3981 _mouseStop: function(event) { |
|
3982 var that = this; |
|
3983 |
|
3984 this.dragged = false; |
|
3985 |
|
3986 $(".ui-unselecting", this.element[0]).each(function() { |
|
3987 var selectee = $.data(this, "selectable-item"); |
|
3988 selectee.$element.removeClass("ui-unselecting"); |
|
3989 selectee.unselecting = false; |
|
3990 selectee.startselected = false; |
|
3991 that._trigger("unselected", event, { |
|
3992 unselected: selectee.element |
|
3993 }); |
|
3994 }); |
|
3995 $(".ui-selecting", this.element[0]).each(function() { |
|
3996 var selectee = $.data(this, "selectable-item"); |
|
3997 selectee.$element.removeClass("ui-selecting").addClass("ui-selected"); |
|
3998 selectee.selecting = false; |
|
3999 selectee.selected = true; |
|
4000 selectee.startselected = true; |
|
4001 that._trigger("selected", event, { |
|
4002 selected: selectee.element |
|
4003 }); |
|
4004 }); |
|
4005 this._trigger("stop", event); |
|
4006 |
|
4007 this.helper.remove(); |
|
4008 |
|
4009 return false; |
|
4010 } |
|
4011 |
|
4012 }); |
|
4013 |
|
4014 })(jQuery); |
|
4015 (function( $, undefined ) { |
|
4016 |
|
4017 function isOverAxis( x, reference, size ) { |
|
4018 return ( x > reference ) && ( x < ( reference + size ) ); |
|
4019 } |
|
4020 |
|
4021 function isFloating(item) { |
|
4022 return (/left|right/).test(item.css("float")) || (/inline|table-cell/).test(item.css("display")); |
|
4023 } |
|
4024 |
|
4025 $.widget("ui.sortable", $.ui.mouse, { |
|
4026 version: "1.10.4", |
|
4027 widgetEventPrefix: "sort", |
|
4028 ready: false, |
|
4029 options: { |
|
4030 appendTo: "parent", |
|
4031 axis: false, |
|
4032 connectWith: false, |
|
4033 containment: false, |
|
4034 cursor: "auto", |
|
4035 cursorAt: false, |
|
4036 dropOnEmpty: true, |
|
4037 forcePlaceholderSize: false, |
|
4038 forceHelperSize: false, |
|
4039 grid: false, |
|
4040 handle: false, |
|
4041 helper: "original", |
|
4042 items: "> *", |
|
4043 opacity: false, |
|
4044 placeholder: false, |
|
4045 revert: false, |
|
4046 scroll: true, |
|
4047 scrollSensitivity: 20, |
|
4048 scrollSpeed: 20, |
|
4049 scope: "default", |
|
4050 tolerance: "intersect", |
|
4051 zIndex: 1000, |
|
4052 |
|
4053 // callbacks |
|
4054 activate: null, |
|
4055 beforeStop: null, |
|
4056 change: null, |
|
4057 deactivate: null, |
|
4058 out: null, |
|
4059 over: null, |
|
4060 receive: null, |
|
4061 remove: null, |
|
4062 sort: null, |
|
4063 start: null, |
|
4064 stop: null, |
|
4065 update: null |
|
4066 }, |
|
4067 _create: function() { |
|
4068 |
|
4069 var o = this.options; |
|
4070 this.containerCache = {}; |
|
4071 this.element.addClass("ui-sortable"); |
|
4072 |
|
4073 //Get the items |
|
4074 this.refresh(); |
|
4075 |
|
4076 //Let's determine if the items are being displayed horizontally |
|
4077 this.floating = this.items.length ? o.axis === "x" || isFloating(this.items[0].item) : false; |
|
4078 |
|
4079 //Let's determine the parent's offset |
|
4080 this.offset = this.element.offset(); |
|
4081 |
|
4082 //Initialize mouse events for interaction |
|
4083 this._mouseInit(); |
|
4084 |
|
4085 //We're ready to go |
|
4086 this.ready = true; |
|
4087 |
|
4088 }, |
|
4089 |
|
4090 _destroy: function() { |
|
4091 this.element |
|
4092 .removeClass("ui-sortable ui-sortable-disabled"); |
|
4093 this._mouseDestroy(); |
|
4094 |
|
4095 for ( var i = this.items.length - 1; i >= 0; i-- ) { |
|
4096 this.items[i].item.removeData(this.widgetName + "-item"); |
|
4097 } |
|
4098 |
|
4099 return this; |
|
4100 }, |
|
4101 |
|
4102 _setOption: function(key, value){ |
|
4103 if ( key === "disabled" ) { |
|
4104 this.options[ key ] = value; |
|
4105 |
|
4106 this.widget().toggleClass( "ui-sortable-disabled", !!value ); |
|
4107 } else { |
|
4108 // Don't call widget base _setOption for disable as it adds ui-state-disabled class |
|
4109 $.Widget.prototype._setOption.apply(this, arguments); |
|
4110 } |
|
4111 }, |
|
4112 |
|
4113 _mouseCapture: function(event, overrideHandle) { |
|
4114 var currentItem = null, |
|
4115 validHandle = false, |
|
4116 that = this; |
|
4117 |
|
4118 if (this.reverting) { |
|
4119 return false; |
|
4120 } |
|
4121 |
|
4122 if(this.options.disabled || this.options.type === "static") { |
|
4123 return false; |
|
4124 } |
|
4125 |
|
4126 //We have to refresh the items data once first |
|
4127 this._refreshItems(event); |
|
4128 |
|
4129 //Find out if the clicked node (or one of its parents) is a actual item in this.items |
|
4130 $(event.target).parents().each(function() { |
|
4131 if($.data(this, that.widgetName + "-item") === that) { |
|
4132 currentItem = $(this); |
|
4133 return false; |
|
4134 } |
|
4135 }); |
|
4136 if($.data(event.target, that.widgetName + "-item") === that) { |
|
4137 currentItem = $(event.target); |
|
4138 } |
|
4139 |
|
4140 if(!currentItem) { |
|
4141 return false; |
|
4142 } |
|
4143 if(this.options.handle && !overrideHandle) { |
|
4144 $(this.options.handle, currentItem).find("*").addBack().each(function() { |
|
4145 if(this === event.target) { |
|
4146 validHandle = true; |
|
4147 } |
|
4148 }); |
|
4149 if(!validHandle) { |
|
4150 return false; |
|
4151 } |
|
4152 } |
|
4153 |
|
4154 this.currentItem = currentItem; |
|
4155 this._removeCurrentsFromItems(); |
|
4156 return true; |
|
4157 |
|
4158 }, |
|
4159 |
|
4160 _mouseStart: function(event, overrideHandle, noActivation) { |
|
4161 |
|
4162 var i, body, |
|
4163 o = this.options; |
|
4164 |
|
4165 this.currentContainer = this; |
|
4166 |
|
4167 //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture |
|
4168 this.refreshPositions(); |
|
4169 |
|
4170 //Create and append the visible helper |
|
4171 this.helper = this._createHelper(event); |
|
4172 |
|
4173 //Cache the helper size |
|
4174 this._cacheHelperProportions(); |
|
4175 |
|
4176 /* |
|
4177 * - Position generation - |
|
4178 * This block generates everything position related - it's the core of draggables. |
|
4179 */ |
|
4180 |
|
4181 //Cache the margins of the original element |
|
4182 this._cacheMargins(); |
|
4183 |
|
4184 //Get the next scrolling parent |
|
4185 this.scrollParent = this.helper.scrollParent(); |
|
4186 |
|
4187 //The element's absolute position on the page minus margins |
|
4188 this.offset = this.currentItem.offset(); |
|
4189 this.offset = { |
|
4190 top: this.offset.top - this.margins.top, |
|
4191 left: this.offset.left - this.margins.left |
|
4192 }; |
|
4193 |
|
4194 $.extend(this.offset, { |
|
4195 click: { //Where the click happened, relative to the element |
|
4196 left: event.pageX - this.offset.left, |
|
4197 top: event.pageY - this.offset.top |
|
4198 }, |
|
4199 parent: this._getParentOffset(), |
|
4200 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper |
|
4201 }); |
|
4202 |
|
4203 // Only after we got the offset, we can change the helper's position to absolute |
|
4204 // TODO: Still need to figure out a way to make relative sorting possible |
|
4205 this.helper.css("position", "absolute"); |
|
4206 this.cssPosition = this.helper.css("position"); |
|
4207 |
|
4208 //Generate the original position |
|
4209 this.originalPosition = this._generatePosition(event); |
|
4210 this.originalPageX = event.pageX; |
|
4211 this.originalPageY = event.pageY; |
|
4212 |
|
4213 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied |
|
4214 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)); |
|
4215 |
|
4216 //Cache the former DOM position |
|
4217 this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] }; |
|
4218 |
|
4219 //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 |
|
4220 if(this.helper[0] !== this.currentItem[0]) { |
|
4221 this.currentItem.hide(); |
|
4222 } |
|
4223 |
|
4224 //Create the placeholder |
|
4225 this._createPlaceholder(); |
|
4226 |
|
4227 //Set a containment if given in the options |
|
4228 if(o.containment) { |
|
4229 this._setContainment(); |
|
4230 } |
|
4231 |
|
4232 if( o.cursor && o.cursor !== "auto" ) { // cursor option |
|
4233 body = this.document.find( "body" ); |
|
4234 |
|
4235 // support: IE |
|
4236 this.storedCursor = body.css( "cursor" ); |
|
4237 body.css( "cursor", o.cursor ); |
|
4238 |
|
4239 this.storedStylesheet = $( "<style>*{ cursor: "+o.cursor+" !important; }</style>" ).appendTo( body ); |
|
4240 } |
|
4241 |
|
4242 if(o.opacity) { // opacity option |
|
4243 if (this.helper.css("opacity")) { |
|
4244 this._storedOpacity = this.helper.css("opacity"); |
|
4245 } |
|
4246 this.helper.css("opacity", o.opacity); |
|
4247 } |
|
4248 |
|
4249 if(o.zIndex) { // zIndex option |
|
4250 if (this.helper.css("zIndex")) { |
|
4251 this._storedZIndex = this.helper.css("zIndex"); |
|
4252 } |
|
4253 this.helper.css("zIndex", o.zIndex); |
|
4254 } |
|
4255 |
|
4256 //Prepare scrolling |
|
4257 if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") { |
|
4258 this.overflowOffset = this.scrollParent.offset(); |
|
4259 } |
|
4260 |
|
4261 //Call callbacks |
|
4262 this._trigger("start", event, this._uiHash()); |
|
4263 |
|
4264 //Recache the helper size |
|
4265 if(!this._preserveHelperProportions) { |
|
4266 this._cacheHelperProportions(); |
|
4267 } |
|
4268 |
|
4269 |
|
4270 //Post "activate" events to possible containers |
|
4271 if( !noActivation ) { |
|
4272 for ( i = this.containers.length - 1; i >= 0; i-- ) { |
|
4273 this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) ); |
|
4274 } |
|
4275 } |
|
4276 |
|
4277 //Prepare possible droppables |
|
4278 if($.ui.ddmanager) { |
|
4279 $.ui.ddmanager.current = this; |
|
4280 } |
|
4281 |
|
4282 if ($.ui.ddmanager && !o.dropBehaviour) { |
|
4283 $.ui.ddmanager.prepareOffsets(this, event); |
|
4284 } |
|
4285 |
|
4286 this.dragging = true; |
|
4287 |
|
4288 this.helper.addClass("ui-sortable-helper"); |
|
4289 this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position |
|
4290 return true; |
|
4291 |
|
4292 }, |
|
4293 |
|
4294 _mouseDrag: function(event) { |
|
4295 var i, item, itemElement, intersection, |
|
4296 o = this.options, |
|
4297 scrolled = false; |
|
4298 |
|
4299 //Compute the helpers position |
|
4300 this.position = this._generatePosition(event); |
|
4301 this.positionAbs = this._convertPositionTo("absolute"); |
|
4302 |
|
4303 if (!this.lastPositionAbs) { |
|
4304 this.lastPositionAbs = this.positionAbs; |
|
4305 } |
|
4306 |
|
4307 //Do scrolling |
|
4308 if(this.options.scroll) { |
|
4309 if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") { |
|
4310 |
|
4311 if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) { |
|
4312 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed; |
|
4313 } else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) { |
|
4314 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed; |
|
4315 } |
|
4316 |
|
4317 if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) { |
|
4318 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed; |
|
4319 } else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) { |
|
4320 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed; |
|
4321 } |
|
4322 |
|
4323 } else { |
|
4324 |
|
4325 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) { |
|
4326 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); |
|
4327 } else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) { |
|
4328 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); |
|
4329 } |
|
4330 |
|
4331 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) { |
|
4332 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); |
|
4333 } else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) { |
|
4334 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); |
|
4335 } |
|
4336 |
|
4337 } |
|
4338 |
|
4339 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) { |
|
4340 $.ui.ddmanager.prepareOffsets(this, event); |
|
4341 } |
|
4342 } |
|
4343 |
|
4344 //Regenerate the absolute position used for position checks |
|
4345 this.positionAbs = this._convertPositionTo("absolute"); |
|
4346 |
|
4347 //Set the helper position |
|
4348 if(!this.options.axis || this.options.axis !== "y") { |
|
4349 this.helper[0].style.left = this.position.left+"px"; |
|
4350 } |
|
4351 if(!this.options.axis || this.options.axis !== "x") { |
|
4352 this.helper[0].style.top = this.position.top+"px"; |
|
4353 } |
|
4354 |
|
4355 //Rearrange |
|
4356 for (i = this.items.length - 1; i >= 0; i--) { |
|
4357 |
|
4358 //Cache variables and intersection, continue if no intersection |
|
4359 item = this.items[i]; |
|
4360 itemElement = item.item[0]; |
|
4361 intersection = this._intersectsWithPointer(item); |
|
4362 if (!intersection) { |
|
4363 continue; |
|
4364 } |
|
4365 |
|
4366 // Only put the placeholder inside the current Container, skip all |
|
4367 // items from other containers. This works because when moving |
|
4368 // an item from one container to another the |
|
4369 // currentContainer is switched before the placeholder is moved. |
|
4370 // |
|
4371 // Without this, moving items in "sub-sortables" can cause |
|
4372 // the placeholder to jitter beetween the outer and inner container. |
|
4373 if (item.instance !== this.currentContainer) { |
|
4374 continue; |
|
4375 } |
|
4376 |
|
4377 // cannot intersect with itself |
|
4378 // no useless actions that have been done before |
|
4379 // no action if the item moved is the parent of the item checked |
|
4380 if (itemElement !== this.currentItem[0] && |
|
4381 this.placeholder[intersection === 1 ? "next" : "prev"]()[0] !== itemElement && |
|
4382 !$.contains(this.placeholder[0], itemElement) && |
|
4383 (this.options.type === "semi-dynamic" ? !$.contains(this.element[0], itemElement) : true) |
|
4384 ) { |
|
4385 |
|
4386 this.direction = intersection === 1 ? "down" : "up"; |
|
4387 |
|
4388 if (this.options.tolerance === "pointer" || this._intersectsWithSides(item)) { |
|
4389 this._rearrange(event, item); |
|
4390 } else { |
|
4391 break; |
|
4392 } |
|
4393 |
|
4394 this._trigger("change", event, this._uiHash()); |
|
4395 break; |
|
4396 } |
|
4397 } |
|
4398 |
|
4399 //Post events to containers |
|
4400 this._contactContainers(event); |
|
4401 |
|
4402 //Interconnect with droppables |
|
4403 if($.ui.ddmanager) { |
|
4404 $.ui.ddmanager.drag(this, event); |
|
4405 } |
|
4406 |
|
4407 //Call callbacks |
|
4408 this._trigger("sort", event, this._uiHash()); |
|
4409 |
|
4410 this.lastPositionAbs = this.positionAbs; |
|
4411 return false; |
|
4412 |
|
4413 }, |
|
4414 |
|
4415 _mouseStop: function(event, noPropagation) { |
|
4416 |
|
4417 if(!event) { |
|
4418 return; |
|
4419 } |
|
4420 |
|
4421 //If we are using droppables, inform the manager about the drop |
|
4422 if ($.ui.ddmanager && !this.options.dropBehaviour) { |
|
4423 $.ui.ddmanager.drop(this, event); |
|
4424 } |
|
4425 |
|
4426 if(this.options.revert) { |
|
4427 var that = this, |
|
4428 cur = this.placeholder.offset(), |
|
4429 axis = this.options.axis, |
|
4430 animation = {}; |
|
4431 |
|
4432 if ( !axis || axis === "x" ) { |
|
4433 animation.left = cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollLeft); |
|
4434 } |
|
4435 if ( !axis || axis === "y" ) { |
|
4436 animation.top = cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollTop); |
|
4437 } |
|
4438 this.reverting = true; |
|
4439 $(this.helper).animate( animation, parseInt(this.options.revert, 10) || 500, function() { |
|
4440 that._clear(event); |
|
4441 }); |
|
4442 } else { |
|
4443 this._clear(event, noPropagation); |
|
4444 } |
|
4445 |
|
4446 return false; |
|
4447 |
|
4448 }, |
|
4449 |
|
4450 cancel: function() { |
|
4451 |
|
4452 if(this.dragging) { |
|
4453 |
|
4454 this._mouseUp({ target: null }); |
|
4455 |
|
4456 if(this.options.helper === "original") { |
|
4457 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); |
|
4458 } else { |
|
4459 this.currentItem.show(); |
|
4460 } |
|
4461 |
|
4462 //Post deactivating events to containers |
|
4463 for (var i = this.containers.length - 1; i >= 0; i--){ |
|
4464 this.containers[i]._trigger("deactivate", null, this._uiHash(this)); |
|
4465 if(this.containers[i].containerCache.over) { |
|
4466 this.containers[i]._trigger("out", null, this._uiHash(this)); |
|
4467 this.containers[i].containerCache.over = 0; |
|
4468 } |
|
4469 } |
|
4470 |
|
4471 } |
|
4472 |
|
4473 if (this.placeholder) { |
|
4474 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! |
|
4475 if(this.placeholder[0].parentNode) { |
|
4476 this.placeholder[0].parentNode.removeChild(this.placeholder[0]); |
|
4477 } |
|
4478 if(this.options.helper !== "original" && this.helper && this.helper[0].parentNode) { |
|
4479 this.helper.remove(); |
|
4480 } |
|
4481 |
|
4482 $.extend(this, { |
|
4483 helper: null, |
|
4484 dragging: false, |
|
4485 reverting: false, |
|
4486 _noFinalSort: null |
|
4487 }); |
|
4488 |
|
4489 if(this.domPosition.prev) { |
|
4490 $(this.domPosition.prev).after(this.currentItem); |
|
4491 } else { |
|
4492 $(this.domPosition.parent).prepend(this.currentItem); |
|
4493 } |
|
4494 } |
|
4495 |
|
4496 return this; |
|
4497 |
|
4498 }, |
|
4499 |
|
4500 serialize: function(o) { |
|
4501 |
|
4502 var items = this._getItemsAsjQuery(o && o.connected), |
|
4503 str = []; |
|
4504 o = o || {}; |
|
4505 |
|
4506 $(items).each(function() { |
|
4507 var res = ($(o.item || this).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[\-=_](.+)/)); |
|
4508 if (res) { |
|
4509 str.push((o.key || res[1]+"[]")+"="+(o.key && o.expression ? res[1] : res[2])); |
|
4510 } |
|
4511 }); |
|
4512 |
|
4513 if(!str.length && o.key) { |
|
4514 str.push(o.key + "="); |
|
4515 } |
|
4516 |
|
4517 return str.join("&"); |
|
4518 |
|
4519 }, |
|
4520 |
|
4521 toArray: function(o) { |
|
4522 |
|
4523 var items = this._getItemsAsjQuery(o && o.connected), |
|
4524 ret = []; |
|
4525 |
|
4526 o = o || {}; |
|
4527 |
|
4528 items.each(function() { ret.push($(o.item || this).attr(o.attribute || "id") || ""); }); |
|
4529 return ret; |
|
4530 |
|
4531 }, |
|
4532 |
|
4533 /* Be careful with the following core functions */ |
|
4534 _intersectsWith: function(item) { |
|
4535 |
|
4536 var x1 = this.positionAbs.left, |
|
4537 x2 = x1 + this.helperProportions.width, |
|
4538 y1 = this.positionAbs.top, |
|
4539 y2 = y1 + this.helperProportions.height, |
|
4540 l = item.left, |
|
4541 r = l + item.width, |
|
4542 t = item.top, |
|
4543 b = t + item.height, |
|
4544 dyClick = this.offset.click.top, |
|
4545 dxClick = this.offset.click.left, |
|
4546 isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t && ( y1 + dyClick ) < b ), |
|
4547 isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l && ( x1 + dxClick ) < r ), |
|
4548 isOverElement = isOverElementHeight && isOverElementWidth; |
|
4549 |
|
4550 if ( this.options.tolerance === "pointer" || |
|
4551 this.options.forcePointerForContainers || |
|
4552 (this.options.tolerance !== "pointer" && this.helperProportions[this.floating ? "width" : "height"] > item[this.floating ? "width" : "height"]) |
|
4553 ) { |
|
4554 return isOverElement; |
|
4555 } else { |
|
4556 |
|
4557 return (l < x1 + (this.helperProportions.width / 2) && // Right Half |
|
4558 x2 - (this.helperProportions.width / 2) < r && // Left Half |
|
4559 t < y1 + (this.helperProportions.height / 2) && // Bottom Half |
|
4560 y2 - (this.helperProportions.height / 2) < b ); // Top Half |
|
4561 |
|
4562 } |
|
4563 }, |
|
4564 |
|
4565 _intersectsWithPointer: function(item) { |
|
4566 |
|
4567 var isOverElementHeight = (this.options.axis === "x") || isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height), |
|
4568 isOverElementWidth = (this.options.axis === "y") || isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width), |
|
4569 isOverElement = isOverElementHeight && isOverElementWidth, |
|
4570 verticalDirection = this._getDragVerticalDirection(), |
|
4571 horizontalDirection = this._getDragHorizontalDirection(); |
|
4572 |
|
4573 if (!isOverElement) { |
|
4574 return false; |
|
4575 } |
|
4576 |
|
4577 return this.floating ? |
|
4578 ( ((horizontalDirection && horizontalDirection === "right") || verticalDirection === "down") ? 2 : 1 ) |
|
4579 : ( verticalDirection && (verticalDirection === "down" ? 2 : 1) ); |
|
4580 |
|
4581 }, |
|
4582 |
|
4583 _intersectsWithSides: function(item) { |
|
4584 |
|
4585 var isOverBottomHalf = isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height), |
|
4586 isOverRightHalf = isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width), |
|
4587 verticalDirection = this._getDragVerticalDirection(), |
|
4588 horizontalDirection = this._getDragHorizontalDirection(); |
|
4589 |
|
4590 if (this.floating && horizontalDirection) { |
|
4591 return ((horizontalDirection === "right" && isOverRightHalf) || (horizontalDirection === "left" && !isOverRightHalf)); |
|
4592 } else { |
|
4593 return verticalDirection && ((verticalDirection === "down" && isOverBottomHalf) || (verticalDirection === "up" && !isOverBottomHalf)); |
|
4594 } |
|
4595 |
|
4596 }, |
|
4597 |
|
4598 _getDragVerticalDirection: function() { |
|
4599 var delta = this.positionAbs.top - this.lastPositionAbs.top; |
|
4600 return delta !== 0 && (delta > 0 ? "down" : "up"); |
|
4601 }, |
|
4602 |
|
4603 _getDragHorizontalDirection: function() { |
|
4604 var delta = this.positionAbs.left - this.lastPositionAbs.left; |
|
4605 return delta !== 0 && (delta > 0 ? "right" : "left"); |
|
4606 }, |
|
4607 |
|
4608 refresh: function(event) { |
|
4609 this._refreshItems(event); |
|
4610 this.refreshPositions(); |
|
4611 return this; |
|
4612 }, |
|
4613 |
|
4614 _connectWith: function() { |
|
4615 var options = this.options; |
|
4616 return options.connectWith.constructor === String ? [options.connectWith] : options.connectWith; |
|
4617 }, |
|
4618 |
|
4619 _getItemsAsjQuery: function(connected) { |
|
4620 |
|
4621 var i, j, cur, inst, |
|
4622 items = [], |
|
4623 queries = [], |
|
4624 connectWith = this._connectWith(); |
|
4625 |
|
4626 if(connectWith && connected) { |
|
4627 for (i = connectWith.length - 1; i >= 0; i--){ |
|
4628 cur = $(connectWith[i]); |
|
4629 for ( j = cur.length - 1; j >= 0; j--){ |
|
4630 inst = $.data(cur[j], this.widgetFullName); |
|
4631 if(inst && inst !== this && !inst.options.disabled) { |
|
4632 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]); |
|
4633 } |
|
4634 } |
|
4635 } |
|
4636 } |
|
4637 |
|
4638 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]); |
|
4639 |
|
4640 function addItems() { |
|
4641 items.push( this ); |
|
4642 } |
|
4643 for (i = queries.length - 1; i >= 0; i--){ |
|
4644 queries[i][0].each( addItems ); |
|
4645 } |
|
4646 |
|
4647 return $(items); |
|
4648 |
|
4649 }, |
|
4650 |
|
4651 _removeCurrentsFromItems: function() { |
|
4652 |
|
4653 var list = this.currentItem.find(":data(" + this.widgetName + "-item)"); |
|
4654 |
|
4655 this.items = $.grep(this.items, function (item) { |
|
4656 for (var j=0; j < list.length; j++) { |
|
4657 if(list[j] === item.item[0]) { |
|
4658 return false; |
|
4659 } |
|
4660 } |
|
4661 return true; |
|
4662 }); |
|
4663 |
|
4664 }, |
|
4665 |
|
4666 _refreshItems: function(event) { |
|
4667 |
|
4668 this.items = []; |
|
4669 this.containers = [this]; |
|
4670 |
|
4671 var i, j, cur, inst, targetData, _queries, item, queriesLength, |
|
4672 items = this.items, |
|
4673 queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]], |
|
4674 connectWith = this._connectWith(); |
|
4675 |
|
4676 if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down |
|
4677 for (i = connectWith.length - 1; i >= 0; i--){ |
|
4678 cur = $(connectWith[i]); |
|
4679 for (j = cur.length - 1; j >= 0; j--){ |
|
4680 inst = $.data(cur[j], this.widgetFullName); |
|
4681 if(inst && inst !== this && !inst.options.disabled) { |
|
4682 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]); |
|
4683 this.containers.push(inst); |
|
4684 } |
|
4685 } |
|
4686 } |
|
4687 } |
|
4688 |
|
4689 for (i = queries.length - 1; i >= 0; i--) { |
|
4690 targetData = queries[i][1]; |
|
4691 _queries = queries[i][0]; |
|
4692 |
|
4693 for (j=0, queriesLength = _queries.length; j < queriesLength; j++) { |
|
4694 item = $(_queries[j]); |
|
4695 |
|
4696 item.data(this.widgetName + "-item", targetData); // Data for target checking (mouse manager) |
|
4697 |
|
4698 items.push({ |
|
4699 item: item, |
|
4700 instance: targetData, |
|
4701 width: 0, height: 0, |
|
4702 left: 0, top: 0 |
|
4703 }); |
|
4704 } |
|
4705 } |
|
4706 |
|
4707 }, |
|
4708 |
|
4709 refreshPositions: function(fast) { |
|
4710 |
|
4711 //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change |
|
4712 if(this.offsetParent && this.helper) { |
|
4713 this.offset.parent = this._getParentOffset(); |
|
4714 } |
|
4715 |
|
4716 var i, item, t, p; |
|
4717 |
|
4718 for (i = this.items.length - 1; i >= 0; i--){ |
|
4719 item = this.items[i]; |
|
4720 |
|
4721 //We ignore calculating positions of all connected containers when we're not over them |
|
4722 if(item.instance !== this.currentContainer && this.currentContainer && item.item[0] !== this.currentItem[0]) { |
|
4723 continue; |
|
4724 } |
|
4725 |
|
4726 t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item; |
|
4727 |
|
4728 if (!fast) { |
|
4729 item.width = t.outerWidth(); |
|
4730 item.height = t.outerHeight(); |
|
4731 } |
|
4732 |
|
4733 p = t.offset(); |
|
4734 item.left = p.left; |
|
4735 item.top = p.top; |
|
4736 } |
|
4737 |
|
4738 if(this.options.custom && this.options.custom.refreshContainers) { |
|
4739 this.options.custom.refreshContainers.call(this); |
|
4740 } else { |
|
4741 for (i = this.containers.length - 1; i >= 0; i--){ |
|
4742 p = this.containers[i].element.offset(); |
|
4743 this.containers[i].containerCache.left = p.left; |
|
4744 this.containers[i].containerCache.top = p.top; |
|
4745 this.containers[i].containerCache.width = this.containers[i].element.outerWidth(); |
|
4746 this.containers[i].containerCache.height = this.containers[i].element.outerHeight(); |
|
4747 } |
|
4748 } |
|
4749 |
|
4750 return this; |
|
4751 }, |
|
4752 |
|
4753 _createPlaceholder: function(that) { |
|
4754 that = that || this; |
|
4755 var className, |
|
4756 o = that.options; |
|
4757 |
|
4758 if(!o.placeholder || o.placeholder.constructor === String) { |
|
4759 className = o.placeholder; |
|
4760 o.placeholder = { |
|
4761 element: function() { |
|
4762 |
|
4763 var nodeName = that.currentItem[0].nodeName.toLowerCase(), |
|
4764 element = $( "<" + nodeName + ">", that.document[0] ) |
|
4765 .addClass(className || that.currentItem[0].className+" ui-sortable-placeholder") |
|
4766 .removeClass("ui-sortable-helper"); |
|
4767 |
|
4768 if ( nodeName === "tr" ) { |
|
4769 that.currentItem.children().each(function() { |
|
4770 $( "<td> </td>", that.document[0] ) |
|
4771 .attr( "colspan", $( this ).attr( "colspan" ) || 1 ) |
|
4772 .appendTo( element ); |
|
4773 }); |
|
4774 } else if ( nodeName === "img" ) { |
|
4775 element.attr( "src", that.currentItem.attr( "src" ) ); |
|
4776 } |
|
4777 |
|
4778 if ( !className ) { |
|
4779 element.css( "visibility", "hidden" ); |
|
4780 } |
|
4781 |
|
4782 return element; |
|
4783 }, |
|
4784 update: function(container, p) { |
|
4785 |
|
4786 // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that |
|
4787 // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified |
|
4788 if(className && !o.forcePlaceholderSize) { |
|
4789 return; |
|
4790 } |
|
4791 |
|
4792 //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 |
|
4793 if(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css("paddingTop")||0, 10) - parseInt(that.currentItem.css("paddingBottom")||0, 10)); } |
|
4794 if(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css("paddingLeft")||0, 10) - parseInt(that.currentItem.css("paddingRight")||0, 10)); } |
|
4795 } |
|
4796 }; |
|
4797 } |
|
4798 |
|
4799 //Create the placeholder |
|
4800 that.placeholder = $(o.placeholder.element.call(that.element, that.currentItem)); |
|
4801 |
|
4802 //Append it after the actual current item |
|
4803 that.currentItem.after(that.placeholder); |
|
4804 |
|
4805 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317) |
|
4806 o.placeholder.update(that, that.placeholder); |
|
4807 |
|
4808 }, |
|
4809 |
|
4810 _contactContainers: function(event) { |
|
4811 var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, base, cur, nearBottom, floating, |
|
4812 innermostContainer = null, |
|
4813 innermostIndex = null; |
|
4814 |
|
4815 // get innermost container that intersects with item |
|
4816 for (i = this.containers.length - 1; i >= 0; i--) { |
|
4817 |
|
4818 // never consider a container that's located within the item itself |
|
4819 if($.contains(this.currentItem[0], this.containers[i].element[0])) { |
|
4820 continue; |
|
4821 } |
|
4822 |
|
4823 if(this._intersectsWith(this.containers[i].containerCache)) { |
|
4824 |
|
4825 // if we've already found a container and it's more "inner" than this, then continue |
|
4826 if(innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0])) { |
|
4827 continue; |
|
4828 } |
|
4829 |
|
4830 innermostContainer = this.containers[i]; |
|
4831 innermostIndex = i; |
|
4832 |
|
4833 } else { |
|
4834 // container doesn't intersect. trigger "out" event if necessary |
|
4835 if(this.containers[i].containerCache.over) { |
|
4836 this.containers[i]._trigger("out", event, this._uiHash(this)); |
|
4837 this.containers[i].containerCache.over = 0; |
|
4838 } |
|
4839 } |
|
4840 |
|
4841 } |
|
4842 |
|
4843 // if no intersecting containers found, return |
|
4844 if(!innermostContainer) { |
|
4845 return; |
|
4846 } |
|
4847 |
|
4848 // move the item into the container if it's not there already |
|
4849 if(this.containers.length === 1) { |
|
4850 if (!this.containers[innermostIndex].containerCache.over) { |
|
4851 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); |
|
4852 this.containers[innermostIndex].containerCache.over = 1; |
|
4853 } |
|
4854 } else { |
|
4855 |
|
4856 //When entering a new container, we will find the item with the least distance and append our item near it |
|
4857 dist = 10000; |
|
4858 itemWithLeastDistance = null; |
|
4859 floating = innermostContainer.floating || isFloating(this.currentItem); |
|
4860 posProperty = floating ? "left" : "top"; |
|
4861 sizeProperty = floating ? "width" : "height"; |
|
4862 base = this.positionAbs[posProperty] + this.offset.click[posProperty]; |
|
4863 for (j = this.items.length - 1; j >= 0; j--) { |
|
4864 if(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) { |
|
4865 continue; |
|
4866 } |
|
4867 if(this.items[j].item[0] === this.currentItem[0]) { |
|
4868 continue; |
|
4869 } |
|
4870 if (floating && !isOverAxis(this.positionAbs.top + this.offset.click.top, this.items[j].top, this.items[j].height)) { |
|
4871 continue; |
|
4872 } |
|
4873 cur = this.items[j].item.offset()[posProperty]; |
|
4874 nearBottom = false; |
|
4875 if(Math.abs(cur - base) > Math.abs(cur + this.items[j][sizeProperty] - base)){ |
|
4876 nearBottom = true; |
|
4877 cur += this.items[j][sizeProperty]; |
|
4878 } |
|
4879 |
|
4880 if(Math.abs(cur - base) < dist) { |
|
4881 dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j]; |
|
4882 this.direction = nearBottom ? "up": "down"; |
|
4883 } |
|
4884 } |
|
4885 |
|
4886 //Check if dropOnEmpty is enabled |
|
4887 if(!itemWithLeastDistance && !this.options.dropOnEmpty) { |
|
4888 return; |
|
4889 } |
|
4890 |
|
4891 if(this.currentContainer === this.containers[innermostIndex]) { |
|
4892 return; |
|
4893 } |
|
4894 |
|
4895 itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true); |
|
4896 this._trigger("change", event, this._uiHash()); |
|
4897 this.containers[innermostIndex]._trigger("change", event, this._uiHash(this)); |
|
4898 this.currentContainer = this.containers[innermostIndex]; |
|
4899 |
|
4900 //Update the placeholder |
|
4901 this.options.placeholder.update(this.currentContainer, this.placeholder); |
|
4902 |
|
4903 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); |
|
4904 this.containers[innermostIndex].containerCache.over = 1; |
|
4905 } |
|
4906 |
|
4907 |
|
4908 }, |
|
4909 |
|
4910 _createHelper: function(event) { |
|
4911 |
|
4912 var o = this.options, |
|
4913 helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper === "clone" ? this.currentItem.clone() : this.currentItem); |
|
4914 |
|
4915 //Add the helper to the DOM if that didn't happen already |
|
4916 if(!helper.parents("body").length) { |
|
4917 $(o.appendTo !== "parent" ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]); |
|
4918 } |
|
4919 |
|
4920 if(helper[0] === this.currentItem[0]) { |
|
4921 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") }; |
|
4922 } |
|
4923 |
|
4924 if(!helper[0].style.width || o.forceHelperSize) { |
|
4925 helper.width(this.currentItem.width()); |
|
4926 } |
|
4927 if(!helper[0].style.height || o.forceHelperSize) { |
|
4928 helper.height(this.currentItem.height()); |
|
4929 } |
|
4930 |
|
4931 return helper; |
|
4932 |
|
4933 }, |
|
4934 |
|
4935 _adjustOffsetFromHelper: function(obj) { |
|
4936 if (typeof obj === "string") { |
|
4937 obj = obj.split(" "); |
|
4938 } |
|
4939 if ($.isArray(obj)) { |
|
4940 obj = {left: +obj[0], top: +obj[1] || 0}; |
|
4941 } |
|
4942 if ("left" in obj) { |
|
4943 this.offset.click.left = obj.left + this.margins.left; |
|
4944 } |
|
4945 if ("right" in obj) { |
|
4946 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; |
|
4947 } |
|
4948 if ("top" in obj) { |
|
4949 this.offset.click.top = obj.top + this.margins.top; |
|
4950 } |
|
4951 if ("bottom" in obj) { |
|
4952 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; |
|
4953 } |
|
4954 }, |
|
4955 |
|
4956 _getParentOffset: function() { |
|
4957 |
|
4958 |
|
4959 //Get the offsetParent and cache its position |
|
4960 this.offsetParent = this.helper.offsetParent(); |
|
4961 var po = this.offsetParent.offset(); |
|
4962 |
|
4963 // This is a special case where we need to modify a offset calculated on start, since the following happened: |
|
4964 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent |
|
4965 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that |
|
4966 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag |
|
4967 if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) { |
|
4968 po.left += this.scrollParent.scrollLeft(); |
|
4969 po.top += this.scrollParent.scrollTop(); |
|
4970 } |
|
4971 |
|
4972 // This needs to be actually done for all browsers, since pageX/pageY includes this information |
|
4973 // with an ugly IE fix |
|
4974 if( this.offsetParent[0] === document.body || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) { |
|
4975 po = { top: 0, left: 0 }; |
|
4976 } |
|
4977 |
|
4978 return { |
|
4979 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0), |
|
4980 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0) |
|
4981 }; |
|
4982 |
|
4983 }, |
|
4984 |
|
4985 _getRelativeOffset: function() { |
|
4986 |
|
4987 if(this.cssPosition === "relative") { |
|
4988 var p = this.currentItem.position(); |
|
4989 return { |
|
4990 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(), |
|
4991 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft() |
|
4992 }; |
|
4993 } else { |
|
4994 return { top: 0, left: 0 }; |
|
4995 } |
|
4996 |
|
4997 }, |
|
4998 |
|
4999 _cacheMargins: function() { |
|
5000 this.margins = { |
|
5001 left: (parseInt(this.currentItem.css("marginLeft"),10) || 0), |
|
5002 top: (parseInt(this.currentItem.css("marginTop"),10) || 0) |
|
5003 }; |
|
5004 }, |
|
5005 |
|
5006 _cacheHelperProportions: function() { |
|
5007 this.helperProportions = { |
|
5008 width: this.helper.outerWidth(), |
|
5009 height: this.helper.outerHeight() |
|
5010 }; |
|
5011 }, |
|
5012 |
|
5013 _setContainment: function() { |
|
5014 |
|
5015 var ce, co, over, |
|
5016 o = this.options; |
|
5017 if(o.containment === "parent") { |
|
5018 o.containment = this.helper[0].parentNode; |
|
5019 } |
|
5020 if(o.containment === "document" || o.containment === "window") { |
|
5021 this.containment = [ |
|
5022 0 - this.offset.relative.left - this.offset.parent.left, |
|
5023 0 - this.offset.relative.top - this.offset.parent.top, |
|
5024 $(o.containment === "document" ? document : window).width() - this.helperProportions.width - this.margins.left, |
|
5025 ($(o.containment === "document" ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top |
|
5026 ]; |
|
5027 } |
|
5028 |
|
5029 if(!(/^(document|window|parent)$/).test(o.containment)) { |
|
5030 ce = $(o.containment)[0]; |
|
5031 co = $(o.containment).offset(); |
|
5032 over = ($(ce).css("overflow") !== "hidden"); |
|
5033 |
|
5034 this.containment = [ |
|
5035 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left, |
|
5036 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top, |
|
5037 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, |
|
5038 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 |
|
5039 ]; |
|
5040 } |
|
5041 |
|
5042 }, |
|
5043 |
|
5044 _convertPositionTo: function(d, pos) { |
|
5045 |
|
5046 if(!pos) { |
|
5047 pos = this.position; |
|
5048 } |
|
5049 var mod = d === "absolute" ? 1 : -1, |
|
5050 scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, |
|
5051 scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); |
|
5052 |
|
5053 return { |
|
5054 top: ( |
|
5055 pos.top + // The absolute mouse position |
|
5056 this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent |
|
5057 this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border) |
|
5058 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod) |
|
5059 ), |
|
5060 left: ( |
|
5061 pos.left + // The absolute mouse position |
|
5062 this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent |
|
5063 this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border) |
|
5064 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod) |
|
5065 ) |
|
5066 }; |
|
5067 |
|
5068 }, |
|
5069 |
|
5070 _generatePosition: function(event) { |
|
5071 |
|
5072 var top, left, |
|
5073 o = this.options, |
|
5074 pageX = event.pageX, |
|
5075 pageY = event.pageY, |
|
5076 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); |
|
5077 |
|
5078 // This is another very weird special case that only happens for relative elements: |
|
5079 // 1. If the css position is relative |
|
5080 // 2. and the scroll parent is the document or similar to the offset parent |
|
5081 // we have to refresh the relative offset during the scroll so there are no jumps |
|
5082 if(this.cssPosition === "relative" && !(this.scrollParent[0] !== document && this.scrollParent[0] !== this.offsetParent[0])) { |
|
5083 this.offset.relative = this._getRelativeOffset(); |
|
5084 } |
|
5085 |
|
5086 /* |
|
5087 * - Position constraining - |
|
5088 * Constrain the position to a mix of grid, containment. |
|
5089 */ |
|
5090 |
|
5091 if(this.originalPosition) { //If we are not dragging yet, we won't check for options |
|
5092 |
|
5093 if(this.containment) { |
|
5094 if(event.pageX - this.offset.click.left < this.containment[0]) { |
|
5095 pageX = this.containment[0] + this.offset.click.left; |
|
5096 } |
|
5097 if(event.pageY - this.offset.click.top < this.containment[1]) { |
|
5098 pageY = this.containment[1] + this.offset.click.top; |
|
5099 } |
|
5100 if(event.pageX - this.offset.click.left > this.containment[2]) { |
|
5101 pageX = this.containment[2] + this.offset.click.left; |
|
5102 } |
|
5103 if(event.pageY - this.offset.click.top > this.containment[3]) { |
|
5104 pageY = this.containment[3] + this.offset.click.top; |
|
5105 } |
|
5106 } |
|
5107 |
|
5108 if(o.grid) { |
|
5109 top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1]; |
|
5110 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; |
|
5111 |
|
5112 left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0]; |
|
5113 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; |
|
5114 } |
|
5115 |
|
5116 } |
|
5117 |
|
5118 return { |
|
5119 top: ( |
|
5120 pageY - // The absolute mouse position |
|
5121 this.offset.click.top - // Click offset (relative to the element) |
|
5122 this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent |
|
5123 this.offset.parent.top + // The offsetParent's offset without borders (offset + border) |
|
5124 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) )) |
|
5125 ), |
|
5126 left: ( |
|
5127 pageX - // The absolute mouse position |
|
5128 this.offset.click.left - // Click offset (relative to the element) |
|
5129 this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent |
|
5130 this.offset.parent.left + // The offsetParent's offset without borders (offset + border) |
|
5131 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() )) |
|
5132 ) |
|
5133 }; |
|
5134 |
|
5135 }, |
|
5136 |
|
5137 _rearrange: function(event, i, a, hardRefresh) { |
|
5138 |
|
5139 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)); |
|
5140 |
|
5141 //Various things done here to improve the performance: |
|
5142 // 1. we create a setTimeout, that calls refreshPositions |
|
5143 // 2. on the instance, we have a counter variable, that get's higher after every append |
|
5144 // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same |
|
5145 // 4. this lets only the last addition to the timeout stack through |
|
5146 this.counter = this.counter ? ++this.counter : 1; |
|
5147 var counter = this.counter; |
|
5148 |
|
5149 this._delay(function() { |
|
5150 if(counter === this.counter) { |
|
5151 this.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove |
|
5152 } |
|
5153 }); |
|
5154 |
|
5155 }, |
|
5156 |
|
5157 _clear: function(event, noPropagation) { |
|
5158 |
|
5159 this.reverting = false; |
|
5160 // We delay all events that have to be triggered to after the point where the placeholder has been removed and |
|
5161 // everything else normalized again |
|
5162 var i, |
|
5163 delayedTriggers = []; |
|
5164 |
|
5165 // We first have to update the dom position of the actual currentItem |
|
5166 // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088) |
|
5167 if(!this._noFinalSort && this.currentItem.parent().length) { |
|
5168 this.placeholder.before(this.currentItem); |
|
5169 } |
|
5170 this._noFinalSort = null; |
|
5171 |
|
5172 if(this.helper[0] === this.currentItem[0]) { |
|
5173 for(i in this._storedCSS) { |
|
5174 if(this._storedCSS[i] === "auto" || this._storedCSS[i] === "static") { |
|
5175 this._storedCSS[i] = ""; |
|
5176 } |
|
5177 } |
|
5178 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); |
|
5179 } else { |
|
5180 this.currentItem.show(); |
|
5181 } |
|
5182 |
|
5183 if(this.fromOutside && !noPropagation) { |
|
5184 delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); }); |
|
5185 } |
|
5186 if((this.fromOutside || this.domPosition.prev !== this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent !== this.currentItem.parent()[0]) && !noPropagation) { |
|
5187 delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed |
|
5188 } |
|
5189 |
|
5190 // Check if the items Container has Changed and trigger appropriate |
|
5191 // events. |
|
5192 if (this !== this.currentContainer) { |
|
5193 if(!noPropagation) { |
|
5194 delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); }); |
|
5195 delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.currentContainer)); |
|
5196 delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.currentContainer)); |
|
5197 } |
|
5198 } |
|
5199 |
|
5200 |
|
5201 //Post events to containers |
|
5202 function delayEvent( type, instance, container ) { |
|
5203 return function( event ) { |
|
5204 container._trigger( type, event, instance._uiHash( instance ) ); |
|
5205 }; |
|
5206 } |
|
5207 for (i = this.containers.length - 1; i >= 0; i--){ |
|
5208 if (!noPropagation) { |
|
5209 delayedTriggers.push( delayEvent( "deactivate", this, this.containers[ i ] ) ); |
|
5210 } |
|
5211 if(this.containers[i].containerCache.over) { |
|
5212 delayedTriggers.push( delayEvent( "out", this, this.containers[ i ] ) ); |
|
5213 this.containers[i].containerCache.over = 0; |
|
5214 } |
|
5215 } |
|
5216 |
|
5217 //Do what was originally in plugins |
|
5218 if ( this.storedCursor ) { |
|
5219 this.document.find( "body" ).css( "cursor", this.storedCursor ); |
|
5220 this.storedStylesheet.remove(); |
|
5221 } |
|
5222 if(this._storedOpacity) { |
|
5223 this.helper.css("opacity", this._storedOpacity); |
|
5224 } |
|
5225 if(this._storedZIndex) { |
|
5226 this.helper.css("zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex); |
|
5227 } |
|
5228 |
|
5229 this.dragging = false; |
|
5230 if(this.cancelHelperRemoval) { |
|
5231 if(!noPropagation) { |
|
5232 this._trigger("beforeStop", event, this._uiHash()); |
|
5233 for (i=0; i < delayedTriggers.length; i++) { |
|
5234 delayedTriggers[i].call(this, event); |
|
5235 } //Trigger all delayed events |
|
5236 this._trigger("stop", event, this._uiHash()); |
|
5237 } |
|
5238 |
|
5239 this.fromOutside = false; |
|
5240 return false; |
|
5241 } |
|
5242 |
|
5243 if(!noPropagation) { |
|
5244 this._trigger("beforeStop", event, this._uiHash()); |
|
5245 } |
|
5246 |
|
5247 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! |
|
5248 this.placeholder[0].parentNode.removeChild(this.placeholder[0]); |
|
5249 |
|
5250 if(this.helper[0] !== this.currentItem[0]) { |
|
5251 this.helper.remove(); |
|
5252 } |
|
5253 this.helper = null; |
|
5254 |
|
5255 if(!noPropagation) { |
|
5256 for (i=0; i < delayedTriggers.length; i++) { |
|
5257 delayedTriggers[i].call(this, event); |
|
5258 } //Trigger all delayed events |
|
5259 this._trigger("stop", event, this._uiHash()); |
|
5260 } |
|
5261 |
|
5262 this.fromOutside = false; |
|
5263 return true; |
|
5264 |
|
5265 }, |
|
5266 |
|
5267 _trigger: function() { |
|
5268 if ($.Widget.prototype._trigger.apply(this, arguments) === false) { |
|
5269 this.cancel(); |
|
5270 } |
|
5271 }, |
|
5272 |
|
5273 _uiHash: function(_inst) { |
|
5274 var inst = _inst || this; |
|
5275 return { |
|
5276 helper: inst.helper, |
|
5277 placeholder: inst.placeholder || $([]), |
|
5278 position: inst.position, |
|
5279 originalPosition: inst.originalPosition, |
|
5280 offset: inst.positionAbs, |
|
5281 item: inst.currentItem, |
|
5282 sender: _inst ? _inst.element : null |
|
5283 }; |
|
5284 } |
|
5285 |
|
5286 }); |
|
5287 |
|
5288 })(jQuery); |
|
5289 (function( $, undefined ) { |
|
5290 |
|
5291 var uid = 0, |
|
5292 hideProps = {}, |
|
5293 showProps = {}; |
|
5294 |
|
5295 hideProps.height = hideProps.paddingTop = hideProps.paddingBottom = |
|
5296 hideProps.borderTopWidth = hideProps.borderBottomWidth = "hide"; |
|
5297 showProps.height = showProps.paddingTop = showProps.paddingBottom = |
|
5298 showProps.borderTopWidth = showProps.borderBottomWidth = "show"; |
|
5299 |
|
5300 $.widget( "ui.accordion", { |
|
5301 version: "1.10.4", |
|
5302 options: { |
|
5303 active: 0, |
|
5304 animate: {}, |
|
5305 collapsible: false, |
|
5306 event: "click", |
|
5307 header: "> li > :first-child,> :not(li):even", |
|
5308 heightStyle: "auto", |
|
5309 icons: { |
|
5310 activeHeader: "ui-icon-triangle-1-s", |
|
5311 header: "ui-icon-triangle-1-e" |
|
5312 }, |
|
5313 |
|
5314 // callbacks |
|
5315 activate: null, |
|
5316 beforeActivate: null |
|
5317 }, |
|
5318 |
|
5319 _create: function() { |
|
5320 var options = this.options; |
|
5321 this.prevShow = this.prevHide = $(); |
|
5322 this.element.addClass( "ui-accordion ui-widget ui-helper-reset" ) |
|
5323 // ARIA |
|
5324 .attr( "role", "tablist" ); |
|
5325 |
|
5326 // don't allow collapsible: false and active: false / null |
|
5327 if ( !options.collapsible && (options.active === false || options.active == null) ) { |
|
5328 options.active = 0; |
|
5329 } |
|
5330 |
|
5331 this._processPanels(); |
|
5332 // handle negative values |
|
5333 if ( options.active < 0 ) { |
|
5334 options.active += this.headers.length; |
|
5335 } |
|
5336 this._refresh(); |
|
5337 }, |
|
5338 |
|
5339 _getCreateEventData: function() { |
|
5340 return { |
|
5341 header: this.active, |
|
5342 panel: !this.active.length ? $() : this.active.next(), |
|
5343 content: !this.active.length ? $() : this.active.next() |
|
5344 }; |
|
5345 }, |
|
5346 |
|
5347 _createIcons: function() { |
|
5348 var icons = this.options.icons; |
|
5349 if ( icons ) { |
|
5350 $( "<span>" ) |
|
5351 .addClass( "ui-accordion-header-icon ui-icon " + icons.header ) |
|
5352 .prependTo( this.headers ); |
|
5353 this.active.children( ".ui-accordion-header-icon" ) |
|
5354 .removeClass( icons.header ) |
|
5355 .addClass( icons.activeHeader ); |
|
5356 this.headers.addClass( "ui-accordion-icons" ); |
|
5357 } |
|
5358 }, |
|
5359 |
|
5360 _destroyIcons: function() { |
|
5361 this.headers |
|
5362 .removeClass( "ui-accordion-icons" ) |
|
5363 .children( ".ui-accordion-header-icon" ) |
|
5364 .remove(); |
|
5365 }, |
|
5366 |
|
5367 _destroy: function() { |
|
5368 var contents; |
|
5369 |
|
5370 // clean up main element |
|
5371 this.element |
|
5372 .removeClass( "ui-accordion ui-widget ui-helper-reset" ) |
|
5373 .removeAttr( "role" ); |
|
5374 |
|
5375 // clean up headers |
|
5376 this.headers |
|
5377 .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" ) |
|
5378 .removeAttr( "role" ) |
|
5379 .removeAttr( "aria-expanded" ) |
|
5380 .removeAttr( "aria-selected" ) |
|
5381 .removeAttr( "aria-controls" ) |
|
5382 .removeAttr( "tabIndex" ) |
|
5383 .each(function() { |
|
5384 if ( /^ui-accordion/.test( this.id ) ) { |
|
5385 this.removeAttribute( "id" ); |
|
5386 } |
|
5387 }); |
|
5388 this._destroyIcons(); |
|
5389 |
|
5390 // clean up content panels |
|
5391 contents = this.headers.next() |
|
5392 .css( "display", "" ) |
|
5393 .removeAttr( "role" ) |
|
5394 .removeAttr( "aria-hidden" ) |
|
5395 .removeAttr( "aria-labelledby" ) |
|
5396 .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled" ) |
|
5397 .each(function() { |
|
5398 if ( /^ui-accordion/.test( this.id ) ) { |
|
5399 this.removeAttribute( "id" ); |
|
5400 } |
|
5401 }); |
|
5402 if ( this.options.heightStyle !== "content" ) { |
|
5403 contents.css( "height", "" ); |
|
5404 } |
|
5405 }, |
|
5406 |
|
5407 _setOption: function( key, value ) { |
|
5408 if ( key === "active" ) { |
|
5409 // _activate() will handle invalid values and update this.options |
|
5410 this._activate( value ); |
|
5411 return; |
|
5412 } |
|
5413 |
|
5414 if ( key === "event" ) { |
|
5415 if ( this.options.event ) { |
|
5416 this._off( this.headers, this.options.event ); |
|
5417 } |
|
5418 this._setupEvents( value ); |
|
5419 } |
|
5420 |
|
5421 this._super( key, value ); |
|
5422 |
|
5423 // setting collapsible: false while collapsed; open first panel |
|
5424 if ( key === "collapsible" && !value && this.options.active === false ) { |
|
5425 this._activate( 0 ); |
|
5426 } |
|
5427 |
|
5428 if ( key === "icons" ) { |
|
5429 this._destroyIcons(); |
|
5430 if ( value ) { |
|
5431 this._createIcons(); |
|
5432 } |
|
5433 } |
|
5434 |
|
5435 // #5332 - opacity doesn't cascade to positioned elements in IE |
|
5436 // so we need to add the disabled class to the headers and panels |
|
5437 if ( key === "disabled" ) { |
|
5438 this.headers.add( this.headers.next() ) |
|
5439 .toggleClass( "ui-state-disabled", !!value ); |
|
5440 } |
|
5441 }, |
|
5442 |
|
5443 _keydown: function( event ) { |
|
5444 if ( event.altKey || event.ctrlKey ) { |
|
5445 return; |
|
5446 } |
|
5447 |
|
5448 var keyCode = $.ui.keyCode, |
|
5449 length = this.headers.length, |
|
5450 currentIndex = this.headers.index( event.target ), |
|
5451 toFocus = false; |
|
5452 |
|
5453 switch ( event.keyCode ) { |
|
5454 case keyCode.RIGHT: |
|
5455 case keyCode.DOWN: |
|
5456 toFocus = this.headers[ ( currentIndex + 1 ) % length ]; |
|
5457 break; |
|
5458 case keyCode.LEFT: |
|
5459 case keyCode.UP: |
|
5460 toFocus = this.headers[ ( currentIndex - 1 + length ) % length ]; |
|
5461 break; |
|
5462 case keyCode.SPACE: |
|
5463 case keyCode.ENTER: |
|
5464 this._eventHandler( event ); |
|
5465 break; |
|
5466 case keyCode.HOME: |
|
5467 toFocus = this.headers[ 0 ]; |
|
5468 break; |
|
5469 case keyCode.END: |
|
5470 toFocus = this.headers[ length - 1 ]; |
|
5471 break; |
|
5472 } |
|
5473 |
|
5474 if ( toFocus ) { |
|
5475 $( event.target ).attr( "tabIndex", -1 ); |
|
5476 $( toFocus ).attr( "tabIndex", 0 ); |
|
5477 toFocus.focus(); |
|
5478 event.preventDefault(); |
|
5479 } |
|
5480 }, |
|
5481 |
|
5482 _panelKeyDown : function( event ) { |
|
5483 if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) { |
|
5484 $( event.currentTarget ).prev().focus(); |
|
5485 } |
|
5486 }, |
|
5487 |
|
5488 refresh: function() { |
|
5489 var options = this.options; |
|
5490 this._processPanels(); |
|
5491 |
|
5492 // was collapsed or no panel |
|
5493 if ( ( options.active === false && options.collapsible === true ) || !this.headers.length ) { |
|
5494 options.active = false; |
|
5495 this.active = $(); |
|
5496 // active false only when collapsible is true |
|
5497 } else if ( options.active === false ) { |
|
5498 this._activate( 0 ); |
|
5499 // was active, but active panel is gone |
|
5500 } else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) { |
|
5501 // all remaining panel are disabled |
|
5502 if ( this.headers.length === this.headers.find(".ui-state-disabled").length ) { |
|
5503 options.active = false; |
|
5504 this.active = $(); |
|
5505 // activate previous panel |
|
5506 } else { |
|
5507 this._activate( Math.max( 0, options.active - 1 ) ); |
|
5508 } |
|
5509 // was active, active panel still exists |
|
5510 } else { |
|
5511 // make sure active index is correct |
|
5512 options.active = this.headers.index( this.active ); |
|
5513 } |
|
5514 |
|
5515 this._destroyIcons(); |
|
5516 |
|
5517 this._refresh(); |
|
5518 }, |
|
5519 |
|
5520 _processPanels: function() { |
|
5521 this.headers = this.element.find( this.options.header ) |
|
5522 .addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" ); |
|
5523 |
|
5524 this.headers.next() |
|
5525 .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" ) |
|
5526 .filter(":not(.ui-accordion-content-active)") |
|
5527 .hide(); |
|
5528 }, |
|
5529 |
|
5530 _refresh: function() { |
|
5531 var maxHeight, |
|
5532 options = this.options, |
|
5533 heightStyle = options.heightStyle, |
|
5534 parent = this.element.parent(), |
|
5535 accordionId = this.accordionId = "ui-accordion-" + |
|
5536 (this.element.attr( "id" ) || ++uid); |
|
5537 |
|
5538 this.active = this._findActive( options.active ) |
|
5539 .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" ) |
|
5540 .removeClass( "ui-corner-all" ); |
|
5541 this.active.next() |
|
5542 .addClass( "ui-accordion-content-active" ) |
|
5543 .show(); |
|
5544 |
|
5545 this.headers |
|
5546 .attr( "role", "tab" ) |
|
5547 .each(function( i ) { |
|
5548 var header = $( this ), |
|
5549 headerId = header.attr( "id" ), |
|
5550 panel = header.next(), |
|
5551 panelId = panel.attr( "id" ); |
|
5552 if ( !headerId ) { |
|
5553 headerId = accordionId + "-header-" + i; |
|
5554 header.attr( "id", headerId ); |
|
5555 } |
|
5556 if ( !panelId ) { |
|
5557 panelId = accordionId + "-panel-" + i; |
|
5558 panel.attr( "id", panelId ); |
|
5559 } |
|
5560 header.attr( "aria-controls", panelId ); |
|
5561 panel.attr( "aria-labelledby", headerId ); |
|
5562 }) |
|
5563 .next() |
|
5564 .attr( "role", "tabpanel" ); |
|
5565 |
|
5566 this.headers |
|
5567 .not( this.active ) |
|
5568 .attr({ |
|
5569 "aria-selected": "false", |
|
5570 "aria-expanded": "false", |
|
5571 tabIndex: -1 |
|
5572 }) |
|
5573 .next() |
|
5574 .attr({ |
|
5575 "aria-hidden": "true" |
|
5576 }) |
|
5577 .hide(); |
|
5578 |
|
5579 // make sure at least one header is in the tab order |
|
5580 if ( !this.active.length ) { |
|
5581 this.headers.eq( 0 ).attr( "tabIndex", 0 ); |
|
5582 } else { |
|
5583 this.active.attr({ |
|
5584 "aria-selected": "true", |
|
5585 "aria-expanded": "true", |
|
5586 tabIndex: 0 |
|
5587 }) |
|
5588 .next() |
|
5589 .attr({ |
|
5590 "aria-hidden": "false" |
|
5591 }); |
|
5592 } |
|
5593 |
|
5594 this._createIcons(); |
|
5595 |
|
5596 this._setupEvents( options.event ); |
|
5597 |
|
5598 if ( heightStyle === "fill" ) { |
|
5599 maxHeight = parent.height(); |
|
5600 this.element.siblings( ":visible" ).each(function() { |
|
5601 var elem = $( this ), |
|
5602 position = elem.css( "position" ); |
|
5603 |
|
5604 if ( position === "absolute" || position === "fixed" ) { |
|
5605 return; |
|
5606 } |
|
5607 maxHeight -= elem.outerHeight( true ); |
|
5608 }); |
|
5609 |
|
5610 this.headers.each(function() { |
|
5611 maxHeight -= $( this ).outerHeight( true ); |
|
5612 }); |
|
5613 |
|
5614 this.headers.next() |
|
5615 .each(function() { |
|
5616 $( this ).height( Math.max( 0, maxHeight - |
|
5617 $( this ).innerHeight() + $( this ).height() ) ); |
|
5618 }) |
|
5619 .css( "overflow", "auto" ); |
|
5620 } else if ( heightStyle === "auto" ) { |
|
5621 maxHeight = 0; |
|
5622 this.headers.next() |
|
5623 .each(function() { |
|
5624 maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() ); |
|
5625 }) |
|
5626 .height( maxHeight ); |
|
5627 } |
|
5628 }, |
|
5629 |
|
5630 _activate: function( index ) { |
|
5631 var active = this._findActive( index )[ 0 ]; |
|
5632 |
|
5633 // trying to activate the already active panel |
|
5634 if ( active === this.active[ 0 ] ) { |
|
5635 return; |
|
5636 } |
|
5637 |
|
5638 // trying to collapse, simulate a click on the currently active header |
|
5639 active = active || this.active[ 0 ]; |
|
5640 |
|
5641 this._eventHandler({ |
|
5642 target: active, |
|
5643 currentTarget: active, |
|
5644 preventDefault: $.noop |
|
5645 }); |
|
5646 }, |
|
5647 |
|
5648 _findActive: function( selector ) { |
|
5649 return typeof selector === "number" ? this.headers.eq( selector ) : $(); |
|
5650 }, |
|
5651 |
|
5652 _setupEvents: function( event ) { |
|
5653 var events = { |
|
5654 keydown: "_keydown" |
|
5655 }; |
|
5656 if ( event ) { |
|
5657 $.each( event.split(" "), function( index, eventName ) { |
|
5658 events[ eventName ] = "_eventHandler"; |
|
5659 }); |
|
5660 } |
|
5661 |
|
5662 this._off( this.headers.add( this.headers.next() ) ); |
|
5663 this._on( this.headers, events ); |
|
5664 this._on( this.headers.next(), { keydown: "_panelKeyDown" }); |
|
5665 this._hoverable( this.headers ); |
|
5666 this._focusable( this.headers ); |
|
5667 }, |
|
5668 |
|
5669 _eventHandler: function( event ) { |
|
5670 var options = this.options, |
|
5671 active = this.active, |
|
5672 clicked = $( event.currentTarget ), |
|
5673 clickedIsActive = clicked[ 0 ] === active[ 0 ], |
|
5674 collapsing = clickedIsActive && options.collapsible, |
|
5675 toShow = collapsing ? $() : clicked.next(), |
|
5676 toHide = active.next(), |
|
5677 eventData = { |
|
5678 oldHeader: active, |
|
5679 oldPanel: toHide, |
|
5680 newHeader: collapsing ? $() : clicked, |
|
5681 newPanel: toShow |
|
5682 }; |
|
5683 |
|
5684 event.preventDefault(); |
|
5685 |
|
5686 if ( |
|
5687 // click on active header, but not collapsible |
|
5688 ( clickedIsActive && !options.collapsible ) || |
|
5689 // allow canceling activation |
|
5690 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { |
|
5691 return; |
|
5692 } |
|
5693 |
|
5694 options.active = collapsing ? false : this.headers.index( clicked ); |
|
5695 |
|
5696 // when the call to ._toggle() comes after the class changes |
|
5697 // it causes a very odd bug in IE 8 (see #6720) |
|
5698 this.active = clickedIsActive ? $() : clicked; |
|
5699 this._toggle( eventData ); |
|
5700 |
|
5701 // switch classes |
|
5702 // corner classes on the previously active header stay after the animation |
|
5703 active.removeClass( "ui-accordion-header-active ui-state-active" ); |
|
5704 if ( options.icons ) { |
|
5705 active.children( ".ui-accordion-header-icon" ) |
|
5706 .removeClass( options.icons.activeHeader ) |
|
5707 .addClass( options.icons.header ); |
|
5708 } |
|
5709 |
|
5710 if ( !clickedIsActive ) { |
|
5711 clicked |
|
5712 .removeClass( "ui-corner-all" ) |
|
5713 .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" ); |
|
5714 if ( options.icons ) { |
|
5715 clicked.children( ".ui-accordion-header-icon" ) |
|
5716 .removeClass( options.icons.header ) |
|
5717 .addClass( options.icons.activeHeader ); |
|
5718 } |
|
5719 |
|
5720 clicked |
|
5721 .next() |
|
5722 .addClass( "ui-accordion-content-active" ); |
|
5723 } |
|
5724 }, |
|
5725 |
|
5726 _toggle: function( data ) { |
|
5727 var toShow = data.newPanel, |
|
5728 toHide = this.prevShow.length ? this.prevShow : data.oldPanel; |
|
5729 |
|
5730 // handle activating a panel during the animation for another activation |
|
5731 this.prevShow.add( this.prevHide ).stop( true, true ); |
|
5732 this.prevShow = toShow; |
|
5733 this.prevHide = toHide; |
|
5734 |
|
5735 if ( this.options.animate ) { |
|
5736 this._animate( toShow, toHide, data ); |
|
5737 } else { |
|
5738 toHide.hide(); |
|
5739 toShow.show(); |
|
5740 this._toggleComplete( data ); |
|
5741 } |
|
5742 |
|
5743 toHide.attr({ |
|
5744 "aria-hidden": "true" |
|
5745 }); |
|
5746 toHide.prev().attr( "aria-selected", "false" ); |
|
5747 // if we're switching panels, remove the old header from the tab order |
|
5748 // if we're opening from collapsed state, remove the previous header from the tab order |
|
5749 // if we're collapsing, then keep the collapsing header in the tab order |
|
5750 if ( toShow.length && toHide.length ) { |
|
5751 toHide.prev().attr({ |
|
5752 "tabIndex": -1, |
|
5753 "aria-expanded": "false" |
|
5754 }); |
|
5755 } else if ( toShow.length ) { |
|
5756 this.headers.filter(function() { |
|
5757 return $( this ).attr( "tabIndex" ) === 0; |
|
5758 }) |
|
5759 .attr( "tabIndex", -1 ); |
|
5760 } |
|
5761 |
|
5762 toShow |
|
5763 .attr( "aria-hidden", "false" ) |
|
5764 .prev() |
|
5765 .attr({ |
|
5766 "aria-selected": "true", |
|
5767 tabIndex: 0, |
|
5768 "aria-expanded": "true" |
|
5769 }); |
|
5770 }, |
|
5771 |
|
5772 _animate: function( toShow, toHide, data ) { |
|
5773 var total, easing, duration, |
|
5774 that = this, |
|
5775 adjust = 0, |
|
5776 down = toShow.length && |
|
5777 ( !toHide.length || ( toShow.index() < toHide.index() ) ), |
|
5778 animate = this.options.animate || {}, |
|
5779 options = down && animate.down || animate, |
|
5780 complete = function() { |
|
5781 that._toggleComplete( data ); |
|
5782 }; |
|
5783 |
|
5784 if ( typeof options === "number" ) { |
|
5785 duration = options; |
|
5786 } |
|
5787 if ( typeof options === "string" ) { |
|
5788 easing = options; |
|
5789 } |
|
5790 // fall back from options to animation in case of partial down settings |
|
5791 easing = easing || options.easing || animate.easing; |
|
5792 duration = duration || options.duration || animate.duration; |
|
5793 |
|
5794 if ( !toHide.length ) { |
|
5795 return toShow.animate( showProps, duration, easing, complete ); |
|
5796 } |
|
5797 if ( !toShow.length ) { |
|
5798 return toHide.animate( hideProps, duration, easing, complete ); |
|
5799 } |
|
5800 |
|
5801 total = toShow.show().outerHeight(); |
|
5802 toHide.animate( hideProps, { |
|
5803 duration: duration, |
|
5804 easing: easing, |
|
5805 step: function( now, fx ) { |
|
5806 fx.now = Math.round( now ); |
|
5807 } |
|
5808 }); |
|
5809 toShow |
|
5810 .hide() |
|
5811 .animate( showProps, { |
|
5812 duration: duration, |
|
5813 easing: easing, |
|
5814 complete: complete, |
|
5815 step: function( now, fx ) { |
|
5816 fx.now = Math.round( now ); |
|
5817 if ( fx.prop !== "height" ) { |
|
5818 adjust += fx.now; |
|
5819 } else if ( that.options.heightStyle !== "content" ) { |
|
5820 fx.now = Math.round( total - toHide.outerHeight() - adjust ); |
|
5821 adjust = 0; |
|
5822 } |
|
5823 } |
|
5824 }); |
|
5825 }, |
|
5826 |
|
5827 _toggleComplete: function( data ) { |
|
5828 var toHide = data.oldPanel; |
|
5829 |
|
5830 toHide |
|
5831 .removeClass( "ui-accordion-content-active" ) |
|
5832 .prev() |
|
5833 .removeClass( "ui-corner-top" ) |
|
5834 .addClass( "ui-corner-all" ); |
|
5835 |
|
5836 // Work around for rendering bug in IE (#5421) |
|
5837 if ( toHide.length ) { |
|
5838 toHide.parent()[0].className = toHide.parent()[0].className; |
|
5839 } |
|
5840 this._trigger( "activate", null, data ); |
|
5841 } |
|
5842 }); |
|
5843 |
|
5844 })( jQuery ); |
|
5845 (function( $, undefined ) { |
|
5846 |
|
5847 $.widget( "ui.autocomplete", { |
|
5848 version: "1.10.4", |
|
5849 defaultElement: "<input>", |
|
5850 options: { |
|
5851 appendTo: null, |
|
5852 autoFocus: false, |
|
5853 delay: 300, |
|
5854 minLength: 1, |
|
5855 position: { |
|
5856 my: "left top", |
|
5857 at: "left bottom", |
|
5858 collision: "none" |
|
5859 }, |
|
5860 source: null, |
|
5861 |
|
5862 // callbacks |
|
5863 change: null, |
|
5864 close: null, |
|
5865 focus: null, |
|
5866 open: null, |
|
5867 response: null, |
|
5868 search: null, |
|
5869 select: null |
|
5870 }, |
|
5871 |
|
5872 requestIndex: 0, |
|
5873 pending: 0, |
|
5874 |
|
5875 _create: function() { |
|
5876 // Some browsers only repeat keydown events, not keypress events, |
|
5877 // so we use the suppressKeyPress flag to determine if we've already |
|
5878 // handled the keydown event. #7269 |
|
5879 // Unfortunately the code for & in keypress is the same as the up arrow, |
|
5880 // so we use the suppressKeyPressRepeat flag to avoid handling keypress |
|
5881 // events when we know the keydown event was used to modify the |
|
5882 // search term. #7799 |
|
5883 var suppressKeyPress, suppressKeyPressRepeat, suppressInput, |
|
5884 nodeName = this.element[0].nodeName.toLowerCase(), |
|
5885 isTextarea = nodeName === "textarea", |
|
5886 isInput = nodeName === "input"; |
|
5887 |
|
5888 this.isMultiLine = |
|
5889 // Textareas are always multi-line |
|
5890 isTextarea ? true : |
|
5891 // Inputs are always single-line, even if inside a contentEditable element |
|
5892 // IE also treats inputs as contentEditable |
|
5893 isInput ? false : |
|
5894 // All other element types are determined by whether or not they're contentEditable |
|
5895 this.element.prop( "isContentEditable" ); |
|
5896 |
|
5897 this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ]; |
|
5898 this.isNewMenu = true; |
|
5899 |
|
5900 this.element |
|
5901 .addClass( "ui-autocomplete-input" ) |
|
5902 .attr( "autocomplete", "off" ); |
|
5903 |
|
5904 this._on( this.element, { |
|
5905 keydown: function( event ) { |
|
5906 if ( this.element.prop( "readOnly" ) ) { |
|
5907 suppressKeyPress = true; |
|
5908 suppressInput = true; |
|
5909 suppressKeyPressRepeat = true; |
|
5910 return; |
|
5911 } |
|
5912 |
|
5913 suppressKeyPress = false; |
|
5914 suppressInput = false; |
|
5915 suppressKeyPressRepeat = false; |
|
5916 var keyCode = $.ui.keyCode; |
|
5917 switch( event.keyCode ) { |
|
5918 case keyCode.PAGE_UP: |
|
5919 suppressKeyPress = true; |
|
5920 this._move( "previousPage", event ); |
|
5921 break; |
|
5922 case keyCode.PAGE_DOWN: |
|
5923 suppressKeyPress = true; |
|
5924 this._move( "nextPage", event ); |
|
5925 break; |
|
5926 case keyCode.UP: |
|
5927 suppressKeyPress = true; |
|
5928 this._keyEvent( "previous", event ); |
|
5929 break; |
|
5930 case keyCode.DOWN: |
|
5931 suppressKeyPress = true; |
|
5932 this._keyEvent( "next", event ); |
|
5933 break; |
|
5934 case keyCode.ENTER: |
|
5935 case keyCode.NUMPAD_ENTER: |
|
5936 // when menu is open and has focus |
|
5937 if ( this.menu.active ) { |
|
5938 // #6055 - Opera still allows the keypress to occur |
|
5939 // which causes forms to submit |
|
5940 suppressKeyPress = true; |
|
5941 event.preventDefault(); |
|
5942 this.menu.select( event ); |
|
5943 } |
|
5944 break; |
|
5945 case keyCode.TAB: |
|
5946 if ( this.menu.active ) { |
|
5947 this.menu.select( event ); |
|
5948 } |
|
5949 break; |
|
5950 case keyCode.ESCAPE: |
|
5951 if ( this.menu.element.is( ":visible" ) ) { |
|
5952 this._value( this.term ); |
|
5953 this.close( event ); |
|
5954 // Different browsers have different default behavior for escape |
|
5955 // Single press can mean undo or clear |
|
5956 // Double press in IE means clear the whole form |
|
5957 event.preventDefault(); |
|
5958 } |
|
5959 break; |
|
5960 default: |
|
5961 suppressKeyPressRepeat = true; |
|
5962 // search timeout should be triggered before the input value is changed |
|
5963 this._searchTimeout( event ); |
|
5964 break; |
|
5965 } |
|
5966 }, |
|
5967 keypress: function( event ) { |
|
5968 if ( suppressKeyPress ) { |
|
5969 suppressKeyPress = false; |
|
5970 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) { |
|
5971 event.preventDefault(); |
|
5972 } |
|
5973 return; |
|
5974 } |
|
5975 if ( suppressKeyPressRepeat ) { |
|
5976 return; |
|
5977 } |
|
5978 |
|
5979 // replicate some key handlers to allow them to repeat in Firefox and Opera |
|
5980 var keyCode = $.ui.keyCode; |
|
5981 switch( event.keyCode ) { |
|
5982 case keyCode.PAGE_UP: |
|
5983 this._move( "previousPage", event ); |
|
5984 break; |
|
5985 case keyCode.PAGE_DOWN: |
|
5986 this._move( "nextPage", event ); |
|
5987 break; |
|
5988 case keyCode.UP: |
|
5989 this._keyEvent( "previous", event ); |
|
5990 break; |
|
5991 case keyCode.DOWN: |
|
5992 this._keyEvent( "next", event ); |
|
5993 break; |
|
5994 } |
|
5995 }, |
|
5996 input: function( event ) { |
|
5997 if ( suppressInput ) { |
|
5998 suppressInput = false; |
|
5999 event.preventDefault(); |
|
6000 return; |
|
6001 } |
|
6002 this._searchTimeout( event ); |
|
6003 }, |
|
6004 focus: function() { |
|
6005 this.selectedItem = null; |
|
6006 this.previous = this._value(); |
|
6007 }, |
|
6008 blur: function( event ) { |
|
6009 if ( this.cancelBlur ) { |
|
6010 delete this.cancelBlur; |
|
6011 return; |
|
6012 } |
|
6013 |
|
6014 clearTimeout( this.searching ); |
|
6015 this.close( event ); |
|
6016 this._change( event ); |
|
6017 } |
|
6018 }); |
|
6019 |
|
6020 this._initSource(); |
|
6021 this.menu = $( "<ul>" ) |
|
6022 .addClass( "ui-autocomplete ui-front" ) |
|
6023 .appendTo( this._appendTo() ) |
|
6024 .menu({ |
|
6025 // disable ARIA support, the live region takes care of that |
|
6026 role: null |
|
6027 }) |
|
6028 .hide() |
|
6029 .data( "ui-menu" ); |
|
6030 |
|
6031 this._on( this.menu.element, { |
|
6032 mousedown: function( event ) { |
|
6033 // prevent moving focus out of the text field |
|
6034 event.preventDefault(); |
|
6035 |
|
6036 // IE doesn't prevent moving focus even with event.preventDefault() |
|
6037 // so we set a flag to know when we should ignore the blur event |
|
6038 this.cancelBlur = true; |
|
6039 this._delay(function() { |
|
6040 delete this.cancelBlur; |
|
6041 }); |
|
6042 |
|
6043 // clicking on the scrollbar causes focus to shift to the body |
|
6044 // but we can't detect a mouseup or a click immediately afterward |
|
6045 // so we have to track the next mousedown and close the menu if |
|
6046 // the user clicks somewhere outside of the autocomplete |
|
6047 var menuElement = this.menu.element[ 0 ]; |
|
6048 if ( !$( event.target ).closest( ".ui-menu-item" ).length ) { |
|
6049 this._delay(function() { |
|
6050 var that = this; |
|
6051 this.document.one( "mousedown", function( event ) { |
|
6052 if ( event.target !== that.element[ 0 ] && |
|
6053 event.target !== menuElement && |
|
6054 !$.contains( menuElement, event.target ) ) { |
|
6055 that.close(); |
|
6056 } |
|
6057 }); |
|
6058 }); |
|
6059 } |
|
6060 }, |
|
6061 menufocus: function( event, ui ) { |
|
6062 // support: Firefox |
|
6063 // Prevent accidental activation of menu items in Firefox (#7024 #9118) |
|
6064 if ( this.isNewMenu ) { |
|
6065 this.isNewMenu = false; |
|
6066 if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) { |
|
6067 this.menu.blur(); |
|
6068 |
|
6069 this.document.one( "mousemove", function() { |
|
6070 $( event.target ).trigger( event.originalEvent ); |
|
6071 }); |
|
6072 |
|
6073 return; |
|
6074 } |
|
6075 } |
|
6076 |
|
6077 var item = ui.item.data( "ui-autocomplete-item" ); |
|
6078 if ( false !== this._trigger( "focus", event, { item: item } ) ) { |
|
6079 // use value to match what will end up in the input, if it was a key event |
|
6080 if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) { |
|
6081 this._value( item.value ); |
|
6082 } |
|
6083 } else { |
|
6084 // Normally the input is populated with the item's value as the |
|
6085 // menu is navigated, causing screen readers to notice a change and |
|
6086 // announce the item. Since the focus event was canceled, this doesn't |
|
6087 // happen, so we update the live region so that screen readers can |
|
6088 // still notice the change and announce it. |
|
6089 this.liveRegion.text( item.value ); |
|
6090 } |
|
6091 }, |
|
6092 menuselect: function( event, ui ) { |
|
6093 var item = ui.item.data( "ui-autocomplete-item" ), |
|
6094 previous = this.previous; |
|
6095 |
|
6096 // only trigger when focus was lost (click on menu) |
|
6097 if ( this.element[0] !== this.document[0].activeElement ) { |
|
6098 this.element.focus(); |
|
6099 this.previous = previous; |
|
6100 // #6109 - IE triggers two focus events and the second |
|
6101 // is asynchronous, so we need to reset the previous |
|
6102 // term synchronously and asynchronously :-( |
|
6103 this._delay(function() { |
|
6104 this.previous = previous; |
|
6105 this.selectedItem = item; |
|
6106 }); |
|
6107 } |
|
6108 |
|
6109 if ( false !== this._trigger( "select", event, { item: item } ) ) { |
|
6110 this._value( item.value ); |
|
6111 } |
|
6112 // reset the term after the select event |
|
6113 // this allows custom select handling to work properly |
|
6114 this.term = this._value(); |
|
6115 |
|
6116 this.close( event ); |
|
6117 this.selectedItem = item; |
|
6118 } |
|
6119 }); |
|
6120 |
|
6121 this.liveRegion = $( "<span>", { |
|
6122 role: "status", |
|
6123 "aria-live": "polite" |
|
6124 }) |
|
6125 .addClass( "ui-helper-hidden-accessible" ) |
|
6126 .insertBefore( this.element ); |
|
6127 |
|
6128 // turning off autocomplete prevents the browser from remembering the |
|
6129 // value when navigating through history, so we re-enable autocomplete |
|
6130 // if the page is unloaded before the widget is destroyed. #7790 |
|
6131 this._on( this.window, { |
|
6132 beforeunload: function() { |
|
6133 this.element.removeAttr( "autocomplete" ); |
|
6134 } |
|
6135 }); |
|
6136 }, |
|
6137 |
|
6138 _destroy: function() { |
|
6139 clearTimeout( this.searching ); |
|
6140 this.element |
|
6141 .removeClass( "ui-autocomplete-input" ) |
|
6142 .removeAttr( "autocomplete" ); |
|
6143 this.menu.element.remove(); |
|
6144 this.liveRegion.remove(); |
|
6145 }, |
|
6146 |
|
6147 _setOption: function( key, value ) { |
|
6148 this._super( key, value ); |
|
6149 if ( key === "source" ) { |
|
6150 this._initSource(); |
|
6151 } |
|
6152 if ( key === "appendTo" ) { |
|
6153 this.menu.element.appendTo( this._appendTo() ); |
|
6154 } |
|
6155 if ( key === "disabled" && value && this.xhr ) { |
|
6156 this.xhr.abort(); |
|
6157 } |
|
6158 }, |
|
6159 |
|
6160 _appendTo: function() { |
|
6161 var element = this.options.appendTo; |
|
6162 |
|
6163 if ( element ) { |
|
6164 element = element.jquery || element.nodeType ? |
|
6165 $( element ) : |
|
6166 this.document.find( element ).eq( 0 ); |
|
6167 } |
|
6168 |
|
6169 if ( !element ) { |
|
6170 element = this.element.closest( ".ui-front" ); |
|
6171 } |
|
6172 |
|
6173 if ( !element.length ) { |
|
6174 element = this.document[0].body; |
|
6175 } |
|
6176 |
|
6177 return element; |
|
6178 }, |
|
6179 |
|
6180 _initSource: function() { |
|
6181 var array, url, |
|
6182 that = this; |
|
6183 if ( $.isArray(this.options.source) ) { |
|
6184 array = this.options.source; |
|
6185 this.source = function( request, response ) { |
|
6186 response( $.ui.autocomplete.filter( array, request.term ) ); |
|
6187 }; |
|
6188 } else if ( typeof this.options.source === "string" ) { |
|
6189 url = this.options.source; |
|
6190 this.source = function( request, response ) { |
|
6191 if ( that.xhr ) { |
|
6192 that.xhr.abort(); |
|
6193 } |
|
6194 that.xhr = $.ajax({ |
|
6195 url: url, |
|
6196 data: request, |
|
6197 dataType: "json", |
|
6198 success: function( data ) { |
|
6199 response( data ); |
|
6200 }, |
|
6201 error: function() { |
|
6202 response( [] ); |
|
6203 } |
|
6204 }); |
|
6205 }; |
|
6206 } else { |
|
6207 this.source = this.options.source; |
|
6208 } |
|
6209 }, |
|
6210 |
|
6211 _searchTimeout: function( event ) { |
|
6212 clearTimeout( this.searching ); |
|
6213 this.searching = this._delay(function() { |
|
6214 // only search if the value has changed |
|
6215 if ( this.term !== this._value() ) { |
|
6216 this.selectedItem = null; |
|
6217 this.search( null, event ); |
|
6218 } |
|
6219 }, this.options.delay ); |
|
6220 }, |
|
6221 |
|
6222 search: function( value, event ) { |
|
6223 value = value != null ? value : this._value(); |
|
6224 |
|
6225 // always save the actual value, not the one passed as an argument |
|
6226 this.term = this._value(); |
|
6227 |
|
6228 if ( value.length < this.options.minLength ) { |
|
6229 return this.close( event ); |
|
6230 } |
|
6231 |
|
6232 if ( this._trigger( "search", event ) === false ) { |
|
6233 return; |
|
6234 } |
|
6235 |
|
6236 return this._search( value ); |
|
6237 }, |
|
6238 |
|
6239 _search: function( value ) { |
|
6240 this.pending++; |
|
6241 this.element.addClass( "ui-autocomplete-loading" ); |
|
6242 this.cancelSearch = false; |
|
6243 |
|
6244 this.source( { term: value }, this._response() ); |
|
6245 }, |
|
6246 |
|
6247 _response: function() { |
|
6248 var index = ++this.requestIndex; |
|
6249 |
|
6250 return $.proxy(function( content ) { |
|
6251 if ( index === this.requestIndex ) { |
|
6252 this.__response( content ); |
|
6253 } |
|
6254 |
|
6255 this.pending--; |
|
6256 if ( !this.pending ) { |
|
6257 this.element.removeClass( "ui-autocomplete-loading" ); |
|
6258 } |
|
6259 }, this ); |
|
6260 }, |
|
6261 |
|
6262 __response: function( content ) { |
|
6263 if ( content ) { |
|
6264 content = this._normalize( content ); |
|
6265 } |
|
6266 this._trigger( "response", null, { content: content } ); |
|
6267 if ( !this.options.disabled && content && content.length && !this.cancelSearch ) { |
|
6268 this._suggest( content ); |
|
6269 this._trigger( "open" ); |
|
6270 } else { |
|
6271 // use ._close() instead of .close() so we don't cancel future searches |
|
6272 this._close(); |
|
6273 } |
|
6274 }, |
|
6275 |
|
6276 close: function( event ) { |
|
6277 this.cancelSearch = true; |
|
6278 this._close( event ); |
|
6279 }, |
|
6280 |
|
6281 _close: function( event ) { |
|
6282 if ( this.menu.element.is( ":visible" ) ) { |
|
6283 this.menu.element.hide(); |
|
6284 this.menu.blur(); |
|
6285 this.isNewMenu = true; |
|
6286 this._trigger( "close", event ); |
|
6287 } |
|
6288 }, |
|
6289 |
|
6290 _change: function( event ) { |
|
6291 if ( this.previous !== this._value() ) { |
|
6292 this._trigger( "change", event, { item: this.selectedItem } ); |
|
6293 } |
|
6294 }, |
|
6295 |
|
6296 _normalize: function( items ) { |
|
6297 // assume all items have the right format when the first item is complete |
|
6298 if ( items.length && items[0].label && items[0].value ) { |
|
6299 return items; |
|
6300 } |
|
6301 return $.map( items, function( item ) { |
|
6302 if ( typeof item === "string" ) { |
|
6303 return { |
|
6304 label: item, |
|
6305 value: item |
|
6306 }; |
|
6307 } |
|
6308 return $.extend({ |
|
6309 label: item.label || item.value, |
|
6310 value: item.value || item.label |
|
6311 }, item ); |
|
6312 }); |
|
6313 }, |
|
6314 |
|
6315 _suggest: function( items ) { |
|
6316 var ul = this.menu.element.empty(); |
|
6317 this._renderMenu( ul, items ); |
|
6318 this.isNewMenu = true; |
|
6319 this.menu.refresh(); |
|
6320 |
|
6321 // size and position menu |
|
6322 ul.show(); |
|
6323 this._resizeMenu(); |
|
6324 ul.position( $.extend({ |
|
6325 of: this.element |
|
6326 }, this.options.position )); |
|
6327 |
|
6328 if ( this.options.autoFocus ) { |
|
6329 this.menu.next(); |
|
6330 } |
|
6331 }, |
|
6332 |
|
6333 _resizeMenu: function() { |
|
6334 var ul = this.menu.element; |
|
6335 ul.outerWidth( Math.max( |
|
6336 // Firefox wraps long text (possibly a rounding bug) |
|
6337 // so we add 1px to avoid the wrapping (#7513) |
|
6338 ul.width( "" ).outerWidth() + 1, |
|
6339 this.element.outerWidth() |
|
6340 ) ); |
|
6341 }, |
|
6342 |
|
6343 _renderMenu: function( ul, items ) { |
|
6344 var that = this; |
|
6345 $.each( items, function( index, item ) { |
|
6346 that._renderItemData( ul, item ); |
|
6347 }); |
|
6348 }, |
|
6349 |
|
6350 _renderItemData: function( ul, item ) { |
|
6351 return this._renderItem( ul, item ).data( "ui-autocomplete-item", item ); |
|
6352 }, |
|
6353 |
|
6354 _renderItem: function( ul, item ) { |
|
6355 return $( "<li>" ) |
|
6356 .append( $( "<a>" ).text( item.label ) ) |
|
6357 .appendTo( ul ); |
|
6358 }, |
|
6359 |
|
6360 _move: function( direction, event ) { |
|
6361 if ( !this.menu.element.is( ":visible" ) ) { |
|
6362 this.search( null, event ); |
|
6363 return; |
|
6364 } |
|
6365 if ( this.menu.isFirstItem() && /^previous/.test( direction ) || |
|
6366 this.menu.isLastItem() && /^next/.test( direction ) ) { |
|
6367 this._value( this.term ); |
|
6368 this.menu.blur(); |
|
6369 return; |
|
6370 } |
|
6371 this.menu[ direction ]( event ); |
|
6372 }, |
|
6373 |
|
6374 widget: function() { |
|
6375 return this.menu.element; |
|
6376 }, |
|
6377 |
|
6378 _value: function() { |
|
6379 return this.valueMethod.apply( this.element, arguments ); |
|
6380 }, |
|
6381 |
|
6382 _keyEvent: function( keyEvent, event ) { |
|
6383 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) { |
|
6384 this._move( keyEvent, event ); |
|
6385 |
|
6386 // prevents moving cursor to beginning/end of the text field in some browsers |
|
6387 event.preventDefault(); |
|
6388 } |
|
6389 } |
|
6390 }); |
|
6391 |
|
6392 $.extend( $.ui.autocomplete, { |
|
6393 escapeRegex: function( value ) { |
|
6394 return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&"); |
|
6395 }, |
|
6396 filter: function(array, term) { |
|
6397 var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" ); |
|
6398 return $.grep( array, function(value) { |
|
6399 return matcher.test( value.label || value.value || value ); |
|
6400 }); |
|
6401 } |
|
6402 }); |
|
6403 |
|
6404 |
|
6405 // live region extension, adding a `messages` option |
|
6406 // NOTE: This is an experimental API. We are still investigating |
|
6407 // a full solution for string manipulation and internationalization. |
|
6408 $.widget( "ui.autocomplete", $.ui.autocomplete, { |
|
6409 options: { |
|
6410 messages: { |
|
6411 noResults: "No search results.", |
|
6412 results: function( amount ) { |
|
6413 return amount + ( amount > 1 ? " results are" : " result is" ) + |
|
6414 " available, use up and down arrow keys to navigate."; |
|
6415 } |
|
6416 } |
|
6417 }, |
|
6418 |
|
6419 __response: function( content ) { |
|
6420 var message; |
|
6421 this._superApply( arguments ); |
|
6422 if ( this.options.disabled || this.cancelSearch ) { |
|
6423 return; |
|
6424 } |
|
6425 if ( content && content.length ) { |
|
6426 message = this.options.messages.results( content.length ); |
|
6427 } else { |
|
6428 message = this.options.messages.noResults; |
|
6429 } |
|
6430 this.liveRegion.text( message ); |
|
6431 } |
|
6432 }); |
|
6433 |
|
6434 }( jQuery )); |
|
6435 (function( $, undefined ) { |
|
6436 |
|
6437 var lastActive, |
|
6438 baseClasses = "ui-button ui-widget ui-state-default ui-corner-all", |
|
6439 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", |
|
6440 formResetHandler = function() { |
|
6441 var form = $( this ); |
|
6442 setTimeout(function() { |
|
6443 form.find( ":ui-button" ).button( "refresh" ); |
|
6444 }, 1 ); |
|
6445 }, |
|
6446 radioGroup = function( radio ) { |
|
6447 var name = radio.name, |
|
6448 form = radio.form, |
|
6449 radios = $( [] ); |
|
6450 if ( name ) { |
|
6451 name = name.replace( /'/g, "\\'" ); |
|
6452 if ( form ) { |
|
6453 radios = $( form ).find( "[name='" + name + "']" ); |
|
6454 } else { |
|
6455 radios = $( "[name='" + name + "']", radio.ownerDocument ) |
|
6456 .filter(function() { |
|
6457 return !this.form; |
|
6458 }); |
|
6459 } |
|
6460 } |
|
6461 return radios; |
|
6462 }; |
|
6463 |
|
6464 $.widget( "ui.button", { |
|
6465 version: "1.10.4", |
|
6466 defaultElement: "<button>", |
|
6467 options: { |
|
6468 disabled: null, |
|
6469 text: true, |
|
6470 label: null, |
|
6471 icons: { |
|
6472 primary: null, |
|
6473 secondary: null |
|
6474 } |
|
6475 }, |
|
6476 _create: function() { |
|
6477 this.element.closest( "form" ) |
|
6478 .unbind( "reset" + this.eventNamespace ) |
|
6479 .bind( "reset" + this.eventNamespace, formResetHandler ); |
|
6480 |
|
6481 if ( typeof this.options.disabled !== "boolean" ) { |
|
6482 this.options.disabled = !!this.element.prop( "disabled" ); |
|
6483 } else { |
|
6484 this.element.prop( "disabled", this.options.disabled ); |
|
6485 } |
|
6486 |
|
6487 this._determineButtonType(); |
|
6488 this.hasTitle = !!this.buttonElement.attr( "title" ); |
|
6489 |
|
6490 var that = this, |
|
6491 options = this.options, |
|
6492 toggleButton = this.type === "checkbox" || this.type === "radio", |
|
6493 activeClass = !toggleButton ? "ui-state-active" : ""; |
|
6494 |
|
6495 if ( options.label === null ) { |
|
6496 options.label = (this.type === "input" ? this.buttonElement.val() : this.buttonElement.html()); |
|
6497 } |
|
6498 |
|
6499 this._hoverable( this.buttonElement ); |
|
6500 |
|
6501 this.buttonElement |
|
6502 .addClass( baseClasses ) |
|
6503 .attr( "role", "button" ) |
|
6504 .bind( "mouseenter" + this.eventNamespace, function() { |
|
6505 if ( options.disabled ) { |
|
6506 return; |
|
6507 } |
|
6508 if ( this === lastActive ) { |
|
6509 $( this ).addClass( "ui-state-active" ); |
|
6510 } |
|
6511 }) |
|
6512 .bind( "mouseleave" + this.eventNamespace, function() { |
|
6513 if ( options.disabled ) { |
|
6514 return; |
|
6515 } |
|
6516 $( this ).removeClass( activeClass ); |
|
6517 }) |
|
6518 .bind( "click" + this.eventNamespace, function( event ) { |
|
6519 if ( options.disabled ) { |
|
6520 event.preventDefault(); |
|
6521 event.stopImmediatePropagation(); |
|
6522 } |
|
6523 }); |
|
6524 |
|
6525 // Can't use _focusable() because the element that receives focus |
|
6526 // and the element that gets the ui-state-focus class are different |
|
6527 this._on({ |
|
6528 focus: function() { |
|
6529 this.buttonElement.addClass( "ui-state-focus" ); |
|
6530 }, |
|
6531 blur: function() { |
|
6532 this.buttonElement.removeClass( "ui-state-focus" ); |
|
6533 } |
|
6534 }); |
|
6535 |
|
6536 if ( toggleButton ) { |
|
6537 this.element.bind( "change" + this.eventNamespace, function() { |
|
6538 that.refresh(); |
|
6539 }); |
|
6540 } |
|
6541 |
|
6542 if ( this.type === "checkbox" ) { |
|
6543 this.buttonElement.bind( "click" + this.eventNamespace, function() { |
|
6544 if ( options.disabled ) { |
|
6545 return false; |
|
6546 } |
|
6547 }); |
|
6548 } else if ( this.type === "radio" ) { |
|
6549 this.buttonElement.bind( "click" + this.eventNamespace, function() { |
|
6550 if ( options.disabled ) { |
|
6551 return false; |
|
6552 } |
|
6553 $( this ).addClass( "ui-state-active" ); |
|
6554 that.buttonElement.attr( "aria-pressed", "true" ); |
|
6555 |
|
6556 var radio = that.element[ 0 ]; |
|
6557 radioGroup( radio ) |
|
6558 .not( radio ) |
|
6559 .map(function() { |
|
6560 return $( this ).button( "widget" )[ 0 ]; |
|
6561 }) |
|
6562 .removeClass( "ui-state-active" ) |
|
6563 .attr( "aria-pressed", "false" ); |
|
6564 }); |
|
6565 } else { |
|
6566 this.buttonElement |
|
6567 .bind( "mousedown" + this.eventNamespace, function() { |
|
6568 if ( options.disabled ) { |
|
6569 return false; |
|
6570 } |
|
6571 $( this ).addClass( "ui-state-active" ); |
|
6572 lastActive = this; |
|
6573 that.document.one( "mouseup", function() { |
|
6574 lastActive = null; |
|
6575 }); |
|
6576 }) |
|
6577 .bind( "mouseup" + this.eventNamespace, function() { |
|
6578 if ( options.disabled ) { |
|
6579 return false; |
|
6580 } |
|
6581 $( this ).removeClass( "ui-state-active" ); |
|
6582 }) |
|
6583 .bind( "keydown" + this.eventNamespace, function(event) { |
|
6584 if ( options.disabled ) { |
|
6585 return false; |
|
6586 } |
|
6587 if ( event.keyCode === $.ui.keyCode.SPACE || event.keyCode === $.ui.keyCode.ENTER ) { |
|
6588 $( this ).addClass( "ui-state-active" ); |
|
6589 } |
|
6590 }) |
|
6591 // see #8559, we bind to blur here in case the button element loses |
|
6592 // focus between keydown and keyup, it would be left in an "active" state |
|
6593 .bind( "keyup" + this.eventNamespace + " blur" + this.eventNamespace, function() { |
|
6594 $( this ).removeClass( "ui-state-active" ); |
|
6595 }); |
|
6596 |
|
6597 if ( this.buttonElement.is("a") ) { |
|
6598 this.buttonElement.keyup(function(event) { |
|
6599 if ( event.keyCode === $.ui.keyCode.SPACE ) { |
|
6600 // TODO pass through original event correctly (just as 2nd argument doesn't work) |
|
6601 $( this ).click(); |
|
6602 } |
|
6603 }); |
|
6604 } |
|
6605 } |
|
6606 |
|
6607 // TODO: pull out $.Widget's handling for the disabled option into |
|
6608 // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can |
|
6609 // be overridden by individual plugins |
|
6610 this._setOption( "disabled", options.disabled ); |
|
6611 this._resetButton(); |
|
6612 }, |
|
6613 |
|
6614 _determineButtonType: function() { |
|
6615 var ancestor, labelSelector, checked; |
|
6616 |
|
6617 if ( this.element.is("[type=checkbox]") ) { |
|
6618 this.type = "checkbox"; |
|
6619 } else if ( this.element.is("[type=radio]") ) { |
|
6620 this.type = "radio"; |
|
6621 } else if ( this.element.is("input") ) { |
|
6622 this.type = "input"; |
|
6623 } else { |
|
6624 this.type = "button"; |
|
6625 } |
|
6626 |
|
6627 if ( this.type === "checkbox" || this.type === "radio" ) { |
|
6628 // we don't search against the document in case the element |
|
6629 // is disconnected from the DOM |
|
6630 ancestor = this.element.parents().last(); |
|
6631 labelSelector = "label[for='" + this.element.attr("id") + "']"; |
|
6632 this.buttonElement = ancestor.find( labelSelector ); |
|
6633 if ( !this.buttonElement.length ) { |
|
6634 ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings(); |
|
6635 this.buttonElement = ancestor.filter( labelSelector ); |
|
6636 if ( !this.buttonElement.length ) { |
|
6637 this.buttonElement = ancestor.find( labelSelector ); |
|
6638 } |
|
6639 } |
|
6640 this.element.addClass( "ui-helper-hidden-accessible" ); |
|
6641 |
|
6642 checked = this.element.is( ":checked" ); |
|
6643 if ( checked ) { |
|
6644 this.buttonElement.addClass( "ui-state-active" ); |
|
6645 } |
|
6646 this.buttonElement.prop( "aria-pressed", checked ); |
|
6647 } else { |
|
6648 this.buttonElement = this.element; |
|
6649 } |
|
6650 }, |
|
6651 |
|
6652 widget: function() { |
|
6653 return this.buttonElement; |
|
6654 }, |
|
6655 |
|
6656 _destroy: function() { |
|
6657 this.element |
|
6658 .removeClass( "ui-helper-hidden-accessible" ); |
|
6659 this.buttonElement |
|
6660 .removeClass( baseClasses + " ui-state-active " + typeClasses ) |
|
6661 .removeAttr( "role" ) |
|
6662 .removeAttr( "aria-pressed" ) |
|
6663 .html( this.buttonElement.find(".ui-button-text").html() ); |
|
6664 |
|
6665 if ( !this.hasTitle ) { |
|
6666 this.buttonElement.removeAttr( "title" ); |
|
6667 } |
|
6668 }, |
|
6669 |
|
6670 _setOption: function( key, value ) { |
|
6671 this._super( key, value ); |
|
6672 if ( key === "disabled" ) { |
|
6673 this.element.prop( "disabled", !!value ); |
|
6674 if ( value ) { |
|
6675 this.buttonElement.removeClass( "ui-state-focus" ); |
|
6676 } |
|
6677 return; |
|
6678 } |
|
6679 this._resetButton(); |
|
6680 }, |
|
6681 |
|
6682 refresh: function() { |
|
6683 //See #8237 & #8828 |
|
6684 var isDisabled = this.element.is( "input, button" ) ? this.element.is( ":disabled" ) : this.element.hasClass( "ui-button-disabled" ); |
|
6685 |
|
6686 if ( isDisabled !== this.options.disabled ) { |
|
6687 this._setOption( "disabled", isDisabled ); |
|
6688 } |
|
6689 if ( this.type === "radio" ) { |
|
6690 radioGroup( this.element[0] ).each(function() { |
|
6691 if ( $( this ).is( ":checked" ) ) { |
|
6692 $( this ).button( "widget" ) |
|
6693 .addClass( "ui-state-active" ) |
|
6694 .attr( "aria-pressed", "true" ); |
|
6695 } else { |
|
6696 $( this ).button( "widget" ) |
|
6697 .removeClass( "ui-state-active" ) |
|
6698 .attr( "aria-pressed", "false" ); |
|
6699 } |
|
6700 }); |
|
6701 } else if ( this.type === "checkbox" ) { |
|
6702 if ( this.element.is( ":checked" ) ) { |
|
6703 this.buttonElement |
|
6704 .addClass( "ui-state-active" ) |
|
6705 .attr( "aria-pressed", "true" ); |
|
6706 } else { |
|
6707 this.buttonElement |
|
6708 .removeClass( "ui-state-active" ) |
|
6709 .attr( "aria-pressed", "false" ); |
|
6710 } |
|
6711 } |
|
6712 }, |
|
6713 |
|
6714 _resetButton: function() { |
|
6715 if ( this.type === "input" ) { |
|
6716 if ( this.options.label ) { |
|
6717 this.element.val( this.options.label ); |
|
6718 } |
|
6719 return; |
|
6720 } |
|
6721 var buttonElement = this.buttonElement.removeClass( typeClasses ), |
|
6722 buttonText = $( "<span></span>", this.document[0] ) |
|
6723 .addClass( "ui-button-text" ) |
|
6724 .html( this.options.label ) |
|
6725 .appendTo( buttonElement.empty() ) |
|
6726 .text(), |
|
6727 icons = this.options.icons, |
|
6728 multipleIcons = icons.primary && icons.secondary, |
|
6729 buttonClasses = []; |
|
6730 |
|
6731 if ( icons.primary || icons.secondary ) { |
|
6732 if ( this.options.text ) { |
|
6733 buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) ); |
|
6734 } |
|
6735 |
|
6736 if ( icons.primary ) { |
|
6737 buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" ); |
|
6738 } |
|
6739 |
|
6740 if ( icons.secondary ) { |
|
6741 buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" ); |
|
6742 } |
|
6743 |
|
6744 if ( !this.options.text ) { |
|
6745 buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" ); |
|
6746 |
|
6747 if ( !this.hasTitle ) { |
|
6748 buttonElement.attr( "title", $.trim( buttonText ) ); |
|
6749 } |
|
6750 } |
|
6751 } else { |
|
6752 buttonClasses.push( "ui-button-text-only" ); |
|
6753 } |
|
6754 buttonElement.addClass( buttonClasses.join( " " ) ); |
|
6755 } |
|
6756 }); |
|
6757 |
|
6758 $.widget( "ui.buttonset", { |
|
6759 version: "1.10.4", |
|
6760 options: { |
|
6761 items: "button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)" |
|
6762 }, |
|
6763 |
|
6764 _create: function() { |
|
6765 this.element.addClass( "ui-buttonset" ); |
|
6766 }, |
|
6767 |
|
6768 _init: function() { |
|
6769 this.refresh(); |
|
6770 }, |
|
6771 |
|
6772 _setOption: function( key, value ) { |
|
6773 if ( key === "disabled" ) { |
|
6774 this.buttons.button( "option", key, value ); |
|
6775 } |
|
6776 |
|
6777 this._super( key, value ); |
|
6778 }, |
|
6779 |
|
6780 refresh: function() { |
|
6781 var rtl = this.element.css( "direction" ) === "rtl"; |
|
6782 |
|
6783 this.buttons = this.element.find( this.options.items ) |
|
6784 .filter( ":ui-button" ) |
|
6785 .button( "refresh" ) |
|
6786 .end() |
|
6787 .not( ":ui-button" ) |
|
6788 .button() |
|
6789 .end() |
|
6790 .map(function() { |
|
6791 return $( this ).button( "widget" )[ 0 ]; |
|
6792 }) |
|
6793 .removeClass( "ui-corner-all ui-corner-left ui-corner-right" ) |
|
6794 .filter( ":first" ) |
|
6795 .addClass( rtl ? "ui-corner-right" : "ui-corner-left" ) |
|
6796 .end() |
|
6797 .filter( ":last" ) |
|
6798 .addClass( rtl ? "ui-corner-left" : "ui-corner-right" ) |
|
6799 .end() |
|
6800 .end(); |
|
6801 }, |
|
6802 |
|
6803 _destroy: function() { |
|
6804 this.element.removeClass( "ui-buttonset" ); |
|
6805 this.buttons |
|
6806 .map(function() { |
|
6807 return $( this ).button( "widget" )[ 0 ]; |
|
6808 }) |
|
6809 .removeClass( "ui-corner-left ui-corner-right" ) |
|
6810 .end() |
|
6811 .button( "destroy" ); |
|
6812 } |
|
6813 }); |
|
6814 |
|
6815 }( jQuery ) ); |
|
6816 (function( $, undefined ) { |
|
6817 |
|
6818 $.extend($.ui, { datepicker: { version: "1.10.4" } }); |
|
6819 |
|
6820 var PROP_NAME = "datepicker", |
|
6821 instActive; |
|
6822 |
|
6823 /* Date picker manager. |
|
6824 Use the singleton instance of this class, $.datepicker, to interact with the date picker. |
|
6825 Settings for (groups of) date pickers are maintained in an instance object, |
|
6826 allowing multiple different settings on the same page. */ |
|
6827 |
|
6828 function Datepicker() { |
|
6829 this._curInst = null; // The current instance in use |
|
6830 this._keyEvent = false; // If the last event was a key event |
|
6831 this._disabledInputs = []; // List of date picker inputs that have been disabled |
|
6832 this._datepickerShowing = false; // True if the popup picker is showing , false if not |
|
6833 this._inDialog = false; // True if showing within a "dialog", false if not |
|
6834 this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division |
|
6835 this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class |
|
6836 this._appendClass = "ui-datepicker-append"; // The name of the append marker class |
|
6837 this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class |
|
6838 this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class |
|
6839 this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class |
|
6840 this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class |
|
6841 this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class |
|
6842 this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class |
|
6843 this.regional = []; // Available regional settings, indexed by language code |
|
6844 this.regional[""] = { // Default regional settings |
|
6845 closeText: "Done", // Display text for close link |
|
6846 prevText: "Prev", // Display text for previous month link |
|
6847 nextText: "Next", // Display text for next month link |
|
6848 currentText: "Today", // Display text for current month link |
|
6849 monthNames: ["January","February","March","April","May","June", |
|
6850 "July","August","September","October","November","December"], // Names of months for drop-down and formatting |
|
6851 monthNamesShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], // For formatting |
|
6852 dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], // For formatting |
|
6853 dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], // For formatting |
|
6854 dayNamesMin: ["Su","Mo","Tu","We","Th","Fr","Sa"], // Column headings for days starting at Sunday |
|
6855 weekHeader: "Wk", // Column header for week of the year |
|
6856 dateFormat: "mm/dd/yy", // See format options on parseDate |
|
6857 firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ... |
|
6858 isRTL: false, // True if right-to-left language, false if left-to-right |
|
6859 showMonthAfterYear: false, // True if the year select precedes month, false for month then year |
|
6860 yearSuffix: "" // Additional text to append to the year in the month headers |
|
6861 }; |
|
6862 this._defaults = { // Global defaults for all the date picker instances |
|
6863 showOn: "focus", // "focus" for popup on focus, |
|
6864 // "button" for trigger button, or "both" for either |
|
6865 showAnim: "fadeIn", // Name of jQuery animation for popup |
|
6866 showOptions: {}, // Options for enhanced animations |
|
6867 defaultDate: null, // Used when field is blank: actual date, |
|
6868 // +/-number for offset from today, null for today |
|
6869 appendText: "", // Display text following the input box, e.g. showing the format |
|
6870 buttonText: "...", // Text for trigger button |
|
6871 buttonImage: "", // URL for trigger button image |
|
6872 buttonImageOnly: false, // True if the image appears alone, false if it appears on a button |
|
6873 hideIfNoPrevNext: false, // True to hide next/previous month links |
|
6874 // if not applicable, false to just disable them |
|
6875 navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links |
|
6876 gotoCurrent: false, // True if today link goes back to current selection instead |
|
6877 changeMonth: false, // True if month can be selected directly, false if only prev/next |
|
6878 changeYear: false, // True if year can be selected directly, false if only prev/next |
|
6879 yearRange: "c-10:c+10", // Range of years to display in drop-down, |
|
6880 // either relative to today's year (-nn:+nn), relative to currently displayed year |
|
6881 // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n) |
|
6882 showOtherMonths: false, // True to show dates in other months, false to leave blank |
|
6883 selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable |
|
6884 showWeek: false, // True to show week of the year, false to not show it |
|
6885 calculateWeek: this.iso8601Week, // How to calculate the week of the year, |
|
6886 // takes a Date and returns the number of the week for it |
|
6887 shortYearCutoff: "+10", // Short year values < this are in the current century, |
|
6888 // > this are in the previous century, |
|
6889 // string value starting with "+" for current year + value |
|
6890 minDate: null, // The earliest selectable date, or null for no limit |
|
6891 maxDate: null, // The latest selectable date, or null for no limit |
|
6892 duration: "fast", // Duration of display/closure |
|
6893 beforeShowDay: null, // Function that takes a date and returns an array with |
|
6894 // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "", |
|
6895 // [2] = cell title (optional), e.g. $.datepicker.noWeekends |
|
6896 beforeShow: null, // Function that takes an input field and |
|
6897 // returns a set of custom settings for the date picker |
|
6898 onSelect: null, // Define a callback function when a date is selected |
|
6899 onChangeMonthYear: null, // Define a callback function when the month or year is changed |
|
6900 onClose: null, // Define a callback function when the datepicker is closed |
|
6901 numberOfMonths: 1, // Number of months to show at a time |
|
6902 showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0) |
|
6903 stepMonths: 1, // Number of months to step back/forward |
|
6904 stepBigMonths: 12, // Number of months to step back/forward for the big links |
|
6905 altField: "", // Selector for an alternate field to store selected dates into |
|
6906 altFormat: "", // The date format to use for the alternate field |
|
6907 constrainInput: true, // The input is constrained by the current date format |
|
6908 showButtonPanel: false, // True to show button panel, false to not show it |
|
6909 autoSize: false, // True to size the input for the date format, false to leave as is |
|
6910 disabled: false // The initial disabled state |
|
6911 }; |
|
6912 $.extend(this._defaults, this.regional[""]); |
|
6913 this.dpDiv = bindHover($("<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")); |
|
6914 } |
|
6915 |
|
6916 $.extend(Datepicker.prototype, { |
|
6917 /* Class name added to elements to indicate already configured with a date picker. */ |
|
6918 markerClassName: "hasDatepicker", |
|
6919 |
|
6920 //Keep track of the maximum number of rows displayed (see #7043) |
|
6921 maxRows: 4, |
|
6922 |
|
6923 // TODO rename to "widget" when switching to widget factory |
|
6924 _widgetDatepicker: function() { |
|
6925 return this.dpDiv; |
|
6926 }, |
|
6927 |
|
6928 /* Override the default settings for all instances of the date picker. |
|
6929 * @param settings object - the new settings to use as defaults (anonymous object) |
|
6930 * @return the manager object |
|
6931 */ |
|
6932 setDefaults: function(settings) { |
|
6933 extendRemove(this._defaults, settings || {}); |
|
6934 return this; |
|
6935 }, |
|
6936 |
|
6937 /* Attach the date picker to a jQuery selection. |
|
6938 * @param target element - the target input field or division or span |
|
6939 * @param settings object - the new settings to use for this date picker instance (anonymous) |
|
6940 */ |
|
6941 _attachDatepicker: function(target, settings) { |
|
6942 var nodeName, inline, inst; |
|
6943 nodeName = target.nodeName.toLowerCase(); |
|
6944 inline = (nodeName === "div" || nodeName === "span"); |
|
6945 if (!target.id) { |
|
6946 this.uuid += 1; |
|
6947 target.id = "dp" + this.uuid; |
|
6948 } |
|
6949 inst = this._newInst($(target), inline); |
|
6950 inst.settings = $.extend({}, settings || {}); |
|
6951 if (nodeName === "input") { |
|
6952 this._connectDatepicker(target, inst); |
|
6953 } else if (inline) { |
|
6954 this._inlineDatepicker(target, inst); |
|
6955 } |
|
6956 }, |
|
6957 |
|
6958 /* Create a new instance object. */ |
|
6959 _newInst: function(target, inline) { |
|
6960 var id = target[0].id.replace(/([^A-Za-z0-9_\-])/g, "\\\\$1"); // escape jQuery meta chars |
|
6961 return {id: id, input: target, // associated target |
|
6962 selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection |
|
6963 drawMonth: 0, drawYear: 0, // month being drawn |
|
6964 inline: inline, // is datepicker inline or not |
|
6965 dpDiv: (!inline ? this.dpDiv : // presentation div |
|
6966 bindHover($("<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")))}; |
|
6967 }, |
|
6968 |
|
6969 /* Attach the date picker to an input field. */ |
|
6970 _connectDatepicker: function(target, inst) { |
|
6971 var input = $(target); |
|
6972 inst.append = $([]); |
|
6973 inst.trigger = $([]); |
|
6974 if (input.hasClass(this.markerClassName)) { |
|
6975 return; |
|
6976 } |
|
6977 this._attachments(input, inst); |
|
6978 input.addClass(this.markerClassName).keydown(this._doKeyDown). |
|
6979 keypress(this._doKeyPress).keyup(this._doKeyUp); |
|
6980 this._autoSize(inst); |
|
6981 $.data(target, PROP_NAME, inst); |
|
6982 //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665) |
|
6983 if( inst.settings.disabled ) { |
|
6984 this._disableDatepicker( target ); |
|
6985 } |
|
6986 }, |
|
6987 |
|
6988 /* Make attachments based on settings. */ |
|
6989 _attachments: function(input, inst) { |
|
6990 var showOn, buttonText, buttonImage, |
|
6991 appendText = this._get(inst, "appendText"), |
|
6992 isRTL = this._get(inst, "isRTL"); |
|
6993 |
|
6994 if (inst.append) { |
|
6995 inst.append.remove(); |
|
6996 } |
|
6997 if (appendText) { |
|
6998 inst.append = $("<span class='" + this._appendClass + "'>" + appendText + "</span>"); |
|
6999 input[isRTL ? "before" : "after"](inst.append); |
|
7000 } |
|
7001 |
|
7002 input.unbind("focus", this._showDatepicker); |
|
7003 |
|
7004 if (inst.trigger) { |
|
7005 inst.trigger.remove(); |
|
7006 } |
|
7007 |
|
7008 showOn = this._get(inst, "showOn"); |
|
7009 if (showOn === "focus" || showOn === "both") { // pop-up date picker when in the marked field |
|
7010 input.focus(this._showDatepicker); |
|
7011 } |
|
7012 if (showOn === "button" || showOn === "both") { // pop-up date picker when button clicked |
|
7013 buttonText = this._get(inst, "buttonText"); |
|
7014 buttonImage = this._get(inst, "buttonImage"); |
|
7015 inst.trigger = $(this._get(inst, "buttonImageOnly") ? |
|
7016 $("<img/>").addClass(this._triggerClass). |
|
7017 attr({ src: buttonImage, alt: buttonText, title: buttonText }) : |
|
7018 $("<button type='button'></button>").addClass(this._triggerClass). |
|
7019 html(!buttonImage ? buttonText : $("<img/>").attr( |
|
7020 { src:buttonImage, alt:buttonText, title:buttonText }))); |
|
7021 input[isRTL ? "before" : "after"](inst.trigger); |
|
7022 inst.trigger.click(function() { |
|
7023 if ($.datepicker._datepickerShowing && $.datepicker._lastInput === input[0]) { |
|
7024 $.datepicker._hideDatepicker(); |
|
7025 } else if ($.datepicker._datepickerShowing && $.datepicker._lastInput !== input[0]) { |
|
7026 $.datepicker._hideDatepicker(); |
|
7027 $.datepicker._showDatepicker(input[0]); |
|
7028 } else { |
|
7029 $.datepicker._showDatepicker(input[0]); |
|
7030 } |
|
7031 return false; |
|
7032 }); |
|
7033 } |
|
7034 }, |
|
7035 |
|
7036 /* Apply the maximum length for the date format. */ |
|
7037 _autoSize: function(inst) { |
|
7038 if (this._get(inst, "autoSize") && !inst.inline) { |
|
7039 var findMax, max, maxI, i, |
|
7040 date = new Date(2009, 12 - 1, 20), // Ensure double digits |
|
7041 dateFormat = this._get(inst, "dateFormat"); |
|
7042 |
|
7043 if (dateFormat.match(/[DM]/)) { |
|
7044 findMax = function(names) { |
|
7045 max = 0; |
|
7046 maxI = 0; |
|
7047 for (i = 0; i < names.length; i++) { |
|
7048 if (names[i].length > max) { |
|
7049 max = names[i].length; |
|
7050 maxI = i; |
|
7051 } |
|
7052 } |
|
7053 return maxI; |
|
7054 }; |
|
7055 date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ? |
|
7056 "monthNames" : "monthNamesShort")))); |
|
7057 date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ? |
|
7058 "dayNames" : "dayNamesShort"))) + 20 - date.getDay()); |
|
7059 } |
|
7060 inst.input.attr("size", this._formatDate(inst, date).length); |
|
7061 } |
|
7062 }, |
|
7063 |
|
7064 /* Attach an inline date picker to a div. */ |
|
7065 _inlineDatepicker: function(target, inst) { |
|
7066 var divSpan = $(target); |
|
7067 if (divSpan.hasClass(this.markerClassName)) { |
|
7068 return; |
|
7069 } |
|
7070 divSpan.addClass(this.markerClassName).append(inst.dpDiv); |
|
7071 $.data(target, PROP_NAME, inst); |
|
7072 this._setDate(inst, this._getDefaultDate(inst), true); |
|
7073 this._updateDatepicker(inst); |
|
7074 this._updateAlternate(inst); |
|
7075 //If disabled option is true, disable the datepicker before showing it (see ticket #5665) |
|
7076 if( inst.settings.disabled ) { |
|
7077 this._disableDatepicker( target ); |
|
7078 } |
|
7079 // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements |
|
7080 // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height |
|
7081 inst.dpDiv.css( "display", "block" ); |
|
7082 }, |
|
7083 |
|
7084 /* Pop-up the date picker in a "dialog" box. |
|
7085 * @param input element - ignored |
|
7086 * @param date string or Date - the initial date to display |
|
7087 * @param onSelect function - the function to call when a date is selected |
|
7088 * @param settings object - update the dialog date picker instance's settings (anonymous object) |
|
7089 * @param pos int[2] - coordinates for the dialog's position within the screen or |
|
7090 * event - with x/y coordinates or |
|
7091 * leave empty for default (screen centre) |
|
7092 * @return the manager object |
|
7093 */ |
|
7094 _dialogDatepicker: function(input, date, onSelect, settings, pos) { |
|
7095 var id, browserWidth, browserHeight, scrollX, scrollY, |
|
7096 inst = this._dialogInst; // internal instance |
|
7097 |
|
7098 if (!inst) { |
|
7099 this.uuid += 1; |
|
7100 id = "dp" + this.uuid; |
|
7101 this._dialogInput = $("<input type='text' id='" + id + |
|
7102 "' style='position: absolute; top: -100px; width: 0px;'/>"); |
|
7103 this._dialogInput.keydown(this._doKeyDown); |
|
7104 $("body").append(this._dialogInput); |
|
7105 inst = this._dialogInst = this._newInst(this._dialogInput, false); |
|
7106 inst.settings = {}; |
|
7107 $.data(this._dialogInput[0], PROP_NAME, inst); |
|
7108 } |
|
7109 extendRemove(inst.settings, settings || {}); |
|
7110 date = (date && date.constructor === Date ? this._formatDate(inst, date) : date); |
|
7111 this._dialogInput.val(date); |
|
7112 |
|
7113 this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null); |
|
7114 if (!this._pos) { |
|
7115 browserWidth = document.documentElement.clientWidth; |
|
7116 browserHeight = document.documentElement.clientHeight; |
|
7117 scrollX = document.documentElement.scrollLeft || document.body.scrollLeft; |
|
7118 scrollY = document.documentElement.scrollTop || document.body.scrollTop; |
|
7119 this._pos = // should use actual width/height below |
|
7120 [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY]; |
|
7121 } |
|
7122 |
|
7123 // move input on screen for focus, but hidden behind dialog |
|
7124 this._dialogInput.css("left", (this._pos[0] + 20) + "px").css("top", this._pos[1] + "px"); |
|
7125 inst.settings.onSelect = onSelect; |
|
7126 this._inDialog = true; |
|
7127 this.dpDiv.addClass(this._dialogClass); |
|
7128 this._showDatepicker(this._dialogInput[0]); |
|
7129 if ($.blockUI) { |
|
7130 $.blockUI(this.dpDiv); |
|
7131 } |
|
7132 $.data(this._dialogInput[0], PROP_NAME, inst); |
|
7133 return this; |
|
7134 }, |
|
7135 |
|
7136 /* Detach a datepicker from its control. |
|
7137 * @param target element - the target input field or division or span |
|
7138 */ |
|
7139 _destroyDatepicker: function(target) { |
|
7140 var nodeName, |
|
7141 $target = $(target), |
|
7142 inst = $.data(target, PROP_NAME); |
|
7143 |
|
7144 if (!$target.hasClass(this.markerClassName)) { |
|
7145 return; |
|
7146 } |
|
7147 |
|
7148 nodeName = target.nodeName.toLowerCase(); |
|
7149 $.removeData(target, PROP_NAME); |
|
7150 if (nodeName === "input") { |
|
7151 inst.append.remove(); |
|
7152 inst.trigger.remove(); |
|
7153 $target.removeClass(this.markerClassName). |
|
7154 unbind("focus", this._showDatepicker). |
|
7155 unbind("keydown", this._doKeyDown). |
|
7156 unbind("keypress", this._doKeyPress). |
|
7157 unbind("keyup", this._doKeyUp); |
|
7158 } else if (nodeName === "div" || nodeName === "span") { |
|
7159 $target.removeClass(this.markerClassName).empty(); |
|
7160 } |
|
7161 }, |
|
7162 |
|
7163 /* Enable the date picker to a jQuery selection. |
|
7164 * @param target element - the target input field or division or span |
|
7165 */ |
|
7166 _enableDatepicker: function(target) { |
|
7167 var nodeName, inline, |
|
7168 $target = $(target), |
|
7169 inst = $.data(target, PROP_NAME); |
|
7170 |
|
7171 if (!$target.hasClass(this.markerClassName)) { |
|
7172 return; |
|
7173 } |
|
7174 |
|
7175 nodeName = target.nodeName.toLowerCase(); |
|
7176 if (nodeName === "input") { |
|
7177 target.disabled = false; |
|
7178 inst.trigger.filter("button"). |
|
7179 each(function() { this.disabled = false; }).end(). |
|
7180 filter("img").css({opacity: "1.0", cursor: ""}); |
|
7181 } else if (nodeName === "div" || nodeName === "span") { |
|
7182 inline = $target.children("." + this._inlineClass); |
|
7183 inline.children().removeClass("ui-state-disabled"); |
|
7184 inline.find("select.ui-datepicker-month, select.ui-datepicker-year"). |
|
7185 prop("disabled", false); |
|
7186 } |
|
7187 this._disabledInputs = $.map(this._disabledInputs, |
|
7188 function(value) { return (value === target ? null : value); }); // delete entry |
|
7189 }, |
|
7190 |
|
7191 /* Disable the date picker to a jQuery selection. |
|
7192 * @param target element - the target input field or division or span |
|
7193 */ |
|
7194 _disableDatepicker: function(target) { |
|
7195 var nodeName, inline, |
|
7196 $target = $(target), |
|
7197 inst = $.data(target, PROP_NAME); |
|
7198 |
|
7199 if (!$target.hasClass(this.markerClassName)) { |
|
7200 return; |
|
7201 } |
|
7202 |
|
7203 nodeName = target.nodeName.toLowerCase(); |
|
7204 if (nodeName === "input") { |
|
7205 target.disabled = true; |
|
7206 inst.trigger.filter("button"). |
|
7207 each(function() { this.disabled = true; }).end(). |
|
7208 filter("img").css({opacity: "0.5", cursor: "default"}); |
|
7209 } else if (nodeName === "div" || nodeName === "span") { |
|
7210 inline = $target.children("." + this._inlineClass); |
|
7211 inline.children().addClass("ui-state-disabled"); |
|
7212 inline.find("select.ui-datepicker-month, select.ui-datepicker-year"). |
|
7213 prop("disabled", true); |
|
7214 } |
|
7215 this._disabledInputs = $.map(this._disabledInputs, |
|
7216 function(value) { return (value === target ? null : value); }); // delete entry |
|
7217 this._disabledInputs[this._disabledInputs.length] = target; |
|
7218 }, |
|
7219 |
|
7220 /* Is the first field in a jQuery collection disabled as a datepicker? |
|
7221 * @param target element - the target input field or division or span |
|
7222 * @return boolean - true if disabled, false if enabled |
|
7223 */ |
|
7224 _isDisabledDatepicker: function(target) { |
|
7225 if (!target) { |
|
7226 return false; |
|
7227 } |
|
7228 for (var i = 0; i < this._disabledInputs.length; i++) { |
|
7229 if (this._disabledInputs[i] === target) { |
|
7230 return true; |
|
7231 } |
|
7232 } |
|
7233 return false; |
|
7234 }, |
|
7235 |
|
7236 /* Retrieve the instance data for the target control. |
|
7237 * @param target element - the target input field or division or span |
|
7238 * @return object - the associated instance data |
|
7239 * @throws error if a jQuery problem getting data |
|
7240 */ |
|
7241 _getInst: function(target) { |
|
7242 try { |
|
7243 return $.data(target, PROP_NAME); |
|
7244 } |
|
7245 catch (err) { |
|
7246 throw "Missing instance data for this datepicker"; |
|
7247 } |
|
7248 }, |
|
7249 |
|
7250 /* Update or retrieve the settings for a date picker attached to an input field or division. |
|
7251 * @param target element - the target input field or division or span |
|
7252 * @param name object - the new settings to update or |
|
7253 * string - the name of the setting to change or retrieve, |
|
7254 * when retrieving also "all" for all instance settings or |
|
7255 * "defaults" for all global defaults |
|
7256 * @param value any - the new value for the setting |
|
7257 * (omit if above is an object or to retrieve a value) |
|
7258 */ |
|
7259 _optionDatepicker: function(target, name, value) { |
|
7260 var settings, date, minDate, maxDate, |
|
7261 inst = this._getInst(target); |
|
7262 |
|
7263 if (arguments.length === 2 && typeof name === "string") { |
|
7264 return (name === "defaults" ? $.extend({}, $.datepicker._defaults) : |
|
7265 (inst ? (name === "all" ? $.extend({}, inst.settings) : |
|
7266 this._get(inst, name)) : null)); |
|
7267 } |
|
7268 |
|
7269 settings = name || {}; |
|
7270 if (typeof name === "string") { |
|
7271 settings = {}; |
|
7272 settings[name] = value; |
|
7273 } |
|
7274 |
|
7275 if (inst) { |
|
7276 if (this._curInst === inst) { |
|
7277 this._hideDatepicker(); |
|
7278 } |
|
7279 |
|
7280 date = this._getDateDatepicker(target, true); |
|
7281 minDate = this._getMinMaxDate(inst, "min"); |
|
7282 maxDate = this._getMinMaxDate(inst, "max"); |
|
7283 extendRemove(inst.settings, settings); |
|
7284 // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided |
|
7285 if (minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined) { |
|
7286 inst.settings.minDate = this._formatDate(inst, minDate); |
|
7287 } |
|
7288 if (maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined) { |
|
7289 inst.settings.maxDate = this._formatDate(inst, maxDate); |
|
7290 } |
|
7291 if ( "disabled" in settings ) { |
|
7292 if ( settings.disabled ) { |
|
7293 this._disableDatepicker(target); |
|
7294 } else { |
|
7295 this._enableDatepicker(target); |
|
7296 } |
|
7297 } |
|
7298 this._attachments($(target), inst); |
|
7299 this._autoSize(inst); |
|
7300 this._setDate(inst, date); |
|
7301 this._updateAlternate(inst); |
|
7302 this._updateDatepicker(inst); |
|
7303 } |
|
7304 }, |
|
7305 |
|
7306 // change method deprecated |
|
7307 _changeDatepicker: function(target, name, value) { |
|
7308 this._optionDatepicker(target, name, value); |
|
7309 }, |
|
7310 |
|
7311 /* Redraw the date picker attached to an input field or division. |
|
7312 * @param target element - the target input field or division or span |
|
7313 */ |
|
7314 _refreshDatepicker: function(target) { |
|
7315 var inst = this._getInst(target); |
|
7316 if (inst) { |
|
7317 this._updateDatepicker(inst); |
|
7318 } |
|
7319 }, |
|
7320 |
|
7321 /* Set the dates for a jQuery selection. |
|
7322 * @param target element - the target input field or division or span |
|
7323 * @param date Date - the new date |
|
7324 */ |
|
7325 _setDateDatepicker: function(target, date) { |
|
7326 var inst = this._getInst(target); |
|
7327 if (inst) { |
|
7328 this._setDate(inst, date); |
|
7329 this._updateDatepicker(inst); |
|
7330 this._updateAlternate(inst); |
|
7331 } |
|
7332 }, |
|
7333 |
|
7334 /* Get the date(s) for the first entry in a jQuery selection. |
|
7335 * @param target element - the target input field or division or span |
|
7336 * @param noDefault boolean - true if no default date is to be used |
|
7337 * @return Date - the current date |
|
7338 */ |
|
7339 _getDateDatepicker: function(target, noDefault) { |
|
7340 var inst = this._getInst(target); |
|
7341 if (inst && !inst.inline) { |
|
7342 this._setDateFromField(inst, noDefault); |
|
7343 } |
|
7344 return (inst ? this._getDate(inst) : null); |
|
7345 }, |
|
7346 |
|
7347 /* Handle keystrokes. */ |
|
7348 _doKeyDown: function(event) { |
|
7349 var onSelect, dateStr, sel, |
|
7350 inst = $.datepicker._getInst(event.target), |
|
7351 handled = true, |
|
7352 isRTL = inst.dpDiv.is(".ui-datepicker-rtl"); |
|
7353 |
|
7354 inst._keyEvent = true; |
|
7355 if ($.datepicker._datepickerShowing) { |
|
7356 switch (event.keyCode) { |
|
7357 case 9: $.datepicker._hideDatepicker(); |
|
7358 handled = false; |
|
7359 break; // hide on tab out |
|
7360 case 13: sel = $("td." + $.datepicker._dayOverClass + ":not(." + |
|
7361 $.datepicker._currentClass + ")", inst.dpDiv); |
|
7362 if (sel[0]) { |
|
7363 $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]); |
|
7364 } |
|
7365 |
|
7366 onSelect = $.datepicker._get(inst, "onSelect"); |
|
7367 if (onSelect) { |
|
7368 dateStr = $.datepicker._formatDate(inst); |
|
7369 |
|
7370 // trigger custom callback |
|
7371 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); |
|
7372 } else { |
|
7373 $.datepicker._hideDatepicker(); |
|
7374 } |
|
7375 |
|
7376 return false; // don't submit the form |
|
7377 case 27: $.datepicker._hideDatepicker(); |
|
7378 break; // hide on escape |
|
7379 case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ? |
|
7380 -$.datepicker._get(inst, "stepBigMonths") : |
|
7381 -$.datepicker._get(inst, "stepMonths")), "M"); |
|
7382 break; // previous month/year on page up/+ ctrl |
|
7383 case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ? |
|
7384 +$.datepicker._get(inst, "stepBigMonths") : |
|
7385 +$.datepicker._get(inst, "stepMonths")), "M"); |
|
7386 break; // next month/year on page down/+ ctrl |
|
7387 case 35: if (event.ctrlKey || event.metaKey) { |
|
7388 $.datepicker._clearDate(event.target); |
|
7389 } |
|
7390 handled = event.ctrlKey || event.metaKey; |
|
7391 break; // clear on ctrl or command +end |
|
7392 case 36: if (event.ctrlKey || event.metaKey) { |
|
7393 $.datepicker._gotoToday(event.target); |
|
7394 } |
|
7395 handled = event.ctrlKey || event.metaKey; |
|
7396 break; // current on ctrl or command +home |
|
7397 case 37: if (event.ctrlKey || event.metaKey) { |
|
7398 $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), "D"); |
|
7399 } |
|
7400 handled = event.ctrlKey || event.metaKey; |
|
7401 // -1 day on ctrl or command +left |
|
7402 if (event.originalEvent.altKey) { |
|
7403 $.datepicker._adjustDate(event.target, (event.ctrlKey ? |
|
7404 -$.datepicker._get(inst, "stepBigMonths") : |
|
7405 -$.datepicker._get(inst, "stepMonths")), "M"); |
|
7406 } |
|
7407 // next month/year on alt +left on Mac |
|
7408 break; |
|
7409 case 38: if (event.ctrlKey || event.metaKey) { |
|
7410 $.datepicker._adjustDate(event.target, -7, "D"); |
|
7411 } |
|
7412 handled = event.ctrlKey || event.metaKey; |
|
7413 break; // -1 week on ctrl or command +up |
|
7414 case 39: if (event.ctrlKey || event.metaKey) { |
|
7415 $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), "D"); |
|
7416 } |
|
7417 handled = event.ctrlKey || event.metaKey; |
|
7418 // +1 day on ctrl or command +right |
|
7419 if (event.originalEvent.altKey) { |
|
7420 $.datepicker._adjustDate(event.target, (event.ctrlKey ? |
|
7421 +$.datepicker._get(inst, "stepBigMonths") : |
|
7422 +$.datepicker._get(inst, "stepMonths")), "M"); |
|
7423 } |
|
7424 // next month/year on alt +right |
|
7425 break; |
|
7426 case 40: if (event.ctrlKey || event.metaKey) { |
|
7427 $.datepicker._adjustDate(event.target, +7, "D"); |
|
7428 } |
|
7429 handled = event.ctrlKey || event.metaKey; |
|
7430 break; // +1 week on ctrl or command +down |
|
7431 default: handled = false; |
|
7432 } |
|
7433 } else if (event.keyCode === 36 && event.ctrlKey) { // display the date picker on ctrl+home |
|
7434 $.datepicker._showDatepicker(this); |
|
7435 } else { |
|
7436 handled = false; |
|
7437 } |
|
7438 |
|
7439 if (handled) { |
|
7440 event.preventDefault(); |
|
7441 event.stopPropagation(); |
|
7442 } |
|
7443 }, |
|
7444 |
|
7445 /* Filter entered characters - based on date format. */ |
|
7446 _doKeyPress: function(event) { |
|
7447 var chars, chr, |
|
7448 inst = $.datepicker._getInst(event.target); |
|
7449 |
|
7450 if ($.datepicker._get(inst, "constrainInput")) { |
|
7451 chars = $.datepicker._possibleChars($.datepicker._get(inst, "dateFormat")); |
|
7452 chr = String.fromCharCode(event.charCode == null ? event.keyCode : event.charCode); |
|
7453 return event.ctrlKey || event.metaKey || (chr < " " || !chars || chars.indexOf(chr) > -1); |
|
7454 } |
|
7455 }, |
|
7456 |
|
7457 /* Synchronise manual entry and field/alternate field. */ |
|
7458 _doKeyUp: function(event) { |
|
7459 var date, |
|
7460 inst = $.datepicker._getInst(event.target); |
|
7461 |
|
7462 if (inst.input.val() !== inst.lastVal) { |
|
7463 try { |
|
7464 date = $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"), |
|
7465 (inst.input ? inst.input.val() : null), |
|
7466 $.datepicker._getFormatConfig(inst)); |
|
7467 |
|
7468 if (date) { // only if valid |
|
7469 $.datepicker._setDateFromField(inst); |
|
7470 $.datepicker._updateAlternate(inst); |
|
7471 $.datepicker._updateDatepicker(inst); |
|
7472 } |
|
7473 } |
|
7474 catch (err) { |
|
7475 } |
|
7476 } |
|
7477 return true; |
|
7478 }, |
|
7479 |
|
7480 /* Pop-up the date picker for a given input field. |
|
7481 * If false returned from beforeShow event handler do not show. |
|
7482 * @param input element - the input field attached to the date picker or |
|
7483 * event - if triggered by focus |
|
7484 */ |
|
7485 _showDatepicker: function(input) { |
|
7486 input = input.target || input; |
|
7487 if (input.nodeName.toLowerCase() !== "input") { // find from button/image trigger |
|
7488 input = $("input", input.parentNode)[0]; |
|
7489 } |
|
7490 |
|
7491 if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput === input) { // already here |
|
7492 return; |
|
7493 } |
|
7494 |
|
7495 var inst, beforeShow, beforeShowSettings, isFixed, |
|
7496 offset, showAnim, duration; |
|
7497 |
|
7498 inst = $.datepicker._getInst(input); |
|
7499 if ($.datepicker._curInst && $.datepicker._curInst !== inst) { |
|
7500 $.datepicker._curInst.dpDiv.stop(true, true); |
|
7501 if ( inst && $.datepicker._datepickerShowing ) { |
|
7502 $.datepicker._hideDatepicker( $.datepicker._curInst.input[0] ); |
|
7503 } |
|
7504 } |
|
7505 |
|
7506 beforeShow = $.datepicker._get(inst, "beforeShow"); |
|
7507 beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {}; |
|
7508 if(beforeShowSettings === false){ |
|
7509 return; |
|
7510 } |
|
7511 extendRemove(inst.settings, beforeShowSettings); |
|
7512 |
|
7513 inst.lastVal = null; |
|
7514 $.datepicker._lastInput = input; |
|
7515 $.datepicker._setDateFromField(inst); |
|
7516 |
|
7517 if ($.datepicker._inDialog) { // hide cursor |
|
7518 input.value = ""; |
|
7519 } |
|
7520 if (!$.datepicker._pos) { // position below input |
|
7521 $.datepicker._pos = $.datepicker._findPos(input); |
|
7522 $.datepicker._pos[1] += input.offsetHeight; // add the height |
|
7523 } |
|
7524 |
|
7525 isFixed = false; |
|
7526 $(input).parents().each(function() { |
|
7527 isFixed |= $(this).css("position") === "fixed"; |
|
7528 return !isFixed; |
|
7529 }); |
|
7530 |
|
7531 offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]}; |
|
7532 $.datepicker._pos = null; |
|
7533 //to avoid flashes on Firefox |
|
7534 inst.dpDiv.empty(); |
|
7535 // determine sizing offscreen |
|
7536 inst.dpDiv.css({position: "absolute", display: "block", top: "-1000px"}); |
|
7537 $.datepicker._updateDatepicker(inst); |
|
7538 // fix width for dynamic number of date pickers |
|
7539 // and adjust position before showing |
|
7540 offset = $.datepicker._checkOffset(inst, offset, isFixed); |
|
7541 inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ? |
|
7542 "static" : (isFixed ? "fixed" : "absolute")), display: "none", |
|
7543 left: offset.left + "px", top: offset.top + "px"}); |
|
7544 |
|
7545 if (!inst.inline) { |
|
7546 showAnim = $.datepicker._get(inst, "showAnim"); |
|
7547 duration = $.datepicker._get(inst, "duration"); |
|
7548 inst.dpDiv.zIndex($(input).zIndex()+1); |
|
7549 $.datepicker._datepickerShowing = true; |
|
7550 |
|
7551 if ( $.effects && $.effects.effect[ showAnim ] ) { |
|
7552 inst.dpDiv.show(showAnim, $.datepicker._get(inst, "showOptions"), duration); |
|
7553 } else { |
|
7554 inst.dpDiv[showAnim || "show"](showAnim ? duration : null); |
|
7555 } |
|
7556 |
|
7557 if ( $.datepicker._shouldFocusInput( inst ) ) { |
|
7558 inst.input.focus(); |
|
7559 } |
|
7560 |
|
7561 $.datepicker._curInst = inst; |
|
7562 } |
|
7563 }, |
|
7564 |
|
7565 /* Generate the date picker content. */ |
|
7566 _updateDatepicker: function(inst) { |
|
7567 this.maxRows = 4; //Reset the max number of rows being displayed (see #7043) |
|
7568 instActive = inst; // for delegate hover events |
|
7569 inst.dpDiv.empty().append(this._generateHTML(inst)); |
|
7570 this._attachHandlers(inst); |
|
7571 inst.dpDiv.find("." + this._dayOverClass + " a").mouseover(); |
|
7572 |
|
7573 var origyearshtml, |
|
7574 numMonths = this._getNumberOfMonths(inst), |
|
7575 cols = numMonths[1], |
|
7576 width = 17; |
|
7577 |
|
7578 inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""); |
|
7579 if (cols > 1) { |
|
7580 inst.dpDiv.addClass("ui-datepicker-multi-" + cols).css("width", (width * cols) + "em"); |
|
7581 } |
|
7582 inst.dpDiv[(numMonths[0] !== 1 || numMonths[1] !== 1 ? "add" : "remove") + |
|
7583 "Class"]("ui-datepicker-multi"); |
|
7584 inst.dpDiv[(this._get(inst, "isRTL") ? "add" : "remove") + |
|
7585 "Class"]("ui-datepicker-rtl"); |
|
7586 |
|
7587 if (inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) { |
|
7588 inst.input.focus(); |
|
7589 } |
|
7590 |
|
7591 // deffered render of the years select (to avoid flashes on Firefox) |
|
7592 if( inst.yearshtml ){ |
|
7593 origyearshtml = inst.yearshtml; |
|
7594 setTimeout(function(){ |
|
7595 //assure that inst.yearshtml didn't change. |
|
7596 if( origyearshtml === inst.yearshtml && inst.yearshtml ){ |
|
7597 inst.dpDiv.find("select.ui-datepicker-year:first").replaceWith(inst.yearshtml); |
|
7598 } |
|
7599 origyearshtml = inst.yearshtml = null; |
|
7600 }, 0); |
|
7601 } |
|
7602 }, |
|
7603 |
|
7604 // #6694 - don't focus the input if it's already focused |
|
7605 // this breaks the change event in IE |
|
7606 // Support: IE and jQuery <1.9 |
|
7607 _shouldFocusInput: function( inst ) { |
|
7608 return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" ); |
|
7609 }, |
|
7610 |
|
7611 /* Check positioning to remain on screen. */ |
|
7612 _checkOffset: function(inst, offset, isFixed) { |
|
7613 var dpWidth = inst.dpDiv.outerWidth(), |
|
7614 dpHeight = inst.dpDiv.outerHeight(), |
|
7615 inputWidth = inst.input ? inst.input.outerWidth() : 0, |
|
7616 inputHeight = inst.input ? inst.input.outerHeight() : 0, |
|
7617 viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft()), |
|
7618 viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop()); |
|
7619 |
|
7620 offset.left -= (this._get(inst, "isRTL") ? (dpWidth - inputWidth) : 0); |
|
7621 offset.left -= (isFixed && offset.left === inst.input.offset().left) ? $(document).scrollLeft() : 0; |
|
7622 offset.top -= (isFixed && offset.top === (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0; |
|
7623 |
|
7624 // now check if datepicker is showing outside window viewport - move to a better place if so. |
|
7625 offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ? |
|
7626 Math.abs(offset.left + dpWidth - viewWidth) : 0); |
|
7627 offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ? |
|
7628 Math.abs(dpHeight + inputHeight) : 0); |
|
7629 |
|
7630 return offset; |
|
7631 }, |
|
7632 |
|
7633 /* Find an object's position on the screen. */ |
|
7634 _findPos: function(obj) { |
|
7635 var position, |
|
7636 inst = this._getInst(obj), |
|
7637 isRTL = this._get(inst, "isRTL"); |
|
7638 |
|
7639 while (obj && (obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden(obj))) { |
|
7640 obj = obj[isRTL ? "previousSibling" : "nextSibling"]; |
|
7641 } |
|
7642 |
|
7643 position = $(obj).offset(); |
|
7644 return [position.left, position.top]; |
|
7645 }, |
|
7646 |
|
7647 /* Hide the date picker from view. |
|
7648 * @param input element - the input field attached to the date picker |
|
7649 */ |
|
7650 _hideDatepicker: function(input) { |
|
7651 var showAnim, duration, postProcess, onClose, |
|
7652 inst = this._curInst; |
|
7653 |
|
7654 if (!inst || (input && inst !== $.data(input, PROP_NAME))) { |
|
7655 return; |
|
7656 } |
|
7657 |
|
7658 if (this._datepickerShowing) { |
|
7659 showAnim = this._get(inst, "showAnim"); |
|
7660 duration = this._get(inst, "duration"); |
|
7661 postProcess = function() { |
|
7662 $.datepicker._tidyDialog(inst); |
|
7663 }; |
|
7664 |
|
7665 // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed |
|
7666 if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) { |
|
7667 inst.dpDiv.hide(showAnim, $.datepicker._get(inst, "showOptions"), duration, postProcess); |
|
7668 } else { |
|
7669 inst.dpDiv[(showAnim === "slideDown" ? "slideUp" : |
|
7670 (showAnim === "fadeIn" ? "fadeOut" : "hide"))]((showAnim ? duration : null), postProcess); |
|
7671 } |
|
7672 |
|
7673 if (!showAnim) { |
|
7674 postProcess(); |
|
7675 } |
|
7676 this._datepickerShowing = false; |
|
7677 |
|
7678 onClose = this._get(inst, "onClose"); |
|
7679 if (onClose) { |
|
7680 onClose.apply((inst.input ? inst.input[0] : null), [(inst.input ? inst.input.val() : ""), inst]); |
|
7681 } |
|
7682 |
|
7683 this._lastInput = null; |
|
7684 if (this._inDialog) { |
|
7685 this._dialogInput.css({ position: "absolute", left: "0", top: "-100px" }); |
|
7686 if ($.blockUI) { |
|
7687 $.unblockUI(); |
|
7688 $("body").append(this.dpDiv); |
|
7689 } |
|
7690 } |
|
7691 this._inDialog = false; |
|
7692 } |
|
7693 }, |
|
7694 |
|
7695 /* Tidy up after a dialog display. */ |
|
7696 _tidyDialog: function(inst) { |
|
7697 inst.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar"); |
|
7698 }, |
|
7699 |
|
7700 /* Close date picker if clicked elsewhere. */ |
|
7701 _checkExternalClick: function(event) { |
|
7702 if (!$.datepicker._curInst) { |
|
7703 return; |
|
7704 } |
|
7705 |
|
7706 var $target = $(event.target), |
|
7707 inst = $.datepicker._getInst($target[0]); |
|
7708 |
|
7709 if ( ( ( $target[0].id !== $.datepicker._mainDivId && |
|
7710 $target.parents("#" + $.datepicker._mainDivId).length === 0 && |
|
7711 !$target.hasClass($.datepicker.markerClassName) && |
|
7712 !$target.closest("." + $.datepicker._triggerClass).length && |
|
7713 $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) || |
|
7714 ( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst !== inst ) ) { |
|
7715 $.datepicker._hideDatepicker(); |
|
7716 } |
|
7717 }, |
|
7718 |
|
7719 /* Adjust one of the date sub-fields. */ |
|
7720 _adjustDate: function(id, offset, period) { |
|
7721 var target = $(id), |
|
7722 inst = this._getInst(target[0]); |
|
7723 |
|
7724 if (this._isDisabledDatepicker(target[0])) { |
|
7725 return; |
|
7726 } |
|
7727 this._adjustInstDate(inst, offset + |
|
7728 (period === "M" ? this._get(inst, "showCurrentAtPos") : 0), // undo positioning |
|
7729 period); |
|
7730 this._updateDatepicker(inst); |
|
7731 }, |
|
7732 |
|
7733 /* Action for current link. */ |
|
7734 _gotoToday: function(id) { |
|
7735 var date, |
|
7736 target = $(id), |
|
7737 inst = this._getInst(target[0]); |
|
7738 |
|
7739 if (this._get(inst, "gotoCurrent") && inst.currentDay) { |
|
7740 inst.selectedDay = inst.currentDay; |
|
7741 inst.drawMonth = inst.selectedMonth = inst.currentMonth; |
|
7742 inst.drawYear = inst.selectedYear = inst.currentYear; |
|
7743 } else { |
|
7744 date = new Date(); |
|
7745 inst.selectedDay = date.getDate(); |
|
7746 inst.drawMonth = inst.selectedMonth = date.getMonth(); |
|
7747 inst.drawYear = inst.selectedYear = date.getFullYear(); |
|
7748 } |
|
7749 this._notifyChange(inst); |
|
7750 this._adjustDate(target); |
|
7751 }, |
|
7752 |
|
7753 /* Action for selecting a new month/year. */ |
|
7754 _selectMonthYear: function(id, select, period) { |
|
7755 var target = $(id), |
|
7756 inst = this._getInst(target[0]); |
|
7757 |
|
7758 inst["selected" + (period === "M" ? "Month" : "Year")] = |
|
7759 inst["draw" + (period === "M" ? "Month" : "Year")] = |
|
7760 parseInt(select.options[select.selectedIndex].value,10); |
|
7761 |
|
7762 this._notifyChange(inst); |
|
7763 this._adjustDate(target); |
|
7764 }, |
|
7765 |
|
7766 /* Action for selecting a day. */ |
|
7767 _selectDay: function(id, month, year, td) { |
|
7768 var inst, |
|
7769 target = $(id); |
|
7770 |
|
7771 if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) { |
|
7772 return; |
|
7773 } |
|
7774 |
|
7775 inst = this._getInst(target[0]); |
|
7776 inst.selectedDay = inst.currentDay = $("a", td).html(); |
|
7777 inst.selectedMonth = inst.currentMonth = month; |
|
7778 inst.selectedYear = inst.currentYear = year; |
|
7779 this._selectDate(id, this._formatDate(inst, |
|
7780 inst.currentDay, inst.currentMonth, inst.currentYear)); |
|
7781 }, |
|
7782 |
|
7783 /* Erase the input field and hide the date picker. */ |
|
7784 _clearDate: function(id) { |
|
7785 var target = $(id); |
|
7786 this._selectDate(target, ""); |
|
7787 }, |
|
7788 |
|
7789 /* Update the input field with the selected date. */ |
|
7790 _selectDate: function(id, dateStr) { |
|
7791 var onSelect, |
|
7792 target = $(id), |
|
7793 inst = this._getInst(target[0]); |
|
7794 |
|
7795 dateStr = (dateStr != null ? dateStr : this._formatDate(inst)); |
|
7796 if (inst.input) { |
|
7797 inst.input.val(dateStr); |
|
7798 } |
|
7799 this._updateAlternate(inst); |
|
7800 |
|
7801 onSelect = this._get(inst, "onSelect"); |
|
7802 if (onSelect) { |
|
7803 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback |
|
7804 } else if (inst.input) { |
|
7805 inst.input.trigger("change"); // fire the change event |
|
7806 } |
|
7807 |
|
7808 if (inst.inline){ |
|
7809 this._updateDatepicker(inst); |
|
7810 } else { |
|
7811 this._hideDatepicker(); |
|
7812 this._lastInput = inst.input[0]; |
|
7813 if (typeof(inst.input[0]) !== "object") { |
|
7814 inst.input.focus(); // restore focus |
|
7815 } |
|
7816 this._lastInput = null; |
|
7817 } |
|
7818 }, |
|
7819 |
|
7820 /* Update any alternate field to synchronise with the main field. */ |
|
7821 _updateAlternate: function(inst) { |
|
7822 var altFormat, date, dateStr, |
|
7823 altField = this._get(inst, "altField"); |
|
7824 |
|
7825 if (altField) { // update alternate field too |
|
7826 altFormat = this._get(inst, "altFormat") || this._get(inst, "dateFormat"); |
|
7827 date = this._getDate(inst); |
|
7828 dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst)); |
|
7829 $(altField).each(function() { $(this).val(dateStr); }); |
|
7830 } |
|
7831 }, |
|
7832 |
|
7833 /* Set as beforeShowDay function to prevent selection of weekends. |
|
7834 * @param date Date - the date to customise |
|
7835 * @return [boolean, string] - is this date selectable?, what is its CSS class? |
|
7836 */ |
|
7837 noWeekends: function(date) { |
|
7838 var day = date.getDay(); |
|
7839 return [(day > 0 && day < 6), ""]; |
|
7840 }, |
|
7841 |
|
7842 /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition. |
|
7843 * @param date Date - the date to get the week for |
|
7844 * @return number - the number of the week within the year that contains this date |
|
7845 */ |
|
7846 iso8601Week: function(date) { |
|
7847 var time, |
|
7848 checkDate = new Date(date.getTime()); |
|
7849 |
|
7850 // Find Thursday of this week starting on Monday |
|
7851 checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); |
|
7852 |
|
7853 time = checkDate.getTime(); |
|
7854 checkDate.setMonth(0); // Compare with Jan 1 |
|
7855 checkDate.setDate(1); |
|
7856 return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1; |
|
7857 }, |
|
7858 |
|
7859 /* Parse a string value into a date object. |
|
7860 * See formatDate below for the possible formats. |
|
7861 * |
|
7862 * @param format string - the expected format of the date |
|
7863 * @param value string - the date in the above format |
|
7864 * @param settings Object - attributes include: |
|
7865 * shortYearCutoff number - the cutoff year for determining the century (optional) |
|
7866 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) |
|
7867 * dayNames string[7] - names of the days from Sunday (optional) |
|
7868 * monthNamesShort string[12] - abbreviated names of the months (optional) |
|
7869 * monthNames string[12] - names of the months (optional) |
|
7870 * @return Date - the extracted date value or null if value is blank |
|
7871 */ |
|
7872 parseDate: function (format, value, settings) { |
|
7873 if (format == null || value == null) { |
|
7874 throw "Invalid arguments"; |
|
7875 } |
|
7876 |
|
7877 value = (typeof value === "object" ? value.toString() : value + ""); |
|
7878 if (value === "") { |
|
7879 return null; |
|
7880 } |
|
7881 |
|
7882 var iFormat, dim, extra, |
|
7883 iValue = 0, |
|
7884 shortYearCutoffTemp = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff, |
|
7885 shortYearCutoff = (typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp : |
|
7886 new Date().getFullYear() % 100 + parseInt(shortYearCutoffTemp, 10)), |
|
7887 dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort, |
|
7888 dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames, |
|
7889 monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort, |
|
7890 monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames, |
|
7891 year = -1, |
|
7892 month = -1, |
|
7893 day = -1, |
|
7894 doy = -1, |
|
7895 literal = false, |
|
7896 date, |
|
7897 // Check whether a format character is doubled |
|
7898 lookAhead = function(match) { |
|
7899 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match); |
|
7900 if (matches) { |
|
7901 iFormat++; |
|
7902 } |
|
7903 return matches; |
|
7904 }, |
|
7905 // Extract a number from the string value |
|
7906 getNumber = function(match) { |
|
7907 var isDoubled = lookAhead(match), |
|
7908 size = (match === "@" ? 14 : (match === "!" ? 20 : |
|
7909 (match === "y" && isDoubled ? 4 : (match === "o" ? 3 : 2)))), |
|
7910 digits = new RegExp("^\\d{1," + size + "}"), |
|
7911 num = value.substring(iValue).match(digits); |
|
7912 if (!num) { |
|
7913 throw "Missing number at position " + iValue; |
|
7914 } |
|
7915 iValue += num[0].length; |
|
7916 return parseInt(num[0], 10); |
|
7917 }, |
|
7918 // Extract a name from the string value and convert to an index |
|
7919 getName = function(match, shortNames, longNames) { |
|
7920 var index = -1, |
|
7921 names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) { |
|
7922 return [ [k, v] ]; |
|
7923 }).sort(function (a, b) { |
|
7924 return -(a[1].length - b[1].length); |
|
7925 }); |
|
7926 |
|
7927 $.each(names, function (i, pair) { |
|
7928 var name = pair[1]; |
|
7929 if (value.substr(iValue, name.length).toLowerCase() === name.toLowerCase()) { |
|
7930 index = pair[0]; |
|
7931 iValue += name.length; |
|
7932 return false; |
|
7933 } |
|
7934 }); |
|
7935 if (index !== -1) { |
|
7936 return index + 1; |
|
7937 } else { |
|
7938 throw "Unknown name at position " + iValue; |
|
7939 } |
|
7940 }, |
|
7941 // Confirm that a literal character matches the string value |
|
7942 checkLiteral = function() { |
|
7943 if (value.charAt(iValue) !== format.charAt(iFormat)) { |
|
7944 throw "Unexpected literal at position " + iValue; |
|
7945 } |
|
7946 iValue++; |
|
7947 }; |
|
7948 |
|
7949 for (iFormat = 0; iFormat < format.length; iFormat++) { |
|
7950 if (literal) { |
|
7951 if (format.charAt(iFormat) === "'" && !lookAhead("'")) { |
|
7952 literal = false; |
|
7953 } else { |
|
7954 checkLiteral(); |
|
7955 } |
|
7956 } else { |
|
7957 switch (format.charAt(iFormat)) { |
|
7958 case "d": |
|
7959 day = getNumber("d"); |
|
7960 break; |
|
7961 case "D": |
|
7962 getName("D", dayNamesShort, dayNames); |
|
7963 break; |
|
7964 case "o": |
|
7965 doy = getNumber("o"); |
|
7966 break; |
|
7967 case "m": |
|
7968 month = getNumber("m"); |
|
7969 break; |
|
7970 case "M": |
|
7971 month = getName("M", monthNamesShort, monthNames); |
|
7972 break; |
|
7973 case "y": |
|
7974 year = getNumber("y"); |
|
7975 break; |
|
7976 case "@": |
|
7977 date = new Date(getNumber("@")); |
|
7978 year = date.getFullYear(); |
|
7979 month = date.getMonth() + 1; |
|
7980 day = date.getDate(); |
|
7981 break; |
|
7982 case "!": |
|
7983 date = new Date((getNumber("!") - this._ticksTo1970) / 10000); |
|
7984 year = date.getFullYear(); |
|
7985 month = date.getMonth() + 1; |
|
7986 day = date.getDate(); |
|
7987 break; |
|
7988 case "'": |
|
7989 if (lookAhead("'")){ |
|
7990 checkLiteral(); |
|
7991 } else { |
|
7992 literal = true; |
|
7993 } |
|
7994 break; |
|
7995 default: |
|
7996 checkLiteral(); |
|
7997 } |
|
7998 } |
|
7999 } |
|
8000 |
|
8001 if (iValue < value.length){ |
|
8002 extra = value.substr(iValue); |
|
8003 if (!/^\s+/.test(extra)) { |
|
8004 throw "Extra/unparsed characters found in date: " + extra; |
|
8005 } |
|
8006 } |
|
8007 |
|
8008 if (year === -1) { |
|
8009 year = new Date().getFullYear(); |
|
8010 } else if (year < 100) { |
|
8011 year += new Date().getFullYear() - new Date().getFullYear() % 100 + |
|
8012 (year <= shortYearCutoff ? 0 : -100); |
|
8013 } |
|
8014 |
|
8015 if (doy > -1) { |
|
8016 month = 1; |
|
8017 day = doy; |
|
8018 do { |
|
8019 dim = this._getDaysInMonth(year, month - 1); |
|
8020 if (day <= dim) { |
|
8021 break; |
|
8022 } |
|
8023 month++; |
|
8024 day -= dim; |
|
8025 } while (true); |
|
8026 } |
|
8027 |
|
8028 date = this._daylightSavingAdjust(new Date(year, month - 1, day)); |
|
8029 if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) { |
|
8030 throw "Invalid date"; // E.g. 31/02/00 |
|
8031 } |
|
8032 return date; |
|
8033 }, |
|
8034 |
|
8035 /* Standard date formats. */ |
|
8036 ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601) |
|
8037 COOKIE: "D, dd M yy", |
|
8038 ISO_8601: "yy-mm-dd", |
|
8039 RFC_822: "D, d M y", |
|
8040 RFC_850: "DD, dd-M-y", |
|
8041 RFC_1036: "D, d M y", |
|
8042 RFC_1123: "D, d M yy", |
|
8043 RFC_2822: "D, d M yy", |
|
8044 RSS: "D, d M y", // RFC 822 |
|
8045 TICKS: "!", |
|
8046 TIMESTAMP: "@", |
|
8047 W3C: "yy-mm-dd", // ISO 8601 |
|
8048 |
|
8049 _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) + |
|
8050 Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000), |
|
8051 |
|
8052 /* Format a date object into a string value. |
|
8053 * The format can be combinations of the following: |
|
8054 * d - day of month (no leading zero) |
|
8055 * dd - day of month (two digit) |
|
8056 * o - day of year (no leading zeros) |
|
8057 * oo - day of year (three digit) |
|
8058 * D - day name short |
|
8059 * DD - day name long |
|
8060 * m - month of year (no leading zero) |
|
8061 * mm - month of year (two digit) |
|
8062 * M - month name short |
|
8063 * MM - month name long |
|
8064 * y - year (two digit) |
|
8065 * yy - year (four digit) |
|
8066 * @ - Unix timestamp (ms since 01/01/1970) |
|
8067 * ! - Windows ticks (100ns since 01/01/0001) |
|
8068 * "..." - literal text |
|
8069 * '' - single quote |
|
8070 * |
|
8071 * @param format string - the desired format of the date |
|
8072 * @param date Date - the date value to format |
|
8073 * @param settings Object - attributes include: |
|
8074 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) |
|
8075 * dayNames string[7] - names of the days from Sunday (optional) |
|
8076 * monthNamesShort string[12] - abbreviated names of the months (optional) |
|
8077 * monthNames string[12] - names of the months (optional) |
|
8078 * @return string - the date in the above format |
|
8079 */ |
|
8080 formatDate: function (format, date, settings) { |
|
8081 if (!date) { |
|
8082 return ""; |
|
8083 } |
|
8084 |
|
8085 var iFormat, |
|
8086 dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort, |
|
8087 dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames, |
|
8088 monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort, |
|
8089 monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames, |
|
8090 // Check whether a format character is doubled |
|
8091 lookAhead = function(match) { |
|
8092 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match); |
|
8093 if (matches) { |
|
8094 iFormat++; |
|
8095 } |
|
8096 return matches; |
|
8097 }, |
|
8098 // Format a number, with leading zero if necessary |
|
8099 formatNumber = function(match, value, len) { |
|
8100 var num = "" + value; |
|
8101 if (lookAhead(match)) { |
|
8102 while (num.length < len) { |
|
8103 num = "0" + num; |
|
8104 } |
|
8105 } |
|
8106 return num; |
|
8107 }, |
|
8108 // Format a name, short or long as requested |
|
8109 formatName = function(match, value, shortNames, longNames) { |
|
8110 return (lookAhead(match) ? longNames[value] : shortNames[value]); |
|
8111 }, |
|
8112 output = "", |
|
8113 literal = false; |
|
8114 |
|
8115 if (date) { |
|
8116 for (iFormat = 0; iFormat < format.length; iFormat++) { |
|
8117 if (literal) { |
|
8118 if (format.charAt(iFormat) === "'" && !lookAhead("'")) { |
|
8119 literal = false; |
|
8120 } else { |
|
8121 output += format.charAt(iFormat); |
|
8122 } |
|
8123 } else { |
|
8124 switch (format.charAt(iFormat)) { |
|
8125 case "d": |
|
8126 output += formatNumber("d", date.getDate(), 2); |
|
8127 break; |
|
8128 case "D": |
|
8129 output += formatName("D", date.getDay(), dayNamesShort, dayNames); |
|
8130 break; |
|
8131 case "o": |
|
8132 output += formatNumber("o", |
|
8133 Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3); |
|
8134 break; |
|
8135 case "m": |
|
8136 output += formatNumber("m", date.getMonth() + 1, 2); |
|
8137 break; |
|
8138 case "M": |
|
8139 output += formatName("M", date.getMonth(), monthNamesShort, monthNames); |
|
8140 break; |
|
8141 case "y": |
|
8142 output += (lookAhead("y") ? date.getFullYear() : |
|
8143 (date.getYear() % 100 < 10 ? "0" : "") + date.getYear() % 100); |
|
8144 break; |
|
8145 case "@": |
|
8146 output += date.getTime(); |
|
8147 break; |
|
8148 case "!": |
|
8149 output += date.getTime() * 10000 + this._ticksTo1970; |
|
8150 break; |
|
8151 case "'": |
|
8152 if (lookAhead("'")) { |
|
8153 output += "'"; |
|
8154 } else { |
|
8155 literal = true; |
|
8156 } |
|
8157 break; |
|
8158 default: |
|
8159 output += format.charAt(iFormat); |
|
8160 } |
|
8161 } |
|
8162 } |
|
8163 } |
|
8164 return output; |
|
8165 }, |
|
8166 |
|
8167 /* Extract all possible characters from the date format. */ |
|
8168 _possibleChars: function (format) { |
|
8169 var iFormat, |
|
8170 chars = "", |
|
8171 literal = false, |
|
8172 // Check whether a format character is doubled |
|
8173 lookAhead = function(match) { |
|
8174 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match); |
|
8175 if (matches) { |
|
8176 iFormat++; |
|
8177 } |
|
8178 return matches; |
|
8179 }; |
|
8180 |
|
8181 for (iFormat = 0; iFormat < format.length; iFormat++) { |
|
8182 if (literal) { |
|
8183 if (format.charAt(iFormat) === "'" && !lookAhead("'")) { |
|
8184 literal = false; |
|
8185 } else { |
|
8186 chars += format.charAt(iFormat); |
|
8187 } |
|
8188 } else { |
|
8189 switch (format.charAt(iFormat)) { |
|
8190 case "d": case "m": case "y": case "@": |
|
8191 chars += "0123456789"; |
|
8192 break; |
|
8193 case "D": case "M": |
|
8194 return null; // Accept anything |
|
8195 case "'": |
|
8196 if (lookAhead("'")) { |
|
8197 chars += "'"; |
|
8198 } else { |
|
8199 literal = true; |
|
8200 } |
|
8201 break; |
|
8202 default: |
|
8203 chars += format.charAt(iFormat); |
|
8204 } |
|
8205 } |
|
8206 } |
|
8207 return chars; |
|
8208 }, |
|
8209 |
|
8210 /* Get a setting value, defaulting if necessary. */ |
|
8211 _get: function(inst, name) { |
|
8212 return inst.settings[name] !== undefined ? |
|
8213 inst.settings[name] : this._defaults[name]; |
|
8214 }, |
|
8215 |
|
8216 /* Parse existing date and initialise date picker. */ |
|
8217 _setDateFromField: function(inst, noDefault) { |
|
8218 if (inst.input.val() === inst.lastVal) { |
|
8219 return; |
|
8220 } |
|
8221 |
|
8222 var dateFormat = this._get(inst, "dateFormat"), |
|
8223 dates = inst.lastVal = inst.input ? inst.input.val() : null, |
|
8224 defaultDate = this._getDefaultDate(inst), |
|
8225 date = defaultDate, |
|
8226 settings = this._getFormatConfig(inst); |
|
8227 |
|
8228 try { |
|
8229 date = this.parseDate(dateFormat, dates, settings) || defaultDate; |
|
8230 } catch (event) { |
|
8231 dates = (noDefault ? "" : dates); |
|
8232 } |
|
8233 inst.selectedDay = date.getDate(); |
|
8234 inst.drawMonth = inst.selectedMonth = date.getMonth(); |
|
8235 inst.drawYear = inst.selectedYear = date.getFullYear(); |
|
8236 inst.currentDay = (dates ? date.getDate() : 0); |
|
8237 inst.currentMonth = (dates ? date.getMonth() : 0); |
|
8238 inst.currentYear = (dates ? date.getFullYear() : 0); |
|
8239 this._adjustInstDate(inst); |
|
8240 }, |
|
8241 |
|
8242 /* Retrieve the default date shown on opening. */ |
|
8243 _getDefaultDate: function(inst) { |
|
8244 return this._restrictMinMax(inst, |
|
8245 this._determineDate(inst, this._get(inst, "defaultDate"), new Date())); |
|
8246 }, |
|
8247 |
|
8248 /* A date may be specified as an exact value or a relative one. */ |
|
8249 _determineDate: function(inst, date, defaultDate) { |
|
8250 var offsetNumeric = function(offset) { |
|
8251 var date = new Date(); |
|
8252 date.setDate(date.getDate() + offset); |
|
8253 return date; |
|
8254 }, |
|
8255 offsetString = function(offset) { |
|
8256 try { |
|
8257 return $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"), |
|
8258 offset, $.datepicker._getFormatConfig(inst)); |
|
8259 } |
|
8260 catch (e) { |
|
8261 // Ignore |
|
8262 } |
|
8263 |
|
8264 var date = (offset.toLowerCase().match(/^c/) ? |
|
8265 $.datepicker._getDate(inst) : null) || new Date(), |
|
8266 year = date.getFullYear(), |
|
8267 month = date.getMonth(), |
|
8268 day = date.getDate(), |
|
8269 pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g, |
|
8270 matches = pattern.exec(offset); |
|
8271 |
|
8272 while (matches) { |
|
8273 switch (matches[2] || "d") { |
|
8274 case "d" : case "D" : |
|
8275 day += parseInt(matches[1],10); break; |
|
8276 case "w" : case "W" : |
|
8277 day += parseInt(matches[1],10) * 7; break; |
|
8278 case "m" : case "M" : |
|
8279 month += parseInt(matches[1],10); |
|
8280 day = Math.min(day, $.datepicker._getDaysInMonth(year, month)); |
|
8281 break; |
|
8282 case "y": case "Y" : |
|
8283 year += parseInt(matches[1],10); |
|
8284 day = Math.min(day, $.datepicker._getDaysInMonth(year, month)); |
|
8285 break; |
|
8286 } |
|
8287 matches = pattern.exec(offset); |
|
8288 } |
|
8289 return new Date(year, month, day); |
|
8290 }, |
|
8291 newDate = (date == null || date === "" ? defaultDate : (typeof date === "string" ? offsetString(date) : |
|
8292 (typeof date === "number" ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime())))); |
|
8293 |
|
8294 newDate = (newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate); |
|
8295 if (newDate) { |
|
8296 newDate.setHours(0); |
|
8297 newDate.setMinutes(0); |
|
8298 newDate.setSeconds(0); |
|
8299 newDate.setMilliseconds(0); |
|
8300 } |
|
8301 return this._daylightSavingAdjust(newDate); |
|
8302 }, |
|
8303 |
|
8304 /* Handle switch to/from daylight saving. |
|
8305 * Hours may be non-zero on daylight saving cut-over: |
|
8306 * > 12 when midnight changeover, but then cannot generate |
|
8307 * midnight datetime, so jump to 1AM, otherwise reset. |
|
8308 * @param date (Date) the date to check |
|
8309 * @return (Date) the corrected date |
|
8310 */ |
|
8311 _daylightSavingAdjust: function(date) { |
|
8312 if (!date) { |
|
8313 return null; |
|
8314 } |
|
8315 date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0); |
|
8316 return date; |
|
8317 }, |
|
8318 |
|
8319 /* Set the date(s) directly. */ |
|
8320 _setDate: function(inst, date, noChange) { |
|
8321 var clear = !date, |
|
8322 origMonth = inst.selectedMonth, |
|
8323 origYear = inst.selectedYear, |
|
8324 newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date())); |
|
8325 |
|
8326 inst.selectedDay = inst.currentDay = newDate.getDate(); |
|
8327 inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth(); |
|
8328 inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear(); |
|
8329 if ((origMonth !== inst.selectedMonth || origYear !== inst.selectedYear) && !noChange) { |
|
8330 this._notifyChange(inst); |
|
8331 } |
|
8332 this._adjustInstDate(inst); |
|
8333 if (inst.input) { |
|
8334 inst.input.val(clear ? "" : this._formatDate(inst)); |
|
8335 } |
|
8336 }, |
|
8337 |
|
8338 /* Retrieve the date(s) directly. */ |
|
8339 _getDate: function(inst) { |
|
8340 var startDate = (!inst.currentYear || (inst.input && inst.input.val() === "") ? null : |
|
8341 this._daylightSavingAdjust(new Date( |
|
8342 inst.currentYear, inst.currentMonth, inst.currentDay))); |
|
8343 return startDate; |
|
8344 }, |
|
8345 |
|
8346 /* Attach the onxxx handlers. These are declared statically so |
|
8347 * they work with static code transformers like Caja. |
|
8348 */ |
|
8349 _attachHandlers: function(inst) { |
|
8350 var stepMonths = this._get(inst, "stepMonths"), |
|
8351 id = "#" + inst.id.replace( /\\\\/g, "\\" ); |
|
8352 inst.dpDiv.find("[data-handler]").map(function () { |
|
8353 var handler = { |
|
8354 prev: function () { |
|
8355 $.datepicker._adjustDate(id, -stepMonths, "M"); |
|
8356 }, |
|
8357 next: function () { |
|
8358 $.datepicker._adjustDate(id, +stepMonths, "M"); |
|
8359 }, |
|
8360 hide: function () { |
|
8361 $.datepicker._hideDatepicker(); |
|
8362 }, |
|
8363 today: function () { |
|
8364 $.datepicker._gotoToday(id); |
|
8365 }, |
|
8366 selectDay: function () { |
|
8367 $.datepicker._selectDay(id, +this.getAttribute("data-month"), +this.getAttribute("data-year"), this); |
|
8368 return false; |
|
8369 }, |
|
8370 selectMonth: function () { |
|
8371 $.datepicker._selectMonthYear(id, this, "M"); |
|
8372 return false; |
|
8373 }, |
|
8374 selectYear: function () { |
|
8375 $.datepicker._selectMonthYear(id, this, "Y"); |
|
8376 return false; |
|
8377 } |
|
8378 }; |
|
8379 $(this).bind(this.getAttribute("data-event"), handler[this.getAttribute("data-handler")]); |
|
8380 }); |
|
8381 }, |
|
8382 |
|
8383 /* Generate the HTML for the current state of the date picker. */ |
|
8384 _generateHTML: function(inst) { |
|
8385 var maxDraw, prevText, prev, nextText, next, currentText, gotoDate, |
|
8386 controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin, |
|
8387 monthNames, monthNamesShort, beforeShowDay, showOtherMonths, |
|
8388 selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate, |
|
8389 cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows, |
|
8390 printDate, dRow, tbody, daySettings, otherMonth, unselectable, |
|
8391 tempDate = new Date(), |
|
8392 today = this._daylightSavingAdjust( |
|
8393 new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate())), // clear time |
|
8394 isRTL = this._get(inst, "isRTL"), |
|
8395 showButtonPanel = this._get(inst, "showButtonPanel"), |
|
8396 hideIfNoPrevNext = this._get(inst, "hideIfNoPrevNext"), |
|
8397 navigationAsDateFormat = this._get(inst, "navigationAsDateFormat"), |
|
8398 numMonths = this._getNumberOfMonths(inst), |
|
8399 showCurrentAtPos = this._get(inst, "showCurrentAtPos"), |
|
8400 stepMonths = this._get(inst, "stepMonths"), |
|
8401 isMultiMonth = (numMonths[0] !== 1 || numMonths[1] !== 1), |
|
8402 currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) : |
|
8403 new Date(inst.currentYear, inst.currentMonth, inst.currentDay))), |
|
8404 minDate = this._getMinMaxDate(inst, "min"), |
|
8405 maxDate = this._getMinMaxDate(inst, "max"), |
|
8406 drawMonth = inst.drawMonth - showCurrentAtPos, |
|
8407 drawYear = inst.drawYear; |
|
8408 |
|
8409 if (drawMonth < 0) { |
|
8410 drawMonth += 12; |
|
8411 drawYear--; |
|
8412 } |
|
8413 if (maxDate) { |
|
8414 maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(), |
|
8415 maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate())); |
|
8416 maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw); |
|
8417 while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) { |
|
8418 drawMonth--; |
|
8419 if (drawMonth < 0) { |
|
8420 drawMonth = 11; |
|
8421 drawYear--; |
|
8422 } |
|
8423 } |
|
8424 } |
|
8425 inst.drawMonth = drawMonth; |
|
8426 inst.drawYear = drawYear; |
|
8427 |
|
8428 prevText = this._get(inst, "prevText"); |
|
8429 prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText, |
|
8430 this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)), |
|
8431 this._getFormatConfig(inst))); |
|
8432 |
|
8433 prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ? |
|
8434 "<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'" + |
|
8435 " title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>" : |
|
8436 (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>")); |
|
8437 |
|
8438 nextText = this._get(inst, "nextText"); |
|
8439 nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText, |
|
8440 this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)), |
|
8441 this._getFormatConfig(inst))); |
|
8442 |
|
8443 next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ? |
|
8444 "<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'" + |
|
8445 " title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>" : |
|
8446 (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>")); |
|
8447 |
|
8448 currentText = this._get(inst, "currentText"); |
|
8449 gotoDate = (this._get(inst, "gotoCurrent") && inst.currentDay ? currentDate : today); |
|
8450 currentText = (!navigationAsDateFormat ? currentText : |
|
8451 this.formatDate(currentText, gotoDate, this._getFormatConfig(inst))); |
|
8452 |
|
8453 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'>" + |
|
8454 this._get(inst, "closeText") + "</button>" : ""); |
|
8455 |
|
8456 buttonPanel = (showButtonPanel) ? "<div class='ui-datepicker-buttonpane ui-widget-content'>" + (isRTL ? controls : "") + |
|
8457 (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'" + |
|
8458 ">" + currentText + "</button>" : "") + (isRTL ? "" : controls) + "</div>" : ""; |
|
8459 |
|
8460 firstDay = parseInt(this._get(inst, "firstDay"),10); |
|
8461 firstDay = (isNaN(firstDay) ? 0 : firstDay); |
|
8462 |
|
8463 showWeek = this._get(inst, "showWeek"); |
|
8464 dayNames = this._get(inst, "dayNames"); |
|
8465 dayNamesMin = this._get(inst, "dayNamesMin"); |
|
8466 monthNames = this._get(inst, "monthNames"); |
|
8467 monthNamesShort = this._get(inst, "monthNamesShort"); |
|
8468 beforeShowDay = this._get(inst, "beforeShowDay"); |
|
8469 showOtherMonths = this._get(inst, "showOtherMonths"); |
|
8470 selectOtherMonths = this._get(inst, "selectOtherMonths"); |
|
8471 defaultDate = this._getDefaultDate(inst); |
|
8472 html = ""; |
|
8473 dow; |
|
8474 for (row = 0; row < numMonths[0]; row++) { |
|
8475 group = ""; |
|
8476 this.maxRows = 4; |
|
8477 for (col = 0; col < numMonths[1]; col++) { |
|
8478 selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay)); |
|
8479 cornerClass = " ui-corner-all"; |
|
8480 calender = ""; |
|
8481 if (isMultiMonth) { |
|
8482 calender += "<div class='ui-datepicker-group"; |
|
8483 if (numMonths[1] > 1) { |
|
8484 switch (col) { |
|
8485 case 0: calender += " ui-datepicker-group-first"; |
|
8486 cornerClass = " ui-corner-" + (isRTL ? "right" : "left"); break; |
|
8487 case numMonths[1]-1: calender += " ui-datepicker-group-last"; |
|
8488 cornerClass = " ui-corner-" + (isRTL ? "left" : "right"); break; |
|
8489 default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break; |
|
8490 } |
|
8491 } |
|
8492 calender += "'>"; |
|
8493 } |
|
8494 calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" + |
|
8495 (/all|left/.test(cornerClass) && row === 0 ? (isRTL ? next : prev) : "") + |
|
8496 (/all|right/.test(cornerClass) && row === 0 ? (isRTL ? prev : next) : "") + |
|
8497 this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate, |
|
8498 row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers |
|
8499 "</div><table class='ui-datepicker-calendar'><thead>" + |
|
8500 "<tr>"; |
|
8501 thead = (showWeek ? "<th class='ui-datepicker-week-col'>" + this._get(inst, "weekHeader") + "</th>" : ""); |
|
8502 for (dow = 0; dow < 7; dow++) { // days of the week |
|
8503 day = (dow + firstDay) % 7; |
|
8504 thead += "<th" + ((dow + firstDay + 6) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "") + ">" + |
|
8505 "<span title='" + dayNames[day] + "'>" + dayNamesMin[day] + "</span></th>"; |
|
8506 } |
|
8507 calender += thead + "</tr></thead><tbody>"; |
|
8508 daysInMonth = this._getDaysInMonth(drawYear, drawMonth); |
|
8509 if (drawYear === inst.selectedYear && drawMonth === inst.selectedMonth) { |
|
8510 inst.selectedDay = Math.min(inst.selectedDay, daysInMonth); |
|
8511 } |
|
8512 leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7; |
|
8513 curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate |
|
8514 numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043) |
|
8515 this.maxRows = numRows; |
|
8516 printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays)); |
|
8517 for (dRow = 0; dRow < numRows; dRow++) { // create date picker rows |
|
8518 calender += "<tr>"; |
|
8519 tbody = (!showWeek ? "" : "<td class='ui-datepicker-week-col'>" + |
|
8520 this._get(inst, "calculateWeek")(printDate) + "</td>"); |
|
8521 for (dow = 0; dow < 7; dow++) { // create date picker days |
|
8522 daySettings = (beforeShowDay ? |
|
8523 beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, ""]); |
|
8524 otherMonth = (printDate.getMonth() !== drawMonth); |
|
8525 unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] || |
|
8526 (minDate && printDate < minDate) || (maxDate && printDate > maxDate); |
|
8527 tbody += "<td class='" + |
|
8528 ((dow + firstDay + 6) % 7 >= 5 ? " ui-datepicker-week-end" : "") + // highlight weekends |
|
8529 (otherMonth ? " ui-datepicker-other-month" : "") + // highlight days from other months |
|
8530 ((printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent) || // user pressed key |
|
8531 (defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime()) ? |
|
8532 // or defaultDate is current printedDate and defaultDate is selectedDate |
|
8533 " " + this._dayOverClass : "") + // highlight selected day |
|
8534 (unselectable ? " " + this._unselectableClass + " ui-state-disabled": "") + // highlight unselectable days |
|
8535 (otherMonth && !showOtherMonths ? "" : " " + daySettings[1] + // highlight custom dates |
|
8536 (printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "") + // highlight selected day |
|
8537 (printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "")) + "'" + // highlight today (if different) |
|
8538 ((!otherMonth || showOtherMonths) && daySettings[2] ? " title='" + daySettings[2].replace(/'/g, "'") + "'" : "") + // cell title |
|
8539 (unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'") + ">" + // actions |
|
8540 (otherMonth && !showOtherMonths ? " " : // display for other months |
|
8541 (unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" + |
|
8542 (printDate.getTime() === today.getTime() ? " ui-state-highlight" : "") + |
|
8543 (printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "") + // highlight selected day |
|
8544 (otherMonth ? " ui-priority-secondary" : "") + // distinguish dates from other months |
|
8545 "' href='#'>" + printDate.getDate() + "</a>")) + "</td>"; // display selectable date |
|
8546 printDate.setDate(printDate.getDate() + 1); |
|
8547 printDate = this._daylightSavingAdjust(printDate); |
|
8548 } |
|
8549 calender += tbody + "</tr>"; |
|
8550 } |
|
8551 drawMonth++; |
|
8552 if (drawMonth > 11) { |
|
8553 drawMonth = 0; |
|
8554 drawYear++; |
|
8555 } |
|
8556 calender += "</tbody></table>" + (isMultiMonth ? "</div>" + |
|
8557 ((numMonths[0] > 0 && col === numMonths[1]-1) ? "<div class='ui-datepicker-row-break'></div>" : "") : ""); |
|
8558 group += calender; |
|
8559 } |
|
8560 html += group; |
|
8561 } |
|
8562 html += buttonPanel; |
|
8563 inst._keyEvent = false; |
|
8564 return html; |
|
8565 }, |
|
8566 |
|
8567 /* Generate the month and year header. */ |
|
8568 _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate, |
|
8569 secondary, monthNames, monthNamesShort) { |
|
8570 |
|
8571 var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear, |
|
8572 changeMonth = this._get(inst, "changeMonth"), |
|
8573 changeYear = this._get(inst, "changeYear"), |
|
8574 showMonthAfterYear = this._get(inst, "showMonthAfterYear"), |
|
8575 html = "<div class='ui-datepicker-title'>", |
|
8576 monthHtml = ""; |
|
8577 |
|
8578 // month selection |
|
8579 if (secondary || !changeMonth) { |
|
8580 monthHtml += "<span class='ui-datepicker-month'>" + monthNames[drawMonth] + "</span>"; |
|
8581 } else { |
|
8582 inMinYear = (minDate && minDate.getFullYear() === drawYear); |
|
8583 inMaxYear = (maxDate && maxDate.getFullYear() === drawYear); |
|
8584 monthHtml += "<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>"; |
|
8585 for ( month = 0; month < 12; month++) { |
|
8586 if ((!inMinYear || month >= minDate.getMonth()) && (!inMaxYear || month <= maxDate.getMonth())) { |
|
8587 monthHtml += "<option value='" + month + "'" + |
|
8588 (month === drawMonth ? " selected='selected'" : "") + |
|
8589 ">" + monthNamesShort[month] + "</option>"; |
|
8590 } |
|
8591 } |
|
8592 monthHtml += "</select>"; |
|
8593 } |
|
8594 |
|
8595 if (!showMonthAfterYear) { |
|
8596 html += monthHtml + (secondary || !(changeMonth && changeYear) ? " " : ""); |
|
8597 } |
|
8598 |
|
8599 // year selection |
|
8600 if ( !inst.yearshtml ) { |
|
8601 inst.yearshtml = ""; |
|
8602 if (secondary || !changeYear) { |
|
8603 html += "<span class='ui-datepicker-year'>" + drawYear + "</span>"; |
|
8604 } else { |
|
8605 // determine range of years to display |
|
8606 years = this._get(inst, "yearRange").split(":"); |
|
8607 thisYear = new Date().getFullYear(); |
|
8608 determineYear = function(value) { |
|
8609 var year = (value.match(/c[+\-].*/) ? drawYear + parseInt(value.substring(1), 10) : |
|
8610 (value.match(/[+\-].*/) ? thisYear + parseInt(value, 10) : |
|
8611 parseInt(value, 10))); |
|
8612 return (isNaN(year) ? thisYear : year); |
|
8613 }; |
|
8614 year = determineYear(years[0]); |
|
8615 endYear = Math.max(year, determineYear(years[1] || "")); |
|
8616 year = (minDate ? Math.max(year, minDate.getFullYear()) : year); |
|
8617 endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear); |
|
8618 inst.yearshtml += "<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>"; |
|
8619 for (; year <= endYear; year++) { |
|
8620 inst.yearshtml += "<option value='" + year + "'" + |
|
8621 (year === drawYear ? " selected='selected'" : "") + |
|
8622 ">" + year + "</option>"; |
|
8623 } |
|
8624 inst.yearshtml += "</select>"; |
|
8625 |
|
8626 html += inst.yearshtml; |
|
8627 inst.yearshtml = null; |
|
8628 } |
|
8629 } |
|
8630 |
|
8631 html += this._get(inst, "yearSuffix"); |
|
8632 if (showMonthAfterYear) { |
|
8633 html += (secondary || !(changeMonth && changeYear) ? " " : "") + monthHtml; |
|
8634 } |
|
8635 html += "</div>"; // Close datepicker_header |
|
8636 return html; |
|
8637 }, |
|
8638 |
|
8639 /* Adjust one of the date sub-fields. */ |
|
8640 _adjustInstDate: function(inst, offset, period) { |
|
8641 var year = inst.drawYear + (period === "Y" ? offset : 0), |
|
8642 month = inst.drawMonth + (period === "M" ? offset : 0), |
|
8643 day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + (period === "D" ? offset : 0), |
|
8644 date = this._restrictMinMax(inst, this._daylightSavingAdjust(new Date(year, month, day))); |
|
8645 |
|
8646 inst.selectedDay = date.getDate(); |
|
8647 inst.drawMonth = inst.selectedMonth = date.getMonth(); |
|
8648 inst.drawYear = inst.selectedYear = date.getFullYear(); |
|
8649 if (period === "M" || period === "Y") { |
|
8650 this._notifyChange(inst); |
|
8651 } |
|
8652 }, |
|
8653 |
|
8654 /* Ensure a date is within any min/max bounds. */ |
|
8655 _restrictMinMax: function(inst, date) { |
|
8656 var minDate = this._getMinMaxDate(inst, "min"), |
|
8657 maxDate = this._getMinMaxDate(inst, "max"), |
|
8658 newDate = (minDate && date < minDate ? minDate : date); |
|
8659 return (maxDate && newDate > maxDate ? maxDate : newDate); |
|
8660 }, |
|
8661 |
|
8662 /* Notify change of month/year. */ |
|
8663 _notifyChange: function(inst) { |
|
8664 var onChange = this._get(inst, "onChangeMonthYear"); |
|
8665 if (onChange) { |
|
8666 onChange.apply((inst.input ? inst.input[0] : null), |
|
8667 [inst.selectedYear, inst.selectedMonth + 1, inst]); |
|
8668 } |
|
8669 }, |
|
8670 |
|
8671 /* Determine the number of months to show. */ |
|
8672 _getNumberOfMonths: function(inst) { |
|
8673 var numMonths = this._get(inst, "numberOfMonths"); |
|
8674 return (numMonths == null ? [1, 1] : (typeof numMonths === "number" ? [1, numMonths] : numMonths)); |
|
8675 }, |
|
8676 |
|
8677 /* Determine the current maximum date - ensure no time components are set. */ |
|
8678 _getMinMaxDate: function(inst, minMax) { |
|
8679 return this._determineDate(inst, this._get(inst, minMax + "Date"), null); |
|
8680 }, |
|
8681 |
|
8682 /* Find the number of days in a given month. */ |
|
8683 _getDaysInMonth: function(year, month) { |
|
8684 return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate(); |
|
8685 }, |
|
8686 |
|
8687 /* Find the day of the week of the first of a month. */ |
|
8688 _getFirstDayOfMonth: function(year, month) { |
|
8689 return new Date(year, month, 1).getDay(); |
|
8690 }, |
|
8691 |
|
8692 /* Determines if we should allow a "next/prev" month display change. */ |
|
8693 _canAdjustMonth: function(inst, offset, curYear, curMonth) { |
|
8694 var numMonths = this._getNumberOfMonths(inst), |
|
8695 date = this._daylightSavingAdjust(new Date(curYear, |
|
8696 curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1)); |
|
8697 |
|
8698 if (offset < 0) { |
|
8699 date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth())); |
|
8700 } |
|
8701 return this._isInRange(inst, date); |
|
8702 }, |
|
8703 |
|
8704 /* Is the given date in the accepted range? */ |
|
8705 _isInRange: function(inst, date) { |
|
8706 var yearSplit, currentYear, |
|
8707 minDate = this._getMinMaxDate(inst, "min"), |
|
8708 maxDate = this._getMinMaxDate(inst, "max"), |
|
8709 minYear = null, |
|
8710 maxYear = null, |
|
8711 years = this._get(inst, "yearRange"); |
|
8712 if (years){ |
|
8713 yearSplit = years.split(":"); |
|
8714 currentYear = new Date().getFullYear(); |
|
8715 minYear = parseInt(yearSplit[0], 10); |
|
8716 maxYear = parseInt(yearSplit[1], 10); |
|
8717 if ( yearSplit[0].match(/[+\-].*/) ) { |
|
8718 minYear += currentYear; |
|
8719 } |
|
8720 if ( yearSplit[1].match(/[+\-].*/) ) { |
|
8721 maxYear += currentYear; |
|
8722 } |
|
8723 } |
|
8724 |
|
8725 return ((!minDate || date.getTime() >= minDate.getTime()) && |
|
8726 (!maxDate || date.getTime() <= maxDate.getTime()) && |
|
8727 (!minYear || date.getFullYear() >= minYear) && |
|
8728 (!maxYear || date.getFullYear() <= maxYear)); |
|
8729 }, |
|
8730 |
|
8731 /* Provide the configuration settings for formatting/parsing. */ |
|
8732 _getFormatConfig: function(inst) { |
|
8733 var shortYearCutoff = this._get(inst, "shortYearCutoff"); |
|
8734 shortYearCutoff = (typeof shortYearCutoff !== "string" ? shortYearCutoff : |
|
8735 new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10)); |
|
8736 return {shortYearCutoff: shortYearCutoff, |
|
8737 dayNamesShort: this._get(inst, "dayNamesShort"), dayNames: this._get(inst, "dayNames"), |
|
8738 monthNamesShort: this._get(inst, "monthNamesShort"), monthNames: this._get(inst, "monthNames")}; |
|
8739 }, |
|
8740 |
|
8741 /* Format the given date for display. */ |
|
8742 _formatDate: function(inst, day, month, year) { |
|
8743 if (!day) { |
|
8744 inst.currentDay = inst.selectedDay; |
|
8745 inst.currentMonth = inst.selectedMonth; |
|
8746 inst.currentYear = inst.selectedYear; |
|
8747 } |
|
8748 var date = (day ? (typeof day === "object" ? day : |
|
8749 this._daylightSavingAdjust(new Date(year, month, day))) : |
|
8750 this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay))); |
|
8751 return this.formatDate(this._get(inst, "dateFormat"), date, this._getFormatConfig(inst)); |
|
8752 } |
|
8753 }); |
|
8754 |
|
8755 /* |
|
8756 * Bind hover events for datepicker elements. |
|
8757 * Done via delegate so the binding only occurs once in the lifetime of the parent div. |
|
8758 * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker. |
|
8759 */ |
|
8760 function bindHover(dpDiv) { |
|
8761 var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a"; |
|
8762 return dpDiv.delegate(selector, "mouseout", function() { |
|
8763 $(this).removeClass("ui-state-hover"); |
|
8764 if (this.className.indexOf("ui-datepicker-prev") !== -1) { |
|
8765 $(this).removeClass("ui-datepicker-prev-hover"); |
|
8766 } |
|
8767 if (this.className.indexOf("ui-datepicker-next") !== -1) { |
|
8768 $(this).removeClass("ui-datepicker-next-hover"); |
|
8769 } |
|
8770 }) |
|
8771 .delegate(selector, "mouseover", function(){ |
|
8772 if (!$.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0])) { |
|
8773 $(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"); |
|
8774 $(this).addClass("ui-state-hover"); |
|
8775 if (this.className.indexOf("ui-datepicker-prev") !== -1) { |
|
8776 $(this).addClass("ui-datepicker-prev-hover"); |
|
8777 } |
|
8778 if (this.className.indexOf("ui-datepicker-next") !== -1) { |
|
8779 $(this).addClass("ui-datepicker-next-hover"); |
|
8780 } |
|
8781 } |
|
8782 }); |
|
8783 } |
|
8784 |
|
8785 /* jQuery extend now ignores nulls! */ |
|
8786 function extendRemove(target, props) { |
|
8787 $.extend(target, props); |
|
8788 for (var name in props) { |
|
8789 if (props[name] == null) { |
|
8790 target[name] = props[name]; |
|
8791 } |
|
8792 } |
|
8793 return target; |
|
8794 } |
|
8795 |
|
8796 /* Invoke the datepicker functionality. |
|
8797 @param options string - a command, optionally followed by additional parameters or |
|
8798 Object - settings for attaching new datepicker functionality |
|
8799 @return jQuery object */ |
|
8800 $.fn.datepicker = function(options){ |
|
8801 |
|
8802 /* Verify an empty collection wasn't passed - Fixes #6976 */ |
|
8803 if ( !this.length ) { |
|
8804 return this; |
|
8805 } |
|
8806 |
|
8807 /* Initialise the date picker. */ |
|
8808 if (!$.datepicker.initialized) { |
|
8809 $(document).mousedown($.datepicker._checkExternalClick); |
|
8810 $.datepicker.initialized = true; |
|
8811 } |
|
8812 |
|
8813 /* Append datepicker main container to body if not exist. */ |
|
8814 if ($("#"+$.datepicker._mainDivId).length === 0) { |
|
8815 $("body").append($.datepicker.dpDiv); |
|
8816 } |
|
8817 |
|
8818 var otherArgs = Array.prototype.slice.call(arguments, 1); |
|
8819 if (typeof options === "string" && (options === "isDisabled" || options === "getDate" || options === "widget")) { |
|
8820 return $.datepicker["_" + options + "Datepicker"]. |
|
8821 apply($.datepicker, [this[0]].concat(otherArgs)); |
|
8822 } |
|
8823 if (options === "option" && arguments.length === 2 && typeof arguments[1] === "string") { |
|
8824 return $.datepicker["_" + options + "Datepicker"]. |
|
8825 apply($.datepicker, [this[0]].concat(otherArgs)); |
|
8826 } |
|
8827 return this.each(function() { |
|
8828 typeof options === "string" ? |
|
8829 $.datepicker["_" + options + "Datepicker"]. |
|
8830 apply($.datepicker, [this].concat(otherArgs)) : |
|
8831 $.datepicker._attachDatepicker(this, options); |
|
8832 }); |
|
8833 }; |
|
8834 |
|
8835 $.datepicker = new Datepicker(); // singleton instance |
|
8836 $.datepicker.initialized = false; |
|
8837 $.datepicker.uuid = new Date().getTime(); |
|
8838 $.datepicker.version = "1.10.4"; |
|
8839 |
|
8840 })(jQuery); |
|
8841 (function( $, undefined ) { |
|
8842 |
|
8843 var sizeRelatedOptions = { |
|
8844 buttons: true, |
|
8845 height: true, |
|
8846 maxHeight: true, |
|
8847 maxWidth: true, |
|
8848 minHeight: true, |
|
8849 minWidth: true, |
|
8850 width: true |
|
8851 }, |
|
8852 resizableRelatedOptions = { |
|
8853 maxHeight: true, |
|
8854 maxWidth: true, |
|
8855 minHeight: true, |
|
8856 minWidth: true |
|
8857 }; |
|
8858 |
|
8859 $.widget( "ui.dialog", { |
|
8860 version: "1.10.4", |
|
8861 options: { |
|
8862 appendTo: "body", |
|
8863 autoOpen: true, |
|
8864 buttons: [], |
|
8865 closeOnEscape: true, |
|
8866 closeText: "close", |
|
8867 dialogClass: "", |
|
8868 draggable: true, |
|
8869 hide: null, |
|
8870 height: "auto", |
|
8871 maxHeight: null, |
|
8872 maxWidth: null, |
|
8873 minHeight: 150, |
|
8874 minWidth: 150, |
|
8875 modal: false, |
|
8876 position: { |
|
8877 my: "center", |
|
8878 at: "center", |
|
8879 of: window, |
|
8880 collision: "fit", |
|
8881 // Ensure the titlebar is always visible |
|
8882 using: function( pos ) { |
|
8883 var topOffset = $( this ).css( pos ).offset().top; |
|
8884 if ( topOffset < 0 ) { |
|
8885 $( this ).css( "top", pos.top - topOffset ); |
|
8886 } |
|
8887 } |
|
8888 }, |
|
8889 resizable: true, |
|
8890 show: null, |
|
8891 title: null, |
|
8892 width: 300, |
|
8893 |
|
8894 // callbacks |
|
8895 beforeClose: null, |
|
8896 close: null, |
|
8897 drag: null, |
|
8898 dragStart: null, |
|
8899 dragStop: null, |
|
8900 focus: null, |
|
8901 open: null, |
|
8902 resize: null, |
|
8903 resizeStart: null, |
|
8904 resizeStop: null |
|
8905 }, |
|
8906 |
|
8907 _create: function() { |
|
8908 this.originalCss = { |
|
8909 display: this.element[0].style.display, |
|
8910 width: this.element[0].style.width, |
|
8911 minHeight: this.element[0].style.minHeight, |
|
8912 maxHeight: this.element[0].style.maxHeight, |
|
8913 height: this.element[0].style.height |
|
8914 }; |
|
8915 this.originalPosition = { |
|
8916 parent: this.element.parent(), |
|
8917 index: this.element.parent().children().index( this.element ) |
|
8918 }; |
|
8919 this.originalTitle = this.element.attr("title"); |
|
8920 this.options.title = this.options.title || this.originalTitle; |
|
8921 |
|
8922 this._createWrapper(); |
|
8923 |
|
8924 this.element |
|
8925 .show() |
|
8926 .removeAttr("title") |
|
8927 .addClass("ui-dialog-content ui-widget-content") |
|
8928 .appendTo( this.uiDialog ); |
|
8929 |
|
8930 this._createTitlebar(); |
|
8931 this._createButtonPane(); |
|
8932 |
|
8933 if ( this.options.draggable && $.fn.draggable ) { |
|
8934 this._makeDraggable(); |
|
8935 } |
|
8936 if ( this.options.resizable && $.fn.resizable ) { |
|
8937 this._makeResizable(); |
|
8938 } |
|
8939 |
|
8940 this._isOpen = false; |
|
8941 }, |
|
8942 |
|
8943 _init: function() { |
|
8944 if ( this.options.autoOpen ) { |
|
8945 this.open(); |
|
8946 } |
|
8947 }, |
|
8948 |
|
8949 _appendTo: function() { |
|
8950 var element = this.options.appendTo; |
|
8951 if ( element && (element.jquery || element.nodeType) ) { |
|
8952 return $( element ); |
|
8953 } |
|
8954 return this.document.find( element || "body" ).eq( 0 ); |
|
8955 }, |
|
8956 |
|
8957 _destroy: function() { |
|
8958 var next, |
|
8959 originalPosition = this.originalPosition; |
|
8960 |
|
8961 this._destroyOverlay(); |
|
8962 |
|
8963 this.element |
|
8964 .removeUniqueId() |
|
8965 .removeClass("ui-dialog-content ui-widget-content") |
|
8966 .css( this.originalCss ) |
|
8967 // Without detaching first, the following becomes really slow |
|
8968 .detach(); |
|
8969 |
|
8970 this.uiDialog.stop( true, true ).remove(); |
|
8971 |
|
8972 if ( this.originalTitle ) { |
|
8973 this.element.attr( "title", this.originalTitle ); |
|
8974 } |
|
8975 |
|
8976 next = originalPosition.parent.children().eq( originalPosition.index ); |
|
8977 // Don't try to place the dialog next to itself (#8613) |
|
8978 if ( next.length && next[0] !== this.element[0] ) { |
|
8979 next.before( this.element ); |
|
8980 } else { |
|
8981 originalPosition.parent.append( this.element ); |
|
8982 } |
|
8983 }, |
|
8984 |
|
8985 widget: function() { |
|
8986 return this.uiDialog; |
|
8987 }, |
|
8988 |
|
8989 disable: $.noop, |
|
8990 enable: $.noop, |
|
8991 |
|
8992 close: function( event ) { |
|
8993 var activeElement, |
|
8994 that = this; |
|
8995 |
|
8996 if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) { |
|
8997 return; |
|
8998 } |
|
8999 |
|
9000 this._isOpen = false; |
|
9001 this._destroyOverlay(); |
|
9002 |
|
9003 if ( !this.opener.filter(":focusable").focus().length ) { |
|
9004 |
|
9005 // support: IE9 |
|
9006 // IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe> |
|
9007 try { |
|
9008 activeElement = this.document[ 0 ].activeElement; |
|
9009 |
|
9010 // Support: IE9, IE10 |
|
9011 // If the <body> is blurred, IE will switch windows, see #4520 |
|
9012 if ( activeElement && activeElement.nodeName.toLowerCase() !== "body" ) { |
|
9013 |
|
9014 // Hiding a focused element doesn't trigger blur in WebKit |
|
9015 // so in case we have nothing to focus on, explicitly blur the active element |
|
9016 // https://bugs.webkit.org/show_bug.cgi?id=47182 |
|
9017 $( activeElement ).blur(); |
|
9018 } |
|
9019 } catch ( error ) {} |
|
9020 } |
|
9021 |
|
9022 this._hide( this.uiDialog, this.options.hide, function() { |
|
9023 that._trigger( "close", event ); |
|
9024 }); |
|
9025 }, |
|
9026 |
|
9027 isOpen: function() { |
|
9028 return this._isOpen; |
|
9029 }, |
|
9030 |
|
9031 moveToTop: function() { |
|
9032 this._moveToTop(); |
|
9033 }, |
|
9034 |
|
9035 _moveToTop: function( event, silent ) { |
|
9036 var moved = !!this.uiDialog.nextAll(":visible").insertBefore( this.uiDialog ).length; |
|
9037 if ( moved && !silent ) { |
|
9038 this._trigger( "focus", event ); |
|
9039 } |
|
9040 return moved; |
|
9041 }, |
|
9042 |
|
9043 open: function() { |
|
9044 var that = this; |
|
9045 if ( this._isOpen ) { |
|
9046 if ( this._moveToTop() ) { |
|
9047 this._focusTabbable(); |
|
9048 } |
|
9049 return; |
|
9050 } |
|
9051 |
|
9052 this._isOpen = true; |
|
9053 this.opener = $( this.document[0].activeElement ); |
|
9054 |
|
9055 this._size(); |
|
9056 this._position(); |
|
9057 this._createOverlay(); |
|
9058 this._moveToTop( null, true ); |
|
9059 this._show( this.uiDialog, this.options.show, function() { |
|
9060 that._focusTabbable(); |
|
9061 that._trigger("focus"); |
|
9062 }); |
|
9063 |
|
9064 this._trigger("open"); |
|
9065 }, |
|
9066 |
|
9067 _focusTabbable: function() { |
|
9068 // Set focus to the first match: |
|
9069 // 1. First element inside the dialog matching [autofocus] |
|
9070 // 2. Tabbable element inside the content element |
|
9071 // 3. Tabbable element inside the buttonpane |
|
9072 // 4. The close button |
|
9073 // 5. The dialog itself |
|
9074 var hasFocus = this.element.find("[autofocus]"); |
|
9075 if ( !hasFocus.length ) { |
|
9076 hasFocus = this.element.find(":tabbable"); |
|
9077 } |
|
9078 if ( !hasFocus.length ) { |
|
9079 hasFocus = this.uiDialogButtonPane.find(":tabbable"); |
|
9080 } |
|
9081 if ( !hasFocus.length ) { |
|
9082 hasFocus = this.uiDialogTitlebarClose.filter(":tabbable"); |
|
9083 } |
|
9084 if ( !hasFocus.length ) { |
|
9085 hasFocus = this.uiDialog; |
|
9086 } |
|
9087 hasFocus.eq( 0 ).focus(); |
|
9088 }, |
|
9089 |
|
9090 _keepFocus: function( event ) { |
|
9091 function checkFocus() { |
|
9092 var activeElement = this.document[0].activeElement, |
|
9093 isActive = this.uiDialog[0] === activeElement || |
|
9094 $.contains( this.uiDialog[0], activeElement ); |
|
9095 if ( !isActive ) { |
|
9096 this._focusTabbable(); |
|
9097 } |
|
9098 } |
|
9099 event.preventDefault(); |
|
9100 checkFocus.call( this ); |
|
9101 // support: IE |
|
9102 // IE <= 8 doesn't prevent moving focus even with event.preventDefault() |
|
9103 // so we check again later |
|
9104 this._delay( checkFocus ); |
|
9105 }, |
|
9106 |
|
9107 _createWrapper: function() { |
|
9108 this.uiDialog = $("<div>") |
|
9109 .addClass( "ui-dialog ui-widget ui-widget-content ui-corner-all ui-front " + |
|
9110 this.options.dialogClass ) |
|
9111 .hide() |
|
9112 .attr({ |
|
9113 // Setting tabIndex makes the div focusable |
|
9114 tabIndex: -1, |
|
9115 role: "dialog" |
|
9116 }) |
|
9117 .appendTo( this._appendTo() ); |
|
9118 |
|
9119 this._on( this.uiDialog, { |
|
9120 keydown: function( event ) { |
|
9121 if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && |
|
9122 event.keyCode === $.ui.keyCode.ESCAPE ) { |
|
9123 event.preventDefault(); |
|
9124 this.close( event ); |
|
9125 return; |
|
9126 } |
|
9127 |
|
9128 // prevent tabbing out of dialogs |
|
9129 if ( event.keyCode !== $.ui.keyCode.TAB ) { |
|
9130 return; |
|
9131 } |
|
9132 var tabbables = this.uiDialog.find(":tabbable"), |
|
9133 first = tabbables.filter(":first"), |
|
9134 last = tabbables.filter(":last"); |
|
9135 |
|
9136 if ( ( event.target === last[0] || event.target === this.uiDialog[0] ) && !event.shiftKey ) { |
|
9137 first.focus( 1 ); |
|
9138 event.preventDefault(); |
|
9139 } else if ( ( event.target === first[0] || event.target === this.uiDialog[0] ) && event.shiftKey ) { |
|
9140 last.focus( 1 ); |
|
9141 event.preventDefault(); |
|
9142 } |
|
9143 }, |
|
9144 mousedown: function( event ) { |
|
9145 if ( this._moveToTop( event ) ) { |
|
9146 this._focusTabbable(); |
|
9147 } |
|
9148 } |
|
9149 }); |
|
9150 |
|
9151 // We assume that any existing aria-describedby attribute means |
|
9152 // that the dialog content is marked up properly |
|
9153 // otherwise we brute force the content as the description |
|
9154 if ( !this.element.find("[aria-describedby]").length ) { |
|
9155 this.uiDialog.attr({ |
|
9156 "aria-describedby": this.element.uniqueId().attr("id") |
|
9157 }); |
|
9158 } |
|
9159 }, |
|
9160 |
|
9161 _createTitlebar: function() { |
|
9162 var uiDialogTitle; |
|
9163 |
|
9164 this.uiDialogTitlebar = $("<div>") |
|
9165 .addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix") |
|
9166 .prependTo( this.uiDialog ); |
|
9167 this._on( this.uiDialogTitlebar, { |
|
9168 mousedown: function( event ) { |
|
9169 // Don't prevent click on close button (#8838) |
|
9170 // Focusing a dialog that is partially scrolled out of view |
|
9171 // causes the browser to scroll it into view, preventing the click event |
|
9172 if ( !$( event.target ).closest(".ui-dialog-titlebar-close") ) { |
|
9173 // Dialog isn't getting focus when dragging (#8063) |
|
9174 this.uiDialog.focus(); |
|
9175 } |
|
9176 } |
|
9177 }); |
|
9178 |
|
9179 // support: IE |
|
9180 // Use type="button" to prevent enter keypresses in textboxes from closing the |
|
9181 // dialog in IE (#9312) |
|
9182 this.uiDialogTitlebarClose = $( "<button type='button'></button>" ) |
|
9183 .button({ |
|
9184 label: this.options.closeText, |
|
9185 icons: { |
|
9186 primary: "ui-icon-closethick" |
|
9187 }, |
|
9188 text: false |
|
9189 }) |
|
9190 .addClass("ui-dialog-titlebar-close") |
|
9191 .appendTo( this.uiDialogTitlebar ); |
|
9192 this._on( this.uiDialogTitlebarClose, { |
|
9193 click: function( event ) { |
|
9194 event.preventDefault(); |
|
9195 this.close( event ); |
|
9196 } |
|
9197 }); |
|
9198 |
|
9199 uiDialogTitle = $("<span>") |
|
9200 .uniqueId() |
|
9201 .addClass("ui-dialog-title") |
|
9202 .prependTo( this.uiDialogTitlebar ); |
|
9203 this._title( uiDialogTitle ); |
|
9204 |
|
9205 this.uiDialog.attr({ |
|
9206 "aria-labelledby": uiDialogTitle.attr("id") |
|
9207 }); |
|
9208 }, |
|
9209 |
|
9210 _title: function( title ) { |
|
9211 if ( !this.options.title ) { |
|
9212 title.html(" "); |
|
9213 } |
|
9214 title.text( this.options.title ); |
|
9215 }, |
|
9216 |
|
9217 _createButtonPane: function() { |
|
9218 this.uiDialogButtonPane = $("<div>") |
|
9219 .addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"); |
|
9220 |
|
9221 this.uiButtonSet = $("<div>") |
|
9222 .addClass("ui-dialog-buttonset") |
|
9223 .appendTo( this.uiDialogButtonPane ); |
|
9224 |
|
9225 this._createButtons(); |
|
9226 }, |
|
9227 |
|
9228 _createButtons: function() { |
|
9229 var that = this, |
|
9230 buttons = this.options.buttons; |
|
9231 |
|
9232 // if we already have a button pane, remove it |
|
9233 this.uiDialogButtonPane.remove(); |
|
9234 this.uiButtonSet.empty(); |
|
9235 |
|
9236 if ( $.isEmptyObject( buttons ) || ($.isArray( buttons ) && !buttons.length) ) { |
|
9237 this.uiDialog.removeClass("ui-dialog-buttons"); |
|
9238 return; |
|
9239 } |
|
9240 |
|
9241 $.each( buttons, function( name, props ) { |
|
9242 var click, buttonOptions; |
|
9243 props = $.isFunction( props ) ? |
|
9244 { click: props, text: name } : |
|
9245 props; |
|
9246 // Default to a non-submitting button |
|
9247 props = $.extend( { type: "button" }, props ); |
|
9248 // Change the context for the click callback to be the main element |
|
9249 click = props.click; |
|
9250 props.click = function() { |
|
9251 click.apply( that.element[0], arguments ); |
|
9252 }; |
|
9253 buttonOptions = { |
|
9254 icons: props.icons, |
|
9255 text: props.showText |
|
9256 }; |
|
9257 delete props.icons; |
|
9258 delete props.showText; |
|
9259 $( "<button></button>", props ) |
|
9260 .button( buttonOptions ) |
|
9261 .appendTo( that.uiButtonSet ); |
|
9262 }); |
|
9263 this.uiDialog.addClass("ui-dialog-buttons"); |
|
9264 this.uiDialogButtonPane.appendTo( this.uiDialog ); |
|
9265 }, |
|
9266 |
|
9267 _makeDraggable: function() { |
|
9268 var that = this, |
|
9269 options = this.options; |
|
9270 |
|
9271 function filteredUi( ui ) { |
|
9272 return { |
|
9273 position: ui.position, |
|
9274 offset: ui.offset |
|
9275 }; |
|
9276 } |
|
9277 |
|
9278 this.uiDialog.draggable({ |
|
9279 cancel: ".ui-dialog-content, .ui-dialog-titlebar-close", |
|
9280 handle: ".ui-dialog-titlebar", |
|
9281 containment: "document", |
|
9282 start: function( event, ui ) { |
|
9283 $( this ).addClass("ui-dialog-dragging"); |
|
9284 that._blockFrames(); |
|
9285 that._trigger( "dragStart", event, filteredUi( ui ) ); |
|
9286 }, |
|
9287 drag: function( event, ui ) { |
|
9288 that._trigger( "drag", event, filteredUi( ui ) ); |
|
9289 }, |
|
9290 stop: function( event, ui ) { |
|
9291 options.position = [ |
|
9292 ui.position.left - that.document.scrollLeft(), |
|
9293 ui.position.top - that.document.scrollTop() |
|
9294 ]; |
|
9295 $( this ).removeClass("ui-dialog-dragging"); |
|
9296 that._unblockFrames(); |
|
9297 that._trigger( "dragStop", event, filteredUi( ui ) ); |
|
9298 } |
|
9299 }); |
|
9300 }, |
|
9301 |
|
9302 _makeResizable: function() { |
|
9303 var that = this, |
|
9304 options = this.options, |
|
9305 handles = options.resizable, |
|
9306 // .ui-resizable has position: relative defined in the stylesheet |
|
9307 // but dialogs have to use absolute or fixed positioning |
|
9308 position = this.uiDialog.css("position"), |
|
9309 resizeHandles = typeof handles === "string" ? |
|
9310 handles : |
|
9311 "n,e,s,w,se,sw,ne,nw"; |
|
9312 |
|
9313 function filteredUi( ui ) { |
|
9314 return { |
|
9315 originalPosition: ui.originalPosition, |
|
9316 originalSize: ui.originalSize, |
|
9317 position: ui.position, |
|
9318 size: ui.size |
|
9319 }; |
|
9320 } |
|
9321 |
|
9322 this.uiDialog.resizable({ |
|
9323 cancel: ".ui-dialog-content", |
|
9324 containment: "document", |
|
9325 alsoResize: this.element, |
|
9326 maxWidth: options.maxWidth, |
|
9327 maxHeight: options.maxHeight, |
|
9328 minWidth: options.minWidth, |
|
9329 minHeight: this._minHeight(), |
|
9330 handles: resizeHandles, |
|
9331 start: function( event, ui ) { |
|
9332 $( this ).addClass("ui-dialog-resizing"); |
|
9333 that._blockFrames(); |
|
9334 that._trigger( "resizeStart", event, filteredUi( ui ) ); |
|
9335 }, |
|
9336 resize: function( event, ui ) { |
|
9337 that._trigger( "resize", event, filteredUi( ui ) ); |
|
9338 }, |
|
9339 stop: function( event, ui ) { |
|
9340 options.height = $( this ).height(); |
|
9341 options.width = $( this ).width(); |
|
9342 $( this ).removeClass("ui-dialog-resizing"); |
|
9343 that._unblockFrames(); |
|
9344 that._trigger( "resizeStop", event, filteredUi( ui ) ); |
|
9345 } |
|
9346 }) |
|
9347 .css( "position", position ); |
|
9348 }, |
|
9349 |
|
9350 _minHeight: function() { |
|
9351 var options = this.options; |
|
9352 |
|
9353 return options.height === "auto" ? |
|
9354 options.minHeight : |
|
9355 Math.min( options.minHeight, options.height ); |
|
9356 }, |
|
9357 |
|
9358 _position: function() { |
|
9359 // Need to show the dialog to get the actual offset in the position plugin |
|
9360 var isVisible = this.uiDialog.is(":visible"); |
|
9361 if ( !isVisible ) { |
|
9362 this.uiDialog.show(); |
|
9363 } |
|
9364 this.uiDialog.position( this.options.position ); |
|
9365 if ( !isVisible ) { |
|
9366 this.uiDialog.hide(); |
|
9367 } |
|
9368 }, |
|
9369 |
|
9370 _setOptions: function( options ) { |
|
9371 var that = this, |
|
9372 resize = false, |
|
9373 resizableOptions = {}; |
|
9374 |
|
9375 $.each( options, function( key, value ) { |
|
9376 that._setOption( key, value ); |
|
9377 |
|
9378 if ( key in sizeRelatedOptions ) { |
|
9379 resize = true; |
|
9380 } |
|
9381 if ( key in resizableRelatedOptions ) { |
|
9382 resizableOptions[ key ] = value; |
|
9383 } |
|
9384 }); |
|
9385 |
|
9386 if ( resize ) { |
|
9387 this._size(); |
|
9388 this._position(); |
|
9389 } |
|
9390 if ( this.uiDialog.is(":data(ui-resizable)") ) { |
|
9391 this.uiDialog.resizable( "option", resizableOptions ); |
|
9392 } |
|
9393 }, |
|
9394 |
|
9395 _setOption: function( key, value ) { |
|
9396 var isDraggable, isResizable, |
|
9397 uiDialog = this.uiDialog; |
|
9398 |
|
9399 if ( key === "dialogClass" ) { |
|
9400 uiDialog |
|
9401 .removeClass( this.options.dialogClass ) |
|
9402 .addClass( value ); |
|
9403 } |
|
9404 |
|
9405 if ( key === "disabled" ) { |
|
9406 return; |
|
9407 } |
|
9408 |
|
9409 this._super( key, value ); |
|
9410 |
|
9411 if ( key === "appendTo" ) { |
|
9412 this.uiDialog.appendTo( this._appendTo() ); |
|
9413 } |
|
9414 |
|
9415 if ( key === "buttons" ) { |
|
9416 this._createButtons(); |
|
9417 } |
|
9418 |
|
9419 if ( key === "closeText" ) { |
|
9420 this.uiDialogTitlebarClose.button({ |
|
9421 // Ensure that we always pass a string |
|
9422 label: "" + value |
|
9423 }); |
|
9424 } |
|
9425 |
|
9426 if ( key === "draggable" ) { |
|
9427 isDraggable = uiDialog.is(":data(ui-draggable)"); |
|
9428 if ( isDraggable && !value ) { |
|
9429 uiDialog.draggable("destroy"); |
|
9430 } |
|
9431 |
|
9432 if ( !isDraggable && value ) { |
|
9433 this._makeDraggable(); |
|
9434 } |
|
9435 } |
|
9436 |
|
9437 if ( key === "position" ) { |
|
9438 this._position(); |
|
9439 } |
|
9440 |
|
9441 if ( key === "resizable" ) { |
|
9442 // currently resizable, becoming non-resizable |
|
9443 isResizable = uiDialog.is(":data(ui-resizable)"); |
|
9444 if ( isResizable && !value ) { |
|
9445 uiDialog.resizable("destroy"); |
|
9446 } |
|
9447 |
|
9448 // currently resizable, changing handles |
|
9449 if ( isResizable && typeof value === "string" ) { |
|
9450 uiDialog.resizable( "option", "handles", value ); |
|
9451 } |
|
9452 |
|
9453 // currently non-resizable, becoming resizable |
|
9454 if ( !isResizable && value !== false ) { |
|
9455 this._makeResizable(); |
|
9456 } |
|
9457 } |
|
9458 |
|
9459 if ( key === "title" ) { |
|
9460 this._title( this.uiDialogTitlebar.find(".ui-dialog-title") ); |
|
9461 } |
|
9462 }, |
|
9463 |
|
9464 _size: function() { |
|
9465 // If the user has resized the dialog, the .ui-dialog and .ui-dialog-content |
|
9466 // divs will both have width and height set, so we need to reset them |
|
9467 var nonContentHeight, minContentHeight, maxContentHeight, |
|
9468 options = this.options; |
|
9469 |
|
9470 // Reset content sizing |
|
9471 this.element.show().css({ |
|
9472 width: "auto", |
|
9473 minHeight: 0, |
|
9474 maxHeight: "none", |
|
9475 height: 0 |
|
9476 }); |
|
9477 |
|
9478 if ( options.minWidth > options.width ) { |
|
9479 options.width = options.minWidth; |
|
9480 } |
|
9481 |
|
9482 // reset wrapper sizing |
|
9483 // determine the height of all the non-content elements |
|
9484 nonContentHeight = this.uiDialog.css({ |
|
9485 height: "auto", |
|
9486 width: options.width |
|
9487 }) |
|
9488 .outerHeight(); |
|
9489 minContentHeight = Math.max( 0, options.minHeight - nonContentHeight ); |
|
9490 maxContentHeight = typeof options.maxHeight === "number" ? |
|
9491 Math.max( 0, options.maxHeight - nonContentHeight ) : |
|
9492 "none"; |
|
9493 |
|
9494 if ( options.height === "auto" ) { |
|
9495 this.element.css({ |
|
9496 minHeight: minContentHeight, |
|
9497 maxHeight: maxContentHeight, |
|
9498 height: "auto" |
|
9499 }); |
|
9500 } else { |
|
9501 this.element.height( Math.max( 0, options.height - nonContentHeight ) ); |
|
9502 } |
|
9503 |
|
9504 if (this.uiDialog.is(":data(ui-resizable)") ) { |
|
9505 this.uiDialog.resizable( "option", "minHeight", this._minHeight() ); |
|
9506 } |
|
9507 }, |
|
9508 |
|
9509 _blockFrames: function() { |
|
9510 this.iframeBlocks = this.document.find( "iframe" ).map(function() { |
|
9511 var iframe = $( this ); |
|
9512 |
|
9513 return $( "<div>" ) |
|
9514 .css({ |
|
9515 position: "absolute", |
|
9516 width: iframe.outerWidth(), |
|
9517 height: iframe.outerHeight() |
|
9518 }) |
|
9519 .appendTo( iframe.parent() ) |
|
9520 .offset( iframe.offset() )[0]; |
|
9521 }); |
|
9522 }, |
|
9523 |
|
9524 _unblockFrames: function() { |
|
9525 if ( this.iframeBlocks ) { |
|
9526 this.iframeBlocks.remove(); |
|
9527 delete this.iframeBlocks; |
|
9528 } |
|
9529 }, |
|
9530 |
|
9531 _allowInteraction: function( event ) { |
|
9532 if ( $( event.target ).closest(".ui-dialog").length ) { |
|
9533 return true; |
|
9534 } |
|
9535 |
|
9536 // TODO: Remove hack when datepicker implements |
|
9537 // the .ui-front logic (#8989) |
|
9538 return !!$( event.target ).closest(".ui-datepicker").length; |
|
9539 }, |
|
9540 |
|
9541 _createOverlay: function() { |
|
9542 if ( !this.options.modal ) { |
|
9543 return; |
|
9544 } |
|
9545 |
|
9546 var that = this, |
|
9547 widgetFullName = this.widgetFullName; |
|
9548 if ( !$.ui.dialog.overlayInstances ) { |
|
9549 // Prevent use of anchors and inputs. |
|
9550 // We use a delay in case the overlay is created from an |
|
9551 // event that we're going to be cancelling. (#2804) |
|
9552 this._delay(function() { |
|
9553 // Handle .dialog().dialog("close") (#4065) |
|
9554 if ( $.ui.dialog.overlayInstances ) { |
|
9555 this.document.bind( "focusin.dialog", function( event ) { |
|
9556 if ( !that._allowInteraction( event ) ) { |
|
9557 event.preventDefault(); |
|
9558 $(".ui-dialog:visible:last .ui-dialog-content") |
|
9559 .data( widgetFullName )._focusTabbable(); |
|
9560 } |
|
9561 }); |
|
9562 } |
|
9563 }); |
|
9564 } |
|
9565 |
|
9566 this.overlay = $("<div>") |
|
9567 .addClass("ui-widget-overlay ui-front") |
|
9568 .appendTo( this._appendTo() ); |
|
9569 this._on( this.overlay, { |
|
9570 mousedown: "_keepFocus" |
|
9571 }); |
|
9572 $.ui.dialog.overlayInstances++; |
|
9573 }, |
|
9574 |
|
9575 _destroyOverlay: function() { |
|
9576 if ( !this.options.modal ) { |
|
9577 return; |
|
9578 } |
|
9579 |
|
9580 if ( this.overlay ) { |
|
9581 $.ui.dialog.overlayInstances--; |
|
9582 |
|
9583 if ( !$.ui.dialog.overlayInstances ) { |
|
9584 this.document.unbind( "focusin.dialog" ); |
|
9585 } |
|
9586 this.overlay.remove(); |
|
9587 this.overlay = null; |
|
9588 } |
|
9589 } |
|
9590 }); |
|
9591 |
|
9592 $.ui.dialog.overlayInstances = 0; |
|
9593 |
|
9594 // DEPRECATED |
|
9595 if ( $.uiBackCompat !== false ) { |
|
9596 // position option with array notation |
|
9597 // just override with old implementation |
|
9598 $.widget( "ui.dialog", $.ui.dialog, { |
|
9599 _position: function() { |
|
9600 var position = this.options.position, |
|
9601 myAt = [], |
|
9602 offset = [ 0, 0 ], |
|
9603 isVisible; |
|
9604 |
|
9605 if ( position ) { |
|
9606 if ( typeof position === "string" || (typeof position === "object" && "0" in position ) ) { |
|
9607 myAt = position.split ? position.split(" ") : [ position[0], position[1] ]; |
|
9608 if ( myAt.length === 1 ) { |
|
9609 myAt[1] = myAt[0]; |
|
9610 } |
|
9611 |
|
9612 $.each( [ "left", "top" ], function( i, offsetPosition ) { |
|
9613 if ( +myAt[ i ] === myAt[ i ] ) { |
|
9614 offset[ i ] = myAt[ i ]; |
|
9615 myAt[ i ] = offsetPosition; |
|
9616 } |
|
9617 }); |
|
9618 |
|
9619 position = { |
|
9620 my: myAt[0] + (offset[0] < 0 ? offset[0] : "+" + offset[0]) + " " + |
|
9621 myAt[1] + (offset[1] < 0 ? offset[1] : "+" + offset[1]), |
|
9622 at: myAt.join(" ") |
|
9623 }; |
|
9624 } |
|
9625 |
|
9626 position = $.extend( {}, $.ui.dialog.prototype.options.position, position ); |
|
9627 } else { |
|
9628 position = $.ui.dialog.prototype.options.position; |
|
9629 } |
|
9630 |
|
9631 // need to show the dialog to get the actual offset in the position plugin |
|
9632 isVisible = this.uiDialog.is(":visible"); |
|
9633 if ( !isVisible ) { |
|
9634 this.uiDialog.show(); |
|
9635 } |
|
9636 this.uiDialog.position( position ); |
|
9637 if ( !isVisible ) { |
|
9638 this.uiDialog.hide(); |
|
9639 } |
|
9640 } |
|
9641 }); |
|
9642 } |
|
9643 |
|
9644 }( jQuery ) ); |
|
9645 (function( $, undefined ) { |
|
9646 |
|
9647 $.widget( "ui.menu", { |
|
9648 version: "1.10.4", |
|
9649 defaultElement: "<ul>", |
|
9650 delay: 300, |
|
9651 options: { |
|
9652 icons: { |
|
9653 submenu: "ui-icon-carat-1-e" |
|
9654 }, |
|
9655 menus: "ul", |
|
9656 position: { |
|
9657 my: "left top", |
|
9658 at: "right top" |
|
9659 }, |
|
9660 role: "menu", |
|
9661 |
|
9662 // callbacks |
|
9663 blur: null, |
|
9664 focus: null, |
|
9665 select: null |
|
9666 }, |
|
9667 |
|
9668 _create: function() { |
|
9669 this.activeMenu = this.element; |
|
9670 // flag used to prevent firing of the click handler |
|
9671 // as the event bubbles up through nested menus |
|
9672 this.mouseHandled = false; |
|
9673 this.element |
|
9674 .uniqueId() |
|
9675 .addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" ) |
|
9676 .toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length ) |
|
9677 .attr({ |
|
9678 role: this.options.role, |
|
9679 tabIndex: 0 |
|
9680 }) |
|
9681 // need to catch all clicks on disabled menu |
|
9682 // not possible through _on |
|
9683 .bind( "click" + this.eventNamespace, $.proxy(function( event ) { |
|
9684 if ( this.options.disabled ) { |
|
9685 event.preventDefault(); |
|
9686 } |
|
9687 }, this )); |
|
9688 |
|
9689 if ( this.options.disabled ) { |
|
9690 this.element |
|
9691 .addClass( "ui-state-disabled" ) |
|
9692 .attr( "aria-disabled", "true" ); |
|
9693 } |
|
9694 |
|
9695 this._on({ |
|
9696 // Prevent focus from sticking to links inside menu after clicking |
|
9697 // them (focus should always stay on UL during navigation). |
|
9698 "mousedown .ui-menu-item > a": function( event ) { |
|
9699 event.preventDefault(); |
|
9700 }, |
|
9701 "click .ui-state-disabled > a": function( event ) { |
|
9702 event.preventDefault(); |
|
9703 }, |
|
9704 "click .ui-menu-item:has(a)": function( event ) { |
|
9705 var target = $( event.target ).closest( ".ui-menu-item" ); |
|
9706 if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) { |
|
9707 this.select( event ); |
|
9708 |
|
9709 // Only set the mouseHandled flag if the event will bubble, see #9469. |
|
9710 if ( !event.isPropagationStopped() ) { |
|
9711 this.mouseHandled = true; |
|
9712 } |
|
9713 |
|
9714 // Open submenu on click |
|
9715 if ( target.has( ".ui-menu" ).length ) { |
|
9716 this.expand( event ); |
|
9717 } else if ( !this.element.is( ":focus" ) && $( this.document[ 0 ].activeElement ).closest( ".ui-menu" ).length ) { |
|
9718 |
|
9719 // Redirect focus to the menu |
|
9720 this.element.trigger( "focus", [ true ] ); |
|
9721 |
|
9722 // If the active item is on the top level, let it stay active. |
|
9723 // Otherwise, blur the active item since it is no longer visible. |
|
9724 if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) { |
|
9725 clearTimeout( this.timer ); |
|
9726 } |
|
9727 } |
|
9728 } |
|
9729 }, |
|
9730 "mouseenter .ui-menu-item": function( event ) { |
|
9731 var target = $( event.currentTarget ); |
|
9732 // Remove ui-state-active class from siblings of the newly focused menu item |
|
9733 // to avoid a jump caused by adjacent elements both having a class with a border |
|
9734 target.siblings().children( ".ui-state-active" ).removeClass( "ui-state-active" ); |
|
9735 this.focus( event, target ); |
|
9736 }, |
|
9737 mouseleave: "collapseAll", |
|
9738 "mouseleave .ui-menu": "collapseAll", |
|
9739 focus: function( event, keepActiveItem ) { |
|
9740 // If there's already an active item, keep it active |
|
9741 // If not, activate the first item |
|
9742 var item = this.active || this.element.children( ".ui-menu-item" ).eq( 0 ); |
|
9743 |
|
9744 if ( !keepActiveItem ) { |
|
9745 this.focus( event, item ); |
|
9746 } |
|
9747 }, |
|
9748 blur: function( event ) { |
|
9749 this._delay(function() { |
|
9750 if ( !$.contains( this.element[0], this.document[0].activeElement ) ) { |
|
9751 this.collapseAll( event ); |
|
9752 } |
|
9753 }); |
|
9754 }, |
|
9755 keydown: "_keydown" |
|
9756 }); |
|
9757 |
|
9758 this.refresh(); |
|
9759 |
|
9760 // Clicks outside of a menu collapse any open menus |
|
9761 this._on( this.document, { |
|
9762 click: function( event ) { |
|
9763 if ( !$( event.target ).closest( ".ui-menu" ).length ) { |
|
9764 this.collapseAll( event ); |
|
9765 } |
|
9766 |
|
9767 // Reset the mouseHandled flag |
|
9768 this.mouseHandled = false; |
|
9769 } |
|
9770 }); |
|
9771 }, |
|
9772 |
|
9773 _destroy: function() { |
|
9774 // Destroy (sub)menus |
|
9775 this.element |
|
9776 .removeAttr( "aria-activedescendant" ) |
|
9777 .find( ".ui-menu" ).addBack() |
|
9778 .removeClass( "ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons" ) |
|
9779 .removeAttr( "role" ) |
|
9780 .removeAttr( "tabIndex" ) |
|
9781 .removeAttr( "aria-labelledby" ) |
|
9782 .removeAttr( "aria-expanded" ) |
|
9783 .removeAttr( "aria-hidden" ) |
|
9784 .removeAttr( "aria-disabled" ) |
|
9785 .removeUniqueId() |
|
9786 .show(); |
|
9787 |
|
9788 // Destroy menu items |
|
9789 this.element.find( ".ui-menu-item" ) |
|
9790 .removeClass( "ui-menu-item" ) |
|
9791 .removeAttr( "role" ) |
|
9792 .removeAttr( "aria-disabled" ) |
|
9793 .children( "a" ) |
|
9794 .removeUniqueId() |
|
9795 .removeClass( "ui-corner-all ui-state-hover" ) |
|
9796 .removeAttr( "tabIndex" ) |
|
9797 .removeAttr( "role" ) |
|
9798 .removeAttr( "aria-haspopup" ) |
|
9799 .children().each( function() { |
|
9800 var elem = $( this ); |
|
9801 if ( elem.data( "ui-menu-submenu-carat" ) ) { |
|
9802 elem.remove(); |
|
9803 } |
|
9804 }); |
|
9805 |
|
9806 // Destroy menu dividers |
|
9807 this.element.find( ".ui-menu-divider" ).removeClass( "ui-menu-divider ui-widget-content" ); |
|
9808 }, |
|
9809 |
|
9810 _keydown: function( event ) { |
|
9811 var match, prev, character, skip, regex, |
|
9812 preventDefault = true; |
|
9813 |
|
9814 function escape( value ) { |
|
9815 return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ); |
|
9816 } |
|
9817 |
|
9818 switch ( event.keyCode ) { |
|
9819 case $.ui.keyCode.PAGE_UP: |
|
9820 this.previousPage( event ); |
|
9821 break; |
|
9822 case $.ui.keyCode.PAGE_DOWN: |
|
9823 this.nextPage( event ); |
|
9824 break; |
|
9825 case $.ui.keyCode.HOME: |
|
9826 this._move( "first", "first", event ); |
|
9827 break; |
|
9828 case $.ui.keyCode.END: |
|
9829 this._move( "last", "last", event ); |
|
9830 break; |
|
9831 case $.ui.keyCode.UP: |
|
9832 this.previous( event ); |
|
9833 break; |
|
9834 case $.ui.keyCode.DOWN: |
|
9835 this.next( event ); |
|
9836 break; |
|
9837 case $.ui.keyCode.LEFT: |
|
9838 this.collapse( event ); |
|
9839 break; |
|
9840 case $.ui.keyCode.RIGHT: |
|
9841 if ( this.active && !this.active.is( ".ui-state-disabled" ) ) { |
|
9842 this.expand( event ); |
|
9843 } |
|
9844 break; |
|
9845 case $.ui.keyCode.ENTER: |
|
9846 case $.ui.keyCode.SPACE: |
|
9847 this._activate( event ); |
|
9848 break; |
|
9849 case $.ui.keyCode.ESCAPE: |
|
9850 this.collapse( event ); |
|
9851 break; |
|
9852 default: |
|
9853 preventDefault = false; |
|
9854 prev = this.previousFilter || ""; |
|
9855 character = String.fromCharCode( event.keyCode ); |
|
9856 skip = false; |
|
9857 |
|
9858 clearTimeout( this.filterTimer ); |
|
9859 |
|
9860 if ( character === prev ) { |
|
9861 skip = true; |
|
9862 } else { |
|
9863 character = prev + character; |
|
9864 } |
|
9865 |
|
9866 regex = new RegExp( "^" + escape( character ), "i" ); |
|
9867 match = this.activeMenu.children( ".ui-menu-item" ).filter(function() { |
|
9868 return regex.test( $( this ).children( "a" ).text() ); |
|
9869 }); |
|
9870 match = skip && match.index( this.active.next() ) !== -1 ? |
|
9871 this.active.nextAll( ".ui-menu-item" ) : |
|
9872 match; |
|
9873 |
|
9874 // If no matches on the current filter, reset to the last character pressed |
|
9875 // to move down the menu to the first item that starts with that character |
|
9876 if ( !match.length ) { |
|
9877 character = String.fromCharCode( event.keyCode ); |
|
9878 regex = new RegExp( "^" + escape( character ), "i" ); |
|
9879 match = this.activeMenu.children( ".ui-menu-item" ).filter(function() { |
|
9880 return regex.test( $( this ).children( "a" ).text() ); |
|
9881 }); |
|
9882 } |
|
9883 |
|
9884 if ( match.length ) { |
|
9885 this.focus( event, match ); |
|
9886 if ( match.length > 1 ) { |
|
9887 this.previousFilter = character; |
|
9888 this.filterTimer = this._delay(function() { |
|
9889 delete this.previousFilter; |
|
9890 }, 1000 ); |
|
9891 } else { |
|
9892 delete this.previousFilter; |
|
9893 } |
|
9894 } else { |
|
9895 delete this.previousFilter; |
|
9896 } |
|
9897 } |
|
9898 |
|
9899 if ( preventDefault ) { |
|
9900 event.preventDefault(); |
|
9901 } |
|
9902 }, |
|
9903 |
|
9904 _activate: function( event ) { |
|
9905 if ( !this.active.is( ".ui-state-disabled" ) ) { |
|
9906 if ( this.active.children( "a[aria-haspopup='true']" ).length ) { |
|
9907 this.expand( event ); |
|
9908 } else { |
|
9909 this.select( event ); |
|
9910 } |
|
9911 } |
|
9912 }, |
|
9913 |
|
9914 refresh: function() { |
|
9915 var menus, |
|
9916 icon = this.options.icons.submenu, |
|
9917 submenus = this.element.find( this.options.menus ); |
|
9918 |
|
9919 this.element.toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length ); |
|
9920 |
|
9921 // Initialize nested menus |
|
9922 submenus.filter( ":not(.ui-menu)" ) |
|
9923 .addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" ) |
|
9924 .hide() |
|
9925 .attr({ |
|
9926 role: this.options.role, |
|
9927 "aria-hidden": "true", |
|
9928 "aria-expanded": "false" |
|
9929 }) |
|
9930 .each(function() { |
|
9931 var menu = $( this ), |
|
9932 item = menu.prev( "a" ), |
|
9933 submenuCarat = $( "<span>" ) |
|
9934 .addClass( "ui-menu-icon ui-icon " + icon ) |
|
9935 .data( "ui-menu-submenu-carat", true ); |
|
9936 |
|
9937 item |
|
9938 .attr( "aria-haspopup", "true" ) |
|
9939 .prepend( submenuCarat ); |
|
9940 menu.attr( "aria-labelledby", item.attr( "id" ) ); |
|
9941 }); |
|
9942 |
|
9943 menus = submenus.add( this.element ); |
|
9944 |
|
9945 // Don't refresh list items that are already adapted |
|
9946 menus.children( ":not(.ui-menu-item):has(a)" ) |
|
9947 .addClass( "ui-menu-item" ) |
|
9948 .attr( "role", "presentation" ) |
|
9949 .children( "a" ) |
|
9950 .uniqueId() |
|
9951 .addClass( "ui-corner-all" ) |
|
9952 .attr({ |
|
9953 tabIndex: -1, |
|
9954 role: this._itemRole() |
|
9955 }); |
|
9956 |
|
9957 // Initialize unlinked menu-items containing spaces and/or dashes only as dividers |
|
9958 menus.children( ":not(.ui-menu-item)" ).each(function() { |
|
9959 var item = $( this ); |
|
9960 // hyphen, em dash, en dash |
|
9961 if ( !/[^\-\u2014\u2013\s]/.test( item.text() ) ) { |
|
9962 item.addClass( "ui-widget-content ui-menu-divider" ); |
|
9963 } |
|
9964 }); |
|
9965 |
|
9966 // Add aria-disabled attribute to any disabled menu item |
|
9967 menus.children( ".ui-state-disabled" ).attr( "aria-disabled", "true" ); |
|
9968 |
|
9969 // If the active item has been removed, blur the menu |
|
9970 if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) { |
|
9971 this.blur(); |
|
9972 } |
|
9973 }, |
|
9974 |
|
9975 _itemRole: function() { |
|
9976 return { |
|
9977 menu: "menuitem", |
|
9978 listbox: "option" |
|
9979 }[ this.options.role ]; |
|
9980 }, |
|
9981 |
|
9982 _setOption: function( key, value ) { |
|
9983 if ( key === "icons" ) { |
|
9984 this.element.find( ".ui-menu-icon" ) |
|
9985 .removeClass( this.options.icons.submenu ) |
|
9986 .addClass( value.submenu ); |
|
9987 } |
|
9988 this._super( key, value ); |
|
9989 }, |
|
9990 |
|
9991 focus: function( event, item ) { |
|
9992 var nested, focused; |
|
9993 this.blur( event, event && event.type === "focus" ); |
|
9994 |
|
9995 this._scrollIntoView( item ); |
|
9996 |
|
9997 this.active = item.first(); |
|
9998 focused = this.active.children( "a" ).addClass( "ui-state-focus" ); |
|
9999 // Only update aria-activedescendant if there's a role |
|
10000 // otherwise we assume focus is managed elsewhere |
|
10001 if ( this.options.role ) { |
|
10002 this.element.attr( "aria-activedescendant", focused.attr( "id" ) ); |
|
10003 } |
|
10004 |
|
10005 // Highlight active parent menu item, if any |
|
10006 this.active |
|
10007 .parent() |
|
10008 .closest( ".ui-menu-item" ) |
|
10009 .children( "a:first" ) |
|
10010 .addClass( "ui-state-active" ); |
|
10011 |
|
10012 if ( event && event.type === "keydown" ) { |
|
10013 this._close(); |
|
10014 } else { |
|
10015 this.timer = this._delay(function() { |
|
10016 this._close(); |
|
10017 }, this.delay ); |
|
10018 } |
|
10019 |
|
10020 nested = item.children( ".ui-menu" ); |
|
10021 if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) { |
|
10022 this._startOpening(nested); |
|
10023 } |
|
10024 this.activeMenu = item.parent(); |
|
10025 |
|
10026 this._trigger( "focus", event, { item: item } ); |
|
10027 }, |
|
10028 |
|
10029 _scrollIntoView: function( item ) { |
|
10030 var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight; |
|
10031 if ( this._hasScroll() ) { |
|
10032 borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0; |
|
10033 paddingTop = parseFloat( $.css( this.activeMenu[0], "paddingTop" ) ) || 0; |
|
10034 offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop; |
|
10035 scroll = this.activeMenu.scrollTop(); |
|
10036 elementHeight = this.activeMenu.height(); |
|
10037 itemHeight = item.height(); |
|
10038 |
|
10039 if ( offset < 0 ) { |
|
10040 this.activeMenu.scrollTop( scroll + offset ); |
|
10041 } else if ( offset + itemHeight > elementHeight ) { |
|
10042 this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight ); |
|
10043 } |
|
10044 } |
|
10045 }, |
|
10046 |
|
10047 blur: function( event, fromFocus ) { |
|
10048 if ( !fromFocus ) { |
|
10049 clearTimeout( this.timer ); |
|
10050 } |
|
10051 |
|
10052 if ( !this.active ) { |
|
10053 return; |
|
10054 } |
|
10055 |
|
10056 this.active.children( "a" ).removeClass( "ui-state-focus" ); |
|
10057 this.active = null; |
|
10058 |
|
10059 this._trigger( "blur", event, { item: this.active } ); |
|
10060 }, |
|
10061 |
|
10062 _startOpening: function( submenu ) { |
|
10063 clearTimeout( this.timer ); |
|
10064 |
|
10065 // Don't open if already open fixes a Firefox bug that caused a .5 pixel |
|
10066 // shift in the submenu position when mousing over the carat icon |
|
10067 if ( submenu.attr( "aria-hidden" ) !== "true" ) { |
|
10068 return; |
|
10069 } |
|
10070 |
|
10071 this.timer = this._delay(function() { |
|
10072 this._close(); |
|
10073 this._open( submenu ); |
|
10074 }, this.delay ); |
|
10075 }, |
|
10076 |
|
10077 _open: function( submenu ) { |
|
10078 var position = $.extend({ |
|
10079 of: this.active |
|
10080 }, this.options.position ); |
|
10081 |
|
10082 clearTimeout( this.timer ); |
|
10083 this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) ) |
|
10084 .hide() |
|
10085 .attr( "aria-hidden", "true" ); |
|
10086 |
|
10087 submenu |
|
10088 .show() |
|
10089 .removeAttr( "aria-hidden" ) |
|
10090 .attr( "aria-expanded", "true" ) |
|
10091 .position( position ); |
|
10092 }, |
|
10093 |
|
10094 collapseAll: function( event, all ) { |
|
10095 clearTimeout( this.timer ); |
|
10096 this.timer = this._delay(function() { |
|
10097 // If we were passed an event, look for the submenu that contains the event |
|
10098 var currentMenu = all ? this.element : |
|
10099 $( event && event.target ).closest( this.element.find( ".ui-menu" ) ); |
|
10100 |
|
10101 // If we found no valid submenu ancestor, use the main menu to close all sub menus anyway |
|
10102 if ( !currentMenu.length ) { |
|
10103 currentMenu = this.element; |
|
10104 } |
|
10105 |
|
10106 this._close( currentMenu ); |
|
10107 |
|
10108 this.blur( event ); |
|
10109 this.activeMenu = currentMenu; |
|
10110 }, this.delay ); |
|
10111 }, |
|
10112 |
|
10113 // With no arguments, closes the currently active menu - if nothing is active |
|
10114 // it closes all menus. If passed an argument, it will search for menus BELOW |
|
10115 _close: function( startMenu ) { |
|
10116 if ( !startMenu ) { |
|
10117 startMenu = this.active ? this.active.parent() : this.element; |
|
10118 } |
|
10119 |
|
10120 startMenu |
|
10121 .find( ".ui-menu" ) |
|
10122 .hide() |
|
10123 .attr( "aria-hidden", "true" ) |
|
10124 .attr( "aria-expanded", "false" ) |
|
10125 .end() |
|
10126 .find( "a.ui-state-active" ) |
|
10127 .removeClass( "ui-state-active" ); |
|
10128 }, |
|
10129 |
|
10130 collapse: function( event ) { |
|
10131 var newItem = this.active && |
|
10132 this.active.parent().closest( ".ui-menu-item", this.element ); |
|
10133 if ( newItem && newItem.length ) { |
|
10134 this._close(); |
|
10135 this.focus( event, newItem ); |
|
10136 } |
|
10137 }, |
|
10138 |
|
10139 expand: function( event ) { |
|
10140 var newItem = this.active && |
|
10141 this.active |
|
10142 .children( ".ui-menu " ) |
|
10143 .children( ".ui-menu-item" ) |
|
10144 .first(); |
|
10145 |
|
10146 if ( newItem && newItem.length ) { |
|
10147 this._open( newItem.parent() ); |
|
10148 |
|
10149 // Delay so Firefox will not hide activedescendant change in expanding submenu from AT |
|
10150 this._delay(function() { |
|
10151 this.focus( event, newItem ); |
|
10152 }); |
|
10153 } |
|
10154 }, |
|
10155 |
|
10156 next: function( event ) { |
|
10157 this._move( "next", "first", event ); |
|
10158 }, |
|
10159 |
|
10160 previous: function( event ) { |
|
10161 this._move( "prev", "last", event ); |
|
10162 }, |
|
10163 |
|
10164 isFirstItem: function() { |
|
10165 return this.active && !this.active.prevAll( ".ui-menu-item" ).length; |
|
10166 }, |
|
10167 |
|
10168 isLastItem: function() { |
|
10169 return this.active && !this.active.nextAll( ".ui-menu-item" ).length; |
|
10170 }, |
|
10171 |
|
10172 _move: function( direction, filter, event ) { |
|
10173 var next; |
|
10174 if ( this.active ) { |
|
10175 if ( direction === "first" || direction === "last" ) { |
|
10176 next = this.active |
|
10177 [ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" ) |
|
10178 .eq( -1 ); |
|
10179 } else { |
|
10180 next = this.active |
|
10181 [ direction + "All" ]( ".ui-menu-item" ) |
|
10182 .eq( 0 ); |
|
10183 } |
|
10184 } |
|
10185 if ( !next || !next.length || !this.active ) { |
|
10186 next = this.activeMenu.children( ".ui-menu-item" )[ filter ](); |
|
10187 } |
|
10188 |
|
10189 this.focus( event, next ); |
|
10190 }, |
|
10191 |
|
10192 nextPage: function( event ) { |
|
10193 var item, base, height; |
|
10194 |
|
10195 if ( !this.active ) { |
|
10196 this.next( event ); |
|
10197 return; |
|
10198 } |
|
10199 if ( this.isLastItem() ) { |
|
10200 return; |
|
10201 } |
|
10202 if ( this._hasScroll() ) { |
|
10203 base = this.active.offset().top; |
|
10204 height = this.element.height(); |
|
10205 this.active.nextAll( ".ui-menu-item" ).each(function() { |
|
10206 item = $( this ); |
|
10207 return item.offset().top - base - height < 0; |
|
10208 }); |
|
10209 |
|
10210 this.focus( event, item ); |
|
10211 } else { |
|
10212 this.focus( event, this.activeMenu.children( ".ui-menu-item" ) |
|
10213 [ !this.active ? "first" : "last" ]() ); |
|
10214 } |
|
10215 }, |
|
10216 |
|
10217 previousPage: function( event ) { |
|
10218 var item, base, height; |
|
10219 if ( !this.active ) { |
|
10220 this.next( event ); |
|
10221 return; |
|
10222 } |
|
10223 if ( this.isFirstItem() ) { |
|
10224 return; |
|
10225 } |
|
10226 if ( this._hasScroll() ) { |
|
10227 base = this.active.offset().top; |
|
10228 height = this.element.height(); |
|
10229 this.active.prevAll( ".ui-menu-item" ).each(function() { |
|
10230 item = $( this ); |
|
10231 return item.offset().top - base + height > 0; |
|
10232 }); |
|
10233 |
|
10234 this.focus( event, item ); |
|
10235 } else { |
|
10236 this.focus( event, this.activeMenu.children( ".ui-menu-item" ).first() ); |
|
10237 } |
|
10238 }, |
|
10239 |
|
10240 _hasScroll: function() { |
|
10241 return this.element.outerHeight() < this.element.prop( "scrollHeight" ); |
|
10242 }, |
|
10243 |
|
10244 select: function( event ) { |
|
10245 // TODO: It should never be possible to not have an active item at this |
|
10246 // point, but the tests don't trigger mouseenter before click. |
|
10247 this.active = this.active || $( event.target ).closest( ".ui-menu-item" ); |
|
10248 var ui = { item: this.active }; |
|
10249 if ( !this.active.has( ".ui-menu" ).length ) { |
|
10250 this.collapseAll( event, true ); |
|
10251 } |
|
10252 this._trigger( "select", event, ui ); |
|
10253 } |
|
10254 }); |
|
10255 |
|
10256 }( jQuery )); |
|
10257 (function( $, undefined ) { |
|
10258 |
|
10259 $.widget( "ui.progressbar", { |
|
10260 version: "1.10.4", |
|
10261 options: { |
|
10262 max: 100, |
|
10263 value: 0, |
|
10264 |
|
10265 change: null, |
|
10266 complete: null |
|
10267 }, |
|
10268 |
|
10269 min: 0, |
|
10270 |
|
10271 _create: function() { |
|
10272 // Constrain initial value |
|
10273 this.oldValue = this.options.value = this._constrainedValue(); |
|
10274 |
|
10275 this.element |
|
10276 .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" ) |
|
10277 .attr({ |
|
10278 // Only set static values, aria-valuenow and aria-valuemax are |
|
10279 // set inside _refreshValue() |
|
10280 role: "progressbar", |
|
10281 "aria-valuemin": this.min |
|
10282 }); |
|
10283 |
|
10284 this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" ) |
|
10285 .appendTo( this.element ); |
|
10286 |
|
10287 this._refreshValue(); |
|
10288 }, |
|
10289 |
|
10290 _destroy: function() { |
|
10291 this.element |
|
10292 .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" ) |
|
10293 .removeAttr( "role" ) |
|
10294 .removeAttr( "aria-valuemin" ) |
|
10295 .removeAttr( "aria-valuemax" ) |
|
10296 .removeAttr( "aria-valuenow" ); |
|
10297 |
|
10298 this.valueDiv.remove(); |
|
10299 }, |
|
10300 |
|
10301 value: function( newValue ) { |
|
10302 if ( newValue === undefined ) { |
|
10303 return this.options.value; |
|
10304 } |
|
10305 |
|
10306 this.options.value = this._constrainedValue( newValue ); |
|
10307 this._refreshValue(); |
|
10308 }, |
|
10309 |
|
10310 _constrainedValue: function( newValue ) { |
|
10311 if ( newValue === undefined ) { |
|
10312 newValue = this.options.value; |
|
10313 } |
|
10314 |
|
10315 this.indeterminate = newValue === false; |
|
10316 |
|
10317 // sanitize value |
|
10318 if ( typeof newValue !== "number" ) { |
|
10319 newValue = 0; |
|
10320 } |
|
10321 |
|
10322 return this.indeterminate ? false : |
|
10323 Math.min( this.options.max, Math.max( this.min, newValue ) ); |
|
10324 }, |
|
10325 |
|
10326 _setOptions: function( options ) { |
|
10327 // Ensure "value" option is set after other values (like max) |
|
10328 var value = options.value; |
|
10329 delete options.value; |
|
10330 |
|
10331 this._super( options ); |
|
10332 |
|
10333 this.options.value = this._constrainedValue( value ); |
|
10334 this._refreshValue(); |
|
10335 }, |
|
10336 |
|
10337 _setOption: function( key, value ) { |
|
10338 if ( key === "max" ) { |
|
10339 // Don't allow a max less than min |
|
10340 value = Math.max( this.min, value ); |
|
10341 } |
|
10342 |
|
10343 this._super( key, value ); |
|
10344 }, |
|
10345 |
|
10346 _percentage: function() { |
|
10347 return this.indeterminate ? 100 : 100 * ( this.options.value - this.min ) / ( this.options.max - this.min ); |
|
10348 }, |
|
10349 |
|
10350 _refreshValue: function() { |
|
10351 var value = this.options.value, |
|
10352 percentage = this._percentage(); |
|
10353 |
|
10354 this.valueDiv |
|
10355 .toggle( this.indeterminate || value > this.min ) |
|
10356 .toggleClass( "ui-corner-right", value === this.options.max ) |
|
10357 .width( percentage.toFixed(0) + "%" ); |
|
10358 |
|
10359 this.element.toggleClass( "ui-progressbar-indeterminate", this.indeterminate ); |
|
10360 |
|
10361 if ( this.indeterminate ) { |
|
10362 this.element.removeAttr( "aria-valuenow" ); |
|
10363 if ( !this.overlayDiv ) { |
|
10364 this.overlayDiv = $( "<div class='ui-progressbar-overlay'></div>" ).appendTo( this.valueDiv ); |
|
10365 } |
|
10366 } else { |
|
10367 this.element.attr({ |
|
10368 "aria-valuemax": this.options.max, |
|
10369 "aria-valuenow": value |
|
10370 }); |
|
10371 if ( this.overlayDiv ) { |
|
10372 this.overlayDiv.remove(); |
|
10373 this.overlayDiv = null; |
|
10374 } |
|
10375 } |
|
10376 |
|
10377 if ( this.oldValue !== value ) { |
|
10378 this.oldValue = value; |
|
10379 this._trigger( "change" ); |
|
10380 } |
|
10381 if ( value === this.options.max ) { |
|
10382 this._trigger( "complete" ); |
|
10383 } |
|
10384 } |
|
10385 }); |
|
10386 |
|
10387 })( jQuery ); |
|
10388 (function( $, undefined ) { |
|
10389 |
|
10390 // number of pages in a slider |
|
10391 // (how many times can you page up/down to go through the whole range) |
|
10392 var numPages = 5; |
|
10393 |
|
10394 $.widget( "ui.slider", $.ui.mouse, { |
|
10395 version: "1.10.4", |
|
10396 widgetEventPrefix: "slide", |
|
10397 |
|
10398 options: { |
|
10399 animate: false, |
|
10400 distance: 0, |
|
10401 max: 100, |
|
10402 min: 0, |
|
10403 orientation: "horizontal", |
|
10404 range: false, |
|
10405 step: 1, |
|
10406 value: 0, |
|
10407 values: null, |
|
10408 |
|
10409 // callbacks |
|
10410 change: null, |
|
10411 slide: null, |
|
10412 start: null, |
|
10413 stop: null |
|
10414 }, |
|
10415 |
|
10416 _create: function() { |
|
10417 this._keySliding = false; |
|
10418 this._mouseSliding = false; |
|
10419 this._animateOff = true; |
|
10420 this._handleIndex = null; |
|
10421 this._detectOrientation(); |
|
10422 this._mouseInit(); |
|
10423 |
|
10424 this.element |
|
10425 .addClass( "ui-slider" + |
|
10426 " ui-slider-" + this.orientation + |
|
10427 " ui-widget" + |
|
10428 " ui-widget-content" + |
|
10429 " ui-corner-all"); |
|
10430 |
|
10431 this._refresh(); |
|
10432 this._setOption( "disabled", this.options.disabled ); |
|
10433 |
|
10434 this._animateOff = false; |
|
10435 }, |
|
10436 |
|
10437 _refresh: function() { |
|
10438 this._createRange(); |
|
10439 this._createHandles(); |
|
10440 this._setupEvents(); |
|
10441 this._refreshValue(); |
|
10442 }, |
|
10443 |
|
10444 _createHandles: function() { |
|
10445 var i, handleCount, |
|
10446 options = this.options, |
|
10447 existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ), |
|
10448 handle = "<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>", |
|
10449 handles = []; |
|
10450 |
|
10451 handleCount = ( options.values && options.values.length ) || 1; |
|
10452 |
|
10453 if ( existingHandles.length > handleCount ) { |
|
10454 existingHandles.slice( handleCount ).remove(); |
|
10455 existingHandles = existingHandles.slice( 0, handleCount ); |
|
10456 } |
|
10457 |
|
10458 for ( i = existingHandles.length; i < handleCount; i++ ) { |
|
10459 handles.push( handle ); |
|
10460 } |
|
10461 |
|
10462 this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) ); |
|
10463 |
|
10464 this.handle = this.handles.eq( 0 ); |
|
10465 |
|
10466 this.handles.each(function( i ) { |
|
10467 $( this ).data( "ui-slider-handle-index", i ); |
|
10468 }); |
|
10469 }, |
|
10470 |
|
10471 _createRange: function() { |
|
10472 var options = this.options, |
|
10473 classes = ""; |
|
10474 |
|
10475 if ( options.range ) { |
|
10476 if ( options.range === true ) { |
|
10477 if ( !options.values ) { |
|
10478 options.values = [ this._valueMin(), this._valueMin() ]; |
|
10479 } else if ( options.values.length && options.values.length !== 2 ) { |
|
10480 options.values = [ options.values[0], options.values[0] ]; |
|
10481 } else if ( $.isArray( options.values ) ) { |
|
10482 options.values = options.values.slice(0); |
|
10483 } |
|
10484 } |
|
10485 |
|
10486 if ( !this.range || !this.range.length ) { |
|
10487 this.range = $( "<div></div>" ) |
|
10488 .appendTo( this.element ); |
|
10489 |
|
10490 classes = "ui-slider-range" + |
|
10491 // note: this isn't the most fittingly semantic framework class for this element, |
|
10492 // but worked best visually with a variety of themes |
|
10493 " ui-widget-header ui-corner-all"; |
|
10494 } else { |
|
10495 this.range.removeClass( "ui-slider-range-min ui-slider-range-max" ) |
|
10496 // Handle range switching from true to min/max |
|
10497 .css({ |
|
10498 "left": "", |
|
10499 "bottom": "" |
|
10500 }); |
|
10501 } |
|
10502 |
|
10503 this.range.addClass( classes + |
|
10504 ( ( options.range === "min" || options.range === "max" ) ? " ui-slider-range-" + options.range : "" ) ); |
|
10505 } else { |
|
10506 if ( this.range ) { |
|
10507 this.range.remove(); |
|
10508 } |
|
10509 this.range = null; |
|
10510 } |
|
10511 }, |
|
10512 |
|
10513 _setupEvents: function() { |
|
10514 var elements = this.handles.add( this.range ).filter( "a" ); |
|
10515 this._off( elements ); |
|
10516 this._on( elements, this._handleEvents ); |
|
10517 this._hoverable( elements ); |
|
10518 this._focusable( elements ); |
|
10519 }, |
|
10520 |
|
10521 _destroy: function() { |
|
10522 this.handles.remove(); |
|
10523 if ( this.range ) { |
|
10524 this.range.remove(); |
|
10525 } |
|
10526 |
|
10527 this.element |
|
10528 .removeClass( "ui-slider" + |
|
10529 " ui-slider-horizontal" + |
|
10530 " ui-slider-vertical" + |
|
10531 " ui-widget" + |
|
10532 " ui-widget-content" + |
|
10533 " ui-corner-all" ); |
|
10534 |
|
10535 this._mouseDestroy(); |
|
10536 }, |
|
10537 |
|
10538 _mouseCapture: function( event ) { |
|
10539 var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle, |
|
10540 that = this, |
|
10541 o = this.options; |
|
10542 |
|
10543 if ( o.disabled ) { |
|
10544 return false; |
|
10545 } |
|
10546 |
|
10547 this.elementSize = { |
|
10548 width: this.element.outerWidth(), |
|
10549 height: this.element.outerHeight() |
|
10550 }; |
|
10551 this.elementOffset = this.element.offset(); |
|
10552 |
|
10553 position = { x: event.pageX, y: event.pageY }; |
|
10554 normValue = this._normValueFromMouse( position ); |
|
10555 distance = this._valueMax() - this._valueMin() + 1; |
|
10556 this.handles.each(function( i ) { |
|
10557 var thisDistance = Math.abs( normValue - that.values(i) ); |
|
10558 if (( distance > thisDistance ) || |
|
10559 ( distance === thisDistance && |
|
10560 (i === that._lastChangedValue || that.values(i) === o.min ))) { |
|
10561 distance = thisDistance; |
|
10562 closestHandle = $( this ); |
|
10563 index = i; |
|
10564 } |
|
10565 }); |
|
10566 |
|
10567 allowed = this._start( event, index ); |
|
10568 if ( allowed === false ) { |
|
10569 return false; |
|
10570 } |
|
10571 this._mouseSliding = true; |
|
10572 |
|
10573 this._handleIndex = index; |
|
10574 |
|
10575 closestHandle |
|
10576 .addClass( "ui-state-active" ) |
|
10577 .focus(); |
|
10578 |
|
10579 offset = closestHandle.offset(); |
|
10580 mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" ); |
|
10581 this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : { |
|
10582 left: event.pageX - offset.left - ( closestHandle.width() / 2 ), |
|
10583 top: event.pageY - offset.top - |
|
10584 ( closestHandle.height() / 2 ) - |
|
10585 ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) - |
|
10586 ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) + |
|
10587 ( parseInt( closestHandle.css("marginTop"), 10 ) || 0) |
|
10588 }; |
|
10589 |
|
10590 if ( !this.handles.hasClass( "ui-state-hover" ) ) { |
|
10591 this._slide( event, index, normValue ); |
|
10592 } |
|
10593 this._animateOff = true; |
|
10594 return true; |
|
10595 }, |
|
10596 |
|
10597 _mouseStart: function() { |
|
10598 return true; |
|
10599 }, |
|
10600 |
|
10601 _mouseDrag: function( event ) { |
|
10602 var position = { x: event.pageX, y: event.pageY }, |
|
10603 normValue = this._normValueFromMouse( position ); |
|
10604 |
|
10605 this._slide( event, this._handleIndex, normValue ); |
|
10606 |
|
10607 return false; |
|
10608 }, |
|
10609 |
|
10610 _mouseStop: function( event ) { |
|
10611 this.handles.removeClass( "ui-state-active" ); |
|
10612 this._mouseSliding = false; |
|
10613 |
|
10614 this._stop( event, this._handleIndex ); |
|
10615 this._change( event, this._handleIndex ); |
|
10616 |
|
10617 this._handleIndex = null; |
|
10618 this._clickOffset = null; |
|
10619 this._animateOff = false; |
|
10620 |
|
10621 return false; |
|
10622 }, |
|
10623 |
|
10624 _detectOrientation: function() { |
|
10625 this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal"; |
|
10626 }, |
|
10627 |
|
10628 _normValueFromMouse: function( position ) { |
|
10629 var pixelTotal, |
|
10630 pixelMouse, |
|
10631 percentMouse, |
|
10632 valueTotal, |
|
10633 valueMouse; |
|
10634 |
|
10635 if ( this.orientation === "horizontal" ) { |
|
10636 pixelTotal = this.elementSize.width; |
|
10637 pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 ); |
|
10638 } else { |
|
10639 pixelTotal = this.elementSize.height; |
|
10640 pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 ); |
|
10641 } |
|
10642 |
|
10643 percentMouse = ( pixelMouse / pixelTotal ); |
|
10644 if ( percentMouse > 1 ) { |
|
10645 percentMouse = 1; |
|
10646 } |
|
10647 if ( percentMouse < 0 ) { |
|
10648 percentMouse = 0; |
|
10649 } |
|
10650 if ( this.orientation === "vertical" ) { |
|
10651 percentMouse = 1 - percentMouse; |
|
10652 } |
|
10653 |
|
10654 valueTotal = this._valueMax() - this._valueMin(); |
|
10655 valueMouse = this._valueMin() + percentMouse * valueTotal; |
|
10656 |
|
10657 return this._trimAlignValue( valueMouse ); |
|
10658 }, |
|
10659 |
|
10660 _start: function( event, index ) { |
|
10661 var uiHash = { |
|
10662 handle: this.handles[ index ], |
|
10663 value: this.value() |
|
10664 }; |
|
10665 if ( this.options.values && this.options.values.length ) { |
|
10666 uiHash.value = this.values( index ); |
|
10667 uiHash.values = this.values(); |
|
10668 } |
|
10669 return this._trigger( "start", event, uiHash ); |
|
10670 }, |
|
10671 |
|
10672 _slide: function( event, index, newVal ) { |
|
10673 var otherVal, |
|
10674 newValues, |
|
10675 allowed; |
|
10676 |
|
10677 if ( this.options.values && this.options.values.length ) { |
|
10678 otherVal = this.values( index ? 0 : 1 ); |
|
10679 |
|
10680 if ( ( this.options.values.length === 2 && this.options.range === true ) && |
|
10681 ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) ) |
|
10682 ) { |
|
10683 newVal = otherVal; |
|
10684 } |
|
10685 |
|
10686 if ( newVal !== this.values( index ) ) { |
|
10687 newValues = this.values(); |
|
10688 newValues[ index ] = newVal; |
|
10689 // A slide can be canceled by returning false from the slide callback |
|
10690 allowed = this._trigger( "slide", event, { |
|
10691 handle: this.handles[ index ], |
|
10692 value: newVal, |
|
10693 values: newValues |
|
10694 } ); |
|
10695 otherVal = this.values( index ? 0 : 1 ); |
|
10696 if ( allowed !== false ) { |
|
10697 this.values( index, newVal ); |
|
10698 } |
|
10699 } |
|
10700 } else { |
|
10701 if ( newVal !== this.value() ) { |
|
10702 // A slide can be canceled by returning false from the slide callback |
|
10703 allowed = this._trigger( "slide", event, { |
|
10704 handle: this.handles[ index ], |
|
10705 value: newVal |
|
10706 } ); |
|
10707 if ( allowed !== false ) { |
|
10708 this.value( newVal ); |
|
10709 } |
|
10710 } |
|
10711 } |
|
10712 }, |
|
10713 |
|
10714 _stop: function( event, index ) { |
|
10715 var uiHash = { |
|
10716 handle: this.handles[ index ], |
|
10717 value: this.value() |
|
10718 }; |
|
10719 if ( this.options.values && this.options.values.length ) { |
|
10720 uiHash.value = this.values( index ); |
|
10721 uiHash.values = this.values(); |
|
10722 } |
|
10723 |
|
10724 this._trigger( "stop", event, uiHash ); |
|
10725 }, |
|
10726 |
|
10727 _change: function( event, index ) { |
|
10728 if ( !this._keySliding && !this._mouseSliding ) { |
|
10729 var uiHash = { |
|
10730 handle: this.handles[ index ], |
|
10731 value: this.value() |
|
10732 }; |
|
10733 if ( this.options.values && this.options.values.length ) { |
|
10734 uiHash.value = this.values( index ); |
|
10735 uiHash.values = this.values(); |
|
10736 } |
|
10737 |
|
10738 //store the last changed value index for reference when handles overlap |
|
10739 this._lastChangedValue = index; |
|
10740 |
|
10741 this._trigger( "change", event, uiHash ); |
|
10742 } |
|
10743 }, |
|
10744 |
|
10745 value: function( newValue ) { |
|
10746 if ( arguments.length ) { |
|
10747 this.options.value = this._trimAlignValue( newValue ); |
|
10748 this._refreshValue(); |
|
10749 this._change( null, 0 ); |
|
10750 return; |
|
10751 } |
|
10752 |
|
10753 return this._value(); |
|
10754 }, |
|
10755 |
|
10756 values: function( index, newValue ) { |
|
10757 var vals, |
|
10758 newValues, |
|
10759 i; |
|
10760 |
|
10761 if ( arguments.length > 1 ) { |
|
10762 this.options.values[ index ] = this._trimAlignValue( newValue ); |
|
10763 this._refreshValue(); |
|
10764 this._change( null, index ); |
|
10765 return; |
|
10766 } |
|
10767 |
|
10768 if ( arguments.length ) { |
|
10769 if ( $.isArray( arguments[ 0 ] ) ) { |
|
10770 vals = this.options.values; |
|
10771 newValues = arguments[ 0 ]; |
|
10772 for ( i = 0; i < vals.length; i += 1 ) { |
|
10773 vals[ i ] = this._trimAlignValue( newValues[ i ] ); |
|
10774 this._change( null, i ); |
|
10775 } |
|
10776 this._refreshValue(); |
|
10777 } else { |
|
10778 if ( this.options.values && this.options.values.length ) { |
|
10779 return this._values( index ); |
|
10780 } else { |
|
10781 return this.value(); |
|
10782 } |
|
10783 } |
|
10784 } else { |
|
10785 return this._values(); |
|
10786 } |
|
10787 }, |
|
10788 |
|
10789 _setOption: function( key, value ) { |
|
10790 var i, |
|
10791 valsLength = 0; |
|
10792 |
|
10793 if ( key === "range" && this.options.range === true ) { |
|
10794 if ( value === "min" ) { |
|
10795 this.options.value = this._values( 0 ); |
|
10796 this.options.values = null; |
|
10797 } else if ( value === "max" ) { |
|
10798 this.options.value = this._values( this.options.values.length-1 ); |
|
10799 this.options.values = null; |
|
10800 } |
|
10801 } |
|
10802 |
|
10803 if ( $.isArray( this.options.values ) ) { |
|
10804 valsLength = this.options.values.length; |
|
10805 } |
|
10806 |
|
10807 $.Widget.prototype._setOption.apply( this, arguments ); |
|
10808 |
|
10809 switch ( key ) { |
|
10810 case "orientation": |
|
10811 this._detectOrientation(); |
|
10812 this.element |
|
10813 .removeClass( "ui-slider-horizontal ui-slider-vertical" ) |
|
10814 .addClass( "ui-slider-" + this.orientation ); |
|
10815 this._refreshValue(); |
|
10816 break; |
|
10817 case "value": |
|
10818 this._animateOff = true; |
|
10819 this._refreshValue(); |
|
10820 this._change( null, 0 ); |
|
10821 this._animateOff = false; |
|
10822 break; |
|
10823 case "values": |
|
10824 this._animateOff = true; |
|
10825 this._refreshValue(); |
|
10826 for ( i = 0; i < valsLength; i += 1 ) { |
|
10827 this._change( null, i ); |
|
10828 } |
|
10829 this._animateOff = false; |
|
10830 break; |
|
10831 case "min": |
|
10832 case "max": |
|
10833 this._animateOff = true; |
|
10834 this._refreshValue(); |
|
10835 this._animateOff = false; |
|
10836 break; |
|
10837 case "range": |
|
10838 this._animateOff = true; |
|
10839 this._refresh(); |
|
10840 this._animateOff = false; |
|
10841 break; |
|
10842 } |
|
10843 }, |
|
10844 |
|
10845 //internal value getter |
|
10846 // _value() returns value trimmed by min and max, aligned by step |
|
10847 _value: function() { |
|
10848 var val = this.options.value; |
|
10849 val = this._trimAlignValue( val ); |
|
10850 |
|
10851 return val; |
|
10852 }, |
|
10853 |
|
10854 //internal values getter |
|
10855 // _values() returns array of values trimmed by min and max, aligned by step |
|
10856 // _values( index ) returns single value trimmed by min and max, aligned by step |
|
10857 _values: function( index ) { |
|
10858 var val, |
|
10859 vals, |
|
10860 i; |
|
10861 |
|
10862 if ( arguments.length ) { |
|
10863 val = this.options.values[ index ]; |
|
10864 val = this._trimAlignValue( val ); |
|
10865 |
|
10866 return val; |
|
10867 } else if ( this.options.values && this.options.values.length ) { |
|
10868 // .slice() creates a copy of the array |
|
10869 // this copy gets trimmed by min and max and then returned |
|
10870 vals = this.options.values.slice(); |
|
10871 for ( i = 0; i < vals.length; i+= 1) { |
|
10872 vals[ i ] = this._trimAlignValue( vals[ i ] ); |
|
10873 } |
|
10874 |
|
10875 return vals; |
|
10876 } else { |
|
10877 return []; |
|
10878 } |
|
10879 }, |
|
10880 |
|
10881 // returns the step-aligned value that val is closest to, between (inclusive) min and max |
|
10882 _trimAlignValue: function( val ) { |
|
10883 if ( val <= this._valueMin() ) { |
|
10884 return this._valueMin(); |
|
10885 } |
|
10886 if ( val >= this._valueMax() ) { |
|
10887 return this._valueMax(); |
|
10888 } |
|
10889 var step = ( this.options.step > 0 ) ? this.options.step : 1, |
|
10890 valModStep = (val - this._valueMin()) % step, |
|
10891 alignValue = val - valModStep; |
|
10892 |
|
10893 if ( Math.abs(valModStep) * 2 >= step ) { |
|
10894 alignValue += ( valModStep > 0 ) ? step : ( -step ); |
|
10895 } |
|
10896 |
|
10897 // Since JavaScript has problems with large floats, round |
|
10898 // the final value to 5 digits after the decimal point (see #4124) |
|
10899 return parseFloat( alignValue.toFixed(5) ); |
|
10900 }, |
|
10901 |
|
10902 _valueMin: function() { |
|
10903 return this.options.min; |
|
10904 }, |
|
10905 |
|
10906 _valueMax: function() { |
|
10907 return this.options.max; |
|
10908 }, |
|
10909 |
|
10910 _refreshValue: function() { |
|
10911 var lastValPercent, valPercent, value, valueMin, valueMax, |
|
10912 oRange = this.options.range, |
|
10913 o = this.options, |
|
10914 that = this, |
|
10915 animate = ( !this._animateOff ) ? o.animate : false, |
|
10916 _set = {}; |
|
10917 |
|
10918 if ( this.options.values && this.options.values.length ) { |
|
10919 this.handles.each(function( i ) { |
|
10920 valPercent = ( that.values(i) - that._valueMin() ) / ( that._valueMax() - that._valueMin() ) * 100; |
|
10921 _set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; |
|
10922 $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); |
|
10923 if ( that.options.range === true ) { |
|
10924 if ( that.orientation === "horizontal" ) { |
|
10925 if ( i === 0 ) { |
|
10926 that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate ); |
|
10927 } |
|
10928 if ( i === 1 ) { |
|
10929 that.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } ); |
|
10930 } |
|
10931 } else { |
|
10932 if ( i === 0 ) { |
|
10933 that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate ); |
|
10934 } |
|
10935 if ( i === 1 ) { |
|
10936 that.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } ); |
|
10937 } |
|
10938 } |
|
10939 } |
|
10940 lastValPercent = valPercent; |
|
10941 }); |
|
10942 } else { |
|
10943 value = this.value(); |
|
10944 valueMin = this._valueMin(); |
|
10945 valueMax = this._valueMax(); |
|
10946 valPercent = ( valueMax !== valueMin ) ? |
|
10947 ( value - valueMin ) / ( valueMax - valueMin ) * 100 : |
|
10948 0; |
|
10949 _set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; |
|
10950 this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); |
|
10951 |
|
10952 if ( oRange === "min" && this.orientation === "horizontal" ) { |
|
10953 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate ); |
|
10954 } |
|
10955 if ( oRange === "max" && this.orientation === "horizontal" ) { |
|
10956 this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } ); |
|
10957 } |
|
10958 if ( oRange === "min" && this.orientation === "vertical" ) { |
|
10959 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate ); |
|
10960 } |
|
10961 if ( oRange === "max" && this.orientation === "vertical" ) { |
|
10962 this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } ); |
|
10963 } |
|
10964 } |
|
10965 }, |
|
10966 |
|
10967 _handleEvents: { |
|
10968 keydown: function( event ) { |
|
10969 var allowed, curVal, newVal, step, |
|
10970 index = $( event.target ).data( "ui-slider-handle-index" ); |
|
10971 |
|
10972 switch ( event.keyCode ) { |
|
10973 case $.ui.keyCode.HOME: |
|
10974 case $.ui.keyCode.END: |
|
10975 case $.ui.keyCode.PAGE_UP: |
|
10976 case $.ui.keyCode.PAGE_DOWN: |
|
10977 case $.ui.keyCode.UP: |
|
10978 case $.ui.keyCode.RIGHT: |
|
10979 case $.ui.keyCode.DOWN: |
|
10980 case $.ui.keyCode.LEFT: |
|
10981 event.preventDefault(); |
|
10982 if ( !this._keySliding ) { |
|
10983 this._keySliding = true; |
|
10984 $( event.target ).addClass( "ui-state-active" ); |
|
10985 allowed = this._start( event, index ); |
|
10986 if ( allowed === false ) { |
|
10987 return; |
|
10988 } |
|
10989 } |
|
10990 break; |
|
10991 } |
|
10992 |
|
10993 step = this.options.step; |
|
10994 if ( this.options.values && this.options.values.length ) { |
|
10995 curVal = newVal = this.values( index ); |
|
10996 } else { |
|
10997 curVal = newVal = this.value(); |
|
10998 } |
|
10999 |
|
11000 switch ( event.keyCode ) { |
|
11001 case $.ui.keyCode.HOME: |
|
11002 newVal = this._valueMin(); |
|
11003 break; |
|
11004 case $.ui.keyCode.END: |
|
11005 newVal = this._valueMax(); |
|
11006 break; |
|
11007 case $.ui.keyCode.PAGE_UP: |
|
11008 newVal = this._trimAlignValue( curVal + ( (this._valueMax() - this._valueMin()) / numPages ) ); |
|
11009 break; |
|
11010 case $.ui.keyCode.PAGE_DOWN: |
|
11011 newVal = this._trimAlignValue( curVal - ( (this._valueMax() - this._valueMin()) / numPages ) ); |
|
11012 break; |
|
11013 case $.ui.keyCode.UP: |
|
11014 case $.ui.keyCode.RIGHT: |
|
11015 if ( curVal === this._valueMax() ) { |
|
11016 return; |
|
11017 } |
|
11018 newVal = this._trimAlignValue( curVal + step ); |
|
11019 break; |
|
11020 case $.ui.keyCode.DOWN: |
|
11021 case $.ui.keyCode.LEFT: |
|
11022 if ( curVal === this._valueMin() ) { |
|
11023 return; |
|
11024 } |
|
11025 newVal = this._trimAlignValue( curVal - step ); |
|
11026 break; |
|
11027 } |
|
11028 |
|
11029 this._slide( event, index, newVal ); |
|
11030 }, |
|
11031 click: function( event ) { |
|
11032 event.preventDefault(); |
|
11033 }, |
|
11034 keyup: function( event ) { |
|
11035 var index = $( event.target ).data( "ui-slider-handle-index" ); |
|
11036 |
|
11037 if ( this._keySliding ) { |
|
11038 this._keySliding = false; |
|
11039 this._stop( event, index ); |
|
11040 this._change( event, index ); |
|
11041 $( event.target ).removeClass( "ui-state-active" ); |
|
11042 } |
|
11043 } |
|
11044 } |
|
11045 |
|
11046 }); |
|
11047 |
|
11048 }(jQuery)); |
|
11049 (function( $ ) { |
|
11050 |
|
11051 function modifier( fn ) { |
|
11052 return function() { |
|
11053 var previous = this.element.val(); |
|
11054 fn.apply( this, arguments ); |
|
11055 this._refresh(); |
|
11056 if ( previous !== this.element.val() ) { |
|
11057 this._trigger( "change" ); |
|
11058 } |
|
11059 }; |
|
11060 } |
|
11061 |
|
11062 $.widget( "ui.spinner", { |
|
11063 version: "1.10.4", |
|
11064 defaultElement: "<input>", |
|
11065 widgetEventPrefix: "spin", |
|
11066 options: { |
|
11067 culture: null, |
|
11068 icons: { |
|
11069 down: "ui-icon-triangle-1-s", |
|
11070 up: "ui-icon-triangle-1-n" |
|
11071 }, |
|
11072 incremental: true, |
|
11073 max: null, |
|
11074 min: null, |
|
11075 numberFormat: null, |
|
11076 page: 10, |
|
11077 step: 1, |
|
11078 |
|
11079 change: null, |
|
11080 spin: null, |
|
11081 start: null, |
|
11082 stop: null |
|
11083 }, |
|
11084 |
|
11085 _create: function() { |
|
11086 // handle string values that need to be parsed |
|
11087 this._setOption( "max", this.options.max ); |
|
11088 this._setOption( "min", this.options.min ); |
|
11089 this._setOption( "step", this.options.step ); |
|
11090 |
|
11091 // Only format if there is a value, prevents the field from being marked |
|
11092 // as invalid in Firefox, see #9573. |
|
11093 if ( this.value() !== "" ) { |
|
11094 // Format the value, but don't constrain. |
|
11095 this._value( this.element.val(), true ); |
|
11096 } |
|
11097 |
|
11098 this._draw(); |
|
11099 this._on( this._events ); |
|
11100 this._refresh(); |
|
11101 |
|
11102 // turning off autocomplete prevents the browser from remembering the |
|
11103 // value when navigating through history, so we re-enable autocomplete |
|
11104 // if the page is unloaded before the widget is destroyed. #7790 |
|
11105 this._on( this.window, { |
|
11106 beforeunload: function() { |
|
11107 this.element.removeAttr( "autocomplete" ); |
|
11108 } |
|
11109 }); |
|
11110 }, |
|
11111 |
|
11112 _getCreateOptions: function() { |
|
11113 var options = {}, |
|
11114 element = this.element; |
|
11115 |
|
11116 $.each( [ "min", "max", "step" ], function( i, option ) { |
|
11117 var value = element.attr( option ); |
|
11118 if ( value !== undefined && value.length ) { |
|
11119 options[ option ] = value; |
|
11120 } |
|
11121 }); |
|
11122 |
|
11123 return options; |
|
11124 }, |
|
11125 |
|
11126 _events: { |
|
11127 keydown: function( event ) { |
|
11128 if ( this._start( event ) && this._keydown( event ) ) { |
|
11129 event.preventDefault(); |
|
11130 } |
|
11131 }, |
|
11132 keyup: "_stop", |
|
11133 focus: function() { |
|
11134 this.previous = this.element.val(); |
|
11135 }, |
|
11136 blur: function( event ) { |
|
11137 if ( this.cancelBlur ) { |
|
11138 delete this.cancelBlur; |
|
11139 return; |
|
11140 } |
|
11141 |
|
11142 this._stop(); |
|
11143 this._refresh(); |
|
11144 if ( this.previous !== this.element.val() ) { |
|
11145 this._trigger( "change", event ); |
|
11146 } |
|
11147 }, |
|
11148 mousewheel: function( event, delta ) { |
|
11149 if ( !delta ) { |
|
11150 return; |
|
11151 } |
|
11152 if ( !this.spinning && !this._start( event ) ) { |
|
11153 return false; |
|
11154 } |
|
11155 |
|
11156 this._spin( (delta > 0 ? 1 : -1) * this.options.step, event ); |
|
11157 clearTimeout( this.mousewheelTimer ); |
|
11158 this.mousewheelTimer = this._delay(function() { |
|
11159 if ( this.spinning ) { |
|
11160 this._stop( event ); |
|
11161 } |
|
11162 }, 100 ); |
|
11163 event.preventDefault(); |
|
11164 }, |
|
11165 "mousedown .ui-spinner-button": function( event ) { |
|
11166 var previous; |
|
11167 |
|
11168 // We never want the buttons to have focus; whenever the user is |
|
11169 // interacting with the spinner, the focus should be on the input. |
|
11170 // If the input is focused then this.previous is properly set from |
|
11171 // when the input first received focus. If the input is not focused |
|
11172 // then we need to set this.previous based on the value before spinning. |
|
11173 previous = this.element[0] === this.document[0].activeElement ? |
|
11174 this.previous : this.element.val(); |
|
11175 function checkFocus() { |
|
11176 var isActive = this.element[0] === this.document[0].activeElement; |
|
11177 if ( !isActive ) { |
|
11178 this.element.focus(); |
|
11179 this.previous = previous; |
|
11180 // support: IE |
|
11181 // IE sets focus asynchronously, so we need to check if focus |
|
11182 // moved off of the input because the user clicked on the button. |
|
11183 this._delay(function() { |
|
11184 this.previous = previous; |
|
11185 }); |
|
11186 } |
|
11187 } |
|
11188 |
|
11189 // ensure focus is on (or stays on) the text field |
|
11190 event.preventDefault(); |
|
11191 checkFocus.call( this ); |
|
11192 |
|
11193 // support: IE |
|
11194 // IE doesn't prevent moving focus even with event.preventDefault() |
|
11195 // so we set a flag to know when we should ignore the blur event |
|
11196 // and check (again) if focus moved off of the input. |
|
11197 this.cancelBlur = true; |
|
11198 this._delay(function() { |
|
11199 delete this.cancelBlur; |
|
11200 checkFocus.call( this ); |
|
11201 }); |
|
11202 |
|
11203 if ( this._start( event ) === false ) { |
|
11204 return; |
|
11205 } |
|
11206 |
|
11207 this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event ); |
|
11208 }, |
|
11209 "mouseup .ui-spinner-button": "_stop", |
|
11210 "mouseenter .ui-spinner-button": function( event ) { |
|
11211 // button will add ui-state-active if mouse was down while mouseleave and kept down |
|
11212 if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) { |
|
11213 return; |
|
11214 } |
|
11215 |
|
11216 if ( this._start( event ) === false ) { |
|
11217 return false; |
|
11218 } |
|
11219 this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event ); |
|
11220 }, |
|
11221 // TODO: do we really want to consider this a stop? |
|
11222 // shouldn't we just stop the repeater and wait until mouseup before |
|
11223 // we trigger the stop event? |
|
11224 "mouseleave .ui-spinner-button": "_stop" |
|
11225 }, |
|
11226 |
|
11227 _draw: function() { |
|
11228 var uiSpinner = this.uiSpinner = this.element |
|
11229 .addClass( "ui-spinner-input" ) |
|
11230 .attr( "autocomplete", "off" ) |
|
11231 .wrap( this._uiSpinnerHtml() ) |
|
11232 .parent() |
|
11233 // add buttons |
|
11234 .append( this._buttonHtml() ); |
|
11235 |
|
11236 this.element.attr( "role", "spinbutton" ); |
|
11237 |
|
11238 // button bindings |
|
11239 this.buttons = uiSpinner.find( ".ui-spinner-button" ) |
|
11240 .attr( "tabIndex", -1 ) |
|
11241 .button() |
|
11242 .removeClass( "ui-corner-all" ); |
|
11243 |
|
11244 // IE 6 doesn't understand height: 50% for the buttons |
|
11245 // unless the wrapper has an explicit height |
|
11246 if ( this.buttons.height() > Math.ceil( uiSpinner.height() * 0.5 ) && |
|
11247 uiSpinner.height() > 0 ) { |
|
11248 uiSpinner.height( uiSpinner.height() ); |
|
11249 } |
|
11250 |
|
11251 // disable spinner if element was already disabled |
|
11252 if ( this.options.disabled ) { |
|
11253 this.disable(); |
|
11254 } |
|
11255 }, |
|
11256 |
|
11257 _keydown: function( event ) { |
|
11258 var options = this.options, |
|
11259 keyCode = $.ui.keyCode; |
|
11260 |
|
11261 switch ( event.keyCode ) { |
|
11262 case keyCode.UP: |
|
11263 this._repeat( null, 1, event ); |
|
11264 return true; |
|
11265 case keyCode.DOWN: |
|
11266 this._repeat( null, -1, event ); |
|
11267 return true; |
|
11268 case keyCode.PAGE_UP: |
|
11269 this._repeat( null, options.page, event ); |
|
11270 return true; |
|
11271 case keyCode.PAGE_DOWN: |
|
11272 this._repeat( null, -options.page, event ); |
|
11273 return true; |
|
11274 } |
|
11275 |
|
11276 return false; |
|
11277 }, |
|
11278 |
|
11279 _uiSpinnerHtml: function() { |
|
11280 return "<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>"; |
|
11281 }, |
|
11282 |
|
11283 _buttonHtml: function() { |
|
11284 return "" + |
|
11285 "<a class='ui-spinner-button ui-spinner-up ui-corner-tr'>" + |
|
11286 "<span class='ui-icon " + this.options.icons.up + "'>▲</span>" + |
|
11287 "</a>" + |
|
11288 "<a class='ui-spinner-button ui-spinner-down ui-corner-br'>" + |
|
11289 "<span class='ui-icon " + this.options.icons.down + "'>▼</span>" + |
|
11290 "</a>"; |
|
11291 }, |
|
11292 |
|
11293 _start: function( event ) { |
|
11294 if ( !this.spinning && this._trigger( "start", event ) === false ) { |
|
11295 return false; |
|
11296 } |
|
11297 |
|
11298 if ( !this.counter ) { |
|
11299 this.counter = 1; |
|
11300 } |
|
11301 this.spinning = true; |
|
11302 return true; |
|
11303 }, |
|
11304 |
|
11305 _repeat: function( i, steps, event ) { |
|
11306 i = i || 500; |
|
11307 |
|
11308 clearTimeout( this.timer ); |
|
11309 this.timer = this._delay(function() { |
|
11310 this._repeat( 40, steps, event ); |
|
11311 }, i ); |
|
11312 |
|
11313 this._spin( steps * this.options.step, event ); |
|
11314 }, |
|
11315 |
|
11316 _spin: function( step, event ) { |
|
11317 var value = this.value() || 0; |
|
11318 |
|
11319 if ( !this.counter ) { |
|
11320 this.counter = 1; |
|
11321 } |
|
11322 |
|
11323 value = this._adjustValue( value + step * this._increment( this.counter ) ); |
|
11324 |
|
11325 if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false) { |
|
11326 this._value( value ); |
|
11327 this.counter++; |
|
11328 } |
|
11329 }, |
|
11330 |
|
11331 _increment: function( i ) { |
|
11332 var incremental = this.options.incremental; |
|
11333 |
|
11334 if ( incremental ) { |
|
11335 return $.isFunction( incremental ) ? |
|
11336 incremental( i ) : |
|
11337 Math.floor( i*i*i/50000 - i*i/500 + 17*i/200 + 1 ); |
|
11338 } |
|
11339 |
|
11340 return 1; |
|
11341 }, |
|
11342 |
|
11343 _precision: function() { |
|
11344 var precision = this._precisionOf( this.options.step ); |
|
11345 if ( this.options.min !== null ) { |
|
11346 precision = Math.max( precision, this._precisionOf( this.options.min ) ); |
|
11347 } |
|
11348 return precision; |
|
11349 }, |
|
11350 |
|
11351 _precisionOf: function( num ) { |
|
11352 var str = num.toString(), |
|
11353 decimal = str.indexOf( "." ); |
|
11354 return decimal === -1 ? 0 : str.length - decimal - 1; |
|
11355 }, |
|
11356 |
|
11357 _adjustValue: function( value ) { |
|
11358 var base, aboveMin, |
|
11359 options = this.options; |
|
11360 |
|
11361 // make sure we're at a valid step |
|
11362 // - find out where we are relative to the base (min or 0) |
|
11363 base = options.min !== null ? options.min : 0; |
|
11364 aboveMin = value - base; |
|
11365 // - round to the nearest step |
|
11366 aboveMin = Math.round(aboveMin / options.step) * options.step; |
|
11367 // - rounding is based on 0, so adjust back to our base |
|
11368 value = base + aboveMin; |
|
11369 |
|
11370 // fix precision from bad JS floating point math |
|
11371 value = parseFloat( value.toFixed( this._precision() ) ); |
|
11372 |
|
11373 // clamp the value |
|
11374 if ( options.max !== null && value > options.max) { |
|
11375 return options.max; |
|
11376 } |
|
11377 if ( options.min !== null && value < options.min ) { |
|
11378 return options.min; |
|
11379 } |
|
11380 |
|
11381 return value; |
|
11382 }, |
|
11383 |
|
11384 _stop: function( event ) { |
|
11385 if ( !this.spinning ) { |
|
11386 return; |
|
11387 } |
|
11388 |
|
11389 clearTimeout( this.timer ); |
|
11390 clearTimeout( this.mousewheelTimer ); |
|
11391 this.counter = 0; |
|
11392 this.spinning = false; |
|
11393 this._trigger( "stop", event ); |
|
11394 }, |
|
11395 |
|
11396 _setOption: function( key, value ) { |
|
11397 if ( key === "culture" || key === "numberFormat" ) { |
|
11398 var prevValue = this._parse( this.element.val() ); |
|
11399 this.options[ key ] = value; |
|
11400 this.element.val( this._format( prevValue ) ); |
|
11401 return; |
|
11402 } |
|
11403 |
|
11404 if ( key === "max" || key === "min" || key === "step" ) { |
|
11405 if ( typeof value === "string" ) { |
|
11406 value = this._parse( value ); |
|
11407 } |
|
11408 } |
|
11409 if ( key === "icons" ) { |
|
11410 this.buttons.first().find( ".ui-icon" ) |
|
11411 .removeClass( this.options.icons.up ) |
|
11412 .addClass( value.up ); |
|
11413 this.buttons.last().find( ".ui-icon" ) |
|
11414 .removeClass( this.options.icons.down ) |
|
11415 .addClass( value.down ); |
|
11416 } |
|
11417 |
|
11418 this._super( key, value ); |
|
11419 |
|
11420 if ( key === "disabled" ) { |
|
11421 if ( value ) { |
|
11422 this.element.prop( "disabled", true ); |
|
11423 this.buttons.button( "disable" ); |
|
11424 } else { |
|
11425 this.element.prop( "disabled", false ); |
|
11426 this.buttons.button( "enable" ); |
|
11427 } |
|
11428 } |
|
11429 }, |
|
11430 |
|
11431 _setOptions: modifier(function( options ) { |
|
11432 this._super( options ); |
|
11433 this._value( this.element.val() ); |
|
11434 }), |
|
11435 |
|
11436 _parse: function( val ) { |
|
11437 if ( typeof val === "string" && val !== "" ) { |
|
11438 val = window.Globalize && this.options.numberFormat ? |
|
11439 Globalize.parseFloat( val, 10, this.options.culture ) : +val; |
|
11440 } |
|
11441 return val === "" || isNaN( val ) ? null : val; |
|
11442 }, |
|
11443 |
|
11444 _format: function( value ) { |
|
11445 if ( value === "" ) { |
|
11446 return ""; |
|
11447 } |
|
11448 return window.Globalize && this.options.numberFormat ? |
|
11449 Globalize.format( value, this.options.numberFormat, this.options.culture ) : |
|
11450 value; |
|
11451 }, |
|
11452 |
|
11453 _refresh: function() { |
|
11454 this.element.attr({ |
|
11455 "aria-valuemin": this.options.min, |
|
11456 "aria-valuemax": this.options.max, |
|
11457 // TODO: what should we do with values that can't be parsed? |
|
11458 "aria-valuenow": this._parse( this.element.val() ) |
|
11459 }); |
|
11460 }, |
|
11461 |
|
11462 // update the value without triggering change |
|
11463 _value: function( value, allowAny ) { |
|
11464 var parsed; |
|
11465 if ( value !== "" ) { |
|
11466 parsed = this._parse( value ); |
|
11467 if ( parsed !== null ) { |
|
11468 if ( !allowAny ) { |
|
11469 parsed = this._adjustValue( parsed ); |
|
11470 } |
|
11471 value = this._format( parsed ); |
|
11472 } |
|
11473 } |
|
11474 this.element.val( value ); |
|
11475 this._refresh(); |
|
11476 }, |
|
11477 |
|
11478 _destroy: function() { |
|
11479 this.element |
|
11480 .removeClass( "ui-spinner-input" ) |
|
11481 .prop( "disabled", false ) |
|
11482 .removeAttr( "autocomplete" ) |
|
11483 .removeAttr( "role" ) |
|
11484 .removeAttr( "aria-valuemin" ) |
|
11485 .removeAttr( "aria-valuemax" ) |
|
11486 .removeAttr( "aria-valuenow" ); |
|
11487 this.uiSpinner.replaceWith( this.element ); |
|
11488 }, |
|
11489 |
|
11490 stepUp: modifier(function( steps ) { |
|
11491 this._stepUp( steps ); |
|
11492 }), |
|
11493 _stepUp: function( steps ) { |
|
11494 if ( this._start() ) { |
|
11495 this._spin( (steps || 1) * this.options.step ); |
|
11496 this._stop(); |
|
11497 } |
|
11498 }, |
|
11499 |
|
11500 stepDown: modifier(function( steps ) { |
|
11501 this._stepDown( steps ); |
|
11502 }), |
|
11503 _stepDown: function( steps ) { |
|
11504 if ( this._start() ) { |
|
11505 this._spin( (steps || 1) * -this.options.step ); |
|
11506 this._stop(); |
|
11507 } |
|
11508 }, |
|
11509 |
|
11510 pageUp: modifier(function( pages ) { |
|
11511 this._stepUp( (pages || 1) * this.options.page ); |
|
11512 }), |
|
11513 |
|
11514 pageDown: modifier(function( pages ) { |
|
11515 this._stepDown( (pages || 1) * this.options.page ); |
|
11516 }), |
|
11517 |
|
11518 value: function( newVal ) { |
|
11519 if ( !arguments.length ) { |
|
11520 return this._parse( this.element.val() ); |
|
11521 } |
|
11522 modifier( this._value ).call( this, newVal ); |
|
11523 }, |
|
11524 |
|
11525 widget: function() { |
|
11526 return this.uiSpinner; |
|
11527 } |
|
11528 }); |
|
11529 |
|
11530 }( jQuery ) ); |
|
11531 (function( $, undefined ) { |
|
11532 |
|
11533 var tabId = 0, |
|
11534 rhash = /#.*$/; |
|
11535 |
|
11536 function getNextTabId() { |
|
11537 return ++tabId; |
|
11538 } |
|
11539 |
|
11540 function isLocal( anchor ) { |
|
11541 // support: IE7 |
|
11542 // IE7 doesn't normalize the href property when set via script (#9317) |
|
11543 anchor = anchor.cloneNode( false ); |
|
11544 |
|
11545 return anchor.hash.length > 1 && |
|
11546 decodeURIComponent( anchor.href.replace( rhash, "" ) ) === |
|
11547 decodeURIComponent( location.href.replace( rhash, "" ) ); |
|
11548 } |
|
11549 |
|
11550 $.widget( "ui.tabs", { |
|
11551 version: "1.10.4", |
|
11552 delay: 300, |
|
11553 options: { |
|
11554 active: null, |
|
11555 collapsible: false, |
|
11556 event: "click", |
|
11557 heightStyle: "content", |
|
11558 hide: null, |
|
11559 show: null, |
|
11560 |
|
11561 // callbacks |
|
11562 activate: null, |
|
11563 beforeActivate: null, |
|
11564 beforeLoad: null, |
|
11565 load: null |
|
11566 }, |
|
11567 |
|
11568 _create: function() { |
|
11569 var that = this, |
|
11570 options = this.options; |
|
11571 |
|
11572 this.running = false; |
|
11573 |
|
11574 this.element |
|
11575 .addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" ) |
|
11576 .toggleClass( "ui-tabs-collapsible", options.collapsible ) |
|
11577 // Prevent users from focusing disabled tabs via click |
|
11578 .delegate( ".ui-tabs-nav > li", "mousedown" + this.eventNamespace, function( event ) { |
|
11579 if ( $( this ).is( ".ui-state-disabled" ) ) { |
|
11580 event.preventDefault(); |
|
11581 } |
|
11582 }) |
|
11583 // support: IE <9 |
|
11584 // Preventing the default action in mousedown doesn't prevent IE |
|
11585 // from focusing the element, so if the anchor gets focused, blur. |
|
11586 // We don't have to worry about focusing the previously focused |
|
11587 // element since clicking on a non-focusable element should focus |
|
11588 // the body anyway. |
|
11589 .delegate( ".ui-tabs-anchor", "focus" + this.eventNamespace, function() { |
|
11590 if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) { |
|
11591 this.blur(); |
|
11592 } |
|
11593 }); |
|
11594 |
|
11595 this._processTabs(); |
|
11596 options.active = this._initialActive(); |
|
11597 |
|
11598 // Take disabling tabs via class attribute from HTML |
|
11599 // into account and update option properly. |
|
11600 if ( $.isArray( options.disabled ) ) { |
|
11601 options.disabled = $.unique( options.disabled.concat( |
|
11602 $.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) { |
|
11603 return that.tabs.index( li ); |
|
11604 }) |
|
11605 ) ).sort(); |
|
11606 } |
|
11607 |
|
11608 // check for length avoids error when initializing empty list |
|
11609 if ( this.options.active !== false && this.anchors.length ) { |
|
11610 this.active = this._findActive( options.active ); |
|
11611 } else { |
|
11612 this.active = $(); |
|
11613 } |
|
11614 |
|
11615 this._refresh(); |
|
11616 |
|
11617 if ( this.active.length ) { |
|
11618 this.load( options.active ); |
|
11619 } |
|
11620 }, |
|
11621 |
|
11622 _initialActive: function() { |
|
11623 var active = this.options.active, |
|
11624 collapsible = this.options.collapsible, |
|
11625 locationHash = location.hash.substring( 1 ); |
|
11626 |
|
11627 if ( active === null ) { |
|
11628 // check the fragment identifier in the URL |
|
11629 if ( locationHash ) { |
|
11630 this.tabs.each(function( i, tab ) { |
|
11631 if ( $( tab ).attr( "aria-controls" ) === locationHash ) { |
|
11632 active = i; |
|
11633 return false; |
|
11634 } |
|
11635 }); |
|
11636 } |
|
11637 |
|
11638 // check for a tab marked active via a class |
|
11639 if ( active === null ) { |
|
11640 active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) ); |
|
11641 } |
|
11642 |
|
11643 // no active tab, set to false |
|
11644 if ( active === null || active === -1 ) { |
|
11645 active = this.tabs.length ? 0 : false; |
|
11646 } |
|
11647 } |
|
11648 |
|
11649 // handle numbers: negative, out of range |
|
11650 if ( active !== false ) { |
|
11651 active = this.tabs.index( this.tabs.eq( active ) ); |
|
11652 if ( active === -1 ) { |
|
11653 active = collapsible ? false : 0; |
|
11654 } |
|
11655 } |
|
11656 |
|
11657 // don't allow collapsible: false and active: false |
|
11658 if ( !collapsible && active === false && this.anchors.length ) { |
|
11659 active = 0; |
|
11660 } |
|
11661 |
|
11662 return active; |
|
11663 }, |
|
11664 |
|
11665 _getCreateEventData: function() { |
|
11666 return { |
|
11667 tab: this.active, |
|
11668 panel: !this.active.length ? $() : this._getPanelForTab( this.active ) |
|
11669 }; |
|
11670 }, |
|
11671 |
|
11672 _tabKeydown: function( event ) { |
|
11673 var focusedTab = $( this.document[0].activeElement ).closest( "li" ), |
|
11674 selectedIndex = this.tabs.index( focusedTab ), |
|
11675 goingForward = true; |
|
11676 |
|
11677 if ( this._handlePageNav( event ) ) { |
|
11678 return; |
|
11679 } |
|
11680 |
|
11681 switch ( event.keyCode ) { |
|
11682 case $.ui.keyCode.RIGHT: |
|
11683 case $.ui.keyCode.DOWN: |
|
11684 selectedIndex++; |
|
11685 break; |
|
11686 case $.ui.keyCode.UP: |
|
11687 case $.ui.keyCode.LEFT: |
|
11688 goingForward = false; |
|
11689 selectedIndex--; |
|
11690 break; |
|
11691 case $.ui.keyCode.END: |
|
11692 selectedIndex = this.anchors.length - 1; |
|
11693 break; |
|
11694 case $.ui.keyCode.HOME: |
|
11695 selectedIndex = 0; |
|
11696 break; |
|
11697 case $.ui.keyCode.SPACE: |
|
11698 // Activate only, no collapsing |
|
11699 event.preventDefault(); |
|
11700 clearTimeout( this.activating ); |
|
11701 this._activate( selectedIndex ); |
|
11702 return; |
|
11703 case $.ui.keyCode.ENTER: |
|
11704 // Toggle (cancel delayed activation, allow collapsing) |
|
11705 event.preventDefault(); |
|
11706 clearTimeout( this.activating ); |
|
11707 // Determine if we should collapse or activate |
|
11708 this._activate( selectedIndex === this.options.active ? false : selectedIndex ); |
|
11709 return; |
|
11710 default: |
|
11711 return; |
|
11712 } |
|
11713 |
|
11714 // Focus the appropriate tab, based on which key was pressed |
|
11715 event.preventDefault(); |
|
11716 clearTimeout( this.activating ); |
|
11717 selectedIndex = this._focusNextTab( selectedIndex, goingForward ); |
|
11718 |
|
11719 // Navigating with control key will prevent automatic activation |
|
11720 if ( !event.ctrlKey ) { |
|
11721 // Update aria-selected immediately so that AT think the tab is already selected. |
|
11722 // Otherwise AT may confuse the user by stating that they need to activate the tab, |
|
11723 // but the tab will already be activated by the time the announcement finishes. |
|
11724 focusedTab.attr( "aria-selected", "false" ); |
|
11725 this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" ); |
|
11726 |
|
11727 this.activating = this._delay(function() { |
|
11728 this.option( "active", selectedIndex ); |
|
11729 }, this.delay ); |
|
11730 } |
|
11731 }, |
|
11732 |
|
11733 _panelKeydown: function( event ) { |
|
11734 if ( this._handlePageNav( event ) ) { |
|
11735 return; |
|
11736 } |
|
11737 |
|
11738 // Ctrl+up moves focus to the current tab |
|
11739 if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) { |
|
11740 event.preventDefault(); |
|
11741 this.active.focus(); |
|
11742 } |
|
11743 }, |
|
11744 |
|
11745 // Alt+page up/down moves focus to the previous/next tab (and activates) |
|
11746 _handlePageNav: function( event ) { |
|
11747 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) { |
|
11748 this._activate( this._focusNextTab( this.options.active - 1, false ) ); |
|
11749 return true; |
|
11750 } |
|
11751 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) { |
|
11752 this._activate( this._focusNextTab( this.options.active + 1, true ) ); |
|
11753 return true; |
|
11754 } |
|
11755 }, |
|
11756 |
|
11757 _findNextTab: function( index, goingForward ) { |
|
11758 var lastTabIndex = this.tabs.length - 1; |
|
11759 |
|
11760 function constrain() { |
|
11761 if ( index > lastTabIndex ) { |
|
11762 index = 0; |
|
11763 } |
|
11764 if ( index < 0 ) { |
|
11765 index = lastTabIndex; |
|
11766 } |
|
11767 return index; |
|
11768 } |
|
11769 |
|
11770 while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) { |
|
11771 index = goingForward ? index + 1 : index - 1; |
|
11772 } |
|
11773 |
|
11774 return index; |
|
11775 }, |
|
11776 |
|
11777 _focusNextTab: function( index, goingForward ) { |
|
11778 index = this._findNextTab( index, goingForward ); |
|
11779 this.tabs.eq( index ).focus(); |
|
11780 return index; |
|
11781 }, |
|
11782 |
|
11783 _setOption: function( key, value ) { |
|
11784 if ( key === "active" ) { |
|
11785 // _activate() will handle invalid values and update this.options |
|
11786 this._activate( value ); |
|
11787 return; |
|
11788 } |
|
11789 |
|
11790 if ( key === "disabled" ) { |
|
11791 // don't use the widget factory's disabled handling |
|
11792 this._setupDisabled( value ); |
|
11793 return; |
|
11794 } |
|
11795 |
|
11796 this._super( key, value); |
|
11797 |
|
11798 if ( key === "collapsible" ) { |
|
11799 this.element.toggleClass( "ui-tabs-collapsible", value ); |
|
11800 // Setting collapsible: false while collapsed; open first panel |
|
11801 if ( !value && this.options.active === false ) { |
|
11802 this._activate( 0 ); |
|
11803 } |
|
11804 } |
|
11805 |
|
11806 if ( key === "event" ) { |
|
11807 this._setupEvents( value ); |
|
11808 } |
|
11809 |
|
11810 if ( key === "heightStyle" ) { |
|
11811 this._setupHeightStyle( value ); |
|
11812 } |
|
11813 }, |
|
11814 |
|
11815 _tabId: function( tab ) { |
|
11816 return tab.attr( "aria-controls" ) || "ui-tabs-" + getNextTabId(); |
|
11817 }, |
|
11818 |
|
11819 _sanitizeSelector: function( hash ) { |
|
11820 return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : ""; |
|
11821 }, |
|
11822 |
|
11823 refresh: function() { |
|
11824 var options = this.options, |
|
11825 lis = this.tablist.children( ":has(a[href])" ); |
|
11826 |
|
11827 // get disabled tabs from class attribute from HTML |
|
11828 // this will get converted to a boolean if needed in _refresh() |
|
11829 options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) { |
|
11830 return lis.index( tab ); |
|
11831 }); |
|
11832 |
|
11833 this._processTabs(); |
|
11834 |
|
11835 // was collapsed or no tabs |
|
11836 if ( options.active === false || !this.anchors.length ) { |
|
11837 options.active = false; |
|
11838 this.active = $(); |
|
11839 // was active, but active tab is gone |
|
11840 } else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) { |
|
11841 // all remaining tabs are disabled |
|
11842 if ( this.tabs.length === options.disabled.length ) { |
|
11843 options.active = false; |
|
11844 this.active = $(); |
|
11845 // activate previous tab |
|
11846 } else { |
|
11847 this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) ); |
|
11848 } |
|
11849 // was active, active tab still exists |
|
11850 } else { |
|
11851 // make sure active index is correct |
|
11852 options.active = this.tabs.index( this.active ); |
|
11853 } |
|
11854 |
|
11855 this._refresh(); |
|
11856 }, |
|
11857 |
|
11858 _refresh: function() { |
|
11859 this._setupDisabled( this.options.disabled ); |
|
11860 this._setupEvents( this.options.event ); |
|
11861 this._setupHeightStyle( this.options.heightStyle ); |
|
11862 |
|
11863 this.tabs.not( this.active ).attr({ |
|
11864 "aria-selected": "false", |
|
11865 tabIndex: -1 |
|
11866 }); |
|
11867 this.panels.not( this._getPanelForTab( this.active ) ) |
|
11868 .hide() |
|
11869 .attr({ |
|
11870 "aria-expanded": "false", |
|
11871 "aria-hidden": "true" |
|
11872 }); |
|
11873 |
|
11874 // Make sure one tab is in the tab order |
|
11875 if ( !this.active.length ) { |
|
11876 this.tabs.eq( 0 ).attr( "tabIndex", 0 ); |
|
11877 } else { |
|
11878 this.active |
|
11879 .addClass( "ui-tabs-active ui-state-active" ) |
|
11880 .attr({ |
|
11881 "aria-selected": "true", |
|
11882 tabIndex: 0 |
|
11883 }); |
|
11884 this._getPanelForTab( this.active ) |
|
11885 .show() |
|
11886 .attr({ |
|
11887 "aria-expanded": "true", |
|
11888 "aria-hidden": "false" |
|
11889 }); |
|
11890 } |
|
11891 }, |
|
11892 |
|
11893 _processTabs: function() { |
|
11894 var that = this; |
|
11895 |
|
11896 this.tablist = this._getList() |
|
11897 .addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ) |
|
11898 .attr( "role", "tablist" ); |
|
11899 |
|
11900 this.tabs = this.tablist.find( "> li:has(a[href])" ) |
|
11901 .addClass( "ui-state-default ui-corner-top" ) |
|
11902 .attr({ |
|
11903 role: "tab", |
|
11904 tabIndex: -1 |
|
11905 }); |
|
11906 |
|
11907 this.anchors = this.tabs.map(function() { |
|
11908 return $( "a", this )[ 0 ]; |
|
11909 }) |
|
11910 .addClass( "ui-tabs-anchor" ) |
|
11911 .attr({ |
|
11912 role: "presentation", |
|
11913 tabIndex: -1 |
|
11914 }); |
|
11915 |
|
11916 this.panels = $(); |
|
11917 |
|
11918 this.anchors.each(function( i, anchor ) { |
|
11919 var selector, panel, panelId, |
|
11920 anchorId = $( anchor ).uniqueId().attr( "id" ), |
|
11921 tab = $( anchor ).closest( "li" ), |
|
11922 originalAriaControls = tab.attr( "aria-controls" ); |
|
11923 |
|
11924 // inline tab |
|
11925 if ( isLocal( anchor ) ) { |
|
11926 selector = anchor.hash; |
|
11927 panel = that.element.find( that._sanitizeSelector( selector ) ); |
|
11928 // remote tab |
|
11929 } else { |
|
11930 panelId = that._tabId( tab ); |
|
11931 selector = "#" + panelId; |
|
11932 panel = that.element.find( selector ); |
|
11933 if ( !panel.length ) { |
|
11934 panel = that._createPanel( panelId ); |
|
11935 panel.insertAfter( that.panels[ i - 1 ] || that.tablist ); |
|
11936 } |
|
11937 panel.attr( "aria-live", "polite" ); |
|
11938 } |
|
11939 |
|
11940 if ( panel.length) { |
|
11941 that.panels = that.panels.add( panel ); |
|
11942 } |
|
11943 if ( originalAriaControls ) { |
|
11944 tab.data( "ui-tabs-aria-controls", originalAriaControls ); |
|
11945 } |
|
11946 tab.attr({ |
|
11947 "aria-controls": selector.substring( 1 ), |
|
11948 "aria-labelledby": anchorId |
|
11949 }); |
|
11950 panel.attr( "aria-labelledby", anchorId ); |
|
11951 }); |
|
11952 |
|
11953 this.panels |
|
11954 .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) |
|
11955 .attr( "role", "tabpanel" ); |
|
11956 }, |
|
11957 |
|
11958 // allow overriding how to find the list for rare usage scenarios (#7715) |
|
11959 _getList: function() { |
|
11960 return this.tablist || this.element.find( "ol,ul" ).eq( 0 ); |
|
11961 }, |
|
11962 |
|
11963 _createPanel: function( id ) { |
|
11964 return $( "<div>" ) |
|
11965 .attr( "id", id ) |
|
11966 .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) |
|
11967 .data( "ui-tabs-destroy", true ); |
|
11968 }, |
|
11969 |
|
11970 _setupDisabled: function( disabled ) { |
|
11971 if ( $.isArray( disabled ) ) { |
|
11972 if ( !disabled.length ) { |
|
11973 disabled = false; |
|
11974 } else if ( disabled.length === this.anchors.length ) { |
|
11975 disabled = true; |
|
11976 } |
|
11977 } |
|
11978 |
|
11979 // disable tabs |
|
11980 for ( var i = 0, li; ( li = this.tabs[ i ] ); i++ ) { |
|
11981 if ( disabled === true || $.inArray( i, disabled ) !== -1 ) { |
|
11982 $( li ) |
|
11983 .addClass( "ui-state-disabled" ) |
|
11984 .attr( "aria-disabled", "true" ); |
|
11985 } else { |
|
11986 $( li ) |
|
11987 .removeClass( "ui-state-disabled" ) |
|
11988 .removeAttr( "aria-disabled" ); |
|
11989 } |
|
11990 } |
|
11991 |
|
11992 this.options.disabled = disabled; |
|
11993 }, |
|
11994 |
|
11995 _setupEvents: function( event ) { |
|
11996 var events = { |
|
11997 click: function( event ) { |
|
11998 event.preventDefault(); |
|
11999 } |
|
12000 }; |
|
12001 if ( event ) { |
|
12002 $.each( event.split(" "), function( index, eventName ) { |
|
12003 events[ eventName ] = "_eventHandler"; |
|
12004 }); |
|
12005 } |
|
12006 |
|
12007 this._off( this.anchors.add( this.tabs ).add( this.panels ) ); |
|
12008 this._on( this.anchors, events ); |
|
12009 this._on( this.tabs, { keydown: "_tabKeydown" } ); |
|
12010 this._on( this.panels, { keydown: "_panelKeydown" } ); |
|
12011 |
|
12012 this._focusable( this.tabs ); |
|
12013 this._hoverable( this.tabs ); |
|
12014 }, |
|
12015 |
|
12016 _setupHeightStyle: function( heightStyle ) { |
|
12017 var maxHeight, |
|
12018 parent = this.element.parent(); |
|
12019 |
|
12020 if ( heightStyle === "fill" ) { |
|
12021 maxHeight = parent.height(); |
|
12022 maxHeight -= this.element.outerHeight() - this.element.height(); |
|
12023 |
|
12024 this.element.siblings( ":visible" ).each(function() { |
|
12025 var elem = $( this ), |
|
12026 position = elem.css( "position" ); |
|
12027 |
|
12028 if ( position === "absolute" || position === "fixed" ) { |
|
12029 return; |
|
12030 } |
|
12031 maxHeight -= elem.outerHeight( true ); |
|
12032 }); |
|
12033 |
|
12034 this.element.children().not( this.panels ).each(function() { |
|
12035 maxHeight -= $( this ).outerHeight( true ); |
|
12036 }); |
|
12037 |
|
12038 this.panels.each(function() { |
|
12039 $( this ).height( Math.max( 0, maxHeight - |
|
12040 $( this ).innerHeight() + $( this ).height() ) ); |
|
12041 }) |
|
12042 .css( "overflow", "auto" ); |
|
12043 } else if ( heightStyle === "auto" ) { |
|
12044 maxHeight = 0; |
|
12045 this.panels.each(function() { |
|
12046 maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() ); |
|
12047 }).height( maxHeight ); |
|
12048 } |
|
12049 }, |
|
12050 |
|
12051 _eventHandler: function( event ) { |
|
12052 var options = this.options, |
|
12053 active = this.active, |
|
12054 anchor = $( event.currentTarget ), |
|
12055 tab = anchor.closest( "li" ), |
|
12056 clickedIsActive = tab[ 0 ] === active[ 0 ], |
|
12057 collapsing = clickedIsActive && options.collapsible, |
|
12058 toShow = collapsing ? $() : this._getPanelForTab( tab ), |
|
12059 toHide = !active.length ? $() : this._getPanelForTab( active ), |
|
12060 eventData = { |
|
12061 oldTab: active, |
|
12062 oldPanel: toHide, |
|
12063 newTab: collapsing ? $() : tab, |
|
12064 newPanel: toShow |
|
12065 }; |
|
12066 |
|
12067 event.preventDefault(); |
|
12068 |
|
12069 if ( tab.hasClass( "ui-state-disabled" ) || |
|
12070 // tab is already loading |
|
12071 tab.hasClass( "ui-tabs-loading" ) || |
|
12072 // can't switch durning an animation |
|
12073 this.running || |
|
12074 // click on active header, but not collapsible |
|
12075 ( clickedIsActive && !options.collapsible ) || |
|
12076 // allow canceling activation |
|
12077 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { |
|
12078 return; |
|
12079 } |
|
12080 |
|
12081 options.active = collapsing ? false : this.tabs.index( tab ); |
|
12082 |
|
12083 this.active = clickedIsActive ? $() : tab; |
|
12084 if ( this.xhr ) { |
|
12085 this.xhr.abort(); |
|
12086 } |
|
12087 |
|
12088 if ( !toHide.length && !toShow.length ) { |
|
12089 $.error( "jQuery UI Tabs: Mismatching fragment identifier." ); |
|
12090 } |
|
12091 |
|
12092 if ( toShow.length ) { |
|
12093 this.load( this.tabs.index( tab ), event ); |
|
12094 } |
|
12095 this._toggle( event, eventData ); |
|
12096 }, |
|
12097 |
|
12098 // handles show/hide for selecting tabs |
|
12099 _toggle: function( event, eventData ) { |
|
12100 var that = this, |
|
12101 toShow = eventData.newPanel, |
|
12102 toHide = eventData.oldPanel; |
|
12103 |
|
12104 this.running = true; |
|
12105 |
|
12106 function complete() { |
|
12107 that.running = false; |
|
12108 that._trigger( "activate", event, eventData ); |
|
12109 } |
|
12110 |
|
12111 function show() { |
|
12112 eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" ); |
|
12113 |
|
12114 if ( toShow.length && that.options.show ) { |
|
12115 that._show( toShow, that.options.show, complete ); |
|
12116 } else { |
|
12117 toShow.show(); |
|
12118 complete(); |
|
12119 } |
|
12120 } |
|
12121 |
|
12122 // start out by hiding, then showing, then completing |
|
12123 if ( toHide.length && this.options.hide ) { |
|
12124 this._hide( toHide, this.options.hide, function() { |
|
12125 eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" ); |
|
12126 show(); |
|
12127 }); |
|
12128 } else { |
|
12129 eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" ); |
|
12130 toHide.hide(); |
|
12131 show(); |
|
12132 } |
|
12133 |
|
12134 toHide.attr({ |
|
12135 "aria-expanded": "false", |
|
12136 "aria-hidden": "true" |
|
12137 }); |
|
12138 eventData.oldTab.attr( "aria-selected", "false" ); |
|
12139 // If we're switching tabs, remove the old tab from the tab order. |
|
12140 // If we're opening from collapsed state, remove the previous tab from the tab order. |
|
12141 // If we're collapsing, then keep the collapsing tab in the tab order. |
|
12142 if ( toShow.length && toHide.length ) { |
|
12143 eventData.oldTab.attr( "tabIndex", -1 ); |
|
12144 } else if ( toShow.length ) { |
|
12145 this.tabs.filter(function() { |
|
12146 return $( this ).attr( "tabIndex" ) === 0; |
|
12147 }) |
|
12148 .attr( "tabIndex", -1 ); |
|
12149 } |
|
12150 |
|
12151 toShow.attr({ |
|
12152 "aria-expanded": "true", |
|
12153 "aria-hidden": "false" |
|
12154 }); |
|
12155 eventData.newTab.attr({ |
|
12156 "aria-selected": "true", |
|
12157 tabIndex: 0 |
|
12158 }); |
|
12159 }, |
|
12160 |
|
12161 _activate: function( index ) { |
|
12162 var anchor, |
|
12163 active = this._findActive( index ); |
|
12164 |
|
12165 // trying to activate the already active panel |
|
12166 if ( active[ 0 ] === this.active[ 0 ] ) { |
|
12167 return; |
|
12168 } |
|
12169 |
|
12170 // trying to collapse, simulate a click on the current active header |
|
12171 if ( !active.length ) { |
|
12172 active = this.active; |
|
12173 } |
|
12174 |
|
12175 anchor = active.find( ".ui-tabs-anchor" )[ 0 ]; |
|
12176 this._eventHandler({ |
|
12177 target: anchor, |
|
12178 currentTarget: anchor, |
|
12179 preventDefault: $.noop |
|
12180 }); |
|
12181 }, |
|
12182 |
|
12183 _findActive: function( index ) { |
|
12184 return index === false ? $() : this.tabs.eq( index ); |
|
12185 }, |
|
12186 |
|
12187 _getIndex: function( index ) { |
|
12188 // meta-function to give users option to provide a href string instead of a numerical index. |
|
12189 if ( typeof index === "string" ) { |
|
12190 index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) ); |
|
12191 } |
|
12192 |
|
12193 return index; |
|
12194 }, |
|
12195 |
|
12196 _destroy: function() { |
|
12197 if ( this.xhr ) { |
|
12198 this.xhr.abort(); |
|
12199 } |
|
12200 |
|
12201 this.element.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" ); |
|
12202 |
|
12203 this.tablist |
|
12204 .removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ) |
|
12205 .removeAttr( "role" ); |
|
12206 |
|
12207 this.anchors |
|
12208 .removeClass( "ui-tabs-anchor" ) |
|
12209 .removeAttr( "role" ) |
|
12210 .removeAttr( "tabIndex" ) |
|
12211 .removeUniqueId(); |
|
12212 |
|
12213 this.tabs.add( this.panels ).each(function() { |
|
12214 if ( $.data( this, "ui-tabs-destroy" ) ) { |
|
12215 $( this ).remove(); |
|
12216 } else { |
|
12217 $( this ) |
|
12218 .removeClass( "ui-state-default ui-state-active ui-state-disabled " + |
|
12219 "ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel" ) |
|
12220 .removeAttr( "tabIndex" ) |
|
12221 .removeAttr( "aria-live" ) |
|
12222 .removeAttr( "aria-busy" ) |
|
12223 .removeAttr( "aria-selected" ) |
|
12224 .removeAttr( "aria-labelledby" ) |
|
12225 .removeAttr( "aria-hidden" ) |
|
12226 .removeAttr( "aria-expanded" ) |
|
12227 .removeAttr( "role" ); |
|
12228 } |
|
12229 }); |
|
12230 |
|
12231 this.tabs.each(function() { |
|
12232 var li = $( this ), |
|
12233 prev = li.data( "ui-tabs-aria-controls" ); |
|
12234 if ( prev ) { |
|
12235 li |
|
12236 .attr( "aria-controls", prev ) |
|
12237 .removeData( "ui-tabs-aria-controls" ); |
|
12238 } else { |
|
12239 li.removeAttr( "aria-controls" ); |
|
12240 } |
|
12241 }); |
|
12242 |
|
12243 this.panels.show(); |
|
12244 |
|
12245 if ( this.options.heightStyle !== "content" ) { |
|
12246 this.panels.css( "height", "" ); |
|
12247 } |
|
12248 }, |
|
12249 |
|
12250 enable: function( index ) { |
|
12251 var disabled = this.options.disabled; |
|
12252 if ( disabled === false ) { |
|
12253 return; |
|
12254 } |
|
12255 |
|
12256 if ( index === undefined ) { |
|
12257 disabled = false; |
|
12258 } else { |
|
12259 index = this._getIndex( index ); |
|
12260 if ( $.isArray( disabled ) ) { |
|
12261 disabled = $.map( disabled, function( num ) { |
|
12262 return num !== index ? num : null; |
|
12263 }); |
|
12264 } else { |
|
12265 disabled = $.map( this.tabs, function( li, num ) { |
|
12266 return num !== index ? num : null; |
|
12267 }); |
|
12268 } |
|
12269 } |
|
12270 this._setupDisabled( disabled ); |
|
12271 }, |
|
12272 |
|
12273 disable: function( index ) { |
|
12274 var disabled = this.options.disabled; |
|
12275 if ( disabled === true ) { |
|
12276 return; |
|
12277 } |
|
12278 |
|
12279 if ( index === undefined ) { |
|
12280 disabled = true; |
|
12281 } else { |
|
12282 index = this._getIndex( index ); |
|
12283 if ( $.inArray( index, disabled ) !== -1 ) { |
|
12284 return; |
|
12285 } |
|
12286 if ( $.isArray( disabled ) ) { |
|
12287 disabled = $.merge( [ index ], disabled ).sort(); |
|
12288 } else { |
|
12289 disabled = [ index ]; |
|
12290 } |
|
12291 } |
|
12292 this._setupDisabled( disabled ); |
|
12293 }, |
|
12294 |
|
12295 load: function( index, event ) { |
|
12296 index = this._getIndex( index ); |
|
12297 var that = this, |
|
12298 tab = this.tabs.eq( index ), |
|
12299 anchor = tab.find( ".ui-tabs-anchor" ), |
|
12300 panel = this._getPanelForTab( tab ), |
|
12301 eventData = { |
|
12302 tab: tab, |
|
12303 panel: panel |
|
12304 }; |
|
12305 |
|
12306 // not remote |
|
12307 if ( isLocal( anchor[ 0 ] ) ) { |
|
12308 return; |
|
12309 } |
|
12310 |
|
12311 this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) ); |
|
12312 |
|
12313 // support: jQuery <1.8 |
|
12314 // jQuery <1.8 returns false if the request is canceled in beforeSend, |
|
12315 // but as of 1.8, $.ajax() always returns a jqXHR object. |
|
12316 if ( this.xhr && this.xhr.statusText !== "canceled" ) { |
|
12317 tab.addClass( "ui-tabs-loading" ); |
|
12318 panel.attr( "aria-busy", "true" ); |
|
12319 |
|
12320 this.xhr |
|
12321 .success(function( response ) { |
|
12322 // support: jQuery <1.8 |
|
12323 // http://bugs.jquery.com/ticket/11778 |
|
12324 setTimeout(function() { |
|
12325 panel.html( response ); |
|
12326 that._trigger( "load", event, eventData ); |
|
12327 }, 1 ); |
|
12328 }) |
|
12329 .complete(function( jqXHR, status ) { |
|
12330 // support: jQuery <1.8 |
|
12331 // http://bugs.jquery.com/ticket/11778 |
|
12332 setTimeout(function() { |
|
12333 if ( status === "abort" ) { |
|
12334 that.panels.stop( false, true ); |
|
12335 } |
|
12336 |
|
12337 tab.removeClass( "ui-tabs-loading" ); |
|
12338 panel.removeAttr( "aria-busy" ); |
|
12339 |
|
12340 if ( jqXHR === that.xhr ) { |
|
12341 delete that.xhr; |
|
12342 } |
|
12343 }, 1 ); |
|
12344 }); |
|
12345 } |
|
12346 }, |
|
12347 |
|
12348 _ajaxSettings: function( anchor, event, eventData ) { |
|
12349 var that = this; |
|
12350 return { |
|
12351 url: anchor.attr( "href" ), |
|
12352 beforeSend: function( jqXHR, settings ) { |
|
12353 return that._trigger( "beforeLoad", event, |
|
12354 $.extend( { jqXHR : jqXHR, ajaxSettings: settings }, eventData ) ); |
|
12355 } |
|
12356 }; |
|
12357 }, |
|
12358 |
|
12359 _getPanelForTab: function( tab ) { |
|
12360 var id = $( tab ).attr( "aria-controls" ); |
|
12361 return this.element.find( this._sanitizeSelector( "#" + id ) ); |
|
12362 } |
|
12363 }); |
|
12364 |
|
12365 })( jQuery ); |
|
12366 (function( $ ) { |
|
12367 |
|
12368 var increments = 0; |
|
12369 |
|
12370 function addDescribedBy( elem, id ) { |
|
12371 var describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ); |
|
12372 describedby.push( id ); |
|
12373 elem |
|
12374 .data( "ui-tooltip-id", id ) |
|
12375 .attr( "aria-describedby", $.trim( describedby.join( " " ) ) ); |
|
12376 } |
|
12377 |
|
12378 function removeDescribedBy( elem ) { |
|
12379 var id = elem.data( "ui-tooltip-id" ), |
|
12380 describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ), |
|
12381 index = $.inArray( id, describedby ); |
|
12382 if ( index !== -1 ) { |
|
12383 describedby.splice( index, 1 ); |
|
12384 } |
|
12385 |
|
12386 elem.removeData( "ui-tooltip-id" ); |
|
12387 describedby = $.trim( describedby.join( " " ) ); |
|
12388 if ( describedby ) { |
|
12389 elem.attr( "aria-describedby", describedby ); |
|
12390 } else { |
|
12391 elem.removeAttr( "aria-describedby" ); |
|
12392 } |
|
12393 } |
|
12394 |
|
12395 $.widget( "ui.tooltip", { |
|
12396 version: "1.10.4", |
|
12397 options: { |
|
12398 content: function() { |
|
12399 // support: IE<9, Opera in jQuery <1.7 |
|
12400 // .text() can't accept undefined, so coerce to a string |
|
12401 var title = $( this ).attr( "title" ) || ""; |
|
12402 // Escape title, since we're going from an attribute to raw HTML |
|
12403 return $( "<a>" ).text( title ).html(); |
|
12404 }, |
|
12405 hide: true, |
|
12406 // Disabled elements have inconsistent behavior across browsers (#8661) |
|
12407 items: "[title]:not([disabled])", |
|
12408 position: { |
|
12409 my: "left top+15", |
|
12410 at: "left bottom", |
|
12411 collision: "flipfit flip" |
|
12412 }, |
|
12413 show: true, |
|
12414 tooltipClass: null, |
|
12415 track: false, |
|
12416 |
|
12417 // callbacks |
|
12418 close: null, |
|
12419 open: null |
|
12420 }, |
|
12421 |
|
12422 _create: function() { |
|
12423 this._on({ |
|
12424 mouseover: "open", |
|
12425 focusin: "open" |
|
12426 }); |
|
12427 |
|
12428 // IDs of generated tooltips, needed for destroy |
|
12429 this.tooltips = {}; |
|
12430 // IDs of parent tooltips where we removed the title attribute |
|
12431 this.parents = {}; |
|
12432 |
|
12433 if ( this.options.disabled ) { |
|
12434 this._disable(); |
|
12435 } |
|
12436 }, |
|
12437 |
|
12438 _setOption: function( key, value ) { |
|
12439 var that = this; |
|
12440 |
|
12441 if ( key === "disabled" ) { |
|
12442 this[ value ? "_disable" : "_enable" ](); |
|
12443 this.options[ key ] = value; |
|
12444 // disable element style changes |
|
12445 return; |
|
12446 } |
|
12447 |
|
12448 this._super( key, value ); |
|
12449 |
|
12450 if ( key === "content" ) { |
|
12451 $.each( this.tooltips, function( id, element ) { |
|
12452 that._updateContent( element ); |
|
12453 }); |
|
12454 } |
|
12455 }, |
|
12456 |
|
12457 _disable: function() { |
|
12458 var that = this; |
|
12459 |
|
12460 // close open tooltips |
|
12461 $.each( this.tooltips, function( id, element ) { |
|
12462 var event = $.Event( "blur" ); |
|
12463 event.target = event.currentTarget = element[0]; |
|
12464 that.close( event, true ); |
|
12465 }); |
|
12466 |
|
12467 // remove title attributes to prevent native tooltips |
|
12468 this.element.find( this.options.items ).addBack().each(function() { |
|
12469 var element = $( this ); |
|
12470 if ( element.is( "[title]" ) ) { |
|
12471 element |
|
12472 .data( "ui-tooltip-title", element.attr( "title" ) ) |
|
12473 .attr( "title", "" ); |
|
12474 } |
|
12475 }); |
|
12476 }, |
|
12477 |
|
12478 _enable: function() { |
|
12479 // restore title attributes |
|
12480 this.element.find( this.options.items ).addBack().each(function() { |
|
12481 var element = $( this ); |
|
12482 if ( element.data( "ui-tooltip-title" ) ) { |
|
12483 element.attr( "title", element.data( "ui-tooltip-title" ) ); |
|
12484 } |
|
12485 }); |
|
12486 }, |
|
12487 |
|
12488 open: function( event ) { |
|
12489 var that = this, |
|
12490 target = $( event ? event.target : this.element ) |
|
12491 // we need closest here due to mouseover bubbling, |
|
12492 // but always pointing at the same event target |
|
12493 .closest( this.options.items ); |
|
12494 |
|
12495 // No element to show a tooltip for or the tooltip is already open |
|
12496 if ( !target.length || target.data( "ui-tooltip-id" ) ) { |
|
12497 return; |
|
12498 } |
|
12499 |
|
12500 if ( target.attr( "title" ) ) { |
|
12501 target.data( "ui-tooltip-title", target.attr( "title" ) ); |
|
12502 } |
|
12503 |
|
12504 target.data( "ui-tooltip-open", true ); |
|
12505 |
|
12506 // kill parent tooltips, custom or native, for hover |
|
12507 if ( event && event.type === "mouseover" ) { |
|
12508 target.parents().each(function() { |
|
12509 var parent = $( this ), |
|
12510 blurEvent; |
|
12511 if ( parent.data( "ui-tooltip-open" ) ) { |
|
12512 blurEvent = $.Event( "blur" ); |
|
12513 blurEvent.target = blurEvent.currentTarget = this; |
|
12514 that.close( blurEvent, true ); |
|
12515 } |
|
12516 if ( parent.attr( "title" ) ) { |
|
12517 parent.uniqueId(); |
|
12518 that.parents[ this.id ] = { |
|
12519 element: this, |
|
12520 title: parent.attr( "title" ) |
|
12521 }; |
|
12522 parent.attr( "title", "" ); |
|
12523 } |
|
12524 }); |
|
12525 } |
|
12526 |
|
12527 this._updateContent( target, event ); |
|
12528 }, |
|
12529 |
|
12530 _updateContent: function( target, event ) { |
|
12531 var content, |
|
12532 contentOption = this.options.content, |
|
12533 that = this, |
|
12534 eventType = event ? event.type : null; |
|
12535 |
|
12536 if ( typeof contentOption === "string" ) { |
|
12537 return this._open( event, target, contentOption ); |
|
12538 } |
|
12539 |
|
12540 content = contentOption.call( target[0], function( response ) { |
|
12541 // ignore async response if tooltip was closed already |
|
12542 if ( !target.data( "ui-tooltip-open" ) ) { |
|
12543 return; |
|
12544 } |
|
12545 // IE may instantly serve a cached response for ajax requests |
|
12546 // delay this call to _open so the other call to _open runs first |
|
12547 that._delay(function() { |
|
12548 // jQuery creates a special event for focusin when it doesn't |
|
12549 // exist natively. To improve performance, the native event |
|
12550 // object is reused and the type is changed. Therefore, we can't |
|
12551 // rely on the type being correct after the event finished |
|
12552 // bubbling, so we set it back to the previous value. (#8740) |
|
12553 if ( event ) { |
|
12554 event.type = eventType; |
|
12555 } |
|
12556 this._open( event, target, response ); |
|
12557 }); |
|
12558 }); |
|
12559 if ( content ) { |
|
12560 this._open( event, target, content ); |
|
12561 } |
|
12562 }, |
|
12563 |
|
12564 _open: function( event, target, content ) { |
|
12565 var tooltip, events, delayedShow, |
|
12566 positionOption = $.extend( {}, this.options.position ); |
|
12567 |
|
12568 if ( !content ) { |
|
12569 return; |
|
12570 } |
|
12571 |
|
12572 // Content can be updated multiple times. If the tooltip already |
|
12573 // exists, then just update the content and bail. |
|
12574 tooltip = this._find( target ); |
|
12575 if ( tooltip.length ) { |
|
12576 tooltip.find( ".ui-tooltip-content" ).html( content ); |
|
12577 return; |
|
12578 } |
|
12579 |
|
12580 // if we have a title, clear it to prevent the native tooltip |
|
12581 // we have to check first to avoid defining a title if none exists |
|
12582 // (we don't want to cause an element to start matching [title]) |
|
12583 // |
|
12584 // We use removeAttr only for key events, to allow IE to export the correct |
|
12585 // accessible attributes. For mouse events, set to empty string to avoid |
|
12586 // native tooltip showing up (happens only when removing inside mouseover). |
|
12587 if ( target.is( "[title]" ) ) { |
|
12588 if ( event && event.type === "mouseover" ) { |
|
12589 target.attr( "title", "" ); |
|
12590 } else { |
|
12591 target.removeAttr( "title" ); |
|
12592 } |
|
12593 } |
|
12594 |
|
12595 tooltip = this._tooltip( target ); |
|
12596 addDescribedBy( target, tooltip.attr( "id" ) ); |
|
12597 tooltip.find( ".ui-tooltip-content" ).html( content ); |
|
12598 |
|
12599 function position( event ) { |
|
12600 positionOption.of = event; |
|
12601 if ( tooltip.is( ":hidden" ) ) { |
|
12602 return; |
|
12603 } |
|
12604 tooltip.position( positionOption ); |
|
12605 } |
|
12606 if ( this.options.track && event && /^mouse/.test( event.type ) ) { |
|
12607 this._on( this.document, { |
|
12608 mousemove: position |
|
12609 }); |
|
12610 // trigger once to override element-relative positioning |
|
12611 position( event ); |
|
12612 } else { |
|
12613 tooltip.position( $.extend({ |
|
12614 of: target |
|
12615 }, this.options.position ) ); |
|
12616 } |
|
12617 |
|
12618 tooltip.hide(); |
|
12619 |
|
12620 this._show( tooltip, this.options.show ); |
|
12621 // Handle tracking tooltips that are shown with a delay (#8644). As soon |
|
12622 // as the tooltip is visible, position the tooltip using the most recent |
|
12623 // event. |
|
12624 if ( this.options.show && this.options.show.delay ) { |
|
12625 delayedShow = this.delayedShow = setInterval(function() { |
|
12626 if ( tooltip.is( ":visible" ) ) { |
|
12627 position( positionOption.of ); |
|
12628 clearInterval( delayedShow ); |
|
12629 } |
|
12630 }, $.fx.interval ); |
|
12631 } |
|
12632 |
|
12633 this._trigger( "open", event, { tooltip: tooltip } ); |
|
12634 |
|
12635 events = { |
|
12636 keyup: function( event ) { |
|
12637 if ( event.keyCode === $.ui.keyCode.ESCAPE ) { |
|
12638 var fakeEvent = $.Event(event); |
|
12639 fakeEvent.currentTarget = target[0]; |
|
12640 this.close( fakeEvent, true ); |
|
12641 } |
|
12642 }, |
|
12643 remove: function() { |
|
12644 this._removeTooltip( tooltip ); |
|
12645 } |
|
12646 }; |
|
12647 if ( !event || event.type === "mouseover" ) { |
|
12648 events.mouseleave = "close"; |
|
12649 } |
|
12650 if ( !event || event.type === "focusin" ) { |
|
12651 events.focusout = "close"; |
|
12652 } |
|
12653 this._on( true, target, events ); |
|
12654 }, |
|
12655 |
|
12656 close: function( event ) { |
|
12657 var that = this, |
|
12658 target = $( event ? event.currentTarget : this.element ), |
|
12659 tooltip = this._find( target ); |
|
12660 |
|
12661 // disabling closes the tooltip, so we need to track when we're closing |
|
12662 // to avoid an infinite loop in case the tooltip becomes disabled on close |
|
12663 if ( this.closing ) { |
|
12664 return; |
|
12665 } |
|
12666 |
|
12667 // Clear the interval for delayed tracking tooltips |
|
12668 clearInterval( this.delayedShow ); |
|
12669 |
|
12670 // only set title if we had one before (see comment in _open()) |
|
12671 if ( target.data( "ui-tooltip-title" ) ) { |
|
12672 target.attr( "title", target.data( "ui-tooltip-title" ) ); |
|
12673 } |
|
12674 |
|
12675 removeDescribedBy( target ); |
|
12676 |
|
12677 tooltip.stop( true ); |
|
12678 this._hide( tooltip, this.options.hide, function() { |
|
12679 that._removeTooltip( $( this ) ); |
|
12680 }); |
|
12681 |
|
12682 target.removeData( "ui-tooltip-open" ); |
|
12683 this._off( target, "mouseleave focusout keyup" ); |
|
12684 // Remove 'remove' binding only on delegated targets |
|
12685 if ( target[0] !== this.element[0] ) { |
|
12686 this._off( target, "remove" ); |
|
12687 } |
|
12688 this._off( this.document, "mousemove" ); |
|
12689 |
|
12690 if ( event && event.type === "mouseleave" ) { |
|
12691 $.each( this.parents, function( id, parent ) { |
|
12692 $( parent.element ).attr( "title", parent.title ); |
|
12693 delete that.parents[ id ]; |
|
12694 }); |
|
12695 } |
|
12696 |
|
12697 this.closing = true; |
|
12698 this._trigger( "close", event, { tooltip: tooltip } ); |
|
12699 this.closing = false; |
|
12700 }, |
|
12701 |
|
12702 _tooltip: function( element ) { |
|
12703 var id = "ui-tooltip-" + increments++, |
|
12704 tooltip = $( "<div>" ) |
|
12705 .attr({ |
|
12706 id: id, |
|
12707 role: "tooltip" |
|
12708 }) |
|
12709 .addClass( "ui-tooltip ui-widget ui-corner-all ui-widget-content " + |
|
12710 ( this.options.tooltipClass || "" ) ); |
|
12711 $( "<div>" ) |
|
12712 .addClass( "ui-tooltip-content" ) |
|
12713 .appendTo( tooltip ); |
|
12714 tooltip.appendTo( this.document[0].body ); |
|
12715 this.tooltips[ id ] = element; |
|
12716 return tooltip; |
|
12717 }, |
|
12718 |
|
12719 _find: function( target ) { |
|
12720 var id = target.data( "ui-tooltip-id" ); |
|
12721 return id ? $( "#" + id ) : $(); |
|
12722 }, |
|
12723 |
|
12724 _removeTooltip: function( tooltip ) { |
|
12725 tooltip.remove(); |
|
12726 delete this.tooltips[ tooltip.attr( "id" ) ]; |
|
12727 }, |
|
12728 |
|
12729 _destroy: function() { |
|
12730 var that = this; |
|
12731 |
|
12732 // close open tooltips |
|
12733 $.each( this.tooltips, function( id, element ) { |
|
12734 // Delegate to close method to handle common cleanup |
|
12735 var event = $.Event( "blur" ); |
|
12736 event.target = event.currentTarget = element[0]; |
|
12737 that.close( event, true ); |
|
12738 |
|
12739 // Remove immediately; destroying an open tooltip doesn't use the |
|
12740 // hide animation |
|
12741 $( "#" + id ).remove(); |
|
12742 |
|
12743 // Restore the title |
|
12744 if ( element.data( "ui-tooltip-title" ) ) { |
|
12745 element.attr( "title", element.data( "ui-tooltip-title" ) ); |
|
12746 element.removeData( "ui-tooltip-title" ); |
|
12747 } |
|
12748 }); |
|
12749 } |
|
12750 }); |
|
12751 |
|
12752 }( jQuery ) ); |
|
12753 (function($, undefined) { |
|
12754 |
|
12755 var dataSpace = "ui-effects-"; |
|
12756 |
|
12757 $.effects = { |
|
12758 effect: {} |
|
12759 }; |
|
12760 |
|
12761 /*! |
|
12762 * jQuery Color Animations v2.1.2 |
|
12763 * https://github.com/jquery/jquery-color |
|
12764 * |
|
12765 * Copyright 2013 jQuery Foundation and other contributors |
|
12766 * Released under the MIT license. |
|
12767 * http://jquery.org/license |
|
12768 * |
|
12769 * Date: Wed Jan 16 08:47:09 2013 -0600 |
|
12770 */ |
|
12771 (function( jQuery, undefined ) { |
|
12772 |
|
12773 var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor", |
|
12774 |
|
12775 // plusequals test for += 100 -= 100 |
|
12776 rplusequals = /^([\-+])=\s*(\d+\.?\d*)/, |
|
12777 // a set of RE's that can match strings and generate color tuples. |
|
12778 stringParsers = [{ |
|
12779 re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, |
|
12780 parse: function( execResult ) { |
|
12781 return [ |
|
12782 execResult[ 1 ], |
|
12783 execResult[ 2 ], |
|
12784 execResult[ 3 ], |
|
12785 execResult[ 4 ] |
|
12786 ]; |
|
12787 } |
|
12788 }, { |
|
12789 re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, |
|
12790 parse: function( execResult ) { |
|
12791 return [ |
|
12792 execResult[ 1 ] * 2.55, |
|
12793 execResult[ 2 ] * 2.55, |
|
12794 execResult[ 3 ] * 2.55, |
|
12795 execResult[ 4 ] |
|
12796 ]; |
|
12797 } |
|
12798 }, { |
|
12799 // this regex ignores A-F because it's compared against an already lowercased string |
|
12800 re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/, |
|
12801 parse: function( execResult ) { |
|
12802 return [ |
|
12803 parseInt( execResult[ 1 ], 16 ), |
|
12804 parseInt( execResult[ 2 ], 16 ), |
|
12805 parseInt( execResult[ 3 ], 16 ) |
|
12806 ]; |
|
12807 } |
|
12808 }, { |
|
12809 // this regex ignores A-F because it's compared against an already lowercased string |
|
12810 re: /#([a-f0-9])([a-f0-9])([a-f0-9])/, |
|
12811 parse: function( execResult ) { |
|
12812 return [ |
|
12813 parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ), |
|
12814 parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ), |
|
12815 parseInt( execResult[ 3 ] + execResult[ 3 ], 16 ) |
|
12816 ]; |
|
12817 } |
|
12818 }, { |
|
12819 re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, |
|
12820 space: "hsla", |
|
12821 parse: function( execResult ) { |
|
12822 return [ |
|
12823 execResult[ 1 ], |
|
12824 execResult[ 2 ] / 100, |
|
12825 execResult[ 3 ] / 100, |
|
12826 execResult[ 4 ] |
|
12827 ]; |
|
12828 } |
|
12829 }], |
|
12830 |
|
12831 // jQuery.Color( ) |
|
12832 color = jQuery.Color = function( color, green, blue, alpha ) { |
|
12833 return new jQuery.Color.fn.parse( color, green, blue, alpha ); |
|
12834 }, |
|
12835 spaces = { |
|
12836 rgba: { |
|
12837 props: { |
|
12838 red: { |
|
12839 idx: 0, |
|
12840 type: "byte" |
|
12841 }, |
|
12842 green: { |
|
12843 idx: 1, |
|
12844 type: "byte" |
|
12845 }, |
|
12846 blue: { |
|
12847 idx: 2, |
|
12848 type: "byte" |
|
12849 } |
|
12850 } |
|
12851 }, |
|
12852 |
|
12853 hsla: { |
|
12854 props: { |
|
12855 hue: { |
|
12856 idx: 0, |
|
12857 type: "degrees" |
|
12858 }, |
|
12859 saturation: { |
|
12860 idx: 1, |
|
12861 type: "percent" |
|
12862 }, |
|
12863 lightness: { |
|
12864 idx: 2, |
|
12865 type: "percent" |
|
12866 } |
|
12867 } |
|
12868 } |
|
12869 }, |
|
12870 propTypes = { |
|
12871 "byte": { |
|
12872 floor: true, |
|
12873 max: 255 |
|
12874 }, |
|
12875 "percent": { |
|
12876 max: 1 |
|
12877 }, |
|
12878 "degrees": { |
|
12879 mod: 360, |
|
12880 floor: true |
|
12881 } |
|
12882 }, |
|
12883 support = color.support = {}, |
|
12884 |
|
12885 // element for support tests |
|
12886 supportElem = jQuery( "<p>" )[ 0 ], |
|
12887 |
|
12888 // colors = jQuery.Color.names |
|
12889 colors, |
|
12890 |
|
12891 // local aliases of functions called often |
|
12892 each = jQuery.each; |
|
12893 |
|
12894 // determine rgba support immediately |
|
12895 supportElem.style.cssText = "background-color:rgba(1,1,1,.5)"; |
|
12896 support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1; |
|
12897 |
|
12898 // define cache name and alpha properties |
|
12899 // for rgba and hsla spaces |
|
12900 each( spaces, function( spaceName, space ) { |
|
12901 space.cache = "_" + spaceName; |
|
12902 space.props.alpha = { |
|
12903 idx: 3, |
|
12904 type: "percent", |
|
12905 def: 1 |
|
12906 }; |
|
12907 }); |
|
12908 |
|
12909 function clamp( value, prop, allowEmpty ) { |
|
12910 var type = propTypes[ prop.type ] || {}; |
|
12911 |
|
12912 if ( value == null ) { |
|
12913 return (allowEmpty || !prop.def) ? null : prop.def; |
|
12914 } |
|
12915 |
|
12916 // ~~ is an short way of doing floor for positive numbers |
|
12917 value = type.floor ? ~~value : parseFloat( value ); |
|
12918 |
|
12919 // IE will pass in empty strings as value for alpha, |
|
12920 // which will hit this case |
|
12921 if ( isNaN( value ) ) { |
|
12922 return prop.def; |
|
12923 } |
|
12924 |
|
12925 if ( type.mod ) { |
|
12926 // we add mod before modding to make sure that negatives values |
|
12927 // get converted properly: -10 -> 350 |
|
12928 return (value + type.mod) % type.mod; |
|
12929 } |
|
12930 |
|
12931 // for now all property types without mod have min and max |
|
12932 return 0 > value ? 0 : type.max < value ? type.max : value; |
|
12933 } |
|
12934 |
|
12935 function stringParse( string ) { |
|
12936 var inst = color(), |
|
12937 rgba = inst._rgba = []; |
|
12938 |
|
12939 string = string.toLowerCase(); |
|
12940 |
|
12941 each( stringParsers, function( i, parser ) { |
|
12942 var parsed, |
|
12943 match = parser.re.exec( string ), |
|
12944 values = match && parser.parse( match ), |
|
12945 spaceName = parser.space || "rgba"; |
|
12946 |
|
12947 if ( values ) { |
|
12948 parsed = inst[ spaceName ]( values ); |
|
12949 |
|
12950 // if this was an rgba parse the assignment might happen twice |
|
12951 // oh well.... |
|
12952 inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ]; |
|
12953 rgba = inst._rgba = parsed._rgba; |
|
12954 |
|
12955 // exit each( stringParsers ) here because we matched |
|
12956 return false; |
|
12957 } |
|
12958 }); |
|
12959 |
|
12960 // Found a stringParser that handled it |
|
12961 if ( rgba.length ) { |
|
12962 |
|
12963 // if this came from a parsed string, force "transparent" when alpha is 0 |
|
12964 // chrome, (and maybe others) return "transparent" as rgba(0,0,0,0) |
|
12965 if ( rgba.join() === "0,0,0,0" ) { |
|
12966 jQuery.extend( rgba, colors.transparent ); |
|
12967 } |
|
12968 return inst; |
|
12969 } |
|
12970 |
|
12971 // named colors |
|
12972 return colors[ string ]; |
|
12973 } |
|
12974 |
|
12975 color.fn = jQuery.extend( color.prototype, { |
|
12976 parse: function( red, green, blue, alpha ) { |
|
12977 if ( red === undefined ) { |
|
12978 this._rgba = [ null, null, null, null ]; |
|
12979 return this; |
|
12980 } |
|
12981 if ( red.jquery || red.nodeType ) { |
|
12982 red = jQuery( red ).css( green ); |
|
12983 green = undefined; |
|
12984 } |
|
12985 |
|
12986 var inst = this, |
|
12987 type = jQuery.type( red ), |
|
12988 rgba = this._rgba = []; |
|
12989 |
|
12990 // more than 1 argument specified - assume ( red, green, blue, alpha ) |
|
12991 if ( green !== undefined ) { |
|
12992 red = [ red, green, blue, alpha ]; |
|
12993 type = "array"; |
|
12994 } |
|
12995 |
|
12996 if ( type === "string" ) { |
|
12997 return this.parse( stringParse( red ) || colors._default ); |
|
12998 } |
|
12999 |
|
13000 if ( type === "array" ) { |
|
13001 each( spaces.rgba.props, function( key, prop ) { |
|
13002 rgba[ prop.idx ] = clamp( red[ prop.idx ], prop ); |
|
13003 }); |
|
13004 return this; |
|
13005 } |
|
13006 |
|
13007 if ( type === "object" ) { |
|
13008 if ( red instanceof color ) { |
|
13009 each( spaces, function( spaceName, space ) { |
|
13010 if ( red[ space.cache ] ) { |
|
13011 inst[ space.cache ] = red[ space.cache ].slice(); |
|
13012 } |
|
13013 }); |
|
13014 } else { |
|
13015 each( spaces, function( spaceName, space ) { |
|
13016 var cache = space.cache; |
|
13017 each( space.props, function( key, prop ) { |
|
13018 |
|
13019 // if the cache doesn't exist, and we know how to convert |
|
13020 if ( !inst[ cache ] && space.to ) { |
|
13021 |
|
13022 // if the value was null, we don't need to copy it |
|
13023 // if the key was alpha, we don't need to copy it either |
|
13024 if ( key === "alpha" || red[ key ] == null ) { |
|
13025 return; |
|
13026 } |
|
13027 inst[ cache ] = space.to( inst._rgba ); |
|
13028 } |
|
13029 |
|
13030 // this is the only case where we allow nulls for ALL properties. |
|
13031 // call clamp with alwaysAllowEmpty |
|
13032 inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true ); |
|
13033 }); |
|
13034 |
|
13035 // everything defined but alpha? |
|
13036 if ( inst[ cache ] && jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) { |
|
13037 // use the default of 1 |
|
13038 inst[ cache ][ 3 ] = 1; |
|
13039 if ( space.from ) { |
|
13040 inst._rgba = space.from( inst[ cache ] ); |
|
13041 } |
|
13042 } |
|
13043 }); |
|
13044 } |
|
13045 return this; |
|
13046 } |
|
13047 }, |
|
13048 is: function( compare ) { |
|
13049 var is = color( compare ), |
|
13050 same = true, |
|
13051 inst = this; |
|
13052 |
|
13053 each( spaces, function( _, space ) { |
|
13054 var localCache, |
|
13055 isCache = is[ space.cache ]; |
|
13056 if (isCache) { |
|
13057 localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || []; |
|
13058 each( space.props, function( _, prop ) { |
|
13059 if ( isCache[ prop.idx ] != null ) { |
|
13060 same = ( isCache[ prop.idx ] === localCache[ prop.idx ] ); |
|
13061 return same; |
|
13062 } |
|
13063 }); |
|
13064 } |
|
13065 return same; |
|
13066 }); |
|
13067 return same; |
|
13068 }, |
|
13069 _space: function() { |
|
13070 var used = [], |
|
13071 inst = this; |
|
13072 each( spaces, function( spaceName, space ) { |
|
13073 if ( inst[ space.cache ] ) { |
|
13074 used.push( spaceName ); |
|
13075 } |
|
13076 }); |
|
13077 return used.pop(); |
|
13078 }, |
|
13079 transition: function( other, distance ) { |
|
13080 var end = color( other ), |
|
13081 spaceName = end._space(), |
|
13082 space = spaces[ spaceName ], |
|
13083 startColor = this.alpha() === 0 ? color( "transparent" ) : this, |
|
13084 start = startColor[ space.cache ] || space.to( startColor._rgba ), |
|
13085 result = start.slice(); |
|
13086 |
|
13087 end = end[ space.cache ]; |
|
13088 each( space.props, function( key, prop ) { |
|
13089 var index = prop.idx, |
|
13090 startValue = start[ index ], |
|
13091 endValue = end[ index ], |
|
13092 type = propTypes[ prop.type ] || {}; |
|
13093 |
|
13094 // if null, don't override start value |
|
13095 if ( endValue === null ) { |
|
13096 return; |
|
13097 } |
|
13098 // if null - use end |
|
13099 if ( startValue === null ) { |
|
13100 result[ index ] = endValue; |
|
13101 } else { |
|
13102 if ( type.mod ) { |
|
13103 if ( endValue - startValue > type.mod / 2 ) { |
|
13104 startValue += type.mod; |
|
13105 } else if ( startValue - endValue > type.mod / 2 ) { |
|
13106 startValue -= type.mod; |
|
13107 } |
|
13108 } |
|
13109 result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop ); |
|
13110 } |
|
13111 }); |
|
13112 return this[ spaceName ]( result ); |
|
13113 }, |
|
13114 blend: function( opaque ) { |
|
13115 // if we are already opaque - return ourself |
|
13116 if ( this._rgba[ 3 ] === 1 ) { |
|
13117 return this; |
|
13118 } |
|
13119 |
|
13120 var rgb = this._rgba.slice(), |
|
13121 a = rgb.pop(), |
|
13122 blend = color( opaque )._rgba; |
|
13123 |
|
13124 return color( jQuery.map( rgb, function( v, i ) { |
|
13125 return ( 1 - a ) * blend[ i ] + a * v; |
|
13126 })); |
|
13127 }, |
|
13128 toRgbaString: function() { |
|
13129 var prefix = "rgba(", |
|
13130 rgba = jQuery.map( this._rgba, function( v, i ) { |
|
13131 return v == null ? ( i > 2 ? 1 : 0 ) : v; |
|
13132 }); |
|
13133 |
|
13134 if ( rgba[ 3 ] === 1 ) { |
|
13135 rgba.pop(); |
|
13136 prefix = "rgb("; |
|
13137 } |
|
13138 |
|
13139 return prefix + rgba.join() + ")"; |
|
13140 }, |
|
13141 toHslaString: function() { |
|
13142 var prefix = "hsla(", |
|
13143 hsla = jQuery.map( this.hsla(), function( v, i ) { |
|
13144 if ( v == null ) { |
|
13145 v = i > 2 ? 1 : 0; |
|
13146 } |
|
13147 |
|
13148 // catch 1 and 2 |
|
13149 if ( i && i < 3 ) { |
|
13150 v = Math.round( v * 100 ) + "%"; |
|
13151 } |
|
13152 return v; |
|
13153 }); |
|
13154 |
|
13155 if ( hsla[ 3 ] === 1 ) { |
|
13156 hsla.pop(); |
|
13157 prefix = "hsl("; |
|
13158 } |
|
13159 return prefix + hsla.join() + ")"; |
|
13160 }, |
|
13161 toHexString: function( includeAlpha ) { |
|
13162 var rgba = this._rgba.slice(), |
|
13163 alpha = rgba.pop(); |
|
13164 |
|
13165 if ( includeAlpha ) { |
|
13166 rgba.push( ~~( alpha * 255 ) ); |
|
13167 } |
|
13168 |
|
13169 return "#" + jQuery.map( rgba, function( v ) { |
|
13170 |
|
13171 // default to 0 when nulls exist |
|
13172 v = ( v || 0 ).toString( 16 ); |
|
13173 return v.length === 1 ? "0" + v : v; |
|
13174 }).join(""); |
|
13175 }, |
|
13176 toString: function() { |
|
13177 return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString(); |
|
13178 } |
|
13179 }); |
|
13180 color.fn.parse.prototype = color.fn; |
|
13181 |
|
13182 // hsla conversions adapted from: |
|
13183 // https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021 |
|
13184 |
|
13185 function hue2rgb( p, q, h ) { |
|
13186 h = ( h + 1 ) % 1; |
|
13187 if ( h * 6 < 1 ) { |
|
13188 return p + (q - p) * h * 6; |
|
13189 } |
|
13190 if ( h * 2 < 1) { |
|
13191 return q; |
|
13192 } |
|
13193 if ( h * 3 < 2 ) { |
|
13194 return p + (q - p) * ((2/3) - h) * 6; |
|
13195 } |
|
13196 return p; |
|
13197 } |
|
13198 |
|
13199 spaces.hsla.to = function ( rgba ) { |
|
13200 if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) { |
|
13201 return [ null, null, null, rgba[ 3 ] ]; |
|
13202 } |
|
13203 var r = rgba[ 0 ] / 255, |
|
13204 g = rgba[ 1 ] / 255, |
|
13205 b = rgba[ 2 ] / 255, |
|
13206 a = rgba[ 3 ], |
|
13207 max = Math.max( r, g, b ), |
|
13208 min = Math.min( r, g, b ), |
|
13209 diff = max - min, |
|
13210 add = max + min, |
|
13211 l = add * 0.5, |
|
13212 h, s; |
|
13213 |
|
13214 if ( min === max ) { |
|
13215 h = 0; |
|
13216 } else if ( r === max ) { |
|
13217 h = ( 60 * ( g - b ) / diff ) + 360; |
|
13218 } else if ( g === max ) { |
|
13219 h = ( 60 * ( b - r ) / diff ) + 120; |
|
13220 } else { |
|
13221 h = ( 60 * ( r - g ) / diff ) + 240; |
|
13222 } |
|
13223 |
|
13224 // chroma (diff) == 0 means greyscale which, by definition, saturation = 0% |
|
13225 // otherwise, saturation is based on the ratio of chroma (diff) to lightness (add) |
|
13226 if ( diff === 0 ) { |
|
13227 s = 0; |
|
13228 } else if ( l <= 0.5 ) { |
|
13229 s = diff / add; |
|
13230 } else { |
|
13231 s = diff / ( 2 - add ); |
|
13232 } |
|
13233 return [ Math.round(h) % 360, s, l, a == null ? 1 : a ]; |
|
13234 }; |
|
13235 |
|
13236 spaces.hsla.from = function ( hsla ) { |
|
13237 if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) { |
|
13238 return [ null, null, null, hsla[ 3 ] ]; |
|
13239 } |
|
13240 var h = hsla[ 0 ] / 360, |
|
13241 s = hsla[ 1 ], |
|
13242 l = hsla[ 2 ], |
|
13243 a = hsla[ 3 ], |
|
13244 q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s, |
|
13245 p = 2 * l - q; |
|
13246 |
|
13247 return [ |
|
13248 Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ), |
|
13249 Math.round( hue2rgb( p, q, h ) * 255 ), |
|
13250 Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ), |
|
13251 a |
|
13252 ]; |
|
13253 }; |
|
13254 |
|
13255 |
|
13256 each( spaces, function( spaceName, space ) { |
|
13257 var props = space.props, |
|
13258 cache = space.cache, |
|
13259 to = space.to, |
|
13260 from = space.from; |
|
13261 |
|
13262 // makes rgba() and hsla() |
|
13263 color.fn[ spaceName ] = function( value ) { |
|
13264 |
|
13265 // generate a cache for this space if it doesn't exist |
|
13266 if ( to && !this[ cache ] ) { |
|
13267 this[ cache ] = to( this._rgba ); |
|
13268 } |
|
13269 if ( value === undefined ) { |
|
13270 return this[ cache ].slice(); |
|
13271 } |
|
13272 |
|
13273 var ret, |
|
13274 type = jQuery.type( value ), |
|
13275 arr = ( type === "array" || type === "object" ) ? value : arguments, |
|
13276 local = this[ cache ].slice(); |
|
13277 |
|
13278 each( props, function( key, prop ) { |
|
13279 var val = arr[ type === "object" ? key : prop.idx ]; |
|
13280 if ( val == null ) { |
|
13281 val = local[ prop.idx ]; |
|
13282 } |
|
13283 local[ prop.idx ] = clamp( val, prop ); |
|
13284 }); |
|
13285 |
|
13286 if ( from ) { |
|
13287 ret = color( from( local ) ); |
|
13288 ret[ cache ] = local; |
|
13289 return ret; |
|
13290 } else { |
|
13291 return color( local ); |
|
13292 } |
|
13293 }; |
|
13294 |
|
13295 // makes red() green() blue() alpha() hue() saturation() lightness() |
|
13296 each( props, function( key, prop ) { |
|
13297 // alpha is included in more than one space |
|
13298 if ( color.fn[ key ] ) { |
|
13299 return; |
|
13300 } |
|
13301 color.fn[ key ] = function( value ) { |
|
13302 var vtype = jQuery.type( value ), |
|
13303 fn = ( key === "alpha" ? ( this._hsla ? "hsla" : "rgba" ) : spaceName ), |
|
13304 local = this[ fn ](), |
|
13305 cur = local[ prop.idx ], |
|
13306 match; |
|
13307 |
|
13308 if ( vtype === "undefined" ) { |
|
13309 return cur; |
|
13310 } |
|
13311 |
|
13312 if ( vtype === "function" ) { |
|
13313 value = value.call( this, cur ); |
|
13314 vtype = jQuery.type( value ); |
|
13315 } |
|
13316 if ( value == null && prop.empty ) { |
|
13317 return this; |
|
13318 } |
|
13319 if ( vtype === "string" ) { |
|
13320 match = rplusequals.exec( value ); |
|
13321 if ( match ) { |
|
13322 value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 ); |
|
13323 } |
|
13324 } |
|
13325 local[ prop.idx ] = value; |
|
13326 return this[ fn ]( local ); |
|
13327 }; |
|
13328 }); |
|
13329 }); |
|
13330 |
|
13331 // add cssHook and .fx.step function for each named hook. |
|
13332 // accept a space separated string of properties |
|
13333 color.hook = function( hook ) { |
|
13334 var hooks = hook.split( " " ); |
|
13335 each( hooks, function( i, hook ) { |
|
13336 jQuery.cssHooks[ hook ] = { |
|
13337 set: function( elem, value ) { |
|
13338 var parsed, curElem, |
|
13339 backgroundColor = ""; |
|
13340 |
|
13341 if ( value !== "transparent" && ( jQuery.type( value ) !== "string" || ( parsed = stringParse( value ) ) ) ) { |
|
13342 value = color( parsed || value ); |
|
13343 if ( !support.rgba && value._rgba[ 3 ] !== 1 ) { |
|
13344 curElem = hook === "backgroundColor" ? elem.parentNode : elem; |
|
13345 while ( |
|
13346 (backgroundColor === "" || backgroundColor === "transparent") && |
|
13347 curElem && curElem.style |
|
13348 ) { |
|
13349 try { |
|
13350 backgroundColor = jQuery.css( curElem, "backgroundColor" ); |
|
13351 curElem = curElem.parentNode; |
|
13352 } catch ( e ) { |
|
13353 } |
|
13354 } |
|
13355 |
|
13356 value = value.blend( backgroundColor && backgroundColor !== "transparent" ? |
|
13357 backgroundColor : |
|
13358 "_default" ); |
|
13359 } |
|
13360 |
|
13361 value = value.toRgbaString(); |
|
13362 } |
|
13363 try { |
|
13364 elem.style[ hook ] = value; |
|
13365 } catch( e ) { |
|
13366 // wrapped to prevent IE from throwing errors on "invalid" values like 'auto' or 'inherit' |
|
13367 } |
|
13368 } |
|
13369 }; |
|
13370 jQuery.fx.step[ hook ] = function( fx ) { |
|
13371 if ( !fx.colorInit ) { |
|
13372 fx.start = color( fx.elem, hook ); |
|
13373 fx.end = color( fx.end ); |
|
13374 fx.colorInit = true; |
|
13375 } |
|
13376 jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) ); |
|
13377 }; |
|
13378 }); |
|
13379 |
|
13380 }; |
|
13381 |
|
13382 color.hook( stepHooks ); |
|
13383 |
|
13384 jQuery.cssHooks.borderColor = { |
|
13385 expand: function( value ) { |
|
13386 var expanded = {}; |
|
13387 |
|
13388 each( [ "Top", "Right", "Bottom", "Left" ], function( i, part ) { |
|
13389 expanded[ "border" + part + "Color" ] = value; |
|
13390 }); |
|
13391 return expanded; |
|
13392 } |
|
13393 }; |
|
13394 |
|
13395 // Basic color names only. |
|
13396 // Usage of any of the other color names requires adding yourself or including |
|
13397 // jquery.color.svg-names.js. |
|
13398 colors = jQuery.Color.names = { |
|
13399 // 4.1. Basic color keywords |
|
13400 aqua: "#00ffff", |
|
13401 black: "#000000", |
|
13402 blue: "#0000ff", |
|
13403 fuchsia: "#ff00ff", |
|
13404 gray: "#808080", |
|
13405 green: "#008000", |
|
13406 lime: "#00ff00", |
|
13407 maroon: "#800000", |
|
13408 navy: "#000080", |
|
13409 olive: "#808000", |
|
13410 purple: "#800080", |
|
13411 red: "#ff0000", |
|
13412 silver: "#c0c0c0", |
|
13413 teal: "#008080", |
|
13414 white: "#ffffff", |
|
13415 yellow: "#ffff00", |
|
13416 |
|
13417 // 4.2.3. "transparent" color keyword |
|
13418 transparent: [ null, null, null, 0 ], |
|
13419 |
|
13420 _default: "#ffffff" |
|
13421 }; |
|
13422 |
|
13423 })( jQuery ); |
|
13424 |
|
13425 |
|
13426 /******************************************************************************/ |
|
13427 /****************************** CLASS ANIMATIONS ******************************/ |
|
13428 /******************************************************************************/ |
|
13429 (function() { |
|
13430 |
|
13431 var classAnimationActions = [ "add", "remove", "toggle" ], |
|
13432 shorthandStyles = { |
|
13433 border: 1, |
|
13434 borderBottom: 1, |
|
13435 borderColor: 1, |
|
13436 borderLeft: 1, |
|
13437 borderRight: 1, |
|
13438 borderTop: 1, |
|
13439 borderWidth: 1, |
|
13440 margin: 1, |
|
13441 padding: 1 |
|
13442 }; |
|
13443 |
|
13444 $.each([ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], function( _, prop ) { |
|
13445 $.fx.step[ prop ] = function( fx ) { |
|
13446 if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) { |
|
13447 jQuery.style( fx.elem, prop, fx.end ); |
|
13448 fx.setAttr = true; |
|
13449 } |
|
13450 }; |
|
13451 }); |
|
13452 |
|
13453 function getElementStyles( elem ) { |
|
13454 var key, len, |
|
13455 style = elem.ownerDocument.defaultView ? |
|
13456 elem.ownerDocument.defaultView.getComputedStyle( elem, null ) : |
|
13457 elem.currentStyle, |
|
13458 styles = {}; |
|
13459 |
|
13460 if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) { |
|
13461 len = style.length; |
|
13462 while ( len-- ) { |
|
13463 key = style[ len ]; |
|
13464 if ( typeof style[ key ] === "string" ) { |
|
13465 styles[ $.camelCase( key ) ] = style[ key ]; |
|
13466 } |
|
13467 } |
|
13468 // support: Opera, IE <9 |
|
13469 } else { |
|
13470 for ( key in style ) { |
|
13471 if ( typeof style[ key ] === "string" ) { |
|
13472 styles[ key ] = style[ key ]; |
|
13473 } |
|
13474 } |
|
13475 } |
|
13476 |
|
13477 return styles; |
|
13478 } |
|
13479 |
|
13480 |
|
13481 function styleDifference( oldStyle, newStyle ) { |
|
13482 var diff = {}, |
|
13483 name, value; |
|
13484 |
|
13485 for ( name in newStyle ) { |
|
13486 value = newStyle[ name ]; |
|
13487 if ( oldStyle[ name ] !== value ) { |
|
13488 if ( !shorthandStyles[ name ] ) { |
|
13489 if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) { |
|
13490 diff[ name ] = value; |
|
13491 } |
|
13492 } |
|
13493 } |
|
13494 } |
|
13495 |
|
13496 return diff; |
|
13497 } |
|
13498 |
|
13499 // support: jQuery <1.8 |
|
13500 if ( !$.fn.addBack ) { |
|
13501 $.fn.addBack = function( selector ) { |
|
13502 return this.add( selector == null ? |
|
13503 this.prevObject : this.prevObject.filter( selector ) |
|
13504 ); |
|
13505 }; |
|
13506 } |
|
13507 |
|
13508 $.effects.animateClass = function( value, duration, easing, callback ) { |
|
13509 var o = $.speed( duration, easing, callback ); |
|
13510 |
|
13511 return this.queue( function() { |
|
13512 var animated = $( this ), |
|
13513 baseClass = animated.attr( "class" ) || "", |
|
13514 applyClassChange, |
|
13515 allAnimations = o.children ? animated.find( "*" ).addBack() : animated; |
|
13516 |
|
13517 // map the animated objects to store the original styles. |
|
13518 allAnimations = allAnimations.map(function() { |
|
13519 var el = $( this ); |
|
13520 return { |
|
13521 el: el, |
|
13522 start: getElementStyles( this ) |
|
13523 }; |
|
13524 }); |
|
13525 |
|
13526 // apply class change |
|
13527 applyClassChange = function() { |
|
13528 $.each( classAnimationActions, function(i, action) { |
|
13529 if ( value[ action ] ) { |
|
13530 animated[ action + "Class" ]( value[ action ] ); |
|
13531 } |
|
13532 }); |
|
13533 }; |
|
13534 applyClassChange(); |
|
13535 |
|
13536 // map all animated objects again - calculate new styles and diff |
|
13537 allAnimations = allAnimations.map(function() { |
|
13538 this.end = getElementStyles( this.el[ 0 ] ); |
|
13539 this.diff = styleDifference( this.start, this.end ); |
|
13540 return this; |
|
13541 }); |
|
13542 |
|
13543 // apply original class |
|
13544 animated.attr( "class", baseClass ); |
|
13545 |
|
13546 // map all animated objects again - this time collecting a promise |
|
13547 allAnimations = allAnimations.map(function() { |
|
13548 var styleInfo = this, |
|
13549 dfd = $.Deferred(), |
|
13550 opts = $.extend({}, o, { |
|
13551 queue: false, |
|
13552 complete: function() { |
|
13553 dfd.resolve( styleInfo ); |
|
13554 } |
|
13555 }); |
|
13556 |
|
13557 this.el.animate( this.diff, opts ); |
|
13558 return dfd.promise(); |
|
13559 }); |
|
13560 |
|
13561 // once all animations have completed: |
|
13562 $.when.apply( $, allAnimations.get() ).done(function() { |
|
13563 |
|
13564 // set the final class |
|
13565 applyClassChange(); |
|
13566 |
|
13567 // for each animated element, |
|
13568 // clear all css properties that were animated |
|
13569 $.each( arguments, function() { |
|
13570 var el = this.el; |
|
13571 $.each( this.diff, function(key) { |
|
13572 el.css( key, "" ); |
|
13573 }); |
|
13574 }); |
|
13575 |
|
13576 // this is guarnteed to be there if you use jQuery.speed() |
|
13577 // it also handles dequeuing the next anim... |
|
13578 o.complete.call( animated[ 0 ] ); |
|
13579 }); |
|
13580 }); |
|
13581 }; |
|
13582 |
|
13583 $.fn.extend({ |
|
13584 addClass: (function( orig ) { |
|
13585 return function( classNames, speed, easing, callback ) { |
|
13586 return speed ? |
|
13587 $.effects.animateClass.call( this, |
|
13588 { add: classNames }, speed, easing, callback ) : |
|
13589 orig.apply( this, arguments ); |
|
13590 }; |
|
13591 })( $.fn.addClass ), |
|
13592 |
|
13593 removeClass: (function( orig ) { |
|
13594 return function( classNames, speed, easing, callback ) { |
|
13595 return arguments.length > 1 ? |
|
13596 $.effects.animateClass.call( this, |
|
13597 { remove: classNames }, speed, easing, callback ) : |
|
13598 orig.apply( this, arguments ); |
|
13599 }; |
|
13600 })( $.fn.removeClass ), |
|
13601 |
|
13602 toggleClass: (function( orig ) { |
|
13603 return function( classNames, force, speed, easing, callback ) { |
|
13604 if ( typeof force === "boolean" || force === undefined ) { |
|
13605 if ( !speed ) { |
|
13606 // without speed parameter |
|
13607 return orig.apply( this, arguments ); |
|
13608 } else { |
|
13609 return $.effects.animateClass.call( this, |
|
13610 (force ? { add: classNames } : { remove: classNames }), |
|
13611 speed, easing, callback ); |
|
13612 } |
|
13613 } else { |
|
13614 // without force parameter |
|
13615 return $.effects.animateClass.call( this, |
|
13616 { toggle: classNames }, force, speed, easing ); |
|
13617 } |
|
13618 }; |
|
13619 })( $.fn.toggleClass ), |
|
13620 |
|
13621 switchClass: function( remove, add, speed, easing, callback) { |
|
13622 return $.effects.animateClass.call( this, { |
|
13623 add: add, |
|
13624 remove: remove |
|
13625 }, speed, easing, callback ); |
|
13626 } |
|
13627 }); |
|
13628 |
|
13629 })(); |
|
13630 |
|
13631 /******************************************************************************/ |
|
13632 /*********************************** EFFECTS **********************************/ |
|
13633 /******************************************************************************/ |
|
13634 |
|
13635 (function() { |
|
13636 |
|
13637 $.extend( $.effects, { |
|
13638 version: "1.10.4", |
|
13639 |
|
13640 // Saves a set of properties in a data storage |
|
13641 save: function( element, set ) { |
|
13642 for( var i=0; i < set.length; i++ ) { |
|
13643 if ( set[ i ] !== null ) { |
|
13644 element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] ); |
|
13645 } |
|
13646 } |
|
13647 }, |
|
13648 |
|
13649 // Restores a set of previously saved properties from a data storage |
|
13650 restore: function( element, set ) { |
|
13651 var val, i; |
|
13652 for( i=0; i < set.length; i++ ) { |
|
13653 if ( set[ i ] !== null ) { |
|
13654 val = element.data( dataSpace + set[ i ] ); |
|
13655 // support: jQuery 1.6.2 |
|
13656 // http://bugs.jquery.com/ticket/9917 |
|
13657 // jQuery 1.6.2 incorrectly returns undefined for any falsy value. |
|
13658 // We can't differentiate between "" and 0 here, so we just assume |
|
13659 // empty string since it's likely to be a more common value... |
|
13660 if ( val === undefined ) { |
|
13661 val = ""; |
|
13662 } |
|
13663 element.css( set[ i ], val ); |
|
13664 } |
|
13665 } |
|
13666 }, |
|
13667 |
|
13668 setMode: function( el, mode ) { |
|
13669 if (mode === "toggle") { |
|
13670 mode = el.is( ":hidden" ) ? "show" : "hide"; |
|
13671 } |
|
13672 return mode; |
|
13673 }, |
|
13674 |
|
13675 // Translates a [top,left] array into a baseline value |
|
13676 // this should be a little more flexible in the future to handle a string & hash |
|
13677 getBaseline: function( origin, original ) { |
|
13678 var y, x; |
|
13679 switch ( origin[ 0 ] ) { |
|
13680 case "top": y = 0; break; |
|
13681 case "middle": y = 0.5; break; |
|
13682 case "bottom": y = 1; break; |
|
13683 default: y = origin[ 0 ] / original.height; |
|
13684 } |
|
13685 switch ( origin[ 1 ] ) { |
|
13686 case "left": x = 0; break; |
|
13687 case "center": x = 0.5; break; |
|
13688 case "right": x = 1; break; |
|
13689 default: x = origin[ 1 ] / original.width; |
|
13690 } |
|
13691 return { |
|
13692 x: x, |
|
13693 y: y |
|
13694 }; |
|
13695 }, |
|
13696 |
|
13697 // Wraps the element around a wrapper that copies position properties |
|
13698 createWrapper: function( element ) { |
|
13699 |
|
13700 // if the element is already wrapped, return it |
|
13701 if ( element.parent().is( ".ui-effects-wrapper" )) { |
|
13702 return element.parent(); |
|
13703 } |
|
13704 |
|
13705 // wrap the element |
|
13706 var props = { |
|
13707 width: element.outerWidth(true), |
|
13708 height: element.outerHeight(true), |
|
13709 "float": element.css( "float" ) |
|
13710 }, |
|
13711 wrapper = $( "<div></div>" ) |
|
13712 .addClass( "ui-effects-wrapper" ) |
|
13713 .css({ |
|
13714 fontSize: "100%", |
|
13715 background: "transparent", |
|
13716 border: "none", |
|
13717 margin: 0, |
|
13718 padding: 0 |
|
13719 }), |
|
13720 // Store the size in case width/height are defined in % - Fixes #5245 |
|
13721 size = { |
|
13722 width: element.width(), |
|
13723 height: element.height() |
|
13724 }, |
|
13725 active = document.activeElement; |
|
13726 |
|
13727 // support: Firefox |
|
13728 // Firefox incorrectly exposes anonymous content |
|
13729 // https://bugzilla.mozilla.org/show_bug.cgi?id=561664 |
|
13730 try { |
|
13731 active.id; |
|
13732 } catch( e ) { |
|
13733 active = document.body; |
|
13734 } |
|
13735 |
|
13736 element.wrap( wrapper ); |
|
13737 |
|
13738 // Fixes #7595 - Elements lose focus when wrapped. |
|
13739 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { |
|
13740 $( active ).focus(); |
|
13741 } |
|
13742 |
|
13743 wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually lose the reference to the wrapped element |
|
13744 |
|
13745 // transfer positioning properties to the wrapper |
|
13746 if ( element.css( "position" ) === "static" ) { |
|
13747 wrapper.css({ position: "relative" }); |
|
13748 element.css({ position: "relative" }); |
|
13749 } else { |
|
13750 $.extend( props, { |
|
13751 position: element.css( "position" ), |
|
13752 zIndex: element.css( "z-index" ) |
|
13753 }); |
|
13754 $.each([ "top", "left", "bottom", "right" ], function(i, pos) { |
|
13755 props[ pos ] = element.css( pos ); |
|
13756 if ( isNaN( parseInt( props[ pos ], 10 ) ) ) { |
|
13757 props[ pos ] = "auto"; |
|
13758 } |
|
13759 }); |
|
13760 element.css({ |
|
13761 position: "relative", |
|
13762 top: 0, |
|
13763 left: 0, |
|
13764 right: "auto", |
|
13765 bottom: "auto" |
|
13766 }); |
|
13767 } |
|
13768 element.css(size); |
|
13769 |
|
13770 return wrapper.css( props ).show(); |
|
13771 }, |
|
13772 |
|
13773 removeWrapper: function( element ) { |
|
13774 var active = document.activeElement; |
|
13775 |
|
13776 if ( element.parent().is( ".ui-effects-wrapper" ) ) { |
|
13777 element.parent().replaceWith( element ); |
|
13778 |
|
13779 // Fixes #7595 - Elements lose focus when wrapped. |
|
13780 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { |
|
13781 $( active ).focus(); |
|
13782 } |
|
13783 } |
|
13784 |
|
13785 |
|
13786 return element; |
|
13787 }, |
|
13788 |
|
13789 setTransition: function( element, list, factor, value ) { |
|
13790 value = value || {}; |
|
13791 $.each( list, function( i, x ) { |
|
13792 var unit = element.cssUnit( x ); |
|
13793 if ( unit[ 0 ] > 0 ) { |
|
13794 value[ x ] = unit[ 0 ] * factor + unit[ 1 ]; |
|
13795 } |
|
13796 }); |
|
13797 return value; |
|
13798 } |
|
13799 }); |
|
13800 |
|
13801 // return an effect options object for the given parameters: |
|
13802 function _normalizeArguments( effect, options, speed, callback ) { |
|
13803 |
|
13804 // allow passing all options as the first parameter |
|
13805 if ( $.isPlainObject( effect ) ) { |
|
13806 options = effect; |
|
13807 effect = effect.effect; |
|
13808 } |
|
13809 |
|
13810 // convert to an object |
|
13811 effect = { effect: effect }; |
|
13812 |
|
13813 // catch (effect, null, ...) |
|
13814 if ( options == null ) { |
|
13815 options = {}; |
|
13816 } |
|
13817 |
|
13818 // catch (effect, callback) |
|
13819 if ( $.isFunction( options ) ) { |
|
13820 callback = options; |
|
13821 speed = null; |
|
13822 options = {}; |
|
13823 } |
|
13824 |
|
13825 // catch (effect, speed, ?) |
|
13826 if ( typeof options === "number" || $.fx.speeds[ options ] ) { |
|
13827 callback = speed; |
|
13828 speed = options; |
|
13829 options = {}; |
|
13830 } |
|
13831 |
|
13832 // catch (effect, options, callback) |
|
13833 if ( $.isFunction( speed ) ) { |
|
13834 callback = speed; |
|
13835 speed = null; |
|
13836 } |
|
13837 |
|
13838 // add options to effect |
|
13839 if ( options ) { |
|
13840 $.extend( effect, options ); |
|
13841 } |
|
13842 |
|
13843 speed = speed || options.duration; |
|
13844 effect.duration = $.fx.off ? 0 : |
|
13845 typeof speed === "number" ? speed : |
|
13846 speed in $.fx.speeds ? $.fx.speeds[ speed ] : |
|
13847 $.fx.speeds._default; |
|
13848 |
|
13849 effect.complete = callback || options.complete; |
|
13850 |
|
13851 return effect; |
|
13852 } |
|
13853 |
|
13854 function standardAnimationOption( option ) { |
|
13855 // Valid standard speeds (nothing, number, named speed) |
|
13856 if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) { |
|
13857 return true; |
|
13858 } |
|
13859 |
|
13860 // Invalid strings - treat as "normal" speed |
|
13861 if ( typeof option === "string" && !$.effects.effect[ option ] ) { |
|
13862 return true; |
|
13863 } |
|
13864 |
|
13865 // Complete callback |
|
13866 if ( $.isFunction( option ) ) { |
|
13867 return true; |
|
13868 } |
|
13869 |
|
13870 // Options hash (but not naming an effect) |
|
13871 if ( typeof option === "object" && !option.effect ) { |
|
13872 return true; |
|
13873 } |
|
13874 |
|
13875 // Didn't match any standard API |
|
13876 return false; |
|
13877 } |
|
13878 |
|
13879 $.fn.extend({ |
|
13880 effect: function( /* effect, options, speed, callback */ ) { |
|
13881 var args = _normalizeArguments.apply( this, arguments ), |
|
13882 mode = args.mode, |
|
13883 queue = args.queue, |
|
13884 effectMethod = $.effects.effect[ args.effect ]; |
|
13885 |
|
13886 if ( $.fx.off || !effectMethod ) { |
|
13887 // delegate to the original method (e.g., .show()) if possible |
|
13888 if ( mode ) { |
|
13889 return this[ mode ]( args.duration, args.complete ); |
|
13890 } else { |
|
13891 return this.each( function() { |
|
13892 if ( args.complete ) { |
|
13893 args.complete.call( this ); |
|
13894 } |
|
13895 }); |
|
13896 } |
|
13897 } |
|
13898 |
|
13899 function run( next ) { |
|
13900 var elem = $( this ), |
|
13901 complete = args.complete, |
|
13902 mode = args.mode; |
|
13903 |
|
13904 function done() { |
|
13905 if ( $.isFunction( complete ) ) { |
|
13906 complete.call( elem[0] ); |
|
13907 } |
|
13908 if ( $.isFunction( next ) ) { |
|
13909 next(); |
|
13910 } |
|
13911 } |
|
13912 |
|
13913 // If the element already has the correct final state, delegate to |
|
13914 // the core methods so the internal tracking of "olddisplay" works. |
|
13915 if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) { |
|
13916 elem[ mode ](); |
|
13917 done(); |
|
13918 } else { |
|
13919 effectMethod.call( elem[0], args, done ); |
|
13920 } |
|
13921 } |
|
13922 |
|
13923 return queue === false ? this.each( run ) : this.queue( queue || "fx", run ); |
|
13924 }, |
|
13925 |
|
13926 show: (function( orig ) { |
|
13927 return function( option ) { |
|
13928 if ( standardAnimationOption( option ) ) { |
|
13929 return orig.apply( this, arguments ); |
|
13930 } else { |
|
13931 var args = _normalizeArguments.apply( this, arguments ); |
|
13932 args.mode = "show"; |
|
13933 return this.effect.call( this, args ); |
|
13934 } |
|
13935 }; |
|
13936 })( $.fn.show ), |
|
13937 |
|
13938 hide: (function( orig ) { |
|
13939 return function( option ) { |
|
13940 if ( standardAnimationOption( option ) ) { |
|
13941 return orig.apply( this, arguments ); |
|
13942 } else { |
|
13943 var args = _normalizeArguments.apply( this, arguments ); |
|
13944 args.mode = "hide"; |
|
13945 return this.effect.call( this, args ); |
|
13946 } |
|
13947 }; |
|
13948 })( $.fn.hide ), |
|
13949 |
|
13950 toggle: (function( orig ) { |
|
13951 return function( option ) { |
|
13952 if ( standardAnimationOption( option ) || typeof option === "boolean" ) { |
|
13953 return orig.apply( this, arguments ); |
|
13954 } else { |
|
13955 var args = _normalizeArguments.apply( this, arguments ); |
|
13956 args.mode = "toggle"; |
|
13957 return this.effect.call( this, args ); |
|
13958 } |
|
13959 }; |
|
13960 })( $.fn.toggle ), |
|
13961 |
|
13962 // helper functions |
|
13963 cssUnit: function(key) { |
|
13964 var style = this.css( key ), |
|
13965 val = []; |
|
13966 |
|
13967 $.each( [ "em", "px", "%", "pt" ], function( i, unit ) { |
|
13968 if ( style.indexOf( unit ) > 0 ) { |
|
13969 val = [ parseFloat( style ), unit ]; |
|
13970 } |
|
13971 }); |
|
13972 return val; |
|
13973 } |
|
13974 }); |
|
13975 |
|
13976 })(); |
|
13977 |
|
13978 /******************************************************************************/ |
|
13979 /*********************************** EASING ***********************************/ |
|
13980 /******************************************************************************/ |
|
13981 |
|
13982 (function() { |
|
13983 |
|
13984 // based on easing equations from Robert Penner (http://www.robertpenner.com/easing) |
|
13985 |
|
13986 var baseEasings = {}; |
|
13987 |
|
13988 $.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) { |
|
13989 baseEasings[ name ] = function( p ) { |
|
13990 return Math.pow( p, i + 2 ); |
|
13991 }; |
|
13992 }); |
|
13993 |
|
13994 $.extend( baseEasings, { |
|
13995 Sine: function ( p ) { |
|
13996 return 1 - Math.cos( p * Math.PI / 2 ); |
|
13997 }, |
|
13998 Circ: function ( p ) { |
|
13999 return 1 - Math.sqrt( 1 - p * p ); |
|
14000 }, |
|
14001 Elastic: function( p ) { |
|
14002 return p === 0 || p === 1 ? p : |
|
14003 -Math.pow( 2, 8 * (p - 1) ) * Math.sin( ( (p - 1) * 80 - 7.5 ) * Math.PI / 15 ); |
|
14004 }, |
|
14005 Back: function( p ) { |
|
14006 return p * p * ( 3 * p - 2 ); |
|
14007 }, |
|
14008 Bounce: function ( p ) { |
|
14009 var pow2, |
|
14010 bounce = 4; |
|
14011 |
|
14012 while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {} |
|
14013 return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 ); |
|
14014 } |
|
14015 }); |
|
14016 |
|
14017 $.each( baseEasings, function( name, easeIn ) { |
|
14018 $.easing[ "easeIn" + name ] = easeIn; |
|
14019 $.easing[ "easeOut" + name ] = function( p ) { |
|
14020 return 1 - easeIn( 1 - p ); |
|
14021 }; |
|
14022 $.easing[ "easeInOut" + name ] = function( p ) { |
|
14023 return p < 0.5 ? |
|
14024 easeIn( p * 2 ) / 2 : |
|
14025 1 - easeIn( p * -2 + 2 ) / 2; |
|
14026 }; |
|
14027 }); |
|
14028 |
|
14029 })(); |
|
14030 |
|
14031 })(jQuery); |
|
14032 (function( $, undefined ) { |
|
14033 |
|
14034 var rvertical = /up|down|vertical/, |
|
14035 rpositivemotion = /up|left|vertical|horizontal/; |
|
14036 |
|
14037 $.effects.effect.blind = function( o, done ) { |
|
14038 // Create element |
|
14039 var el = $( this ), |
|
14040 props = [ "position", "top", "bottom", "left", "right", "height", "width" ], |
|
14041 mode = $.effects.setMode( el, o.mode || "hide" ), |
|
14042 direction = o.direction || "up", |
|
14043 vertical = rvertical.test( direction ), |
|
14044 ref = vertical ? "height" : "width", |
|
14045 ref2 = vertical ? "top" : "left", |
|
14046 motion = rpositivemotion.test( direction ), |
|
14047 animation = {}, |
|
14048 show = mode === "show", |
|
14049 wrapper, distance, margin; |
|
14050 |
|
14051 // if already wrapped, the wrapper's properties are my property. #6245 |
|
14052 if ( el.parent().is( ".ui-effects-wrapper" ) ) { |
|
14053 $.effects.save( el.parent(), props ); |
|
14054 } else { |
|
14055 $.effects.save( el, props ); |
|
14056 } |
|
14057 el.show(); |
|
14058 wrapper = $.effects.createWrapper( el ).css({ |
|
14059 overflow: "hidden" |
|
14060 }); |
|
14061 |
|
14062 distance = wrapper[ ref ](); |
|
14063 margin = parseFloat( wrapper.css( ref2 ) ) || 0; |
|
14064 |
|
14065 animation[ ref ] = show ? distance : 0; |
|
14066 if ( !motion ) { |
|
14067 el |
|
14068 .css( vertical ? "bottom" : "right", 0 ) |
|
14069 .css( vertical ? "top" : "left", "auto" ) |
|
14070 .css({ position: "absolute" }); |
|
14071 |
|
14072 animation[ ref2 ] = show ? margin : distance + margin; |
|
14073 } |
|
14074 |
|
14075 // start at 0 if we are showing |
|
14076 if ( show ) { |
|
14077 wrapper.css( ref, 0 ); |
|
14078 if ( ! motion ) { |
|
14079 wrapper.css( ref2, margin + distance ); |
|
14080 } |
|
14081 } |
|
14082 |
|
14083 // Animate |
|
14084 wrapper.animate( animation, { |
|
14085 duration: o.duration, |
|
14086 easing: o.easing, |
|
14087 queue: false, |
|
14088 complete: function() { |
|
14089 if ( mode === "hide" ) { |
|
14090 el.hide(); |
|
14091 } |
|
14092 $.effects.restore( el, props ); |
|
14093 $.effects.removeWrapper( el ); |
|
14094 done(); |
|
14095 } |
|
14096 }); |
|
14097 |
|
14098 }; |
|
14099 |
|
14100 })(jQuery); |
|
14101 (function( $, undefined ) { |
|
14102 |
|
14103 $.effects.effect.bounce = function( o, done ) { |
|
14104 var el = $( this ), |
|
14105 props = [ "position", "top", "bottom", "left", "right", "height", "width" ], |
|
14106 |
|
14107 // defaults: |
|
14108 mode = $.effects.setMode( el, o.mode || "effect" ), |
|
14109 hide = mode === "hide", |
|
14110 show = mode === "show", |
|
14111 direction = o.direction || "up", |
|
14112 distance = o.distance, |
|
14113 times = o.times || 5, |
|
14114 |
|
14115 // number of internal animations |
|
14116 anims = times * 2 + ( show || hide ? 1 : 0 ), |
|
14117 speed = o.duration / anims, |
|
14118 easing = o.easing, |
|
14119 |
|
14120 // utility: |
|
14121 ref = ( direction === "up" || direction === "down" ) ? "top" : "left", |
|
14122 motion = ( direction === "up" || direction === "left" ), |
|
14123 i, |
|
14124 upAnim, |
|
14125 downAnim, |
|
14126 |
|
14127 // we will need to re-assemble the queue to stack our animations in place |
|
14128 queue = el.queue(), |
|
14129 queuelen = queue.length; |
|
14130 |
|
14131 // Avoid touching opacity to prevent clearType and PNG issues in IE |
|
14132 if ( show || hide ) { |
|
14133 props.push( "opacity" ); |
|
14134 } |
|
14135 |
|
14136 $.effects.save( el, props ); |
|
14137 el.show(); |
|
14138 $.effects.createWrapper( el ); // Create Wrapper |
|
14139 |
|
14140 // default distance for the BIGGEST bounce is the outer Distance / 3 |
|
14141 if ( !distance ) { |
|
14142 distance = el[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3; |
|
14143 } |
|
14144 |
|
14145 if ( show ) { |
|
14146 downAnim = { opacity: 1 }; |
|
14147 downAnim[ ref ] = 0; |
|
14148 |
|
14149 // if we are showing, force opacity 0 and set the initial position |
|
14150 // then do the "first" animation |
|
14151 el.css( "opacity", 0 ) |
|
14152 .css( ref, motion ? -distance * 2 : distance * 2 ) |
|
14153 .animate( downAnim, speed, easing ); |
|
14154 } |
|
14155 |
|
14156 // start at the smallest distance if we are hiding |
|
14157 if ( hide ) { |
|
14158 distance = distance / Math.pow( 2, times - 1 ); |
|
14159 } |
|
14160 |
|
14161 downAnim = {}; |
|
14162 downAnim[ ref ] = 0; |
|
14163 // Bounces up/down/left/right then back to 0 -- times * 2 animations happen here |
|
14164 for ( i = 0; i < times; i++ ) { |
|
14165 upAnim = {}; |
|
14166 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance; |
|
14167 |
|
14168 el.animate( upAnim, speed, easing ) |
|
14169 .animate( downAnim, speed, easing ); |
|
14170 |
|
14171 distance = hide ? distance * 2 : distance / 2; |
|
14172 } |
|
14173 |
|
14174 // Last Bounce when Hiding |
|
14175 if ( hide ) { |
|
14176 upAnim = { opacity: 0 }; |
|
14177 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance; |
|
14178 |
|
14179 el.animate( upAnim, speed, easing ); |
|
14180 } |
|
14181 |
|
14182 el.queue(function() { |
|
14183 if ( hide ) { |
|
14184 el.hide(); |
|
14185 } |
|
14186 $.effects.restore( el, props ); |
|
14187 $.effects.removeWrapper( el ); |
|
14188 done(); |
|
14189 }); |
|
14190 |
|
14191 // inject all the animations we just queued to be first in line (after "inprogress") |
|
14192 if ( queuelen > 1) { |
|
14193 queue.splice.apply( queue, |
|
14194 [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) ); |
|
14195 } |
|
14196 el.dequeue(); |
|
14197 |
|
14198 }; |
|
14199 |
|
14200 })(jQuery); |
|
14201 (function( $, undefined ) { |
|
14202 |
|
14203 $.effects.effect.clip = function( o, done ) { |
|
14204 // Create element |
|
14205 var el = $( this ), |
|
14206 props = [ "position", "top", "bottom", "left", "right", "height", "width" ], |
|
14207 mode = $.effects.setMode( el, o.mode || "hide" ), |
|
14208 show = mode === "show", |
|
14209 direction = o.direction || "vertical", |
|
14210 vert = direction === "vertical", |
|
14211 size = vert ? "height" : "width", |
|
14212 position = vert ? "top" : "left", |
|
14213 animation = {}, |
|
14214 wrapper, animate, distance; |
|
14215 |
|
14216 // Save & Show |
|
14217 $.effects.save( el, props ); |
|
14218 el.show(); |
|
14219 |
|
14220 // Create Wrapper |
|
14221 wrapper = $.effects.createWrapper( el ).css({ |
|
14222 overflow: "hidden" |
|
14223 }); |
|
14224 animate = ( el[0].tagName === "IMG" ) ? wrapper : el; |
|
14225 distance = animate[ size ](); |
|
14226 |
|
14227 // Shift |
|
14228 if ( show ) { |
|
14229 animate.css( size, 0 ); |
|
14230 animate.css( position, distance / 2 ); |
|
14231 } |
|
14232 |
|
14233 // Create Animation Object: |
|
14234 animation[ size ] = show ? distance : 0; |
|
14235 animation[ position ] = show ? 0 : distance / 2; |
|
14236 |
|
14237 // Animate |
|
14238 animate.animate( animation, { |
|
14239 queue: false, |
|
14240 duration: o.duration, |
|
14241 easing: o.easing, |
|
14242 complete: function() { |
|
14243 if ( !show ) { |
|
14244 el.hide(); |
|
14245 } |
|
14246 $.effects.restore( el, props ); |
|
14247 $.effects.removeWrapper( el ); |
|
14248 done(); |
|
14249 } |
|
14250 }); |
|
14251 |
|
14252 }; |
|
14253 |
|
14254 })(jQuery); |
|
14255 (function( $, undefined ) { |
|
14256 |
|
14257 $.effects.effect.drop = function( o, done ) { |
|
14258 |
|
14259 var el = $( this ), |
|
14260 props = [ "position", "top", "bottom", "left", "right", "opacity", "height", "width" ], |
|
14261 mode = $.effects.setMode( el, o.mode || "hide" ), |
|
14262 show = mode === "show", |
|
14263 direction = o.direction || "left", |
|
14264 ref = ( direction === "up" || direction === "down" ) ? "top" : "left", |
|
14265 motion = ( direction === "up" || direction === "left" ) ? "pos" : "neg", |
|
14266 animation = { |
|
14267 opacity: show ? 1 : 0 |
|
14268 }, |
|
14269 distance; |
|
14270 |
|
14271 // Adjust |
|
14272 $.effects.save( el, props ); |
|
14273 el.show(); |
|
14274 $.effects.createWrapper( el ); |
|
14275 |
|
14276 distance = o.distance || el[ ref === "top" ? "outerHeight": "outerWidth" ]( true ) / 2; |
|
14277 |
|
14278 if ( show ) { |
|
14279 el |
|
14280 .css( "opacity", 0 ) |
|
14281 .css( ref, motion === "pos" ? -distance : distance ); |
|
14282 } |
|
14283 |
|
14284 // Animation |
|
14285 animation[ ref ] = ( show ? |
|
14286 ( motion === "pos" ? "+=" : "-=" ) : |
|
14287 ( motion === "pos" ? "-=" : "+=" ) ) + |
|
14288 distance; |
|
14289 |
|
14290 // Animate |
|
14291 el.animate( animation, { |
|
14292 queue: false, |
|
14293 duration: o.duration, |
|
14294 easing: o.easing, |
|
14295 complete: function() { |
|
14296 if ( mode === "hide" ) { |
|
14297 el.hide(); |
|
14298 } |
|
14299 $.effects.restore( el, props ); |
|
14300 $.effects.removeWrapper( el ); |
|
14301 done(); |
|
14302 } |
|
14303 }); |
|
14304 }; |
|
14305 |
|
14306 })(jQuery); |
|
14307 (function( $, undefined ) { |
|
14308 |
|
14309 $.effects.effect.explode = function( o, done ) { |
|
14310 |
|
14311 var rows = o.pieces ? Math.round( Math.sqrt( o.pieces ) ) : 3, |
|
14312 cells = rows, |
|
14313 el = $( this ), |
|
14314 mode = $.effects.setMode( el, o.mode || "hide" ), |
|
14315 show = mode === "show", |
|
14316 |
|
14317 // show and then visibility:hidden the element before calculating offset |
|
14318 offset = el.show().css( "visibility", "hidden" ).offset(), |
|
14319 |
|
14320 // width and height of a piece |
|
14321 width = Math.ceil( el.outerWidth() / cells ), |
|
14322 height = Math.ceil( el.outerHeight() / rows ), |
|
14323 pieces = [], |
|
14324 |
|
14325 // loop |
|
14326 i, j, left, top, mx, my; |
|
14327 |
|
14328 // children animate complete: |
|
14329 function childComplete() { |
|
14330 pieces.push( this ); |
|
14331 if ( pieces.length === rows * cells ) { |
|
14332 animComplete(); |
|
14333 } |
|
14334 } |
|
14335 |
|
14336 // clone the element for each row and cell. |
|
14337 for( i = 0; i < rows ; i++ ) { // ===> |
|
14338 top = offset.top + i * height; |
|
14339 my = i - ( rows - 1 ) / 2 ; |
|
14340 |
|
14341 for( j = 0; j < cells ; j++ ) { // ||| |
|
14342 left = offset.left + j * width; |
|
14343 mx = j - ( cells - 1 ) / 2 ; |
|
14344 |
|
14345 // Create a clone of the now hidden main element that will be absolute positioned |
|
14346 // within a wrapper div off the -left and -top equal to size of our pieces |
|
14347 el |
|
14348 .clone() |
|
14349 .appendTo( "body" ) |
|
14350 .wrap( "<div></div>" ) |
|
14351 .css({ |
|
14352 position: "absolute", |
|
14353 visibility: "visible", |
|
14354 left: -j * width, |
|
14355 top: -i * height |
|
14356 }) |
|
14357 |
|
14358 // select the wrapper - make it overflow: hidden and absolute positioned based on |
|
14359 // where the original was located +left and +top equal to the size of pieces |
|
14360 .parent() |
|
14361 .addClass( "ui-effects-explode" ) |
|
14362 .css({ |
|
14363 position: "absolute", |
|
14364 overflow: "hidden", |
|
14365 width: width, |
|
14366 height: height, |
|
14367 left: left + ( show ? mx * width : 0 ), |
|
14368 top: top + ( show ? my * height : 0 ), |
|
14369 opacity: show ? 0 : 1 |
|
14370 }).animate({ |
|
14371 left: left + ( show ? 0 : mx * width ), |
|
14372 top: top + ( show ? 0 : my * height ), |
|
14373 opacity: show ? 1 : 0 |
|
14374 }, o.duration || 500, o.easing, childComplete ); |
|
14375 } |
|
14376 } |
|
14377 |
|
14378 function animComplete() { |
|
14379 el.css({ |
|
14380 visibility: "visible" |
|
14381 }); |
|
14382 $( pieces ).remove(); |
|
14383 if ( !show ) { |
|
14384 el.hide(); |
|
14385 } |
|
14386 done(); |
|
14387 } |
|
14388 }; |
|
14389 |
|
14390 })(jQuery); |
|
14391 (function( $, undefined ) { |
|
14392 |
|
14393 $.effects.effect.fade = function( o, done ) { |
|
14394 var el = $( this ), |
|
14395 mode = $.effects.setMode( el, o.mode || "toggle" ); |
|
14396 |
|
14397 el.animate({ |
|
14398 opacity: mode |
|
14399 }, { |
|
14400 queue: false, |
|
14401 duration: o.duration, |
|
14402 easing: o.easing, |
|
14403 complete: done |
|
14404 }); |
|
14405 }; |
|
14406 |
|
14407 })( jQuery ); |
|
14408 (function( $, undefined ) { |
|
14409 |
|
14410 $.effects.effect.fold = function( o, done ) { |
|
14411 |
|
14412 // Create element |
|
14413 var el = $( this ), |
|
14414 props = [ "position", "top", "bottom", "left", "right", "height", "width" ], |
|
14415 mode = $.effects.setMode( el, o.mode || "hide" ), |
|
14416 show = mode === "show", |
|
14417 hide = mode === "hide", |
|
14418 size = o.size || 15, |
|
14419 percent = /([0-9]+)%/.exec( size ), |
|
14420 horizFirst = !!o.horizFirst, |
|
14421 widthFirst = show !== horizFirst, |
|
14422 ref = widthFirst ? [ "width", "height" ] : [ "height", "width" ], |
|
14423 duration = o.duration / 2, |
|
14424 wrapper, distance, |
|
14425 animation1 = {}, |
|
14426 animation2 = {}; |
|
14427 |
|
14428 $.effects.save( el, props ); |
|
14429 el.show(); |
|
14430 |
|
14431 // Create Wrapper |
|
14432 wrapper = $.effects.createWrapper( el ).css({ |
|
14433 overflow: "hidden" |
|
14434 }); |
|
14435 distance = widthFirst ? |
|
14436 [ wrapper.width(), wrapper.height() ] : |
|
14437 [ wrapper.height(), wrapper.width() ]; |
|
14438 |
|
14439 if ( percent ) { |
|
14440 size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ]; |
|
14441 } |
|
14442 if ( show ) { |
|
14443 wrapper.css( horizFirst ? { |
|
14444 height: 0, |
|
14445 width: size |
|
14446 } : { |
|
14447 height: size, |
|
14448 width: 0 |
|
14449 }); |
|
14450 } |
|
14451 |
|
14452 // Animation |
|
14453 animation1[ ref[ 0 ] ] = show ? distance[ 0 ] : size; |
|
14454 animation2[ ref[ 1 ] ] = show ? distance[ 1 ] : 0; |
|
14455 |
|
14456 // Animate |
|
14457 wrapper |
|
14458 .animate( animation1, duration, o.easing ) |
|
14459 .animate( animation2, duration, o.easing, function() { |
|
14460 if ( hide ) { |
|
14461 el.hide(); |
|
14462 } |
|
14463 $.effects.restore( el, props ); |
|
14464 $.effects.removeWrapper( el ); |
|
14465 done(); |
|
14466 }); |
|
14467 |
|
14468 }; |
|
14469 |
|
14470 })(jQuery); |
|
14471 (function( $, undefined ) { |
|
14472 |
|
14473 $.effects.effect.highlight = function( o, done ) { |
|
14474 var elem = $( this ), |
|
14475 props = [ "backgroundImage", "backgroundColor", "opacity" ], |
|
14476 mode = $.effects.setMode( elem, o.mode || "show" ), |
|
14477 animation = { |
|
14478 backgroundColor: elem.css( "backgroundColor" ) |
|
14479 }; |
|
14480 |
|
14481 if (mode === "hide") { |
|
14482 animation.opacity = 0; |
|
14483 } |
|
14484 |
|
14485 $.effects.save( elem, props ); |
|
14486 |
|
14487 elem |
|
14488 .show() |
|
14489 .css({ |
|
14490 backgroundImage: "none", |
|
14491 backgroundColor: o.color || "#ffff99" |
|
14492 }) |
|
14493 .animate( animation, { |
|
14494 queue: false, |
|
14495 duration: o.duration, |
|
14496 easing: o.easing, |
|
14497 complete: function() { |
|
14498 if ( mode === "hide" ) { |
|
14499 elem.hide(); |
|
14500 } |
|
14501 $.effects.restore( elem, props ); |
|
14502 done(); |
|
14503 } |
|
14504 }); |
|
14505 }; |
|
14506 |
|
14507 })(jQuery); |
|
14508 (function( $, undefined ) { |
|
14509 |
|
14510 $.effects.effect.pulsate = function( o, done ) { |
|
14511 var elem = $( this ), |
|
14512 mode = $.effects.setMode( elem, o.mode || "show" ), |
|
14513 show = mode === "show", |
|
14514 hide = mode === "hide", |
|
14515 showhide = ( show || mode === "hide" ), |
|
14516 |
|
14517 // showing or hiding leaves of the "last" animation |
|
14518 anims = ( ( o.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ), |
|
14519 duration = o.duration / anims, |
|
14520 animateTo = 0, |
|
14521 queue = elem.queue(), |
|
14522 queuelen = queue.length, |
|
14523 i; |
|
14524 |
|
14525 if ( show || !elem.is(":visible")) { |
|
14526 elem.css( "opacity", 0 ).show(); |
|
14527 animateTo = 1; |
|
14528 } |
|
14529 |
|
14530 // anims - 1 opacity "toggles" |
|
14531 for ( i = 1; i < anims; i++ ) { |
|
14532 elem.animate({ |
|
14533 opacity: animateTo |
|
14534 }, duration, o.easing ); |
|
14535 animateTo = 1 - animateTo; |
|
14536 } |
|
14537 |
|
14538 elem.animate({ |
|
14539 opacity: animateTo |
|
14540 }, duration, o.easing); |
|
14541 |
|
14542 elem.queue(function() { |
|
14543 if ( hide ) { |
|
14544 elem.hide(); |
|
14545 } |
|
14546 done(); |
|
14547 }); |
|
14548 |
|
14549 // We just queued up "anims" animations, we need to put them next in the queue |
|
14550 if ( queuelen > 1 ) { |
|
14551 queue.splice.apply( queue, |
|
14552 [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) ); |
|
14553 } |
|
14554 elem.dequeue(); |
|
14555 }; |
|
14556 |
|
14557 })(jQuery); |
|
14558 (function( $, undefined ) { |
|
14559 |
|
14560 $.effects.effect.puff = function( o, done ) { |
|
14561 var elem = $( this ), |
|
14562 mode = $.effects.setMode( elem, o.mode || "hide" ), |
|
14563 hide = mode === "hide", |
|
14564 percent = parseInt( o.percent, 10 ) || 150, |
|
14565 factor = percent / 100, |
|
14566 original = { |
|
14567 height: elem.height(), |
|
14568 width: elem.width(), |
|
14569 outerHeight: elem.outerHeight(), |
|
14570 outerWidth: elem.outerWidth() |
|
14571 }; |
|
14572 |
|
14573 $.extend( o, { |
|
14574 effect: "scale", |
|
14575 queue: false, |
|
14576 fade: true, |
|
14577 mode: mode, |
|
14578 complete: done, |
|
14579 percent: hide ? percent : 100, |
|
14580 from: hide ? |
|
14581 original : |
|
14582 { |
|
14583 height: original.height * factor, |
|
14584 width: original.width * factor, |
|
14585 outerHeight: original.outerHeight * factor, |
|
14586 outerWidth: original.outerWidth * factor |
|
14587 } |
|
14588 }); |
|
14589 |
|
14590 elem.effect( o ); |
|
14591 }; |
|
14592 |
|
14593 $.effects.effect.scale = function( o, done ) { |
|
14594 |
|
14595 // Create element |
|
14596 var el = $( this ), |
|
14597 options = $.extend( true, {}, o ), |
|
14598 mode = $.effects.setMode( el, o.mode || "effect" ), |
|
14599 percent = parseInt( o.percent, 10 ) || |
|
14600 ( parseInt( o.percent, 10 ) === 0 ? 0 : ( mode === "hide" ? 0 : 100 ) ), |
|
14601 direction = o.direction || "both", |
|
14602 origin = o.origin, |
|
14603 original = { |
|
14604 height: el.height(), |
|
14605 width: el.width(), |
|
14606 outerHeight: el.outerHeight(), |
|
14607 outerWidth: el.outerWidth() |
|
14608 }, |
|
14609 factor = { |
|
14610 y: direction !== "horizontal" ? (percent / 100) : 1, |
|
14611 x: direction !== "vertical" ? (percent / 100) : 1 |
|
14612 }; |
|
14613 |
|
14614 // We are going to pass this effect to the size effect: |
|
14615 options.effect = "size"; |
|
14616 options.queue = false; |
|
14617 options.complete = done; |
|
14618 |
|
14619 // Set default origin and restore for show/hide |
|
14620 if ( mode !== "effect" ) { |
|
14621 options.origin = origin || ["middle","center"]; |
|
14622 options.restore = true; |
|
14623 } |
|
14624 |
|
14625 options.from = o.from || ( mode === "show" ? { |
|
14626 height: 0, |
|
14627 width: 0, |
|
14628 outerHeight: 0, |
|
14629 outerWidth: 0 |
|
14630 } : original ); |
|
14631 options.to = { |
|
14632 height: original.height * factor.y, |
|
14633 width: original.width * factor.x, |
|
14634 outerHeight: original.outerHeight * factor.y, |
|
14635 outerWidth: original.outerWidth * factor.x |
|
14636 }; |
|
14637 |
|
14638 // Fade option to support puff |
|
14639 if ( options.fade ) { |
|
14640 if ( mode === "show" ) { |
|
14641 options.from.opacity = 0; |
|
14642 options.to.opacity = 1; |
|
14643 } |
|
14644 if ( mode === "hide" ) { |
|
14645 options.from.opacity = 1; |
|
14646 options.to.opacity = 0; |
|
14647 } |
|
14648 } |
|
14649 |
|
14650 // Animate |
|
14651 el.effect( options ); |
|
14652 |
|
14653 }; |
|
14654 |
|
14655 $.effects.effect.size = function( o, done ) { |
|
14656 |
|
14657 // Create element |
|
14658 var original, baseline, factor, |
|
14659 el = $( this ), |
|
14660 props0 = [ "position", "top", "bottom", "left", "right", "width", "height", "overflow", "opacity" ], |
|
14661 |
|
14662 // Always restore |
|
14663 props1 = [ "position", "top", "bottom", "left", "right", "overflow", "opacity" ], |
|
14664 |
|
14665 // Copy for children |
|
14666 props2 = [ "width", "height", "overflow" ], |
|
14667 cProps = [ "fontSize" ], |
|
14668 vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ], |
|
14669 hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ], |
|
14670 |
|
14671 // Set options |
|
14672 mode = $.effects.setMode( el, o.mode || "effect" ), |
|
14673 restore = o.restore || mode !== "effect", |
|
14674 scale = o.scale || "both", |
|
14675 origin = o.origin || [ "middle", "center" ], |
|
14676 position = el.css( "position" ), |
|
14677 props = restore ? props0 : props1, |
|
14678 zero = { |
|
14679 height: 0, |
|
14680 width: 0, |
|
14681 outerHeight: 0, |
|
14682 outerWidth: 0 |
|
14683 }; |
|
14684 |
|
14685 if ( mode === "show" ) { |
|
14686 el.show(); |
|
14687 } |
|
14688 original = { |
|
14689 height: el.height(), |
|
14690 width: el.width(), |
|
14691 outerHeight: el.outerHeight(), |
|
14692 outerWidth: el.outerWidth() |
|
14693 }; |
|
14694 |
|
14695 if ( o.mode === "toggle" && mode === "show" ) { |
|
14696 el.from = o.to || zero; |
|
14697 el.to = o.from || original; |
|
14698 } else { |
|
14699 el.from = o.from || ( mode === "show" ? zero : original ); |
|
14700 el.to = o.to || ( mode === "hide" ? zero : original ); |
|
14701 } |
|
14702 |
|
14703 // Set scaling factor |
|
14704 factor = { |
|
14705 from: { |
|
14706 y: el.from.height / original.height, |
|
14707 x: el.from.width / original.width |
|
14708 }, |
|
14709 to: { |
|
14710 y: el.to.height / original.height, |
|
14711 x: el.to.width / original.width |
|
14712 } |
|
14713 }; |
|
14714 |
|
14715 // Scale the css box |
|
14716 if ( scale === "box" || scale === "both" ) { |
|
14717 |
|
14718 // Vertical props scaling |
|
14719 if ( factor.from.y !== factor.to.y ) { |
|
14720 props = props.concat( vProps ); |
|
14721 el.from = $.effects.setTransition( el, vProps, factor.from.y, el.from ); |
|
14722 el.to = $.effects.setTransition( el, vProps, factor.to.y, el.to ); |
|
14723 } |
|
14724 |
|
14725 // Horizontal props scaling |
|
14726 if ( factor.from.x !== factor.to.x ) { |
|
14727 props = props.concat( hProps ); |
|
14728 el.from = $.effects.setTransition( el, hProps, factor.from.x, el.from ); |
|
14729 el.to = $.effects.setTransition( el, hProps, factor.to.x, el.to ); |
|
14730 } |
|
14731 } |
|
14732 |
|
14733 // Scale the content |
|
14734 if ( scale === "content" || scale === "both" ) { |
|
14735 |
|
14736 // Vertical props scaling |
|
14737 if ( factor.from.y !== factor.to.y ) { |
|
14738 props = props.concat( cProps ).concat( props2 ); |
|
14739 el.from = $.effects.setTransition( el, cProps, factor.from.y, el.from ); |
|
14740 el.to = $.effects.setTransition( el, cProps, factor.to.y, el.to ); |
|
14741 } |
|
14742 } |
|
14743 |
|
14744 $.effects.save( el, props ); |
|
14745 el.show(); |
|
14746 $.effects.createWrapper( el ); |
|
14747 el.css( "overflow", "hidden" ).css( el.from ); |
|
14748 |
|
14749 // Adjust |
|
14750 if (origin) { // Calculate baseline shifts |
|
14751 baseline = $.effects.getBaseline( origin, original ); |
|
14752 el.from.top = ( original.outerHeight - el.outerHeight() ) * baseline.y; |
|
14753 el.from.left = ( original.outerWidth - el.outerWidth() ) * baseline.x; |
|
14754 el.to.top = ( original.outerHeight - el.to.outerHeight ) * baseline.y; |
|
14755 el.to.left = ( original.outerWidth - el.to.outerWidth ) * baseline.x; |
|
14756 } |
|
14757 el.css( el.from ); // set top & left |
|
14758 |
|
14759 // Animate |
|
14760 if ( scale === "content" || scale === "both" ) { // Scale the children |
|
14761 |
|
14762 // Add margins/font-size |
|
14763 vProps = vProps.concat([ "marginTop", "marginBottom" ]).concat(cProps); |
|
14764 hProps = hProps.concat([ "marginLeft", "marginRight" ]); |
|
14765 props2 = props0.concat(vProps).concat(hProps); |
|
14766 |
|
14767 el.find( "*[width]" ).each( function(){ |
|
14768 var child = $( this ), |
|
14769 c_original = { |
|
14770 height: child.height(), |
|
14771 width: child.width(), |
|
14772 outerHeight: child.outerHeight(), |
|
14773 outerWidth: child.outerWidth() |
|
14774 }; |
|
14775 if (restore) { |
|
14776 $.effects.save(child, props2); |
|
14777 } |
|
14778 |
|
14779 child.from = { |
|
14780 height: c_original.height * factor.from.y, |
|
14781 width: c_original.width * factor.from.x, |
|
14782 outerHeight: c_original.outerHeight * factor.from.y, |
|
14783 outerWidth: c_original.outerWidth * factor.from.x |
|
14784 }; |
|
14785 child.to = { |
|
14786 height: c_original.height * factor.to.y, |
|
14787 width: c_original.width * factor.to.x, |
|
14788 outerHeight: c_original.height * factor.to.y, |
|
14789 outerWidth: c_original.width * factor.to.x |
|
14790 }; |
|
14791 |
|
14792 // Vertical props scaling |
|
14793 if ( factor.from.y !== factor.to.y ) { |
|
14794 child.from = $.effects.setTransition( child, vProps, factor.from.y, child.from ); |
|
14795 child.to = $.effects.setTransition( child, vProps, factor.to.y, child.to ); |
|
14796 } |
|
14797 |
|
14798 // Horizontal props scaling |
|
14799 if ( factor.from.x !== factor.to.x ) { |
|
14800 child.from = $.effects.setTransition( child, hProps, factor.from.x, child.from ); |
|
14801 child.to = $.effects.setTransition( child, hProps, factor.to.x, child.to ); |
|
14802 } |
|
14803 |
|
14804 // Animate children |
|
14805 child.css( child.from ); |
|
14806 child.animate( child.to, o.duration, o.easing, function() { |
|
14807 |
|
14808 // Restore children |
|
14809 if ( restore ) { |
|
14810 $.effects.restore( child, props2 ); |
|
14811 } |
|
14812 }); |
|
14813 }); |
|
14814 } |
|
14815 |
|
14816 // Animate |
|
14817 el.animate( el.to, { |
|
14818 queue: false, |
|
14819 duration: o.duration, |
|
14820 easing: o.easing, |
|
14821 complete: function() { |
|
14822 if ( el.to.opacity === 0 ) { |
|
14823 el.css( "opacity", el.from.opacity ); |
|
14824 } |
|
14825 if( mode === "hide" ) { |
|
14826 el.hide(); |
|
14827 } |
|
14828 $.effects.restore( el, props ); |
|
14829 if ( !restore ) { |
|
14830 |
|
14831 // we need to calculate our new positioning based on the scaling |
|
14832 if ( position === "static" ) { |
|
14833 el.css({ |
|
14834 position: "relative", |
|
14835 top: el.to.top, |
|
14836 left: el.to.left |
|
14837 }); |
|
14838 } else { |
|
14839 $.each([ "top", "left" ], function( idx, pos ) { |
|
14840 el.css( pos, function( _, str ) { |
|
14841 var val = parseInt( str, 10 ), |
|
14842 toRef = idx ? el.to.left : el.to.top; |
|
14843 |
|
14844 // if original was "auto", recalculate the new value from wrapper |
|
14845 if ( str === "auto" ) { |
|
14846 return toRef + "px"; |
|
14847 } |
|
14848 |
|
14849 return val + toRef + "px"; |
|
14850 }); |
|
14851 }); |
|
14852 } |
|
14853 } |
|
14854 |
|
14855 $.effects.removeWrapper( el ); |
|
14856 done(); |
|
14857 } |
|
14858 }); |
|
14859 |
|
14860 }; |
|
14861 |
|
14862 })(jQuery); |
|
14863 (function( $, undefined ) { |
|
14864 |
|
14865 $.effects.effect.shake = function( o, done ) { |
|
14866 |
|
14867 var el = $( this ), |
|
14868 props = [ "position", "top", "bottom", "left", "right", "height", "width" ], |
|
14869 mode = $.effects.setMode( el, o.mode || "effect" ), |
|
14870 direction = o.direction || "left", |
|
14871 distance = o.distance || 20, |
|
14872 times = o.times || 3, |
|
14873 anims = times * 2 + 1, |
|
14874 speed = Math.round(o.duration/anims), |
|
14875 ref = (direction === "up" || direction === "down") ? "top" : "left", |
|
14876 positiveMotion = (direction === "up" || direction === "left"), |
|
14877 animation = {}, |
|
14878 animation1 = {}, |
|
14879 animation2 = {}, |
|
14880 i, |
|
14881 |
|
14882 // we will need to re-assemble the queue to stack our animations in place |
|
14883 queue = el.queue(), |
|
14884 queuelen = queue.length; |
|
14885 |
|
14886 $.effects.save( el, props ); |
|
14887 el.show(); |
|
14888 $.effects.createWrapper( el ); |
|
14889 |
|
14890 // Animation |
|
14891 animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance; |
|
14892 animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2; |
|
14893 animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2; |
|
14894 |
|
14895 // Animate |
|
14896 el.animate( animation, speed, o.easing ); |
|
14897 |
|
14898 // Shakes |
|
14899 for ( i = 1; i < times; i++ ) { |
|
14900 el.animate( animation1, speed, o.easing ).animate( animation2, speed, o.easing ); |
|
14901 } |
|
14902 el |
|
14903 .animate( animation1, speed, o.easing ) |
|
14904 .animate( animation, speed / 2, o.easing ) |
|
14905 .queue(function() { |
|
14906 if ( mode === "hide" ) { |
|
14907 el.hide(); |
|
14908 } |
|
14909 $.effects.restore( el, props ); |
|
14910 $.effects.removeWrapper( el ); |
|
14911 done(); |
|
14912 }); |
|
14913 |
|
14914 // inject all the animations we just queued to be first in line (after "inprogress") |
|
14915 if ( queuelen > 1) { |
|
14916 queue.splice.apply( queue, |
|
14917 [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) ); |
|
14918 } |
|
14919 el.dequeue(); |
|
14920 |
|
14921 }; |
|
14922 |
|
14923 })(jQuery); |
|
14924 (function( $, undefined ) { |
|
14925 |
|
14926 $.effects.effect.slide = function( o, done ) { |
|
14927 |
|
14928 // Create element |
|
14929 var el = $( this ), |
|
14930 props = [ "position", "top", "bottom", "left", "right", "width", "height" ], |
|
14931 mode = $.effects.setMode( el, o.mode || "show" ), |
|
14932 show = mode === "show", |
|
14933 direction = o.direction || "left", |
|
14934 ref = (direction === "up" || direction === "down") ? "top" : "left", |
|
14935 positiveMotion = (direction === "up" || direction === "left"), |
|
14936 distance, |
|
14937 animation = {}; |
|
14938 |
|
14939 // Adjust |
|
14940 $.effects.save( el, props ); |
|
14941 el.show(); |
|
14942 distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ); |
|
14943 |
|
14944 $.effects.createWrapper( el ).css({ |
|
14945 overflow: "hidden" |
|
14946 }); |
|
14947 |
|
14948 if ( show ) { |
|
14949 el.css( ref, positiveMotion ? (isNaN(distance) ? "-" + distance : -distance) : distance ); |
|
14950 } |
|
14951 |
|
14952 // Animation |
|
14953 animation[ ref ] = ( show ? |
|
14954 ( positiveMotion ? "+=" : "-=") : |
|
14955 ( positiveMotion ? "-=" : "+=")) + |
|
14956 distance; |
|
14957 |
|
14958 // Animate |
|
14959 el.animate( animation, { |
|
14960 queue: false, |
|
14961 duration: o.duration, |
|
14962 easing: o.easing, |
|
14963 complete: function() { |
|
14964 if ( mode === "hide" ) { |
|
14965 el.hide(); |
|
14966 } |
|
14967 $.effects.restore( el, props ); |
|
14968 $.effects.removeWrapper( el ); |
|
14969 done(); |
|
14970 } |
|
14971 }); |
|
14972 }; |
|
14973 |
|
14974 })(jQuery); |
|
14975 (function( $, undefined ) { |
|
14976 |
|
14977 $.effects.effect.transfer = function( o, done ) { |
|
14978 var elem = $( this ), |
|
14979 target = $( o.to ), |
|
14980 targetFixed = target.css( "position" ) === "fixed", |
|
14981 body = $("body"), |
|
14982 fixTop = targetFixed ? body.scrollTop() : 0, |
|
14983 fixLeft = targetFixed ? body.scrollLeft() : 0, |
|
14984 endPosition = target.offset(), |
|
14985 animation = { |
|
14986 top: endPosition.top - fixTop , |
|
14987 left: endPosition.left - fixLeft , |
|
14988 height: target.innerHeight(), |
|
14989 width: target.innerWidth() |
|
14990 }, |
|
14991 startPosition = elem.offset(), |
|
14992 transfer = $( "<div class='ui-effects-transfer'></div>" ) |
|
14993 .appendTo( document.body ) |
|
14994 .addClass( o.className ) |
|
14995 .css({ |
|
14996 top: startPosition.top - fixTop , |
|
14997 left: startPosition.left - fixLeft , |
|
14998 height: elem.innerHeight(), |
|
14999 width: elem.innerWidth(), |
|
15000 position: targetFixed ? "fixed" : "absolute" |
|
15001 }) |
|
15002 .animate( animation, o.duration, o.easing, function() { |
|
15003 transfer.remove(); |
|
15004 done(); |
|
15005 }); |
|
15006 }; |
|
15007 |
|
15008 })(jQuery); |
|