" ) )
.addClass( "ui-dialog-buttonset" )
.appendTo( uiDialogButtonPane );
uiDialog.attr({
role: "dialog",
"aria-labelledby": uiDialogTitle.attr( "id" )
});
uiDialogTitlebar.find( "*" ).add( uiDialogTitlebar ).disableSelection();
this._hoverable( uiDialogTitlebarClose );
this._focusable( uiDialogTitlebarClose );
if ( options.draggable && $.fn.draggable ) {
this._makeDraggable();
}
if ( options.resizable && $.fn.resizable ) {
this._makeResizable();
}
this._createButtons( options.buttons );
this._isOpen = false;
if ( $.fn.bgiframe ) {
uiDialog.bgiframe();
}
// prevent tabbing out of modal dialogs
this._on( uiDialog, { keydown: function( event ) {
if ( !options.modal || event.keyCode !== $.ui.keyCode.TAB ) {
return;
}
var tabbables = $( ":tabbable", uiDialog ),
first = tabbables.filter( ":first" ),
last = tabbables.filter( ":last" );
if ( event.target === last[0] && !event.shiftKey ) {
first.focus( 1 );
return false;
} else if ( event.target === first[0] && event.shiftKey ) {
last.focus( 1 );
return false;
}
}});
},
_init: function() {
if ( this.options.autoOpen ) {
this.open();
}
},
_destroy: function() {
var next,
oldPosition = this.oldPosition;
if ( this.overlay ) {
this.overlay.destroy();
}
this.uiDialog.hide();
this.element
.removeClass( "ui-dialog-content ui-widget-content" )
.hide()
.appendTo( "body" );
this.uiDialog.remove();
if ( this.originalTitle ) {
this.element.attr( "title", this.originalTitle );
}
next = oldPosition.parent.children().eq( oldPosition.index );
// Don't try to place the dialog next to itself (#8613)
if ( next.length && next[ 0 ] !== this.element[ 0 ] ) {
next.before( this.element );
} else {
oldPosition.parent.append( this.element );
}
},
widget: function() {
return this.uiDialog;
},
close: function( event ) {
var that = this,
maxZ, thisZ;
if ( !this._isOpen ) {
return;
}
if ( false === this._trigger( "beforeClose", event ) ) {
return;
}
this._isOpen = false;
if ( this.overlay ) {
this.overlay.destroy();
}
if ( this.options.hide ) {
this._hide( this.uiDialog, this.options.hide, function() {
that._trigger( "close", event );
});
} else {
this.uiDialog.hide();
this._trigger( "close", event );
}
$.ui.dialog.overlay.resize();
// adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
if ( this.options.modal ) {
maxZ = 0;
$( ".ui-dialog" ).each(function() {
if ( this !== that.uiDialog[0] ) {
thisZ = $( this ).css( "z-index" );
if ( !isNaN( thisZ ) ) {
maxZ = Math.max( maxZ, thisZ );
}
}
});
$.ui.dialog.maxZ = maxZ;
}
return this;
},
isOpen: function() {
return this._isOpen;
},
// the force parameter allows us to move modal dialogs to their correct
// position on open
moveToTop: function( force, event ) {
var options = this.options,
saveScroll;
if ( ( options.modal && !force ) ||
( !options.stack && !options.modal ) ) {
return this._trigger( "focus", event );
}
if ( options.zIndex > $.ui.dialog.maxZ ) {
$.ui.dialog.maxZ = options.zIndex;
}
if ( this.overlay ) {
$.ui.dialog.maxZ += 1;
$.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ;
this.overlay.$el.css( "z-index", $.ui.dialog.overlay.maxZ );
}
// Save and then restore scroll
// Opera 9.5+ resets when parent z-index is changed.
// http://bugs.jqueryui.com/ticket/3193
saveScroll = {
scrollTop: this.element.scrollTop(),
scrollLeft: this.element.scrollLeft()
};
$.ui.dialog.maxZ += 1;
this.uiDialog.css( "z-index", $.ui.dialog.maxZ );
this.element.attr( saveScroll );
this._trigger( "focus", event );
return this;
},
open: function() {
if ( this._isOpen ) {
return;
}
var hasFocus,
options = this.options,
uiDialog = this.uiDialog;
this._size();
this._position( options.position );
uiDialog.show( options.show );
this.overlay = options.modal ? new $.ui.dialog.overlay( this ) : null;
this.moveToTop( true );
// set focus to the first tabbable element in the content area or the first button
// if there are no tabbable elements, set focus on the dialog itself
hasFocus = this.element.find( ":tabbable" );
if ( !hasFocus.length ) {
hasFocus = this.uiDialogButtonPane.find( ":tabbable" );
if ( !hasFocus.length ) {
hasFocus = uiDialog;
}
}
hasFocus.eq( 0 ).focus();
this._isOpen = true;
this._trigger( "open" );
return this;
},
_createButtons: function( buttons ) {
var that = this,
hasButtons = false;
// if we already have a button pane, remove it
this.uiDialogButtonPane.remove();
this.uiButtonSet.empty();
if ( typeof buttons === "object" && buttons !== null ) {
$.each( buttons, function() {
return !(hasButtons = true);
});
}
if ( hasButtons ) {
$.each( buttons, function( name, props ) {
var button, click;
props = $.isFunction( props ) ?
{ click: props, text: name } :
props;
// Default to a non-submitting button
props = $.extend( { type: "button" }, props );
// Change the context for the click callback to be the main element
click = props.click;
props.click = function() {
click.apply( that.element[0], arguments );
};
button = $( "
", props )
.appendTo( that.uiButtonSet );
if ( $.fn.button ) {
button.button();
}
});
this.uiDialog.addClass( "ui-dialog-buttons" );
this.uiDialogButtonPane.appendTo( this.uiDialog );
} else {
this.uiDialog.removeClass( "ui-dialog-buttons" );
}
},
_makeDraggable: function() {
var that = this,
options = this.options;
function filteredUi( ui ) {
return {
position: ui.position,
offset: ui.offset
};
}
this.uiDialog.draggable({
cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
handle: ".ui-dialog-titlebar",
containment: "document",
start: function( event, ui ) {
$( this )
.addClass( "ui-dialog-dragging" );
that._trigger( "dragStart", event, filteredUi( ui ) );
},
drag: function( event, ui ) {
that._trigger( "drag", event, filteredUi( ui ) );
},
stop: function( event, ui ) {
options.position = [
ui.position.left - that.document.scrollLeft(),
ui.position.top - that.document.scrollTop()
];
$( this )
.removeClass( "ui-dialog-dragging" );
that._trigger( "dragStop", event, filteredUi( ui ) );
$.ui.dialog.overlay.resize();
}
});
},
_makeResizable: function( handles ) {
handles = (handles === undefined ? this.options.resizable : handles);
var that = this,
options = this.options,
// .ui-resizable has position: relative defined in the stylesheet
// but dialogs have to use absolute or fixed positioning
position = this.uiDialog.css( "position" ),
resizeHandles = typeof handles === 'string' ?
handles :
"n,e,s,w,se,sw,ne,nw";
function filteredUi( ui ) {
return {
originalPosition: ui.originalPosition,
originalSize: ui.originalSize,
position: ui.position,
size: ui.size
};
}
this.uiDialog.resizable({
cancel: ".ui-dialog-content",
containment: "document",
alsoResize: this.element,
maxWidth: options.maxWidth,
maxHeight: options.maxHeight,
minWidth: options.minWidth,
minHeight: this._minHeight(),
handles: resizeHandles,
start: function( event, ui ) {
$( this ).addClass( "ui-dialog-resizing" );
that._trigger( "resizeStart", event, filteredUi( ui ) );
},
resize: function( event, ui ) {
that._trigger( "resize", event, filteredUi( ui ) );
},
stop: function( event, ui ) {
$( this ).removeClass( "ui-dialog-resizing" );
options.height = $( this ).height();
options.width = $( this ).width();
that._trigger( "resizeStop", event, filteredUi( ui ) );
$.ui.dialog.overlay.resize();
}
})
.css( "position", position )
.find( ".ui-resizable-se" )
.addClass( "ui-icon ui-icon-grip-diagonal-se" );
},
_minHeight: function() {
var options = this.options;
if ( options.height === "auto" ) {
return options.minHeight;
} else {
return Math.min( options.minHeight, options.height );
}
},
_position: function( position ) {
var myAt = [],
offset = [ 0, 0 ],
isVisible;
if ( position ) {
// deep extending converts arrays to objects in jQuery <= 1.3.2 :-(
// if (typeof position == 'string' || $.isArray(position)) {
// myAt = $.isArray(position) ? position : position.split(' ');
if ( typeof position === "string" || (typeof position === "object" && "0" in position ) ) {
myAt = position.split ? position.split( " " ) : [ position[ 0 ], position[ 1 ] ];
if ( myAt.length === 1 ) {
myAt[ 1 ] = myAt[ 0 ];
}
$.each( [ "left", "top" ], function( i, offsetPosition ) {
if ( +myAt[ i ] === myAt[ i ] ) {
offset[ i ] = myAt[ i ];
myAt[ i ] = offsetPosition;
}
});
position = {
my: myAt[0] + (offset[0] < 0 ? offset[0] : "+" + offset[0]) + " " +
myAt[1] + (offset[1] < 0 ? offset[1] : "+" + offset[1]),
at: myAt.join( " " )
};
}
position = $.extend( {}, $.ui.dialog.prototype.options.position, position );
} else {
position = $.ui.dialog.prototype.options.position;
}
// need to show the dialog to get the actual offset in the position plugin
isVisible = this.uiDialog.is( ":visible" );
if ( !isVisible ) {
this.uiDialog.show();
}
this.uiDialog.position( position );
if ( !isVisible ) {
this.uiDialog.hide();
}
},
_setOptions: function( options ) {
var that = this,
resizableOptions = {},
resize = false;
$.each( options, function( key, value ) {
that._setOption( key, value );
if ( key in sizeRelatedOptions ) {
resize = true;
}
if ( key in resizableRelatedOptions ) {
resizableOptions[ key ] = value;
}
});
if ( resize ) {
this._size();
}
if ( this.uiDialog.is( ":data(resizable)" ) ) {
this.uiDialog.resizable( "option", resizableOptions );
}
},
_setOption: function( key, value ) {
var isDraggable, isResizable,
uiDialog = this.uiDialog;
switch ( key ) {
case "buttons":
this._createButtons( value );
break;
case "closeText":
// ensure that we always pass a string
this.uiDialogTitlebarCloseText.text( "" + value );
break;
case "dialogClass":
uiDialog
.removeClass( this.options.dialogClass )
.addClass( uiDialogClasses + value );
break;
case "disabled":
if ( value ) {
uiDialog.addClass( "ui-dialog-disabled" );
} else {
uiDialog.removeClass( "ui-dialog-disabled" );
}
break;
case "draggable":
isDraggable = uiDialog.is( ":data(draggable)" );
if ( isDraggable && !value ) {
uiDialog.draggable( "destroy" );
}
if ( !isDraggable && value ) {
this._makeDraggable();
}
break;
case "position":
this._position( value );
break;
case "resizable":
// currently resizable, becoming non-resizable
isResizable = uiDialog.is( ":data(resizable)" );
if ( isResizable && !value ) {
uiDialog.resizable( "destroy" );
}
// currently resizable, changing handles
if ( isResizable && typeof value === "string" ) {
uiDialog.resizable( "option", "handles", value );
}
// currently non-resizable, becoming resizable
if ( !isResizable && value !== false ) {
this._makeResizable( value );
}
break;
case "title":
// convert whatever was passed in o a string, for html() to not throw up
$( ".ui-dialog-title", this.uiDialogTitlebar )
.html( "" + ( value || " " ) );
break;
}
this._super( key, value );
},
_size: function() {
/* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
* divs will both have width and height set, so we need to reset them
*/
var nonContentHeight, minContentHeight, autoHeight,
options = this.options,
isVisible = this.uiDialog.is( ":visible" );
// reset content sizing
this.element.show().css({
width: "auto",
minHeight: 0,
height: 0
});
if ( options.minWidth > options.width ) {
options.width = options.minWidth;
}
// reset wrapper sizing
// determine the height of all the non-content elements
nonContentHeight = this.uiDialog.css({
height: "auto",
width: options.width
})
.outerHeight();
minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
if ( options.height === "auto" ) {
// only needed for IE6 support
if ( $.support.minHeight ) {
this.element.css({
minHeight: minContentHeight,
height: "auto"
});
} else {
this.uiDialog.show();
autoHeight = this.element.css( "height", "auto" ).height();
if ( !isVisible ) {
this.uiDialog.hide();
}
this.element.height( Math.max( autoHeight, minContentHeight ) );
}
} else {
this.element.height( Math.max( options.height - nonContentHeight, 0 ) );
}
if (this.uiDialog.is( ":data(resizable)" ) ) {
this.uiDialog.resizable( "option", "minHeight", this._minHeight() );
}
}
});
$.extend($.ui.dialog, {
uuid: 0,
maxZ: 0,
getTitleId: function($el) {
var id = $el.attr( "id" );
if ( !id ) {
this.uuid += 1;
id = this.uuid;
}
return "ui-dialog-title-" + id;
},
overlay: function( dialog ) {
this.$el = $.ui.dialog.overlay.create( dialog );
}
});
$.extend( $.ui.dialog.overlay, {
instances: [],
// reuse old instances due to IE memory leak with alpha transparency (see #5185)
oldInstances: [],
maxZ: 0,
events: $.map(
"focus,mousedown,mouseup,keydown,keypress,click".split( "," ),
function( event ) {
return event + ".dialog-overlay";
}
).join( " " ),
create: function( dialog ) {
if ( this.instances.length === 0 ) {
// prevent use of anchors and inputs
// we use a setTimeout in case the overlay is created from an
// event that we're going to be cancelling (see #2804)
setTimeout(function() {
// handle $(el).dialog().dialog('close') (see #4065)
if ( $.ui.dialog.overlay.instances.length ) {
$( document ).bind( $.ui.dialog.overlay.events, function( event ) {
// stop events if the z-index of the target is < the z-index of the overlay
// we cannot return true when we don't want to cancel the event (#3523)
if ( $( event.target ).zIndex() < $.ui.dialog.overlay.maxZ ) {
return false;
}
});
}
}, 1 );
// handle window resize
$( window ).bind( "resize.dialog-overlay", $.ui.dialog.overlay.resize );
}
var $el = ( this.oldInstances.pop() || $( "
" ).addClass( "ui-widget-overlay" ) );
// allow closing by pressing the escape key
$( document ).bind( "keydown.dialog-overlay", function( event ) {
var instances = $.ui.dialog.overlay.instances;
// only react to the event if we're the top overlay
if ( instances.length !== 0 && instances[ instances.length - 1 ] === $el &&
dialog.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
event.keyCode === $.ui.keyCode.ESCAPE ) {
dialog.close( event );
event.preventDefault();
}
});
$el.appendTo( document.body ).css({
width: this.width(),
height: this.height()
});
if ( $.fn.bgiframe ) {
$el.bgiframe();
}
this.instances.push( $el );
return $el;
},
destroy: function( $el ) {
var indexOf = $.inArray( $el, this.instances ),
maxZ = 0;
if ( indexOf !== -1 ) {
this.oldInstances.push( this.instances.splice( indexOf, 1 )[ 0 ] );
}
if ( this.instances.length === 0 ) {
$( [ document, window ] ).unbind( ".dialog-overlay" );
}
$el.height( 0 ).width( 0 ).remove();
// adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
$.each( this.instances, function() {
maxZ = Math.max( maxZ, this.css( "z-index" ) );
});
this.maxZ = maxZ;
},
height: function() {
var scrollHeight,
offsetHeight;
// handle IE
if ( $.ui.ie ) {
scrollHeight = Math.max(
document.documentElement.scrollHeight,
document.body.scrollHeight
);
offsetHeight = Math.max(
document.documentElement.offsetHeight,
document.body.offsetHeight
);
if ( scrollHeight < offsetHeight ) {
return $( window ).height() + "px";
} else {
return scrollHeight + "px";
}
// handle "good" browsers
} else {
return $( document ).height() + "px";
}
},
width: function() {
var scrollWidth,
offsetWidth;
// handle IE
if ( $.ui.ie ) {
scrollWidth = Math.max(
document.documentElement.scrollWidth,
document.body.scrollWidth
);
offsetWidth = Math.max(
document.documentElement.offsetWidth,
document.body.offsetWidth
);
if ( scrollWidth < offsetWidth ) {
return $( window ).width() + "px";
} else {
return scrollWidth + "px";
}
// handle "good" browsers
} else {
return $( document ).width() + "px";
}
},
resize: function() {
/* If the dialog is draggable and the user drags it past the
* right edge of the window, the document becomes wider so we
* need to stretch the overlay. If the user then drags the
* dialog back to the left, the document will become narrower,
* so we need to shrink the overlay to the appropriate size.
* This is handled by shrinking the overlay before setting it
* to the full document size.
*/
var $overlays = $( [] );
$.each( $.ui.dialog.overlay.instances, function() {
$overlays = $overlays.add( this );
});
$overlays.css({
width: 0,
height: 0
}).css({
width: $.ui.dialog.overlay.width(),
height: $.ui.dialog.overlay.height()
});
}
});
$.extend( $.ui.dialog.overlay.prototype, {
destroy: function() {
$.ui.dialog.overlay.destroy( this.$el );
}
});
}( jQuery ) );
(function( $, undefined ) {
var rvertical = /up|down|vertical/,
rpositivemotion = /up|left|vertical|horizontal/;
$.effects.effect.blind = function( o, done ) {
// Create element
var el = $( this ),
props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
mode = $.effects.setMode( el, o.mode || "hide" ),
direction = o.direction || "up",
vertical = rvertical.test( direction ),
ref = vertical ? "height" : "width",
ref2 = vertical ? "top" : "left",
motion = rpositivemotion.test( direction ),
animation = {},
show = mode === "show",
wrapper, distance, margin;
// if already wrapped, the wrapper's properties are my property. #6245
if ( el.parent().is( ".ui-effects-wrapper" ) ) {
$.effects.save( el.parent(), props );
} else {
$.effects.save( el, props );
}
el.show();
wrapper = $.effects.createWrapper( el ).css({
overflow: "hidden"
});
distance = wrapper[ ref ]();
margin = parseFloat( wrapper.css( ref2 ) ) || 0;
animation[ ref ] = show ? distance : 0;
if ( !motion ) {
el
.css( vertical ? "bottom" : "right", 0 )
.css( vertical ? "top" : "left", "auto" )
.css({ position: "absolute" });
animation[ ref2 ] = show ? margin : distance + margin;
}
// start at 0 if we are showing
if ( show ) {
wrapper.css( ref, 0 );
if ( ! motion ) {
wrapper.css( ref2, margin + distance );
}
}
// Animate
wrapper.animate( animation, {
duration: o.duration,
easing: o.easing,
queue: false,
complete: function() {
if ( mode === "hide" ) {
el.hide();
}
$.effects.restore( el, props );
$.effects.removeWrapper( el );
done();
}
});
};
})(jQuery);
(function( $, undefined ) {
$.effects.effect.bounce = function( o, done ) {
var el = $( this ),
props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
// defaults:
mode = $.effects.setMode( el, o.mode || "effect" ),
hide = mode === "hide",
show = mode === "show",
direction = o.direction || "up",
distance = o.distance,
times = o.times || 5,
// number of internal animations
anims = times * 2 + ( show || hide ? 1 : 0 ),
speed = o.duration / anims,
easing = o.easing,
// utility:
ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
motion = ( direction === "up" || direction === "left" ),
i,
upAnim,
downAnim,
// we will need to re-assemble the queue to stack our animations in place
queue = el.queue(),
queuelen = queue.length;
// Avoid touching opacity to prevent clearType and PNG issues in IE
if ( show || hide ) {
props.push( "opacity" );
}
$.effects.save( el, props );
el.show();
$.effects.createWrapper( el ); // Create Wrapper
// default distance for the BIGGEST bounce is the outer Distance / 3
if ( !distance ) {
distance = el[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3;
}
if ( show ) {
downAnim = { opacity: 1 };
downAnim[ ref ] = 0;
// if we are showing, force opacity 0 and set the initial position
// then do the "first" animation
el.css( "opacity", 0 )
.css( ref, motion ? -distance * 2 : distance * 2 )
.animate( downAnim, speed, easing );
}
// start at the smallest distance if we are hiding
if ( hide ) {
distance = distance / Math.pow( 2, times - 1 );
}
downAnim = {};
downAnim[ ref ] = 0;
// Bounces up/down/left/right then back to 0 -- times * 2 animations happen here
for ( i = 0; i < times; i++ ) {
upAnim = {};
upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
el.animate( upAnim, speed, easing )
.animate( downAnim, speed, easing );
distance = hide ? distance * 2 : distance / 2;
}
// Last Bounce when Hiding
if ( hide ) {
upAnim = { opacity: 0 };
upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
el.animate( upAnim, speed, easing );
}
el.queue(function() {
if ( hide ) {
el.hide();
}
$.effects.restore( el, props );
$.effects.removeWrapper( el );
done();
});
// inject all the animations we just queued to be first in line (after "inprogress")
if ( queuelen > 1) {
queue.splice.apply( queue,
[ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
}
el.dequeue();
};
})(jQuery);
(function( $, undefined ) {
$.effects.effect.clip = function( o, done ) {
// Create element
var el = $( this ),
props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
mode = $.effects.setMode( el, o.mode || "hide" ),
show = mode === "show",
direction = o.direction || "vertical",
vert = direction === "vertical",
size = vert ? "height" : "width",
position = vert ? "top" : "left",
animation = {},
wrapper, animate, distance;
// Save & Show
$.effects.save( el, props );
el.show();
// Create Wrapper
wrapper = $.effects.createWrapper( el ).css({
overflow: "hidden"
});
animate = ( el[0].tagName === "IMG" ) ? wrapper : el;
distance = animate[ size ]();
// Shift
if ( show ) {
animate.css( size, 0 );
animate.css( position, distance / 2 );
}
// Create Animation Object:
animation[ size ] = show ? distance : 0;
animation[ position ] = show ? 0 : distance / 2;
// Animate
animate.animate( animation, {
queue: false,
duration: o.duration,
easing: o.easing,
complete: function() {
if ( !show ) {
el.hide();
}
$.effects.restore( el, props );
$.effects.removeWrapper( el );
done();
}
});
};
})(jQuery);
(function( $, undefined ) {
$.effects.effect.drop = function( o, done ) {
var el = $( this ),
props = [ "position", "top", "bottom", "left", "right", "opacity", "height", "width" ],
mode = $.effects.setMode( el, o.mode || "hide" ),
show = mode === "show",
direction = o.direction || "left",
ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
motion = ( direction === "up" || direction === "left" ) ? "pos" : "neg",
animation = {
opacity: show ? 1 : 0
},
distance;
// Adjust
$.effects.save( el, props );
el.show();
$.effects.createWrapper( el );
distance = o.distance || el[ ref === "top" ? "outerHeight": "outerWidth" ]( true ) / 2;
if ( show ) {
el
.css( "opacity", 0 )
.css( ref, motion === "pos" ? -distance : distance );
}
// Animation
animation[ ref ] = ( show ?
( motion === "pos" ? "+=" : "-=" ) :
( motion === "pos" ? "-=" : "+=" ) ) +
distance;
// Animate
el.animate( animation, {
queue: false,
duration: o.duration,
easing: o.easing,
complete: function() {
if ( mode === "hide" ) {
el.hide();
}
$.effects.restore( el, props );
$.effects.removeWrapper( el );
done();
}
});
};
})(jQuery);
(function( $, undefined ) {
$.effects.effect.explode = function( o, done ) {
var rows = o.pieces ? Math.round( Math.sqrt( o.pieces ) ) : 3,
cells = rows,
el = $( this ),
mode = $.effects.setMode( el, o.mode || "hide" ),
show = mode === "show",
// show and then visibility:hidden the element before calculating offset
offset = el.show().css( "visibility", "hidden" ).offset(),
// width and height of a piece
width = Math.ceil( el.outerWidth() / cells ),
height = Math.ceil( el.outerHeight() / rows ),
pieces = [],
// loop
i, j, left, top, mx, my;
// children animate complete:
function childComplete() {
pieces.push( this );
if ( pieces.length === rows * cells ) {
animComplete();
}
}
// clone the element for each row and cell.
for( i = 0; i < rows ; i++ ) { // ===>
top = offset.top + i * height;
my = i - ( rows - 1 ) / 2 ;
for( j = 0; j < cells ; j++ ) { // |||
left = offset.left + j * width;
mx = j - ( cells - 1 ) / 2 ;
// Create a clone of the now hidden main element that will be absolute positioned
// within a wrapper div off the -left and -top equal to size of our pieces
el
.clone()
.appendTo( "body" )
.wrap( "
" )
.css({
position: "absolute",
visibility: "visible",
left: -j * width,
top: -i * height
})
// select the wrapper - make it overflow: hidden and absolute positioned based on
// where the original was located +left and +top equal to the size of pieces
.parent()
.addClass( "ui-effects-explode" )
.css({
position: "absolute",
overflow: "hidden",
width: width,
height: height,
left: left + ( show ? mx * width : 0 ),
top: top + ( show ? my * height : 0 ),
opacity: show ? 0 : 1
}).animate({
left: left + ( show ? 0 : mx * width ),
top: top + ( show ? 0 : my * height ),
opacity: show ? 1 : 0
}, o.duration || 500, o.easing, childComplete );
}
}
function animComplete() {
el.css({
visibility: "visible"
});
$( pieces ).remove();
if ( !show ) {
el.hide();
}
done();
}
};
})(jQuery);
(function( $, undefined ) {
$.effects.effect.fade = function( o, done ) {
var el = $( this ),
mode = $.effects.setMode( el, o.mode || "toggle" );
el.animate({
opacity: mode
}, {
queue: false,
duration: o.duration,
easing: o.easing,
complete: done
});
};
})( jQuery );
(function( $, undefined ) {
$.effects.effect.fold = function( o, done ) {
// Create element
var el = $( this ),
props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
mode = $.effects.setMode( el, o.mode || "hide" ),
show = mode === "show",
hide = mode === "hide",
size = o.size || 15,
percent = /([0-9]+)%/.exec( size ),
horizFirst = !!o.horizFirst,
widthFirst = show !== horizFirst,
ref = widthFirst ? [ "width", "height" ] : [ "height", "width" ],
duration = o.duration / 2,
wrapper, distance,
animation1 = {},
animation2 = {};
$.effects.save( el, props );
el.show();
// Create Wrapper
wrapper = $.effects.createWrapper( el ).css({
overflow: "hidden"
});
distance = widthFirst ?
[ wrapper.width(), wrapper.height() ] :
[ wrapper.height(), wrapper.width() ];
if ( percent ) {
size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ];
}
if ( show ) {
wrapper.css( horizFirst ? {
height: 0,
width: size
} : {
height: size,
width: 0
});
}
// Animation
animation1[ ref[ 0 ] ] = show ? distance[ 0 ] : size;
animation2[ ref[ 1 ] ] = show ? distance[ 1 ] : 0;
// Animate
wrapper
.animate( animation1, duration, o.easing )
.animate( animation2, duration, o.easing, function() {
if ( hide ) {
el.hide();
}
$.effects.restore( el, props );
$.effects.removeWrapper( el );
done();
});
};
})(jQuery);
(function( $, undefined ) {
$.effects.effect.highlight = function( o, done ) {
var elem = $( this ),
props = [ "backgroundImage", "backgroundColor", "opacity" ],
mode = $.effects.setMode( elem, o.mode || "show" ),
animation = {
backgroundColor: elem.css( "backgroundColor" )
};
if (mode === "hide") {
animation.opacity = 0;
}
$.effects.save( elem, props );
elem
.show()
.css({
backgroundImage: "none",
backgroundColor: o.color || "#ffff99"
})
.animate( animation, {
queue: false,
duration: o.duration,
easing: o.easing,
complete: function() {
if ( mode === "hide" ) {
elem.hide();
}
$.effects.restore( elem, props );
done();
}
});
};
})(jQuery);
(function( $, undefined ) {
$.effects.effect.pulsate = function( o, done ) {
var elem = $( this ),
mode = $.effects.setMode( elem, o.mode || "show" ),
show = mode === "show",
hide = mode === "hide",
showhide = ( show || mode === "hide" ),
// showing or hiding leaves of the "last" animation
anims = ( ( o.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ),
duration = o.duration / anims,
animateTo = 0,
queue = elem.queue(),
queuelen = queue.length,
i;
if ( show || !elem.is(":visible")) {
elem.css( "opacity", 0 ).show();
animateTo = 1;
}
// anims - 1 opacity "toggles"
for ( i = 1; i < anims; i++ ) {
elem.animate({
opacity: animateTo
}, duration, o.easing );
animateTo = 1 - animateTo;
}
elem.animate({
opacity: animateTo
}, duration, o.easing);
elem.queue(function() {
if ( hide ) {
elem.hide();
}
done();
});
// We just queued up "anims" animations, we need to put them next in the queue
if ( queuelen > 1 ) {
queue.splice.apply( queue,
[ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
}
elem.dequeue();
};
})(jQuery);
(function( $, undefined ) {
$.effects.effect.puff = function( o, done ) {
var elem = $( this ),
mode = $.effects.setMode( elem, o.mode || "hide" ),
hide = mode === "hide",
percent = parseInt( o.percent, 10 ) || 150,
factor = percent / 100,
original = {
height: elem.height(),
width: elem.width(),
outerHeight: elem.outerHeight(),
outerWidth: elem.outerWidth()
};
$.extend( o, {
effect: "scale",
queue: false,
fade: true,
mode: mode,
complete: done,
percent: hide ? percent : 100,
from: hide ?
original :
{
height: original.height * factor,
width: original.width * factor,
outerHeight: original.outerHeight * factor,
outerWidth: original.outerWidth * factor
}
});
elem.effect( o );
};
$.effects.effect.scale = function( o, done ) {
// Create element
var el = $( this ),
options = $.extend( true, {}, o ),
mode = $.effects.setMode( el, o.mode || "effect" ),
percent = parseInt( o.percent, 10 ) ||
( parseInt( o.percent, 10 ) === 0 ? 0 : ( mode === "hide" ? 0 : 100 ) ),
direction = o.direction || "both",
origin = o.origin,
original = {
height: el.height(),
width: el.width(),
outerHeight: el.outerHeight(),
outerWidth: el.outerWidth()
},
factor = {
y: direction !== "horizontal" ? (percent / 100) : 1,
x: direction !== "vertical" ? (percent / 100) : 1
};
// We are going to pass this effect to the size effect:
options.effect = "size";
options.queue = false;
options.complete = done;
// Set default origin and restore for show/hide
if ( mode !== "effect" ) {
options.origin = origin || ["middle","center"];
options.restore = true;
}
options.from = o.from || ( mode === "show" ? {
height: 0,
width: 0,
outerHeight: 0,
outerWidth: 0
} : original );
options.to = {
height: original.height * factor.y,
width: original.width * factor.x,
outerHeight: original.outerHeight * factor.y,
outerWidth: original.outerWidth * factor.x
};
// Fade option to support puff
if ( options.fade ) {
if ( mode === "show" ) {
options.from.opacity = 0;
options.to.opacity = 1;
}
if ( mode === "hide" ) {
options.from.opacity = 1;
options.to.opacity = 0;
}
}
// Animate
el.effect( options );
};
$.effects.effect.size = function( o, done ) {
// Create element
var original, baseline, factor,
el = $( this ),
props0 = [ "position", "top", "bottom", "left", "right", "width", "height", "overflow", "opacity" ],
// Always restore
props1 = [ "position", "top", "bottom", "left", "right", "overflow", "opacity" ],
// Copy for children
props2 = [ "width", "height", "overflow" ],
cProps = [ "fontSize" ],
vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ],
hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ],
// Set options
mode = $.effects.setMode( el, o.mode || "effect" ),
restore = o.restore || mode !== "effect",
scale = o.scale || "both",
origin = o.origin || [ "middle", "center" ],
position = el.css( "position" ),
props = restore ? props0 : props1,
zero = {
height: 0,
width: 0,
outerHeight: 0,
outerWidth: 0
};
if ( mode === "show" ) {
el.show();
}
original = {
height: el.height(),
width: el.width(),
outerHeight: el.outerHeight(),
outerWidth: el.outerWidth()
};
if ( o.mode === "toggle" && mode === "show" ) {
el.from = o.to || zero;
el.to = o.from || original;
} else {
el.from = o.from || ( mode === "show" ? zero : original );
el.to = o.to || ( mode === "hide" ? zero : original );
}
// Set scaling factor
factor = {
from: {
y: el.from.height / original.height,
x: el.from.width / original.width
},
to: {
y: el.to.height / original.height,
x: el.to.width / original.width
}
};
// Scale the css box
if ( scale === "box" || scale === "both" ) {
// Vertical props scaling
if ( factor.from.y !== factor.to.y ) {
props = props.concat( vProps );
el.from = $.effects.setTransition( el, vProps, factor.from.y, el.from );
el.to = $.effects.setTransition( el, vProps, factor.to.y, el.to );
}
// Horizontal props scaling
if ( factor.from.x !== factor.to.x ) {
props = props.concat( hProps );
el.from = $.effects.setTransition( el, hProps, factor.from.x, el.from );
el.to = $.effects.setTransition( el, hProps, factor.to.x, el.to );
}
}
// Scale the content
if ( scale === "content" || scale === "both" ) {
// Vertical props scaling
if ( factor.from.y !== factor.to.y ) {
props = props.concat( cProps ).concat( props2 );
el.from = $.effects.setTransition( el, cProps, factor.from.y, el.from );
el.to = $.effects.setTransition( el, cProps, factor.to.y, el.to );
}
}
$.effects.save( el, props );
el.show();
$.effects.createWrapper( el );
el.css( "overflow", "hidden" ).css( el.from );
// Adjust
if (origin) { // Calculate baseline shifts
baseline = $.effects.getBaseline( origin, original );
el.from.top = ( original.outerHeight - el.outerHeight() ) * baseline.y;
el.from.left = ( original.outerWidth - el.outerWidth() ) * baseline.x;
el.to.top = ( original.outerHeight - el.to.outerHeight ) * baseline.y;
el.to.left = ( original.outerWidth - el.to.outerWidth ) * baseline.x;
}
el.css( el.from ); // set top & left
// Animate
if ( scale === "content" || scale === "both" ) { // Scale the children
// Add margins/font-size
vProps = vProps.concat([ "marginTop", "marginBottom" ]).concat(cProps);
hProps = hProps.concat([ "marginLeft", "marginRight" ]);
props2 = props0.concat(vProps).concat(hProps);
el.find( "*[width]" ).each( function(){
var child = $( this ),
c_original = {
height: child.height(),
width: child.width(),
outerHeight: child.outerHeight(),
outerWidth: child.outerWidth()
};
if (restore) {
$.effects.save(child, props2);
}
child.from = {
height: c_original.height * factor.from.y,
width: c_original.width * factor.from.x,
outerHeight: c_original.outerHeight * factor.from.y,
outerWidth: c_original.outerWidth * factor.from.x
};
child.to = {
height: c_original.height * factor.to.y,
width: c_original.width * factor.to.x,
outerHeight: c_original.height * factor.to.y,
outerWidth: c_original.width * factor.to.x
};
// Vertical props scaling
if ( factor.from.y !== factor.to.y ) {
child.from = $.effects.setTransition( child, vProps, factor.from.y, child.from );
child.to = $.effects.setTransition( child, vProps, factor.to.y, child.to );
}
// Horizontal props scaling
if ( factor.from.x !== factor.to.x ) {
child.from = $.effects.setTransition( child, hProps, factor.from.x, child.from );
child.to = $.effects.setTransition( child, hProps, factor.to.x, child.to );
}
// Animate children
child.css( child.from );
child.animate( child.to, o.duration, o.easing, function() {
// Restore children
if ( restore ) {
$.effects.restore( child, props2 );
}
});
});
}
// Animate
el.animate( el.to, {
queue: false,
duration: o.duration,
easing: o.easing,
complete: function() {
if ( el.to.opacity === 0 ) {
el.css( "opacity", el.from.opacity );
}
if( mode === "hide" ) {
el.hide();
}
$.effects.restore( el, props );
if ( !restore ) {
// we need to calculate our new positioning based on the scaling
if ( position === "static" ) {
el.css({
position: "relative",
top: el.to.top,
left: el.to.left
});
} else {
$.each([ "top", "left" ], function( idx, pos ) {
el.css( pos, function( _, str ) {
var val = parseInt( str, 10 ),
toRef = idx ? el.to.left : el.to.top;
// if original was "auto", recalculate the new value from wrapper
if ( str === "auto" ) {
return toRef + "px";
}
return val + toRef + "px";
});
});
}
}
$.effects.removeWrapper( el );
done();
}
});
};
})(jQuery);
(function( $, undefined ) {
$.effects.effect.shake = function( o, done ) {
var el = $( this ),
props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
mode = $.effects.setMode( el, o.mode || "effect" ),
direction = o.direction || "left",
distance = o.distance || 20,
times = o.times || 3,
anims = times * 2 + 1,
speed = Math.round(o.duration/anims),
ref = (direction === "up" || direction === "down") ? "top" : "left",
positiveMotion = (direction === "up" || direction === "left"),
animation = {},
animation1 = {},
animation2 = {},
i,
// we will need to re-assemble the queue to stack our animations in place
queue = el.queue(),
queuelen = queue.length;
$.effects.save( el, props );
el.show();
$.effects.createWrapper( el );
// Animation
animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance;
animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2;
animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2;
// Animate
el.animate( animation, speed, o.easing );
// Shakes
for ( i = 1; i < times; i++ ) {
el.animate( animation1, speed, o.easing ).animate( animation2, speed, o.easing );
}
el
.animate( animation1, speed, o.easing )
.animate( animation, speed / 2, o.easing )
.queue(function() {
if ( mode === "hide" ) {
el.hide();
}
$.effects.restore( el, props );
$.effects.removeWrapper( el );
done();
});
// inject all the animations we just queued to be first in line (after "inprogress")
if ( queuelen > 1) {
queue.splice.apply( queue,
[ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
}
el.dequeue();
};
})(jQuery);
(function( $, undefined ) {
$.effects.effect.slide = function( o, done ) {
// Create element
var el = $( this ),
props = [ "position", "top", "bottom", "left", "right", "width", "height" ],
mode = $.effects.setMode( el, o.mode || "show" ),
show = mode === "show",
direction = o.direction || "left",
ref = (direction === "up" || direction === "down") ? "top" : "left",
positiveMotion = (direction === "up" || direction === "left"),
distance,
animation = {};
// Adjust
$.effects.save( el, props );
el.show();
distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true );
$.effects.createWrapper( el ).css({
overflow: "hidden"
});
if ( show ) {
el.css( ref, positiveMotion ? (isNaN(distance) ? "-" + distance : -distance) : distance );
}
// Animation
animation[ ref ] = ( show ?
( positiveMotion ? "+=" : "-=") :
( positiveMotion ? "-=" : "+=")) +
distance;
// Animate
el.animate( animation, {
queue: false,
duration: o.duration,
easing: o.easing,
complete: function() {
if ( mode === "hide" ) {
el.hide();
}
$.effects.restore( el, props );
$.effects.removeWrapper( el );
done();
}
});
};
})(jQuery);
(function( $, undefined ) {
$.effects.effect.transfer = function( o, done ) {
var elem = $( this ),
target = $( o.to ),
targetFixed = target.css( "position" ) === "fixed",
body = $("body"),
fixTop = targetFixed ? body.scrollTop() : 0,
fixLeft = targetFixed ? body.scrollLeft() : 0,
endPosition = target.offset(),
animation = {
top: endPosition.top - fixTop ,
left: endPosition.left - fixLeft ,
height: target.innerHeight(),
width: target.innerWidth()
},
startPosition = elem.offset(),
transfer = $( '
' )
.appendTo( document.body )
.addClass( o.className )
.css({
top: startPosition.top - fixTop ,
left: startPosition.left - fixLeft ,
height: elem.innerHeight(),
width: elem.innerWidth(),
position: targetFixed ? "fixed" : "absolute"
})
.animate( animation, o.duration, o.easing, function() {
transfer.remove();
done();
});
};
})(jQuery);
(function( $, undefined ) {
var mouseHandled = false;
$.widget( "ui.menu", {
version: "1.9.2",
defaultElement: "
",
delay: 300,
options: {
icons: {
submenu: "ui-icon-carat-1-e"
},
menus: "ul",
position: {
my: "left top",
at: "right top"
},
role: "menu",
// callbacks
blur: null,
focus: null,
select: null
},
_create: function() {
this.activeMenu = this.element;
this.element
.uniqueId()
.addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" )
.toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length )
.attr({
role: this.options.role,
tabIndex: 0
})
// need to catch all clicks on disabled menu
// not possible through _on
.bind( "click" + this.eventNamespace, $.proxy(function( event ) {
if ( this.options.disabled ) {
event.preventDefault();
}
}, this ));
if ( this.options.disabled ) {
this.element
.addClass( "ui-state-disabled" )
.attr( "aria-disabled", "true" );
}
this._on({
// Prevent focus from sticking to links inside menu after clicking
// them (focus should always stay on UL during navigation).
"mousedown .ui-menu-item > a": function( event ) {
event.preventDefault();
},
"click .ui-state-disabled > a": function( event ) {
event.preventDefault();
},
"click .ui-menu-item:has(a)": function( event ) {
var target = $( event.target ).closest( ".ui-menu-item" );
if ( !mouseHandled && target.not( ".ui-state-disabled" ).length ) {
mouseHandled = true;
this.select( event );
// Open submenu on click
if ( target.has( ".ui-menu" ).length ) {
this.expand( event );
} else if ( !this.element.is( ":focus" ) ) {
// Redirect focus to the menu
this.element.trigger( "focus", [ true ] );
// If the active item is on the top level, let it stay active.
// Otherwise, blur the active item since it is no longer visible.
if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {
clearTimeout( this.timer );
}
}
}
},
"mouseenter .ui-menu-item": function( event ) {
var target = $( event.currentTarget );
// Remove ui-state-active class from siblings of the newly focused menu item
// to avoid a jump caused by adjacent elements both having a class with a border
target.siblings().children( ".ui-state-active" ).removeClass( "ui-state-active" );
this.focus( event, target );
},
mouseleave: "collapseAll",
"mouseleave .ui-menu": "collapseAll",
focus: function( event, keepActiveItem ) {
// If there's already an active item, keep it active
// If not, activate the first item
var item = this.active || this.element.children( ".ui-menu-item" ).eq( 0 );
if ( !keepActiveItem ) {
this.focus( event, item );
}
},
blur: function( event ) {
this._delay(function() {
if ( !$.contains( this.element[0], this.document[0].activeElement ) ) {
this.collapseAll( event );
}
});
},
keydown: "_keydown"
});
this.refresh();
// Clicks outside of a menu collapse any open menus
this._on( this.document, {
click: function( event ) {
if ( !$( event.target ).closest( ".ui-menu" ).length ) {
this.collapseAll( event );
}
// Reset the mouseHandled flag
mouseHandled = false;
}
});
},
_destroy: function() {
// Destroy (sub)menus
this.element
.removeAttr( "aria-activedescendant" )
.find( ".ui-menu" ).addBack()
.removeClass( "ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons" )
.removeAttr( "role" )
.removeAttr( "tabIndex" )
.removeAttr( "aria-labelledby" )
.removeAttr( "aria-expanded" )
.removeAttr( "aria-hidden" )
.removeAttr( "aria-disabled" )
.removeUniqueId()
.show();
// Destroy menu items
this.element.find( ".ui-menu-item" )
.removeClass( "ui-menu-item" )
.removeAttr( "role" )
.removeAttr( "aria-disabled" )
.children( "a" )
.removeUniqueId()
.removeClass( "ui-corner-all ui-state-hover" )
.removeAttr( "tabIndex" )
.removeAttr( "role" )
.removeAttr( "aria-haspopup" )
.children().each( function() {
var elem = $( this );
if ( elem.data( "ui-menu-submenu-carat" ) ) {
elem.remove();
}
});
// Destroy menu dividers
this.element.find( ".ui-menu-divider" ).removeClass( "ui-menu-divider ui-widget-content" );
},
_keydown: function( event ) {
var match, prev, character, skip, regex,
preventDefault = true;
function escape( value ) {
return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
}
switch ( event.keyCode ) {
case $.ui.keyCode.PAGE_UP:
this.previousPage( event );
break;
case $.ui.keyCode.PAGE_DOWN:
this.nextPage( event );
break;
case $.ui.keyCode.HOME:
this._move( "first", "first", event );
break;
case $.ui.keyCode.END:
this._move( "last", "last", event );
break;
case $.ui.keyCode.UP:
this.previous( event );
break;
case $.ui.keyCode.DOWN:
this.next( event );
break;
case $.ui.keyCode.LEFT:
this.collapse( event );
break;
case $.ui.keyCode.RIGHT:
if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
this.expand( event );
}
break;
case $.ui.keyCode.ENTER:
case $.ui.keyCode.SPACE:
this._activate( event );
break;
case $.ui.keyCode.ESCAPE:
this.collapse( event );
break;
default:
preventDefault = false;
prev = this.previousFilter || "";
character = String.fromCharCode( event.keyCode );
skip = false;
clearTimeout( this.filterTimer );
if ( character === prev ) {
skip = true;
} else {
character = prev + character;
}
regex = new RegExp( "^" + escape( character ), "i" );
match = this.activeMenu.children( ".ui-menu-item" ).filter(function() {
return regex.test( $( this ).children( "a" ).text() );
});
match = skip && match.index( this.active.next() ) !== -1 ?
this.active.nextAll( ".ui-menu-item" ) :
match;
// If no matches on the current filter, reset to the last character pressed
// to move down the menu to the first item that starts with that character
if ( !match.length ) {
character = String.fromCharCode( event.keyCode );
regex = new RegExp( "^" + escape( character ), "i" );
match = this.activeMenu.children( ".ui-menu-item" ).filter(function() {
return regex.test( $( this ).children( "a" ).text() );
});
}
if ( match.length ) {
this.focus( event, match );
if ( match.length > 1 ) {
this.previousFilter = character;
this.filterTimer = this._delay(function() {
delete this.previousFilter;
}, 1000 );
} else {
delete this.previousFilter;
}
} else {
delete this.previousFilter;
}
}
if ( preventDefault ) {
event.preventDefault();
}
},
_activate: function( event ) {
if ( !this.active.is( ".ui-state-disabled" ) ) {
if ( this.active.children( "a[aria-haspopup='true']" ).length ) {
this.expand( event );
} else {
this.select( event );
}
}
},
refresh: function() {
var menus,
icon = this.options.icons.submenu,
submenus = this.element.find( this.options.menus );
// Initialize nested menus
submenus.filter( ":not(.ui-menu)" )
.addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" )
.hide()
.attr({
role: this.options.role,
"aria-hidden": "true",
"aria-expanded": "false"
})
.each(function() {
var menu = $( this ),
item = menu.prev( "a" ),
submenuCarat = $( "" )
.addClass( "ui-menu-icon ui-icon " + icon )
.data( "ui-menu-submenu-carat", true );
item
.attr( "aria-haspopup", "true" )
.prepend( submenuCarat );
menu.attr( "aria-labelledby", item.attr( "id" ) );
});
menus = submenus.add( this.element );
// Don't refresh list items that are already adapted
menus.children( ":not(.ui-menu-item):has(a)" )
.addClass( "ui-menu-item" )
.attr( "role", "presentation" )
.children( "a" )
.uniqueId()
.addClass( "ui-corner-all" )
.attr({
tabIndex: -1,
role: this._itemRole()
});
// Initialize unlinked menu-items containing spaces and/or dashes only as dividers
menus.children( ":not(.ui-menu-item)" ).each(function() {
var item = $( this );
// hyphen, em dash, en dash
if ( !/[^\-?붴€?s]/.test( item.text() ) ) {
item.addClass( "ui-widget-content ui-menu-divider" );
}
});
// Add aria-disabled attribute to any disabled menu item
menus.children( ".ui-state-disabled" ).attr( "aria-disabled", "true" );
// If the active item has been removed, blur the menu
if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
this.blur();
}
},
_itemRole: function() {
return {
menu: "menuitem",
listbox: "option"
}[ this.options.role ];
},
focus: function( event, item ) {
var nested, focused;
this.blur( event, event && event.type === "focus" );
this._scrollIntoView( item );
this.active = item.first();
focused = this.active.children( "a" ).addClass( "ui-state-focus" );
// Only update aria-activedescendant if there's a role
// otherwise we assume focus is managed elsewhere
if ( this.options.role ) {
this.element.attr( "aria-activedescendant", focused.attr( "id" ) );
}
// Highlight active parent menu item, if any
this.active
.parent()
.closest( ".ui-menu-item" )
.children( "a:first" )
.addClass( "ui-state-active" );
if ( event && event.type === "keydown" ) {
this._close();
} else {
this.timer = this._delay(function() {
this._close();
}, this.delay );
}
nested = item.children( ".ui-menu" );
if ( nested.length && ( /^mouse/.test( event.type ) ) ) {
this._startOpening(nested);
}
this.activeMenu = item.parent();
this._trigger( "focus", event, { item: item } );
},
_scrollIntoView: function( item ) {
var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
if ( this._hasScroll() ) {
borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0;
paddingTop = parseFloat( $.css( this.activeMenu[0], "paddingTop" ) ) || 0;
offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
scroll = this.activeMenu.scrollTop();
elementHeight = this.activeMenu.height();
itemHeight = item.height();
if ( offset < 0 ) {
this.activeMenu.scrollTop( scroll + offset );
} else if ( offset + itemHeight > elementHeight ) {
this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
}
}
},
blur: function( event, fromFocus ) {
if ( !fromFocus ) {
clearTimeout( this.timer );
}
if ( !this.active ) {
return;
}
this.active.children( "a" ).removeClass( "ui-state-focus" );
this.active = null;
this._trigger( "blur", event, { item: this.active } );
},
_startOpening: function( submenu ) {
clearTimeout( this.timer );
// Don't open if already open fixes a Firefox bug that caused a .5 pixel
// shift in the submenu position when mousing over the carat icon
if ( submenu.attr( "aria-hidden" ) !== "true" ) {
return;
}
this.timer = this._delay(function() {
this._close();
this._open( submenu );
}, this.delay );
},
_open: function( submenu ) {
var position = $.extend({
of: this.active
}, this.options.position );
clearTimeout( this.timer );
this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )
.hide()
.attr( "aria-hidden", "true" );
submenu
.show()
.removeAttr( "aria-hidden" )
.attr( "aria-expanded", "true" )
.position( position );
},
collapseAll: function( event, all ) {
clearTimeout( this.timer );
this.timer = this._delay(function() {
// If we were passed an event, look for the submenu that contains the event
var currentMenu = all ? this.element :
$( event && event.target ).closest( this.element.find( ".ui-menu" ) );
// If we found no valid submenu ancestor, use the main menu to close all sub menus anyway
if ( !currentMenu.length ) {
currentMenu = this.element;
}
this._close( currentMenu );
this.blur( event );
this.activeMenu = currentMenu;
}, this.delay );
},
// With no arguments, closes the currently active menu - if nothing is active
// it closes all menus. If passed an argument, it will search for menus BELOW
_close: function( startMenu ) {
if ( !startMenu ) {
startMenu = this.active ? this.active.parent() : this.element;
}
startMenu
.find( ".ui-menu" )
.hide()
.attr( "aria-hidden", "true" )
.attr( "aria-expanded", "false" )
.end()
.find( "a.ui-state-active" )
.removeClass( "ui-state-active" );
},
collapse: function( event ) {
var newItem = this.active &&
this.active.parent().closest( ".ui-menu-item", this.element );
if ( newItem && newItem.length ) {
this._close();
this.focus( event, newItem );
}
},
expand: function( event ) {
var newItem = this.active &&
this.active
.children( ".ui-menu " )
.children( ".ui-menu-item" )
.first();
if ( newItem && newItem.length ) {
this._open( newItem.parent() );
// Delay so Firefox will not hide activedescendant change in expanding submenu from AT
this._delay(function() {
this.focus( event, newItem );
});
}
},
next: function( event ) {
this._move( "next", "first", event );
},
previous: function( event ) {
this._move( "prev", "last", event );
},
isFirstItem: function() {
return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
},
isLastItem: function() {
return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
},
_move: function( direction, filter, event ) {
var next;
if ( this.active ) {
if ( direction === "first" || direction === "last" ) {
next = this.active
[ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
.eq( -1 );
} else {
next = this.active
[ direction + "All" ]( ".ui-menu-item" )
.eq( 0 );
}
}
if ( !next || !next.length || !this.active ) {
next = this.activeMenu.children( ".ui-menu-item" )[ filter ]();
}
this.focus( event, next );
},
nextPage: function( event ) {
var item, base, height;
if ( !this.active ) {
this.next( event );
return;
}
if ( this.isLastItem() ) {
return;
}
if ( this._hasScroll() ) {
base = this.active.offset().top;
height = this.element.height();
this.active.nextAll( ".ui-menu-item" ).each(function() {
item = $( this );
return item.offset().top - base - height < 0;
});
this.focus( event, item );
} else {
this.focus( event, this.activeMenu.children( ".ui-menu-item" )
[ !this.active ? "first" : "last" ]() );
}
},
previousPage: function( event ) {
var item, base, height;
if ( !this.active ) {
this.next( event );
return;
}
if ( this.isFirstItem() ) {
return;
}
if ( this._hasScroll() ) {
base = this.active.offset().top;
height = this.element.height();
this.active.prevAll( ".ui-menu-item" ).each(function() {
item = $( this );
return item.offset().top - base + height > 0;
});
this.focus( event, item );
} else {
this.focus( event, this.activeMenu.children( ".ui-menu-item" ).first() );
}
},
_hasScroll: function() {
return this.element.outerHeight() < this.element.prop( "scrollHeight" );
},
select: function( event ) {
// TODO: It should never be possible to not have an active item at this
// point, but the tests don't trigger mouseenter before click.
this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
var ui = { item: this.active };
if ( !this.active.has( ".ui-menu" ).length ) {
this.collapseAll( event, true );
}
this._trigger( "select", event, ui );
}
});
}( jQuery ));
(function( $, undefined ) {
$.ui = $.ui || {};
var cachedScrollbarWidth,
max = Math.max,
abs = Math.abs,
round = Math.round,
rhorizontal = /left|center|right/,
rvertical = /top|center|bottom/,
roffset = /[\+\-]\d+%?/,
rposition = /^\w+/,
rpercent = /%$/,
_position = $.fn.position;
function getOffsets( offsets, width, height ) {
return [
parseInt( offsets[ 0 ], 10 ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
parseInt( offsets[ 1 ], 10 ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
];
}
function parseCss( element, property ) {
return parseInt( $.css( element, property ), 10 ) || 0;
}
$.position = {
scrollbarWidth: function() {
if ( cachedScrollbarWidth !== undefined ) {
return cachedScrollbarWidth;
}
var w1, w2,
div = $( "" ),
innerDiv = div.children()[0];
$( "body" ).append( div );
w1 = innerDiv.offsetWidth;
div.css( "overflow", "scroll" );
w2 = innerDiv.offsetWidth;
if ( w1 === w2 ) {
w2 = div[0].clientWidth;
}
div.remove();
return (cachedScrollbarWidth = w1 - w2);
},
getScrollInfo: function( within ) {
var overflowX = within.isWindow ? "" : within.element.css( "overflow-x" ),
overflowY = within.isWindow ? "" : within.element.css( "overflow-y" ),
hasOverflowX = overflowX === "scroll" ||
( overflowX === "auto" && within.width < within.element[0].scrollWidth ),
hasOverflowY = overflowY === "scroll" ||
( overflowY === "auto" && within.height < within.element[0].scrollHeight );
return {
width: hasOverflowX ? $.position.scrollbarWidth() : 0,
height: hasOverflowY ? $.position.scrollbarWidth() : 0
};
},
getWithinInfo: function( element ) {
var withinElement = $( element || window ),
isWindow = $.isWindow( withinElement[0] );
return {
element: withinElement,
isWindow: isWindow,
offset: withinElement.offset() || { left: 0, top: 0 },
scrollLeft: withinElement.scrollLeft(),
scrollTop: withinElement.scrollTop(),
width: isWindow ? withinElement.width() : withinElement.outerWidth(),
height: isWindow ? withinElement.height() : withinElement.outerHeight()
};
}
};
$.fn.position = function( options ) {
if ( !options || !options.of ) {
return _position.apply( this, arguments );
}
// make a copy, we don't want to modify arguments
options = $.extend( {}, options );
var atOffset, targetWidth, targetHeight, targetOffset, basePosition,
target = $( options.of ),
within = $.position.getWithinInfo( options.within ),
scrollInfo = $.position.getScrollInfo( within ),
targetElem = target[0],
collision = ( options.collision || "flip" ).split( " " ),
offsets = {};
if ( targetElem.nodeType === 9 ) {
targetWidth = target.width();
targetHeight = target.height();
targetOffset = { top: 0, left: 0 };
} else if ( $.isWindow( targetElem ) ) {
targetWidth = target.width();
targetHeight = target.height();
targetOffset = { top: target.scrollTop(), left: target.scrollLeft() };
} else if ( targetElem.preventDefault ) {
// force left top to allow flipping
options.at = "left top";
targetWidth = targetHeight = 0;
targetOffset = { top: targetElem.pageY, left: targetElem.pageX };
} else {
targetWidth = target.outerWidth();
targetHeight = target.outerHeight();
targetOffset = target.offset();
}
// clone to reuse original targetOffset later
basePosition = $.extend( {}, targetOffset );
// force my and at to have valid horizontal and vertical positions
// if a value is missing or invalid, it will be converted to center
$.each( [ "my", "at" ], function() {
var pos = ( options[ this ] || "" ).split( " " ),
horizontalOffset,
verticalOffset;
if ( pos.length === 1) {
pos = rhorizontal.test( pos[ 0 ] ) ?
pos.concat( [ "center" ] ) :
rvertical.test( pos[ 0 ] ) ?
[ "center" ].concat( pos ) :
[ "center", "center" ];
}
pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
// calculate offsets
horizontalOffset = roffset.exec( pos[ 0 ] );
verticalOffset = roffset.exec( pos[ 1 ] );
offsets[ this ] = [
horizontalOffset ? horizontalOffset[ 0 ] : 0,
verticalOffset ? verticalOffset[ 0 ] : 0
];
// reduce to just the positions without the offsets
options[ this ] = [
rposition.exec( pos[ 0 ] )[ 0 ],
rposition.exec( pos[ 1 ] )[ 0 ]
];
});
// normalize collision option
if ( collision.length === 1 ) {
collision[ 1 ] = collision[ 0 ];
}
if ( options.at[ 0 ] === "right" ) {
basePosition.left += targetWidth;
} else if ( options.at[ 0 ] === "center" ) {
basePosition.left += targetWidth / 2;
}
if ( options.at[ 1 ] === "bottom" ) {
basePosition.top += targetHeight;
} else if ( options.at[ 1 ] === "center" ) {
basePosition.top += targetHeight / 2;
}
atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
basePosition.left += atOffset[ 0 ];
basePosition.top += atOffset[ 1 ];
return this.each(function() {
var collisionPosition, using,
elem = $( this ),
elemWidth = elem.outerWidth(),
elemHeight = elem.outerHeight(),
marginLeft = parseCss( this, "marginLeft" ),
marginTop = parseCss( this, "marginTop" ),
collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width,
collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height,
position = $.extend( {}, basePosition ),
myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
if ( options.my[ 0 ] === "right" ) {
position.left -= elemWidth;
} else if ( options.my[ 0 ] === "center" ) {
position.left -= elemWidth / 2;
}
if ( options.my[ 1 ] === "bottom" ) {
position.top -= elemHeight;
} else if ( options.my[ 1 ] === "center" ) {
position.top -= elemHeight / 2;
}
position.left += myOffset[ 0 ];
position.top += myOffset[ 1 ];
// if the browser doesn't support fractions, then round for consistent results
if ( !$.support.offsetFractions ) {
position.left = round( position.left );
position.top = round( position.top );
}
collisionPosition = {
marginLeft: marginLeft,
marginTop: marginTop
};
$.each( [ "left", "top" ], function( i, dir ) {
if ( $.ui.position[ collision[ i ] ] ) {
$.ui.position[ collision[ i ] ][ dir ]( position, {
targetWidth: targetWidth,
targetHeight: targetHeight,
elemWidth: elemWidth,
elemHeight: elemHeight,
collisionPosition: collisionPosition,
collisionWidth: collisionWidth,
collisionHeight: collisionHeight,
offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
my: options.my,
at: options.at,
within: within,
elem : elem
});
}
});
if ( $.fn.bgiframe ) {
elem.bgiframe();
}
if ( options.using ) {
// adds feedback as second argument to using callback, if present
using = function( props ) {
var left = targetOffset.left - position.left,
right = left + targetWidth - elemWidth,
top = targetOffset.top - position.top,
bottom = top + targetHeight - elemHeight,
feedback = {
target: {
element: target,
left: targetOffset.left,
top: targetOffset.top,
width: targetWidth,
height: targetHeight
},
element: {
element: elem,
left: position.left,
top: position.top,
width: elemWidth,
height: elemHeight
},
horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
};
if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
feedback.horizontal = "center";
}
if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
feedback.vertical = "middle";
}
if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
feedback.important = "horizontal";
} else {
feedback.important = "vertical";
}
options.using.call( this, props, feedback );
};
}
elem.offset( $.extend( position, { using: using } ) );
});
};
$.ui.position = {
fit: {
left: function( position, data ) {
var within = data.within,
withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
outerWidth = within.width,
collisionPosLeft = position.left - data.collisionPosition.marginLeft,
overLeft = withinOffset - collisionPosLeft,
overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
newOverRight;
// element is wider than within
if ( data.collisionWidth > outerWidth ) {
// element is initially over the left side of within
if ( overLeft > 0 && overRight <= 0 ) {
newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset;
position.left += overLeft - newOverRight;
// element is initially over right side of within
} else if ( overRight > 0 && overLeft <= 0 ) {
position.left = withinOffset;
// element is initially over both left and right sides of within
} else {
if ( overLeft > overRight ) {
position.left = withinOffset + outerWidth - data.collisionWidth;
} else {
position.left = withinOffset;
}
}
// too far left -> align with left edge
} else if ( overLeft > 0 ) {
position.left += overLeft;
// too far right -> align with right edge
} else if ( overRight > 0 ) {
position.left -= overRight;
// adjust based on position and margin
} else {
position.left = max( position.left - collisionPosLeft, position.left );
}
},
top: function( position, data ) {
var within = data.within,
withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
outerHeight = data.within.height,
collisionPosTop = position.top - data.collisionPosition.marginTop,
overTop = withinOffset - collisionPosTop,
overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
newOverBottom;
// element is taller than within
if ( data.collisionHeight > outerHeight ) {
// element is initially over the top of within
if ( overTop > 0 && overBottom <= 0 ) {
newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset;
position.top += overTop - newOverBottom;
// element is initially over bottom of within
} else if ( overBottom > 0 && overTop <= 0 ) {
position.top = withinOffset;
// element is initially over both top and bottom of within
} else {
if ( overTop > overBottom ) {
position.top = withinOffset + outerHeight - data.collisionHeight;
} else {
position.top = withinOffset;
}
}
// too far up -> align with top
} else if ( overTop > 0 ) {
position.top += overTop;
// too far down -> align with bottom edge
} else if ( overBottom > 0 ) {
position.top -= overBottom;
// adjust based on position and margin
} else {
position.top = max( position.top - collisionPosTop, position.top );
}
}
},
flip: {
left: function( position, data ) {
var within = data.within,
withinOffset = within.offset.left + within.scrollLeft,
outerWidth = within.width,
offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
collisionPosLeft = position.left - data.collisionPosition.marginLeft,
overLeft = collisionPosLeft - offsetLeft,
overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
myOffset = data.my[ 0 ] === "left" ?
-data.elemWidth :
data.my[ 0 ] === "right" ?
data.elemWidth :
0,
atOffset = data.at[ 0 ] === "left" ?
data.targetWidth :
data.at[ 0 ] === "right" ?
-data.targetWidth :
0,
offset = -2 * data.offset[ 0 ],
newOverRight,
newOverLeft;
if ( overLeft < 0 ) {
newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset;
if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
position.left += myOffset + atOffset + offset;
}
}
else if ( overRight > 0 ) {
newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft;
if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
position.left += myOffset + atOffset + offset;
}
}
},
top: function( position, data ) {
var within = data.within,
withinOffset = within.offset.top + within.scrollTop,
outerHeight = within.height,
offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
collisionPosTop = position.top - data.collisionPosition.marginTop,
overTop = collisionPosTop - offsetTop,
overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
top = data.my[ 1 ] === "top",
myOffset = top ?
-data.elemHeight :
data.my[ 1 ] === "bottom" ?
data.elemHeight :
0,
atOffset = data.at[ 1 ] === "top" ?
data.targetHeight :
data.at[ 1 ] === "bottom" ?
-data.targetHeight :
0,
offset = -2 * data.offset[ 1 ],
newOverTop,
newOverBottom;
if ( overTop < 0 ) {
newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset;
if ( ( position.top + myOffset + atOffset + offset) > overTop && ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) ) {
position.top += myOffset + atOffset + offset;
}
}
else if ( overBottom > 0 ) {
newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop;
if ( ( position.top + myOffset + atOffset + offset) > overBottom && ( newOverTop > 0 || abs( newOverTop ) < overBottom ) ) {
position.top += myOffset + atOffset + offset;
}
}
}
},
flipfit: {
left: function() {
$.ui.position.flip.left.apply( this, arguments );
$.ui.position.fit.left.apply( this, arguments );
},
top: function() {
$.ui.position.flip.top.apply( this, arguments );
$.ui.position.fit.top.apply( this, arguments );
}
}
};
// fraction support test
(function () {
var testElement, testElementParent, testElementStyle, offsetLeft, i,
body = document.getElementsByTagName( "body" )[ 0 ],
div = document.createElement( "div" );
//Create a "fake body" for testing based on method used in jQuery.support
testElement = document.createElement( body ? "div" : "body" );
testElementStyle = {
visibility: "hidden",
width: 0,
height: 0,
border: 0,
margin: 0,
background: "none"
};
if ( body ) {
$.extend( testElementStyle, {
position: "absolute",
left: "-1000px",
top: "-1000px"
});
}
for ( i in testElementStyle ) {
testElement.style[ i ] = testElementStyle[ i ];
}
testElement.appendChild( div );
testElementParent = body || document.documentElement;
testElementParent.insertBefore( testElement, testElementParent.firstChild );
div.style.cssText = "position: absolute; left: 10.7432222px;";
offsetLeft = $( div ).offset().left;
$.support.offsetFractions = offsetLeft > 10 && offsetLeft < 11;
testElement.innerHTML = "";
testElementParent.removeChild( testElement );
})();
// DEPRECATED
if ( $.uiBackCompat !== false ) {
// offset option
(function( $ ) {
var _position = $.fn.position;
$.fn.position = function( options ) {
if ( !options || !options.offset ) {
return _position.call( this, options );
}
var offset = options.offset.split( " " ),
at = options.at.split( " " );
if ( offset.length === 1 ) {
offset[ 1 ] = offset[ 0 ];
}
if ( /^\d/.test( offset[ 0 ] ) ) {
offset[ 0 ] = "+" + offset[ 0 ];
}
if ( /^\d/.test( offset[ 1 ] ) ) {
offset[ 1 ] = "+" + offset[ 1 ];
}
if ( at.length === 1 ) {
if ( /left|center|right/.test( at[ 0 ] ) ) {
at[ 1 ] = "center";
} else {
at[ 1 ] = at[ 0 ];
at[ 0 ] = "center";
}
}
return _position.call( this, $.extend( options, {
at: at[ 0 ] + offset[ 0 ] + " " + at[ 1 ] + offset[ 1 ],
offset: undefined
} ) );
};
}( jQuery ) );
}
}( jQuery ) );
(function( $, undefined ) {
$.widget( "ui.progressbar", {
version: "1.9.2",
options: {
value: 0,
max: 100
},
min: 0,
_create: function() {
this.element
.addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
.attr({
role: "progressbar",
"aria-valuemin": this.min,
"aria-valuemax": this.options.max,
"aria-valuenow": this._value()
});
this.valueDiv = $( "" )
.appendTo( this.element );
this.oldValue = this._value();
this._refreshValue();
},
_destroy: function() {
this.element
.removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
.removeAttr( "role" )
.removeAttr( "aria-valuemin" )
.removeAttr( "aria-valuemax" )
.removeAttr( "aria-valuenow" );
this.valueDiv.remove();
},
value: function( newValue ) {
if ( newValue === undefined ) {
return this._value();
}
this._setOption( "value", newValue );
return this;
},
_setOption: function( key, value ) {
if ( key === "value" ) {
this.options.value = value;
this._refreshValue();
if ( this._value() === this.options.max ) {
this._trigger( "complete" );
}
}
this._super( key, value );
},
_value: function() {
var val = this.options.value;
// normalize invalid value
if ( typeof val !== "number" ) {
val = 0;
}
return Math.min( this.options.max, Math.max( this.min, val ) );
},
_percentage: function() {
return 100 * this._value() / this.options.max;
},
_refreshValue: function() {
var value = this.value(),
percentage = this._percentage();
if ( this.oldValue !== value ) {
this.oldValue = value;
this._trigger( "change" );
}
this.valueDiv
.toggle( value > this.min )
.toggleClass( "ui-corner-right", value === this.options.max )
.width( percentage.toFixed(0) + "%" );
this.element.attr( "aria-valuenow", value );
}
});
})( jQuery );
(function( $, undefined ) {
// number of pages in a slider
// (how many times can you page up/down to go through the whole range)
var numPages = 5;
$.widget( "ui.slider", $.ui.mouse, {
version: "1.9.2",
widgetEventPrefix: "slide",
options: {
animate: false,
distance: 0,
max: 100,
min: 0,
orientation: "horizontal",
range: false,
step: 1,
value: 0,
values: null
},
_create: function() {
var i, handleCount,
o = this.options,
existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ),
handle = "",
handles = [];
this._keySliding = false;
this._mouseSliding = false;
this._animateOff = true;
this._handleIndex = null;
this._detectOrientation();
this._mouseInit();
this.element
.addClass( "ui-slider" +
" ui-slider-" + this.orientation +
" ui-widget" +
" ui-widget-content" +
" ui-corner-all" +
( o.disabled ? " ui-slider-disabled ui-disabled" : "" ) );
this.range = $([]);
if ( o.range ) {
if ( o.range === true ) {
if ( !o.values ) {
o.values = [ this._valueMin(), this._valueMin() ];
}
if ( o.values.length && o.values.length !== 2 ) {
o.values = [ o.values[0], o.values[0] ];
}
}
this.range = $( "" )
.appendTo( this.element )
.addClass( "ui-slider-range" +
// note: this isn't the most fittingly semantic framework class for this element,
// but worked best visually with a variety of themes
" ui-widget-header" +
( ( o.range === "min" || o.range === "max" ) ? " ui-slider-range-" + o.range : "" ) );
}
handleCount = ( o.values && o.values.length ) || 1;
for ( i = existingHandles.length; i < handleCount; i++ ) {
handles.push( handle );
}
this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) );
this.handle = this.handles.eq( 0 );
this.handles.add( this.range ).filter( "a" )
.click(function( event ) {
event.preventDefault();
})
.mouseenter(function() {
if ( !o.disabled ) {
$( this ).addClass( "ui-state-hover" );
}
})
.mouseleave(function() {
$( this ).removeClass( "ui-state-hover" );
})
.focus(function() {
if ( !o.disabled ) {
$( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" );
$( this ).addClass( "ui-state-focus" );
} else {
$( this ).blur();
}
})
.blur(function() {
$( this ).removeClass( "ui-state-focus" );
});
this.handles.each(function( i ) {
$( this ).data( "ui-slider-handle-index", i );
});
this._on( this.handles, {
keydown: function( event ) {
var allowed, curVal, newVal, step,
index = $( event.target ).data( "ui-slider-handle-index" );
switch ( event.keyCode ) {
case $.ui.keyCode.HOME:
case $.ui.keyCode.END:
case $.ui.keyCode.PAGE_UP:
case $.ui.keyCode.PAGE_DOWN:
case $.ui.keyCode.UP:
case $.ui.keyCode.RIGHT:
case $.ui.keyCode.DOWN:
case $.ui.keyCode.LEFT:
event.preventDefault();
if ( !this._keySliding ) {
this._keySliding = true;
$( event.target ).addClass( "ui-state-active" );
allowed = this._start( event, index );
if ( allowed === false ) {
return;
}
}
break;
}
step = this.options.step;
if ( this.options.values && this.options.values.length ) {
curVal = newVal = this.values( index );
} else {
curVal = newVal = this.value();
}
switch ( event.keyCode ) {
case $.ui.keyCode.HOME:
newVal = this._valueMin();
break;
case $.ui.keyCode.END:
newVal = this._valueMax();
break;
case $.ui.keyCode.PAGE_UP:
newVal = this._trimAlignValue( curVal + ( (this._valueMax() - this._valueMin()) / numPages ) );
break;
case $.ui.keyCode.PAGE_DOWN:
newVal = this._trimAlignValue( curVal - ( (this._valueMax() - this._valueMin()) / numPages ) );
break;
case $.ui.keyCode.UP:
case $.ui.keyCode.RIGHT:
if ( curVal === this._valueMax() ) {
return;
}
newVal = this._trimAlignValue( curVal + step );
break;
case $.ui.keyCode.DOWN:
case $.ui.keyCode.LEFT:
if ( curVal === this._valueMin() ) {
return;
}
newVal = this._trimAlignValue( curVal - step );
break;
}
this._slide( event, index, newVal );
},
keyup: function( event ) {
var index = $( event.target ).data( "ui-slider-handle-index" );
if ( this._keySliding ) {
this._keySliding = false;
this._stop( event, index );
this._change( event, index );
$( event.target ).removeClass( "ui-state-active" );
}
}
});
this._refreshValue();
this._animateOff = false;
},
_destroy: function() {
this.handles.remove();
this.range.remove();
this.element
.removeClass( "ui-slider" +
" ui-slider-horizontal" +
" ui-slider-vertical" +
" ui-slider-disabled" +
" ui-widget" +
" ui-widget-content" +
" ui-corner-all" );
this._mouseDestroy();
},
_mouseCapture: function( event ) {
var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,
that = this,
o = this.options;
if ( o.disabled ) {
return false;
}
this.elementSize = {
width: this.element.outerWidth(),
height: this.element.outerHeight()
};
this.elementOffset = this.element.offset();
position = { x: event.pageX, y: event.pageY };
normValue = this._normValueFromMouse( position );
distance = this._valueMax() - this._valueMin() + 1;
this.handles.each(function( i ) {
var thisDistance = Math.abs( normValue - that.values(i) );
if ( distance > thisDistance ) {
distance = thisDistance;
closestHandle = $( this );
index = i;
}
});
// workaround for bug #3736 (if both handles of a range are at 0,
// the first is always used as the one with least distance,
// and moving it is obviously prevented by preventing negative ranges)
if( o.range === true && this.values(1) === o.min ) {
index += 1;
closestHandle = $( this.handles[index] );
}
allowed = this._start( event, index );
if ( allowed === false ) {
return false;
}
this._mouseSliding = true;
this._handleIndex = index;
closestHandle
.addClass( "ui-state-active" )
.focus();
offset = closestHandle.offset();
mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" );
this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
top: event.pageY - offset.top -
( closestHandle.height() / 2 ) -
( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
};
if ( !this.handles.hasClass( "ui-state-hover" ) ) {
this._slide( event, index, normValue );
}
this._animateOff = true;
return true;
},
_mouseStart: function() {
return true;
},
_mouseDrag: function( event ) {
var position = { x: event.pageX, y: event.pageY },
normValue = this._normValueFromMouse( position );
this._slide( event, this._handleIndex, normValue );
return false;
},
_mouseStop: function( event ) {
this.handles.removeClass( "ui-state-active" );
this._mouseSliding = false;
this._stop( event, this._handleIndex );
this._change( event, this._handleIndex );
this._handleIndex = null;
this._clickOffset = null;
this._animateOff = false;
return false;
},
_detectOrientation: function() {
this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
},
_normValueFromMouse: function( position ) {
var pixelTotal,
pixelMouse,
percentMouse,
valueTotal,
valueMouse;
if ( this.orientation === "horizontal" ) {
pixelTotal = this.elementSize.width;
pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
} else {
pixelTotal = this.elementSize.height;
pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
}
percentMouse = ( pixelMouse / pixelTotal );
if ( percentMouse > 1 ) {
percentMouse = 1;
}
if ( percentMouse < 0 ) {
percentMouse = 0;
}
if ( this.orientation === "vertical" ) {
percentMouse = 1 - percentMouse;
}
valueTotal = this._valueMax() - this._valueMin();
valueMouse = this._valueMin() + percentMouse * valueTotal;
return this._trimAlignValue( valueMouse );
},
_start: function( event, index ) {
var uiHash = {
handle: this.handles[ index ],
value: this.value()
};
if ( this.options.values && this.options.values.length ) {
uiHash.value = this.values( index );
uiHash.values = this.values();
}
return this._trigger( "start", event, uiHash );
},
_slide: function( event, index, newVal ) {
var otherVal,
newValues,
allowed;
if ( this.options.values && this.options.values.length ) {
otherVal = this.values( index ? 0 : 1 );
if ( ( this.options.values.length === 2 && this.options.range === true ) &&
( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
) {
newVal = otherVal;
}
if ( newVal !== this.values( index ) ) {
newValues = this.values();
newValues[ index ] = newVal;
// A slide can be canceled by returning false from the slide callback
allowed = this._trigger( "slide", event, {
handle: this.handles[ index ],
value: newVal,
values: newValues
} );
otherVal = this.values( index ? 0 : 1 );
if ( allowed !== false ) {
this.values( index, newVal, true );
}
}
} else {
if ( newVal !== this.value() ) {
// A slide can be canceled by returning false from the slide callback
allowed = this._trigger( "slide", event, {
handle: this.handles[ index ],
value: newVal
} );
if ( allowed !== false ) {
this.value( newVal );
}
}
}
},
_stop: function( event, index ) {
var uiHash = {
handle: this.handles[ index ],
value: this.value()
};
if ( this.options.values && this.options.values.length ) {
uiHash.value = this.values( index );
uiHash.values = this.values();
}
this._trigger( "stop", event, uiHash );
},
_change: function( event, index ) {
if ( !this._keySliding && !this._mouseSliding ) {
var uiHash = {
handle: this.handles[ index ],
value: this.value()
};
if ( this.options.values && this.options.values.length ) {
uiHash.value = this.values( index );
uiHash.values = this.values();
}
this._trigger( "change", event, uiHash );
}
},
value: function( newValue ) {
if ( arguments.length ) {
this.options.value = this._trimAlignValue( newValue );
this._refreshValue();
this._change( null, 0 );
return;
}
return this._value();
},
values: function( index, newValue ) {
var vals,
newValues,
i;
if ( arguments.length > 1 ) {
this.options.values[ index ] = this._trimAlignValue( newValue );
this._refreshValue();
this._change( null, index );
return;
}
if ( arguments.length ) {
if ( $.isArray( arguments[ 0 ] ) ) {
vals = this.options.values;
newValues = arguments[ 0 ];
for ( i = 0; i < vals.length; i += 1 ) {
vals[ i ] = this._trimAlignValue( newValues[ i ] );
this._change( null, i );
}
this._refreshValue();
} else {
if ( this.options.values && this.options.values.length ) {
return this._values( index );
} else {
return this.value();
}
}
} else {
return this._values();
}
},
_setOption: function( key, value ) {
var i,
valsLength = 0;
if ( $.isArray( this.options.values ) ) {
valsLength = this.options.values.length;
}
$.Widget.prototype._setOption.apply( this, arguments );
switch ( key ) {
case "disabled":
if ( value ) {
this.handles.filter( ".ui-state-focus" ).blur();
this.handles.removeClass( "ui-state-hover" );
this.handles.prop( "disabled", true );
this.element.addClass( "ui-disabled" );
} else {
this.handles.prop( "disabled", false );
this.element.removeClass( "ui-disabled" );
}
break;
case "orientation":
this._detectOrientation();
this.element
.removeClass( "ui-slider-horizontal ui-slider-vertical" )
.addClass( "ui-slider-" + this.orientation );
this._refreshValue();
break;
case "value":
this._animateOff = true;
this._refreshValue();
this._change( null, 0 );
this._animateOff = false;
break;
case "values":
this._animateOff = true;
this._refreshValue();
for ( i = 0; i < valsLength; i += 1 ) {
this._change( null, i );
}
this._animateOff = false;
break;
case "min":
case "max":
this._animateOff = true;
this._refreshValue();
this._animateOff = false;
break;
}
},
//internal value getter
// _value() returns value trimmed by min and max, aligned by step
_value: function() {
var val = this.options.value;
val = this._trimAlignValue( val );
return val;
},
//internal values getter
// _values() returns array of values trimmed by min and max, aligned by step
// _values( index ) returns single value trimmed by min and max, aligned by step
_values: function( index ) {
var val,
vals,
i;
if ( arguments.length ) {
val = this.options.values[ index ];
val = this._trimAlignValue( val );
return val;
} else {
// .slice() creates a copy of the array
// this copy gets trimmed by min and max and then returned
vals = this.options.values.slice();
for ( i = 0; i < vals.length; i+= 1) {
vals[ i ] = this._trimAlignValue( vals[ i ] );
}
return vals;
}
},
// returns the step-aligned value that val is closest to, between (inclusive) min and max
_trimAlignValue: function( val ) {
if ( val <= this._valueMin() ) {
return this._valueMin();
}
if ( val >= this._valueMax() ) {
return this._valueMax();
}
var step = ( this.options.step > 0 ) ? this.options.step : 1,
valModStep = (val - this._valueMin()) % step,
alignValue = val - valModStep;
if ( Math.abs(valModStep) * 2 >= step ) {
alignValue += ( valModStep > 0 ) ? step : ( -step );
}
// Since JavaScript has problems with large floats, round
// the final value to 5 digits after the decimal point (see #4124)
return parseFloat( alignValue.toFixed(5) );
},
_valueMin: function() {
return this.options.min;
},
_valueMax: function() {
return this.options.max;
},
_refreshValue: function() {
var lastValPercent, valPercent, value, valueMin, valueMax,
oRange = this.options.range,
o = this.options,
that = this,
animate = ( !this._animateOff ) ? o.animate : false,
_set = {};
if ( this.options.values && this.options.values.length ) {
this.handles.each(function( i ) {
valPercent = ( that.values(i) - that._valueMin() ) / ( that._valueMax() - that._valueMin() ) * 100;
_set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
$( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
if ( that.options.range === true ) {
if ( that.orientation === "horizontal" ) {
if ( i === 0 ) {
that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
}
if ( i === 1 ) {
that.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
}
} else {
if ( i === 0 ) {
that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
}
if ( i === 1 ) {
that.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
}
}
}
lastValPercent = valPercent;
});
} else {
value = this.value();
valueMin = this._valueMin();
valueMax = this._valueMax();
valPercent = ( valueMax !== valueMin ) ?
( value - valueMin ) / ( valueMax - valueMin ) * 100 :
0;
_set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
if ( oRange === "min" && this.orientation === "horizontal" ) {
this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
}
if ( oRange === "max" && this.orientation === "horizontal" ) {
this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
}
if ( oRange === "min" && this.orientation === "vertical" ) {
this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
}
if ( oRange === "max" && this.orientation === "vertical" ) {
this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
}
}
}
});
}(jQuery));
(function( $ ) {
function modifier( fn ) {
return function() {
var previous = this.element.val();
fn.apply( this, arguments );
this._refresh();
if ( previous !== this.element.val() ) {
this._trigger( "change" );
}
};
}
$.widget( "ui.spinner", {
version: "1.9.2",
defaultElement: "",
widgetEventPrefix: "spin",
options: {
culture: null,
icons: {
down: "ui-icon-triangle-1-s",
up: "ui-icon-triangle-1-n"
},
incremental: true,
max: null,
min: null,
numberFormat: null,
page: 10,
step: 1,
change: null,
spin: null,
start: null,
stop: null
},
_create: function() {
// handle string values that need to be parsed
this._setOption( "max", this.options.max );
this._setOption( "min", this.options.min );
this._setOption( "step", this.options.step );
// format the value, but don't constrain
this._value( this.element.val(), true );
this._draw();
this._on( this._events );
this._refresh();
// turning off autocomplete prevents the browser from remembering the
// value when navigating through history, so we re-enable autocomplete
// if the page is unloaded before the widget is destroyed. #7790
this._on( this.window, {
beforeunload: function() {
this.element.removeAttr( "autocomplete" );
}
});
},
_getCreateOptions: function() {
var options = {},
element = this.element;
$.each( [ "min", "max", "step" ], function( i, option ) {
var value = element.attr( option );
if ( value !== undefined && value.length ) {
options[ option ] = value;
}
});
return options;
},
_events: {
keydown: function( event ) {
if ( this._start( event ) && this._keydown( event ) ) {
event.preventDefault();
}
},
keyup: "_stop",
focus: function() {
this.previous = this.element.val();
},
blur: function( event ) {
if ( this.cancelBlur ) {
delete this.cancelBlur;
return;
}
this._refresh();
if ( this.previous !== this.element.val() ) {
this._trigger( "change", event );
}
},
mousewheel: function( event, delta ) {
if ( !delta ) {
return;
}
if ( !this.spinning && !this._start( event ) ) {
return false;
}
this._spin( (delta > 0 ? 1 : -1) * this.options.step, event );
clearTimeout( this.mousewheelTimer );
this.mousewheelTimer = this._delay(function() {
if ( this.spinning ) {
this._stop( event );
}
}, 100 );
event.preventDefault();
},
"mousedown .ui-spinner-button": function( event ) {
var previous;
// We never want the buttons to have focus; whenever the user is
// interacting with the spinner, the focus should be on the input.
// If the input is focused then this.previous is properly set from
// when the input first received focus. If the input is not focused
// then we need to set this.previous based on the value before spinning.
previous = this.element[0] === this.document[0].activeElement ?
this.previous : this.element.val();
function checkFocus() {
var isActive = this.element[0] === this.document[0].activeElement;
if ( !isActive ) {
this.element.focus();
this.previous = previous;
// support: IE
// IE sets focus asynchronously, so we need to check if focus
// moved off of the input because the user clicked on the button.
this._delay(function() {
this.previous = previous;
});
}
}
// ensure focus is on (or stays on) the text field
event.preventDefault();
checkFocus.call( this );
// support: IE
// IE doesn't prevent moving focus even with event.preventDefault()
// so we set a flag to know when we should ignore the blur event
// and check (again) if focus moved off of the input.
this.cancelBlur = true;
this._delay(function() {
delete this.cancelBlur;
checkFocus.call( this );
});
if ( this._start( event ) === false ) {
return;
}
this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
},
"mouseup .ui-spinner-button": "_stop",
"mouseenter .ui-spinner-button": function( event ) {
// button will add ui-state-active if mouse was down while mouseleave and kept down
if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) {
return;
}
if ( this._start( event ) === false ) {
return false;
}
this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
},
// TODO: do we really want to consider this a stop?
// shouldn't we just stop the repeater and wait until mouseup before
// we trigger the stop event?
"mouseleave .ui-spinner-button": "_stop"
},
_draw: function() {
var uiSpinner = this.uiSpinner = this.element
.addClass( "ui-spinner-input" )
.attr( "autocomplete", "off" )
.wrap( this._uiSpinnerHtml() )
.parent()
// add buttons
.append( this._buttonHtml() );
this.element.attr( "role", "spinbutton" );
// button bindings
this.buttons = uiSpinner.find( ".ui-spinner-button" )
.attr( "tabIndex", -1 )
.button()
.removeClass( "ui-corner-all" );
// IE 6 doesn't understand height: 50% for the buttons
// unless the wrapper has an explicit height
if ( this.buttons.height() > Math.ceil( uiSpinner.height() * 0.5 ) &&
uiSpinner.height() > 0 ) {
uiSpinner.height( uiSpinner.height() );
}
// disable spinner if element was already disabled
if ( this.options.disabled ) {
this.disable();
}
},
_keydown: function( event ) {
var options = this.options,
keyCode = $.ui.keyCode;
switch ( event.keyCode ) {
case keyCode.UP:
this._repeat( null, 1, event );
return true;
case keyCode.DOWN:
this._repeat( null, -1, event );
return true;
case keyCode.PAGE_UP:
this._repeat( null, options.page, event );
return true;
case keyCode.PAGE_DOWN:
this._repeat( null, -options.page, event );
return true;
}
return false;
},
_uiSpinnerHtml: function() {
return "";
},
_buttonHtml: function() {
return "" +
"" +
"▲" +
"" +
"" +
"▼" +
"";
},
_start: function( event ) {
if ( !this.spinning && this._trigger( "start", event ) === false ) {
return false;
}
if ( !this.counter ) {
this.counter = 1;
}
this.spinning = true;
return true;
},
_repeat: function( i, steps, event ) {
i = i || 500;
clearTimeout( this.timer );
this.timer = this._delay(function() {
this._repeat( 40, steps, event );
}, i );
this._spin( steps * this.options.step, event );
},
_spin: function( step, event ) {
var value = this.value() || 0;
if ( !this.counter ) {
this.counter = 1;
}
value = this._adjustValue( value + step * this._increment( this.counter ) );
if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false) {
this._value( value );
this.counter++;
}
},
_increment: function( i ) {
var incremental = this.options.incremental;
if ( incremental ) {
return $.isFunction( incremental ) ?
incremental( i ) :
Math.floor( i*i*i/50000 - i*i/500 + 17*i/200 + 1 );
}
return 1;
},
_precision: function() {
var precision = this._precisionOf( this.options.step );
if ( this.options.min !== null ) {
precision = Math.max( precision, this._precisionOf( this.options.min ) );
}
return precision;
},
_precisionOf: function( num ) {
var str = num.toString(),
decimal = str.indexOf( "." );
return decimal === -1 ? 0 : str.length - decimal - 1;
},
_adjustValue: function( value ) {
var base, aboveMin,
options = this.options;
// make sure we're at a valid step
// - find out where we are relative to the base (min or 0)
base = options.min !== null ? options.min : 0;
aboveMin = value - base;
// - round to the nearest step
aboveMin = Math.round(aboveMin / options.step) * options.step;
// - rounding is based on 0, so adjust back to our base
value = base + aboveMin;
// fix precision from bad JS floating point math
value = parseFloat( value.toFixed( this._precision() ) );
// clamp the value
if ( options.max !== null && value > options.max) {
return options.max;
}
if ( options.min !== null && value < options.min ) {
return options.min;
}
return value;
},
_stop: function( event ) {
if ( !this.spinning ) {
return;
}
clearTimeout( this.timer );
clearTimeout( this.mousewheelTimer );
this.counter = 0;
this.spinning = false;
this._trigger( "stop", event );
},
_setOption: function( key, value ) {
if ( key === "culture" || key === "numberFormat" ) {
var prevValue = this._parse( this.element.val() );
this.options[ key ] = value;
this.element.val( this._format( prevValue ) );
return;
}
if ( key === "max" || key === "min" || key === "step" ) {
if ( typeof value === "string" ) {
value = this._parse( value );
}
}
this._super( key, value );
if ( key === "disabled" ) {
if ( value ) {
this.element.prop( "disabled", true );
this.buttons.button( "disable" );
} else {
this.element.prop( "disabled", false );
this.buttons.button( "enable" );
}
}
},
_setOptions: modifier(function( options ) {
this._super( options );
this._value( this.element.val() );
}),
_parse: function( val ) {
if ( typeof val === "string" && val !== "" ) {
val = window.Globalize && this.options.numberFormat ?
Globalize.parseFloat( val, 10, this.options.culture ) : +val;
}
return val === "" || isNaN( val ) ? null : val;
},
_format: function( value ) {
if ( value === "" ) {
return "";
}
return window.Globalize && this.options.numberFormat ?
Globalize.format( value, this.options.numberFormat, this.options.culture ) :
value;
},
_refresh: function() {
this.element.attr({
"aria-valuemin": this.options.min,
"aria-valuemax": this.options.max,
// TODO: what should we do with values that can't be parsed?
"aria-valuenow": this._parse( this.element.val() )
});
},
// update the value without triggering change
_value: function( value, allowAny ) {
var parsed;
if ( value !== "" ) {
parsed = this._parse( value );
if ( parsed !== null ) {
if ( !allowAny ) {
parsed = this._adjustValue( parsed );
}
value = this._format( parsed );
}
}
this.element.val( value );
this._refresh();
},
_destroy: function() {
this.element
.removeClass( "ui-spinner-input" )
.prop( "disabled", false )
.removeAttr( "autocomplete" )
.removeAttr( "role" )
.removeAttr( "aria-valuemin" )
.removeAttr( "aria-valuemax" )
.removeAttr( "aria-valuenow" );
this.uiSpinner.replaceWith( this.element );
},
stepUp: modifier(function( steps ) {
this._stepUp( steps );
}),
_stepUp: function( steps ) {
this._spin( (steps || 1) * this.options.step );
},
stepDown: modifier(function( steps ) {
this._stepDown( steps );
}),
_stepDown: function( steps ) {
this._spin( (steps || 1) * -this.options.step );
},
pageUp: modifier(function( pages ) {
this._stepUp( (pages || 1) * this.options.page );
}),
pageDown: modifier(function( pages ) {
this._stepDown( (pages || 1) * this.options.page );
}),
value: function( newVal ) {
if ( !arguments.length ) {
return this._parse( this.element.val() );
}
modifier( this._value ).call( this, newVal );
},
widget: function() {
return this.uiSpinner;
}
});
}( jQuery ) );
(function( $, undefined ) {
var tabId = 0,
rhash = /#.*$/;
function getNextTabId() {
return ++tabId;
}
function isLocal( anchor ) {
return anchor.hash.length > 1 &&
anchor.href.replace( rhash, "" ) ===
location.href.replace( rhash, "" )
// support: Safari 5.1
// Safari 5.1 doesn't encode spaces in window.location
// but it does encode spaces from anchors (#8777)
.replace( /\s/g, "%20" );
}
$.widget( "ui.tabs", {
version: "1.9.2",
delay: 300,
options: {
active: null,
collapsible: false,
event: "click",
heightStyle: "content",
hide: null,
show: null,
// callbacks
activate: null,
beforeActivate: null,
beforeLoad: null,
load: null
},
_create: function() {
var that = this,
options = this.options,
active = options.active,
locationHash = location.hash.substring( 1 );
this.running = false;
this.element
.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" )
.toggleClass( "ui-tabs-collapsible", options.collapsible )
// Prevent users from focusing disabled tabs via click
.delegate( ".ui-tabs-nav > li", "mousedown" + this.eventNamespace, function( event ) {
if ( $( this ).is( ".ui-state-disabled" ) ) {
event.preventDefault();
}
})
// support: IE <9
// Preventing the default action in mousedown doesn't prevent IE
// from focusing the element, so if the anchor gets focused, blur.
// We don't have to worry about focusing the previously focused
// element since clicking on a non-focusable element should focus
// the body anyway.
.delegate( ".ui-tabs-anchor", "focus" + this.eventNamespace, function() {
if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) {
this.blur();
}
});
this._processTabs();
if ( active === null ) {
// check the fragment identifier in the URL
if ( locationHash ) {
this.tabs.each(function( i, tab ) {
if ( $( tab ).attr( "aria-controls" ) === locationHash ) {
active = i;
return false;
}
});
}
// check for a tab marked active via a class
if ( active === null ) {
active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );
}
// no active tab, set to false
if ( active === null || active === -1 ) {
active = this.tabs.length ? 0 : false;
}
}
// handle numbers: negative, out of range
if ( active !== false ) {
active = this.tabs.index( this.tabs.eq( active ) );
if ( active === -1 ) {
active = options.collapsible ? false : 0;
}
}
options.active = active;
// don't allow collapsible: false and active: false
if ( !options.collapsible && options.active === false && this.anchors.length ) {
options.active = 0;
}
// Take disabling tabs via class attribute from HTML
// into account and update option properly.
if ( $.isArray( options.disabled ) ) {
options.disabled = $.unique( options.disabled.concat(
$.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {
return that.tabs.index( li );
})
) ).sort();
}
// check for length avoids error when initializing empty list
if ( this.options.active !== false && this.anchors.length ) {
this.active = this._findActive( this.options.active );
} else {
this.active = $();
}
this._refresh();
if ( this.active.length ) {
this.load( options.active );
}
},
_getCreateEventData: function() {
return {
tab: this.active,
panel: !this.active.length ? $() : this._getPanelForTab( this.active )
};
},
_tabKeydown: function( event ) {
var focusedTab = $( this.document[0].activeElement ).closest( "li" ),
selectedIndex = this.tabs.index( focusedTab ),
goingForward = true;
if ( this._handlePageNav( event ) ) {
return;
}
switch ( event.keyCode ) {
case $.ui.keyCode.RIGHT:
case $.ui.keyCode.DOWN:
selectedIndex++;
break;
case $.ui.keyCode.UP:
case $.ui.keyCode.LEFT:
goingForward = false;
selectedIndex--;
break;
case $.ui.keyCode.END:
selectedIndex = this.anchors.length - 1;
break;
case $.ui.keyCode.HOME:
selectedIndex = 0;
break;
case $.ui.keyCode.SPACE:
// Activate only, no collapsing
event.preventDefault();
clearTimeout( this.activating );
this._activate( selectedIndex );
return;
case $.ui.keyCode.ENTER:
// Toggle (cancel delayed activation, allow collapsing)
event.preventDefault();
clearTimeout( this.activating );
// Determine if we should collapse or activate
this._activate( selectedIndex === this.options.active ? false : selectedIndex );
return;
default:
return;
}
// Focus the appropriate tab, based on which key was pressed
event.preventDefault();
clearTimeout( this.activating );
selectedIndex = this._focusNextTab( selectedIndex, goingForward );
// Navigating with control key will prevent automatic activation
if ( !event.ctrlKey ) {
// Update aria-selected immediately so that AT think the tab is already selected.
// Otherwise AT may confuse the user by stating that they need to activate the tab,
// but the tab will already be activated by the time the announcement finishes.
focusedTab.attr( "aria-selected", "false" );
this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );
this.activating = this._delay(function() {
this.option( "active", selectedIndex );
}, this.delay );
}
},
_panelKeydown: function( event ) {
if ( this._handlePageNav( event ) ) {
return;
}
// Ctrl+up moves focus to the current tab
if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {
event.preventDefault();
this.active.focus();
}
},
// Alt+page up/down moves focus to the previous/next tab (and activates)
_handlePageNav: function( event ) {
if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {
this._activate( this._focusNextTab( this.options.active - 1, false ) );
return true;
}
if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {
this._activate( this._focusNextTab( this.options.active + 1, true ) );
return true;
}
},
_findNextTab: function( index, goingForward ) {
var lastTabIndex = this.tabs.length - 1;
function constrain() {
if ( index > lastTabIndex ) {
index = 0;
}
if ( index < 0 ) {
index = lastTabIndex;
}
return index;
}
while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {
index = goingForward ? index + 1 : index - 1;
}
return index;
},
_focusNextTab: function( index, goingForward ) {
index = this._findNextTab( index, goingForward );
this.tabs.eq( index ).focus();
return index;
},
_setOption: function( key, value ) {
if ( key === "active" ) {
// _activate() will handle invalid values and update this.options
this._activate( value );
return;
}
if ( key === "disabled" ) {
// don't use the widget factory's disabled handling
this._setupDisabled( value );
return;
}
this._super( key, value);
if ( key === "collapsible" ) {
this.element.toggleClass( "ui-tabs-collapsible", value );
// Setting collapsible: false while collapsed; open first panel
if ( !value && this.options.active === false ) {
this._activate( 0 );
}
}
if ( key === "event" ) {
this._setupEvents( value );
}
if ( key === "heightStyle" ) {
this._setupHeightStyle( value );
}
},
_tabId: function( tab ) {
return tab.attr( "aria-controls" ) || "ui-tabs-" + getNextTabId();
},
_sanitizeSelector: function( hash ) {
return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : "";
},
refresh: function() {
var options = this.options,
lis = this.tablist.children( ":has(a[href])" );
// get disabled tabs from class attribute from HTML
// this will get converted to a boolean if needed in _refresh()
options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {
return lis.index( tab );
});
this._processTabs();
// was collapsed or no tabs
if ( options.active === false || !this.anchors.length ) {
options.active = false;
this.active = $();
// was active, but active tab is gone
} else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {
// all remaining tabs are disabled
if ( this.tabs.length === options.disabled.length ) {
options.active = false;
this.active = $();
// activate previous tab
} else {
this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );
}
// was active, active tab still exists
} else {
// make sure active index is correct
options.active = this.tabs.index( this.active );
}
this._refresh();
},
_refresh: function() {
this._setupDisabled( this.options.disabled );
this._setupEvents( this.options.event );
this._setupHeightStyle( this.options.heightStyle );
this.tabs.not( this.active ).attr({
"aria-selected": "false",
tabIndex: -1
});
this.panels.not( this._getPanelForTab( this.active ) )
.hide()
.attr({
"aria-expanded": "false",
"aria-hidden": "true"
});
// Make sure one tab is in the tab order
if ( !this.active.length ) {
this.tabs.eq( 0 ).attr( "tabIndex", 0 );
} else {
this.active
.addClass( "ui-tabs-active ui-state-active" )
.attr({
"aria-selected": "true",
tabIndex: 0
});
this._getPanelForTab( this.active )
.show()
.attr({
"aria-expanded": "true",
"aria-hidden": "false"
});
}
},
_processTabs: function() {
var that = this;
this.tablist = this._getList()
.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
.attr( "role", "tablist" );
this.tabs = this.tablist.find( "> li:has(a[href])" )
.addClass( "ui-state-default ui-corner-top" )
.attr({
role: "tab",
tabIndex: -1
});
this.anchors = this.tabs.map(function() {
return $( "a", this )[ 0 ];
})
.addClass( "ui-tabs-anchor" )
.attr({
role: "presentation",
tabIndex: -1
});
this.panels = $();
this.anchors.each(function( i, anchor ) {
var selector, panel, panelId,
anchorId = $( anchor ).uniqueId().attr( "id" ),
tab = $( anchor ).closest( "li" ),
originalAriaControls = tab.attr( "aria-controls" );
// inline tab
if ( isLocal( anchor ) ) {
selector = anchor.hash;
panel = that.element.find( that._sanitizeSelector( selector ) );
// remote tab
} else {
panelId = that._tabId( tab );
selector = "#" + panelId;
panel = that.element.find( selector );
if ( !panel.length ) {
panel = that._createPanel( panelId );
panel.insertAfter( that.panels[ i - 1 ] || that.tablist );
}
panel.attr( "aria-live", "polite" );
}
if ( panel.length) {
that.panels = that.panels.add( panel );
}
if ( originalAriaControls ) {
tab.data( "ui-tabs-aria-controls", originalAriaControls );
}
tab.attr({
"aria-controls": selector.substring( 1 ),
"aria-labelledby": anchorId
});
panel.attr( "aria-labelledby", anchorId );
});
this.panels
.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
.attr( "role", "tabpanel" );
},
// allow overriding how to find the list for rare usage scenarios (#7715)
_getList: function() {
return this.element.find( "ol,ul" ).eq( 0 );
},
_createPanel: function( id ) {
return $( "" )
.attr( "id", id )
.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
.data( "ui-tabs-destroy", true );
},
_setupDisabled: function( disabled ) {
if ( $.isArray( disabled ) ) {
if ( !disabled.length ) {
disabled = false;
} else if ( disabled.length === this.anchors.length ) {
disabled = true;
}
}
// disable tabs
for ( var i = 0, li; ( li = this.tabs[ i ] ); i++ ) {
if ( disabled === true || $.inArray( i, disabled ) !== -1 ) {
$( li )
.addClass( "ui-state-disabled" )
.attr( "aria-disabled", "true" );
} else {
$( li )
.removeClass( "ui-state-disabled" )
.removeAttr( "aria-disabled" );
}
}
this.options.disabled = disabled;
},
_setupEvents: function( event ) {
var events = {
click: function( event ) {
event.preventDefault();
}
};
if ( event ) {
$.each( event.split(" "), function( index, eventName ) {
events[ eventName ] = "_eventHandler";
});
}
this._off( this.anchors.add( this.tabs ).add( this.panels ) );
this._on( this.anchors, events );
this._on( this.tabs, { keydown: "_tabKeydown" } );
this._on( this.panels, { keydown: "_panelKeydown" } );
this._focusable( this.tabs );
this._hoverable( this.tabs );
},
_setupHeightStyle: function( heightStyle ) {
var maxHeight, overflow,
parent = this.element.parent();
if ( heightStyle === "fill" ) {
// IE 6 treats height like minHeight, so we need to turn off overflow
// in order to get a reliable height
// we use the minHeight support test because we assume that only
// browsers that don't support minHeight will treat height as minHeight
if ( !$.support.minHeight ) {
overflow = parent.css( "overflow" );
parent.css( "overflow", "hidden");
}
maxHeight = parent.height();
this.element.siblings( ":visible" ).each(function() {
var elem = $( this ),
position = elem.css( "position" );
if ( position === "absolute" || position === "fixed" ) {
return;
}
maxHeight -= elem.outerHeight( true );
});
if ( overflow ) {
parent.css( "overflow", overflow );
}
this.element.children().not( this.panels ).each(function() {
maxHeight -= $( this ).outerHeight( true );
});
this.panels.each(function() {
$( this ).height( Math.max( 0, maxHeight -
$( this ).innerHeight() + $( this ).height() ) );
})
.css( "overflow", "auto" );
} else if ( heightStyle === "auto" ) {
maxHeight = 0;
this.panels.each(function() {
maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
}).height( maxHeight );
}
},
_eventHandler: function( event ) {
var options = this.options,
active = this.active,
anchor = $( event.currentTarget ),
tab = anchor.closest( "li" ),
clickedIsActive = tab[ 0 ] === active[ 0 ],
collapsing = clickedIsActive && options.collapsible,
toShow = collapsing ? $() : this._getPanelForTab( tab ),
toHide = !active.length ? $() : this._getPanelForTab( active ),
eventData = {
oldTab: active,
oldPanel: toHide,
newTab: collapsing ? $() : tab,
newPanel: toShow
};
event.preventDefault();
if ( tab.hasClass( "ui-state-disabled" ) ||
// tab is already loading
tab.hasClass( "ui-tabs-loading" ) ||
// can't switch durning an animation
this.running ||
// click on active header, but not collapsible
( clickedIsActive && !options.collapsible ) ||
// allow canceling activation
( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
return;
}
options.active = collapsing ? false : this.tabs.index( tab );
this.active = clickedIsActive ? $() : tab;
if ( this.xhr ) {
this.xhr.abort();
}
if ( !toHide.length && !toShow.length ) {
$.error( "jQuery UI Tabs: Mismatching fragment identifier." );
}
if ( toShow.length ) {
this.load( this.tabs.index( tab ), event );
}
this._toggle( event, eventData );
},
// handles show/hide for selecting tabs
_toggle: function( event, eventData ) {
var that = this,
toShow = eventData.newPanel,
toHide = eventData.oldPanel;
this.running = true;
function complete() {
that.running = false;
that._trigger( "activate", event, eventData );
}
function show() {
eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" );
if ( toShow.length && that.options.show ) {
that._show( toShow, that.options.show, complete );
} else {
toShow.show();
complete();
}
}
// start out by hiding, then showing, then completing
if ( toHide.length && this.options.hide ) {
this._hide( toHide, this.options.hide, function() {
eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
show();
});
} else {
eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
toHide.hide();
show();
}
toHide.attr({
"aria-expanded": "false",
"aria-hidden": "true"
});
eventData.oldTab.attr( "aria-selected", "false" );
// If we're switching tabs, remove the old tab from the tab order.
// If we're opening from collapsed state, remove the previous tab from the tab order.
// If we're collapsing, then keep the collapsing tab in the tab order.
if ( toShow.length && toHide.length ) {
eventData.oldTab.attr( "tabIndex", -1 );
} else if ( toShow.length ) {
this.tabs.filter(function() {
return $( this ).attr( "tabIndex" ) === 0;
})
.attr( "tabIndex", -1 );
}
toShow.attr({
"aria-expanded": "true",
"aria-hidden": "false"
});
eventData.newTab.attr({
"aria-selected": "true",
tabIndex: 0
});
},
_activate: function( index ) {
var anchor,
active = this._findActive( index );
// trying to activate the already active panel
if ( active[ 0 ] === this.active[ 0 ] ) {
return;
}
// trying to collapse, simulate a click on the current active header
if ( !active.length ) {
active = this.active;
}
anchor = active.find( ".ui-tabs-anchor" )[ 0 ];
this._eventHandler({
target: anchor,
currentTarget: anchor,
preventDefault: $.noop
});
},
_findActive: function( index ) {
return index === false ? $() : this.tabs.eq( index );
},
_getIndex: function( index ) {
// meta-function to give users option to provide a href string instead of a numerical index.
if ( typeof index === "string" ) {
index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) );
}
return index;
},
_destroy: function() {
if ( this.xhr ) {
this.xhr.abort();
}
this.element.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" );
this.tablist
.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
.removeAttr( "role" );
this.anchors
.removeClass( "ui-tabs-anchor" )
.removeAttr( "role" )
.removeAttr( "tabIndex" )
.removeData( "href.tabs" )
.removeData( "load.tabs" )
.removeUniqueId();
this.tabs.add( this.panels ).each(function() {
if ( $.data( this, "ui-tabs-destroy" ) ) {
$( this ).remove();
} else {
$( this )
.removeClass( "ui-state-default ui-state-active ui-state-disabled " +
"ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel" )
.removeAttr( "tabIndex" )
.removeAttr( "aria-live" )
.removeAttr( "aria-busy" )
.removeAttr( "aria-selected" )
.removeAttr( "aria-labelledby" )
.removeAttr( "aria-hidden" )
.removeAttr( "aria-expanded" )
.removeAttr( "role" );
}
});
this.tabs.each(function() {
var li = $( this ),
prev = li.data( "ui-tabs-aria-controls" );
if ( prev ) {
li.attr( "aria-controls", prev );
} else {
li.removeAttr( "aria-controls" );
}
});
this.panels.show();
if ( this.options.heightStyle !== "content" ) {
this.panels.css( "height", "" );
}
},
enable: function( index ) {
var disabled = this.options.disabled;
if ( disabled === false ) {
return;
}
if ( index === undefined ) {
disabled = false;
} else {
index = this._getIndex( index );
if ( $.isArray( disabled ) ) {
disabled = $.map( disabled, function( num ) {
return num !== index ? num : null;
});
} else {
disabled = $.map( this.tabs, function( li, num ) {
return num !== index ? num : null;
});
}
}
this._setupDisabled( disabled );
},
disable: function( index ) {
var disabled = this.options.disabled;
if ( disabled === true ) {
return;
}
if ( index === undefined ) {
disabled = true;
} else {
index = this._getIndex( index );
if ( $.inArray( index, disabled ) !== -1 ) {
return;
}
if ( $.isArray( disabled ) ) {
disabled = $.merge( [ index ], disabled ).sort();
} else {
disabled = [ index ];
}
}
this._setupDisabled( disabled );
},
load: function( index, event ) {
index = this._getIndex( index );
var that = this,
tab = this.tabs.eq( index ),
anchor = tab.find( ".ui-tabs-anchor" ),
panel = this._getPanelForTab( tab ),
eventData = {
tab: tab,
panel: panel
};
// not remote
if ( isLocal( anchor[ 0 ] ) ) {
return;
}
this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );
// support: jQuery <1.8
// jQuery <1.8 returns false if the request is canceled in beforeSend,
// but as of 1.8, $.ajax() always returns a jqXHR object.
if ( this.xhr && this.xhr.statusText !== "canceled" ) {
tab.addClass( "ui-tabs-loading" );
panel.attr( "aria-busy", "true" );
this.xhr
.success(function( response ) {
// support: jQuery <1.8
// http://bugs.jquery.com/ticket/11778
setTimeout(function() {
panel.html( response );
that._trigger( "load", event, eventData );
}, 1 );
})
.complete(function( jqXHR, status ) {
// support: jQuery <1.8
// http://bugs.jquery.com/ticket/11778
setTimeout(function() {
if ( status === "abort" ) {
that.panels.stop( false, true );
}
tab.removeClass( "ui-tabs-loading" );
panel.removeAttr( "aria-busy" );
if ( jqXHR === that.xhr ) {
delete that.xhr;
}
}, 1 );
});
}
},
// TODO: Remove this function in 1.10 when ajaxOptions is removed
_ajaxSettings: function( anchor, event, eventData ) {
var that = this;
return {
url: anchor.attr( "href" ),
beforeSend: function( jqXHR, settings ) {
return that._trigger( "beforeLoad", event,
$.extend( { jqXHR : jqXHR, ajaxSettings: settings }, eventData ) );
}
};
},
_getPanelForTab: function( tab ) {
var id = $( tab ).attr( "aria-controls" );
return this.element.find( this._sanitizeSelector( "#" + id ) );
}
});
// DEPRECATED
if ( $.uiBackCompat !== false ) {
// helper method for a lot of the back compat extensions
$.ui.tabs.prototype._ui = function( tab, panel ) {
return {
tab: tab,
panel: panel,
index: this.anchors.index( tab )
};
};
// url method
$.widget( "ui.tabs", $.ui.tabs, {
url: function( index, url ) {
this.anchors.eq( index ).attr( "href", url );
}
});
// TODO: Remove _ajaxSettings() method when removing this extension
// ajaxOptions and cache options
$.widget( "ui.tabs", $.ui.tabs, {
options: {
ajaxOptions: null,
cache: false
},
_create: function() {
this._super();
var that = this;
this._on({ tabsbeforeload: function( event, ui ) {
// tab is already cached
if ( $.data( ui.tab[ 0 ], "cache.tabs" ) ) {
event.preventDefault();
return;
}
ui.jqXHR.success(function() {
if ( that.options.cache ) {
$.data( ui.tab[ 0 ], "cache.tabs", true );
}
});
}});
},
_ajaxSettings: function( anchor, event, ui ) {
var ajaxOptions = this.options.ajaxOptions;
return $.extend( {}, ajaxOptions, {
error: function( xhr, status ) {
try {
// Passing index avoid a race condition when this method is
// called after the user has selected another tab.
// Pass the anchor that initiated this request allows
// loadError to manipulate the tab content panel via $(a.hash)
ajaxOptions.error(
xhr, status, ui.tab.closest( "li" ).index(), ui.tab[ 0 ] );
}
catch ( error ) {}
}
}, this._superApply( arguments ) );
},
_setOption: function( key, value ) {
// reset cache if switching from cached to not cached
if ( key === "cache" && value === false ) {
this.anchors.removeData( "cache.tabs" );
}
this._super( key, value );
},
_destroy: function() {
this.anchors.removeData( "cache.tabs" );
this._super();
},
url: function( index ){
this.anchors.eq( index ).removeData( "cache.tabs" );
this._superApply( arguments );
}
});
// abort method
$.widget( "ui.tabs", $.ui.tabs, {
abort: function() {
if ( this.xhr ) {
this.xhr.abort();
}
}
});
// spinner
$.widget( "ui.tabs", $.ui.tabs, {
options: {
spinner: "
Loading…"
},
_create: function() {
this._super();
this._on({
tabsbeforeload: function( event, ui ) {
// Don't react to nested tabs or tabs that don't use a spinner
if ( event.target !== this.element[ 0 ] ||
!this.options.spinner ) {
return;
}
var span = ui.tab.find( "span" ),
html = span.html();
span.html( this.options.spinner );
ui.jqXHR.complete(function() {
span.html( html );
});
}
});
}
});
// enable/disable events
$.widget( "ui.tabs", $.ui.tabs, {
options: {
enable: null,
disable: null
},
enable: function( index ) {
var options = this.options,
trigger;
if ( index && options.disabled === true ||
( $.isArray( options.disabled ) && $.inArray( index, options.disabled ) !== -1 ) ) {
trigger = true;
}
this._superApply( arguments );
if ( trigger ) {
this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
}
},
disable: function( index ) {
var options = this.options,
trigger;
if ( index && options.disabled === false ||
( $.isArray( options.disabled ) && $.inArray( index, options.disabled ) === -1 ) ) {
trigger = true;
}
this._superApply( arguments );
if ( trigger ) {
this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
}
}
});
// add/remove methods and events
$.widget( "ui.tabs", $.ui.tabs, {
options: {
add: null,
remove: null,
tabTemplate: "
- #{label}
"
},
add: function( url, label, index ) {
if ( index === undefined ) {
index = this.anchors.length;
}
var doInsertAfter, panel,
options = this.options,
li = $( options.tabTemplate
.replace( /#\{href\}/g, url )
.replace( /#\{label\}/g, label ) ),
id = !url.indexOf( "#" ) ?
url.replace( "#", "" ) :
this._tabId( li );
li.addClass( "ui-state-default ui-corner-top" ).data( "ui-tabs-destroy", true );
li.attr( "aria-controls", id );
doInsertAfter = index >= this.tabs.length;
// try to find an existing element before creating a new one
panel = this.element.find( "#" + id );
if ( !panel.length ) {
panel = this._createPanel( id );
if ( doInsertAfter ) {
if ( index > 0 ) {
panel.insertAfter( this.panels.eq( -1 ) );
} else {
panel.appendTo( this.element );
}
} else {
panel.insertBefore( this.panels[ index ] );
}
}
panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ).hide();
if ( doInsertAfter ) {
li.appendTo( this.tablist );
} else {
li.insertBefore( this.tabs[ index ] );
}
options.disabled = $.map( options.disabled, function( n ) {
return n >= index ? ++n : n;
});
this.refresh();
if ( this.tabs.length === 1 && options.active === false ) {
this.option( "active", 0 );
}
this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
return this;
},
remove: function( index ) {
index = this._getIndex( index );
var options = this.options,
tab = this.tabs.eq( index ).remove(),
panel = this._getPanelForTab( tab ).remove();
// If selected tab was removed focus tab to the right or
// in case the last tab was removed the tab to the left.
// We check for more than 2 tabs, because if there are only 2,
// then when we remove this tab, there will only be one tab left
// so we don't need to detect which tab to activate.
if ( tab.hasClass( "ui-tabs-active" ) && this.anchors.length > 2 ) {
this._activate( index + ( index + 1 < this.anchors.length ? 1 : -1 ) );
}
options.disabled = $.map(
$.grep( options.disabled, function( n ) {
return n !== index;
}),
function( n ) {
return n >= index ? --n : n;
});
this.refresh();
this._trigger( "remove", null, this._ui( tab.find( "a" )[ 0 ], panel[ 0 ] ) );
return this;
}
});
// length method
$.widget( "ui.tabs", $.ui.tabs, {
length: function() {
return this.anchors.length;
}
});
// panel ids (idPrefix option + title attribute)
$.widget( "ui.tabs", $.ui.tabs, {
options: {
idPrefix: "ui-tabs-"
},
_tabId: function( tab ) {
var a = tab.is( "li" ) ? tab.find( "a[href]" ) : tab;
a = a[0];
return $( a ).closest( "li" ).attr( "aria-controls" ) ||
a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF\-]/g, "" ) ||
this.options.idPrefix + getNextTabId();
}
});
// _createPanel method
$.widget( "ui.tabs", $.ui.tabs, {
options: {
panelTemplate: "
"
},
_createPanel: function( id ) {
return $( this.options.panelTemplate )
.attr( "id", id )
.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
.data( "ui-tabs-destroy", true );
}
});
// selected option
$.widget( "ui.tabs", $.ui.tabs, {
_create: function() {
var options = this.options;
if ( options.active === null && options.selected !== undefined ) {
options.active = options.selected === -1 ? false : options.selected;
}
this._super();
options.selected = options.active;
if ( options.selected === false ) {
options.selected = -1;
}
},
_setOption: function( key, value ) {
if ( key !== "selected" ) {
return this._super( key, value );
}
var options = this.options;
this._super( "active", value === -1 ? false : value );
options.selected = options.active;
if ( options.selected === false ) {
options.selected = -1;
}
},
_eventHandler: function() {
this._superApply( arguments );
this.options.selected = this.options.active;
if ( this.options.selected === false ) {
this.options.selected = -1;
}
}
});
// show and select event
$.widget( "ui.tabs", $.ui.tabs, {
options: {
show: null,
select: null
},
_create: function() {
this._super();
if ( this.options.active !== false ) {
this._trigger( "show", null, this._ui(
this.active.find( ".ui-tabs-anchor" )[ 0 ],
this._getPanelForTab( this.active )[ 0 ] ) );
}
},
_trigger: function( type, event, data ) {
var tab, panel,
ret = this._superApply( arguments );
if ( !ret ) {
return false;
}
if ( type === "beforeActivate" ) {
tab = data.newTab.length ? data.newTab : data.oldTab;
panel = data.newPanel.length ? data.newPanel : data.oldPanel;
ret = this._super( "select", event, {
tab: tab.find( ".ui-tabs-anchor" )[ 0],
panel: panel[ 0 ],
index: tab.closest( "li" ).index()
});
} else if ( type === "activate" && data.newTab.length ) {
ret = this._super( "show", event, {
tab: data.newTab.find( ".ui-tabs-anchor" )[ 0 ],
panel: data.newPanel[ 0 ],
index: data.newTab.closest( "li" ).index()
});
}
return ret;
}
});
// select method
$.widget( "ui.tabs", $.ui.tabs, {
select: function( index ) {
index = this._getIndex( index );
if ( index === -1 ) {
if ( this.options.collapsible && this.options.selected !== -1 ) {
index = this.options.selected;
} else {
return;
}
}
this.anchors.eq( index ).trigger( this.options.event + this.eventNamespace );
}
});
// cookie option
(function() {
var listId = 0;
$.widget( "ui.tabs", $.ui.tabs, {
options: {
cookie: null // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
},
_create: function() {
var options = this.options,
active;
if ( options.active == null && options.cookie ) {
active = parseInt( this._cookie(), 10 );
if ( active === -1 ) {
active = false;
}
options.active = active;
}
this._super();
},
_cookie: function( active ) {
var cookie = [ this.cookie ||
( this.cookie = this.options.cookie.name || "ui-tabs-" + (++listId) ) ];
if ( arguments.length ) {
cookie.push( active === false ? -1 : active );
cookie.push( this.options.cookie );
}
return $.cookie.apply( null, cookie );
},
_refresh: function() {
this._super();
if ( this.options.cookie ) {
this._cookie( this.options.active, this.options.cookie );
}
},
_eventHandler: function() {
this._superApply( arguments );
if ( this.options.cookie ) {
this._cookie( this.options.active, this.options.cookie );
}
},
_destroy: function() {
this._super();
if ( this.options.cookie ) {
this._cookie( null, this.options.cookie );
}
}
});
})();
// load event
$.widget( "ui.tabs", $.ui.tabs, {
_trigger: function( type, event, data ) {
var _data = $.extend( {}, data );
if ( type === "load" ) {
_data.panel = _data.panel[ 0 ];
_data.tab = _data.tab.find( ".ui-tabs-anchor" )[ 0 ];
}
return this._super( type, event, _data );
}
});
// fx option
// The new animation options (show, hide) conflict with the old show callback.
// The old fx option wins over show/hide anyway (always favor back-compat).
// If a user wants to use the new animation API, they must give up the old API.
$.widget( "ui.tabs", $.ui.tabs, {
options: {
fx: null // e.g. { height: "toggle", opacity: "toggle", duration: 200 }
},
_getFx: function() {
var hide, show,
fx = this.options.fx;
if ( fx ) {
if ( $.isArray( fx ) ) {
hide = fx[ 0 ];
show = fx[ 1 ];
} else {
hide = show = fx;
}
}
return fx ? { show: show, hide: hide } : null;
},
_toggle: function( event, eventData ) {
var that = this,
toShow = eventData.newPanel,
toHide = eventData.oldPanel,
fx = this._getFx();
if ( !fx ) {
return this._super( event, eventData );
}
that.running = true;
function complete() {
that.running = false;
that._trigger( "activate", event, eventData );
}
function show() {
eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" );
if ( toShow.length && fx.show ) {
toShow
.animate( fx.show, fx.show.duration, function() {
complete();
});
} else {
toShow.show();
complete();
}
}
// start out by hiding, then showing, then completing
if ( toHide.length && fx.hide ) {
toHide.animate( fx.hide, fx.hide.duration, function() {
eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
show();
});
} else {
eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
toHide.hide();
show();
}
}
});
}
})( jQuery );
(function( $ ) {
var increments = 0;
function addDescribedBy( elem, id ) {
var describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ );
describedby.push( id );
elem
.data( "ui-tooltip-id", id )
.attr( "aria-describedby", $.trim( describedby.join( " " ) ) );
}
function removeDescribedBy( elem ) {
var id = elem.data( "ui-tooltip-id" ),
describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ),
index = $.inArray( id, describedby );
if ( index !== -1 ) {
describedby.splice( index, 1 );
}
elem.removeData( "ui-tooltip-id" );
describedby = $.trim( describedby.join( " " ) );
if ( describedby ) {
elem.attr( "aria-describedby", describedby );
} else {
elem.removeAttr( "aria-describedby" );
}
}
$.widget( "ui.tooltip", {
version: "1.9.2",
options: {
content: function() {
return $( this ).attr( "title" );
},
hide: true,
// Disabled elements have inconsistent behavior across browsers (#8661)
items: "[title]:not([disabled])",
position: {
my: "left top+15",
at: "left bottom",
collision: "flipfit flip"
},
show: true,
tooltipClass: null,
track: false,
// callbacks
close: null,
open: null
},
_create: function() {
this._on({
mouseover: "open",
focusin: "open"
});
// IDs of generated tooltips, needed for destroy
this.tooltips = {};
// IDs of parent tooltips where we removed the title attribute
this.parents = {};
if ( this.options.disabled ) {
this._disable();
}
},
_setOption: function( key, value ) {
var that = this;
if ( key === "disabled" ) {
this[ value ? "_disable" : "_enable" ]();
this.options[ key ] = value;
// disable element style changes
return;
}
this._super( key, value );
if ( key === "content" ) {
$.each( this.tooltips, function( id, element ) {
that._updateContent( element );
});
}
},
_disable: function() {
var that = this;
// close open tooltips
$.each( this.tooltips, function( id, element ) {
var event = $.Event( "blur" );
event.target = event.currentTarget = element[0];
that.close( event, true );
});
// remove title attributes to prevent native tooltips
this.element.find( this.options.items ).addBack().each(function() {
var element = $( this );
if ( element.is( "[title]" ) ) {
element
.data( "ui-tooltip-title", element.attr( "title" ) )
.attr( "title", "" );
}
});
},
_enable: function() {
// restore title attributes
this.element.find( this.options.items ).addBack().each(function() {
var element = $( this );
if ( element.data( "ui-tooltip-title" ) ) {
element.attr( "title", element.data( "ui-tooltip-title" ) );
}
});
},
open: function( event ) {
var that = this,
target = $( event ? event.target : this.element )
// we need closest here due to mouseover bubbling,
// but always pointing at the same event target
.closest( this.options.items );
// No element to show a tooltip for or the tooltip is already open
if ( !target.length || target.data( "ui-tooltip-id" ) ) {
return;
}
if ( target.attr( "title" ) ) {
target.data( "ui-tooltip-title", target.attr( "title" ) );
}
target.data( "ui-tooltip-open", true );
// kill parent tooltips, custom or native, for hover
if ( event && event.type === "mouseover" ) {
target.parents().each(function() {
var parent = $( this ),
blurEvent;
if ( parent.data( "ui-tooltip-open" ) ) {
blurEvent = $.Event( "blur" );
blurEvent.target = blurEvent.currentTarget = this;
that.close( blurEvent, true );
}
if ( parent.attr( "title" ) ) {
parent.uniqueId();
that.parents[ this.id ] = {
element: this,
title: parent.attr( "title" )
};
parent.attr( "title", "" );
}
});
}
this._updateContent( target, event );
},
_updateContent: function( target, event ) {
var content,
contentOption = this.options.content,
that = this,
eventType = event ? event.type : null;
if ( typeof contentOption === "string" ) {
return this._open( event, target, contentOption );
}
content = contentOption.call( target[0], function( response ) {
// ignore async response if tooltip was closed already
if ( !target.data( "ui-tooltip-open" ) ) {
return;
}
// IE may instantly serve a cached response for ajax requests
// delay this call to _open so the other call to _open runs first
that._delay(function() {
// jQuery creates a special event for focusin when it doesn't
// exist natively. To improve performance, the native event
// object is reused and the type is changed. Therefore, we can't
// rely on the type being correct after the event finished
// bubbling, so we set it back to the previous value. (#8740)
if ( event ) {
event.type = eventType;
}
this._open( event, target, response );
});
});
if ( content ) {
this._open( event, target, content );
}
},
_open: function( event, target, content ) {
var tooltip, events, delayedShow,
positionOption = $.extend( {}, this.options.position );
if ( !content ) {
return;
}
// Content can be updated multiple times. If the tooltip already
// exists, then just update the content and bail.
tooltip = this._find( target );
if ( tooltip.length ) {
tooltip.find( ".ui-tooltip-content" ).html( content );
return;
}
// if we have a title, clear it to prevent the native tooltip
// we have to check first to avoid defining a title if none exists
// (we don't want to cause an element to start matching [title])
//
// We use removeAttr only for key events, to allow IE to export the correct
// accessible attributes. For mouse events, set to empty string to avoid
// native tooltip showing up (happens only when removing inside mouseover).
if ( target.is( "[title]" ) ) {
if ( event && event.type === "mouseover" ) {
target.attr( "title", "" );
} else {
target.removeAttr( "title" );
}
}
tooltip = this._tooltip( target );
addDescribedBy( target, tooltip.attr( "id" ) );
tooltip.find( ".ui-tooltip-content" ).html( content );
function position( event ) {
positionOption.of = event;
if ( tooltip.is( ":hidden" ) ) {
return;
}
tooltip.position( positionOption );
}
if ( this.options.track && event && /^mouse/.test( event.type ) ) {
this._on( this.document, {
mousemove: position
});
// trigger once to override element-relative positioning
position( event );
} else {
tooltip.position( $.extend({
of: target
}, this.options.position ) );
}
tooltip.hide();
this._show( tooltip, this.options.show );
// Handle tracking tooltips that are shown with a delay (#8644). As soon
// as the tooltip is visible, position the tooltip using the most recent
// event.
if ( this.options.show && this.options.show.delay ) {
delayedShow = setInterval(function() {
if ( tooltip.is( ":visible" ) ) {
position( positionOption.of );
clearInterval( delayedShow );
}
}, $.fx.interval );
}
this._trigger( "open", event, { tooltip: tooltip } );
events = {
keyup: function( event ) {
if ( event.keyCode === $.ui.keyCode.ESCAPE ) {
var fakeEvent = $.Event(event);
fakeEvent.currentTarget = target[0];
this.close( fakeEvent, true );
}
},
remove: function() {
this._removeTooltip( tooltip );
}
};
if ( !event || event.type === "mouseover" ) {
events.mouseleave = "close";
}
if ( !event || event.type === "focusin" ) {
events.focusout = "close";
}
this._on( true, target, events );
},
close: function( event ) {
var that = this,
target = $( event ? event.currentTarget : this.element ),
tooltip = this._find( target );
// disabling closes the tooltip, so we need to track when we're closing
// to avoid an infinite loop in case the tooltip becomes disabled on close
if ( this.closing ) {
return;
}
// only set title if we had one before (see comment in _open())
if ( target.data( "ui-tooltip-title" ) ) {
target.attr( "title", target.data( "ui-tooltip-title" ) );
}
removeDescribedBy( target );
tooltip.stop( true );
this._hide( tooltip, this.options.hide, function() {
that._removeTooltip( $( this ) );
});
target.removeData( "ui-tooltip-open" );
this._off( target, "mouseleave focusout keyup" );
// Remove 'remove' binding only on delegated targets
if ( target[0] !== this.element[0] ) {
this._off( target, "remove" );
}
this._off( this.document, "mousemove" );
if ( event && event.type === "mouseleave" ) {
$.each( this.parents, function( id, parent ) {
$( parent.element ).attr( "title", parent.title );
delete that.parents[ id ];
});
}
this.closing = true;
this._trigger( "close", event, { tooltip: tooltip } );
this.closing = false;
},
_tooltip: function( element ) {
var id = "ui-tooltip-" + increments++,
tooltip = $( "
" )
.attr({
id: id,
role: "tooltip"
})
.addClass( "ui-tooltip ui-widget ui-corner-all ui-widget-content " +
( this.options.tooltipClass || "" ) );
$( "
" )
.addClass( "ui-tooltip-content" )
.appendTo( tooltip );
tooltip.appendTo( this.document[0].body );
if ( $.fn.bgiframe ) {
tooltip.bgiframe();
}
this.tooltips[ id ] = element;
return tooltip;
},
_find: function( target ) {
var id = target.data( "ui-tooltip-id" );
return id ? $( "#" + id ) : $();
},
_removeTooltip: function( tooltip ) {
tooltip.remove();
delete this.tooltips[ tooltip.attr( "id" ) ];
},
_destroy: function() {
var that = this;
// close open tooltips
$.each( this.tooltips, function( id, element ) {
// Delegate to close method to handle common cleanup
var event = $.Event( "blur" );
event.target = event.currentTarget = element[0];
that.close( event, true );
// Remove immediately; destroying an open tooltip doesn't use the
// hide animation
$( "#" + id ).remove();
// Restore the title
if ( element.data( "ui-tooltip-title" ) ) {
element.attr( "title", element.data( "ui-tooltip-title" ) );
element.removeData( "ui-tooltip-title" );
}
});
}
});
}( jQuery ) );