From aaaf1682857736e269a609411c8e75fe557d30ec Mon Sep 17 00:00:00 2001 From: dspeed2 Date: Wed, 12 Nov 2025 12:09:15 +0000 Subject: [PATCH 01/12] Merge tested changes from dv5-demo into dv5-main ready for release. (#858) * #LUC070-162 Fixed the bug where multiple reviews breaks the /vaults page 1) Updated ReviewsController so that /vaultreviews/depositreviews/ expects / uses a depositReviewId param rather than depositId 2) Updated DepositsReviewService so that getDepositReview now gets the depositReview by id rather than deposit_id 3) Updated VaultsController so that it passes the depositReviewId rather than deposit_id when getting the deposit review in getVault method 4) Updated RestService so that getDepostReview expected a depositReviewId rather than a depositId * #LUC070-162 Fixed the new bug where the fix for multiple reviews now breaks the /admin/vaults/vaultID/review page I think at some point we merged two lines of code into one, the fix for the previous issue changed the value of a param which then broke something else. I've put both params back and used them in the correct place. I suspect I'll have to fix / update some tests before this is complete but it all looks fine when deployed locally. I've also changed the order of the deposits in review output to be based on creation time. 1) Updated the order of the reviews list in VaultsController 2) Added both params (depositId and depositReviewId) to AdminReviewsController and updated the order of the reviews list in AdminReviewsController * #LUC070-162 Fixed tests that were failing after the fixes * #LUC070-180 Fix for the post 4.1.6 release review issue (#849) I noticed that the code was using the deposit id instead of DepositReviewId after changing that all the tests still pass. Things also look good when I did a test review on my local deploy. We'll need to test more on Demo. * Remove jacoco from build job as it appears to be failing after recent Jenkins upgrade. * Re add jacoco from build job as it didn't change anything (in fact I've realised it was working and providing a coverage report) * Remove jacoco from build job after uninstalling from Jenkins * More changes to try and debug the Jenkins demo build failure * More changes to try and debug the Jenkins demo build failure * Add the jacoco post run stuff back now we have discovered it was one of the docker plugins causing the issues. * DS-LUC070-145-20250318 Upgrade SB dependencies along with assorted other mvn dependencies (#848) * Spring Boot 3.3.2 and other library version upgrades updated maven wrapper too * #LUC070-145 Upgrade spring boot and other dependencies 1) Upgraded pom.xml 2) Upgraded various impacted tests * #LUC070-145 Upgrade spring boot and other dependencies 1) Upgraded pom.xml * #LUC070-145 Upgrade spring boot and other dependencies 1) Upgraded pom.xml * #LUC070-145 Upgrade spring boot and other dependencies 1) Upgraded pom.xml 2) Upgraded common/pom.xml Removed unused dep and upgraded tika * #LUC070-145 Upgrade spring boot and other dependencies 1) Upgraded pom.xml 2) Upgraded datavault-broker/pom.xml Removed unused dep and upgraded tika --------- Co-authored-by: David Hay * LUC070-209 - Added a local Accessibility page. (#852) Co-authored-by: John Pinto * Fix failing tests * Fix for Accessibility Statement footer links. They are now clickable. (#853) Co-authored-by: John Pinto * Luc070 209 Added local accessibility page (#854) * Fix for Accessibility Statement footer links. They are now clickable. * Fix for non-clickable links for footer on all pages except the "Edit Pending Vault" and "Create New Vault" pages. --------- Co-authored-by: John Pinto * LUC070-20 - Fix for making footer links clickable for Create Vault (#856) Pages. Co-authored-by: John Pinto --------- Co-authored-by: David Hay Co-authored-by: John Pinto Co-authored-by: John Pinto --- .../webapp/WEB-INF/templates/layout/editvaultlayout.html | 2 +- .../src/main/webapp/resources/theme/css/createVault.css | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/datavault-webapp/src/main/webapp/WEB-INF/templates/layout/editvaultlayout.html b/datavault-webapp/src/main/webapp/WEB-INF/templates/layout/editvaultlayout.html index 9d0823a3c..5b6797c45 100644 --- a/datavault-webapp/src/main/webapp/WEB-INF/templates/layout/editvaultlayout.html +++ b/datavault-webapp/src/main/webapp/WEB-INF/templates/layout/editvaultlayout.html @@ -14,7 +14,7 @@
NESTED CONTENT GOES HERE
- diff --git a/datavault-webapp/src/main/webapp/resources/theme/css/createVault.css b/datavault-webapp/src/main/webapp/resources/theme/css/createVault.css index 4cdf4c19c..e9f5e16f4 100644 --- a/datavault-webapp/src/main/webapp/resources/theme/css/createVault.css +++ b/datavault-webapp/src/main/webapp/resources/theme/css/createVault.css @@ -144,4 +144,9 @@ .extra-depositor { margin-top: 2px; +} + +#vault-creation-form .dropdown-menu, +#pendingvault-edit-form .dropdown-menu { + height: 30rem !important; } \ No newline at end of file From 7ff8c134a1049bd406c5a4b801005f9bdb64d8ff Mon Sep 17 00:00:00 2001 From: dspeed2 Date: Thu, 27 Nov 2025 08:32:59 +0000 Subject: [PATCH 02/12] Merge tested changes for DV5-4.11.0 (#860) * #LUC070-162 Fixed the bug where multiple reviews breaks the /vaults page 1) Updated ReviewsController so that /vaultreviews/depositreviews/ expects / uses a depositReviewId param rather than depositId 2) Updated DepositsReviewService so that getDepositReview now gets the depositReview by id rather than deposit_id 3) Updated VaultsController so that it passes the depositReviewId rather than deposit_id when getting the deposit review in getVault method 4) Updated RestService so that getDepostReview expected a depositReviewId rather than a depositId * #LUC070-162 Fixed the new bug where the fix for multiple reviews now breaks the /admin/vaults/vaultID/review page I think at some point we merged two lines of code into one, the fix for the previous issue changed the value of a param which then broke something else. I've put both params back and used them in the correct place. I suspect I'll have to fix / update some tests before this is complete but it all looks fine when deployed locally. I've also changed the order of the deposits in review output to be based on creation time. 1) Updated the order of the reviews list in VaultsController 2) Added both params (depositId and depositReviewId) to AdminReviewsController and updated the order of the reviews list in AdminReviewsController * #LUC070-162 Fixed tests that were failing after the fixes * #LUC070-180 Fix for the post 4.1.6 release review issue (#849) I noticed that the code was using the deposit id instead of DepositReviewId after changing that all the tests still pass. Things also look good when I did a test review on my local deploy. We'll need to test more on Demo. * Remove jacoco from build job as it appears to be failing after recent Jenkins upgrade. * Re add jacoco from build job as it didn't change anything (in fact I've realised it was working and providing a coverage report) * Remove jacoco from build job after uninstalling from Jenkins * More changes to try and debug the Jenkins demo build failure * More changes to try and debug the Jenkins demo build failure * Add the jacoco post run stuff back now we have discovered it was one of the docker plugins causing the issues. * DS-LUC070-145-20250318 Upgrade SB dependencies along with assorted other mvn dependencies (#848) * Spring Boot 3.3.2 and other library version upgrades updated maven wrapper too * #LUC070-145 Upgrade spring boot and other dependencies 1) Upgraded pom.xml 2) Upgraded various impacted tests * #LUC070-145 Upgrade spring boot and other dependencies 1) Upgraded pom.xml * #LUC070-145 Upgrade spring boot and other dependencies 1) Upgraded pom.xml * #LUC070-145 Upgrade spring boot and other dependencies 1) Upgraded pom.xml 2) Upgraded common/pom.xml Removed unused dep and upgraded tika * #LUC070-145 Upgrade spring boot and other dependencies 1) Upgraded pom.xml 2) Upgraded datavault-broker/pom.xml Removed unused dep and upgraded tika --------- Co-authored-by: David Hay * LUC070-209 - Added a local Accessibility page. (#852) Co-authored-by: John Pinto * Fix failing tests * Fix for Accessibility Statement footer links. They are now clickable. (#853) Co-authored-by: John Pinto * Luc070 209 Added local accessibility page (#854) * Fix for Accessibility Statement footer links. They are now clickable. * Fix for non-clickable links for footer on all pages except the "Edit Pending Vault" and "Create New Vault" pages. --------- Co-authored-by: John Pinto * LUC070-20 - Fix for making footer links clickable for Create Vault (#856) Pages. Co-authored-by: John Pinto * #LUC070-221 Fix the copy ssh key modal by making it open a tab instead of using an iframe (#857) Fix the copy ssh key modal by making it open a tab instead of using an iframe (#857) * #LUC070-228 Further changes re the accessibility page (#859) * #LUC070-228 Add lang="en" to the templates that don't have it. * #LUC070-228 Further changes re the accessibility statement --------- Co-authored-by: David Hay Co-authored-by: John Pinto Co-authored-by: John Pinto --- .../WEB-INF/templates/accessibility.html | 18 ++++++------ .../WEB-INF/templates/filestores/index.html | 28 ++----------------- .../WEB-INF/templates/layout/footer.html | 2 +- .../WEB-INF/templates/layout/loginlayout.html | 2 +- .../templates/layout/welcomelayout.html | 2 +- 5 files changed, 15 insertions(+), 37 deletions(-) diff --git a/datavault-webapp/src/main/webapp/WEB-INF/templates/accessibility.html b/datavault-webapp/src/main/webapp/WEB-INF/templates/accessibility.html index 6e6924b16..76a59a39f 100644 --- a/datavault-webapp/src/main/webapp/WEB-INF/templates/accessibility.html +++ b/datavault-webapp/src/main/webapp/WEB-INF/templates/accessibility.html @@ -5,7 +5,7 @@ Accessibility statement for the Datavault website - " ).appendTo( body ); + } + + // We need to make sure to grab the zIndex before setting the + // opacity, because setting the opacity to anything lower than 1 + // causes the zIndex to change from "auto" to 0. + if ( o.zIndex ) { // zIndex option + if ( this.helper.css( "zIndex" ) ) { + this._storedZIndex = this.helper.css( "zIndex" ); + } + this.helper.css( "zIndex", o.zIndex ); + } + + if ( o.opacity ) { // opacity option + if ( this.helper.css( "opacity" ) ) { + this._storedOpacity = this.helper.css( "opacity" ); + } + this.helper.css( "opacity", o.opacity ); + } + + //Prepare scrolling + if ( this.scrollParent[ 0 ] !== this.document[ 0 ] && + this.scrollParent[ 0 ].tagName !== "HTML" ) { + this.overflowOffset = this.scrollParent.offset(); + } + + //Call callbacks + this._trigger( "start", event, this._uiHash() ); + + //Recache the helper size + if ( !this._preserveHelperProportions ) { + this._cacheHelperProportions(); + } + + //Post "activate" events to possible containers + if ( !noActivation ) { + for ( i = this.containers.length - 1; i >= 0; i-- ) { + this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) ); + } + } + + //Prepare possible droppables + if ( $.ui.ddmanager ) { + $.ui.ddmanager.current = this; + } + + if ( $.ui.ddmanager && !o.dropBehaviour ) { + $.ui.ddmanager.prepareOffsets( this, event ); + } + + this.dragging = true; + + this._addClass( this.helper, "ui-sortable-helper" ); + + //Move the helper, if needed + if ( !this.helper.parent().is( this.appendTo ) ) { + this.helper.detach().appendTo( this.appendTo ); + + //Update position + this.offset.parent = this._getParentOffset(); + } + + //Generate the original position + this.position = this.originalPosition = this._generatePosition( event ); + this.originalPageX = event.pageX; + this.originalPageY = event.pageY; + this.lastPositionAbs = this.positionAbs = this._convertPositionTo( "absolute" ); + + this._mouseDrag( event ); + + return true; + + }, + + _scroll: function( event ) { + var o = this.options, + scrolled = false; + + if ( this.scrollParent[ 0 ] !== this.document[ 0 ] && + this.scrollParent[ 0 ].tagName !== "HTML" ) { + + if ( ( this.overflowOffset.top + this.scrollParent[ 0 ].offsetHeight ) - + event.pageY < o.scrollSensitivity ) { + this.scrollParent[ 0 ].scrollTop = + scrolled = this.scrollParent[ 0 ].scrollTop + o.scrollSpeed; + } else if ( event.pageY - this.overflowOffset.top < o.scrollSensitivity ) { + this.scrollParent[ 0 ].scrollTop = + scrolled = this.scrollParent[ 0 ].scrollTop - o.scrollSpeed; + } + + if ( ( this.overflowOffset.left + this.scrollParent[ 0 ].offsetWidth ) - + event.pageX < o.scrollSensitivity ) { + this.scrollParent[ 0 ].scrollLeft = scrolled = + this.scrollParent[ 0 ].scrollLeft + o.scrollSpeed; + } else if ( event.pageX - this.overflowOffset.left < o.scrollSensitivity ) { + this.scrollParent[ 0 ].scrollLeft = scrolled = + this.scrollParent[ 0 ].scrollLeft - o.scrollSpeed; + } + + } else { + + if ( event.pageY - this.document.scrollTop() < o.scrollSensitivity ) { + scrolled = this.document.scrollTop( this.document.scrollTop() - o.scrollSpeed ); + } else if ( this.window.height() - ( event.pageY - this.document.scrollTop() ) < + o.scrollSensitivity ) { + scrolled = this.document.scrollTop( this.document.scrollTop() + o.scrollSpeed ); + } + + if ( event.pageX - this.document.scrollLeft() < o.scrollSensitivity ) { + scrolled = this.document.scrollLeft( + this.document.scrollLeft() - o.scrollSpeed + ); + } else if ( this.window.width() - ( event.pageX - this.document.scrollLeft() ) < + o.scrollSensitivity ) { + scrolled = this.document.scrollLeft( + this.document.scrollLeft() + o.scrollSpeed + ); + } + + } + + return scrolled; + }, + + _mouseDrag: function( event ) { + var i, item, itemElement, intersection, + o = this.options; + + //Compute the helpers position + this.position = this._generatePosition( event ); + this.positionAbs = this._convertPositionTo( "absolute" ); + + //Set the helper position + if ( !this.options.axis || this.options.axis !== "y" ) { + this.helper[ 0 ].style.left = this.position.left + "px"; + } + if ( !this.options.axis || this.options.axis !== "x" ) { + this.helper[ 0 ].style.top = this.position.top + "px"; + } + + //Do scrolling + if ( o.scroll ) { + if ( this._scroll( event ) !== false ) { + + //Update item positions used in position checks + this._refreshItemPositions( true ); + + if ( $.ui.ddmanager && !o.dropBehaviour ) { + $.ui.ddmanager.prepareOffsets( this, event ); + } + } + } + + this.dragDirection = { + vertical: this._getDragVerticalDirection(), + horizontal: this._getDragHorizontalDirection() + }; + + //Rearrange + for ( i = this.items.length - 1; i >= 0; i-- ) { + + //Cache variables and intersection, continue if no intersection + item = this.items[ i ]; + itemElement = item.item[ 0 ]; + intersection = this._intersectsWithPointer( item ); + if ( !intersection ) { + continue; + } + + // Only put the placeholder inside the current Container, skip all + // items from other containers. This works because when moving + // an item from one container to another the + // currentContainer is switched before the placeholder is moved. + // + // Without this, moving items in "sub-sortables" can cause + // the placeholder to jitter between the outer and inner container. + if ( item.instance !== this.currentContainer ) { + continue; + } + + // Cannot intersect with itself + // no useless actions that have been done before + // no action if the item moved is the parent of the item checked + if ( itemElement !== this.currentItem[ 0 ] && + this.placeholder[ intersection === 1 ? + "next" : "prev" ]()[ 0 ] !== itemElement && + !$.contains( this.placeholder[ 0 ], itemElement ) && + ( this.options.type === "semi-dynamic" ? + !$.contains( this.element[ 0 ], itemElement ) : + true + ) + ) { + + this.direction = intersection === 1 ? "down" : "up"; + + if ( this.options.tolerance === "pointer" || + this._intersectsWithSides( item ) ) { + this._rearrange( event, item ); + } else { + break; + } + + this._trigger( "change", event, this._uiHash() ); + break; + } + } + + //Post events to containers + this._contactContainers( event ); + + //Interconnect with droppables + if ( $.ui.ddmanager ) { + $.ui.ddmanager.drag( this, event ); + } + + //Call callbacks + this._trigger( "sort", event, this._uiHash() ); + + this.lastPositionAbs = this.positionAbs; + return false; + + }, + + _mouseStop: function( event, noPropagation ) { + + if ( !event ) { + return; + } + + //If we are using droppables, inform the manager about the drop + if ( $.ui.ddmanager && !this.options.dropBehaviour ) { + $.ui.ddmanager.drop( this, event ); + } + + if ( this.options.revert ) { + var that = this, + cur = this.placeholder.offset(), + axis = this.options.axis, + animation = {}; + + if ( !axis || axis === "x" ) { + animation.left = cur.left - this.offset.parent.left - this.margins.left + + ( this.offsetParent[ 0 ] === this.document[ 0 ].body ? + 0 : + this.offsetParent[ 0 ].scrollLeft + ); + } + if ( !axis || axis === "y" ) { + animation.top = cur.top - this.offset.parent.top - this.margins.top + + ( this.offsetParent[ 0 ] === this.document[ 0 ].body ? + 0 : + this.offsetParent[ 0 ].scrollTop + ); + } + this.reverting = true; + $( this.helper ).animate( + animation, + parseInt( this.options.revert, 10 ) || 500, + function() { + that._clear( event ); + } + ); + } else { + this._clear( event, noPropagation ); + } + + return false; + + }, + + cancel: function() { + + if ( this.dragging ) { + + this._mouseUp( new $.Event( "mouseup", { target: null } ) ); + + if ( this.options.helper === "original" ) { + this.currentItem.css( this._storedCSS ); + this._removeClass( this.currentItem, "ui-sortable-helper" ); + } else { + this.currentItem.show(); + } + + //Post deactivating events to containers + for ( var i = this.containers.length - 1; i >= 0; i-- ) { + this.containers[ i ]._trigger( "deactivate", null, this._uiHash( this ) ); + if ( this.containers[ i ].containerCache.over ) { + this.containers[ i ]._trigger( "out", null, this._uiHash( this ) ); + this.containers[ i ].containerCache.over = 0; + } + } + + } + + if ( this.placeholder ) { + + //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, + // it unbinds ALL events from the original node! + if ( this.placeholder[ 0 ].parentNode ) { + this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] ); + } + if ( this.options.helper !== "original" && this.helper && + this.helper[ 0 ].parentNode ) { + this.helper.remove(); + } + + $.extend( this, { + helper: null, + dragging: false, + reverting: false, + _noFinalSort: null + } ); + + if ( this.domPosition.prev ) { + $( this.domPosition.prev ).after( this.currentItem ); + } else { + $( this.domPosition.parent ).prepend( this.currentItem ); + } + } + + return this; + + }, + + serialize: function( o ) { + + var items = this._getItemsAsjQuery( o && o.connected ), + str = []; + o = o || {}; + + $( items ).each( function() { + var res = ( $( o.item || this ).attr( o.attribute || "id" ) || "" ) + .match( o.expression || ( /(.+)[\-=_](.+)/ ) ); + if ( res ) { + str.push( + ( o.key || res[ 1 ] + "[]" ) + + "=" + ( o.key && o.expression ? res[ 1 ] : res[ 2 ] ) ); + } + } ); + + if ( !str.length && o.key ) { + str.push( o.key + "=" ); + } + + return str.join( "&" ); + + }, + + toArray: function( o ) { + + var items = this._getItemsAsjQuery( o && o.connected ), + ret = []; + + o = o || {}; + + items.each( function() { + ret.push( $( o.item || this ).attr( o.attribute || "id" ) || "" ); + } ); + return ret; + + }, + + /* Be careful with the following core functions */ + _intersectsWith: function( item ) { + + var x1 = this.positionAbs.left, + x2 = x1 + this.helperProportions.width, + y1 = this.positionAbs.top, + y2 = y1 + this.helperProportions.height, + l = item.left, + r = l + item.width, + t = item.top, + b = t + item.height, + dyClick = this.offset.click.top, + dxClick = this.offset.click.left, + isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t && + ( y1 + dyClick ) < b ), + isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l && + ( x1 + dxClick ) < r ), + isOverElement = isOverElementHeight && isOverElementWidth; + + if ( this.options.tolerance === "pointer" || + this.options.forcePointerForContainers || + ( this.options.tolerance !== "pointer" && + this.helperProportions[ this.floating ? "width" : "height" ] > + item[ this.floating ? "width" : "height" ] ) + ) { + return isOverElement; + } else { + + return ( l < x1 + ( this.helperProportions.width / 2 ) && // Right Half + x2 - ( this.helperProportions.width / 2 ) < r && // Left Half + t < y1 + ( this.helperProportions.height / 2 ) && // Bottom Half + y2 - ( this.helperProportions.height / 2 ) < b ); // Top Half + + } + }, + + _intersectsWithPointer: function( item ) { + var verticalDirection, horizontalDirection, + isOverElementHeight = ( this.options.axis === "x" ) || + this._isOverAxis( + this.positionAbs.top + this.offset.click.top, item.top, item.height ), + isOverElementWidth = ( this.options.axis === "y" ) || + this._isOverAxis( + this.positionAbs.left + this.offset.click.left, item.left, item.width ), + isOverElement = isOverElementHeight && isOverElementWidth; + + if ( !isOverElement ) { + return false; + } + + verticalDirection = this.dragDirection.vertical; + horizontalDirection = this.dragDirection.horizontal; + + return this.floating ? + ( ( horizontalDirection === "right" || verticalDirection === "down" ) ? 2 : 1 ) : + ( verticalDirection && ( verticalDirection === "down" ? 2 : 1 ) ); + + }, + + _intersectsWithSides: function( item ) { + + var isOverBottomHalf = this._isOverAxis( this.positionAbs.top + + this.offset.click.top, item.top + ( item.height / 2 ), item.height ), + isOverRightHalf = this._isOverAxis( this.positionAbs.left + + this.offset.click.left, item.left + ( item.width / 2 ), item.width ), + verticalDirection = this.dragDirection.vertical, + horizontalDirection = this.dragDirection.horizontal; + + if ( this.floating && horizontalDirection ) { + return ( ( horizontalDirection === "right" && isOverRightHalf ) || + ( horizontalDirection === "left" && !isOverRightHalf ) ); + } else { + return verticalDirection && ( ( verticalDirection === "down" && isOverBottomHalf ) || + ( verticalDirection === "up" && !isOverBottomHalf ) ); + } + + }, + + _getDragVerticalDirection: function() { + var delta = this.positionAbs.top - this.lastPositionAbs.top; + return delta !== 0 && ( delta > 0 ? "down" : "up" ); + }, + + _getDragHorizontalDirection: function() { + var delta = this.positionAbs.left - this.lastPositionAbs.left; + return delta !== 0 && ( delta > 0 ? "right" : "left" ); + }, + + refresh: function( event ) { + this._refreshItems( event ); + this._setHandleClassName(); + this.refreshPositions(); + return this; + }, + + _connectWith: function() { + var options = this.options; + return options.connectWith.constructor === String ? + [ options.connectWith ] : + options.connectWith; + }, + + _getItemsAsjQuery: function( connected ) { + + var i, j, cur, inst, + items = [], + queries = [], + connectWith = this._connectWith(); + + if ( connectWith && connected ) { + for ( i = connectWith.length - 1; i >= 0; i-- ) { + cur = $( connectWith[ i ], this.document[ 0 ] ); + for ( j = cur.length - 1; j >= 0; j-- ) { + inst = $.data( cur[ j ], this.widgetFullName ); + if ( inst && inst !== this && !inst.options.disabled ) { + queries.push( [ typeof inst.options.items === "function" ? + inst.options.items.call( inst.element ) : + $( inst.options.items, inst.element ) + .not( ".ui-sortable-helper" ) + .not( ".ui-sortable-placeholder" ), inst ] ); + } + } + } + } + + queries.push( [ typeof this.options.items === "function" ? + this.options.items + .call( this.element, null, { options: this.options, item: this.currentItem } ) : + $( this.options.items, this.element ) + .not( ".ui-sortable-helper" ) + .not( ".ui-sortable-placeholder" ), this ] ); + + function addItems() { + items.push( this ); + } + for ( i = queries.length - 1; i >= 0; i-- ) { + queries[ i ][ 0 ].each( addItems ); + } + + return $( items ); + + }, + + _removeCurrentsFromItems: function() { + + var list = this.currentItem.find( ":data(" + this.widgetName + "-item)" ); + + this.items = $.grep( this.items, function( item ) { + for ( var j = 0; j < list.length; j++ ) { + if ( list[ j ] === item.item[ 0 ] ) { + return false; + } + } + return true; + } ); + + }, + + _refreshItems: function( event ) { + + this.items = []; + this.containers = [ this ]; + + var i, j, cur, inst, targetData, _queries, item, queriesLength, + items = this.items, + queries = [ [ typeof this.options.items === "function" ? + this.options.items.call( this.element[ 0 ], event, { item: this.currentItem } ) : + $( this.options.items, this.element ), this ] ], + connectWith = this._connectWith(); + + //Shouldn't be run the first time through due to massive slow-down + if ( connectWith && this.ready ) { + for ( i = connectWith.length - 1; i >= 0; i-- ) { + cur = $( connectWith[ i ], this.document[ 0 ] ); + for ( j = cur.length - 1; j >= 0; j-- ) { + inst = $.data( cur[ j ], this.widgetFullName ); + if ( inst && inst !== this && !inst.options.disabled ) { + queries.push( [ typeof inst.options.items === "function" ? + inst.options.items + .call( inst.element[ 0 ], event, { item: this.currentItem } ) : + $( inst.options.items, inst.element ), inst ] ); + this.containers.push( inst ); + } + } + } + } + + for ( i = queries.length - 1; i >= 0; i-- ) { + targetData = queries[ i ][ 1 ]; + _queries = queries[ i ][ 0 ]; + + for ( j = 0, queriesLength = _queries.length; j < queriesLength; j++ ) { + item = $( _queries[ j ] ); + + // Data for target checking (mouse manager) + item.data( this.widgetName + "-item", targetData ); + + items.push( { + item: item, + instance: targetData, + width: 0, height: 0, + left: 0, top: 0 + } ); + } + } + + }, + + _refreshItemPositions: function( fast ) { + var i, item, t, p; + + for ( i = this.items.length - 1; i >= 0; i-- ) { + item = this.items[ i ]; + + //We ignore calculating positions of all connected containers when we're not over them + if ( this.currentContainer && item.instance !== this.currentContainer && + item.item[ 0 ] !== this.currentItem[ 0 ] ) { + continue; + } + + t = this.options.toleranceElement ? + $( this.options.toleranceElement, item.item ) : + item.item; + + if ( !fast ) { + item.width = t.outerWidth(); + item.height = t.outerHeight(); + } + + p = t.offset(); + item.left = p.left; + item.top = p.top; + } + }, + + refreshPositions: function( fast ) { + + // Determine whether items are being displayed horizontally + this.floating = this.items.length ? + this.options.axis === "x" || this._isFloating( this.items[ 0 ].item ) : + false; + + // This has to be redone because due to the item being moved out/into the offsetParent, + // the offsetParent's position will change + if ( this.offsetParent && this.helper ) { + this.offset.parent = this._getParentOffset(); + } + + this._refreshItemPositions( fast ); + + var i, p; + + if ( this.options.custom && this.options.custom.refreshContainers ) { + this.options.custom.refreshContainers.call( this ); + } else { + for ( i = this.containers.length - 1; i >= 0; i-- ) { + p = this.containers[ i ].element.offset(); + this.containers[ i ].containerCache.left = p.left; + this.containers[ i ].containerCache.top = p.top; + this.containers[ i ].containerCache.width = + this.containers[ i ].element.outerWidth(); + this.containers[ i ].containerCache.height = + this.containers[ i ].element.outerHeight(); + } + } + + return this; + }, + + _createPlaceholder: function( that ) { + that = that || this; + var className, nodeName, + o = that.options; + + if ( !o.placeholder || o.placeholder.constructor === String ) { + className = o.placeholder; + nodeName = that.currentItem[ 0 ].nodeName.toLowerCase(); + o.placeholder = { + element: function() { + + var element = $( "<" + nodeName + ">", that.document[ 0 ] ); + + that._addClass( element, "ui-sortable-placeholder", + className || that.currentItem[ 0 ].className ) + ._removeClass( element, "ui-sortable-helper" ); + + if ( nodeName === "tbody" ) { + that._createTrPlaceholder( + that.currentItem.find( "tr" ).eq( 0 ), + $( "", that.document[ 0 ] ).appendTo( element ) + ); + } else if ( nodeName === "tr" ) { + that._createTrPlaceholder( that.currentItem, element ); + } else if ( nodeName === "img" ) { + element.attr( "src", that.currentItem.attr( "src" ) ); + } + + if ( !className ) { + element.css( "visibility", "hidden" ); + } + + return element; + }, + update: function( container, p ) { + + // 1. If a className is set as 'placeholder option, we don't force sizes - + // the class is responsible for that + // 2. The option 'forcePlaceholderSize can be enabled to force it even if a + // class name is specified + if ( className && !o.forcePlaceholderSize ) { + return; + } + + // If the element doesn't have a actual height or width by itself (without + // styles coming from a stylesheet), it receives the inline height and width + // from the dragged item. Or, if it's a tbody or tr, it's going to have a height + // anyway since we're populating them with s above, but they're unlikely to + // be the correct height on their own if the row heights are dynamic, so we'll + // always assign the height of the dragged item given forcePlaceholderSize + // is true. + if ( !p.height() || ( o.forcePlaceholderSize && + ( nodeName === "tbody" || nodeName === "tr" ) ) ) { + p.height( + that.currentItem.innerHeight() - + parseInt( that.currentItem.css( "paddingTop" ) || 0, 10 ) - + parseInt( that.currentItem.css( "paddingBottom" ) || 0, 10 ) ); + } + if ( !p.width() ) { + p.width( + that.currentItem.innerWidth() - + parseInt( that.currentItem.css( "paddingLeft" ) || 0, 10 ) - + parseInt( that.currentItem.css( "paddingRight" ) || 0, 10 ) ); + } + } + }; + } + + //Create the placeholder + that.placeholder = $( o.placeholder.element.call( that.element, that.currentItem ) ); + + //Append it after the actual current item + that.currentItem.after( that.placeholder ); + + //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317) + o.placeholder.update( that, that.placeholder ); + + }, + + _createTrPlaceholder: function( sourceTr, targetTr ) { + var that = this; + + sourceTr.children().each( function() { + $( " ", that.document[ 0 ] ) + .attr( "colspan", $( this ).attr( "colspan" ) || 1 ) + .appendTo( targetTr ); + } ); + }, + + _contactContainers: function( event ) { + var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, cur, nearBottom, + floating, axis, + innermostContainer = null, + innermostIndex = null; + + // Get innermost container that intersects with item + for ( i = this.containers.length - 1; i >= 0; i-- ) { + + // Never consider a container that's located within the item itself + if ( $.contains( this.currentItem[ 0 ], this.containers[ i ].element[ 0 ] ) ) { + continue; + } + + if ( this._intersectsWith( this.containers[ i ].containerCache ) ) { + + // If we've already found a container and it's more "inner" than this, then continue + if ( innermostContainer && + $.contains( + this.containers[ i ].element[ 0 ], + innermostContainer.element[ 0 ] ) ) { + continue; + } + + innermostContainer = this.containers[ i ]; + innermostIndex = i; + + } else { + + // container doesn't intersect. trigger "out" event if necessary + if ( this.containers[ i ].containerCache.over ) { + this.containers[ i ]._trigger( "out", event, this._uiHash( this ) ); + this.containers[ i ].containerCache.over = 0; + } + } + + } + + // If no intersecting containers found, return + if ( !innermostContainer ) { + return; + } + + // Move the item into the container if it's not there already + if ( this.containers.length === 1 ) { + if ( !this.containers[ innermostIndex ].containerCache.over ) { + this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) ); + this.containers[ innermostIndex ].containerCache.over = 1; + } + } else { + + // When entering a new container, we will find the item with the least distance and + // append our item near it + dist = 10000; + itemWithLeastDistance = null; + floating = innermostContainer.floating || this._isFloating( this.currentItem ); + posProperty = floating ? "left" : "top"; + sizeProperty = floating ? "width" : "height"; + axis = floating ? "pageX" : "pageY"; + + for ( j = this.items.length - 1; j >= 0; j-- ) { + if ( !$.contains( + this.containers[ innermostIndex ].element[ 0 ], this.items[ j ].item[ 0 ] ) + ) { + continue; + } + if ( this.items[ j ].item[ 0 ] === this.currentItem[ 0 ] ) { + continue; + } + + cur = this.items[ j ].item.offset()[ posProperty ]; + nearBottom = false; + if ( event[ axis ] - cur > this.items[ j ][ sizeProperty ] / 2 ) { + nearBottom = true; + } + + if ( Math.abs( event[ axis ] - cur ) < dist ) { + dist = Math.abs( event[ axis ] - cur ); + itemWithLeastDistance = this.items[ j ]; + this.direction = nearBottom ? "up" : "down"; + } + } + + //Check if dropOnEmpty is enabled + if ( !itemWithLeastDistance && !this.options.dropOnEmpty ) { + return; + } + + if ( this.currentContainer === this.containers[ innermostIndex ] ) { + if ( !this.currentContainer.containerCache.over ) { + this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash() ); + this.currentContainer.containerCache.over = 1; + } + return; + } + + if ( itemWithLeastDistance ) { + this._rearrange( event, itemWithLeastDistance, null, true ); + } else { + this._rearrange( event, null, this.containers[ innermostIndex ].element, true ); + } + this._trigger( "change", event, this._uiHash() ); + this.containers[ innermostIndex ]._trigger( "change", event, this._uiHash( this ) ); + this.currentContainer = this.containers[ innermostIndex ]; + + //Update the placeholder + this.options.placeholder.update( this.currentContainer, this.placeholder ); + + //Update scrollParent + this.scrollParent = this.placeholder.scrollParent(); + + //Update overflowOffset + if ( this.scrollParent[ 0 ] !== this.document[ 0 ] && + this.scrollParent[ 0 ].tagName !== "HTML" ) { + this.overflowOffset = this.scrollParent.offset(); + } + + this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) ); + this.containers[ innermostIndex ].containerCache.over = 1; + } + + }, + + _createHelper: function( event ) { + + var o = this.options, + helper = typeof o.helper === "function" ? + $( o.helper.apply( this.element[ 0 ], [ event, this.currentItem ] ) ) : + ( o.helper === "clone" ? this.currentItem.clone() : this.currentItem ); + + //Add the helper to the DOM if that didn't happen already + if ( !helper.parents( "body" ).length ) { + this.appendTo[ 0 ].appendChild( helper[ 0 ] ); + } + + if ( helper[ 0 ] === this.currentItem[ 0 ] ) { + this._storedCSS = { + width: this.currentItem[ 0 ].style.width, + height: this.currentItem[ 0 ].style.height, + position: this.currentItem.css( "position" ), + top: this.currentItem.css( "top" ), + left: this.currentItem.css( "left" ) + }; + } + + if ( !helper[ 0 ].style.width || o.forceHelperSize ) { + helper.width( this.currentItem.width() ); + } + if ( !helper[ 0 ].style.height || o.forceHelperSize ) { + helper.height( this.currentItem.height() ); + } + + return helper; + + }, + + _adjustOffsetFromHelper: function( obj ) { + if ( typeof obj === "string" ) { + obj = obj.split( " " ); + } + if ( Array.isArray( obj ) ) { + obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 }; + } + if ( "left" in obj ) { + this.offset.click.left = obj.left + this.margins.left; + } + if ( "right" in obj ) { + this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; + } + if ( "top" in obj ) { + this.offset.click.top = obj.top + this.margins.top; + } + if ( "bottom" in obj ) { + this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; + } + }, + + _getParentOffset: function() { + + //Get the offsetParent and cache its position + this.offsetParent = this.helper.offsetParent(); + var po = this.offsetParent.offset(); + + // This is a special case where we need to modify a offset calculated on start, since the + // following happened: + // 1. The position of the helper is absolute, so it's position is calculated based on the + // next positioned parent + // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't + // the document, which means that the scroll is included in the initial calculation of the + // offset of the parent, and never recalculated upon drag + if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== this.document[ 0 ] && + $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) { + po.left += this.scrollParent.scrollLeft(); + po.top += this.scrollParent.scrollTop(); + } + + // This needs to be actually done for all browsers, since pageX/pageY includes + // this information. + if ( this.offsetParent[ 0 ] === this.document[ 0 ].body ) { + po = { top: 0, left: 0 }; + } + + return { + top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ), + left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 ) + }; + + }, + + _getRelativeOffset: function() { + + if ( this.cssPosition === "relative" ) { + var p = this.currentItem.position(); + return { + top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) + + this.scrollParent.scrollTop(), + left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) + + this.scrollParent.scrollLeft() + }; + } else { + return { top: 0, left: 0 }; + } + + }, + + _cacheMargins: function() { + this.margins = { + left: ( parseInt( this.currentItem.css( "marginLeft" ), 10 ) || 0 ), + top: ( parseInt( this.currentItem.css( "marginTop" ), 10 ) || 0 ) + }; + }, + + _cacheHelperProportions: function() { + this.helperProportions = { + width: this.helper.outerWidth(), + height: this.helper.outerHeight() + }; + }, + + _setContainment: function() { + + var ce, co, over, + o = this.options; + if ( o.containment === "parent" ) { + o.containment = this.helper[ 0 ].parentNode; + } + if ( o.containment === "document" || o.containment === "window" ) { + this.containment = [ + 0 - this.offset.relative.left - this.offset.parent.left, + 0 - this.offset.relative.top - this.offset.parent.top, + o.containment === "document" ? + this.document.width() : + this.window.width() - this.helperProportions.width - this.margins.left, + ( o.containment === "document" ? + ( this.document.height() || document.body.parentNode.scrollHeight ) : + this.window.height() || this.document[ 0 ].body.parentNode.scrollHeight + ) - this.helperProportions.height - this.margins.top + ]; + } + + if ( !( /^(document|window|parent)$/ ).test( o.containment ) ) { + ce = $( o.containment )[ 0 ]; + co = $( o.containment ).offset(); + over = ( $( ce ).css( "overflow" ) !== "hidden" ); + + this.containment = [ + co.left + ( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) + + ( parseInt( $( ce ).css( "paddingLeft" ), 10 ) || 0 ) - this.margins.left, + co.top + ( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) + + ( parseInt( $( ce ).css( "paddingTop" ), 10 ) || 0 ) - this.margins.top, + co.left + ( over ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) - + ( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) - + ( parseInt( $( ce ).css( "paddingRight" ), 10 ) || 0 ) - + this.helperProportions.width - this.margins.left, + co.top + ( over ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) - + ( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) - + ( parseInt( $( ce ).css( "paddingBottom" ), 10 ) || 0 ) - + this.helperProportions.height - this.margins.top + ]; + } + + }, + + _convertPositionTo: function( d, pos ) { + + if ( !pos ) { + pos = this.position; + } + var mod = d === "absolute" ? 1 : -1, + scroll = this.cssPosition === "absolute" && + !( this.scrollParent[ 0 ] !== this.document[ 0 ] && + $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ? + this.offsetParent : + this.scrollParent, + scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName ); + + return { + top: ( + + // The absolute mouse position + pos.top + + + // Only for relative positioned nodes: Relative offset from element to offset parent + this.offset.relative.top * mod + + + // The offsetParent's offset without borders (offset + border) + this.offset.parent.top * mod - + ( ( this.cssPosition === "fixed" ? + -this.scrollParent.scrollTop() : + ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod ) + ), + left: ( + + // The absolute mouse position + pos.left + + + // Only for relative positioned nodes: Relative offset from element to offset parent + this.offset.relative.left * mod + + + // The offsetParent's offset without borders (offset + border) + this.offset.parent.left * mod - + ( ( this.cssPosition === "fixed" ? + -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : + scroll.scrollLeft() ) * mod ) + ) + }; + + }, + + _generatePosition: function( event ) { + + var top, left, + o = this.options, + pageX = event.pageX, + pageY = event.pageY, + scroll = this.cssPosition === "absolute" && + !( this.scrollParent[ 0 ] !== this.document[ 0 ] && + $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ? + this.offsetParent : + this.scrollParent, + scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName ); + + // This is another very weird special case that only happens for relative elements: + // 1. If the css position is relative + // 2. and the scroll parent is the document or similar to the offset parent + // we have to refresh the relative offset during the scroll so there are no jumps + if ( this.cssPosition === "relative" && !( this.scrollParent[ 0 ] !== this.document[ 0 ] && + this.scrollParent[ 0 ] !== this.offsetParent[ 0 ] ) ) { + this.offset.relative = this._getRelativeOffset(); + } + + /* + * - Position constraining - + * Constrain the position to a mix of grid, containment. + */ + + if ( this.originalPosition ) { //If we are not dragging yet, we won't check for options + + if ( this.containment ) { + if ( event.pageX - this.offset.click.left < this.containment[ 0 ] ) { + pageX = this.containment[ 0 ] + this.offset.click.left; + } + if ( event.pageY - this.offset.click.top < this.containment[ 1 ] ) { + pageY = this.containment[ 1 ] + this.offset.click.top; + } + if ( event.pageX - this.offset.click.left > this.containment[ 2 ] ) { + pageX = this.containment[ 2 ] + this.offset.click.left; + } + if ( event.pageY - this.offset.click.top > this.containment[ 3 ] ) { + pageY = this.containment[ 3 ] + this.offset.click.top; + } + } + + if ( o.grid ) { + top = this.originalPageY + Math.round( ( pageY - this.originalPageY ) / + o.grid[ 1 ] ) * o.grid[ 1 ]; + pageY = this.containment ? + ( ( top - this.offset.click.top >= this.containment[ 1 ] && + top - this.offset.click.top <= this.containment[ 3 ] ) ? + top : + ( ( top - this.offset.click.top >= this.containment[ 1 ] ) ? + top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) : + top; + + left = this.originalPageX + Math.round( ( pageX - this.originalPageX ) / + o.grid[ 0 ] ) * o.grid[ 0 ]; + pageX = this.containment ? + ( ( left - this.offset.click.left >= this.containment[ 0 ] && + left - this.offset.click.left <= this.containment[ 2 ] ) ? + left : + ( ( left - this.offset.click.left >= this.containment[ 0 ] ) ? + left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) : + left; + } + + } + + return { + top: ( + + // The absolute mouse position + pageY - + + // Click offset (relative to the element) + this.offset.click.top - + + // Only for relative positioned nodes: Relative offset from element to offset parent + this.offset.relative.top - + + // The offsetParent's offset without borders (offset + border) + this.offset.parent.top + + ( ( this.cssPosition === "fixed" ? + -this.scrollParent.scrollTop() : + ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) ) + ), + left: ( + + // The absolute mouse position + pageX - + + // Click offset (relative to the element) + this.offset.click.left - + + // Only for relative positioned nodes: Relative offset from element to offset parent + this.offset.relative.left - + + // The offsetParent's offset without borders (offset + border) + this.offset.parent.left + + ( ( this.cssPosition === "fixed" ? + -this.scrollParent.scrollLeft() : + scrollIsRootNode ? 0 : scroll.scrollLeft() ) ) + ) + }; + + }, + + _rearrange: function( event, i, a, hardRefresh ) { + + if ( a ) { + a[ 0 ].appendChild( this.placeholder[ 0 ] ); + } else { + i.item[ 0 ].parentNode.insertBefore( this.placeholder[ 0 ], + ( this.direction === "down" ? i.item[ 0 ] : i.item[ 0 ].nextSibling ) ); + } + + //Various things done here to improve the performance: + // 1. we create a setTimeout, that calls refreshPositions + // 2. on the instance, we have a counter variable, that get's higher after every append + // 3. on the local scope, we copy the counter variable, and check in the timeout, + // if it's still the same + // 4. this lets only the last addition to the timeout stack through + this.counter = this.counter ? ++this.counter : 1; + var counter = this.counter; + + this._delay( function() { + if ( counter === this.counter ) { + + //Precompute after each DOM insertion, NOT on mousemove + this.refreshPositions( !hardRefresh ); + } + } ); + + }, + + _clear: function( event, noPropagation ) { + + this.reverting = false; + + // We delay all events that have to be triggered to after the point where the placeholder + // has been removed and everything else normalized again + var i, + delayedTriggers = []; + + // We first have to update the dom position of the actual currentItem + // Note: don't do it if the current item is already removed (by a user), or it gets + // reappended (see #4088) + if ( !this._noFinalSort && this.currentItem.parent().length ) { + this.placeholder.before( this.currentItem ); + } + this._noFinalSort = null; + + if ( this.helper[ 0 ] === this.currentItem[ 0 ] ) { + for ( i in this._storedCSS ) { + if ( this._storedCSS[ i ] === "auto" || this._storedCSS[ i ] === "static" ) { + this._storedCSS[ i ] = ""; + } + } + this.currentItem.css( this._storedCSS ); + this._removeClass( this.currentItem, "ui-sortable-helper" ); + } else { + this.currentItem.show(); + } + + if ( this.fromOutside && !noPropagation ) { + delayedTriggers.push( function( event ) { + this._trigger( "receive", event, this._uiHash( this.fromOutside ) ); + } ); + } + if ( ( this.fromOutside || + this.domPosition.prev !== + this.currentItem.prev().not( ".ui-sortable-helper" )[ 0 ] || + this.domPosition.parent !== this.currentItem.parent()[ 0 ] ) && !noPropagation ) { + + // Trigger update callback if the DOM position has changed + delayedTriggers.push( function( event ) { + this._trigger( "update", event, this._uiHash() ); + } ); + } + + // Check if the items Container has Changed and trigger appropriate + // events. + if ( this !== this.currentContainer ) { + if ( !noPropagation ) { + delayedTriggers.push( function( event ) { + this._trigger( "remove", event, this._uiHash() ); + } ); + delayedTriggers.push( ( function( c ) { + return function( event ) { + c._trigger( "receive", event, this._uiHash( this ) ); + }; + } ).call( this, this.currentContainer ) ); + delayedTriggers.push( ( function( c ) { + return function( event ) { + c._trigger( "update", event, this._uiHash( this ) ); + }; + } ).call( this, this.currentContainer ) ); + } + } + + //Post events to containers + function delayEvent( type, instance, container ) { + return function( event ) { + container._trigger( type, event, instance._uiHash( instance ) ); + }; + } + for ( i = this.containers.length - 1; i >= 0; i-- ) { + if ( !noPropagation ) { + delayedTriggers.push( delayEvent( "deactivate", this, this.containers[ i ] ) ); + } + if ( this.containers[ i ].containerCache.over ) { + delayedTriggers.push( delayEvent( "out", this, this.containers[ i ] ) ); + this.containers[ i ].containerCache.over = 0; + } + } + + //Do what was originally in plugins + if ( this._storedStylesheet ) { + this._storedStylesheet.remove(); + this._storedStylesheet = null; + } + if ( this._storedOpacity ) { + this.helper.css( "opacity", this._storedOpacity ); + } + if ( this._storedZIndex ) { + this.helper.css( "zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex ); + } + + this.dragging = false; + + if ( !noPropagation ) { + this._trigger( "beforeStop", event, this._uiHash() ); + } + + //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, + // it unbinds ALL events from the original node! + this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] ); + + if ( !this.cancelHelperRemoval ) { + if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) { + this.helper.remove(); + } + this.helper = null; + } + + if ( !noPropagation ) { + for ( i = 0; i < delayedTriggers.length; i++ ) { + + // Trigger all delayed events + delayedTriggers[ i ].call( this, event ); + } + this._trigger( "stop", event, this._uiHash() ); + } + + this.fromOutside = false; + return !this.cancelHelperRemoval; + + }, + + _trigger: function() { + if ( $.Widget.prototype._trigger.apply( this, arguments ) === false ) { + this.cancel(); + } + }, + + _uiHash: function( _inst ) { + var inst = _inst || this; + return { + helper: inst.helper, + placeholder: inst.placeholder || $( [] ), + position: inst.position, + originalPosition: inst.originalPosition, + offset: inst.positionAbs, + item: inst.currentItem, + sender: _inst ? _inst.element : null + }; + } + +} ); + + +/*! + * jQuery UI Spinner 1.14.1 + * https://jqueryui.com + * + * Copyright OpenJS Foundation and other contributors + * Released under the MIT license. + * https://jquery.org/license + */ + +//>>label: Spinner +//>>group: Widgets +//>>description: Displays buttons to easily input numbers via the keyboard or mouse. +//>>docs: https://api.jqueryui.com/spinner/ +//>>demos: https://jqueryui.com/spinner/ +//>>css.structure: ../../themes/base/core.css +//>>css.structure: ../../themes/base/spinner.css +//>>css.theme: ../../themes/base/theme.css + + +function spinnerModifier( 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.14.1", + defaultElement: "", + widgetEventPrefix: "spin", + options: { + classes: { + "ui-spinner": "ui-corner-all", + "ui-spinner-down": "ui-corner-br", + "ui-spinner-up": "ui-corner-tr" + }, + 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 ); + + // Only format if there is a value, prevents the field from being marked + // as invalid in Firefox, see #9573. + if ( this.value() !== "" ) { + + // 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 = this._super(); + var element = this.element; + + $.each( [ "min", "max", "step" ], function( i, option ) { + var value = element.attr( option ); + if ( value != null && 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 ) { + this._stop(); + this._refresh(); + if ( this.previous !== this.element.val() ) { + this._trigger( "change", event ); + } + }, + mousewheel: function( event, delta ) { + var activeElement = this.document[ 0 ].activeElement; + var isActive = this.element[ 0 ] === activeElement; + + if ( !isActive || !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.trigger( "focus" ); + this.previous = previous; + } + } + + // Ensure focus is on (or stays on) the text field + event.preventDefault(); + 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" + }, + + // Support mobile enhanced option and make backcompat more sane + _enhance: function() { + this.uiSpinner = this.element + .attr( "autocomplete", "off" ) + .wrap( "" ) + .parent() + + // Add buttons + .append( + "" + ); + }, + + _draw: function() { + this._enhance(); + + this._addClass( this.uiSpinner, "ui-spinner", "ui-widget ui-widget-content" ); + this._addClass( "ui-spinner-input" ); + + this.element.attr( "role", "spinbutton" ); + + // Button bindings + this.buttons = this.uiSpinner.children( "a" ) + .attr( "tabIndex", -1 ) + .attr( "aria-hidden", true ) + .button( { + classes: { + "ui-button": "" + } + } ); + + // TODO: Right now button does not support classes this is already updated in button PR + this._removeClass( this.buttons, "ui-corner-all" ); + + this._addClass( this.buttons.first(), "ui-spinner-button ui-spinner-up" ); + this._addClass( this.buttons.last(), "ui-spinner-button ui-spinner-down" ); + this.buttons.first().button( { + "icon": this.options.icons.up, + "showLabel": false + } ); + this.buttons.last().button( { + "icon": this.options.icons.down, + "showLabel": false + } ); + + // IE 6 doesn't understand height: 50% for the buttons + // unless the wrapper has an explicit height + if ( this.buttons.height() > Math.ceil( this.uiSpinner.height() * 0.5 ) && + this.uiSpinner.height() > 0 ) { + this.uiSpinner.height( this.uiSpinner.height() ); + } + }, + + _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; + }, + + _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 typeof incremental === "function" ? + 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 ) { + var prevValue, first, last; + + if ( key === "culture" || key === "numberFormat" ) { + 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 ); + } + } + if ( key === "icons" ) { + first = this.buttons.first().find( ".ui-icon" ); + this._removeClass( first, null, this.options.icons.up ); + this._addClass( first, null, value.up ); + last = this.buttons.last().find( ".ui-icon" ); + this._removeClass( last, null, this.options.icons.down ); + this._addClass( last, null, value.down ); + } + + this._super( key, value ); + }, + + _setOptionDisabled: function( value ) { + this._super( value ); + + this._toggleClass( this.uiSpinner, null, "ui-state-disabled", !!value ); + this.element.prop( "disabled", !!value ); + this.buttons.button( value ? "disable" : "enable" ); + }, + + _setOptions: spinnerModifier( function( options ) { + this._super( options ); + } ), + + _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() ) + } ); + }, + + isValid: function() { + var value = this.value(); + + // Null is invalid + if ( value === null ) { + return false; + } + + // If value gets adjusted, it's invalid + return value === this._adjustValue( value ); + }, + + // 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 + .prop( "disabled", false ) + .removeAttr( "autocomplete role aria-valuemin aria-valuemax aria-valuenow" ); + + this.uiSpinner.replaceWith( this.element ); + }, + + stepUp: spinnerModifier( function( steps ) { + this._stepUp( steps ); + } ), + _stepUp: function( steps ) { + if ( this._start() ) { + this._spin( ( steps || 1 ) * this.options.step ); + this._stop(); + } + }, + + stepDown: spinnerModifier( function( steps ) { + this._stepDown( steps ); + } ), + _stepDown: function( steps ) { + if ( this._start() ) { + this._spin( ( steps || 1 ) * -this.options.step ); + this._stop(); + } + }, + + pageUp: spinnerModifier( function( pages ) { + this._stepUp( ( pages || 1 ) * this.options.page ); + } ), + + pageDown: spinnerModifier( function( pages ) { + this._stepDown( ( pages || 1 ) * this.options.page ); + } ), + + value: function( newVal ) { + if ( !arguments.length ) { + return this._parse( this.element.val() ); + } + spinnerModifier( this._value ).call( this, newVal ); + }, + + widget: function() { + return this.uiSpinner; + } +} ); + +// DEPRECATED +// TODO: switch return back to widget declaration at top of file when this is removed +if ( $.uiBackCompat === true ) { + + // Backcompat for spinner html extension points + $.widget( "ui.spinner", $.ui.spinner, { + _enhance: function() { + this.uiSpinner = this.element + .attr( "autocomplete", "off" ) + .wrap( this._uiSpinnerHtml() ) + .parent() + + // Add buttons + .append( this._buttonHtml() ); + }, + _uiSpinnerHtml: function() { + return ""; + }, + + _buttonHtml: function() { + return ""; + } + } ); +} + +var widgetsSpinner = $.ui.spinner; + + +/*! + * jQuery UI Tabs 1.14.1 + * https://jqueryui.com + * + * Copyright OpenJS Foundation and other contributors + * Released under the MIT license. + * https://jquery.org/license + */ + +//>>label: Tabs +//>>group: Widgets +//>>description: Transforms a set of container elements into a tab structure. +//>>docs: https://api.jqueryui.com/tabs/ +//>>demos: https://jqueryui.com/tabs/ +//>>css.structure: ../../themes/base/core.css +//>>css.structure: ../../themes/base/tabs.css +//>>css.theme: ../../themes/base/theme.css + + +$.widget( "ui.tabs", { + version: "1.14.1", + delay: 300, + options: { + active: null, + classes: { + "ui-tabs": "ui-corner-all", + "ui-tabs-nav": "ui-corner-all", + "ui-tabs-panel": "ui-corner-bottom", + "ui-tabs-tab": "ui-corner-top" + }, + collapsible: false, + event: "click", + heightStyle: "content", + hide: null, + show: null, + + // Callbacks + activate: null, + beforeActivate: null, + beforeLoad: null, + load: null + }, + + _isLocal: ( function() { + var rhash = /#.*$/; + + return function( anchor ) { + var anchorUrl, locationUrl; + + anchorUrl = anchor.href.replace( rhash, "" ); + locationUrl = location.href.replace( rhash, "" ); + + // Decoding may throw an error if the URL isn't UTF-8 (#9518) + try { + anchorUrl = decodeURIComponent( anchorUrl ); + } catch ( error ) {} + try { + locationUrl = decodeURIComponent( locationUrl ); + } catch ( error ) {} + + return anchor.hash.length > 1 && anchorUrl === locationUrl; + }; + } )(), + + _create: function() { + var that = this, + options = this.options; + + this.running = false; + + this._addClass( "ui-tabs", "ui-widget ui-widget-content" ); + this._toggleClass( "ui-tabs-collapsible", null, options.collapsible ); + + this._processTabs(); + options.active = this._initialActive(); + + // Take disabling tabs via class attribute from HTML + // into account and update option properly. + if ( Array.isArray( options.disabled ) ) { + options.disabled = $.uniqueSort( 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( options.active ); + } else { + this.active = $(); + } + + this._refresh(); + + if ( this.active.length ) { + this.load( options.active ); + } + }, + + _initialActive: function() { + var active = this.options.active, + collapsible = this.options.collapsible, + locationHashDecoded = decodeURIComponent( location.hash.substring( 1 ) ); + + if ( active === null ) { + + // check the fragment identifier in the URL + if ( locationHashDecoded ) { + this.tabs.each( function( i, tab ) { + if ( $( tab ).attr( "aria-controls" ) === locationHashDecoded ) { + 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 = collapsible ? false : 0; + } + } + + // Don't allow collapsible: false and active: false + if ( !collapsible && active === false && this.anchors.length ) { + active = 0; + } + + return 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/command key will prevent automatic activation + if ( !event.ctrlKey && !event.metaKey ) { + + // 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.trigger( "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 ).trigger( "focus" ); + return index; + }, + + _setOption: function( key, value ) { + if ( key === "active" ) { + + // _activate() will handle invalid values and update this.options + this._activate( value ); + return; + } + + this._super( key, value ); + + if ( key === "collapsible" ) { + this._toggleClass( "ui-tabs-collapsible", null, 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 ); + } + }, + + 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._setOptionDisabled( this.options.disabled ); + this._setupEvents( this.options.event ); + this._setupHeightStyle( this.options.heightStyle ); + + this.tabs.not( this.active ).attr( { + "aria-selected": "false", + "aria-expanded": "false", + tabIndex: -1 + } ); + this.panels.not( this._getPanelForTab( this.active ) ) + .hide() + .attr( { + "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 + .attr( { + "aria-selected": "true", + "aria-expanded": "true", + tabIndex: 0 + } ); + this._addClass( this.active, "ui-tabs-active", "ui-state-active" ); + this._getPanelForTab( this.active ) + .show() + .attr( { + "aria-hidden": "false" + } ); + } + }, + + _processTabs: function() { + var that = this, + prevTabs = this.tabs, + prevAnchors = this.anchors, + prevPanels = this.panels; + + this.tablist = this._getList().attr( "role", "tablist" ); + this._addClass( this.tablist, "ui-tabs-nav", + "ui-helper-reset ui-helper-clearfix ui-widget-header" ); + + // Prevent users from focusing disabled tabs via click + this.tablist + .on( "mousedown" + this.eventNamespace, "> li", function( event ) { + if ( $( this ).is( ".ui-state-disabled" ) ) { + event.preventDefault(); + } + } ); + + this.tabs = this.tablist.find( "> li:has(a[href])" ) + .attr( { + role: "tab", + tabIndex: -1 + } ); + this._addClass( this.tabs, "ui-tabs-tab", "ui-state-default" ); + + this.anchors = this.tabs.map( function() { + return $( "a", this )[ 0 ]; + } ) + .attr( { + tabIndex: -1 + } ); + this._addClass( this.anchors, "ui-tabs-anchor" ); + + 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 ( that._isLocal( anchor ) ) { + selector = decodeURIComponent( anchor.hash ); + panelId = selector.substring( 1 ); + panel = that.element.find( "#" + CSS.escape( panelId ) ); + + // remote tab + } else { + + // If the tab doesn't already have aria-controls, + // generate an id by using a throw-away element + panelId = tab.attr( "aria-controls" ) || $( {} ).uniqueId()[ 0 ].id; + 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": panelId, + "aria-labelledby": anchorId + } ); + panel.attr( "aria-labelledby", anchorId ); + } ); + + this.panels.attr( "role", "tabpanel" ); + this._addClass( this.panels, "ui-tabs-panel", "ui-widget-content" ); + + // Avoid memory leaks (#10056) + if ( prevTabs ) { + this._off( prevTabs.not( this.tabs ) ); + this._off( prevAnchors.not( this.anchors ) ); + this._off( prevPanels.not( this.panels ) ); + } + }, + + // Allow overriding how to find the list for rare usage scenarios (#7715) + _getList: function() { + return this.tablist || this.element.find( "ol, ul" ).eq( 0 ); + }, + + _createPanel: function( id ) { + return $( "
" ) + .attr( "id", id ) + .data( "ui-tabs-destroy", true ); + }, + + _setOptionDisabled: function( disabled ) { + var currentItem, li, i; + + if ( Array.isArray( disabled ) ) { + if ( !disabled.length ) { + disabled = false; + } else if ( disabled.length === this.anchors.length ) { + disabled = true; + } + } + + // Disable tabs + for ( i = 0; ( li = this.tabs[ i ] ); i++ ) { + currentItem = $( li ); + if ( disabled === true || $.inArray( i, disabled ) !== -1 ) { + currentItem.attr( "aria-disabled", "true" ); + this._addClass( currentItem, null, "ui-state-disabled" ); + } else { + currentItem.removeAttr( "aria-disabled" ); + this._removeClass( currentItem, null, "ui-state-disabled" ); + } + } + + this.options.disabled = disabled; + + this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, + disabled === true ); + }, + + _setupEvents: function( event ) { + var events = {}; + if ( event ) { + $.each( event.split( " " ), function( index, eventName ) { + events[ eventName ] = "_eventHandler"; + } ); + } + + this._off( this.anchors.add( this.tabs ).add( this.panels ) ); + + // Always prevent the default action, even when disabled + this._on( true, this.anchors, { + click: function( event ) { + event.preventDefault(); + } + } ); + 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, + parent = this.element.parent(); + + if ( heightStyle === "fill" ) { + maxHeight = parent.height(); + maxHeight -= this.element.outerHeight() - this.element.height(); + + this.element.siblings( ":visible" ).each( function() { + var elem = $( this ), + position = elem.css( "position" ); + + if ( position === "absolute" || position === "fixed" ) { + return; + } + maxHeight -= elem.outerHeight( true ); + } ); + + 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() { + that._addClass( eventData.newTab.closest( "li" ), "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() { + that._removeClass( eventData.oldTab.closest( "li" ), + "ui-tabs-active", "ui-state-active" ); + show(); + } ); + } else { + this._removeClass( eventData.oldTab.closest( "li" ), + "ui-tabs-active", "ui-state-active" ); + toHide.hide(); + show(); + } + + toHide.attr( "aria-hidden", "true" ); + eventData.oldTab.attr( { + "aria-selected": "false", + "aria-expanded": "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-hidden", "false" ); + eventData.newTab.attr( { + "aria-selected": "true", + "aria-expanded": "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$='" + + CSS.escape( index ) + "']" ) ); + } + + return index; + }, + + _destroy: function() { + if ( this.xhr ) { + this.xhr.abort(); + } + + this.tablist + .removeAttr( "role" ) + .off( this.eventNamespace ); + + this.anchors + .removeAttr( "role tabIndex" ) + .removeUniqueId(); + + this.tabs.add( this.panels ).each( function() { + if ( $.data( this, "ui-tabs-destroy" ) ) { + $( this ).remove(); + } else { + $( this ).removeAttr( "role tabIndex " + + "aria-live aria-busy aria-selected aria-labelledby aria-hidden aria-expanded" ); + } + } ); + + this.tabs.each( function() { + var li = $( this ), + prev = li.data( "ui-tabs-aria-controls" ); + if ( prev ) { + li + .attr( "aria-controls", prev ) + .removeData( "ui-tabs-aria-controls" ); + } 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 ( Array.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._setOptionDisabled( 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 ( Array.isArray( disabled ) ) { + disabled = $.merge( [ index ], disabled ).sort(); + } else { + disabled = [ index ]; + } + } + this._setOptionDisabled( 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 + }, + complete = function( jqXHR, status ) { + if ( status === "abort" ) { + that.panels.stop( false, true ); + } + + that._removeClass( tab, "ui-tabs-loading" ); + panel.removeAttr( "aria-busy" ); + + if ( jqXHR === that.xhr ) { + delete that.xhr; + } + }; + + // Not remote + if ( this._isLocal( anchor[ 0 ] ) ) { + return; + } + + this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) ); + + if ( this.xhr.statusText !== "canceled" ) { + this._addClass( tab, "ui-tabs-loading" ); + panel.attr( "aria-busy", "true" ); + + this.xhr + .done( function( response, status, jqXHR ) { + panel.html( response ); + that._trigger( "load", event, eventData ); + + complete( jqXHR, status ); + } ) + .fail( function( jqXHR, status ) { + complete( jqXHR, status ); + } ); + } + }, + + _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( "#" + CSS.escape( id ) ); + } +} ); + +// DEPRECATED +// TODO: Switch return back to widget declaration at top of file when this is removed +if ( $.uiBackCompat === true ) { + + // Backcompat for ui-tab class (now ui-tabs-tab) + $.widget( "ui.tabs", $.ui.tabs, { + _processTabs: function() { + this._superApply( arguments ); + this._addClass( this.tabs, "ui-tab" ); + } + } ); +} + +var widgetsTabs = $.ui.tabs; + + +/*! + * jQuery UI Tooltip 1.14.1 + * https://jqueryui.com + * + * Copyright OpenJS Foundation and other contributors + * Released under the MIT license. + * https://jquery.org/license + */ + +//>>label: Tooltip +//>>group: Widgets +//>>description: Shows additional information for any element on hover or focus. +//>>docs: https://api.jqueryui.com/tooltip/ +//>>demos: https://jqueryui.com/tooltip/ +//>>css.structure: ../../themes/base/core.css +//>>css.structure: ../../themes/base/tooltip.css +//>>css.theme: ../../themes/base/theme.css + + +$.widget( "ui.tooltip", { + version: "1.14.1", + options: { + classes: { + "ui-tooltip": "ui-corner-all ui-widget-shadow" + }, + content: function() { + var title = $( this ).attr( "title" ); + + // Escape title, since we're going from an attribute to raw HTML + return $( "" ).text( title ).html(); + }, + 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, + track: false, + + // Callbacks + close: null, + open: null + }, + + _addDescribedBy: function( elem, id ) { + var describedby = ( elem.attr( "aria-describedby" ) || "" ).split( /\s+/ ); + describedby.push( id ); + elem + .data( "ui-tooltip-id", id ) + .attr( "aria-describedby", String.prototype.trim.call( describedby.join( " " ) ) ); + }, + + _removeDescribedBy: function( 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 = String.prototype.trim.call( describedby.join( " " ) ); + if ( describedby ) { + elem.attr( "aria-describedby", describedby ); + } else { + elem.removeAttr( "aria-describedby" ); + } + }, + + _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 = {}; + + // Append the aria-live region so tooltips announce correctly + this.liveRegion = $( "
" ) + .attr( { + role: "log", + "aria-live": "assertive", + "aria-relevant": "additions" + } ) + .appendTo( this.document[ 0 ].body ); + this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" ); + + this.disabledTitles = $( [] ); + }, + + _setOption: function( key, value ) { + var that = this; + + this._super( key, value ); + + if ( key === "content" ) { + $.each( this.tooltips, function( id, tooltipData ) { + that._updateContent( tooltipData.element ); + } ); + } + }, + + _setOptionDisabled: function( value ) { + this[ value ? "_disable" : "_enable" ](); + }, + + _disable: function() { + var that = this; + + // Close open tooltips + $.each( this.tooltips, function( id, tooltipData ) { + var event = $.Event( "blur" ); + event.target = event.currentTarget = tooltipData.element[ 0 ]; + that.close( event, true ); + } ); + + // Remove title attributes to prevent native tooltips + this.disabledTitles = this.disabledTitles.add( + this.element.find( this.options.items ).addBack() + .filter( function() { + var element = $( this ); + if ( element.is( "[title]" ) ) { + return element + .data( "ui-tooltip-title", element.attr( "title" ) ) + .removeAttr( "title" ); + } + } ) + ); + }, + + _enable: function() { + + // restore title attributes + this.disabledTitles.each( function() { + var element = $( this ); + if ( element.data( "ui-tooltip-title" ) ) { + element.attr( "title", element.data( "ui-tooltip-title" ) ); + } + } ); + this.disabledTitles = $( [] ); + }, + + 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._registerCloseHandlers( event, target ); + 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" || contentOption.nodeType || + contentOption.jquery ) { + 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; + } + + // 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; + } + that._open( event, target, response ); + } ); + if ( content ) { + this._open( event, target, content ); + } + }, + + _open: function( event, target, content ) { + var tooltipData, tooltip, delayedShow, a11yContent, + 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. + tooltipData = this._find( target ); + if ( tooltipData ) { + tooltipData.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" ); + } + } + + tooltipData = this._tooltip( target ); + tooltip = tooltipData.tooltip; + this._addDescribedBy( target, tooltip.attr( "id" ) ); + tooltip.find( ".ui-tooltip-content" ).html( content ); + + // Support: Voiceover on OS X, JAWS on IE <= 9 + // JAWS announces deletions even when aria-relevant="additions" + // Voiceover will sometimes re-read the entire log region's contents from the beginning + this.liveRegion.children().hide(); + a11yContent = $( "
" ).html( tooltip.find( ".ui-tooltip-content" ).html() ); + a11yContent.removeAttr( "name" ).find( "[name]" ).removeAttr( "name" ); + a11yContent.removeAttr( "id" ).find( "[id]" ).removeAttr( "id" ); + a11yContent.appendTo( this.liveRegion ); + + 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. + // Adds the check to add the timers only when both delay and track options are set (#14682) + if ( this.options.track && this.options.show && this.options.show.delay ) { + delayedShow = this.delayedShow = setInterval( function() { + if ( tooltip.is( ":visible" ) ) { + position( positionOption.of ); + clearInterval( delayedShow ); + } + }, 13 ); + } + + this._trigger( "open", event, { tooltip: tooltip } ); + }, + + _registerCloseHandlers: function( event, target ) { + var events = { + keyup: function( event ) { + if ( event.keyCode === $.ui.keyCode.ESCAPE ) { + var fakeEvent = $.Event( event ); + fakeEvent.currentTarget = target[ 0 ]; + this.close( fakeEvent, true ); + } + } + }; + + // Only bind remove handler for delegated targets. Non-delegated + // tooltips will handle this in destroy. + if ( target[ 0 ] !== this.element[ 0 ] ) { + events.remove = function() { + var targetElement = this._find( target ); + if ( targetElement ) { + this._removeTooltip( targetElement.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 tooltip, + that = this, + target = $( event ? event.currentTarget : this.element ), + tooltipData = this._find( target ); + + // The tooltip may already be closed + if ( !tooltipData ) { + + // We set ui-tooltip-open immediately upon open (in open()), but only set the + // additional data once there's actually content to show (in _open()). So even if the + // tooltip doesn't have full data, we always remove ui-tooltip-open in case we're in + // the period between open() and _open(). + target.removeData( "ui-tooltip-open" ); + return; + } + + tooltip = tooltipData.tooltip; + + // 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 ( tooltipData.closing ) { + return; + } + + // Clear the interval for delayed tracking tooltips + clearInterval( this.delayedShow ); + + // Only set title if we had one before (see comment in _open()) + // If the title attribute has changed since open(), don't restore + if ( target.data( "ui-tooltip-title" ) && !target.attr( "title" ) ) { + target.attr( "title", target.data( "ui-tooltip-title" ) ); + } + + this._removeDescribedBy( target ); + + tooltipData.hiding = true; + 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 ]; + } ); + } + + tooltipData.closing = true; + this._trigger( "close", event, { tooltip: tooltip } ); + if ( !tooltipData.hiding ) { + tooltipData.closing = false; + } + }, + + _tooltip: function( element ) { + var tooltip = $( "
" ).attr( "role", "tooltip" ), + content = $( "
" ).appendTo( tooltip ), + id = tooltip.uniqueId().attr( "id" ); + + this._addClass( content, "ui-tooltip-content" ); + this._addClass( tooltip, "ui-tooltip", "ui-widget ui-widget-content" ); + + tooltip.appendTo( this._appendTo( element ) ); + + return this.tooltips[ id ] = { + element: element, + tooltip: tooltip + }; + }, + + _find: function( target ) { + var id = target.data( "ui-tooltip-id" ); + return id ? this.tooltips[ id ] : null; + }, + + _removeTooltip: function( tooltip ) { + + // Clear the interval for delayed tracking tooltips + clearInterval( this.delayedShow ); + + tooltip.remove(); + delete this.tooltips[ tooltip.attr( "id" ) ]; + }, + + _appendTo: function( target ) { + var element = target.closest( ".ui-front, dialog" ); + + if ( !element.length ) { + element = this.document[ 0 ].body; + } + + return element; + }, + + _destroy: function() { + var that = this; + + // Close open tooltips + $.each( this.tooltips, function( id, tooltipData ) { + + // Delegate to close method to handle common cleanup + var event = $.Event( "blur" ), + element = tooltipData.element; + 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" ) ) { + + // If the title attribute has changed since open(), don't restore + if ( !element.attr( "title" ) ) { + element.attr( "title", element.data( "ui-tooltip-title" ) ); + } + element.removeData( "ui-tooltip-title" ); + } + } ); + this.liveRegion.remove(); + } +} ); + +// DEPRECATED +// TODO: Switch return back to widget declaration at top of file when this is removed +if ( $.uiBackCompat === true ) { + + // Backcompat for tooltipClass option + $.widget( "ui.tooltip", $.ui.tooltip, { + options: { + tooltipClass: null + }, + _tooltip: function() { + var tooltipData = this._superApply( arguments ); + if ( this.options.tooltipClass ) { + tooltipData.tooltip.addClass( this.options.tooltipClass ); + } + return tooltipData; + } + } ); +} + +var widgetsTooltip = $.ui.tooltip; + + + + +} ); \ No newline at end of file diff --git a/datavault-webapp/src/main/webapp/resources/jquery-ui/1.14.1/jquery-ui.min.js b/datavault-webapp/src/main/webapp/resources/jquery-ui/1.14.1/jquery-ui.min.js new file mode 100644 index 000000000..841179e84 --- /dev/null +++ b/datavault-webapp/src/main/webapp/resources/jquery-ui/1.14.1/jquery-ui.min.js @@ -0,0 +1,6 @@ +/*! jQuery UI - v1.14.1 - 2024-10-30 +* https://jqueryui.com +* Includes: widget.js, position.js, data.js, disable-selection.js, effect.js, effects/effect-blind.js, effects/effect-bounce.js, effects/effect-clip.js, effects/effect-drop.js, effects/effect-explode.js, effects/effect-fade.js, effects/effect-fold.js, effects/effect-highlight.js, effects/effect-puff.js, effects/effect-pulsate.js, effects/effect-scale.js, effects/effect-shake.js, effects/effect-size.js, effects/effect-slide.js, effects/effect-transfer.js, focusable.js, form-reset-mixin.js, jquery-patch.js, keycode.js, labels.js, scroll-parent.js, tabbable.js, unique-id.js, widgets/accordion.js, widgets/autocomplete.js, widgets/button.js, widgets/checkboxradio.js, widgets/controlgroup.js, widgets/datepicker.js, widgets/dialog.js, widgets/draggable.js, widgets/droppable.js, widgets/menu.js, widgets/mouse.js, widgets/progressbar.js, widgets/resizable.js, widgets/selectable.js, widgets/selectmenu.js, widgets/slider.js, widgets/sortable.js, widgets/spinner.js, widgets/tabs.js, widgets/tooltip.js +* Copyright OpenJS Foundation and other contributors; Licensed MIT */ + +(t=>{"function"==typeof define&&define.amd?define(["jquery"],t):t(jQuery)})(function(V){V.ui=V.ui||{};V.ui.version="1.14.1";var n,s,x,k,o,a,r,l,h,i,E=0,N=Array.prototype.hasOwnProperty,c=Array.prototype.slice;V.cleanData=(n=V.cleanData,function(t){for(var e,i,s=0;null!=(i=t[s]);s++)(e=V._data(i,"events"))&&e.remove&&V(i).triggerHandler("remove");n(t)}),V.widget=function(t,i,e){var s,n,o,a,r={},l=t.split(".")[0];return"__proto__"===(t=t.split(".")[1])||"constructor"===t?V.error("Invalid widget name: "+t):(a=l+"-"+t,e||(e=i,i=V.Widget),Array.isArray(e)&&(e=V.extend.apply(null,[{}].concat(e))),V.expr.pseudos[a.toLowerCase()]=function(t){return!!V.data(t,a)},V[l]=V[l]||{},s=V[l][t],n=V[l][t]=function(t,e){if(!this||!this._createWidget)return new n(t,e);arguments.length&&this._createWidget(t,e)},V.extend(n,s,{version:e.version,_proto:V.extend({},e),_childConstructors:[]}),(o=new i).options=V.widget.extend({},o.options),V.each(e,function(e,s){function n(){return i.prototype[e].apply(this,arguments)}function o(t){return i.prototype[e].apply(this,t)}r[e]="function"!=typeof s?s:function(){var t,e=this._super,i=this._superApply;return this._super=n,this._superApply=o,t=s.apply(this,arguments),this._super=e,this._superApply=i,t}}),n.prototype=V.widget.extend(o,{widgetEventPrefix:s&&o.widgetEventPrefix||t},r,{constructor:n,namespace:l,widgetName:t,widgetFullName:a}),s?(V.each(s._childConstructors,function(t,e){var i=e.prototype;V.widget(i.namespace+"."+i.widgetName,n,e._proto)}),delete s._childConstructors):i._childConstructors.push(n),V.widget.bridge(t,n),n)},V.widget.extend=function(t){for(var e,i,s=c.call(arguments,1),n=0,o=s.length;n",options:{classes:{},disabled:!1,create:null},_createWidget:function(t,e){e=V(e||this.defaultElement||this)[0],this.element=V(e),this.uuid=E++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=V(),this.hoverable=V(),this.focusable=V(),this.classesElementLookup={},e!==this&&(V.data(e,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t){t.target===e&&this.destroy()}}),this.document=V(e.style?e.ownerDocument:e.document||e),this.window=V(this.document[0].defaultView||this.document[0].parentWindow)),this.options=V.widget.extend({},this.options,this._getCreateOptions(),t),this._create(),this.options.disabled&&this._setOptionDisabled(this.options.disabled),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:function(){return{}},_getCreateEventData:V.noop,_create:V.noop,_init:V.noop,destroy:function(){var i=this;this._destroy(),V.each(this.classesElementLookup,function(t,e){i._removeClass(e,t)}),this.element.off(this.eventNamespace).removeData(this.widgetFullName),this.widget().off(this.eventNamespace).removeAttr("aria-disabled"),this.bindings.off(this.eventNamespace)},_destroy:V.noop,widget:function(){return this.element},option:function(t,e){var i,s,n,o=t;if(0===arguments.length)return V.widget.extend({},this.options);if("string"==typeof t)if(o={},t=(i=t.split(".")).shift(),i.length){for(s=o[t]=V.widget.extend({},this.options[t]),n=0;n{var i=[];n.element.each(function(t,e){V.map(a.classesElementLookup,function(t){return t}).some(function(t){return t.is(e)})||i.push(e)}),a._on(V(i),{remove:"_untrackClassesElement"})})(),V(V.uniqueSort(i.get().concat(n.element.get())))):V(i.not(n.element).get()),a.classesElementLookup[t[s]]=i,o.push(t[s]),e&&n.classes[t[s]]&&o.push(n.classes[t[s]])}return(n=V.extend({element:this.element,classes:this.options.classes||{}},n)).keys&&t(n.keys.match(/\S+/g)||[],!0),n.extra&&t(n.extra.match(/\S+/g)||[]),o.join(" ")},_untrackClassesElement:function(i){var s=this;V.each(s.classesElementLookup,function(t,e){-1!==V.inArray(i.target,e)&&(s.classesElementLookup[t]=V(e.not(i.target).get()))}),this._off(V(i.target))},_removeClass:function(t,e,i){return this._toggleClass(t,e,i,!1)},_addClass:function(t,e,i){return this._toggleClass(t,e,i,!0)},_toggleClass:function(t,e,i,s){var n="string"==typeof t||null===t,e={extra:n?e:i,keys:n?t:e,element:n?this.element:t,add:s="boolean"==typeof s?s:i};return e.element.toggleClass(this._classes(e),s),this},_on:function(n,o,t){var a,r=this;"boolean"!=typeof n&&(t=o,o=n,n=!1),t?(o=a=V(o),this.bindings=this.bindings.add(o)):(t=o,o=this.element,a=this.widget()),V.each(t,function(t,e){function i(){if(n||!0!==r.options.disabled&&!V(this).hasClass("ui-state-disabled"))return("string"==typeof e?r[e]:e).apply(r,arguments)}"string"!=typeof e&&(i.guid=e.guid=e.guid||i.guid||V.guid++);var t=t.match(/^([\w:-]*)\s*(.*)$/),s=t[1]+r.eventNamespace,t=t[2];t?a.on(s,t,i):o.on(s,i)})},_off:function(t,e){e=(e||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,t.off(e),this.bindings=V(this.bindings.not(t).get()),this.focusable=V(this.focusable.not(t).get()),this.hoverable=V(this.hoverable.not(t).get())},_delay:function(t,e){var i=this;return setTimeout(function(){return("string"==typeof t?i[t]:t).apply(i,arguments)},e||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){this._addClass(V(t.currentTarget),null,"ui-state-hover")},mouseleave:function(t){this._removeClass(V(t.currentTarget),null,"ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){this._addClass(V(t.currentTarget),null,"ui-state-focus")},focusout:function(t){this._removeClass(V(t.currentTarget),null,"ui-state-focus")}})},_trigger:function(t,e,i){var s,n,o=this.options[t];if(i=i||{},(e=V.Event(e)).type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),e.target=this.element[0],n=e.originalEvent)for(s in n)s in e||(e[s]=n[s]);return this.element.trigger(e,i),!("function"==typeof o&&!1===o.apply(this.element[0],[e].concat(i))||e.isDefaultPrevented())}},V.each({show:"fadeIn",hide:"fadeOut"},function(o,a){V.Widget.prototype["_"+o]=function(e,t,i){var s,n=(t="string"==typeof t?{effect:t}:t)?!0!==t&&"number"!=typeof t&&t.effect||a:o;"number"==typeof(t=t||{})?t={duration:t}:!0===t&&(t={}),s=!V.isEmptyObject(t),t.complete=i,t.delay&&e.delay(t.delay),s&&V.effects&&V.effects.effect[n]?e[o](t):n!==o&&e[n]?e[n](t.duration,t.easing,i):e.queue(function(t){V(this)[o](),i&&i.call(e[0]),t()})}}),V.widget;function C(t,e,i){return[parseFloat(t[0])*(h.test(t[0])?e/100:1),parseFloat(t[1])*(h.test(t[1])?i/100:1)]}function D(t,e){return parseInt(V.css(t,e),10)||0}function I(t){return null!=t&&t===t.window}x=Math.max,k=Math.abs,o=/left|center|right/,a=/top|center|bottom/,r=/[\+\-]\d+(\.[\d]+)?%?/,l=/^\w+/,h=/%$/,i=V.fn.position,V.position={scrollbarWidth:function(){var t,e,i;return void 0!==s?s:(i=(e=V("
")).children()[0],V("body").append(e),t=i.offsetWidth,e.css("overflow","scroll"),t===(i=i.offsetWidth)&&(i=e[0].clientWidth),e.remove(),s=t-i)},getScrollInfo:function(t){var e=t.isWindow||t.isDocument?"":t.element.css("overflow-x"),i=t.isWindow||t.isDocument?"":t.element.css("overflow-y"),e="scroll"===e||"auto"===e&&t.widthx(k(s),k(n))?o.important="horizontal":o.important="vertical",u.using.call(this,t,o)}),a.offset(V.extend(h,{using:t}))})):i.apply(this,arguments)},V.ui.position={fit:{left:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollLeft:s.offset.left,s=s.width,o=t.left-e.collisionPosition.marginLeft,a=n-o,r=o+e.collisionWidth-s-n;so.mod/2?s+=o.mod:s-n>o.mod/2&&(s-=o.mod)),l[i]=_((n-s)*a+s,e)))}),this[t](l)},blend:function(t){var e,i,s;return 1===this._rgba[3]?this:(e=this._rgba.slice(),i=e.pop(),s=p(t)._rgba,p(u.map(e,function(t,e){return(1-i)*s[e]+i*t})))},toRgbaString:function(){var t="rgba(",e=u.map(this._rgba,function(t,e){return null!=t?t:2{var i,s,n={};for(i in e)s=e[i],t[i]===s||U[i]||!V.fx.step[i]&&isNaN(parseFloat(s))||(n[i]=s);return n})(this.start,this.end),this}),i.attr("class",t),e=e.map(function(){var t=this,e=V.Deferred(),i=V.extend({},o,{queue:!1,complete:function(){e.resolve(t)}});return this.el.animate(this.diff,i),e.promise()}),V.when.apply(V,e.get()).done(function(){s(),V.each(arguments,function(){var e=this.el;V.each(this.diff,function(t){e.css(t,"")})}),o.complete.call(i[0])})})},V.fn.extend({addClass:(q=V.fn.addClass,function(t,e,i,s){return e?V.effects.animateClass.call(this,{add:t},e,i,s):q.apply(this,arguments)}),removeClass:(j=V.fn.removeClass,function(t,e,i,s){return 1
").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),e={width:i.width(),height:i.height()},n=document.activeElement;try{n.id}catch(t){n=document.body}return i.wrap(t),i[0]!==n&&!V.contains(i[0],n)||V(n).trigger("focus"),t=i.parent(),"static"===i.css("position")?(t.css({position:"relative"}),i.css({position:"relative"})):(V.extend(s,{position:i.css("position"),zIndex:i.css("z-index")}),V.each(["top","left","bottom","right"],function(t,e){s[e]=i.css(e),isNaN(parseInt(s[e],10))&&(s[e]="auto")}),i.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})),i.css(e),t.css(s).show()},removeWrapper:function(t){var e=document.activeElement;return t.parent().is(".ui-effects-wrapper")&&(t.parent().replaceWith(t),t[0]!==e&&!V.contains(t[0],e)||V(e).trigger("focus")),t}}),V.extend(V.effects,{version:"1.14.1",define:function(t,e,i){return i||(i=e,e="effect"),V.effects.effect[t]=i,V.effects.effect[t].mode=e,i},scaledDimensions:function(t,e,i){var s;return 0===e?{height:0,width:0,outerHeight:0,outerWidth:0}:(s="horizontal"!==i?(e||100)/100:1,i="vertical"!==i?(e||100)/100:1,{height:t.height()*i,width:t.width()*s,outerHeight:t.outerHeight()*i,outerWidth:t.outerWidth()*s})},clipToBox:function(t){return{width:t.clip.right-t.clip.left,height:t.clip.bottom-t.clip.top,left:t.clip.left,top:t.clip.top}},unshift:function(t,e,i){var s=t.queue();1").insertAfter(t).css({display:/^(inline|ruby)/.test(t.css("display"))?"inline-block":"block",visibility:"hidden",marginTop:t.css("marginTop"),marginBottom:t.css("marginBottom"),marginLeft:t.css("marginLeft"),marginRight:t.css("marginRight"),float:t.css("float")}).outerWidth(t.outerWidth()).outerHeight(t.outerHeight()).addClass("ui-effects-placeholder"),t.data(w+"placeholder",e)),t.css({position:i,left:s.left,top:s.top}),e},removePlaceholder:function(t){var e=w+"placeholder",i=t.data(e);i&&(i.remove(),t.removeData(e))},cleanUp:function(t){V.effects.restoreStyle(t),V.effects.removePlaceholder(t)},setTransition:function(s,t,n,o){return o=o||{},V.each(t,function(t,e){var i=s.cssUnit(e);0
");l.appendTo("body").addClass(t.className).css({top:s.top-a,left:s.left-o,height:i.innerHeight(),width:i.innerWidth(),position:n?"fixed":"absolute"}).animate(r,t.duration,t.easing,function(){l.remove(),"function"==typeof e&&e()})}}),V.fx.step.clip=function(t){t.clipInit||(t.start=V(t.elem).cssClip(),"string"==typeof t.end&&(t.end=Z(t.end,t.elem)),t.clipInit=!0),V(t.elem).cssClip({top:t.pos*(t.end.top-t.start.top)+t.start.top,right:t.pos*(t.end.right-t.start.right)+t.start.right,bottom:t.pos*(t.end.bottom-t.start.bottom)+t.start.bottom,left:t.pos*(t.end.left-t.start.left)+t.start.left})},b={},V.each(["Quad","Cubic","Quart","Quint","Expo"],function(e,t){b[t]=function(t){return Math.pow(t,e+2)}}),V.extend(b,{Sine:function(t){return 1-Math.cos(t*Math.PI/2)},Circ:function(t){return 1-Math.sqrt(1-t*t)},Elastic:function(t){return 0===t||1===t?t:-Math.pow(2,8*(t-1))*Math.sin((80*(t-1)-7.5)*Math.PI/15)},Back:function(t){return t*t*(3*t-2)},Bounce:function(t){for(var e,i=4;t<((e=Math.pow(2,--i))-1)/11;);return 1/Math.pow(4,3-i)-7.5625*Math.pow((3*e-2)/22-t,2)}}),V.each(b,function(t,e){V.easing["easeIn"+t]=e,V.easing["easeOut"+t]=function(t){return 1-e(1-t)},V.easing["easeInOut"+t]=function(t){return t<.5?e(2*t)/2:1-e(-2*t+2)/2}});var tt,et,S,it=V.effects,st=(V.effects.define("blind","hide",function(t,e){var i={up:["bottom","top"],vertical:["bottom","top"],down:["top","bottom"],left:["right","left"],horizontal:["right","left"],right:["left","right"]},s=V(this),n=t.direction||"up",o=s.cssClip(),a={clip:V.extend({},o)},r=V.effects.createPlaceholder(s);a.clip[i[n][0]]=a.clip[i[n][1]],"show"===t.mode&&(s.cssClip(a.clip),r&&r.css(V.effects.clipToBox(a)),a.clip=o),r&&r.animate(V.effects.clipToBox(a),t.duration,t.easing),s.animate(a,{queue:!1,duration:t.duration,easing:t.easing,complete:e})}),V.effects.define("bounce",function(t,e){var i,s,n=V(this),o=t.mode,a="hide"===o,o="show"===o,r=t.direction||"up",l=t.distance,h=t.times||5,c=2*h+(o||a?1:0),u=t.duration/c,d=t.easing,p="up"===r||"down"===r?"top":"left",f="up"===r||"left"===r,g=0,t=n.queue().length;for(V.effects.createPlaceholder(n),r=n.css(p),l=l||n["top"==p?"outerHeight":"outerWidth"]()/3,o&&((s={opacity:1})[p]=r,n.css("opacity",0).css(p,f?2*-l:2*l).animate(s,u,d)),a&&(l/=Math.pow(2,h-1)),(s={})[p]=r;g
").css({position:"absolute",visibility:"visible",left:-s*p,top:-i*f}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:p,height:f,left:n+(u?a*p:0),top:o+(u?r*f:0),opacity:u?0:1}).animate({left:n+(u?0:a*p),top:o+(u?0:r*f),opacity:u?1:0},t.duration||500,t.easing,m)}),V.effects.define("fade","toggle",function(t,e){var i="show"===t.mode;V(this).css("opacity",i?0:1).animate({opacity:i?1:0},{queue:!1,duration:t.duration,easing:t.easing,complete:e})}),V.effects.define("fold","hide",function(e,t){var i=V(this),s=e.mode,n="show"===s,s="hide"===s,o=e.size||15,a=/([0-9]+)%/.exec(o),r=!!e.horizFirst?["right","bottom"]:["bottom","right"],l=e.duration/2,h=V.effects.createPlaceholder(i),c=i.cssClip(),u={clip:V.extend({},c)},d={clip:V.extend({},c)},p=[c[r[0]],c[r[1]]],f=i.queue().length;a&&(o=parseInt(a[1],10)/100*p[s?0:1]),u.clip[r[0]]=o,d.clip[r[0]]=o,d.clip[r[1]]=0,n&&(i.cssClip(d.clip),h&&h.css(V.effects.clipToBox(d)),d.clip=c),i.queue(function(t){h&&h.animate(V.effects.clipToBox(u),l,e.easing).animate(V.effects.clipToBox(d),l,e.easing),t()}).animate(u,l,e.easing).animate(d,l,e.easing).queue(t),V.effects.unshift(i,f,4)}),V.effects.define("highlight","show",function(t,e){var i=V(this),s={backgroundColor:i.css("backgroundColor")};"hide"===t.mode&&(s.opacity=0),V.effects.saveStyle(i),i.css({backgroundImage:"none",backgroundColor:t.color||"#ffff99"}).animate(s,{queue:!1,duration:t.duration,easing:t.easing,complete:e})}),V.effects.define("size",function(s,e){var n,i=V(this),t=["fontSize"],o=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"],a=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"],r=s.mode,l="effect"!==r,h=s.scale||"both",c=s.origin||["middle","center"],u=i.css("position"),d=i.position(),p=V.effects.scaledDimensions(i),f=s.from||p,g=s.to||V.effects.scaledDimensions(i,0);V.effects.createPlaceholder(i),"show"===r&&(r=f,f=g,g=r),n={from:{y:f.height/p.height,x:f.width/p.width},to:{y:g.height/p.height,x:g.width/p.width}},"box"!==h&&"both"!==h||(n.from.y!==n.to.y&&(f=V.effects.setTransition(i,o,n.from.y,f),g=V.effects.setTransition(i,o,n.to.y,g)),n.from.x!==n.to.x&&(f=V.effects.setTransition(i,a,n.from.x,f),g=V.effects.setTransition(i,a,n.to.x,g))),"content"!==h&&"both"!==h||n.from.y!==n.to.y&&(f=V.effects.setTransition(i,t,n.from.y,f),g=V.effects.setTransition(i,t,n.to.y,g)),c&&(r=V.effects.getBaseline(c,p),f.top=(p.outerHeight-f.outerHeight)*r.y+d.top,f.left=(p.outerWidth-f.outerWidth)*r.x+d.left,g.top=(p.outerHeight-g.outerHeight)*r.y+d.top,g.left=(p.outerWidth-g.outerWidth)*r.x+d.left),delete f.outerHeight,delete f.outerWidth,i.css(f),"content"!==h&&"both"!==h||(o=o.concat(["marginTop","marginBottom"]).concat(t),a=a.concat(["marginLeft","marginRight"]),i.find("*[width]").each(function(){var t=V(this),e=V.effects.scaledDimensions(t),i={height:e.height*n.from.y,width:e.width*n.from.x,outerHeight:e.outerHeight*n.from.y,outerWidth:e.outerWidth*n.from.x},e={height:e.height*n.to.y,width:e.width*n.to.x,outerHeight:e.height*n.to.y,outerWidth:e.width*n.to.x};n.from.y!==n.to.y&&(i=V.effects.setTransition(t,o,n.from.y,i),e=V.effects.setTransition(t,o,n.to.y,e)),n.from.x!==n.to.x&&(i=V.effects.setTransition(t,a,n.from.x,i),e=V.effects.setTransition(t,a,n.to.x,e)),l&&V.effects.saveStyle(t),t.css(i),t.animate(e,s.duration,s.easing,function(){l&&V.effects.restoreStyle(t)})})),i.animate(g,{queue:!1,duration:s.duration,easing:s.easing,complete:function(){var t=i.offset();0===g.opacity&&i.css("opacity",f.opacity),l||(i.css("position","static"===u?"relative":u).offset(t),V.effects.saveStyle(i)),e()}})}),V.effects.define("scale",function(t,e){var i=V(this),s=t.mode,s=parseInt(t.percent,10)||(0===parseInt(t.percent,10)||"effect"!==s?0:100),i=V.extend(!0,{from:V.effects.scaledDimensions(i),to:V.effects.scaledDimensions(i,s,t.direction||"both"),origin:t.origin||["middle","center"]},t);t.fade&&(i.from.opacity=1,i.to.opacity=0),V.effects.effect.size.call(this,i,e)}),V.effects.define("puff","hide",function(t,e){t=V.extend(!0,{},t,{fade:!0,percent:parseInt(t.percent,10)||150});V.effects.effect.scale.call(this,t,e)}),V.effects.define("pulsate","show",function(t,e){var i=V(this),s=t.mode,n="show"===s,o=2*(t.times||5)+(n||"hide"===s?1:0),a=t.duration/o,r=0,l=1,s=i.queue().length;for(!n&&i.is(":visible")||(i.css("opacity",0).show(),r=1);l li > :first-child").add(t.find("> :not(li)").filter(function(t){return t%2==0}))},heightStyle:"auto",icons:{activeHeader:"ui-icon-triangle-1-s",header:"ui-icon-triangle-1-e"},activate:null,beforeActivate:null},hideProps:{borderTopWidth:"hide",borderBottomWidth:"hide",paddingTop:"hide",paddingBottom:"hide",height:"hide"},showProps:{borderTopWidth:"show",borderBottomWidth:"show",paddingTop:"show",paddingBottom:"show",height:"show"},_create:function(){var t=this.options;this.prevShow=this.prevHide=V(),this._addClass("ui-accordion","ui-widget ui-helper-reset"),this.element.attr("role","tablist"),t.collapsible||!1!==t.active&&null!=t.active||(t.active=0),this._processPanels(),t.active<0&&(t.active+=this.headers.length),this._refresh()},_getCreateEventData:function(){return{header:this.active,panel:this.active.length?this.active.next():V()}},_createIcons:function(){var t,e=this.options.icons;e&&(t=V(""),this._addClass(t,"ui-accordion-header-icon","ui-icon "+e.header),t.prependTo(this.headers),t=this.active.children(".ui-accordion-header-icon"),this._removeClass(t,e.header)._addClass(t,null,e.activeHeader)._addClass(this.headers,"ui-accordion-icons"))},_destroyIcons:function(){this._removeClass(this.headers,"ui-accordion-icons"),this.headers.children(".ui-accordion-header-icon").remove()},_destroy:function(){var t;this.element.removeAttr("role"),this.headers.removeAttr("role aria-expanded aria-selected aria-controls tabIndex").removeUniqueId(),this._destroyIcons(),t=this.headers.next().css("display","").removeAttr("role aria-hidden aria-labelledby").removeUniqueId(),"content"!==this.options.heightStyle&&t.css("height","")},_setOption:function(t,e){"active"===t?this._activate(e):("event"===t&&(this.options.event&&this._off(this.headers,this.options.event),this._setupEvents(e)),this._super(t,e),"collapsible"!==t||e||!1!==this.options.active||this._activate(0),"icons"===t&&(this._destroyIcons(),e)&&this._createIcons())},_setOptionDisabled:function(t){this._super(t),this.element.attr("aria-disabled",t),this._toggleClass(null,"ui-state-disabled",!!t)},_keydown:function(t){if(!t.altKey&&!t.ctrlKey){var e=V.ui.keyCode,i=this.headers.length,s=this.headers.index(t.target),n=!1;switch(t.keyCode){case e.RIGHT:case e.DOWN:n=this.headers[(s+1)%i];break;case e.LEFT:case e.UP:n=this.headers[(s-1+i)%i];break;case e.SPACE:case e.ENTER:this._eventHandler(t);break;case e.HOME:n=this.headers[0];break;case e.END:n=this.headers[i-1]}n&&(V(t.target).attr("tabIndex",-1),V(n).attr("tabIndex",0),V(n).trigger("focus"),t.preventDefault())}},_panelKeyDown:function(t){t.keyCode===V.ui.keyCode.UP&&t.ctrlKey&&V(t.currentTarget).prev().trigger("focus")},refresh:function(){var t=this.options;this._processPanels(),!1===t.active&&!0===t.collapsible||!this.headers.length?(t.active=!1,this.active=V()):!1===t.active?this._activate(0):this.active.length&&!V.contains(this.element[0],this.active[0])?this.headers.length===this.headers.find(".ui-state-disabled").length?(t.active=!1,this.active=V()):this._activate(Math.max(0,t.active-1)):t.active=this.headers.index(this.active),this._destroyIcons(),this._refresh()},_processPanels:function(){var t=this.headers,e=this.panels;"function"==typeof this.options.header?this.headers=this.options.header(this.element):this.headers=this.element.find(this.options.header),this._addClass(this.headers,"ui-accordion-header ui-accordion-header-collapsed","ui-state-default"),this.panels=this.headers.next().filter(":not(.ui-accordion-content-active)").hide(),this._addClass(this.panels,"ui-accordion-content","ui-helper-reset ui-widget-content"),e&&(this._off(t.not(this.headers)),this._off(e.not(this.panels)))},_refresh:function(){var i,t=this.options,e=t.heightStyle,s=this.element.parent();this.active=this._findActive(t.active),this._addClass(this.active,"ui-accordion-header-active","ui-state-active")._removeClass(this.active,"ui-accordion-header-collapsed"),this._addClass(this.active.next(),"ui-accordion-content-active"),this.active.next().show(),this.headers.attr("role","tab").each(function(){var t=V(this),e=t.uniqueId().attr("id"),i=t.next(),s=i.uniqueId().attr("id");t.attr("aria-controls",s),i.attr("aria-labelledby",e)}).next().attr("role","tabpanel"),this.headers.not(this.active).attr({"aria-selected":"false","aria-expanded":"false",tabIndex:-1}).next().attr({"aria-hidden":"true"}).hide(),this.active.length?this.active.attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0}).next().attr({"aria-hidden":"false"}):this.headers.eq(0).attr("tabIndex",0),this._createIcons(),this._setupEvents(t.event),"fill"===e?(i=s.height(),this.element.siblings(":visible").each(function(){var t=V(this),e=t.css("position");"absolute"!==e&&"fixed"!==e&&(i-=t.outerHeight(!0))}),this.headers.each(function(){i-=V(this).outerHeight(!0)}),this.headers.next().each(function(){V(this).height(Math.max(0,i-V(this).innerHeight()+V(this).height()))}).css("overflow","auto")):"auto"===e&&(i=0,this.headers.next().each(function(){var t=V(this).is(":visible");t||V(this).show(),i=Math.max(i,V(this).css("height","").height()),t||V(this).hide()}).height(i))},_activate:function(t){t=this._findActive(t)[0];t!==this.active[0]&&(t=t||this.active[0],this._eventHandler({target:t,currentTarget:t,preventDefault:V.noop}))},_findActive:function(t){return"number"==typeof t?this.headers.eq(t):V()},_setupEvents:function(t){var i={keydown:"_keydown"};t&&V.each(t.split(" "),function(t,e){i[e]="_eventHandler"}),this._off(this.headers.add(this.headers.next())),this._on(this.headers,i),this._on(this.headers.next(),{keydown:"_panelKeyDown"}),this._hoverable(this.headers),this._focusable(this.headers)},_eventHandler:function(t){var e=this.options,i=this.active,s=V(t.currentTarget),n=s[0]===i[0],o=n&&e.collapsible,a=o?V():s.next(),r=i.next(),r={oldHeader:i,oldPanel:r,newHeader:o?V():s,newPanel:a};t.preventDefault(),n&&!e.collapsible||!1===this._trigger("beforeActivate",t,r)||(e.active=!o&&this.headers.index(s),this.active=n?V():s,this._toggle(r),this._removeClass(i,"ui-accordion-header-active","ui-state-active"),e.icons&&(a=i.children(".ui-accordion-header-icon"),this._removeClass(a,null,e.icons.activeHeader)._addClass(a,null,e.icons.header)),n)||(this._removeClass(s,"ui-accordion-header-collapsed")._addClass(s,"ui-accordion-header-active","ui-state-active"),e.icons&&(t=s.children(".ui-accordion-header-icon"),this._removeClass(t,null,e.icons.header)._addClass(t,null,e.icons.activeHeader)),this._addClass(s.next(),"ui-accordion-content-active"))},_toggle:function(t){var e=t.newPanel,i=this.prevShow.length?this.prevShow:t.oldPanel;this.prevShow.add(this.prevHide).stop(!0,!0),this.prevShow=e,this.prevHide=i,this.options.animate?this._animate(e,i,t):(i.hide(),e.show(),this._toggleComplete(t)),i.attr({"aria-hidden":"true"}),i.prev().attr({"aria-selected":"false","aria-expanded":"false"}),e.length&&i.length?i.prev().attr({tabIndex:-1,"aria-expanded":"false"}):e.length&&this.headers.filter(function(){return 0===parseInt(V(this).attr("tabIndex"),10)}).attr("tabIndex",-1),e.attr("aria-hidden","false").prev().attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0})},_animate:function(t,i,e){function s(){o._toggleComplete(e)}var n,o=this,a=0,r=t.css("box-sizing"),l=t.length&&(!i.length||t.index()",delay:300,options:{icons:{submenu:"ui-icon-caret-1-e"},items:"> *",menus:"ul",position:{my:"left top",at:"right top"},role:"menu",blur:null,focus:null,select:null},_create:function(){this.activeMenu=this.element,this.mouseHandled=!1,this.lastMousePosition={x:null,y:null},this.element.uniqueId().attr({role:this.options.role,tabIndex:0}),this._addClass("ui-menu","ui-widget ui-widget-content"),this._on({"mousedown .ui-menu-item":function(t){t.preventDefault(),this._activateItem(t)},"click .ui-menu-item":function(t){var e=V(t.target),i=V(this.document[0].activeElement);!this.mouseHandled&&e.not(".ui-state-disabled").length&&(this.select(t),t.isPropagationStopped()||(this.mouseHandled=!0),e.has(".ui-menu").length?this.expand(t):!this.element.is(":focus")&&i.closest(".ui-menu").length&&(this.element.trigger("focus",[!0]),this.active)&&1===this.active.parents(".ui-menu").length&&clearTimeout(this.timer))},"mouseenter .ui-menu-item":"_activateItem","mousemove .ui-menu-item":"_activateItem",mouseleave:"collapseAll","mouseleave .ui-menu":"collapseAll",focus:function(t,e){var i=this.active||this._menuItems().first();e||this.focus(t,i)},blur:function(t){this._delay(function(){V.contains(this.element[0],this.document[0].activeElement)||this.collapseAll(t)})},keydown:"_keydown"}),this.refresh(),this._on(this.document,{click:function(t){this._closeOnDocumentClick(t)&&this.collapseAll(t,!0),this.mouseHandled=!1}})},_activateItem:function(t){var e,i;this.previousFilter||t.clientX===this.lastMousePosition.x&&t.clientY===this.lastMousePosition.y||(this.lastMousePosition={x:t.clientX,y:t.clientY},e=V(t.target).closest(".ui-menu-item"),i=V(t.currentTarget),e[0]!==i[0])||i.is(".ui-state-active")||(this._removeClass(i.siblings().children(".ui-state-active"),null,"ui-state-active"),this.focus(t,i))},_destroy:function(){var t=this.element.find(".ui-menu-item").removeAttr("role aria-disabled").children(".ui-menu-item-wrapper").removeUniqueId().removeAttr("tabIndex role aria-haspopup");this.element.removeAttr("aria-activedescendant").find(".ui-menu").addBack().removeAttr("role aria-labelledby aria-expanded aria-hidden aria-disabled tabIndex").removeUniqueId().show(),t.children().each(function(){var t=V(this);t.data("ui-menu-submenu-caret")&&t.remove()})},_keydown:function(t){var e,i,s,n=!0;switch(t.keyCode){case V.ui.keyCode.PAGE_UP:this.previousPage(t);break;case V.ui.keyCode.PAGE_DOWN:this.nextPage(t);break;case V.ui.keyCode.HOME:this._move("first","first",t);break;case V.ui.keyCode.END:this._move("last","last",t);break;case V.ui.keyCode.UP:this.previous(t);break;case V.ui.keyCode.DOWN:this.next(t);break;case V.ui.keyCode.LEFT:this.collapse(t);break;case V.ui.keyCode.RIGHT:this.active&&!this.active.is(".ui-state-disabled")&&this.expand(t);break;case V.ui.keyCode.ENTER:case V.ui.keyCode.SPACE:this._activate(t);break;case V.ui.keyCode.ESCAPE:this.collapse(t);break;default:e=this.previousFilter||"",s=n=!1,i=96<=t.keyCode&&t.keyCode<=105?(t.keyCode-96).toString():String.fromCharCode(t.keyCode),clearTimeout(this.filterTimer),i===e?s=!0:i=e+i,e=this._filterMenuItems(i),(e=s&&-1!==e.index(this.active.next())?this.active.nextAll(".ui-menu-item"):e).length||(i=String.fromCharCode(t.keyCode),e=this._filterMenuItems(i)),e.length?(this.focus(t,e),this.previousFilter=i,this.filterTimer=this._delay(function(){delete this.previousFilter},1e3)):delete this.previousFilter}n&&t.preventDefault()},_activate:function(t){this.active&&!this.active.is(".ui-state-disabled")&&(this.active.children("[aria-haspopup='true']").length?this.expand(t):this.select(t))},refresh:function(){var t,e,s=this,n=this.options.icons.submenu,i=this.element.find(this.options.menus);this._toggleClass("ui-menu-icons",null,!!this.element.find(".ui-icon").length),t=i.filter(":not(.ui-menu)").hide().attr({role:this.options.role,"aria-hidden":"true","aria-expanded":"false"}).each(function(){var t=V(this),e=t.prev(),i=V("").data("ui-menu-submenu-caret",!0);s._addClass(i,"ui-menu-icon","ui-icon "+n),e.attr("aria-haspopup","true").prepend(i),t.attr("aria-labelledby",e.attr("id"))}),this._addClass(t,"ui-menu","ui-widget ui-widget-content ui-front"),(t=i.add(this.element).find(this.options.items)).not(".ui-menu-item").each(function(){var t=V(this);s._isDivider(t)&&s._addClass(t,"ui-menu-divider","ui-widget-content")}),e=(i=t.not(".ui-menu-item, .ui-menu-divider")).children().not(".ui-menu").uniqueId().attr({tabIndex:-1,role:this._itemRole()}),this._addClass(i,"ui-menu-item")._addClass(e,"ui-menu-item-wrapper"),t.filter(".ui-state-disabled").attr("aria-disabled","true"),this.active&&!V.contains(this.element[0],this.active[0])&&this.blur()},_itemRole:function(){return{menu:"menuitem",listbox:"option"}[this.options.role]},_setOption:function(t,e){var i;"icons"===t&&(i=this.element.find(".ui-menu-icon"),this._removeClass(i,null,this.options.icons.submenu)._addClass(i,null,e.submenu)),this._super(t,e)},_setOptionDisabled:function(t){this._super(t),this.element.attr("aria-disabled",String(t)),this._toggleClass(null,"ui-state-disabled",!!t)},focus:function(t,e){var i;this.blur(t,t&&"focus"===t.type),this._scrollIntoView(e),this.active=e.first(),i=this.active.children(".ui-menu-item-wrapper"),this._addClass(i,null,"ui-state-active"),this.options.role&&this.element.attr("aria-activedescendant",i.attr("id")),i=this.active.parent().closest(".ui-menu-item").children(".ui-menu-item-wrapper"),this._addClass(i,null,"ui-state-active"),t&&"keydown"===t.type?this._close():this.timer=this._delay(function(){this._close()},this.delay),(i=e.children(".ui-menu")).length&&t&&/^mouse/.test(t.type)&&this._startOpening(i),this.activeMenu=e.parent(),this._trigger("focus",t,{item:e})},_scrollIntoView:function(t){var e,i,s;this._hasScroll()&&(e=parseFloat(V.css(this.activeMenu[0],"borderTopWidth"))||0,i=parseFloat(V.css(this.activeMenu[0],"paddingTop"))||0,e=t.offset().top-this.activeMenu.offset().top-e-i,i=this.activeMenu.scrollTop(),s=this.activeMenu.height(),t=t.outerHeight(),e<0?this.activeMenu.scrollTop(i+e):s",options:{appendTo:null,autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null,change:null,close:null,focus:null,open:null,response:null,search:null,select:null},requestIndex:0,pending:0,liveRegionTimer:null,_create:function(){var i,s,n,t=this.element[0].nodeName.toLowerCase(),e="textarea"===t,t="input"===t;this.isMultiLine=e||!t&&"true"===this.element.prop("contentEditable"),this.valueMethod=this.element[e||t?"val":"text"],this.isNewMenu=!0,this._addClass("ui-autocomplete-input"),this.element.attr("autocomplete","off"),this._on(this.element,{keydown:function(t){if(this.element.prop("readOnly"))s=n=i=!0;else{s=n=i=!1;var e=V.ui.keyCode;switch(t.keyCode){case e.PAGE_UP:i=!0,this._move("previousPage",t);break;case e.PAGE_DOWN:i=!0,this._move("nextPage",t);break;case e.UP:i=!0,this._keyEvent("previous",t);break;case e.DOWN:i=!0,this._keyEvent("next",t);break;case e.ENTER:this.menu.active&&(i=!0,t.preventDefault(),this.menu.select(t));break;case e.TAB:this.menu.active&&this.menu.select(t);break;case e.ESCAPE:this.menu.element.is(":visible")&&(this.isMultiLine||this._value(this.term),this.close(t),t.preventDefault());break;default:s=!0,this._searchTimeout(t)}}},keypress:function(t){if(i)i=!1,this.isMultiLine&&!this.menu.element.is(":visible")||t.preventDefault();else if(!s){var e=V.ui.keyCode;switch(t.keyCode){case e.PAGE_UP:this._move("previousPage",t);break;case e.PAGE_DOWN:this._move("nextPage",t);break;case e.UP:this._keyEvent("previous",t);break;case e.DOWN:this._keyEvent("next",t)}}},input:function(t){n?(n=!1,t.preventDefault()):this._searchTimeout(t)},focus:function(){this.selectedItem=null,this.previous=this._value()},blur:function(t){clearTimeout(this.searching),this.close(t),this._change(t)}}),this._initSource(),this.menu=V("