{"version":3,"sources":["garnish.js"],"names":["$","cancel","raf","erd","Base","extend","_instance","_static","prototype","_prototyping","proto","this","call","base","constructor","klass","_constructing","apply","arguments","ancestor","forEach","implement","toString","valueOf","type","init","source","value","length","test","method","previous","returnValue","toSource","hidden","i","key","desc","Object","getOwnPropertyDescriptor","defineProperty","version","object","block","context","undefined","String","Garnish","getErd","elementResizeDetectorMaker","callOnAdd","triggerResizeEvent","elem","trigger","$win","window","$doc","document","$bod","body","rtl","hasClass","ltr","$scrollContainer","DELETE_KEY","SHIFT_KEY","CTRL_KEY","ALT_KEY","RETURN_KEY","ESC_KEY","SPACE_KEY","LEFT_KEY","UP_KEY","RIGHT_KEY","DOWN_KEY","A_KEY","S_KEY","CMD_KEY","PRIMARY_CLICK","SECONDARY_CLICK","X_AXIS","Y_AXIS","FX_DURATION","TEXT_NODE","log","msg","console","_isMobileBrowser","_isMobileOrTabletBrowser","isMobileBrowser","detectTablets","a","navigator","userAgent","vendor","opera","RegExp","substr","isArray","val","Array","isJquery","jQuery","isString","hasAttr","attr","isTextNode","nodeType","getOffset","_offset","offset","top","scrollTop","left","scrollLeft","getDist","x1","y1","x2","y2","Math","sqrt","pow","hitTest","x","y","_$elem","_x1","_y1","_x2","outerWidth","_y2","outerHeight","isCursorOver","ev","pageX","pageY","copyTextStyles","target","$source","css","fontFamily","fontSize","fontWeight","letterSpacing","lineHeight","textAlign","textIndent","whiteSpace","wordSpacing","wordWrap","getBodyScrollTop","_scrollTop","_maxScrollTop","height","requestAnimationFrame","mozRequestAnimationFrame","webkitRequestAnimationFrame","fn","setTimeout","cancelAnimationFrame","mozCancelAnimationFrame","webkitCancelAnimationFrame","clearTimeout","id","scrollContainerToElement","container","$elem","$container","scrollParent","prop","elemScrollOffset","elemOffset","targetScrollTop","elemHeight","containerHeight","innerHeight","clientHeight","velocity","mobileHA","SHAKE_STEPS","SHAKE_STEP_DURATION","shake","startingPoint","parseInt","isNaN","_properties","getElement","makeArray","getInputBasename","name","replace","getInputPostVal","$input","findInputs","find","getPostData","inputName","postData","arrayInputCounters","$inputs","eq","inputVal","isArrayInput","croppedName","substring","j","copyInputValues","$sourceInputs","$targetInputs","isCtrlKeyPressed","platform","match","metaKey","ctrlKey","_eventHandlers","_normalizeEvents","events","split","on","data","handler","push","namespace","off","eventHandler","splice","settings","_namespace","_$listeners","_disabled","floor","random","_listeners","noop","setSettings","defaults","baseSettings","_ev","_splitEvents","trim","_formatEvents","slice","join","addListener","func","bind","proxy","inArray","removeListener","removeAllListeners","disable","enable","destroy","event","special","activate","setup","namespaces","eventHandle","mousedown.garnish-activate","e","preventDefault","click.garnish-activate","keydown.garnish-activate","keyCode","addClass","removeClass","removeAttr","teardown","textchange","handle","el","args","delay","handleObj","targetData","delayTimeout","resize","listenTo","each","BaseDrag","$items","dragging","mousedownX","mousedownY","realMouseX","realMouseY","mouseX","mouseY","mouseDistX","mouseDistY","mouseOffsetX","mouseOffsetY","$targetItem","scrollProperty","scrollAxis","scrollDist","scrollProxy","scrollFrame","_","items","isPlainObject","addItems","allowDragging","startDragging","onDragStart","drag","didMouseMove","_scrollProperty","axis","_winScrollTop","_minMouseScrollY","windowScrollTargetSize","_scrollAxis","_scrollDist","round","_maxMouseScrollY","_winScrollLeft","_minMouseScrollX","_maxMouseScrollX","width","_scrollWindow","_cancelWindowScroll","onDrag","stopDragging","onDragStop","item","removeItems","add","index","_deinitItem","removeAllItems","_handleMouseDown","which","$target","$handle","_getItemHandle","currentTarget","is","closest","ignoreHandleSelector","_handleMouseMove","_mouseDist","minMouseDist","_handleMouseUp","scrollPos","removeData","CheckboxSelect","$all","$options","$checkboxes","filter","not","onAllChange","isAllChecked","checked","disabled","ContextMenu","options","$menu","showingMenu","counter","buildMenu","menuClass","$ul","appendTo","hasOwnProperty","option","$li","$a","label","onClick","mousedown","hideMenu","showMenu","showing","show","hide","CustomSelect","visible","$anchor","menuId","_windowWidth","_windowHeight","_windowScrollLeft","_windowScrollTop","_anchorOffset","_anchorWidth","_anchorHeight","_anchorOffsetRight","_anchorOffsetBottom","_menuWidth","_menuHeight","addOptions","$menuList","role","aria-hidden","attachToElement","anchor","stopPropagation","nodeName","optionKey","tabindex","selectOption","setPositionRelativeToAnchor","topClearance","bottomClearance","maxHeight","windowSpacing","min","align","_alignCenter","rightClearance","leftClearance","_alignRight","_alignLeft","opacity","display","shortcutManager","addLayer","registerShortcut","duration","detach","removeLayer","onOptionSelect","selectedOption","right","Menu","DisclosureMenu","$trigger","$alignmentElement","$wrapper","_wrapperElementOffset","_alignmentElementOffset","_triggerWidth","_triggerHeight","triggerId","alignmentSelector","wrapper","addDisclosureMenuEventListeners","handleTriggerClick","handleKeypress","handleMousedown","focusElement","direction","newIndex","currentFocus","focusable","currentIndex","focus","newTarget","triggerButton","newTargetIsInsideDisclosure","has","isExpanded","setContainerPosition","firstFocusableEl","getBoundingClientRect","bottom","topAdjustment","bottomAdjustment","leftAdjustment","rightAdjustment","Drag","targetItemWidth","targetItemHeight","targetItemPositionInDraggee","$draggee","otherItems","totalOtherItems","helpers","helperTargets","helperPositions","helperLagIncrement","updateHelperPosProxy","updateHelperPosFrame","lastMouseX","lastMouseY","_returningHelpersToDraggees","draggeeDisplay","setDraggee","findDraggee","_updateHelperPos","helperLagIncrementDividend","concat","toArray","singleHelper","_createHelper","removeDraggee","collapseDraggees","appendDraggee","$newDraggee","oldLength","newLength","draggeeVirtualMidpointX","draggeeVirtualMidpointY","getHelperTargetX","getHelperTargetY","returnHelpersToDraggees","$helper","visibility","callback","draggeeOffset","_showDraggee","onReturnHelpersToDraggees","$draggeeHelper","clone","copyDraggeeInputValuesToHelper","ceil","margin","pointer-events","helper","append","helperPos","_getHelperTarget","position","zIndex","helperBaseZindex","helperOpacity","_i","_j","_lag","helperLagBase","helperSpacingX","helperSpacingY","remove","DragDrop","$dropTargets","$activeDropTarget","updateDropTargets","dropTargets","_activeDropTarget","_elem","activeDropTargetClass","onDropTargetChange","fadeOutHelpers","complete","DragMove","DragSort","$heightedContainer","$insertion","insertionVisible","oldDraggeeIndexes","newDraggeeIndexes","closestItem","_midpointVersion","_$prevItem","createInsertion","insertion","magnetStrength","_draggeeOffsetX","_draggeeOffsetY","canInsertBefore","$item","canInsertAfter","_getDraggeeIndexes","moveTargetItemToFront","_getItemIndex","first","insertBefore","_placeInsertionWithDraggee","_clearMidpoints","parent","_removeInsertion","_getClosestItem","_updateInsertion","insertAfter","onSortChange","onInsertionPointChange","indexes","_closestItem","_testForClosestItem","_midpoint","_getItemMidpoint","_startXDist","_lastXDist","abs","_startYDist","_lastYDist","_$otherItem","prev","_xDist","_yDist","last","next","_repositionDraggee","get","_moveDraggeeToItem","_$item","prependTo","_mouseDistX","_mouseDistY","_closestItemMouseDistY","_closestItemMouseDistX","EscManager","handlers","escapeLatest","register","obj","unregister","pop","escManager","HUD","$fixedTriggerParent","$hud","$tip","$body","$header","$footer","$mainContainer","$main","$shade","orientation","updatingSizeAndPosition","windowWidth","windowHeight","mainWidth","mainHeight","bodyContents","onShow","onHide","onSubmit","activeHUDs","class","shadeClass","hudClass","tipClass","bodyClass","mainContainerClass","mainClass","updateBody","$parent","offsetParent","hideOnShadeClick","closeBtn","html","headerClass","footerClass","closeOtherHUDs","hudID","hideOnEsc","updateRecords","updateSizeAndPosition","changed","force","updateSizeAndPositionInternal","triggerWidth","triggerHeight","triggerOffset","windowScrollLeft","windowScrollTop","scrollContainerTriggerOffset","scrollContainerScrollLeft","scrollContainerScrollTop","hudBodyWidth","hudBodyHeight","overflow-x","overflow-y","maxHudBodyWidth","maxHudBodyHeight","triggerCenter","clearances","orientations","relevantSize","triggerSpacing","tipClasses","minBodyWidth","minBodyHeight","maxLeft","minLeft","tipLeft","tipWidth","maxTop","minTop","tipTop","toggle","submit","_handleSubmit","MenuBtn","$btn","menu","btn","menuAnchor","aria-controls","aria-haspopup","aria-expanded","onMenuHide","onBlur","contains","activeElement","onKeyDown","$option","$currentOption","click","focusOption","onMouseDown","MixedInput","elements","focussedElement","blurTimeout","getElementIndex","isText","onFocus","setFocus","setCarotPos","addTextElement","text","TextElement","addElement","focussedElementIndex","selectionStart","selectionEnd","preVal","postVal","newText","removeElement","$prevElem","$nextElem","prevElemVal","newVal","blurFocussedElement","focusPreviousElement","$from","focusNextElement","pos","parentInput","$stage","focussed","interval","padding","setWidth","getIndex","buildStage","getTextWidth","stageWidth","setInterval","checkInput","NiceText","clearInterval","getVal","setVal","onChange","Modal","dragger","desiredWidth","desiredHeight","resizeDragger","resizeStartWidth","resizeStartHeight","setContainer","autoShow","instances","draggable","dragHandleSelector","resizable","$resizeDragHandle","_handleResizeStart","_handleResize","closeOtherModals","visibleModal","onFadeIn","quickShow","onFadeOut","quickHide","max","min-width","min-height","_width","getWidth","minGutter","_height","getHeight","_handleWindowResize","relativeElemPadding","$hint","$charsLeft","autoHeight","maxLength","showCharsLeft","showingHint","inputBoxSizing","minHeight","initialized","input","isVisible","initialize","getHeightForValue","updateHeight","hint","$hintContainer","charsLeftClass","updateCharsLeft","initializeIfVisible","showHint","hintFadeDuration","hideHint","onTextChange","border-top","border-right","border-bottom","border-left","padding-top","padding-right","padding-bottom","padding-left","-webkit-box-sizing","-moz-box-sizing","box-sizing","spaces","onHeightChange","updateHeightIfWidthChanged","_charsLeft","charsLeftHtml","negativeCharsLeftClass","charsLeft","Select","$selectedItems","$focusedItem","mousedownTarget","mouseUpTimeout","callbackFrame","$focusable","$first","$last","allowEmpty","checkboxMode","ignoreClick","deselectAll","getItemIndex","isSelected","selectItem","preventScroll","multi","setFocusableItem","focusItem","_selectItems","selectAll","selectRange","sliceFrom","sliceTo","deselectItem","_deselectItems","clearFirst","deselectOthers","toggleItem","_canDeselect","clearMouseUpTimeout","getFirstItem","getLastItem","isPreviousItem","isNextItem","getPreviousItem","getNextItem","getItemToTheLeft","horizontal","vertical","getClosestItem","getItemToTheRight","getItemAbove","getItemBelow","dir","step","axisProps","closestItemAxisProps","dirProps","closestItemDirectionProps","$thisItem","thisOffset","thisMidpoint","midpointOffset","midpointSizeFunc","otherRowPos","smallestMidpointDiff","$closestItem","$otherItem","otherOffset","isNextRow","rowOffset","otherMidpoint","midpointDiff","isWrongDirection","getFurthestItemToTheLeft","getFurthestItem","getFurthestItemToTheRight","getFurthestItemAbove","getFurthestItemBelow","$testItem","totalSelected","getTotalSelected","updateIndexes","itemsChanged","selectionChanged","selectedIndex","selectedClass","onSelectionChange","resetItemOrder","getSelectedItems","shiftKey","_actAsCheckbox","onMouseUp","<","b",">","SelectMenu","selected","build","_addSelectedOptionClass","select","dom","ul","className","setBtnText","$btnLabel","ulClass","ShortcutManager","shortcuts","layer","shortcut","_normalizeShortcut","JSON","stringify","unregisterShortcut","ctrl","shift","alt","triggerShortcut","altKey"],"mappings":"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","file":"garnish.js","sourcesContent":["/**\n * Garnish UI toolkit\n *\n * @copyright 2013 Pixel & Tonic, Inc.. All rights reserved.\n * @author    Brandon Kelly <brandon@pixelandtonic.com>\n * @version   0.1.47\n * @license   MIT\n */\n(function($){\n\n/*!\r\n\tBase.js, version 1.1a\r\n\tCopyright 2006-2010, Dean Edwards\r\n\tLicense: http://www.opensource.org/licenses/mit-license.php\r\n*/\r\n\r\nvar Base = function() {\r\n\t// dummy\r\n};\r\n\r\nBase.extend = function(_instance, _static) { // subclass\r\n\tvar extend = Base.prototype.extend;\r\n\r\n\t// build the prototype\r\n\tBase._prototyping = true;\r\n\tvar proto = new this;\r\n\textend.call(proto, _instance);\r\n\tproto.base = function() {\r\n\t\t// call this method from any other method to invoke that method's ancestor\r\n\t};\r\n\tdelete Base._prototyping;\r\n\r\n\t// create the wrapper for the constructor function\r\n\t//var constructor = proto.constructor.valueOf(); //-dean\r\n\tvar constructor = proto.constructor;\r\n\tvar klass = proto.constructor = function() {\r\n\t\tif (!Base._prototyping) {\r\n\t\t\tif (this._constructing || this.constructor == klass) { // instantiation\r\n\t\t\t\tthis._constructing = true;\r\n\t\t\t\tconstructor.apply(this, arguments);\r\n\t\t\t\tdelete this._constructing;\r\n\t\t\t} else if (arguments[0] != null) { // casting\r\n\t\t\t\treturn (arguments[0].extend || extend).call(arguments[0], proto);\r\n\t\t\t}\r\n\t\t}\r\n\t};\r\n\r\n\t// build the class interface\r\n\tklass.ancestor = this;\r\n\tklass.extend = this.extend;\r\n\tklass.forEach = this.forEach;\r\n\tklass.implement = this.implement;\r\n\tklass.prototype = proto;\r\n\tklass.toString = this.toString;\r\n\tklass.valueOf = function(type) {\r\n\t\t//return (type == \"object\") ? klass : constructor; //-dean\r\n\t\treturn (type == \"object\") ? klass : constructor.valueOf();\r\n\t};\r\n\textend.call(klass, _static);\r\n\t// class initialisation\r\n\tif (typeof klass.init == \"function\") klass.init();\r\n\treturn klass;\r\n};\r\n\r\nBase.prototype = {\r\n\textend: function(source, value) {\r\n\t\tif (arguments.length > 1) { // extending with a name/value pair\r\n\t\t\tvar ancestor = this[source];\r\n\t\t\tif (ancestor && (typeof value == \"function\") && // overriding a method?\r\n\t\t\t\t// the valueOf() comparison is to avoid circular references\r\n\t\t\t\t(!ancestor.valueOf || ancestor.valueOf() != value.valueOf()) &&\r\n\t\t\t\t/\\bbase\\b/.test(value)) {\r\n\t\t\t\t// get the underlying method\r\n\t\t\t\tvar method = value.valueOf();\r\n\t\t\t\t// override\r\n\t\t\t\tvalue = function() {\r\n\t\t\t\t\tvar previous = this.base || Base.prototype.base;\r\n\t\t\t\t\tthis.base = ancestor;\r\n\t\t\t\t\tvar returnValue = method.apply(this, arguments);\r\n\t\t\t\t\tthis.base = previous;\r\n\t\t\t\t\treturn returnValue;\r\n\t\t\t\t};\r\n\t\t\t\t// point to the underlying method\r\n\t\t\t\tvalue.valueOf = function(type) {\r\n\t\t\t\t\treturn (type == \"object\") ? value : method;\r\n\t\t\t\t};\r\n\t\t\t\tvalue.toString = Base.toString;\r\n\t\t\t}\r\n\t\t\tthis[source] = value;\r\n\t\t} else if (source) { // extending with an object literal\r\n\t\t\tvar extend = Base.prototype.extend;\r\n\t\t\t// if this object has a customised extend method then use it\r\n\t\t\tif (!Base._prototyping && typeof this != \"function\") {\r\n\t\t\t\textend = this.extend || extend;\r\n\t\t\t}\r\n\t\t\tvar proto = {toSource: null};\r\n\t\t\t// do the \"toString\" and other methods manually\r\n\t\t\tvar hidden = [\"constructor\", \"toString\", \"valueOf\"];\r\n\t\t\t// if we are prototyping then include the constructor\r\n\t\t\tvar i = Base._prototyping ? 0 : 1;\r\n\t\t\twhile (key = hidden[i++]) {\r\n\t\t\t\tif (source[key] != proto[key]) {\r\n\t\t\t\t\textend.call(this, key, source[key]);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t// copy each of the source object's properties to this object\r\n\t\t\tfor (var key in source) {\r\n\t\t\t\tif (!proto[key]) {\r\n\t\t\t\t\tvar desc = Object.getOwnPropertyDescriptor(source, key);\r\n\t\t\t\t\tif (typeof desc.value != typeof undefined) {\r\n\t\t\t\t\t\t// set the value normally in case it's a function that needs to be overwritten\r\n\t\t\t\t\t\textend.call(this, key, desc.value);\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\t// set it while maintaining the original descriptor settings\r\n\t\t\t\t\t\tObject.defineProperty(this, key, desc);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn this;\r\n\t}\r\n};\r\n\r\n// initialise\r\nBase = Base.extend({\r\n\tconstructor: function() {\r\n\t\tthis.extend(arguments[0]);\r\n\t}\r\n}, {\r\n\tancestor: Object,\r\n\tversion: \"1.1\",\r\n\r\n\tforEach: function(object, block, context) {\r\n\t\tfor (var key in object) {\r\n\t\t\tif (this.prototype[key] === undefined) {\r\n\t\t\t\tblock.call(context, object[key], key, object);\r\n\t\t\t}\r\n\t\t}\r\n\t},\r\n\r\n\timplement: function() {\r\n\t\tfor (var i = 0; i < arguments.length; i++) {\r\n\t\t\tif (typeof arguments[i] == \"function\") {\r\n\t\t\t\t// if it's a function, call it\r\n\t\t\t\targuments[i](this.prototype);\r\n\t\t\t} else {\r\n\t\t\t\t// add the interface using the extend method\r\n\t\t\t\tthis.prototype.extend(arguments[i]);\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\ttoString: function() {\r\n\t\treturn String(this.valueOf());\r\n\t}\r\n});\r\n\n/**\n * @namespace Garnish\n */\n\n// Bail if Garnish is already defined\nif (typeof Garnish !== 'undefined') {\n    throw 'Garnish is already defined!';\n}\n\nGarnish = {\n\n    // jQuery objects for common elements\n    $win: $(window),\n    $doc: $(document),\n    $bod: $(document.body)\n\n};\n\nGarnish.rtl = Garnish.$bod.hasClass('rtl');\nGarnish.ltr = !Garnish.rtl;\n\nGarnish = $.extend(Garnish, {\n\n    $scrollContainer: Garnish.$win,\n\n    // Key code constants\n    DELETE_KEY: 8,\n    SHIFT_KEY: 16,\n    CTRL_KEY: 17,\n    ALT_KEY: 18,\n    RETURN_KEY: 13,\n    ESC_KEY: 27,\n    SPACE_KEY: 32,\n    LEFT_KEY: 37,\n    UP_KEY: 38,\n    RIGHT_KEY: 39,\n    DOWN_KEY: 40,\n    A_KEY: 65,\n    S_KEY: 83,\n    CMD_KEY: 91,\n\n    // Mouse button constants\n    PRIMARY_CLICK: 1,\n    SECONDARY_CLICK: 3,\n\n    // Axis constants\n    X_AXIS: 'x',\n    Y_AXIS: 'y',\n\n    FX_DURATION: 100,\n\n    // Node types\n    TEXT_NODE: 3,\n\n    /**\n     * Logs a message to the browser's console, if the browser has one.\n     *\n     * @param {string} msg\n     */\n    log: function(msg) {\n        if (typeof console !== 'undefined' && typeof console.log === 'function') {\n            console.log(msg);\n        }\n    },\n\n    _isMobileBrowser: null,\n    _isMobileOrTabletBrowser: null,\n\n    /**\n     * Returns whether this is a mobile browser.\n     * Detection script courtesy of http://detectmobilebrowsers.com\n     *\n     * Last updated: 2014-11-24\n     *\n     * @param {boolean} detectTablets\n     * @return {boolean}\n     */\n    isMobileBrowser: function(detectTablets) {\n        var key = detectTablets ? '_isMobileOrTabletBrowser' : '_isMobileBrowser';\n\n        if (Garnish[key] === null) {\n            var a = navigator.userAgent || navigator.vendor || window.opera;\n            Garnish[key] = ((new RegExp('(android|bb\\d+|meego).+mobile|avantgo|bada\\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\\.(browser|link)|vodafone|wap|windows ce|xda|xiino' + (detectTablets ? '|android|ipad|playbook|silk' : ''), 'i')).test(a) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\\-(n|u)|c55\\/|capi|ccwa|cdm\\-|cell|chtm|cldc|cmd\\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\\-s|devi|dica|dmob|do(c|p)o|ds(12|\\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\\-|_)|g1 u|g560|gene|gf\\-5|g\\-mo|go(\\.w|od)|gr(ad|un)|haie|hcit|hd\\-(m|p|t)|hei\\-|hi(pt|ta)|hp( i|ip)|hs\\-c|ht(c(\\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\\-(20|go|ma)|i230|iac( |\\-|\\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\\/)|klon|kpt |kwc\\-|kyo(c|k)|le(no|xi)|lg( g|\\/(k|l|u)|50|54|\\-[a-w])|libw|lynx|m1\\-w|m3ga|m50\\/|ma(te|ui|xo)|mc(01|21|ca)|m\\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\\-2|po(ck|rt|se)|prox|psio|pt\\-g|qa\\-a|qc(07|12|21|32|60|\\-[2-7]|i\\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\\-|oo|p\\-)|sdk\\/|se(c(\\-|0|1)|47|mc|nd|ri)|sgh\\-|shar|sie(\\-|m)|sk\\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\\-|v\\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\\-|tdg\\-|tel(i|m)|tim\\-|t\\-mo|to(pl|sh)|ts(70|m\\-|m3|m5)|tx\\-9|up(\\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\\-|your|zeto|zte\\-/i.test(a.substr(0, 4)));\n        }\n\n        return Garnish[key];\n    },\n\n    /**\n     * Returns whether a variable is an array.\n     *\n     * @param {object} val\n     * @return {boolean}\n     */\n    isArray: function(val) {\n        return (val instanceof Array);\n    },\n\n    /**\n     * Returns whether a variable is a jQuery collection.\n     *\n     * @param {object} val\n     * @return {boolean}\n     */\n    isJquery: function(val) {\n        return (val instanceof jQuery);\n    },\n\n    /**\n     * Returns whether a variable is a string.\n     *\n     * @param {object} val\n     * @return {boolean}\n     */\n    isString: function(val) {\n        return (typeof val === 'string');\n    },\n\n    /**\n     * Returns whether an element has an attribute.\n     *\n     * @see http://stackoverflow.com/questions/1318076/jquery-hasattr-checking-to-see-if-there-is-an-attribute-on-an-element/1318091#1318091\n     */\n    hasAttr: function(elem, attr) {\n        var val = $(elem).attr(attr);\n        return (typeof val !== 'undefined' && val !== false);\n    },\n\n    /**\n     * Returns whether something is a text node.\n     *\n     * @param {object} elem\n     * @return {boolean}\n     */\n    isTextNode: function(elem) {\n        return (elem.nodeType === Garnish.TEXT_NODE);\n    },\n\n    /**\n     * Returns the offset of an element within the scroll container, whether that's the window or something else\n     */\n    getOffset: function(elem) {\n        this.getOffset._offset = $(elem).offset();\n\n        if (Garnish.$scrollContainer[0] !== Garnish.$win[0]) {\n            this.getOffset._offset.top += Garnish.$scrollContainer.scrollTop();\n            this.getOffset._offset.left += Garnish.$scrollContainer.scrollLeft();\n        }\n\n        return this.getOffset._offset;\n    },\n\n    /**\n     * Returns the distance between two coordinates.\n     *\n     * @param {number} x1 The first coordinate's X position.\n     * @param {number} y1 The first coordinate's Y position.\n     * @param {number} x2 The second coordinate's X position.\n     * @param {number} y2 The second coordinate's Y position.\n     * @return {number}\n     */\n    getDist: function(x1, y1, x2, y2) {\n        return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));\n    },\n\n    /**\n     * Returns whether an element is touching an x/y coordinate.\n     *\n     * @param {number}    x    The coordinate's X position.\n     * @param {number}    y    The coordinate's Y position.\n     * @param {object} elem Either an actual element or a jQuery collection.\n     * @return {boolean}\n     */\n    hitTest: function(x, y, elem) {\n        Garnish.hitTest._$elem = $(elem);\n        Garnish.hitTest._offset = Garnish.hitTest._$elem.offset();\n        Garnish.hitTest._x1 = Garnish.hitTest._offset.left;\n        Garnish.hitTest._y1 = Garnish.hitTest._offset.top;\n        Garnish.hitTest._x2 = Garnish.hitTest._x1 + Garnish.hitTest._$elem.outerWidth();\n        Garnish.hitTest._y2 = Garnish.hitTest._y1 + Garnish.hitTest._$elem.outerHeight();\n\n        return (x >= Garnish.hitTest._x1 && x < Garnish.hitTest._x2 && y >= Garnish.hitTest._y1 && y < Garnish.hitTest._y2);\n    },\n\n    /**\n     * Returns whether the cursor is touching an element.\n     *\n     * @param {object} ev   The mouse event object containing pageX and pageY properties.\n     * @param {object} elem Either an actual element or a jQuery collection.\n     * @return {boolean}\n     */\n    isCursorOver: function(ev, elem) {\n        return Garnish.hitTest(ev.pageX, ev.pageY, elem);\n    },\n\n    /**\n     * Copies text styles from one element to another.\n     *\n     * @param {object} source The source element. Can be either an actual element or a jQuery collection.\n     * @param {object} target The target element. Can be either an actual element or a jQuery collection.\n     */\n    copyTextStyles: function(source, target) {\n        var $source = $(source),\n            $target = $(target);\n\n        $target.css({\n            fontFamily: $source.css('fontFamily'),\n            fontSize: $source.css('fontSize'),\n            fontWeight: $source.css('fontWeight'),\n            letterSpacing: $source.css('letterSpacing'),\n            lineHeight: $source.css('lineHeight'),\n            textAlign: $source.css('textAlign'),\n            textIndent: $source.css('textIndent'),\n            whiteSpace: $source.css('whiteSpace'),\n            wordSpacing: $source.css('wordSpacing'),\n            wordWrap: $source.css('wordWrap')\n        });\n    },\n\n    /**\n     * Returns the body's real scrollTop, discarding any window banding in Safari.\n     *\n     * @return {number}\n     */\n    getBodyScrollTop: function() {\n        Garnish.getBodyScrollTop._scrollTop = document.body.scrollTop;\n\n        if (Garnish.getBodyScrollTop._scrollTop < 0) {\n            Garnish.getBodyScrollTop._scrollTop = 0;\n        }\n        else {\n            Garnish.getBodyScrollTop._maxScrollTop = Garnish.$bod.outerHeight() - Garnish.$win.height();\n\n            if (Garnish.getBodyScrollTop._scrollTop > Garnish.getBodyScrollTop._maxScrollTop) {\n                Garnish.getBodyScrollTop._scrollTop = Garnish.getBodyScrollTop._maxScrollTop;\n            }\n        }\n\n        return Garnish.getBodyScrollTop._scrollTop;\n    },\n\n    requestAnimationFrame: (function() {\n            var raf = (\n                window.requestAnimationFrame ||\n                window.mozRequestAnimationFrame ||\n                window.webkitRequestAnimationFrame ||\n                function(fn) {\n                    return window.setTimeout(fn, 20);\n                }\n            );\n\n            return function(fn) {\n                return raf(fn);\n            };\n        })(),\n\n    cancelAnimationFrame: (function() {\n            var cancel = (\n                window.cancelAnimationFrame ||\n                window.mozCancelAnimationFrame ||\n                window.webkitCancelAnimationFrame ||\n                window.clearTimeout\n            );\n\n            return function(id) {\n                return cancel(id);\n            };\n        })(),\n\n    /**\n     * Scrolls a container element to an element within it.\n     *\n     * @param {object} container Either an actual element or a jQuery collection.\n     * @param {object} elem      Either an actual element or a jQuery collection.\n     */\n    scrollContainerToElement: function(container, elem) {\n        var $elem;\n\n        if (typeof elem === 'undefined') {\n            $elem = $(container);\n            $container = $elem.scrollParent();\n        }\n        else {\n            var $container = $(container);\n            $elem = $(elem);\n        }\n\n        if ($container.prop('nodeName') === 'HTML' || $container[0] === Garnish.$doc[0]) {\n            $container = Garnish.$win;\n        }\n\n        var scrollTop = $container.scrollTop(),\n            elemOffset = $elem.offset().top;\n\n        var elemScrollOffset;\n\n        if ($container[0] === window) {\n            elemScrollOffset = elemOffset - scrollTop;\n        }\n        else {\n            elemScrollOffset = elemOffset - $container.offset().top;\n        }\n\n        var targetScrollTop = false;\n\n        // Is the element above the fold?\n        if (elemScrollOffset < 0) {\n            targetScrollTop = scrollTop + elemScrollOffset - 10;\n        }\n        else {\n            var elemHeight = $elem.outerHeight(),\n                containerHeight = ($container[0] === window ? window.innerHeight : $container[0].clientHeight);\n\n            // Is it below the fold?\n            if (elemScrollOffset + elemHeight > containerHeight) {\n                targetScrollTop = scrollTop + (elemScrollOffset - (containerHeight - elemHeight)) + 10;\n            }\n        }\n\n        if (targetScrollTop !== false) {\n            // Velocity only allows you to scroll to an arbitrary position if you're scrolling the main window\n            if ($container[0] === window) {\n                $('html').velocity('scroll', {\n                    offset: targetScrollTop + 'px',\n                    mobileHA: false\n                });\n            }\n            else {\n                $container.scrollTop(targetScrollTop);\n            }\n        }\n    },\n\n    SHAKE_STEPS: 10,\n    SHAKE_STEP_DURATION: 25,\n\n    /**\n     * Shakes an element.\n     *\n     * @param {object}  elem Either an actual element or a jQuery collection.\n     * @param {string} prop The property that should be adjusted (default is 'margin-left').\n     */\n    shake: function(elem, prop) {\n        var $elem = $(elem);\n\n        if (!prop) {\n            prop = 'margin-left';\n        }\n\n        var startingPoint = parseInt($elem.css(prop));\n        if (isNaN(startingPoint)) {\n            startingPoint = 0;\n        }\n\n        for (var i = 0; i <= Garnish.SHAKE_STEPS; i++) {\n            (function(i) {\n                setTimeout(function() {\n                    Garnish.shake._properties = {};\n                    Garnish.shake._properties[prop] = startingPoint + (i % 2 ? -1 : 1) * (10 - i);\n                    $elem.velocity(Garnish.shake._properties, Garnish.SHAKE_STEP_DURATION);\n                }, (Garnish.SHAKE_STEP_DURATION * i));\n            })(i);\n        }\n    },\n\n    /**\n     * Returns the first element in an array or jQuery collection.\n     *\n     * @param {object} elem\n     * @return mixed\n     */\n    getElement: function(elem) {\n        return $.makeArray(elem)[0];\n    },\n\n    /**\n     * Returns the beginning of an input's name= attribute value with any [bracktes] stripped out.\n     *\n     * @param {object} elem\n     * @return string|null\n     */\n    getInputBasename: function(elem) {\n        var name = $(elem).attr('name');\n\n        if (name) {\n            return name.replace(/\\[.*/, '');\n        }\n        else {\n            return null;\n        }\n    },\n\n    /**\n     * Returns an input's value as it would be POSTed.\n     * So unchecked checkboxes and radio buttons return null,\n     * and multi-selects whose name don't end in \"[]\" only return the last selection\n     *\n     * @param {object} $input\n     * @return {(string|string[])}\n     */\n    getInputPostVal: function($input) {\n        var type = $input.attr('type'),\n            val = $input.val();\n\n        // Is this an unchecked checkbox or radio button?\n        if ((type === 'checkbox' || type === 'radio')) {\n            if ($input.prop('checked')) {\n                return val;\n            }\n            else {\n                return null;\n            }\n        }\n\n        // Flatten any array values whose input name doesn't end in \"[]\"\n        //  - e.g. a multi-select\n        else if (Garnish.isArray(val) && $input.attr('name').substr(-2) !== '[]') {\n            if (val.length) {\n                return val[val.length - 1];\n            }\n            else {\n                return null;\n            }\n        }\n\n        // Just return the value\n        else {\n            return val;\n        }\n    },\n\n    /**\n     * Returns the inputs within a container\n     *\n     * @param {object} container The container element. Can be either an actual element or a jQuery collection.\n     * @return {object}\n     */\n    findInputs: function(container) {\n        return $(container).find('input,text,textarea,select,button');\n    },\n\n    /**\n     * Returns the post data within a container.\n     *\n     * @param {object} container\n     * @return {array}\n     */\n    getPostData: function(container) {\n        var postData = {},\n            arrayInputCounters = {},\n            $inputs = Garnish.findInputs(container);\n\n        var inputName;\n\n        for (var i = 0; i < $inputs.length; i++) {\n            var $input = $inputs.eq(i);\n\n            if ($input.prop('disabled')) {\n                continue;\n            }\n\n            inputName = $input.attr('name');\n            if (!inputName) {\n                continue;\n            }\n\n            var inputVal = Garnish.getInputPostVal($input);\n            if (inputVal === null) {\n                continue;\n            }\n\n            var isArrayInput = (inputName.substr(-2) === '[]');\n\n            if (isArrayInput) {\n                // Get the cropped input name\n                var croppedName = inputName.substring(0, inputName.length - 2);\n\n                // Prep the input counter\n                if (typeof arrayInputCounters[croppedName] === 'undefined') {\n                    arrayInputCounters[croppedName] = 0;\n                }\n            }\n\n            if (!Garnish.isArray(inputVal)) {\n                inputVal = [inputVal];\n            }\n\n            for (var j = 0; j < inputVal.length; j++) {\n                if (isArrayInput) {\n                    inputName = croppedName + '[' + arrayInputCounters[croppedName] + ']';\n                    arrayInputCounters[croppedName]++;\n                }\n\n                postData[inputName] = inputVal[j];\n            }\n        }\n\n        return postData;\n    },\n\n    copyInputValues: function(source, target) {\n        var $sourceInputs = Garnish.findInputs(source),\n            $targetInputs = Garnish.findInputs(target);\n\n        for (var i = 0; i < $sourceInputs.length; i++) {\n            if (typeof $targetInputs[i] === 'undefined') {\n                break;\n            }\n\n            $targetInputs.eq(i).val(\n                $sourceInputs.eq(i).val()\n            );\n        }\n    },\n\n    /**\n     * Returns whether the \"Ctrl\" key is pressed (or ⌘ if this is a Mac) for a given keyboard event\n     *\n     * @param ev The keyboard event\n     *\n     * @return {boolean} Whether the \"Ctrl\" key is pressed\n     */\n    isCtrlKeyPressed: function(ev) {\n        if (window.navigator.platform.match(/Mac/)) {\n            // metaKey maps to ⌘ on Macs\n            return ev.metaKey;\n        }\n        return ev.ctrlKey;\n    },\n\n    _eventHandlers: [],\n\n    _normalizeEvents: function(events) {\n        if (typeof events === 'string') {\n            events = events.split(' ');\n        }\n\n        for (var i = 0; i < events.length; i++) {\n            if (typeof events[i] === 'string') {\n                events[i] = events[i].split('.');\n            }\n        }\n\n        return events;\n    },\n\n    on: function(target, events, data, handler) {\n        if (typeof data === 'function') {\n            handler = data;\n            data = {};\n        }\n\n        events = this._normalizeEvents(events);\n\n        for (var i = 0; i < events.length; i++) {\n            var ev = events[i];\n            this._eventHandlers.push({\n                target: target,\n                type: ev[0],\n                namespace: ev[1],\n                data: data,\n                handler: handler\n            });\n        }\n    },\n\n    off: function(target, events, handler) {\n        events = this._normalizeEvents(events);\n\n        for (var i = 0; i < events.length; i++) {\n            var ev = events[i];\n\n            for (var j = this._eventHandlers.length - 1; j >= 0; j--) {\n                var eventHandler = this._eventHandlers[j];\n\n                if (\n                    eventHandler.target === target &&\n                    eventHandler.type === ev[0] &&\n                    (!ev[1] || eventHandler.namespace === ev[1]) &&\n                    eventHandler.handler === handler\n                ) {\n                    this._eventHandlers.splice(j, 1);\n                }\n            }\n        }\n    }\n});\n\n\n/**\n * Garnish base class\n */\nGarnish.Base = Base.extend({\n\n    settings: null,\n\n    _eventHandlers: null,\n    _namespace: null,\n    _$listeners: null,\n    _disabled: false,\n\n    constructor: function() {\n        this._eventHandlers = [];\n        this._namespace = '.Garnish' + Math.floor(Math.random() * 1000000000);\n        this._listeners = [];\n        this.init.apply(this, arguments);\n    },\n\n    init: $.noop,\n\n    setSettings: function(settings, defaults) {\n        var baseSettings = (typeof this.settings === 'undefined' ? {} : this.settings);\n        this.settings = $.extend({}, baseSettings, defaults, settings);\n    },\n\n    on: function(events, data, handler) {\n        if (typeof data === 'function') {\n            handler = data;\n            data = {};\n        }\n\n        events = Garnish._normalizeEvents(events);\n\n        for (var i = 0; i < events.length; i++) {\n            var ev = events[i];\n            this._eventHandlers.push({\n                type: ev[0],\n                namespace: ev[1],\n                data: data,\n                handler: handler\n            });\n        }\n    },\n\n    off: function(events, handler) {\n        events = Garnish._normalizeEvents(events);\n\n        for (var i = 0; i < events.length; i++) {\n            var ev = events[i];\n\n            for (var j = this._eventHandlers.length - 1; j >= 0; j--) {\n                var eventHandler = this._eventHandlers[j];\n\n                if (\n                    eventHandler.type === ev[0] &&\n                    (!ev[1] || eventHandler.namespace === ev[1]) &&\n                    eventHandler.handler === handler\n                ) {\n                    this._eventHandlers.splice(j, 1);\n                }\n            }\n        }\n    },\n\n    trigger: function(type, data) {\n        var ev = {\n            type: type,\n            target: this\n        };\n\n        // instance level event handlers\n        var i, handler, _ev;\n        for (i = 0; i < this._eventHandlers.length; i++) {\n            handler = this._eventHandlers[i];\n\n            if (handler.type === type) {\n                _ev = $.extend({data: handler.data}, data, ev);\n                handler.handler(_ev);\n            }\n        }\n\n        // class level event handlers\n        for (i = 0; i < Garnish._eventHandlers.length; i++) {\n            handler = Garnish._eventHandlers[i];\n\n            if (this instanceof handler.target && handler.type === type) {\n                _ev = $.extend({data: handler.data}, data, ev);\n                handler.handler(_ev);\n            }\n        }\n    },\n\n    _splitEvents: function(events) {\n        if (typeof events === 'string') {\n            events = events.split(',');\n\n            for (var i = 0; i < events.length; i++) {\n                events[i] = $.trim(events[i]);\n            }\n        }\n\n        return events;\n    },\n\n    _formatEvents: function(events) {\n        events = this._splitEvents(events).slice(0);\n\n        for (var i = 0; i < events.length; i++) {\n            events[i] += this._namespace;\n        }\n\n        return events.join(' ');\n    },\n\n    addListener: function(elem, events, data, func) {\n        var $elem = $(elem);\n\n        // Ignore if there aren't any elements\n        if (!$elem.length) {\n            return;\n        }\n\n        events = this._splitEvents(events);\n\n        // Param mapping\n        if (typeof func === 'undefined' && typeof data !== 'object') {\n            // (elem, events, func)\n            func = data;\n            data = {};\n        }\n\n        if (typeof func === 'function') {\n            func = func.bind(this);\n        }\n        else {\n            func = this[func].bind(this);\n        }\n\n        $elem.on(this._formatEvents(events), data, $.proxy(function() {\n            if (!this._disabled) {\n                return func.apply(this, arguments);\n            }\n        }, this));\n\n        // Remember that we're listening to this element\n        if ($.inArray(elem, this._listeners) === -1) {\n            this._listeners.push(elem);\n        }\n    },\n\n    removeListener: function(elem, events) {\n        $(elem).off(this._formatEvents(events));\n    },\n\n    removeAllListeners: function(elem) {\n        $(elem).off(this._namespace);\n    },\n\n    disable: function() {\n        this._disabled = true;\n    },\n\n    enable: function() {\n        this._disabled = false;\n    },\n\n    destroy: function() {\n        this.trigger('destroy');\n        this.removeAllListeners(this._listeners);\n    }\n});\n\n// Custom events\n// -----------------------------------------------------------------------------\n\nvar erd;\n\nfunction getErd() {\n    if (typeof erd === 'undefined') {\n        erd = elementResizeDetectorMaker({\n            callOnAdd: false\n        });\n    }\n\n    return erd;\n}\n\nfunction triggerResizeEvent(elem) {\n    $(elem).trigger('resize');\n}\n\n// Work them into jQuery's event system\n$.extend(jQuery.event.special, {\n    activate: {\n        setup: function(data, namespaces, eventHandle) {\n            var activateNamespace = this._namespace + '-activate';\n            var $elem = $(this);\n\n            $elem.on({\n                'mousedown.garnish-activate': function(e) {\n                    // Prevent buttons from getting focus on click\n                    e.preventDefault();\n                },\n                'click.garnish-activate': function(e) {\n                    e.preventDefault();\n\n                    if (!$elem.hasClass('disabled')) {\n                        $elem.trigger('activate');\n                    }\n                },\n                'keydown.garnish-activate': function(e) {\n                    // Ignore if the event was bubbled up, or if it wasn't the space key\n                    if (this !== $elem[0] || e.keyCode !== Garnish.SPACE_KEY) {\n                        return;\n                    }\n\n                    e.preventDefault();\n\n                    if (!$elem.hasClass('disabled')) {\n                        $elem.addClass('active');\n\n                        Garnish.$doc.on('keyup.garnish-activate', function(e) {\n                            $elem.removeClass('active');\n\n                            if (e.keyCode === Garnish.SPACE_KEY) {\n                                e.preventDefault();\n                                $elem.trigger('activate');\n                            }\n\n                            Garnish.$doc.off('keyup.garnish-activate');\n                        });\n                    }\n                }\n            });\n\n            if (!$elem.hasClass('disabled')) {\n                $elem.attr('tabindex', '0');\n            } else {\n                $elem.removeAttr('tabindex');\n            }\n        },\n        teardown: function() {\n            $(this).off('.garnish-activate');\n        }\n    },\n\n    textchange: {\n        setup: function(data, namespaces, eventHandle) {\n            var $elem = $(this);\n            $elem.data('garnish-textchange-value', $elem.val());\n            $elem.on('keypress.garnish-textchange keyup.garnish-textchange change.garnish-textchange blur.garnish-textchange', function(e) {\n                var val = $elem.val();\n                if (val !== $elem.data('garnish-textchange-value')) {\n                    $elem.data('garnish-textchange-value', val);\n                    $elem.trigger('textchange');\n                }\n            });\n        },\n        teardown: function() {\n            $(this).off('.garnish-textchange');\n        },\n        handle: function(ev, data) {\n            var el = this;\n            var args = arguments;\n            var delay = data && typeof data.delay !== 'undefined' ? data.delay : (ev.data && ev.data.delay !== undefined ? ev.data.delay : null);\n            var handleObj = ev.handleObj;\n            var targetData = $.data(ev.target);\n\n            // Was this event configured with a delay?\n            if (delay) {\n                if (targetData.delayTimeout) {\n                    clearTimeout(targetData.delayTimeout);\n                }\n\n                targetData.delayTimeout = setTimeout(function() {\n                    handleObj.handler.apply(el, args);\n                }, delay);\n            } else {\n                return handleObj.handler.apply(el, args);\n            }\n        }\n    },\n\n    resize: {\n        setup: function(data, namespaces, eventHandle) {\n            // window is the only element that natively supports a resize event\n            if (this === window) {\n                return false;\n            }\n\n            $('> :last-child', this).addClass('last');\n            getErd().listenTo(this, triggerResizeEvent)\n        },\n        teardown: function() {\n            if (this === window) {\n                return false;\n            }\n\n            getErd().removeListener(this, triggerResizeEvent);\n        }\n    }\n});\n\n// Give them their own element collection chaining methods\njQuery.each(['activate', 'textchange', 'resize'], function(i, name) {\n    jQuery.fn[name] = function(data, fn) {\n        return arguments.length > 0 ?\n            this.on(name, null, data, fn) :\n            this.trigger(name);\n    };\n});\n\n/** global: Garnish */\n/**\n * Base drag class\n *\n * Does all the grunt work for manipulating elements via click-and-drag,\n * while leaving the actual element manipulation up to a subclass.\n */\nGarnish.BaseDrag = Garnish.Base.extend(\n    {\n        $items: null,\n\n        dragging: false,\n\n        mousedownX: null,\n        mousedownY: null,\n        realMouseX: null,\n        realMouseY: null,\n        mouseX: null,\n        mouseY: null,\n        mouseDistX: null,\n        mouseDistY: null,\n        mouseOffsetX: null,\n        mouseOffsetY: null,\n\n        $targetItem: null,\n\n        scrollProperty: null,\n        scrollAxis: null,\n        scrollDist: null,\n        scrollProxy: null,\n        scrollFrame: null,\n\n        _: null,\n\n        /**\n         * Constructor\n         *\n         * @param {object} items    Elements that should be draggable right away. (Can be skipped.)\n         * @param {object} settings Any settings that should override the defaults.\n         */\n        init: function(items, settings) {\n            // Param mapping\n            if (typeof settings === 'undefined' && $.isPlainObject(items)) {\n                // (settings)\n                settings = items;\n                items = null;\n            }\n\n            this.settings = $.extend({}, Garnish.BaseDrag.defaults, settings);\n\n            this.$items = $();\n            this._ = {};\n\n            if (items) {\n                this.addItems(items);\n            }\n        },\n\n        /**\n         * Returns whether dragging is allowed right now.\n         */\n        allowDragging: function() {\n            return true;\n        },\n\n        /**\n         * Start Dragging\n         */\n        startDragging: function() {\n            this.dragging = true;\n            this.onDragStart();\n        },\n\n        /**\n         * Drag\n         */\n        drag: function(didMouseMove) {\n            if (didMouseMove) {\n                // Is the mouse up against one of the window edges?\n                this.drag._scrollProperty = null;\n\n                if (this.settings.axis !== Garnish.X_AXIS) {\n                    // Scrolling up?\n                    this.drag._winScrollTop = Garnish.$win.scrollTop();\n                    this.drag._minMouseScrollY = this.drag._winScrollTop + Garnish.BaseDrag.windowScrollTargetSize;\n\n                    if (this.mouseY < this.drag._minMouseScrollY) {\n                        this.drag._scrollProperty = 'scrollTop';\n                        this.drag._scrollAxis = 'Y';\n                        this.drag._scrollDist = Math.round((this.mouseY - this.drag._minMouseScrollY) / 2);\n                    }\n                    else {\n                        // Scrolling down?\n                        this.drag._maxMouseScrollY = this.drag._winScrollTop + Garnish.$win.height() - Garnish.BaseDrag.windowScrollTargetSize;\n\n                        if (this.mouseY > this.drag._maxMouseScrollY) {\n                            this.drag._scrollProperty = 'scrollTop';\n                            this.drag._scrollAxis = 'Y';\n                            this.drag._scrollDist = Math.round((this.mouseY - this.drag._maxMouseScrollY) / 2);\n                        }\n                    }\n                }\n\n                if (!this.drag._scrollProperty && this.settings.axis !== Garnish.Y_AXIS) {\n                    // Scrolling left?\n                    this.drag._winScrollLeft = Garnish.$win.scrollLeft();\n                    this.drag._minMouseScrollX = this.drag._winScrollLeft + Garnish.BaseDrag.windowScrollTargetSize;\n\n                    if (this.mouseX < this.drag._minMouseScrollX) {\n                        this.drag._scrollProperty = 'scrollLeft';\n                        this.drag._scrollAxis = 'X';\n                        this.drag._scrollDist = Math.round((this.mouseX - this.drag._minMouseScrollX) / 2);\n                    }\n                    else {\n                        // Scrolling right?\n                        this.drag._maxMouseScrollX = this.drag._winScrollLeft + Garnish.$win.width() - Garnish.BaseDrag.windowScrollTargetSize;\n\n                        if (this.mouseX > this.drag._maxMouseScrollX) {\n                            this.drag._scrollProperty = 'scrollLeft';\n                            this.drag._scrollAxis = 'X';\n                            this.drag._scrollDist = Math.round((this.mouseX - this.drag._maxMouseScrollX) / 2);\n                        }\n                    }\n                }\n\n                if (this.drag._scrollProperty) {\n                    // Are we starting to scroll now?\n                    if (!this.scrollProperty) {\n                        if (!this.scrollProxy) {\n                            this.scrollProxy = this._scrollWindow.bind(this);\n                        }\n\n                        if (this.scrollFrame) {\n                            Garnish.cancelAnimationFrame(this.scrollFrame);\n                            this.scrollFrame = null;\n                        }\n\n                        this.scrollFrame = Garnish.requestAnimationFrame(this.scrollProxy);\n                    }\n\n                    this.scrollProperty = this.drag._scrollProperty;\n                    this.scrollAxis = this.drag._scrollAxis;\n                    this.scrollDist = this.drag._scrollDist;\n                }\n                else {\n                    this._cancelWindowScroll();\n                }\n            }\n\n            this.onDrag();\n        },\n\n        /**\n         * Stop Dragging\n         */\n        stopDragging: function() {\n            this.dragging = false;\n            this.onDragStop();\n\n            // Clear the scroll animation\n            this._cancelWindowScroll();\n        },\n\n        /**\n         * Add Items\n         *\n         * @param {object} items Elements that should be draggable.\n         */\n        addItems: function(items) {\n            items = $.makeArray(items);\n\n            for (var i = 0; i < items.length; i++) {\n                var item = items[i];\n\n                // Make sure this element doesn't belong to another dragger\n                if ($.data(item, 'drag')) {\n                    Garnish.log('Element was added to more than one dragger');\n                    $.data(item, 'drag').removeItems(item);\n                }\n\n                // Add the item\n                $.data(item, 'drag', this);\n\n                // Add the listener\n                this.addListener(item, 'mousedown', '_handleMouseDown');\n            }\n\n            this.$items = this.$items.add(items);\n        },\n\n        /**\n         * Remove Items\n         *\n         * @param {object} items Elements that should no longer be draggable.\n         */\n        removeItems: function(items) {\n            items = $.makeArray(items);\n\n            for (var i = 0; i < items.length; i++) {\n                var item = items[i];\n\n                // Make sure we actually know about this item\n                var index = $.inArray(item, this.$items);\n                if (index !== -1) {\n                    this._deinitItem(item);\n                    this.$items.splice(index, 1);\n                }\n            }\n        },\n\n        /**\n         * Remove All Items\n         */\n        removeAllItems: function() {\n            for (var i = 0; i < this.$items.length; i++) {\n                this._deinitItem(this.$items[i]);\n            }\n\n            this.$items = $();\n        },\n\n        /**\n         * Destroy\n         */\n        destroy: function() {\n            this.removeAllItems();\n            this.base();\n        },\n\n        // Events\n        // ---------------------------------------------------------------------\n\n        /**\n         * On Drag Start\n         */\n        onDragStart: function() {\n            Garnish.requestAnimationFrame(function() {\n                this.trigger('dragStart');\n                this.settings.onDragStart();\n            }.bind(this));\n        },\n\n        /**\n         * On Drag\n         */\n        onDrag: function() {\n            Garnish.requestAnimationFrame(function() {\n                this.trigger('drag');\n                this.settings.onDrag();\n            }.bind(this));\n        },\n\n        /**\n         * On Drag Stop\n         */\n        onDragStop: function() {\n            Garnish.requestAnimationFrame(function() {\n                this.trigger('dragStop');\n                this.settings.onDragStop();\n            }.bind(this));\n        },\n\n        // Private methods\n        // ---------------------------------------------------------------------\n\n        /**\n         * Handle Mouse Down\n         */\n        _handleMouseDown: function(ev) {\n            // Ignore right clicks\n            if (ev.which !== Garnish.PRIMARY_CLICK) {\n                return;\n            }\n\n            // Ignore if we already have a target\n            if (this.$targetItem) {\n                return;\n            }\n\n            // Ignore if they didn't actually click on the handle\n            var $target = $(ev.target),\n                $handle = this._getItemHandle(ev.currentTarget);\n\n            if (!$target.is($handle) && !$target.closest($handle).length) {\n                return;\n            }\n\n            // Make sure the target isn't a button (unless the button is the handle)\n            if (ev.currentTarget !== ev.target && this.settings.ignoreHandleSelector) {\n                if (\n                    $target.is(this.settings.ignoreHandleSelector) ||\n                    $target.closest(this.settings.ignoreHandleSelector).length\n                ) {\n                    return;\n                }\n            }\n\n            ev.preventDefault();\n\n            // Make sure that dragging is allowed right now\n            if (!this.allowDragging()) {\n                return;\n            }\n\n            // Capture the target\n            this.$targetItem = $(ev.currentTarget);\n\n            // Capture the current mouse position\n            this.mousedownX = this.mouseX = ev.pageX;\n            this.mousedownY = this.mouseY = ev.pageY;\n\n            // Capture the difference between the mouse position and the target item's offset\n            var offset = this.$targetItem.offset();\n            this.mouseOffsetX = ev.pageX - offset.left;\n            this.mouseOffsetY = ev.pageY - offset.top;\n\n            // Listen for mousemove, mouseup\n            this.addListener(Garnish.$doc, 'mousemove', '_handleMouseMove');\n            this.addListener(Garnish.$doc, 'mouseup', '_handleMouseUp');\n        },\n\n        _getItemHandle: function(item) {\n            if (this.settings.handle) {\n                if (typeof this.settings.handle === 'object') {\n                    return $(this.settings.handle);\n                }\n\n                if (typeof this.settings.handle === 'string') {\n                    return $(this.settings.handle, item);\n                }\n\n                if (typeof this.settings.handle === 'function') {\n                    return $(this.settings.handle(item));\n                }\n            }\n\n            return $(item);\n        },\n\n        /**\n         * Handle Mouse Move\n         */\n        _handleMouseMove: function(ev) {\n            ev.preventDefault();\n\n            this.realMouseX = ev.pageX;\n            this.realMouseY = ev.pageY;\n\n            if (this.settings.axis !== Garnish.Y_AXIS) {\n                this.mouseX = ev.pageX;\n            }\n\n            if (this.settings.axis !== Garnish.X_AXIS) {\n                this.mouseY = ev.pageY;\n            }\n\n            this.mouseDistX = this.mouseX - this.mousedownX;\n            this.mouseDistY = this.mouseY - this.mousedownY;\n\n            if (!this.dragging) {\n                // Has the mouse moved far enough to initiate dragging yet?\n                this._handleMouseMove._mouseDist = Garnish.getDist(this.mousedownX, this.mousedownY, this.realMouseX, this.realMouseY);\n\n                if (this._handleMouseMove._mouseDist >= Garnish.BaseDrag.minMouseDist) {\n                    this.startDragging();\n                }\n            }\n\n            if (this.dragging) {\n                this.drag(true);\n            }\n        },\n\n        /**\n         * Handle Moues Up\n         */\n        _handleMouseUp: function(ev) {\n            // Unbind the document events\n            this.removeAllListeners(Garnish.$doc);\n\n            if (this.dragging) {\n                this.stopDragging();\n            }\n\n            this.$targetItem = null;\n        },\n\n        /**\n         * Scroll Window\n         */\n        _scrollWindow: function() {\n            this._.scrollPos = Garnish.$scrollContainer[this.scrollProperty]();\n            Garnish.$scrollContainer[this.scrollProperty](this._.scrollPos + this.scrollDist);\n\n            this['mouse' + this.scrollAxis] -= this._.scrollPos - Garnish.$scrollContainer[this.scrollProperty]();\n            this['realMouse' + this.scrollAxis] = this['mouse' + this.scrollAxis];\n\n            this.drag();\n\n            this.scrollFrame = Garnish.requestAnimationFrame(this.scrollProxy);\n        },\n\n        /**\n         * Cancel Window Scroll\n         */\n        _cancelWindowScroll: function() {\n            if (this.scrollFrame) {\n                Garnish.cancelAnimationFrame(this.scrollFrame);\n                this.scrollFrame = null;\n            }\n\n            this.scrollProperty = null;\n            this.scrollAxis = null;\n            this.scrollDist = null;\n        },\n\n        /**\n         * Deinitialize an item.\n         */\n        _deinitItem: function(item) {\n            this.removeAllListeners(item);\n            $.removeData(item, 'drag');\n        }\n    },\n    {\n        minMouseDist: 1,\n        windowScrollTargetSize: 25,\n\n        defaults: {\n            handle: null,\n            axis: null,\n            ignoreHandleSelector: 'input, textarea, button, select, .btn',\n\n            onDragStart: $.noop,\n            onDrag: $.noop,\n            onDragStop: $.noop\n        }\n    }\n);\n\n/** global: Garnish */\n/**\n * Checkbox select class\n */\nGarnish.CheckboxSelect = Garnish.Base.extend(\n    {\n        $container: null,\n        $all: null,\n        $options: null,\n\n        init: function(container) {\n            this.$container = $(container);\n\n            // Is this already a checkbox select?\n            if (this.$container.data('checkboxSelect')) {\n                Garnish.log('Double-instantiating a checkbox select on an element');\n                this.$container.data('checkbox-select').destroy();\n            }\n\n            this.$container.data('checkboxSelect', this);\n\n            var $checkboxes = this.$container.find('input');\n            this.$all = $checkboxes.filter('.all:first');\n            this.$options = $checkboxes.not(this.$all);\n\n            this.addListener(this.$all, 'change', 'onAllChange');\n        },\n\n        onAllChange: function() {\n            var isAllChecked = this.$all.prop('checked');\n\n            this.$options.prop({\n                checked: isAllChecked,\n                disabled: isAllChecked\n            });\n        },\n\n        /**\n         * Destroy\n         */\n        destroy: function() {\n            this.$container.removeData('checkboxSelect');\n            this.base();\n        }\n    }\n);\n\n/** global: Garnish */\n/**\n * Context Menu\n */\nGarnish.ContextMenu = Garnish.Base.extend(\n    {\n        $target: null,\n        options: null,\n        $menu: null,\n        showingMenu: false,\n\n        /**\n         * Constructor\n         */\n        init: function(target, options, settings) {\n            this.$target = $(target);\n\n            // Is this already a context menu target?\n            if (this.$target.data('contextmenu')) {\n                Garnish.log('Double-instantiating a context menu on an element');\n                this.$target.data('contextmenu').destroy();\n            }\n\n            this.$target.data('contextmenu', this);\n\n            this.options = options;\n            this.setSettings(settings, Garnish.ContextMenu.defaults);\n\n            Garnish.ContextMenu.counter++;\n\n            this.enable();\n        },\n\n        /**\n         * Build Menu\n         */\n        buildMenu: function() {\n            this.$menu = $('<div class=\"' + this.settings.menuClass + '\" style=\"display: none\" />');\n\n            var $ul = $('<ul/>').appendTo(this.$menu);\n\n            for (var i in this.options) {\n                if (!this.options.hasOwnProperty(i)) {\n                    continue;\n                }\n\n                var option = this.options[i];\n\n                if (option === '-') {\n                    // Create a new <ul>\n                    $('<hr/>').appendTo(this.$menu);\n                    $ul = $('<ul/>').appendTo(this.$menu);\n                }\n                else {\n                    var $li = $('<li></li>').appendTo($ul),\n                        $a = $('<a>' + option.label + '</a>').appendTo($li);\n\n                    if (typeof option.onClick === 'function') {\n                        // maintain the current $a and options.onClick variables\n                        (function($a, onClick) {\n                            setTimeout(function() {\n                                $a.mousedown(function(ev) {\n                                    this.hideMenu();\n                                    // call the onClick callback, with the scope set to the item,\n                                    // and pass it the event with currentTarget set to the item as well\n                                    onClick.call(this.currentTarget, $.extend(ev, {currentTarget: this.currentTarget}));\n                                }.bind(this));\n                            }.bind(this), 1);\n                        }).call(this, $a, option.onClick);\n                    }\n                }\n            }\n        },\n\n        /**\n         * Show Menu\n         */\n        showMenu: function(ev) {\n            // Ignore left mouse clicks\n            if (ev.type === 'mousedown' && ev.which !== Garnish.SECONDARY_CLICK) {\n                return;\n            }\n\n            if (ev.type === 'contextmenu') {\n                // Prevent the real context menu from showing\n                ev.preventDefault();\n            }\n\n            // Ignore if already showing\n            if (this.showing && ev.currentTarget === this.currentTarget) {\n                return;\n            }\n\n            this.currentTarget = ev.currentTarget;\n\n            if (!this.$menu) {\n                this.buildMenu();\n            }\n\n            this.$menu.appendTo(document.body);\n            this.$menu.show();\n            this.$menu.css({left: ev.pageX + 1, top: ev.pageY - 4});\n\n            this.showing = true;\n\n            setTimeout(function() {\n                this.addListener(Garnish.$doc, 'mousedown', 'hideMenu');\n            }.bind(this), 0);\n        },\n\n        /**\n         * Hide Menu\n         */\n        hideMenu: function() {\n            this.removeListener(Garnish.$doc, 'mousedown');\n            this.$menu.hide();\n            this.showing = false;\n        },\n\n        /**\n         * Enable\n         */\n        enable: function() {\n            this.addListener(this.$target, 'contextmenu,mousedown', 'showMenu');\n        },\n\n        /**\n         * Disable\n         */\n        disable: function() {\n            this.removeListener(this.$target, 'contextmenu,mousedown');\n        },\n\n        /**\n         * Destroy\n         */\n        destroy: function() {\n            this.$target.removeData('contextmenu');\n            this.base();\n        }\n    },\n    {\n        defaults: {\n            menuClass: 'menu'\n        },\n        counter: 0\n    }\n);\n\n/** global: Garnish */\n/**\n * Custom Select Menu\n */\nGarnish.CustomSelect = Garnish.Base.extend(\n  {\n    settings: null,\n    visible: false,\n\n    $container: null,\n    $options: null,\n    $anchor: null,\n\n    menuId: null,\n\n    _windowWidth: null,\n    _windowHeight: null,\n    _windowScrollLeft: null,\n    _windowScrollTop: null,\n\n    _anchorOffset: null,\n    _anchorWidth: null,\n    _anchorHeight: null,\n    _anchorOffsetRight: null,\n    _anchorOffsetBottom: null,\n\n    _menuWidth: null,\n    _menuHeight: null,\n\n    /**\n     * Constructor\n     */\n    init: function (container, settings) {\n      this.setSettings(settings, Garnish.CustomSelect.defaults);\n\n      this.$container = $(container);\n\n      this.$options = $();\n      this.addOptions(this.$container.find('a'));\n\n      // Menu List\n      this.menuId = 'menu' + this._namespace;\n      this.$menuList = $('ul', this.$container);\n      this.$menuList.attr({\n        role: 'listbox',\n        id: this.menuId,\n        'aria-hidden': 'true',\n      });\n\n      // Deprecated\n      if (this.settings.attachToElement) {\n        this.settings.anchor = this.settings.attachToElement;\n        Garnish.log(\n          \"The 'attachToElement' setting is deprecated. Use 'anchor' instead.\"\n        );\n      }\n\n      if (this.settings.anchor) {\n        this.$anchor = $(this.settings.anchor);\n      }\n\n      // Prevent clicking on the container from hiding the menu\n      this.addListener(this.$container, 'mousedown', function (ev) {\n        ev.stopPropagation();\n\n        if (ev.target.nodeName !== 'INPUT') {\n          // Prevent this from causing the menu button to blur\n          ev.preventDefault();\n        }\n      });\n    },\n\n    addOptions: function ($options) {\n      this.$options = this.$options.add($options);\n      $options.data('menu', this);\n\n      $options.each(\n        function (optionKey, option) {\n          $(option).attr({\n            role: 'option',\n            tabindex: '-1',\n            id: this.menuId + '-option-' + optionKey,\n          });\n        }.bind(this)\n      );\n\n      this.removeAllListeners($options);\n      this.addListener($options, 'click', function (ev) {\n        this.selectOption(ev.currentTarget);\n      });\n    },\n\n    setPositionRelativeToAnchor: function () {\n      this._windowWidth = Garnish.$win.width();\n      this._windowHeight = Garnish.$win.height();\n      this._windowScrollLeft = Garnish.$win.scrollLeft();\n      this._windowScrollTop = Garnish.$win.scrollTop();\n\n      this._anchorOffset = this.$anchor.offset();\n      this._anchorWidth = this.$anchor.outerWidth();\n      this._anchorHeight = this.$anchor.outerHeight();\n      this._anchorOffsetRight = this._anchorOffset.left + this._anchorHeight;\n      this._anchorOffsetBottom = this._anchorOffset.top + this._anchorHeight;\n\n      this.$container.css('minWidth', 0);\n      this.$container.css(\n        'minWidth',\n        this._anchorWidth -\n          (this.$container.outerWidth() - this.$container.width())\n      );\n\n      this._menuWidth = this.$container.outerWidth();\n      this._menuHeight = this.$container.outerHeight();\n\n      // Is there room for the menu below the anchor?\n      var topClearance = this._anchorOffset.top - this._windowScrollTop,\n        bottomClearance =\n          this._windowHeight + this._windowScrollTop - this._anchorOffsetBottom;\n\n      if (\n        bottomClearance >= this._menuHeight ||\n        (topClearance < this._menuHeight && bottomClearance >= topClearance)\n      ) {\n        this.$container.css({\n          top: this._anchorOffsetBottom,\n          maxHeight: bottomClearance - this.settings.windowSpacing,\n        });\n      } else {\n        this.$container.css({\n          top:\n            this._anchorOffset.top -\n            Math.min(\n              this._menuHeight,\n              topClearance - this.settings.windowSpacing\n            ),\n          maxHeight: topClearance - this.settings.windowSpacing,\n        });\n      }\n\n      // Figure out how we're aliging it\n      var align = this.$container.data('align');\n\n      if (align !== 'left' && align !== 'center' && align !== 'right') {\n        align = 'left';\n      }\n\n      if (align === 'center') {\n        this._alignCenter();\n      } else {\n        // Figure out which options are actually possible\n        var rightClearance =\n            this._windowWidth +\n            this._windowScrollLeft -\n            (this._anchorOffset.left + this._menuWidth),\n          leftClearance = this._anchorOffsetRight - this._menuWidth;\n\n        if ((align === 'right' && leftClearance >= 0) || rightClearance < 0) {\n          this._alignRight();\n        } else {\n          this._alignLeft();\n        }\n      }\n\n      delete this._windowWidth;\n      delete this._windowHeight;\n      delete this._windowScrollLeft;\n      delete this._windowScrollTop;\n      delete this._anchorOffset;\n      delete this._anchorWidth;\n      delete this._anchorHeight;\n      delete this._anchorOffsetRight;\n      delete this._anchorOffsetBottom;\n      delete this._menuWidth;\n      delete this._menuHeight;\n    },\n\n    show: function () {\n      if (this.visible) {\n        return;\n      }\n\n      // Move the menu to the end of the DOM\n      this.$container.appendTo(Garnish.$bod);\n\n      if (this.$anchor) {\n        this.setPositionRelativeToAnchor();\n      }\n\n      this.$container.velocity('stop');\n      this.$container.css({\n        opacity: 1,\n        display: 'block',\n      });\n\n      this.$menuList.attr('aria-hidden', 'false');\n\n      Garnish.shortcutManager\n        .addLayer()\n        .registerShortcut(Garnish.ESC_KEY, this.hide.bind(this));\n\n      this.addListener(\n        Garnish.$scrollContainer,\n        'scroll',\n        'setPositionRelativeToAnchor'\n      );\n\n      this.visible = true;\n      this.trigger('show');\n    },\n\n    hide: function () {\n      if (!this.visible) {\n        return;\n      }\n\n      this.$menuList.attr('aria-hidden', 'true');\n\n      this.$container.velocity(\n        'fadeOut',\n        { duration: Garnish.FX_DURATION },\n        function () {\n          this.$container.detach();\n        }.bind(this)\n      );\n\n      Garnish.shortcutManager.removeLayer();\n      this.removeListener(Garnish.$scrollContainer, 'scroll');\n      this.visible = false;\n      this.trigger('hide');\n    },\n\n    selectOption: function (option) {\n      this.settings.onOptionSelect(option);\n      this.trigger('optionselect', { selectedOption: option });\n      this.hide();\n    },\n\n    _alignLeft: function () {\n      this.$container.css({\n        left: this._anchorOffset.left,\n        right: 'auto',\n      });\n    },\n\n    _alignRight: function () {\n      this.$container.css({\n        right:\n          this._windowWidth - (this._anchorOffset.left + this._anchorWidth),\n        left: 'auto',\n      });\n    },\n\n    _alignCenter: function () {\n      var left = Math.round(\n        this._anchorOffset.left + this._anchorWidth / 2 - this._menuWidth / 2\n      );\n\n      if (left < 0) {\n        left = 0;\n      }\n\n      this.$container.css('left', left);\n    },\n  },\n  {\n    defaults: {\n      anchor: null,\n      windowSpacing: 5,\n      onOptionSelect: $.noop,\n    },\n  }\n);\n\n/**\n * @deprecated\n */\nGarnish.Menu = Garnish.CustomSelect;\n\n/** global: Garnish */\n/**\n * Disclosure Widget\n */\nGarnish.DisclosureMenu = Garnish.Base.extend(\n  {\n    settings: null,\n\n    $trigger: null,\n    $container: null,\n    $alignmentElement: null,\n    $wrapper: null,\n\n    _windowWidth: null,\n    _windowHeight: null,\n    _windowScrollLeft: null,\n    _windowScrollTop: null,\n\n    _wrapperElementOffset: null,\n    _alignmentElementOffset: null,\n    _triggerWidth: null,\n    _triggerHeight: null,\n\n    _menuWidth: null,\n    _menuHeight: null,\n\n    /**\n     * Constructor\n     */\n    init: function (trigger, settings) {\n      this.setSettings(settings, Garnish.DisclosureMenu.defaults);\n\n      this.$trigger = $(trigger);\n      var triggerId = this.$trigger.attr('aria-controls');\n      this.$container = $(\"#\" + triggerId);\n\n      if (!this.$container) return; /* Exit if no disclosure container is found */\n\n      // Get and store expanded state from trigger\n      var expanded = this.$trigger.attr('aria-expanded');\n\n      // If no expanded state exists on trigger, add for a11y\n      if (!expanded) {\n        this.$trigger.attr('aria-expanded', 'false');\n      }\n\n      // Capture additional alignment element\n      var alignmentSelector = this.$container.data('align-to');\n      if (alignmentSelector) {\n        this.$alignmentElement = $(alignmentSelector);\n      } else {\n        this.$alignmentElement = this.$trigger;\n      }\n\n      var wrapper = this.$container.closest('[data-wrapper]');\n      if (wrapper) {\n        this.$wrapper = wrapper;\n      }\n\n      this.addDisclosureMenuEventListeners();\n    },\n\n    addDisclosureMenuEventListeners: function() {\n      this.addListener(this.$trigger, 'click', function() {\n        this.handleTriggerClick();\n      });\n\n      this.addListener(this.$container, 'keydown', function(event) {\n        this.handleKeypress(event);\n      });\n\n      this.addListener(Garnish.$doc, 'mousedown', this.handleMousedown)\n    },\n\n    focusElement: function(direction) {\n      var currentFocus = $(':focus');\n\n      var focusable = this.$container.find(':focusable');\n\n      var currentIndex = focusable.index(currentFocus);\n      var newIndex;\n\n      if (direction === 'prev') {\n        newIndex = currentIndex - 1;\n      } else {\n        newIndex = currentIndex + 1;\n      }\n\n      if (newIndex >= 0 && newIndex < focusable.length) {\n        var elementToFocus = focusable[newIndex];\n        elementToFocus.focus();\n      }\n    },\n\n    handleMousedown: function (event) {\n      var newTarget = event.target;\n      var triggerButton = $(newTarget).closest('[data-disclosure-trigger]');\n      var newTargetIsInsideDisclosure = this.$container.has(newTarget).length > 0;\n\n      // If click target matches trigger element or disclosure child, do nothing\n      if ($(triggerButton).is(this.$trigger) || newTargetIsInsideDisclosure) {\n        return;\n      }\n\n      this.hide();\n    },\n\n    handleKeypress: function(event) {\n      var keyCode = event.keyCode;\n      \n      switch (keyCode) {\n        case Garnish.ESC_KEY:\n          this.hide();\n          this.$trigger.focus();\n          break;\n        case Garnish.RIGHT_KEY:\n        case Garnish.DOWN_KEY:\n          event.preventDefault();\n          this.focusElement('next');\n          break;\n        case Garnish.LEFT_KEY:\n        case Garnish.UP_KEY:\n          event.preventDefault();\n          this.focusElement('prev');\n          break;\n        default:\n          break;\n      }\n    },\n\n    isExpanded: function () {\n      var isExpanded = this.$trigger.attr('aria-expanded');\n\n      return isExpanded === 'true';\n    },\n\n    handleTriggerClick: function() {\n      if (!this.isExpanded()) {\n        this.show();\n      } else {\n        this.hide();\n      }\n    },\n\n    show: function () {\n      if (this.isExpanded()) {\n        return;\n      }\n\n      this.setContainerPosition();\n      this.addListener(\n        Garnish.$scrollContainer,\n        'scroll',\n        'setContainerPosition'\n      );\n      \n      this.$container.velocity('stop');\n      this.$container.css({\n        opacity: 1,\n        display: 'block',\n      });\n\n      \n      // Set ARIA attribute for expanded\n      this.$trigger.attr('aria-expanded', 'true');\n\n      // Focus first focusable element\n      var firstFocusableEl = this.$container.find(':focusable')[0];\n      if (firstFocusableEl) {\n        firstFocusableEl.focus();\n      } else {\n        this.$container.attr('tabindex', '-1');\n        this.$container.focus();\n      }\n    },\n\n    hide: function () {\n      if (!this.isExpanded()) {\n        return;\n      }\n\n      this.$container.velocity(\n        'fadeOut',\n        { duration: Garnish.FX_DURATION }\n      );\n\n      this.$trigger.attr('aria-expanded', 'false');\n    },\n\n    setContainerPosition: function () {\n      this._windowWidth = Garnish.$win.width();\n      this._windowHeight = Garnish.$win.height();\n      this._windowScrollLeft = Garnish.$win.scrollLeft();\n      this._windowScrollTop = Garnish.$win.scrollTop();\n\n      this._alignmentElementOffset = this.$alignmentElement[0].getBoundingClientRect();\n\n      this._wrapperElementOffset = this.$wrapper[0].getBoundingClientRect();\n\n      this._triggerWidth = this.$trigger.outerWidth();\n\n      this.$container.css('minWidth', 0);\n      this.$container.css(\n        'minWidth',\n        this._triggerWidth -\n          (this.$container.outerWidth() - this.$container.width())\n      );\n\n      this._menuWidth = this.$container.outerWidth();\n      this._menuHeight = this.$container.outerHeight();\n\n      // Is there room for the menu below the trigger?\n      var topClearance = this._alignmentElementOffset.top,\n        bottomClearance = this._windowHeight - this._alignmentElementOffset.bottom;\n\n      // Find top/bottom offset relative to wrapper element\n      var topAdjustment = this._alignmentElementOffset.top - this._wrapperElementOffset.top;\n      var bottomAdjustment = this._alignmentElementOffset.bottom - this._wrapperElementOffset.bottom;\n\n      var bottomClearanceExists = \n        bottomClearance >= this._menuHeight ||\n        (topClearance < this._menuHeight && bottomClearance >= topClearance);\n      \n      if (bottomClearanceExists) {\n        this.$container.css({\n          top: 'calc(100% + ' + bottomAdjustment + 'px)',\n          bottom: 'unset',\n          maxHeight: bottomClearance - this.settings.windowSpacing,\n        });\n      } else {\n        this.$container.css({\n          bottom: 'calc(100% - ' + topAdjustment + 'px)',\n          top: 'unset',\n          maxHeight: topClearance - this.settings.windowSpacing,\n        });\n      }\n\n      // Figure out how we're aliging it\n      var align = this.$container.data('align');\n\n      if (align !== 'left' && align !== 'center' && align !== 'right') {\n        align = 'left';\n      }\n\n      if (align === 'center') {\n        this._alignCenter();\n      } else {\n        // Figure out which options are actually possible\n        var rightClearance =\n            this._windowWidth +\n            this._windowScrollLeft -\n            (this._alignmentElementOffset.left + this._menuWidth),\n          leftClearance = this._alignmentElementOffset.right - this._menuWidth;\n\n        if ((align === 'right' && leftClearance >= 0) || rightClearance < 0) {\n          this._alignRight();\n        } else {\n          this._alignLeft();\n        }\n      }\n\n      delete this._windowWidth;\n      delete this._windowHeight;\n      delete this._windowScrollLeft;\n      delete this._windowScrollTop;\n      delete this._wrapperElementOffset;\n      delete this._alignmentElementOffset;\n      delete this._triggerWidth;\n      delete this._triggerHeight;\n      delete this._menuWidth;\n      delete this._menuHeight;\n    },\n\n    _alignLeft: function () {\n      var leftAdjustment = this._alignmentElementOffset.left - this._wrapperElementOffset.left;\n\n      this.$container.css({\n        right: 'unset',\n        left: leftAdjustment + 'px',\n      });\n    },\n\n    _alignRight: function () {\n      var rightAdjustment = this._alignmentElementOffset.right - this._wrapperElementOffset.right;\n      \n      this.$container.css({\n        left: 'unset',\n        right: - rightAdjustment + 'px',\n      });\n    },\n\n    _alignCenter: function () {\n      var left = Math.round(this._triggerWidth / 2 - this._menuWidth / 2);\n      var leftAdjustment = this._alignmentElementOffset.left - this._wrapperElementOffset.left;\n\n      this.$container.css('left', left - leftAdjustment);\n    },\n  },\n  {\n    defaults: {\n      windowSpacing: 5,\n    },\n  }\n);\n\n/** global: Garnish */\n/**\n * Drag class\n *\n * Builds on the BaseDrag class by \"picking up\" the selceted element(s),\n * without worrying about what to do when an element is being dragged.\n */\nGarnish.Drag = Garnish.BaseDrag.extend(\n    {\n        targetItemWidth: null,\n        targetItemHeight: null,\n        targetItemPositionInDraggee: null,\n\n        $draggee: null,\n\n        otherItems: null,\n        totalOtherItems: null,\n\n        helpers: null,\n        helperTargets: null,\n        helperPositions: null,\n        helperLagIncrement: null,\n        updateHelperPosProxy: null,\n        updateHelperPosFrame: null,\n\n        lastMouseX: null,\n        lastMouseY: null,\n\n        _returningHelpersToDraggees: false,\n\n        /**\n         * Constructor\n         *\n         * @param {object} items    Elements that should be draggable right away. (Can be skipped.)\n         * @param {object} settings Any settings that should override the defaults.\n         */\n        init: function(items, settings) {\n            // Param mapping\n            if (typeof settings === 'undefined' && $.isPlainObject(items)) {\n                // (settings)\n                settings = items;\n                items = null;\n            }\n\n            settings = $.extend({}, Garnish.Drag.defaults, settings);\n            this.base(items, settings);\n        },\n\n        /**\n         * Returns whether dragging is allowed right now.\n         */\n        allowDragging: function() {\n            // Don't allow dragging if we're in the middle of animating the helpers back to the draggees\n            return !this._returningHelpersToDraggees;\n        },\n\n        /**\n         * Start Dragging\n         */\n        startDragging: function() {\n            // Reset some things\n            this.helpers = [];\n            this.helperTargets = [];\n            this.helperPositions = [];\n            this.lastMouseX = this.lastMouseY = null;\n\n            // Capture the target item's width/height\n            this.targetItemWidth = this.$targetItem.outerWidth();\n            this.targetItemHeight = this.$targetItem.outerHeight();\n\n            // Save the draggee's display style (block/table-row) so we can re-apply it later\n            this.draggeeDisplay = this.$targetItem.css('display');\n\n            // Set the $draggee\n            this.setDraggee(this.findDraggee());\n\n            // Create an array of all the other items\n            this.otherItems = [];\n\n            for (var i = 0; i < this.$items.length; i++) {\n                var item = this.$items[i];\n\n                if ($.inArray(item, this.$draggee) === -1) {\n                    this.otherItems.push(item);\n                }\n            }\n\n            this.totalOtherItems = this.otherItems.length;\n\n            // Keep the helpers following the cursor, with a little lag to smooth it out\n            if (!this.updateHelperPosProxy) {\n                this.updateHelperPosProxy = this._updateHelperPos.bind(this);\n            }\n\n            this.helperLagIncrement = this.helpers.length === 1 ? 0 : this.settings.helperLagIncrementDividend / (this.helpers.length - 1);\n            this.updateHelperPosFrame = Garnish.requestAnimationFrame(this.updateHelperPosProxy);\n\n            this.base();\n        },\n\n        /**\n         * Sets the draggee.\n         */\n        setDraggee: function($draggee) {\n            // Record the target item's position in the draggee\n            this.targetItemPositionInDraggee = $.inArray(this.$targetItem[0], $draggee.add(this.$targetItem[0]));\n\n            // Keep the target item at the front of the list\n            this.$draggee = $([this.$targetItem[0]].concat($draggee.not(this.$targetItem).toArray()));\n\n            // Create the helper(s)\n            if (this.settings.singleHelper) {\n                this._createHelper(0);\n            }\n            else {\n                for (var i = 0; i < this.$draggee.length; i++) {\n                    this._createHelper(i);\n                }\n            }\n\n            if (this.settings.removeDraggee) {\n                this.$draggee.hide();\n            }\n            else if (this.settings.collapseDraggees) {\n                this.$targetItem.css('visibility', 'hidden');\n                this.$draggee.not(this.$targetItem).hide();\n            }\n            else {\n                this.$draggee.css('visibility', 'hidden');\n            }\n        },\n\n        /**\n         * Appends additional items to the draggee.\n         */\n        appendDraggee: function($newDraggee) {\n            if (!$newDraggee.length) {\n                return;\n            }\n\n            if (!this.settings.collapseDraggees) {\n                var oldLength = this.$draggee.length;\n            }\n\n            this.$draggee = $(this.$draggee.toArray().concat($newDraggee.toArray()));\n\n            // Create new helpers?\n            if (!this.settings.collapseDraggees) {\n                var newLength = this.$draggee.length;\n\n                for (var i = oldLength; i < newLength; i++) {\n                    this._createHelper(i);\n                }\n            }\n\n            if (this.settings.removeDraggee || this.settings.collapseDraggees) {\n                $newDraggee.hide();\n            }\n            else {\n                $newDraggee.css('visibility', 'hidden');\n            }\n        },\n\n        /**\n         * Drag\n         */\n        drag: function(didMouseMove) {\n            // Update the draggee's virtual midpoint\n            this.draggeeVirtualMidpointX = this.mouseX - this.mouseOffsetX + (this.targetItemWidth / 2);\n            this.draggeeVirtualMidpointY = this.mouseY - this.mouseOffsetY + (this.targetItemHeight / 2);\n\n            this.base(didMouseMove);\n        },\n\n        /**\n         * Stop Dragging\n         */\n        stopDragging: function() {\n            // Clear the helper animation\n            Garnish.cancelAnimationFrame(this.updateHelperPosFrame);\n\n            this.base();\n        },\n\n        /**\n         * Identifies the item(s) that are being dragged.\n         */\n        findDraggee: function() {\n            switch (typeof this.settings.filter) {\n                case 'function': {\n                    return this.settings.filter();\n                }\n\n                case 'string': {\n                    return this.$items.filter(this.settings.filter);\n                }\n\n                default: {\n                    return this.$targetItem;\n                }\n            }\n        },\n\n        /**\n         * Returns the helper’s target X position\n         */\n        getHelperTargetX: function() {\n            return this.mouseX - this.mouseOffsetX;\n        },\n\n        /**\n         * Returns the helper’s target Y position\n         */\n        getHelperTargetY: function() {\n            return this.mouseY - this.mouseOffsetY;\n        },\n\n        /**\n         * Return Helpers to Draggees\n         */\n        returnHelpersToDraggees: function() {\n            this._returningHelpersToDraggees = true;\n\n            for (var i = 0; i < this.helpers.length; i++) {\n                var $draggee = this.$draggee.eq(i),\n                    $helper = this.helpers[i];\n\n                $draggee.css({\n                    display: this.draggeeDisplay,\n                    visibility: 'hidden'\n                });\n\n                var draggeeOffset = $draggee.offset();\n                var callback;\n\n                if (i === 0) {\n                    callback = this._showDraggee.bind(this);\n                }\n                else {\n                    callback = null;\n                }\n\n                $helper.velocity({left: draggeeOffset.left, top: draggeeOffset.top}, Garnish.FX_DURATION, callback);\n            }\n        },\n\n        // Events\n        // ---------------------------------------------------------------------\n\n        onReturnHelpersToDraggees: function() {\n            Garnish.requestAnimationFrame(function() {\n                this.trigger('returnHelpersToDraggees');\n                this.settings.onReturnHelpersToDraggees();\n            }.bind(this));\n        },\n\n        // Private methods\n        // ---------------------------------------------------------------------\n\n        /**\n         * Creates a helper.\n         */\n        _createHelper: function(i) {\n            var $draggee = this.$draggee.eq(i),\n                $draggeeHelper = $draggee.clone().addClass('draghelper');\n\n            if (this.settings.copyDraggeeInputValuesToHelper) {\n                Garnish.copyInputValues($draggee, $draggeeHelper);\n            }\n\n            // Remove any name= attributes so radio buttons don't lose their values\n            $draggeeHelper.find('[name]').attr('name', '');\n\n            $draggeeHelper\n                .outerWidth(Math.ceil($draggee.outerWidth()))\n                .outerHeight(Math.ceil($draggee.outerHeight()))\n                .css({margin: 0, 'pointer-events': 'none'});\n\n            if (this.settings.helper) {\n                if (typeof this.settings.helper === 'function') {\n                    $draggeeHelper = this.settings.helper($draggeeHelper);\n                }\n                else {\n                    $draggeeHelper = $(this.settings.helper).append($draggeeHelper);\n                }\n            }\n\n            $draggeeHelper.appendTo(Garnish.$bod);\n\n            var helperPos = this._getHelperTarget(i);\n\n            $draggeeHelper.css({\n                position: 'absolute',\n                top: helperPos.top,\n                left: helperPos.left,\n                zIndex: this.settings.helperBaseZindex + this.$draggee.length - i,\n                opacity: this.settings.helperOpacity\n            });\n\n            this.helperPositions[i] = {\n                top: helperPos.top,\n                left: helperPos.left\n            };\n\n            this.helpers.push($draggeeHelper);\n        },\n\n        /**\n         * Update Helper Position\n         */\n        _updateHelperPos: function() {\n            // Has the mouse moved?\n            if (this.mouseX !== this.lastMouseX || this.mouseY !== this.lastMouseY) {\n                // Get the new target helper positions\n                for (this._updateHelperPos._i = 0; this._updateHelperPos._i < this.helpers.length; this._updateHelperPos._i++) {\n                    this.helperTargets[this._updateHelperPos._i] = this._getHelperTarget(this._updateHelperPos._i);\n                }\n\n                this.lastMouseX = this.mouseX;\n                this.lastMouseY = this.mouseY;\n            }\n\n            // Gravitate helpers toward their target positions\n            for (this._updateHelperPos._j = 0; this._updateHelperPos._j < this.helpers.length; this._updateHelperPos._j++) {\n                this._updateHelperPos._lag = this.settings.helperLagBase + (this.helperLagIncrement * this._updateHelperPos._j);\n\n                this.helperPositions[this._updateHelperPos._j] = {\n                    left: this.helperPositions[this._updateHelperPos._j].left + ((this.helperTargets[this._updateHelperPos._j].left - this.helperPositions[this._updateHelperPos._j].left) / this._updateHelperPos._lag),\n                    top: this.helperPositions[this._updateHelperPos._j].top + ((this.helperTargets[this._updateHelperPos._j].top - this.helperPositions[this._updateHelperPos._j].top) / this._updateHelperPos._lag)\n                };\n\n                this.helpers[this._updateHelperPos._j].css(this.helperPositions[this._updateHelperPos._j]);\n            }\n\n            // Let's do this again on the next frame!\n            this.updateHelperPosFrame = Garnish.requestAnimationFrame(this.updateHelperPosProxy);\n        },\n\n        /**\n         * Get the helper position for a draggee helper\n         */\n        _getHelperTarget: function(i) {\n            return {\n                left: this.getHelperTargetX() + (this.settings.helperSpacingX * i),\n                top: this.getHelperTargetY() + (this.settings.helperSpacingY * i)\n            };\n        },\n\n        _showDraggee: function() {\n            // Remove the helpers\n            for (var i = 0; i < this.helpers.length; i++) {\n                this.helpers[i].remove();\n            }\n\n            this.helpers = null;\n\n            this.$draggee.show().css('visibility', 'inherit');\n\n            this.onReturnHelpersToDraggees();\n\n            this._returningHelpersToDraggees = false;\n        }\n    },\n    {\n        defaults: {\n            filter: null,\n            singleHelper: false,\n            collapseDraggees: false,\n            removeDraggee: false,\n            copyDraggeeInputValuesToHelper: false,\n            helperOpacity: 1,\n            helper: null,\n            helperBaseZindex: 1000,\n            helperLagBase: 1,\n            helperLagIncrementDividend: 1.5,\n            helperSpacingX: 5,\n            helperSpacingY: 5,\n            onReturnHelpersToDraggees: $.noop\n        }\n    }\n);\n\n/** global: Garnish */\n/**\n * Drag-and-drop class\n *\n * Builds on the Drag class by allowing you to set up \"drop targets\"\n * which the dragged elemements can be dropped onto.\n */\nGarnish.DragDrop = Garnish.Drag.extend({\n\n        $dropTargets: null,\n        $activeDropTarget: null,\n\n        /**\n         * Constructor\n         */\n        init: function(settings) {\n            settings = $.extend({}, Garnish.DragDrop.defaults, settings);\n            this.base(settings);\n        },\n\n        updateDropTargets: function() {\n            if (this.settings.dropTargets) {\n                if (typeof this.settings.dropTargets === 'function') {\n                    this.$dropTargets = $(this.settings.dropTargets());\n                }\n                else {\n                    this.$dropTargets = $(this.settings.dropTargets);\n                }\n\n                // Discard if it's an empty array\n                if (!this.$dropTargets.length) {\n                    this.$dropTargets = null;\n                }\n            }\n        },\n\n        /**\n         * On Drag Start\n         */\n        onDragStart: function() {\n            this.updateDropTargets();\n            this.$activeDropTarget = null;\n            this.base();\n        },\n\n        /**\n         * On Drag\n         */\n        onDrag: function() {\n            if (this.$dropTargets) {\n                this.onDrag._activeDropTarget = null;\n\n                // is the cursor over any of the drop target?\n                for (this.onDrag._i = 0; this.onDrag._i < this.$dropTargets.length; this.onDrag._i++) {\n                    this.onDrag._elem = this.$dropTargets[this.onDrag._i];\n\n                    if (Garnish.hitTest(this.mouseX, this.mouseY, this.onDrag._elem)) {\n                        this.onDrag._activeDropTarget = this.onDrag._elem;\n                        break;\n                    }\n                }\n\n                // has the drop target changed?\n                if (\n                    (this.$activeDropTarget && this.onDrag._activeDropTarget !== this.$activeDropTarget[0]) ||\n                    (!this.$activeDropTarget && this.onDrag._activeDropTarget !== null)\n                ) {\n                    // was there a previous one?\n                    if (this.$activeDropTarget) {\n                        this.$activeDropTarget.removeClass(this.settings.activeDropTargetClass);\n                    }\n\n                    // remember the new one\n                    if (this.onDrag._activeDropTarget) {\n                        this.$activeDropTarget = $(this.onDrag._activeDropTarget).addClass(this.settings.activeDropTargetClass);\n                    }\n                    else {\n                        this.$activeDropTarget = null;\n                    }\n\n                    this.settings.onDropTargetChange(this.$activeDropTarget);\n                }\n            }\n\n            this.base();\n        },\n\n        /**\n         * On Drag Stop\n         */\n        onDragStop: function() {\n            if (this.$dropTargets && this.$activeDropTarget) {\n                this.$activeDropTarget.removeClass(this.settings.activeDropTargetClass);\n            }\n\n            this.base();\n        },\n\n        /**\n         * Fade Out Helpers\n         */\n        fadeOutHelpers: function() {\n            for (var i = 0; i < this.helpers.length; i++) {\n                (function($draggeeHelper) {\n                    $draggeeHelper.velocity('fadeOut', {\n                        duration: Garnish.FX_DURATION,\n                        complete: function() {\n                            $draggeeHelper.remove();\n                        }\n                    });\n                })(this.helpers[i]);\n            }\n        }\n    },\n    {\n        defaults: {\n            dropTargets: null,\n            onDropTargetChange: $.noop,\n            activeDropTargetClass: 'active'\n        }\n    });\n\n/** global: Garnish */\n/**\n * Drag-to-move clas\n *\n * Builds on the BaseDrag class by simply moving the dragged element(s) along with the mouse.\n */\nGarnish.DragMove = Garnish.BaseDrag.extend(\n    {\n        onDrag: function(items, settings) {\n            this.$targetItem.css({\n                left: this.mouseX - this.mouseOffsetX,\n                top: this.mouseY - this.mouseOffsetY\n            });\n        }\n    }\n);\n\n/** global: Garnish */\n/**\n * Drag-to-sort class\n *\n * Builds on the Drag class by allowing you to sort the elements amongst themselves.\n */\nGarnish.DragSort = Garnish.Drag.extend(\n    {\n        $heightedContainer: null,\n        $insertion: null,\n        insertionVisible: false,\n        oldDraggeeIndexes: null,\n        newDraggeeIndexes: null,\n        closestItem: null,\n\n        _midpointVersion: 0,\n        _$prevItem: null,\n\n        /**\n         * Constructor\n         *\n         * @param {object} items    Elements that should be draggable right away. (Can be skipped.)\n         * @param {object} settings Any settings that should override the defaults.\n         */\n        init: function(items, settings) {\n            // Param mapping\n            if (typeof settings === 'undefined' && $.isPlainObject(items)) {\n                // (settings)\n                settings = items;\n                items = null;\n            }\n\n            settings = $.extend({}, Garnish.DragSort.defaults, settings);\n            this.base(items, settings);\n        },\n\n        /**\n         * Creates the insertion element.\n         */\n        createInsertion: function() {\n            if (this.settings.insertion) {\n                if (typeof this.settings.insertion === 'function') {\n                    return $(this.settings.insertion(this.$draggee));\n                }\n                else {\n                    return $(this.settings.insertion);\n                }\n            }\n        },\n\n        /**\n         * Returns the helper’s target X position\n         */\n        getHelperTargetX: function() {\n            if (this.settings.magnetStrength !== 1) {\n                this.getHelperTargetX._draggeeOffsetX = this.$draggee.offset().left;\n                return this.getHelperTargetX._draggeeOffsetX + ((this.mouseX - this.mouseOffsetX - this.getHelperTargetX._draggeeOffsetX) / this.settings.magnetStrength);\n            }\n            else {\n                return this.base();\n            }\n        },\n\n        /**\n         * Returns the helper’s target Y position\n         */\n        getHelperTargetY: function() {\n            if (this.settings.magnetStrength !== 1) {\n                this.getHelperTargetY._draggeeOffsetY = this.$draggee.offset().top;\n                return this.getHelperTargetY._draggeeOffsetY + ((this.mouseY - this.mouseOffsetY - this.getHelperTargetY._draggeeOffsetY) / this.settings.magnetStrength);\n            }\n            else {\n                return this.base();\n            }\n        },\n\n        /**\n         * Returns whether the draggee can be inserted before a given item.\n         */\n        canInsertBefore: function($item) {\n            return true;\n        },\n\n        /**\n         * Returns whether the draggee can be inserted after a given item.\n         */\n        canInsertAfter: function($item) {\n            return true;\n        },\n\n        // Events\n        // ---------------------------------------------------------------------\n\n        /**\n         * On Drag Start\n         */\n        onDragStart: function() {\n            this.oldDraggeeIndexes = this._getDraggeeIndexes();\n\n            // Are we supposed to be moving the target item to the front, and is it not already there?\n            if (\n                this.settings.moveTargetItemToFront &&\n                this.$draggee.length > 1 &&\n                this._getItemIndex(this.$draggee[0]) > this._getItemIndex(this.$draggee[1])\n            ) {\n                // Reposition the target item before the other draggee items in the DOM\n                this.$draggee.first().insertBefore(this.$draggee[1]);\n            }\n\n            // Create the insertion\n            this.$insertion = this.createInsertion();\n            this._placeInsertionWithDraggee();\n\n            this.closestItem = null;\n            this._clearMidpoints();\n\n            //  Get the closest container that has a height\n            if (this.settings.container) {\n                this.$heightedContainer = $(this.settings.container);\n\n                while (!this.$heightedContainer.height()) {\n                    this.$heightedContainer = this.$heightedContainer.parent();\n                }\n            }\n\n            this.base();\n        },\n\n        /**\n         * On Drag\n         */\n        onDrag: function() {\n            // If there's a container set, make sure that we're hovering over it\n            if (this.$heightedContainer && !Garnish.hitTest(this.mouseX, this.mouseY, this.$heightedContainer)) {\n                if (this.closestItem) {\n                    this.closestItem = null;\n                    this._removeInsertion();\n                }\n            }\n            else {\n                // Is there a new closest item?\n                if (\n                    this.closestItem !== (this.closestItem = this._getClosestItem()) &&\n                    this.closestItem !== null\n                ) {\n                    this._updateInsertion();\n                }\n            }\n\n            this.base();\n        },\n\n        /**\n         * On Drag Stop\n         */\n        onDragStop: function() {\n            this._removeInsertion();\n\n            // Should we keep the target item where it was?\n            if (!this.settings.moveTargetItemToFront && this.targetItemPositionInDraggee !== 0) {\n                this.$targetItem.insertAfter(this.$draggee.eq(this.targetItemPositionInDraggee));\n            }\n\n            // Return the helpers to the draggees\n            this.returnHelpersToDraggees();\n\n            this.base();\n\n            // Has the item actually moved?\n            this.$items = $().add(this.$items);\n            this.newDraggeeIndexes = this._getDraggeeIndexes();\n\n            if (this.newDraggeeIndexes.join(',') !== this.oldDraggeeIndexes.join(',')) {\n                this.onSortChange();\n            }\n        },\n\n        /**\n         * On Insertion Point Change event\n         */\n        onInsertionPointChange: function() {\n            Garnish.requestAnimationFrame(function() {\n                this.trigger('insertionPointChange');\n                this.settings.onInsertionPointChange();\n            }.bind(this));\n        },\n\n        /**\n         * On Sort Change event\n         */\n        onSortChange: function() {\n            Garnish.requestAnimationFrame(function() {\n                this.trigger('sortChange');\n                this.settings.onSortChange();\n            }.bind(this));\n        },\n\n        // Private methods\n        // ---------------------------------------------------------------------\n\n        _getItemIndex: function(item) {\n            return $.inArray(item, this.$items);\n        },\n\n        _getDraggeeIndexes: function() {\n            var indexes = [];\n\n            for (var i = 0; i < this.$draggee.length; i++) {\n                indexes.push(this._getItemIndex(this.$draggee[i]))\n            }\n\n            return indexes;\n        },\n\n        /**\n         * Returns the closest item to the cursor.\n         */\n        _getClosestItem: function() {\n            this._getClosestItem._closestItem = null;\n\n            // Start by checking the draggee/insertion, if either are visible\n            if (!this.settings.removeDraggee) {\n                this._testForClosestItem(this.$draggee[0]);\n            }\n            else if (this.insertionVisible) {\n                this._testForClosestItem(this.$insertion[0]);\n            }\n\n            // Check items before the draggee\n            if (this._getClosestItem._closestItem) {\n                this._getClosestItem._midpoint = this._getItemMidpoint(this._getClosestItem._closestItem)\n            }\n            if (this.settings.axis !== Garnish.Y_AXIS) {\n                this._getClosestItem._startXDist = this._getClosestItem._lastXDist = this._getClosestItem._closestItem ? Math.abs(this._getClosestItem._midpoint.x - this.draggeeVirtualMidpointX) : null;\n            }\n            if (this.settings.axis !== Garnish.X_AXIS) {\n                this._getClosestItem._startYDist = this._getClosestItem._lastYDist = this._getClosestItem._closestItem ? Math.abs(this._getClosestItem._midpoint.y - this.draggeeVirtualMidpointY) : null;\n            }\n\n            this._getClosestItem._$otherItem = this.$draggee.first().prev();\n\n            while (this._getClosestItem._$otherItem.length) {\n                // See if we're just getting further away\n                this._getClosestItem._midpoint = this._getItemMidpoint(this._getClosestItem._$otherItem[0]);\n                if (this.settings.axis !== Garnish.Y_AXIS) {\n                    this._getClosestItem._xDist = Math.abs(this._getClosestItem._midpoint.x - this.draggeeVirtualMidpointX);\n                }\n                if (this.settings.axis !== Garnish.X_AXIS) {\n                    this._getClosestItem._yDist = Math.abs(this._getClosestItem._midpoint.y - this.draggeeVirtualMidpointY);\n                }\n\n                if (\n                    (this.settings.axis === Garnish.Y_AXIS || (this._getClosestItem._lastXDist !== null && this._getClosestItem._xDist > this._getClosestItem._lastXDist)) &&\n                    (this.settings.axis === Garnish.X_AXIS || (this._getClosestItem._lastYDist !== null && this._getClosestItem._yDist > this._getClosestItem._lastYDist))\n                ) {\n                    break;\n                }\n\n                if (this.settings.axis !== Garnish.Y_AXIS) {\n                    this._getClosestItem._lastXDist = this._getClosestItem._xDist;\n                }\n                if (this.settings.axis !== Garnish.X_AXIS) {\n                    this._getClosestItem._lastYDist = this._getClosestItem._yDist;\n                }\n\n                // Give the extending class a chance to allow/disallow this item\n                if (this.canInsertBefore(this._getClosestItem._$otherItem)) {\n                    this._testForClosestItem(this._getClosestItem._$otherItem[0]);\n                }\n\n                // Prep the next item\n                this._getClosestItem._$otherItem = this._getClosestItem._$otherItem.prev();\n            }\n\n            // Check items after the draggee\n            if (this.settings.axis !== Garnish.Y_AXIS) {\n                this._getClosestItem._lastXDist = this._getClosestItem._startXDist;\n            }\n            if (this.settings.axis !== Garnish.X_AXIS) {\n                this._getClosestItem._lastYDist = this._getClosestItem._startYDist;\n            }\n\n            this._getClosestItem._$otherItem = this.$draggee.last().next();\n\n            while (this._getClosestItem._$otherItem.length) {\n                // See if we're just getting further away\n                this._getClosestItem._midpoint = this._getItemMidpoint(this._getClosestItem._$otherItem[0]);\n                if (this.settings.axis !== Garnish.Y_AXIS) {\n                    this._getClosestItem._xDist = Math.abs(this._getClosestItem._midpoint.x - this.draggeeVirtualMidpointX);\n                }\n                if (this.settings.axis !== Garnish.X_AXIS) {\n                    this._getClosestItem._yDist = Math.abs(this._getClosestItem._midpoint.y - this.draggeeVirtualMidpointY);\n                }\n\n                if (\n                    (this.settings.axis === Garnish.Y_AXIS || (this._getClosestItem._lastXDist !== null && this._getClosestItem._xDist > this._getClosestItem._lastXDist)) &&\n                    (this.settings.axis === Garnish.X_AXIS || (this._getClosestItem._lastYDist !== null && this._getClosestItem._yDist > this._getClosestItem._lastYDist))\n                ) {\n                    break;\n                }\n\n                if (this.settings.axis !== Garnish.Y_AXIS) {\n                    this._getClosestItem._lastXDist = this._getClosestItem._xDist;\n                }\n                if (this.settings.axis !== Garnish.X_AXIS) {\n                    this._getClosestItem._lastYDist = this._getClosestItem._yDist;\n                }\n\n                // Give the extending class a chance to allow/disallow this item\n                if (this.canInsertAfter(this._getClosestItem._$otherItem)) {\n                    this._testForClosestItem(this._getClosestItem._$otherItem[0]);\n                }\n\n                // Prep the next item\n                this._getClosestItem._$otherItem = this._getClosestItem._$otherItem.next();\n            }\n\n            // Return the result\n\n            // Ignore if it's the draggee or insertion\n            if (\n                this._getClosestItem._closestItem !== this.$draggee[0] &&\n                (!this.insertionVisible || this._getClosestItem._closestItem !== this.$insertion[0])\n            ) {\n                return this._getClosestItem._closestItem;\n            }\n            else {\n                return null;\n            }\n        },\n\n        _clearMidpoints: function() {\n            this._midpointVersion++;\n            this._$prevItem = null;\n        },\n\n        _getItemMidpoint: function(item) {\n            if ($.data(item, 'midpointVersion') !== this._midpointVersion) {\n                // If this isn't the draggee, temporarily move the draggee to this item\n                this._getItemMidpoint._repositionDraggee = (\n                    !this.settings.axis &&\n                    (!this.settings.removeDraggee || this.insertionVisible) &&\n                    item !== this.$draggee[0] &&\n                    (!this.$insertion || item !== this.$insertion.get(0))\n                );\n\n                if (this._getItemMidpoint._repositionDraggee) {\n                    // Is this the first time we've had to temporarily reposition the draggee since the last midpoint clearing?\n                    if (!this._$prevItem) {\n                        this._$prevItem = (this.insertionVisible ? this.$insertion : this.$draggee).first().prev();\n                    }\n\n                    this._moveDraggeeToItem(item);\n\n                    // Now figure out which element we're actually getting the midpoint of\n                    if (!this.settings.removeDraggee) {\n                        this._getItemMidpoint._$item = this.$draggee;\n                    }\n                    else {\n                        this._getItemMidpoint._$item = this.$insertion;\n                    }\n                }\n                else {\n                    // We're actually getting the midpoint of this item\n                    this._getItemMidpoint._$item = $(item);\n                }\n\n                this._getItemMidpoint._offset = this._getItemMidpoint._$item.offset();\n\n                $.data(item, 'midpoint', {\n                    x: this._getItemMidpoint._offset.left + this._getItemMidpoint._$item.outerWidth() / 2,\n                    y: this._getItemMidpoint._offset.top + this._getItemMidpoint._$item.outerHeight() / 2\n                });\n\n                $.data(item, 'midpointVersion', this._midpointVersion);\n\n                delete this._getItemMidpoint._$item;\n                delete this._getItemMidpoint._offset;\n\n                if (this._getItemMidpoint._repositionDraggee) {\n                    // Move the draggee back\n                    if (this._$prevItem.length) {\n                        this.$draggee.insertAfter(this._$prevItem);\n                    }\n                    else {\n                        this.$draggee.prependTo(this.$draggee.parent());\n                    }\n\n                    this._placeInsertionWithDraggee();\n                }\n            }\n\n            return $.data(item, 'midpoint');\n        },\n\n        _testForClosestItem: function(item) {\n            this._testForClosestItem._midpoint = this._getItemMidpoint(item);\n            this._testForClosestItem._mouseDistX = Math.abs(this._testForClosestItem._midpoint.x - this.draggeeVirtualMidpointX);\n            this._testForClosestItem._mouseDistY = Math.abs(this._testForClosestItem._midpoint.y - this.draggeeVirtualMidpointY);\n\n            // Don't even consider items that are further away on the Y axis\n            if (\n                this._getClosestItem._closestItem === null ||\n                this._testForClosestItem._mouseDistY < this._getClosestItem._closestItemMouseDistY ||\n                (\n                    this._testForClosestItem._mouseDistY === this._getClosestItem._closestItemMouseDistY &&\n                    this._testForClosestItem._mouseDistX <= this._getClosestItem._closestItemMouseDistX\n                )\n            ) {\n                this._getClosestItem._closestItem = item;\n                this._getClosestItem._closestItemMouseDistX = this._testForClosestItem._mouseDistX;\n                this._getClosestItem._closestItemMouseDistY = this._testForClosestItem._mouseDistY;\n            }\n        },\n\n        /**\n         * Updates the position of the insertion point.\n         */\n        _updateInsertion: function() {\n            if (this.closestItem) {\n                this._moveDraggeeToItem(this.closestItem);\n            }\n\n            // Now that things have shifted around, invalidate the midpoints\n            this._clearMidpoints();\n\n            this.onInsertionPointChange();\n        },\n\n        _moveDraggeeToItem: function(item) {\n            // Going down?\n            if (this.$draggee.index() < $(item).index()) {\n                this.$draggee.insertAfter(item);\n            }\n            else {\n                this.$draggee.insertBefore(item);\n            }\n\n            this._placeInsertionWithDraggee();\n        },\n\n        _placeInsertionWithDraggee: function() {\n            if (this.$insertion) {\n                this.$insertion.insertBefore(this.$draggee.first());\n                this.insertionVisible = true;\n            }\n        },\n\n        /**\n         * Removes the insertion, if it's visible.\n         */\n        _removeInsertion: function() {\n            if (this.insertionVisible) {\n                this.$insertion.remove();\n                this.insertionVisible = false;\n            }\n        }\n    },\n    {\n        defaults: {\n            container: null,\n            insertion: null,\n            moveTargetItemToFront: false,\n            magnetStrength: 1,\n            onInsertionPointChange: $.noop,\n            onSortChange: $.noop\n        }\n    }\n);\n\n/** global: Garnish */\n/**\n * ESC key manager class\n * @deprecated Use Garnish.ShortcutManager instead\n */\nGarnish.EscManager = Garnish.Base.extend(\n    {\n        handlers: null,\n\n        init: function() {\n            this.handlers = [];\n\n            this.addListener(Garnish.$bod, 'keyup', function(ev) {\n                if (ev.keyCode === Garnish.ESC_KEY) {\n                    this.escapeLatest(ev);\n                }\n            });\n        },\n\n        register: function(obj, func) {\n            this.handlers.push({\n                obj: obj,\n                func: func\n            });\n        },\n\n        unregister: function(obj) {\n            for (var i = this.handlers.length - 1; i >= 0; i--) {\n                if (this.handlers[i].obj === obj) {\n                    this.handlers.splice(i, 1);\n                }\n            }\n        },\n\n        escapeLatest: function(ev) {\n            if (this.handlers.length) {\n                var handler = this.handlers.pop();\n\n                var func;\n\n                if (typeof handler.func === 'function') {\n                    func = handler.func;\n                }\n                else {\n                    func = handler.obj[handler.func];\n                }\n\n                func.call(handler.obj, ev);\n\n                if (typeof handler.obj.trigger === 'function') {\n                    handler.obj.trigger('escape');\n                }\n            }\n        }\n    }\n);\n\nGarnish.escManager = new Garnish.EscManager();\n\n/** global: Garnish */\n/**\n * HUD\n */\nGarnish.HUD = Garnish.Base.extend(\n    {\n        $trigger: null,\n        $fixedTriggerParent: null,\n        $hud: null,\n        $tip: null,\n        $body: null,\n        $header: null,\n        $footer: null,\n        $mainContainer: null,\n        $main: null,\n        $shade: null,\n\n        showing: false,\n        orientation: null,\n\n        updatingSizeAndPosition: false,\n        windowWidth: null,\n        windowHeight: null,\n        scrollTop: null,\n        scrollLeft: null,\n        mainWidth: null,\n        mainHeight: null,\n\n        /**\n         * Constructor\n         */\n        init: function(trigger, bodyContents, settings) {\n\n            this.$trigger = $(trigger);\n\n            this.setSettings(settings, Garnish.HUD.defaults);\n            this.on('show', this.settings.onShow);\n            this.on('hide', this.settings.onHide);\n            this.on('submit', this.settings.onSubmit);\n\n            if (typeof Garnish.HUD.activeHUDs === 'undefined') {\n                Garnish.HUD.activeHUDs = {};\n            }\n\n            this.$shade = $('<div/>', {'class': this.settings.shadeClass});\n            this.$hud = $('<div/>', {'class': this.settings.hudClass}).data('hud', this);\n            this.$tip = $('<div/>', {'class': this.settings.tipClass}).appendTo(this.$hud);\n            this.$body = $('<form/>', {'class': this.settings.bodyClass}).appendTo(this.$hud);\n            this.$mainContainer = $('<div/>', {'class': this.settings.mainContainerClass}).appendTo(this.$body);\n            this.$main = $('<div/>', {'class': this.settings.mainClass}).appendTo(this.$mainContainer);\n\n            this.updateBody(bodyContents);\n\n            // See if the trigger is fixed\n            var $parent = this.$trigger;\n\n            do {\n                if ($parent.css('position') === 'fixed') {\n                    this.$fixedTriggerParent = $parent;\n                    break;\n                }\n\n                $parent = $parent.offsetParent();\n            }\n            while ($parent.length && $parent.prop('nodeName') !== 'HTML');\n\n            if (this.$fixedTriggerParent) {\n                this.$hud.css('position', 'fixed');\n            }\n            else {\n                this.$hud.css('position', 'absolute');\n            }\n\n            // Hide the HUD until it gets positioned\n\t\t\tthis.$hud.css('opacity', 0);\n            this.show();\n            this.$hud.css('opacity', 1);\n\n            this.addListener(this.$body, 'submit', '_handleSubmit');\n\n            if (this.settings.hideOnShadeClick) {\n                this.addListener(this.$shade, 'tap,click', 'hide');\n            }\n\n            if (this.settings.closeBtn) {\n                this.addListener(this.settings.closeBtn, 'activate', 'hide');\n            }\n\n            this.addListener(Garnish.$win, 'resize', 'updateSizeAndPosition');\n            this.addListener(this.$main, 'resize', 'updateSizeAndPosition');\n            if (!this.$fixedTriggerParent && Garnish.$scrollContainer[0] !== Garnish.$win[0]) {\n                this.addListener(Garnish.$scrollContainer, 'scroll', 'updateSizeAndPosition');\n            }\n        },\n\n        /**\n         * Update the body contents\n         */\n        updateBody: function(bodyContents) {\n            // Cleanup\n            this.$main.html('');\n\n            if (this.$header) {\n                this.$hud.removeClass('has-header');\n                this.$header.remove();\n                this.$header = null;\n            }\n\n            if (this.$footer) {\n                this.$hud.removeClass('has-footer');\n                this.$footer.remove();\n                this.$footer = null;\n            }\n\n            // Append the new body contents\n            this.$main.append(bodyContents);\n\n            // Look for a header and footer\n            var $header = this.$main.find('.' + this.settings.headerClass + ':first'),\n                $footer = this.$main.find('.' + this.settings.footerClass + ':first');\n\n            if ($header.length) {\n                this.$header = $header.insertBefore(this.$mainContainer);\n                this.$hud.addClass('has-header');\n            }\n\n            if ($footer.length) {\n                this.$footer = $footer.insertAfter(this.$mainContainer);\n                this.$hud.addClass('has-footer');\n            }\n        },\n\n        /**\n         * Show\n         */\n        show: function(ev) {\n            if (ev && ev.stopPropagation) {\n                ev.stopPropagation();\n            }\n\n            if (this.showing) {\n                return;\n            }\n\n            if (this.settings.closeOtherHUDs) {\n                for (var hudID in Garnish.HUD.activeHUDs) {\n                    if (!Garnish.HUD.activeHUDs.hasOwnProperty(hudID)) {\n                        continue;\n                    }\n                    Garnish.HUD.activeHUDs[hudID].hide();\n                }\n            }\n\n            // Move it to the end of <body> so it gets the highest sub-z-index\n            this.$shade.appendTo(Garnish.$bod);\n            this.$hud.appendTo(Garnish.$bod);\n\n            this.$hud.show();\n            this.$shade.show();\n            this.showing = true;\n            Garnish.HUD.activeHUDs[this._namespace] = this;\n\n            Garnish.shortcutManager.addLayer();\n\n            if (this.settings.hideOnEsc) {\n                Garnish.shortcutManager.registerShortcut(Garnish.ESC_KEY, this.hide.bind(this));\n            }\n\n            this.onShow();\n            this.enable();\n\n            if (this.updateRecords()) {\n                // Prevent the browser from jumping\n                this.$hud.css('top', Garnish.$scrollContainer.scrollTop());\n\n                this.updateSizeAndPosition(true);\n            }\n        },\n\n        onShow: function() {\n            this.trigger('show');\n        },\n\n        updateRecords: function() {\n            var changed = false;\n            changed = (this.windowWidth !== (this.windowWidth = Garnish.$win.width())) || changed;\n            changed = (this.windowHeight !== (this.windowHeight = Garnish.$win.height())) || changed;\n            changed = (this.scrollTop !== (this.scrollTop = Garnish.$scrollContainer.scrollTop())) || changed;\n            changed = (this.scrollLeft !== (this.scrollLeft = Garnish.$scrollContainer.scrollLeft())) || changed;\n            changed = (this.mainWidth !== (this.mainWidth = this.$main.outerWidth())) || changed;\n            changed = (this.mainHeight !== (this.mainHeight = this.$main.outerHeight())) || changed;\n            return changed;\n        },\n\n        updateSizeAndPosition: function(force) {\n            if (force === true || (this.updateRecords() && !this.updatingSizeAndPosition)) {\n                this.updatingSizeAndPosition = true;\n                Garnish.requestAnimationFrame(this.updateSizeAndPositionInternal.bind(this));\n            }\n        },\n\n        updateSizeAndPositionInternal: function() {\n            var triggerWidth,\n                triggerHeight,\n                triggerOffset,\n                windowScrollLeft,\n                windowScrollTop,\n                scrollContainerTriggerOffset,\n                scrollContainerScrollLeft,\n                scrollContainerScrollTop,\n                hudBodyWidth,\n                hudBodyHeight;\n\n            // Get the window sizes and trigger offset\n\n            windowScrollLeft = Garnish.$win.scrollLeft();\n            windowScrollTop = Garnish.$win.scrollTop();\n\n            // Get the trigger's dimensions\n            triggerWidth = this.$trigger.outerWidth();\n            triggerHeight = this.$trigger.outerHeight();\n\n            // Get the offsets for each side of the trigger element\n            triggerOffset = this.$trigger.offset();\n\n            if (this.$fixedTriggerParent) {\n                triggerOffset.left -= windowScrollLeft;\n                triggerOffset.top -= windowScrollTop;\n\n                scrollContainerTriggerOffset = triggerOffset;\n\n                windowScrollLeft = 0;\n                windowScrollTop = 0;\n                scrollContainerScrollLeft = 0;\n                scrollContainerScrollTop = 0;\n            }\n            else {\n                scrollContainerTriggerOffset = Garnish.getOffset(this.$trigger);\n\n                scrollContainerScrollLeft = Garnish.$scrollContainer.scrollLeft();\n                scrollContainerScrollTop = Garnish.$scrollContainer.scrollTop();\n            }\n\n            triggerOffset.right = triggerOffset.left + triggerWidth;\n            triggerOffset.bottom = triggerOffset.top + triggerHeight;\n\n            scrollContainerTriggerOffset.right = scrollContainerTriggerOffset.left + triggerWidth;\n            scrollContainerTriggerOffset.bottom = scrollContainerTriggerOffset.top + triggerHeight;\n\n            // Get the HUD dimensions\n            this.$hud.css({\n                width: ''\n            });\n\n            this.$mainContainer.css({\n                height: '',\n                'overflow-x': '',\n                'overflow-y': ''\n            });\n\n            hudBodyWidth = this.$body.width();\n            hudBodyHeight = this.$body.height();\n\n            // Determine the best orientation for the HUD\n\n            // Find the actual available top/right/bottom/left clearances\n            var clearances = {\n                bottom: this.windowHeight + scrollContainerScrollTop - scrollContainerTriggerOffset.bottom,\n                top: scrollContainerTriggerOffset.top - scrollContainerScrollTop,\n                right: this.windowWidth + scrollContainerScrollLeft - scrollContainerTriggerOffset.right,\n                left: scrollContainerTriggerOffset.left - scrollContainerScrollLeft\n            };\n\n            // Find the first position that has enough room\n            this.orientation = null;\n\n            for (var i = 0; i < this.settings.orientations.length; i++) {\n                var orientation = this.settings.orientations[i],\n                    relevantSize = (orientation === 'top' || orientation === 'bottom' ? hudBodyHeight : hudBodyWidth);\n\n                if (clearances[orientation] - (this.settings.windowSpacing + this.settings.triggerSpacing) >= relevantSize) {\n                    // This is the first orientation that has enough room in order of preference, so we'll go with this\n                    this.orientation = orientation;\n                    break;\n                }\n\n                if (!this.orientation || clearances[orientation] > clearances[this.orientation]) {\n                    // Use this as a fallback as it's the orientation with the most clearance so far\n                    this.orientation = orientation;\n                }\n            }\n\n            // Just in case...\n            if (!this.orientation || $.inArray(this.orientation, ['bottom', 'top', 'right', 'left']) === -1) {\n                this.orientation = 'bottom'\n            }\n\n            // Update the tip class\n            if (this.tipClass) {\n                this.$tip.removeClass(this.tipClass);\n            }\n\n            this.tipClass = this.settings.tipClass + '-' + Garnish.HUD.tipClasses[this.orientation];\n            this.$tip.addClass(this.tipClass);\n\n            // Make sure the HUD body is within the allowed size\n\n            var maxHudBodyWidth,\n                maxHudBodyHeight;\n\n            if (this.orientation === 'top' || this.orientation === 'bottom') {\n                maxHudBodyWidth = this.windowWidth - this.settings.windowSpacing * 2;\n                maxHudBodyHeight = clearances[this.orientation] - this.settings.windowSpacing - this.settings.triggerSpacing;\n            }\n            else {\n                maxHudBodyWidth = clearances[this.orientation] - this.settings.windowSpacing - this.settings.triggerSpacing;\n                maxHudBodyHeight = this.windowHeight - this.settings.windowSpacing * 2;\n            }\n\n            if (maxHudBodyWidth < this.settings.minBodyWidth) {\n                maxHudBodyWidth = this.settings.minBodyWidth;\n            }\n\n            if (maxHudBodyHeight < this.settings.minBodyHeight) {\n                maxHudBodyHeight = this.settings.minBodyHeight;\n            }\n\n            if (hudBodyWidth > maxHudBodyWidth || hudBodyWidth < this.settings.minBodyWidth) {\n                if (hudBodyWidth > maxHudBodyWidth) {\n                    hudBodyWidth = maxHudBodyWidth;\n                }\n                else {\n                    hudBodyWidth = this.settings.minBodyWidth;\n                }\n\n                this.$hud.width(hudBodyWidth);\n\n                // Is there any overflow now?\n                if (this.mainWidth > maxHudBodyWidth) {\n                    this.$mainContainer.css('overflow-x', 'scroll');\n                }\n\n                // The height may have just changed\n                hudBodyHeight = this.$body.height();\n            }\n\n            if (hudBodyHeight > maxHudBodyHeight || hudBodyHeight < this.settings.minBodyHeight) {\n                if (hudBodyHeight > maxHudBodyHeight) {\n                    hudBodyHeight = maxHudBodyHeight;\n                }\n                else {\n                    hudBodyHeight = this.settings.minBodyHeight;\n                }\n\n                var mainHeight = hudBodyHeight;\n\n                if (this.$header) {\n                    mainHeight -= this.$header.outerHeight();\n                }\n\n                if (this.$footer) {\n                    mainHeight -= this.$footer.outerHeight();\n                }\n\n                this.$mainContainer.height(mainHeight);\n\n                // Is there any overflow now?\n                if (this.mainHeight > mainHeight) {\n                    this.$mainContainer.css('overflow-y', 'scroll');\n                }\n            }\n\n            // Set the HUD/tip positions\n            var triggerCenter, left, top;\n\n            if (this.orientation === 'top' || this.orientation === 'bottom') {\n                // Center the HUD horizontally\n                var maxLeft = (this.windowWidth + windowScrollLeft) - (hudBodyWidth + this.settings.windowSpacing);\n                var minLeft = (windowScrollLeft + this.settings.windowSpacing);\n                triggerCenter = triggerOffset.left + Math.round(triggerWidth / 2);\n                left = triggerCenter - Math.round(hudBodyWidth / 2);\n\n                if (left > maxLeft) {\n                    left = maxLeft;\n                }\n                if (left < minLeft) {\n                    left = minLeft;\n                }\n\n                this.$hud.css('left', left);\n\n                var tipLeft = (triggerCenter - left) - (this.settings.tipWidth / 2);\n                this.$tip.css({left: tipLeft, top: ''});\n\n                if (this.orientation === 'top') {\n                    top = triggerOffset.top - (hudBodyHeight + this.settings.triggerSpacing);\n                    this.$hud.css('top', top);\n                }\n                else {\n                    top = triggerOffset.bottom + this.settings.triggerSpacing;\n                    this.$hud.css('top', top);\n                }\n            }\n            else {\n                // Center the HUD vertically\n                var maxTop = (this.windowHeight + windowScrollTop) - (hudBodyHeight + this.settings.windowSpacing);\n                var minTop = (windowScrollTop + this.settings.windowSpacing);\n                triggerCenter = triggerOffset.top + Math.round(triggerHeight / 2);\n                top = triggerCenter - Math.round(hudBodyHeight / 2);\n\n                if (top > maxTop) {\n                    top = maxTop;\n                }\n                if (top < minTop) {\n                    top = minTop;\n                }\n\n                this.$hud.css('top', top);\n\n                var tipTop = (triggerCenter - top) - (this.settings.tipWidth / 2);\n                this.$tip.css({top: tipTop, left: ''});\n\n\n                if (this.orientation === 'left') {\n                    left = triggerOffset.left - (hudBodyWidth + this.settings.triggerSpacing);\n                    this.$hud.css('left', left);\n                }\n                else {\n                    left = triggerOffset.right + this.settings.triggerSpacing;\n                    this.$hud.css('left', left);\n                }\n            }\n\n            this.updatingSizeAndPosition = false;\n            this.trigger('updateSizeAndPosition');\n        },\n\n        /**\n         * Hide\n         */\n        hide: function() {\n            if (!this.showing) {\n                return;\n            }\n\n            this.disable();\n\n            this.$hud.hide();\n            this.$shade.hide();\n\n            this.showing = false;\n            delete Garnish.HUD.activeHUDs[this._namespace];\n            Garnish.shortcutManager.removeLayer();\n            this.onHide();\n        },\n\n        onHide: function() {\n            this.trigger('hide');\n        },\n\n        toggle: function() {\n            if (this.showing) {\n                this.hide();\n            }\n            else {\n                this.show();\n            }\n        },\n\n        submit: function() {\n            this.onSubmit();\n        },\n\n        onSubmit: function() {\n            this.trigger('submit');\n        },\n\n        _handleSubmit: function(ev) {\n            ev.preventDefault();\n            this.submit();\n        }\n    },\n    {\n        tipClasses: {bottom: 'top', top: 'bottom', right: 'left', left: 'right'},\n\n        defaults: {\n            shadeClass: 'hud-shade',\n            hudClass: 'hud',\n            tipClass: 'tip',\n            bodyClass: 'body',\n            headerClass: 'hud-header',\n            footerClass: 'hud-footer',\n            mainContainerClass: 'main-container',\n            mainClass: 'main',\n            orientations: ['bottom', 'top', 'right', 'left'],\n            triggerSpacing: 10,\n            windowSpacing: 10,\n            tipWidth: 30,\n            minBodyWidth: 200,\n            minBodyHeight: 0,\n            onShow: $.noop,\n            onHide: $.noop,\n            onSubmit: $.noop,\n            closeBtn: null,\n            closeOtherHUDs: true,\n            hideOnEsc: true,\n            hideOnShadeClick: true,\n        }\n    }\n);\n\n/** global: Garnish */\n/**\n * Menu Button\n */\nGarnish.MenuBtn = Garnish.Base.extend(\n    {\n        $btn: null,\n        menu: null,\n        showingMenu: false,\n        disabled: true,\n\n        /**\n         * Constructor\n         */\n        init: function(btn, menu, settings) {\n            // Param mapping\n            if (typeof settings === 'undefined' && $.isPlainObject(menu)) {\n                // (btn, settings)\n                settings = menu;\n                menu = null;\n            }\n\n            this.$btn = $(btn);\n            var $menu;\n\n            // Is this already a menu button?\n            if (this.$btn.data('menubtn')) {\n                // Grab the old MenuBtn's menu container\n                if (!menu) {\n                    $menu = this.$btn.data('menubtn').menu.$container;\n                }\n\n                Garnish.log('Double-instantiating a menu button on an element');\n                this.$btn.data('menubtn').destroy();\n            }\n            else if (!menu) {\n                $menu = this.$btn.next('.menu').detach();\n            }\n\n            this.$btn.data('menubtn', this);\n\n            this.setSettings(settings, Garnish.MenuBtn.defaults);\n\n            this.menu = menu || new Garnish.CustomSelect($menu);\n            this.menu.$anchor = $(this.settings.menuAnchor || this.$btn);\n            this.menu.on('optionselect', function(ev) {\n                this.onOptionSelect(ev.selectedOption);\n            }.bind(this));\n\n            this.$btn.attr({\n                'tabindex': 0,\n                'aria-controls': this.menu.menuId,\n                'aria-haspopup': 'listbox',\n                'aria-expanded': 'false'\n            });\n\n            this.menu.on('hide', this.onMenuHide.bind(this));\n            this.addListener(this.$btn, 'mousedown', 'onMouseDown');\n            this.addListener(this.$btn, 'keydown', 'onKeyDown');\n            this.addListener(this.$btn, 'blur', 'onBlur');\n            this.enable();\n        },\n\n        onBlur: function() {\n            if (this.showingMenu) {\n                Garnish.requestAnimationFrame(function() {\n                    if (!$.contains(this.menu.$container.get(0), document.activeElement)) {\n                        this.hideMenu();\n                    }\n                }.bind(this));\n            }\n        },\n\n        onKeyDown: function(ev) {\n            var $option;\n\n            switch (ev.keyCode) {\n                case Garnish.RETURN_KEY: {\n                    ev.preventDefault();\n\n                    const $currentOption = this.menu.$options.filter('.hover');\n                    if ($currentOption.length > 0) {\n                        $currentOption.get(0).click();\n                    }\n\n                    break;\n                }\n\n                case Garnish.SPACE_KEY: {\n                    ev.preventDefault();\n\n                    if (this.showingMenu) {\n                        const $currentOption = this.menu.$options.filter('.hover');\n                        if ($currentOption.length > 0) {\n                            $currentOption.get(0).click();\n                        }\n                    } else {\n                        this.showMenu();\n\n                        $option = this.menu.$options.filter('.sel:first');\n\n                        if ($option.length === 0) {\n                            $option = this.menu.$options.first();\n                        }\n\n                        this.focusOption($option);\n                    }\n\n                    break;\n                }\n\n                case Garnish.DOWN_KEY: {\n                    ev.preventDefault();\n\n                    if (this.showingMenu) {\n                        $.each(this.menu.$options, function(index, value) {\n                            if (!$option) {\n                                if ($(value).hasClass('hover')) {\n                                    if ((index + 1) < this.menu.$options.length) {\n                                        $option = $(this.menu.$options[(index + 1)]);\n                                    }\n                                }\n                            }\n                        }.bind(this));\n\n                        if (!$option) {\n                            $option = $(this.menu.$options[0]);\n                        }\n                    }\n                    else {\n                        this.showMenu();\n\n                        $option = this.menu.$options.filter('.sel:first');\n\n                        if ($option.length === 0) {\n                            $option = this.menu.$options.first();\n                        }\n                    }\n\n                    this.focusOption($option);\n\n                    break;\n                }\n\n                case Garnish.UP_KEY: {\n                    ev.preventDefault();\n\n                    if (this.showingMenu) {\n                        $.each(this.menu.$options, function(index, value) {\n                            if (!$option) {\n                                if ($(value).hasClass('hover')) {\n                                    if ((index - 1) >= 0) {\n                                        $option = $(this.menu.$options[(index - 1)]);\n                                    }\n                                }\n                            }\n                        }.bind(this));\n\n                        if (!$option) {\n                            $option = $(this.menu.$options[(this.menu.$options.length - 1)]);\n                        }\n                    }\n                    else {\n                        this.showMenu();\n\n                        $option = this.menu.$options.filter('.sel:first');\n\n                        if ($option.length === 0) {\n                            $option = this.menu.$options.last();\n                        }\n                    }\n\n                    this.focusOption($option);\n\n                    break;\n                }\n            }\n        },\n\n        focusOption: function($option) {\n            this.menu.$options.removeClass('hover');\n\n            $option.addClass('hover');\n\n            this.menu.$menuList.attr('aria-activedescendant', $option.attr('id'));\n            this.$btn.attr('aria-activedescendant', $option.attr('id'));\n        },\n\n        onMouseDown: function(ev) {\n            if (ev.which !== Garnish.PRIMARY_CLICK || Garnish.isCtrlKeyPressed(ev) || ev.target.nodeName === 'INPUT') {\n                return;\n            }\n\n            ev.preventDefault();\n\n            if (this.showingMenu) {\n                this.hideMenu();\n            }\n            else {\n                this.showMenu();\n            }\n        },\n\n        showMenu: function() {\n            if (this.disabled) {\n                return;\n            }\n\n            this.menu.show();\n            this.$btn.addClass('active');\n            this.$btn.trigger('focus');\n            this.$btn.attr('aria-expanded', 'true');\n\n            this.showingMenu = true;\n\n            setTimeout(function() {\n                this.addListener(Garnish.$doc, 'mousedown', 'onMouseDown');\n            }.bind(this), 1);\n        },\n\n        hideMenu: function() {\n            this.menu.hide();\n            this.$btn.attr('aria-expanded', 'false');\n        },\n\n        onMenuHide: function() {\n            this.$btn.removeClass('active');\n            this.showingMenu = false;\n\n            this.removeListener(Garnish.$doc, 'mousedown');\n        },\n\n        onOptionSelect: function(option) {\n            this.settings.onOptionSelect(option);\n            this.trigger('optionSelect', {option: option});\n        },\n\n        enable: function() {\n            this.disabled = false;\n        },\n\n        disable: function() {\n            this.disabled = true;\n        },\n\n        /**\n         * Destroy\n         */\n        destroy: function() {\n            this.$btn.removeData('menubtn');\n            this.base();\n        }\n    },\n    {\n        defaults: {\n            menuAnchor: null,\n            onOptionSelect: $.noop\n        }\n    }\n);\n\n/** global: Garnish */\n/**\n * Mixed input\n *\n * @todo RTL support, in the event that the input doesn't have dir=\"ltr\".\n */\nGarnish.MixedInput = Garnish.Base.extend(\n    {\n        $container: null,\n        elements: null,\n        focussedElement: null,\n        blurTimeout: null,\n\n        init: function(container, settings) {\n            this.$container = $(container);\n            this.setSettings(settings, Garnish.MixedInput.defaults);\n\n            this.elements = [];\n\n            // Allow the container to receive focus\n            this.$container.attr('tabindex', 0);\n            this.addListener(this.$container, 'focus', 'onFocus');\n        },\n\n        getElementIndex: function($elem) {\n            return $.inArray($elem, this.elements);\n        },\n\n        isText: function($elem) {\n            return ($elem.prop('nodeName') === 'INPUT');\n        },\n\n        onFocus: function() {\n            // Set focus to the first element\n            if (this.elements.length) {\n                var $elem = this.elements[0];\n                this.setFocus($elem);\n                this.setCarotPos($elem, 0);\n            }\n            else {\n                this.addTextElement();\n            }\n        },\n\n        addTextElement: function(index) {\n            var text = new TextElement(this);\n            this.addElement(text.$input, index);\n            return text;\n        },\n\n        addElement: function($elem, index) {\n            // Was a target index passed, and is it valid?\n            if (typeof index === 'undefined') {\n                if (this.focussedElement) {\n                    var focussedElement = this.focussedElement,\n                        focussedElementIndex = this.getElementIndex(focussedElement);\n\n                    // Is the focus on a text element?\n                    if (this.isText(focussedElement)) {\n                        var selectionStart = focussedElement.prop('selectionStart'),\n                            selectionEnd = focussedElement.prop('selectionEnd'),\n                            val = focussedElement.val(),\n                            preVal = val.substring(0, selectionStart),\n                            postVal = val.substr(selectionEnd);\n\n                        if (preVal && postVal) {\n                            // Split the input into two\n                            focussedElement.val(preVal).trigger('change');\n                            var newText = new TextElement(this);\n                            newText.$input.val(postVal).trigger('change');\n                            this.addElement(newText.$input, focussedElementIndex + 1);\n\n                            // Insert the new element in between them\n                            index = focussedElementIndex + 1;\n                        }\n                        else if (!preVal) {\n                            // Insert the new element before this one\n                            index = focussedElementIndex;\n                        }\n                        else {\n                            // Insert it after this one\n                            index = focussedElementIndex + 1;\n                        }\n                    }\n                    else {\n                        // Just insert the new one after this one\n                        index = focussedElementIndex + 1;\n                    }\n                }\n                else {\n                    // Insert the new element at the end\n                    index = this.elements.length;\n                }\n            }\n\n            // Add the element\n            if (typeof this.elements[index] !== 'undefined') {\n                $elem.insertBefore(this.elements[index]);\n                this.elements.splice(index, 0, $elem);\n            }\n            else {\n                // Just for safe measure, set the index to what it really will be\n                index = this.elements.length;\n\n                this.$container.append($elem);\n                this.elements.push($elem);\n            }\n\n            // Make sure that there are text elements surrounding all non-text elements\n            if (!this.isText($elem)) {\n                // Add a text element before?\n                if (index === 0 || !this.isText(this.elements[index - 1])) {\n                    this.addTextElement(index);\n                    index++;\n                }\n\n                // Add a text element after?\n                if (index === this.elements.length - 1 || !this.isText(this.elements[index + 1])) {\n                    this.addTextElement(index + 1);\n                }\n            }\n\n            // Add event listeners\n            this.addListener($elem, 'click', function() {\n                this.setFocus($elem);\n            });\n\n            // Set focus to the new element\n            setTimeout(function() {\n                this.setFocus($elem);\n            }.bind(this), 1);\n        },\n\n        removeElement: function($elem) {\n            var index = this.getElementIndex($elem);\n            if (index !== -1) {\n                this.elements.splice(index, 1);\n\n                if (!this.isText($elem)) {\n                    // Combine the two now-adjacent text elements\n                    var $prevElem = this.elements[index - 1],\n                        $nextElem = this.elements[index];\n\n                    if (this.isText($prevElem) && this.isText($nextElem)) {\n                        var prevElemVal = $prevElem.val(),\n                            newVal = prevElemVal + $nextElem.val();\n                        $prevElem.val(newVal).trigger('change');\n                        this.removeElement($nextElem);\n                        this.setFocus($prevElem);\n                        this.setCarotPos($prevElem, prevElemVal.length);\n                    }\n                }\n\n                $elem.remove();\n            }\n        },\n\n        setFocus: function($elem) {\n            this.$container.addClass('focus');\n\n            if (!this.focussedElement) {\n                // Prevent the container from receiving focus\n                // as long as one of its elements has focus\n                this.$container.attr('tabindex', '-1');\n            }\n            else {\n                // Blur the previously-focussed element\n                this.blurFocussedElement();\n            }\n\n            $elem.attr('tabindex', '0');\n            $elem.focus();\n            this.focussedElement = $elem;\n\n            this.addListener($elem, 'blur', function() {\n                this.blurTimeout = setTimeout(function() {\n                    if (this.focussedElement === $elem) {\n                        this.blurFocussedElement();\n                        this.focussedElement = null;\n                        this.$container.removeClass('focus');\n\n                        // Get ready for future focus\n                        this.$container.attr('tabindex', '0');\n                    }\n                }.bind(this), 1);\n            });\n        },\n\n        blurFocussedElement: function() {\n            this.removeListener(this.focussedElement, 'blur');\n            this.focussedElement.attr('tabindex', '-1');\n        },\n\n        focusPreviousElement: function($from) {\n            var index = this.getElementIndex($from);\n\n            if (index > 0) {\n                var $elem = this.elements[index - 1];\n                this.setFocus($elem);\n\n                // If it's a text element, put the carot at the end\n                if (this.isText($elem)) {\n                    var length = $elem.val().length;\n                    this.setCarotPos($elem, length);\n                }\n            }\n        },\n\n        focusNextElement: function($from) {\n            var index = this.getElementIndex($from);\n\n            if (index < this.elements.length - 1) {\n                var $elem = this.elements[index + 1];\n                this.setFocus($elem);\n\n                // If it's a text element, put the carot at the beginning\n                if (this.isText($elem)) {\n                    this.setCarotPos($elem, 0)\n                }\n            }\n        },\n\n        setCarotPos: function($elem, pos) {\n            $elem.prop('selectionStart', pos);\n            $elem.prop('selectionEnd', pos);\n        }\n\n    });\n\n\nvar TextElement = Garnish.Base.extend({\n\n        parentInput: null,\n        $input: null,\n        $stage: null,\n        val: null,\n        focussed: false,\n        interval: null,\n\n        init: function(parentInput) {\n            this.parentInput = parentInput;\n\n            this.$input = $('<input type=\"text\"/>').appendTo(this.parentInput.$container);\n            this.$input.css('margin-right', (2 - TextElement.padding) + 'px');\n\n            this.setWidth();\n\n            this.addListener(this.$input, 'focus', 'onFocus');\n            this.addListener(this.$input, 'blur', 'onBlur');\n            this.addListener(this.$input, 'keydown', 'onKeyDown');\n            this.addListener(this.$input, 'change', 'checkInput');\n        },\n\n        getIndex: function() {\n            return this.parentInput.getElementIndex(this.$input);\n        },\n\n        buildStage: function() {\n            this.$stage = $('<stage/>').appendTo(Garnish.$bod);\n\n            // replicate the textarea's text styles\n            this.$stage.css({\n                position: 'absolute',\n                top: -9999,\n                left: -9999,\n                wordWrap: 'nowrap'\n            });\n\n            Garnish.copyTextStyles(this.$input, this.$stage);\n        },\n\n        getTextWidth: function(val) {\n            if (!this.$stage) {\n                this.buildStage();\n            }\n\n            if (val) {\n                // Ampersand entities\n                val = val.replace(/&/g, '&amp;');\n\n                // < and >\n                val = val.replace(/</g, '&lt;');\n                val = val.replace(/>/g, '&gt;');\n\n                // Spaces\n                val = val.replace(/ /g, '&nbsp;');\n            }\n\n            this.$stage.html(val);\n            this.stageWidth = this.$stage.width();\n            return this.stageWidth;\n        },\n\n        onFocus: function() {\n            this.focussed = true;\n            this.interval = setInterval(this.checkInput.bind(this), Garnish.NiceText.interval);\n            this.checkInput();\n        },\n\n        onBlur: function() {\n            this.focussed = false;\n            clearInterval(this.interval);\n            this.checkInput();\n        },\n\n        onKeyDown: function(ev) {\n            setTimeout(this.checkInput.bind(this), 1);\n\n            switch (ev.keyCode) {\n                case Garnish.LEFT_KEY: {\n                    if (this.$input.prop('selectionStart') === 0 && this.$input.prop('selectionEnd') === 0) {\n                        // Set focus to the previous element\n                        this.parentInput.focusPreviousElement(this.$input);\n                    }\n                    break;\n                }\n\n                case Garnish.RIGHT_KEY: {\n                    if (this.$input.prop('selectionStart') === this.val.length && this.$input.prop('selectionEnd') === this.val.length) {\n                        // Set focus to the next element\n                        this.parentInput.focusNextElement(this.$input);\n                    }\n                    break;\n                }\n\n                case Garnish.DELETE_KEY: {\n                    if (this.$input.prop('selectionStart') === 0 && this.$input.prop('selectionEnd') === 0) {\n                        // Set focus to the previous element\n                        this.parentInput.focusPreviousElement(this.$input);\n                        ev.preventDefault();\n                    }\n                }\n            }\n        },\n\n        getVal: function() {\n            this.val = this.$input.val();\n            return this.val;\n        },\n\n        setVal: function(val) {\n            this.$input.val(val);\n            this.checkInput();\n        },\n\n        checkInput: function() {\n            // Has the value changed?\n            var changed = (this.val !== this.getVal());\n            if (changed) {\n                this.setWidth();\n                this.onChange();\n            }\n\n            return changed;\n        },\n\n        setWidth: function() {\n            // has the width changed?\n            if (this.stageWidth !== this.getTextWidth(this.val)) {\n                // update the textarea width\n                var width = this.stageWidth + TextElement.padding;\n                this.$input.width(width);\n            }\n        },\n\n        onChange: $.noop\n    },\n    {\n        padding: 20\n    }\n);\n\n/** global: Garnish */\n/**\n * Modal\n */\nGarnish.Modal = Garnish.Base.extend(\n    {\n        $container: null,\n        $shade: null,\n\n        visible: false,\n\n        dragger: null,\n\n        desiredWidth: null,\n        desiredHeight: null,\n        resizeDragger: null,\n        resizeStartWidth: null,\n        resizeStartHeight: null,\n\n        init: function(container, settings) {\n            // Param mapping\n            if (typeof settings === 'undefined' && $.isPlainObject(container)) {\n                // (settings)\n                settings = container;\n                container = null;\n            }\n\n            this.setSettings(settings, Garnish.Modal.defaults);\n\n            // Create the shade\n            this.$shade = $('<div class=\"' + this.settings.shadeClass + '\"/>');\n\n            // If the container is already set, drop the shade below it.\n            if (container) {\n                this.$shade.insertBefore(container);\n            }\n            else {\n                this.$shade.appendTo(Garnish.$bod);\n            }\n\n            if (container) {\n                this.setContainer(container);\n\n                if (this.settings.autoShow) {\n                    this.show();\n                }\n            }\n\n            Garnish.Modal.instances.push(this);\n        },\n\n        setContainer: function(container) {\n            this.$container = $(container);\n\n            // Is this already a modal?\n            if (this.$container.data('modal')) {\n                Garnish.log('Double-instantiating a modal on an element');\n                this.$container.data('modal').destroy();\n            }\n\n            this.$container.data('modal', this);\n\n            if (this.settings.draggable) {\n                this.dragger = new Garnish.DragMove(this.$container, {\n                    handle: (this.settings.dragHandleSelector ? this.$container.find(this.settings.dragHandleSelector) : this.$container)\n                });\n            }\n\n            if (this.settings.resizable) {\n                var $resizeDragHandle = $('<div class=\"resizehandle\"/>').appendTo(this.$container);\n\n                this.resizeDragger = new Garnish.BaseDrag($resizeDragHandle, {\n                    onDragStart: this._handleResizeStart.bind(this),\n                    onDrag: this._handleResize.bind(this)\n                });\n            }\n\n            this.addListener(this.$container, 'click', function(ev) {\n                ev.stopPropagation();\n            });\n\n            // Show it if we're late to the party\n            if (this.visible) {\n                this.show();\n            }\n        },\n\n        show: function() {\n            // Close other modals as needed\n            if (this.settings.closeOtherModals && Garnish.Modal.visibleModal && Garnish.Modal.visibleModal !== this) {\n                Garnish.Modal.visibleModal.hide();\n            }\n\n            if (this.$container) {\n                // Move it to the end of <body> so it gets the highest sub-z-index\n                this.$shade.appendTo(Garnish.$bod);\n                this.$container.appendTo(Garnish.$bod);\n\n                this.$container.show();\n                this.updateSizeAndPosition();\n\n                this.$shade.velocity('fadeIn', {\n                    duration: 50,\n                    complete: function() {\n                        this.$container.velocity('fadeIn', {\n                            complete: function() {\n                                this.updateSizeAndPosition();\n                                this.onFadeIn();\n                            }.bind(this)\n                        });\n                    }.bind(this)\n                });\n\n                if (this.settings.hideOnShadeClick) {\n                    this.addListener(this.$shade, 'click', 'hide');\n                }\n\n                this.addListener(Garnish.$win, 'resize', '_handleWindowResize');\n            }\n\n            this.enable();\n\n            if (!this.visible) {\n                this.visible = true;\n                Garnish.Modal.visibleModal = this;\n\n                Garnish.shortcutManager.addLayer();\n\n                if (this.settings.hideOnEsc) {\n                    Garnish.shortcutManager.registerShortcut(Garnish.ESC_KEY, this.hide.bind(this));\n                }\n\n                this.trigger('show');\n                this.settings.onShow();\n            }\n        },\n\n        quickShow: function() {\n            this.show();\n\n            if (this.$container) {\n                this.$container.velocity('stop');\n                this.$container.show().css('opacity', 1);\n\n                this.$shade.velocity('stop');\n                this.$shade.show().css('opacity', 1);\n            }\n        },\n\n        hide: function(ev) {\n            if (!this.visible) {\n                return;\n            }\n\n            this.disable();\n\n            if (ev) {\n                ev.stopPropagation();\n            }\n\n            if (this.$container) {\n                this.$container.velocity('fadeOut', {duration: Garnish.FX_DURATION});\n                this.$shade.velocity('fadeOut', {\n                    duration: Garnish.FX_DURATION,\n                    complete: this.onFadeOut.bind(this)\n                });\n\n                if (this.settings.hideOnShadeClick) {\n                    this.removeListener(this.$shade, 'click');\n                }\n\n                this.removeListener(Garnish.$win, 'resize');\n            }\n\n            this.visible = false;\n            Garnish.Modal.visibleModal = null;\n            Garnish.shortcutManager.removeLayer();\n            this.trigger('hide');\n            this.settings.onHide();\n        },\n\n        quickHide: function() {\n            this.hide();\n\n            if (this.$container) {\n                this.$container.velocity('stop');\n                this.$container.css('opacity', 0).hide();\n\n                this.$shade.velocity('stop');\n                this.$shade.css('opacity', 0).hide();\n            }\n        },\n\n        updateSizeAndPosition: function() {\n            if (!this.$container) {\n                return;\n            }\n\n            this.$container.css({\n                'width': (this.desiredWidth ? Math.max(this.desiredWidth, 200) : ''),\n                'height': (this.desiredHeight ? Math.max(this.desiredHeight, 200) : ''),\n                'min-width': '',\n                'min-height': ''\n            });\n\n            // Set the width first so that the height can adjust for the width\n            this.updateSizeAndPosition._windowWidth = Garnish.$win.width();\n            this.updateSizeAndPosition._width = Math.min(this.getWidth(), this.updateSizeAndPosition._windowWidth - this.settings.minGutter * 2);\n\n            this.$container.css({\n                'width': this.updateSizeAndPosition._width,\n                'min-width': this.updateSizeAndPosition._width,\n                'left': Math.round((this.updateSizeAndPosition._windowWidth - this.updateSizeAndPosition._width) / 2)\n            });\n\n            // Now set the height\n            this.updateSizeAndPosition._windowHeight = Garnish.$win.height();\n            this.updateSizeAndPosition._height = Math.min(this.getHeight(), this.updateSizeAndPosition._windowHeight - this.settings.minGutter * 2);\n\n            this.$container.css({\n                'height': this.updateSizeAndPosition._height,\n                'min-height': this.updateSizeAndPosition._height,\n                'top': Math.round((this.updateSizeAndPosition._windowHeight - this.updateSizeAndPosition._height) / 2)\n            });\n\n            this.trigger('updateSizeAndPosition');\n        },\n\n        onFadeIn: function() {\n            this.trigger('fadeIn');\n            this.settings.onFadeIn();\n        },\n\n        onFadeOut: function() {\n            this.trigger('fadeOut');\n            this.settings.onFadeOut();\n        },\n\n        getHeight: function() {\n            if (!this.$container) {\n                throw 'Attempted to get the height of a modal whose container has not been set.';\n            }\n\n            if (!this.visible) {\n                this.$container.show();\n            }\n\n            this.getHeight._height = this.$container.outerHeight();\n\n            if (!this.visible) {\n                this.$container.hide();\n            }\n\n            return this.getHeight._height;\n        },\n\n        getWidth: function() {\n            if (!this.$container) {\n                throw 'Attempted to get the width of a modal whose container has not been set.';\n            }\n\n            if (!this.visible) {\n                this.$container.show();\n            }\n\n            // Chrome might be 1px shy here for some reason\n            this.getWidth._width = this.$container.outerWidth() + 1;\n\n            if (!this.visible) {\n                this.$container.hide();\n            }\n\n            return this.getWidth._width;\n        },\n\n        _handleWindowResize: function(ev) {\n            // ignore propagated resize events\n            if (ev.target === window) {\n                this.updateSizeAndPosition();\n            }\n        },\n\n        _handleResizeStart: function() {\n            this.resizeStartWidth = this.getWidth();\n            this.resizeStartHeight = this.getHeight();\n        },\n\n        _handleResize: function() {\n            if (Garnish.ltr) {\n                this.desiredWidth = this.resizeStartWidth + (this.resizeDragger.mouseDistX * 2);\n            }\n            else {\n                this.desiredWidth = this.resizeStartWidth - (this.resizeDragger.mouseDistX * 2);\n            }\n\n            this.desiredHeight = this.resizeStartHeight + (this.resizeDragger.mouseDistY * 2);\n\n            this.updateSizeAndPosition();\n        },\n\n        /**\n         * Destroy\n         */\n        destroy: function() {\n            if (this.$container) {\n                this.$container.removeData('modal').remove();\n            }\n\n            if (this.dragger) {\n                this.dragger.destroy();\n            }\n\n            if (this.resizeDragger) {\n                this.resizeDragger.destroy();\n            }\n\n            this.base();\n        }\n    },\n    {\n        relativeElemPadding: 8,\n        defaults: {\n            autoShow: true,\n            draggable: false,\n            dragHandleSelector: null,\n            resizable: false,\n            minGutter: 10,\n            onShow: $.noop,\n            onHide: $.noop,\n            onFadeIn: $.noop,\n            onFadeOut: $.noop,\n            closeOtherModals: false,\n            hideOnEsc: true,\n            hideOnShadeClick: true,\n            shadeClass: 'modal-shade'\n        },\n        instances: [],\n        visibleModal: null\n    }\n);\n\n/** global: Garnish */\n/**\n * Nice Text\n */\nGarnish.NiceText = Garnish.Base.extend(\n    {\n        $input: null,\n        $hint: null,\n        $stage: null,\n        $charsLeft: null,\n        autoHeight: null,\n        maxLength: null,\n        showCharsLeft: false,\n        showingHint: false,\n        val: null,\n        inputBoxSizing: 'content-box',\n        width: null,\n        height: null,\n        minHeight: null,\n        initialized: false,\n\n        init: function(input, settings) {\n            this.$input = $(input);\n            this.settings = $.extend({}, Garnish.NiceText.defaults, settings);\n\n            if (this.isVisible()) {\n                this.initialize();\n            }\n            else {\n                this.addListener(Garnish.$win, 'resize', 'initializeIfVisible');\n            }\n        },\n\n        isVisible: function() {\n            return (this.$input.height() > 0);\n        },\n\n        initialize: function() {\n            if (this.initialized) {\n                return;\n            }\n\n            this.initialized = true;\n            this.removeListener(Garnish.$win, 'resize');\n\n            this.maxLength = this.$input.attr('maxlength');\n\n            if (this.maxLength) {\n                this.maxLength = parseInt(this.maxLength);\n            }\n\n            if (this.maxLength && (this.settings.showCharsLeft || Garnish.hasAttr(this.$input, 'data-show-chars-left'))) {\n                this.showCharsLeft = true;\n\n                // Remove the maxlength attribute\n                this.$input.removeAttr('maxlength');\n            }\n\n            // Is this already a transparent text input?\n            if (this.$input.data('nicetext')) {\n                Garnish.log('Double-instantiating a transparent text input on an element');\n                this.$input.data('nicetext').destroy();\n            }\n\n            this.$input.data('nicetext', this);\n\n            this.getVal();\n\n            this.autoHeight = (this.settings.autoHeight && this.$input.prop('nodeName') === 'TEXTAREA');\n\n            if (this.autoHeight) {\n                this.minHeight = this.getHeightForValue('');\n                this.updateHeight();\n\n                // Update height when the window resizes\n                this.width = this.$input.width();\n                this.addListener(Garnish.$win, 'resize', 'updateHeightIfWidthChanged');\n            }\n\n            if (this.settings.hint) {\n                this.$hintContainer = $('<div class=\"texthint-container\"/>').insertBefore(this.$input);\n                this.$hint = $('<div class=\"texthint\">' + this.settings.hint + '</div>').appendTo(this.$hintContainer);\n                this.$hint.css({\n                    top: (parseInt(this.$input.css('borderTopWidth')) + parseInt(this.$input.css('paddingTop'))),\n                    left: (parseInt(this.$input.css('borderLeftWidth')) + parseInt(this.$input.css('paddingLeft')) + 1)\n                });\n                Garnish.copyTextStyles(this.$input, this.$hint);\n\n                if (this.val) {\n                    this.$hint.hide();\n                }\n                else {\n                    this.showingHint = true;\n                }\n\n                // Focus the input when clicking on the hint\n                this.addListener(this.$hint, 'mousedown', function(ev) {\n                    ev.preventDefault();\n                    this.$input.focus();\n                });\n            }\n\n            if (this.showCharsLeft) {\n                this.$charsLeft = $('<div aria-live=\"polite\" class=\"' + this.settings.charsLeftClass + '\"/>').insertAfter(this.$input);\n                this.updateCharsLeft();\n            }\n\n            this.addListener(this.$input, 'textchange', 'onTextChange');\n            this.addListener(this.$input, 'keydown', 'onKeyDown');\n        },\n\n        initializeIfVisible: function() {\n            if (this.isVisible()) {\n                this.initialize();\n            }\n        },\n\n        getVal: function() {\n            this.val = this.$input.val();\n            return this.val;\n        },\n\n        showHint: function() {\n            this.$hint.velocity('fadeIn', {\n                complete: Garnish.NiceText.hintFadeDuration\n            });\n\n            this.showingHint = true;\n        },\n\n        hideHint: function() {\n            this.$hint.velocity('fadeOut', {\n                complete: Garnish.NiceText.hintFadeDuration\n            });\n\n            this.showingHint = false;\n        },\n\n        onTextChange: function() {\n            this.getVal();\n\n            if (this.$hint) {\n                if (this.showingHint && this.val) {\n                    this.hideHint();\n                }\n                else if (!this.showingHint && !this.val) {\n                    this.showHint();\n                }\n            }\n\n            if (this.autoHeight) {\n                this.updateHeight();\n            }\n\n            if (this.showCharsLeft) {\n                this.updateCharsLeft();\n            }\n        },\n\n        onKeyDown: function(ev) {\n            // If Ctrl/Command + Return is pressed, submit the closest form\n            if (ev.keyCode === Garnish.RETURN_KEY && Garnish.isCtrlKeyPressed(ev)) {\n                ev.preventDefault();\n                this.$input.closest('form').submit();\n            }\n        },\n\n        buildStage: function() {\n            this.$stage = $('<stage/>').appendTo(Garnish.$bod);\n\n            // replicate the textarea's text styles\n            this.$stage.css({\n                display: 'block',\n                position: 'absolute',\n                top: -9999,\n                left: -9999\n            });\n\n            this.inputBoxSizing = this.$input.css('box-sizing');\n\n            if (this.inputBoxSizing === 'border-box') {\n                this.$stage.css({\n                    'border-top': this.$input.css('border-top'),\n                    'border-right': this.$input.css('border-right'),\n                    'border-bottom': this.$input.css('border-bottom'),\n                    'border-left': this.$input.css('border-left'),\n                    'padding-top': this.$input.css('padding-top'),\n                    'padding-right': this.$input.css('padding-right'),\n                    'padding-bottom': this.$input.css('padding-bottom'),\n                    'padding-left': this.$input.css('padding-left'),\n                    '-webkit-box-sizing': this.inputBoxSizing,\n                    '-moz-box-sizing': this.inputBoxSizing,\n                    'box-sizing': this.inputBoxSizing\n                });\n            }\n\n            Garnish.copyTextStyles(this.$input, this.$stage);\n        },\n\n        getHeightForValue: function(val) {\n            if (!this.$stage) {\n                this.buildStage();\n            }\n\n            if (this.inputBoxSizing === 'border-box') {\n                this.$stage.css('width', this.$input.outerWidth());\n            }\n            else {\n                this.$stage.css('width', this.$input.width());\n            }\n\n            if (!val) {\n                val = '&nbsp;';\n                for (var i = 1; i < this.$input.prop('rows'); i++) {\n                    val += '<br/>&nbsp;';\n                }\n            }\n            else {\n                // Ampersand entities\n                val = val.replace(/&/g, '&amp;');\n\n                // < and >\n                val = val.replace(/</g, '&lt;');\n                val = val.replace(/>/g, '&gt;');\n\n                // Multiple spaces\n                val = val.replace(/ {2,}/g, function(spaces) {\n                    // TODO: replace with String.repeat() when more broadly available?\n                    var replace = '';\n                    for (var i = 0; i < spaces.length - 1; i++) {\n                        replace += '&nbsp;';\n                    }\n                    return replace + ' ';\n                });\n\n                // Line breaks\n                val = val.replace(/[\\n\\r]$/g, '<br/>&nbsp;');\n                val = val.replace(/[\\n\\r]/g, '<br/>');\n            }\n\n            this.$stage.html(val);\n\n            if (this.inputBoxSizing === 'border-box') {\n                this.getHeightForValue._height = this.$stage.outerHeight();\n            }\n            else {\n                this.getHeightForValue._height = this.$stage.height();\n            }\n\n            if (this.minHeight && this.getHeightForValue._height < this.minHeight) {\n                this.getHeightForValue._height = this.minHeight;\n            }\n\n            return this.getHeightForValue._height;\n        },\n\n        updateHeight: function() {\n            // has the height changed?\n            if (this.height !== (this.height = this.getHeightForValue(this.val))) {\n                this.$input.css('min-height', this.height);\n\n                if (this.initialized) {\n                    this.onHeightChange();\n                }\n            }\n        },\n\n        updateHeightIfWidthChanged: function() {\n            if (this.isVisible() && this.width !== (this.width = this.$input.width()) && this.width) {\n                this.updateHeight();\n            }\n        },\n\n        onHeightChange: function() {\n            this.settings.onHeightChange();\n        },\n\n        updateCharsLeft: function() {\n            this.updateCharsLeft._charsLeft = this.maxLength - this.val.length;\n            this.$charsLeft.html(Garnish.NiceText.charsLeftHtml(this.updateCharsLeft._charsLeft));\n\n            if (this.updateCharsLeft._charsLeft >= 0) {\n                this.$charsLeft.removeClass(this.settings.negativeCharsLeftClass);\n            }\n            else {\n                this.$charsLeft.addClass(this.settings.negativeCharsLeftClass);\n            }\n        },\n\n        /**\n         * Destroy\n         */\n        destroy: function() {\n            this.$input.removeData('nicetext');\n\n            if (this.$hint) {\n                this.$hint.remove();\n            }\n\n            if (this.$stage) {\n                this.$stage.remove();\n            }\n\n            this.base();\n        }\n    },\n    {\n        interval: 100,\n        hintFadeDuration: 50,\n        charsLeftHtml: function(charsLeft) {\n            return charsLeft;\n        },\n        defaults: {\n            autoHeight: true,\n            showCharsLeft: false,\n            charsLeftClass: 'chars-left',\n            negativeCharsLeftClass: 'negative-chars-left',\n            onHeightChange: $.noop\n        }\n    }\n);\n\n/** global: Garnish */\n/**\n * Select\n */\nGarnish.Select = Garnish.Base.extend(\n    {\n        $container: null,\n        $items: null,\n        $selectedItems: null,\n        $focusedItem: null,\n\n        mousedownTarget: null,\n        mouseUpTimeout: null,\n        callbackFrame: null,\n\n        $focusable: null,\n        $first: null,\n        first: null,\n        $last: null,\n        last: null,\n\n        /**\n         * Constructor\n         */\n        init: function(container, items, settings) {\n            this.$container = $(container);\n\n            // Param mapping\n            if (typeof items === 'undefined' && $.isPlainObject(container)) {\n                // (settings)\n                settings = container;\n                container = null;\n                items = null;\n            }\n            else if (typeof settings === 'undefined' && $.isPlainObject(items)) {\n                // (container, settings)\n                settings = items;\n                items = null;\n            }\n\n            // Is this already a select?\n            if (this.$container.data('select')) {\n                Garnish.log('Double-instantiating a select on an element');\n                this.$container.data('select').destroy();\n            }\n\n            this.$container.data('select', this);\n\n            this.setSettings(settings, Garnish.Select.defaults);\n\n            this.$items = $();\n            this.$selectedItems = $();\n\n            this.addItems(items);\n\n            // --------------------------------------------------------------------\n\n            if (this.settings.allowEmpty && !this.settings.checkboxMode) {\n                this.addListener(this.$container, 'click', function() {\n                    if (this.ignoreClick) {\n                        this.ignoreClick = false;\n                    }\n                    else {\n                        // Deselect all items on container click\n                        this.deselectAll(true);\n                    }\n                });\n            }\n        },\n\n        /**\n         * Get Item Index\n         */\n        getItemIndex: function($item) {\n            return this.$items.index($item[0]);\n        },\n\n        /**\n         * Is Selected?\n         */\n        isSelected: function(item) {\n            if (Garnish.isJquery(item)) {\n                if (!item[0]) {\n                    return false;\n                }\n\n                item = item[0];\n            }\n\n            return ($.inArray(item, this.$selectedItems) !== -1);\n        },\n\n        /**\n         * Select Item\n         */\n        selectItem: function($item, focus, preventScroll) {\n            if (!this.settings.multi) {\n                this.deselectAll();\n            }\n\n            this.$first = this.$last = $item;\n            this.first = this.last = this.getItemIndex($item);\n\n            if (focus) {\n                this.setFocusableItem($item);\n                this.focusItem($item, preventScroll);\n            }\n\n            this._selectItems($item);\n        },\n\n        selectAll: function() {\n            if (!this.settings.multi || !this.$items.length) {\n                return;\n            }\n\n            this.first = 0;\n            this.last = this.$items.length - 1;\n            this.$first = this.$items.eq(this.first);\n            this.$last = this.$items.eq(this.last);\n\n            this._selectItems(this.$items);\n        },\n\n        /**\n         * Select Range\n         */\n        selectRange: function($item, preventScroll) {\n            if (!this.settings.multi) {\n                return this.selectItem($item, true, true);\n            }\n\n            this.deselectAll();\n\n            this.$last = $item;\n            this.last = this.getItemIndex($item);\n\n            this.setFocusableItem($item);\n            this.focusItem($item, preventScroll);\n\n            // prepare params for $.slice()\n            var sliceFrom, sliceTo;\n\n            if (this.first < this.last) {\n                sliceFrom = this.first;\n                sliceTo = this.last + 1;\n            }\n            else {\n                sliceFrom = this.last;\n                sliceTo = this.first + 1;\n            }\n\n            this._selectItems(this.$items.slice(sliceFrom, sliceTo));\n        },\n\n        /**\n         * Deselect Item\n         */\n        deselectItem: function($item) {\n            var index = this.getItemIndex($item);\n            if (this.first === index) {\n                this.$first = this.first = null;\n            }\n            if (this.last === index) {\n                this.$last = this.last = null;\n            }\n\n            this._deselectItems($item);\n        },\n\n        /**\n         * Deselect All\n         */\n        deselectAll: function(clearFirst) {\n            if (clearFirst) {\n                this.$first = this.first = this.$last = this.last = null;\n            }\n\n            this._deselectItems(this.$items);\n        },\n\n        /**\n         * Deselect Others\n         */\n        deselectOthers: function($item) {\n            this.deselectAll();\n            this.selectItem($item, true, true);\n        },\n\n        /**\n         * Toggle Item\n         */\n        toggleItem: function($item, preventScroll) {\n            if (!this.isSelected($item)) {\n                this.selectItem($item, true, preventScroll);\n            }\n            else {\n                if (this._canDeselect($item)) {\n                    this.deselectItem($item, true);\n                }\n            }\n        },\n\n        clearMouseUpTimeout: function() {\n            clearTimeout(this.mouseUpTimeout);\n        },\n\n        getFirstItem: function() {\n            if (this.$items.length) {\n                return this.$items.first();\n            }\n        },\n\n        getLastItem: function() {\n            if (this.$items.length) {\n                return this.$items.last();\n            }\n        },\n\n        isPreviousItem: function(index) {\n            return (index > 0);\n        },\n\n        isNextItem: function(index) {\n            return (index < this.$items.length - 1);\n        },\n\n        getPreviousItem: function(index) {\n            if (this.isPreviousItem(index)) {\n                return this.$items.eq(index - 1);\n            }\n        },\n\n        getNextItem: function(index) {\n            if (this.isNextItem(index)) {\n                return this.$items.eq(index + 1);\n            }\n        },\n\n        getItemToTheLeft: function(index) {\n            var func = (Garnish.ltr ? 'Previous' : 'Next');\n\n            if (this['is' + func + 'Item'](index)) {\n                if (this.settings.horizontal) {\n                    return this['get' + func + 'Item'](index);\n                }\n                if (!this.settings.vertical) {\n                    return this.getClosestItem(index, Garnish.X_AXIS, '<');\n                }\n            }\n        },\n\n        getItemToTheRight: function(index) {\n            var func = (Garnish.ltr ? 'Next' : 'Previous');\n\n            if (this['is' + func + 'Item'](index)) {\n                if (this.settings.horizontal) {\n                    return this['get' + func + 'Item'](index);\n                }\n                else if (!this.settings.vertical) {\n                    return this.getClosestItem(index, Garnish.X_AXIS, '>');\n                }\n            }\n        },\n\n        getItemAbove: function(index) {\n            if (this.isPreviousItem(index)) {\n                if (this.settings.vertical) {\n                    return this.getPreviousItem(index);\n                }\n                else if (!this.settings.horizontal) {\n                    return this.getClosestItem(index, Garnish.Y_AXIS, '<');\n                }\n            }\n        },\n\n        getItemBelow: function(index) {\n            if (this.isNextItem(index)) {\n                if (this.settings.vertical) {\n                    return this.getNextItem(index);\n                }\n                else if (!this.settings.horizontal) {\n                    return this.getClosestItem(index, Garnish.Y_AXIS, '>');\n                }\n            }\n        },\n\n        getClosestItem: function(index, axis, dir) {\n            var axisProps = Garnish.Select.closestItemAxisProps[axis],\n                dirProps = Garnish.Select.closestItemDirectionProps[dir];\n\n            var $thisItem = this.$items.eq(index),\n                thisOffset = $thisItem.offset(),\n                thisMidpoint = thisOffset[axisProps.midpointOffset] + Math.round($thisItem[axisProps.midpointSizeFunc]() / 2),\n                otherRowPos = null,\n                smallestMidpointDiff = null,\n                $closestItem = null;\n\n            // Go the other way if this is the X axis and a RTL page\n            var step;\n\n            if (Garnish.rtl && axis === Garnish.X_AXIS) {\n                step = dirProps.step * -1;\n            }\n            else {\n                step = dirProps.step;\n            }\n\n            for (var i = index + step; (typeof this.$items[i] !== 'undefined'); i += step) {\n                var $otherItem = this.$items.eq(i),\n                    otherOffset = $otherItem.offset();\n\n                // Are we on the next row yet?\n                if (dirProps.isNextRow(otherOffset[axisProps.rowOffset], thisOffset[axisProps.rowOffset])) {\n                    // Is this the first time we've seen this row?\n                    if (otherRowPos === null) {\n                        otherRowPos = otherOffset[axisProps.rowOffset];\n                    }\n                    // Have we gone too far?\n                    else if (otherOffset[axisProps.rowOffset] !== otherRowPos) {\n                        break;\n                    }\n\n                    var otherMidpoint = otherOffset[axisProps.midpointOffset] + Math.round($otherItem[axisProps.midpointSizeFunc]() / 2),\n                        midpointDiff = Math.abs(thisMidpoint - otherMidpoint);\n\n                    // Are we getting warmer?\n                    if (smallestMidpointDiff === null || midpointDiff < smallestMidpointDiff) {\n                        smallestMidpointDiff = midpointDiff;\n                        $closestItem = $otherItem;\n                    }\n                    // Getting colder?\n                    else {\n                        break;\n                    }\n                }\n                // Getting colder?\n                else if (dirProps.isWrongDirection(otherOffset[axisProps.rowOffset], thisOffset[axisProps.rowOffset])) {\n                    break;\n                }\n            }\n\n            return $closestItem;\n        },\n\n        getFurthestItemToTheLeft: function(index) {\n            return this.getFurthestItem(index, 'ToTheLeft');\n        },\n\n        getFurthestItemToTheRight: function(index) {\n            return this.getFurthestItem(index, 'ToTheRight');\n        },\n\n        getFurthestItemAbove: function(index) {\n            return this.getFurthestItem(index, 'Above');\n        },\n\n        getFurthestItemBelow: function(index) {\n            return this.getFurthestItem(index, 'Below');\n        },\n\n        getFurthestItem: function(index, dir) {\n            var $item, $testItem;\n\n            while ($testItem = this['getItem' + dir](index)) {\n                $item = $testItem;\n                index = this.getItemIndex($item);\n            }\n\n            return $item;\n        },\n\n        /**\n         * totalSelected getter\n         */\n        get totalSelected() {\n            return this.getTotalSelected();\n        },\n\n        /**\n         * Get Total Selected\n         */\n        getTotalSelected: function() {\n            return this.$selectedItems.length;\n        },\n\n        /**\n         * Add Items\n         */\n        addItems: function(items) {\n            var $items = $(items);\n\n            for (var i = 0; i < $items.length; i++) {\n                var item = $items[i];\n\n                // Make sure this element doesn't belong to another selector\n                if ($.data(item, 'select')) {\n                    Garnish.log('Element was added to more than one selector');\n                    $.data(item, 'select').removeItems(item);\n                }\n\n                // Add the item\n                $.data(item, 'select', this);\n\n                // Get the handle\n                var $handle;\n\n                if (this.settings.handle) {\n                    if (typeof this.settings.handle === 'object') {\n                        $handle = $(this.settings.handle);\n                    }\n                    else if (typeof this.settings.handle === 'string') {\n                        $handle = $(item).find(this.settings.handle);\n                    }\n                    else if (typeof this.settings.handle === 'function') {\n                        $handle = $(this.settings.handle(item));\n                    }\n                }\n                else {\n                    $handle = $(item);\n                }\n\n                $.data(item, 'select-handle', $handle);\n                $handle.data('select-item', item);\n\n                this.addListener($handle, 'mousedown', 'onMouseDown');\n                this.addListener($handle, 'mouseup', 'onMouseUp');\n                this.addListener($handle, 'click', function() {\n                    this.ignoreClick = true;\n                });\n\n                this.addListener(item, 'keydown', 'onKeyDown');\n            }\n\n            this.$items = this.$items.add($items);\n            this.updateIndexes();\n        },\n\n        /**\n         * Remove Items\n         */\n        removeItems: function(items) {\n            items = $.makeArray(items);\n\n            var itemsChanged = false,\n                selectionChanged = false;\n\n            for (var i = 0; i < items.length; i++) {\n                var item = items[i];\n\n                // Make sure we actually know about this item\n                var index = $.inArray(item, this.$items);\n                if (index !== -1) {\n                    this._deinitItem(item);\n                    this.$items.splice(index, 1);\n                    itemsChanged = true;\n\n                    var selectedIndex = $.inArray(item, this.$selectedItems);\n                    if (selectedIndex !== -1) {\n                        this.$selectedItems.splice(selectedIndex, 1);\n                        selectionChanged = true;\n                    }\n                }\n            }\n\n            if (itemsChanged) {\n                this.updateIndexes();\n\n                if (selectionChanged) {\n                    $(items).removeClass(this.settings.selectedClass);\n                    this.onSelectionChange();\n                }\n            }\n        },\n\n        /**\n         * Remove All Items\n         */\n        removeAllItems: function() {\n            for (var i = 0; i < this.$items.length; i++) {\n                this._deinitItem(this.$items[i]);\n            }\n\n            this.$items = $();\n            this.$selectedItems = $();\n            this.updateIndexes();\n        },\n\n        /**\n         * Update First/Last indexes\n         */\n        updateIndexes: function() {\n            if (this.first !== null) {\n                this.first = this.getItemIndex(this.$first);\n                this.setFocusableItem(this.$first);\n            }\n            else if (this.$items.length) {\n                this.setFocusableItem($(this.$items[0]));\n            }\n\n            if (this.$focusedItem) {\n                this.setFocusableItem(this.$focusedItem);\n                this.focusItem(this.$focusedItem, true);\n            }\n\n            if (this.last !== null) {\n                this.last = this.getItemIndex(this.$last);\n            }\n        },\n\n        /**\n         * Reset Item Order\n         */\n        resetItemOrder: function() {\n            this.$items = $().add(this.$items);\n            this.$selectedItems = $().add(this.$selectedItems);\n            this.updateIndexes();\n        },\n\n        /**\n         * Sets the focusable item.\n         *\n         * We only want to have one focusable item per selection list, so that the user\n         * doesn't have to tab through a million items.\n         *\n         * @param {object} $item\n         */\n        setFocusableItem: function($item) {\n            if (this.$focusable) {\n                this.$focusable.removeAttr('tabindex');\n            }\n\n            this.$focusable = $item.attr('tabindex', '0');\n        },\n\n        /**\n         * Sets the focus on an item.\n         */\n        focusItem: function($item, preventScroll) {\n            $item[0].focus({preventScroll: !!preventScroll});\n            this.$focusedItem = $item;\n            this.trigger('focusItem', {item: $item});\n        },\n\n        /**\n         * Get Selected Items\n         */\n        getSelectedItems: function() {\n            return this.$selectedItems;\n        },\n\n        /**\n         * Destroy\n         */\n        destroy: function() {\n            this.$container.removeData('select');\n            this.removeAllItems();\n            this.base();\n        },\n\n        // Events\n        // ---------------------------------------------------------------------\n\n        /**\n         * On Mouse Down\n         */\n        onMouseDown: function(ev) {\n            // ignore right clicks\n            if (ev.which !== Garnish.PRIMARY_CLICK) {\n                return;\n            }\n\n            // Enforce the filter\n            if (this.settings.filter && !$(ev.target).is(this.settings.filter)) {\n                return;\n            }\n\n            this.mousedownTarget = ev.currentTarget;\n\n            var $item = $($.data(ev.currentTarget, 'select-item'));\n\n            if (this.first !== null && ev.shiftKey) {\n                // Shift key is consistent for both selection modes\n                this.selectRange($item, true);\n            }\n            else if (this._actAsCheckbox(ev)) {\n                this.toggleItem($item, true);\n            }\n        },\n\n        /**\n         * On Mouse Up\n         */\n        onMouseUp: function(ev) {\n            // ignore right clicks\n            if (ev.which !== Garnish.PRIMARY_CLICK) {\n                return;\n            }\n\n            // Enfore the filter\n            if (this.settings.filter && !$(ev.target).is(this.settings.filter)) {\n                return;\n            }\n\n            var $item = $($.data(ev.currentTarget, 'select-item'));\n\n            // was this a click?\n            if (\n                !this._actAsCheckbox(ev) && !ev.shiftKey &&\n                ev.currentTarget === this.mousedownTarget\n            ) {\n                // If this is already selected, wait a moment to see if this is a double click before making any rash decisions\n                if (this.isSelected($item)) {\n                    this.clearMouseUpTimeout();\n\n                    this.mouseUpTimeout = setTimeout(function() {\n                        this.deselectOthers($item);\n                    }.bind(this), 300);\n                }\n                else {\n                    this.deselectAll();\n                    this.selectItem($item, true, true);\n                }\n            }\n        },\n\n        /**\n         * On Key Down\n         */\n        onKeyDown: function(ev) {\n            // Ignore if the focus isn't on one of our items\n            if (ev.target !== ev.currentTarget) {\n                return;\n            }\n\n            var ctrlKey = Garnish.isCtrlKeyPressed(ev);\n            var shiftKey = ev.shiftKey;\n\n            var anchor, $item;\n\n            if (!this.settings.checkboxMode || !this.$focusable.length) {\n                anchor = ev.shiftKey ? this.last : this.first;\n            }\n            else {\n                anchor = $.inArray(this.$focusable[0], this.$items);\n\n                if (anchor === -1) {\n                    anchor = 0;\n                }\n            }\n\n            // Ok, what are we doing here?\n            switch (ev.keyCode) {\n                case Garnish.LEFT_KEY: {\n                    ev.preventDefault();\n\n                    // Select the last item if none are selected\n                    if (this.first === null) {\n                        if (Garnish.ltr) {\n                            $item = this.getLastItem();\n                        }\n                        else {\n                            $item = this.getFirstItem();\n                        }\n                    }\n                    else {\n                        if (ctrlKey) {\n                            $item = this.getFurthestItemToTheLeft(anchor);\n                        }\n                        else {\n                            $item = this.getItemToTheLeft(anchor);\n                        }\n                    }\n\n                    break;\n                }\n\n                case Garnish.RIGHT_KEY: {\n                    ev.preventDefault();\n\n                    // Select the first item if none are selected\n                    if (this.first === null) {\n                        if (Garnish.ltr) {\n                            $item = this.getFirstItem();\n                        }\n                        else {\n                            $item = this.getLastItem();\n                        }\n                    }\n                    else {\n                        if (ctrlKey) {\n                            $item = this.getFurthestItemToTheRight(anchor);\n                        }\n                        else {\n                            $item = this.getItemToTheRight(anchor);\n                        }\n                    }\n\n                    break;\n                }\n\n                case Garnish.UP_KEY: {\n                    ev.preventDefault();\n\n                    // Select the last item if none are selected\n                    if (this.first === null) {\n                        if (this.$focusable) {\n                            $item = this.$focusable.prev();\n                        }\n\n                        if (!this.$focusable || !$item.length) {\n                            $item = this.getLastItem();\n                        }\n                    }\n                    else {\n                        if (ctrlKey) {\n                            $item = this.getFurthestItemAbove(anchor);\n                        }\n                        else {\n                            $item = this.getItemAbove(anchor);\n                        }\n\n                        if (!$item) {\n                            $item = this.getFirstItem();\n                        }\n                    }\n\n                    break;\n                }\n\n                case Garnish.DOWN_KEY: {\n                    ev.preventDefault();\n\n                    // Select the first item if none are selected\n                    if (this.first === null) {\n                        if (this.$focusable) {\n                            $item = this.$focusable.next();\n                        }\n\n                        if (!this.$focusable || !$item.length) {\n                            $item = this.getFirstItem();\n                        }\n                    }\n                    else {\n                        if (ctrlKey) {\n                            $item = this.getFurthestItemBelow(anchor);\n                        }\n                        else {\n                            $item = this.getItemBelow(anchor);\n                        }\n\n                        if (!$item) {\n                            $item = this.getLastItem();\n                        }\n                    }\n\n                    break;\n                }\n\n                case Garnish.SPACE_KEY: {\n                    if (!ctrlKey && !shiftKey) {\n                        ev.preventDefault();\n\n                        if (this.isSelected(this.$focusable)) {\n                            if (this._canDeselect(this.$focusable)) {\n                                this.deselectItem(this.$focusable);\n                            }\n                        }\n                        else {\n                            this.selectItem(this.$focusable, true, false);\n                        }\n                    }\n\n                    break;\n                }\n\n                case Garnish.A_KEY: {\n                    if (ctrlKey) {\n                        ev.preventDefault();\n                        this.selectAll();\n                    }\n\n                    break;\n                }\n            }\n\n            // Is there an item queued up for focus/selection?\n            if ($item && $item.length) {\n                if (!this.settings.checkboxMode) {\n                    // select it\n                    if (this.first !== null && ev.shiftKey) {\n                        this.selectRange($item, false);\n                    }\n                    else {\n                        this.deselectAll();\n                        this.selectItem($item, true, false);\n                    }\n                }\n                else {\n                    // just set the new item to be focusable\n                    this.setFocusableItem($item);\n                    $item.focus();\n                    this.$focusedItem = $item;\n                    this.trigger('focusItem', {item: $item});\n                }\n            }\n        },\n\n        /**\n         * Set Callback Timeout\n         */\n        onSelectionChange: function() {\n            if (this.callbackFrame) {\n                Garnish.cancelAnimationFrame(this.callbackFrame);\n                this.callbackFrame = null;\n            }\n\n            this.callbackFrame = Garnish.requestAnimationFrame(function() {\n                this.callbackFrame = null;\n                this.trigger('selectionChange');\n                this.settings.onSelectionChange();\n            }.bind(this));\n        },\n\n        // Private methods\n        // ---------------------------------------------------------------------\n\n        _actAsCheckbox: function(ev) {\n            if (Garnish.isCtrlKeyPressed(ev)) {\n                return !this.settings.checkboxMode;\n            }\n            else {\n                return this.settings.checkboxMode;\n            }\n        },\n\n        _canDeselect: function($items) {\n            return (this.settings.allowEmpty || this.totalSelected > $items.length);\n        },\n\n        _selectItems: function($items) {\n            $items.addClass(this.settings.selectedClass);\n            this.$selectedItems = this.$selectedItems.add($items);\n            this.onSelectionChange();\n        },\n\n        _deselectItems: function($items) {\n            $items.removeClass(this.settings.selectedClass);\n            this.$selectedItems = this.$selectedItems.not($items);\n            this.onSelectionChange();\n        },\n\n        /**\n         * Deinitialize an item.\n         */\n        _deinitItem: function(item) {\n            var $handle = $.data(item, 'select-handle');\n\n            if ($handle) {\n                $handle.removeData('select-item');\n                this.removeAllListeners($handle);\n            }\n\n            $.removeData(item, 'select');\n            $.removeData(item, 'select-handle');\n\n            if (this.$focusedItem && this.$focusedItem[0] === item) {\n                this.$focusedItem = null;\n            }\n        }\n    },\n    {\n        defaults: {\n            selectedClass: 'sel',\n            multi: false,\n            allowEmpty: true,\n            vertical: false,\n            horizontal: false,\n            handle: null,\n            filter: null,\n            checkboxMode: false,\n            onSelectionChange: $.noop\n        },\n\n        closestItemAxisProps: {\n            x: {\n                midpointOffset: 'top',\n                midpointSizeFunc: 'outerHeight',\n                rowOffset: 'left'\n            },\n            y: {\n                midpointOffset: 'left',\n                midpointSizeFunc: 'outerWidth',\n                rowOffset: 'top'\n            }\n        },\n\n        closestItemDirectionProps: {\n            '<': {\n                step: -1,\n                isNextRow: function(a, b) {\n                    return (a < b);\n                },\n                isWrongDirection: function(a, b) {\n                    return (a > b);\n                }\n            },\n            '>': {\n                step: 1,\n                isNextRow: function(a, b) {\n                    return (a > b);\n                },\n                isWrongDirection: function(a, b) {\n                    return (a < b);\n                }\n            }\n        }\n    }\n);\n\n/** global: Garnish */\n/**\n * Select Menu\n */\nGarnish.SelectMenu = Garnish.CustomSelect.extend(\n    {\n        /**\n         * Constructor\n         */\n        init: function(btn, options, settings, callback) {\n            // argument mapping\n            if (typeof settings === 'function') {\n                // (btn, options, callback)\n                callback = settings;\n                settings = {};\n            }\n\n            settings = $.extend({}, Garnish.SelectMenu.defaults, settings);\n\n            this.base(btn, options, settings, callback);\n\n            this.selected = -1;\n        },\n\n        /**\n         * Build\n         */\n        build: function() {\n            this.base();\n\n            if (this.selected !== -1) {\n                this._addSelectedOptionClass(this.selected);\n            }\n        },\n\n        /**\n         * Select\n         */\n        select: function(option) {\n            // ignore if it's already selected\n            if (option === this.selected) {\n                return;\n            }\n\n            if (this.dom.ul) {\n                if (this.selected !== -1) {\n                    this.dom.options[this.selected].className = '';\n                }\n\n                this._addSelectedOptionClass(option);\n            }\n\n            this.selected = option;\n\n            // set the button text to the selected option\n            this.setBtnText($(this.options[option].label).text());\n\n            this.base(option);\n        },\n\n        /**\n         * Add Selected Option Class\n         */\n        _addSelectedOptionClass: function(option) {\n            this.dom.options[option].className = 'sel';\n        },\n\n        /**\n         * Set Button Text\n         */\n        setBtnText: function(text) {\n            this.dom.$btnLabel.text(text);\n        }\n\n    },\n    {\n        defaults: {\n            ulClass: 'menu select'\n        }\n    }\n);\n\n/** global: Garnish */\n/**\n * Keyboard shortcut manager class\n *\n * This can be used to map keyboard events to the current UI \"layer\" (whether that's the base document,\n * a modal, an HUD, or a menu).\n */\nGarnish.ShortcutManager = Garnish.Base.extend(\n    {\n        shortcuts: null,\n        layer: 0,\n\n        init: function() {\n            this.shortcuts = [[]];\n            this.addListener(Garnish.$bod, 'keydown', 'triggerShortcut');\n        },\n\n        addLayer: function() {\n            this.layer++;\n            this.shortcuts.push([]);\n            return this;\n        },\n\n        removeLayer: function() {\n            if (this.layer === 0) {\n                throw 'Can’t remove the base layer.';\n            }\n            this.layer--;\n            this.shortcuts.pop();\n            return this;\n        },\n\n        registerShortcut: function(shortcut, callback, layer) {\n            shortcut = this._normalizeShortcut(shortcut);\n            if (typeof layer === 'undefined') {\n                layer = this.layer;\n            }\n            this.shortcuts[layer].push({\n                key: JSON.stringify(shortcut),\n                shortcut: shortcut,\n                callback: callback,\n            });\n            return this;\n        },\n\n        unregisterShortcut: function(shortcut, layer) {\n            shortcut = this._normalizeShortcut(shortcut);\n            var key = JSON.stringify(shortcut);\n            if (typeof layer === 'undefined') {\n                layer = this.layer;\n            }\n            for (var i = 0; i < this.shortcuts[layer].length; i++) {\n                if (this.shortcuts[layer][i].key === key) {\n                    this.shortcuts[layer].splice(i, 1);\n                    break;\n                }\n            }\n            return this;\n        },\n\n        _normalizeShortcut: function(shortcut) {\n            if (typeof shortcut === 'number') {\n                shortcut = {keyCode: shortcut};\n            }\n\n            if (typeof shortcut.keyCode !== 'number') {\n                throw 'Invalid shortcut';\n            }\n\n            return {\n                keyCode: shortcut.keyCode,\n                ctrl: !!shortcut.ctrl,\n                shift: !!shortcut.shift,\n                alt: !!shortcut.alt,\n            };\n        },\n\n        triggerShortcut: function(ev) {\n            var shortcut;\n            for (var i = 0; i < this.shortcuts[this.layer].length; i++) {\n                shortcut = this.shortcuts[this.layer][i].shortcut;\n                if (\n                    shortcut.keyCode === ev.keyCode &&\n                    shortcut.ctrl === Garnish.isCtrlKeyPressed(ev) &&\n                    shortcut.shift === ev.shiftKey &&\n                    shortcut.alt === ev.altKey\n                ) {\n                    ev.preventDefault();\n                    this.shortcuts[this.layer][i].callback(ev);\n                    break;\n                }\n            }\n        },\n    }\n);\n\nGarnish.shortcutManager = new Garnish.ShortcutManager();\n\n})(jQuery);\n"]}