{"version":3,"sources":["../lib/Base.js","../src/Garnish.js","../src/BaseDrag.js","../src/CheckboxSelect.js","../src/ContextMenu.js","../src/Drag.js","../src/DragDrop.js","../src/DragMove.js","../src/DragSort.js","../src/EscManager.js","../src/HUD.js","../src/Menu.js","../src/MenuBtn.js","../src/MixedInput.js","../src/Modal.js","../src/NiceText.js","../src/Pill.js","../src/Select.js","../src/SelectMenu.js","garnish.js"],"names":["$","getErd","erd","elementResizeDetectorMaker","callOnAdd","triggerResizeEvent","elem","trigger","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","$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","$target","css","fontFamily","fontSize","fontWeight","letterSpacing","lineHeight","textAlign","textIndent","whiteSpace","wordSpacing","wordWrap","getBodyScrollTop","_scrollTop","_maxScrollTop","height","requestAnimationFrame","raf","mozRequestAnimationFrame","webkitRequestAnimationFrame","fn","setTimeout","cancelAnimationFrame","cancel","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","altKey","_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","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","_cancelWindowScroll","onDrag","stopDragging","onDragStop","item","removeItems","add","index","_deinitItem","removeAllItems","_handleMouseDown","which","$handle","_getItemHandle","currentTarget","is","closest","ignoreHandleSelector","_handleMouseMove","_mouseDist","minMouseDist","_handleMouseUp","_scrollWindow","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","Drag","targetItemWidth","targetItemHeight","targetItemPositionInDraggee","$draggee","otherItems","totalOtherItems","helpers","helperTargets","helperPositions","helperLagIncrement","updateHelperPosProxy","updateHelperPosFrame","lastMouseX","lastMouseY","_returningHelpersToDraggees","draggeeDisplay","setDraggee","findDraggee","helperLagIncrementDividend","concat","toArray","singleHelper","_createHelper","removeDraggee","collapseDraggees","appendDraggee","$newDraggee","oldLength","newLength","draggeeVirtualMidpointX","draggeeVirtualMidpointY","getHelperTargetX","getHelperTargetY","returnHelpersToDraggees","$helper","display","visibility","callback","draggeeOffset","onReturnHelpersToDraggees","$draggeeHelper","clone","copyDraggeeInputValuesToHelper","margin","pointer-events","helper","append","helperPos","_getHelperTarget","position","zIndex","helperBaseZindex","opacity","helperOpacity","_updateHelperPos","_i","_j","_lag","helperLagBase","helperSpacingX","helperSpacingY","_showDraggee","remove","DragDrop","$dropTargets","$activeDropTarget","updateDropTargets","dropTargets","_activeDropTarget","_elem","activeDropTargetClass","onDropTargetChange","fadeOutHelpers","duration","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","$trigger","$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","closeBtn","html","headerClass","footerClass","stopPropagation","closeOtherHUDs","hudID","updateRecords","updateSizeAndPosition","changed","force","updateSizeAndPositionInternal","triggerWidth","triggerHeight","triggerOffset","windowScrollLeft","windowScrollTop","scrollContainerTriggerOffset","scrollContainerScrollLeft","scrollContainerScrollTop","hudBodyWidth","hudBodyHeight","right","bottom","overflow-x","overflow-y","clearances","orientations","relevantSize","windowSpacing","triggerSpacing","tipClasses","maxHudBodyWidth","maxHudBodyHeight","minBodyWidth","minBodyHeight","triggerCenter","maxLeft","minLeft","tipLeft","tipWidth","maxTop","minTop","tipTop","toggle","submit","_handleSubmit","Menu","$anchor","menuId","_windowWidth","_windowHeight","_windowScrollLeft","_windowScrollTop","_anchorOffset","_anchorWidth","_anchorHeight","_anchorOffsetRight","_anchorOffsetBottom","_menuWidth","_menuHeight","addOptions","$menuList","role","aria-hidden","attachToElement","anchor","optionKey","tabindex","setPositionRelativeToAnchor","topClearance","bottomClearance","maxHeight","min","align","_alignCenter","rightClearance","leftClearance","_alignRight","_alignLeft","detach","selectOption","onOptionSelect","selectedOption","MenuBtn","$btn","menu","btn","menuAnchor","aria-owns","aria-haspopup","aria-expanded","onBlur","onKeyDown","$option","$currentOption","click","focusOption","onMouseDown","onMenuHide","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","focus","focusPreviousElement","$from","focusNextElement","pos","parentInput","$stage","focussed","interval","padding","setWidth","getIndex","buildStage","getTextWidth","stageWidth","setInterval","NiceText","checkInput","clearInterval","getVal","setVal","onChange","Modal","visible","dragger","desiredWidth","desiredHeight","resizeDragger","resizeStartWidth","resizeStartHeight","setContainer","autoShow","instances","draggable","dragHandleSelector","resizable","$resizeDragHandle","closeOtherModals","visibleModal","onFadeIn","hideOnShadeClick","hideOnEsc","quickShow","quickHide","max","min-width","min-height","_width","getWidth","minGutter","_height","getHeight","onFadeOut","_handleWindowResize","_handleResizeStart","_handleResize","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","negativeCharsLeftClass","Pill","$outerContainer","$innerContainer","$btns","$selectedBtn","outerContainer","preventOutlineOnMouseFocus","select","selectNext","nextIndex","_getSelectedBtnIndex","selectPrev","prevIndex","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","scrollTo","getSelectedItems","shiftKey","_actAsCheckbox","onMouseUp","<","b",">","SelectMenu","selected","build","_addSelectedOptionClass","dom","ul","className","setBtnText","$btnLabel","ulClass"],"mappings":"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","file":"garnish.min.js","sourcesContent":["/*!\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 * @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 else {\n // Both altKey and ctrlKey == true on some Windows keyboards when the right-hand ALT key is pressed\n // so just be safe and make sure altKey == false\n return (ev.ctrlKey && !ev.altKey);\n }\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 = $.proxy(func, this);\n }\n else {\n func = $.proxy(this, func);\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","/** 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 = $.proxy(this, '_scrollWindow');\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($.proxy(function() {\n this.trigger('dragStart');\n this.settings.onDragStart();\n }, this));\n },\n\n /**\n * On Drag\n */\n onDrag: function() {\n Garnish.requestAnimationFrame($.proxy(function() {\n this.trigger('drag');\n this.settings.onDrag();\n }, this));\n },\n\n /**\n * On Drag Stop\n */\n onDragStop: function() {\n Garnish.requestAnimationFrame($.proxy(function() {\n this.trigger('dragStop');\n this.settings.onDragStop();\n }, 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","/** 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","/** 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($.proxy(function() {\n $a.mousedown($.proxy(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 }, this));\n }, 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($.proxy(function() {\n this.addListener(Garnish.$doc, 'mousedown', 'hideMenu');\n }, 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","/** 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 = $.proxy(this, '_updateHelperPos');\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 = $.proxy(this, '_showDraggee');\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($.proxy(function() {\n this.trigger('returnHelpersToDraggees');\n this.settings.onReturnHelpersToDraggees();\n }, 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.css({\n width: $draggee.width() + 1, // Prevent the brower from wrapping text if the width was actually a fraction of a pixel larger\n height: $draggee.height(),\n margin: 0,\n 'pointer-events': 'none'\n });\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","/** 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","/** 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","/** 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($.proxy(function() {\n this.trigger('insertionPointChange');\n this.settings.onInsertionPointChange();\n }, this));\n },\n\n /**\n * On Sort Change event\n */\n onSortChange: function() {\n Garnish.requestAnimationFrame($.proxy(function() {\n this.trigger('sortChange');\n this.settings.onSortChange();\n }, 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","/** global: Garnish */\n/**\n * ESC key manager class\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","/** 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\tvar windowWidth = Garnish.$win.width();\n\n\t\t\tthis.$hud.css({\n left: '-' + windowWidth + 'px',\n\t\t\t});\n\n this.show();\n\n this.addListener(this.$body, 'submit', '_handleSubmit');\n this.addListener(this.$shade, 'tap,click', 'hide');\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 Garnish.escManager.register(this, 'hide');\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($.proxy(this, 'updateSizeAndPositionInternal'));\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 this.disable();\n\n this.$hud.hide();\n this.$shade.hide();\n\n this.showing = false;\n //this.windowWidth = null;\n //this.windowHeight = null;\n //this.scrollTop = null;\n //this.scrollLeft = null;\n //this.mainWidth = null;\n //this.mainHeight = null;\n\n delete Garnish.HUD.activeHUDs[this._namespace];\n\n Garnish.escManager.unregister(this);\n\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 }\n }\n);\n","/** global: Garnish */\n/**\n * Menu\n */\nGarnish.Menu = Garnish.Base.extend(\n {\n settings: null,\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.Menu.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('The \\'attachToElement\\' setting is deprecated. Use \\'anchor\\' instead.');\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 // Prevent this from causing the menu button to blur\n ev.preventDefault();\n });\n },\n\n addOptions: function($options) {\n this.$options = this.$options.add($options);\n $options.data('menu', this);\n\n $options.each($.proxy(function(optionKey, option) {\n $(option).attr({\n 'role': 'option',\n 'tabindex': '-1',\n 'id': this.menuId + '-option-' + optionKey\n });\n }, this));\n\n this.addListener($options, 'click', 'selectOption');\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('minWidth', this._anchorWidth - (this.$container.outerWidth() - this.$container.width()));\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 = this._windowHeight + this._windowScrollTop - this._anchorOffsetBottom;\n\n if (bottomClearance >= this._menuHeight || (topClearance < this._menuHeight && bottomClearance >= topClearance)) {\n this.$container.css({\n top: this._anchorOffsetBottom,\n maxHeight: bottomClearance - this.settings.windowSpacing\n });\n } else {\n this.$container.css({\n top: this._anchorOffset.top - Math.min(this._menuHeight, topClearance - this.settings.windowSpacing),\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 }\n else {\n // Figure out which options are actually possible\n var rightClearance = this._windowWidth + this._windowScrollLeft - (this._anchorOffset.left + this._menuWidth),\n leftClearance = this._anchorOffsetRight - this._menuWidth;\n\n if (align === 'right' && leftClearance >= 0 || rightClearance < 0) {\n this._alignRight();\n }\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 // 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.escManager.register(this, 'hide');\n this.addListener(Garnish.$scrollContainer, 'scroll', 'setPositionRelativeToAnchor');\n },\n\n hide: function() {\n this.$menuList.attr('aria-hidden', 'true');\n\n this.$container.velocity('fadeOut', {duration: Garnish.FX_DURATION}, $.proxy(function() {\n this.$container.detach();\n }, this));\n\n Garnish.escManager.unregister(this);\n this.removeListener(Garnish.$scrollContainer, 'scroll');\n\n this.trigger('hide');\n },\n\n selectOption: function(ev) {\n this.settings.onOptionSelect(ev.currentTarget);\n this.trigger('optionselect', {selectedOption: ev.currentTarget});\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: this._windowWidth - (this._anchorOffset.left + this._anchorWidth),\n left: 'auto'\n });\n },\n\n _alignCenter: function() {\n var left = Math.round((this._anchorOffset.left + this._anchorWidth / 2) - (this._menuWidth / 2));\n\n if (left < 0) {\n left = 0;\n }\n\n this.$container.css('left', left);\n }\n\n },\n {\n defaults: {\n anchor: null,\n windowSpacing: 5,\n onOptionSelect: $.noop\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, settings) {\n this.$btn = $(btn);\n\n // Is this already a menu button?\n if (this.$btn.data('menubtn')) {\n // Grab the old MenuBtn's menu container\n var $menu = this.$btn.data('menubtn').menu.$container;\n\n Garnish.log('Double-instantiating a menu button on an element');\n this.$btn.data('menubtn').destroy();\n }\n else {\n var $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 = new Garnish.Menu($menu, {\n anchor: (this.settings.menuAnchor || this.$btn),\n onOptionSelect: $.proxy(this, 'onOptionSelect')\n });\n\n this.$btn.attr({\n 'tabindex': 0,\n 'role': 'combobox',\n 'aria-owns': this.menu.menuId,\n 'aria-haspopup': 'true',\n 'aria-expanded': 'false'\n });\n\n this.menu.on('hide', $.proxy(this, 'onMenuHide'));\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(ev) {\n if (this.showingMenu) {\n this.hideMenu();\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 var $currentOption = this.menu.$options.filter('.hover');\n\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 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, $.proxy(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 }, 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, $.proxy(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 }, 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)) {\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($.proxy(function() {\n this.addListener(Garnish.$doc, 'mousedown', 'onMouseDown');\n }, 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","/** 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($.proxy(function() {\n this.setFocus($elem);\n }, 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($.proxy(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 }, 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, '&');\n\n // < and >\n val = val.replace(/</g, '<');\n val = val.replace(/>/g, '>');\n\n // Spaces\n val = val.replace(/ /g, ' ');\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($.proxy(this, 'checkInput'), 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($.proxy(this, 'checkInput'), 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","/** 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: $.proxy(this, '_handleResizeStart'),\n onDrag: $.proxy(this, '_handleResize')\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: $.proxy(function() {\n this.$container.velocity('fadeIn', {\n complete: $.proxy(function() {\n this.updateSizeAndPosition();\n this.onFadeIn();\n }, this)\n });\n }, 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.settings.hideOnEsc) {\n Garnish.escManager.register(this, 'hide');\n }\n\n if (!this.visible) {\n this.visible = true;\n Garnish.Modal.visibleModal = this;\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 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: $.proxy(this, 'onFadeOut')\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\n if (this.settings.hideOnEsc) {\n Garnish.escManager.unregister(this);\n }\n\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","/** 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 class=\"' + this.settings.charsLeftClass + '\"/>').insertAfter(this.$input);\n this.updateCharsLeft();\n }\n\n this.addListener(this.$input, 'textchange', 'onTextChange');\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 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 = ' ';\n for (var i = 1; i < this.$input.prop('rows'); i++) {\n val += '<br/> ';\n }\n }\n else {\n // Ampersand entities\n val = val.replace(/&/g, '&');\n\n // < and >\n val = val.replace(/</g, '<');\n val = val.replace(/>/g, '>');\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 += ' ';\n }\n return replace + ' ';\n });\n\n // Line breaks\n val = val.replace(/[\\n\\r]$/g, '<br/> ');\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.text(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 defaults: {\n autoHeight: true,\n showCharsLeft: false,\n charsLeftClass: 'chars-left',\n negativeCharsLeftClass: 'negative-chars-left',\n onHeightChange: $.noop\n }\n }\n);\n","/** global: Garnish */\n/**\n * Pill\n */\nGarnish.Pill = Garnish.Base.extend(\n {\n $outerContainer: null,\n $innerContainer: null,\n $btns: null,\n $selectedBtn: null,\n $input: null,\n\n init: function(outerContainer) {\n this.$outerContainer = $(outerContainer);\n\n // Is this already a pill?\n if (this.$outerContainer.data('pill')) {\n Garnish.log('Double-instantiating a pill on an element');\n this.$outerContainer.data('pill').destroy();\n }\n\n this.$outerContainer.data('pill', this);\n\n this.$innerContainer = this.$outerContainer.find('.btngroup:first');\n this.$btns = this.$innerContainer.find('.btn');\n this.$selectedBtn = this.$btns.filter('.active:first');\n this.$input = this.$outerContainer.find('input:first');\n\n Garnish.preventOutlineOnMouseFocus(this.$innerContainer);\n this.addListener(this.$btns, 'mousedown', 'onMouseDown');\n this.addListener(this.$innerContainer, 'keydown', 'onKeyDown');\n },\n\n select: function(btn) {\n this.$selectedBtn.removeClass('active');\n var $btn = $(btn);\n $btn.addClass('active');\n this.$input.val($btn.attr('data-value'));\n this.$selectedBtn = $btn;\n },\n\n selectNext: function() {\n if (!this.$selectedBtn.length) {\n this.select(this.$btns[this.$btns.length - 1]);\n }\n else {\n var nextIndex = this._getSelectedBtnIndex() + 1;\n\n if (typeof this.$btns[nextIndex] !== 'undefined') {\n this.select(this.$btns[nextIndex]);\n }\n }\n },\n\n selectPrev: function() {\n if (!this.$selectedBtn.length) {\n this.select(this.$btns[0]);\n }\n else {\n var prevIndex = this._getSelectedBtnIndex() - 1;\n\n if (typeof this.$btns[prevIndex] !== 'undefined') {\n this.select(this.$btns[prevIndex]);\n }\n }\n },\n\n onMouseDown: function(ev) {\n this.select(ev.currentTarget);\n },\n\n _getSelectedBtnIndex: function() {\n if (typeof this.$selectedBtn[0] !== 'undefined') {\n return $.inArray(this.$selectedBtn[0], this.$btns);\n }\n else {\n return -1;\n }\n },\n\n onKeyDown: function(ev) {\n switch (ev.keyCode) {\n case Garnish.RIGHT_KEY: {\n if (Garnish.ltr) {\n this.selectNext();\n }\n else {\n this.selectPrev();\n }\n\n ev.preventDefault();\n break;\n }\n\n case Garnish.LEFT_KEY: {\n if (Garnish.ltr) {\n this.selectPrev();\n }\n else {\n this.selectNext();\n }\n\n ev.preventDefault();\n break;\n }\n }\n },\n\n /**\n * Destroy\n */\n destroy: function() {\n this.$outerContainer.removeData('pill');\n this.base();\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);\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);\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);\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 if (preventScroll) {\n var scrollLeft = Garnish.$doc.scrollLeft(),\n scrollTop = Garnish.$doc.scrollTop();\n $item.focus();\n window.scrollTo(scrollLeft, scrollTop);\n }\n else {\n $item.focus();\n }\n\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($.proxy(function() {\n this.deselectOthers($item);\n }, 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);\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);\n }\n else {\n this.deselectAll();\n this.selectItem($item, true);\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($.proxy(function() {\n this.callbackFrame = null;\n this.trigger('selectionChange');\n this.settings.onSelectionChange();\n }, 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","/** global: Garnish */\n/**\n * Select Menu\n */\nGarnish.SelectMenu = Garnish.Menu.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 * Garnish UI toolkit\n *\n * @copyright 2013 Pixel & Tonic, Inc.. All rights reserved.\n * @author Brandon Kelly <brandon@pixelandtonic.com>\n * @version 0.1.29\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 else {\n // Both altKey and ctrlKey == true on some Windows keyboards when the right-hand ALT key is pressed\n // so just be safe and make sure altKey == false\n return (ev.ctrlKey && !ev.altKey);\n }\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 = $.proxy(func, this);\n }\n else {\n func = $.proxy(this, func);\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 = $.proxy(this, '_scrollWindow');\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($.proxy(function() {\n this.trigger('dragStart');\n this.settings.onDragStart();\n }, this));\n },\n\n /**\n * On Drag\n */\n onDrag: function() {\n Garnish.requestAnimationFrame($.proxy(function() {\n this.trigger('drag');\n this.settings.onDrag();\n }, this));\n },\n\n /**\n * On Drag Stop\n */\n onDragStop: function() {\n Garnish.requestAnimationFrame($.proxy(function() {\n this.trigger('dragStop');\n this.settings.onDragStop();\n }, 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($.proxy(function() {\n $a.mousedown($.proxy(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 }, this));\n }, 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($.proxy(function() {\n this.addListener(Garnish.$doc, 'mousedown', 'hideMenu');\n }, 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 * 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 = $.proxy(this, '_updateHelperPos');\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 = $.proxy(this, '_showDraggee');\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($.proxy(function() {\n this.trigger('returnHelpersToDraggees');\n this.settings.onReturnHelpersToDraggees();\n }, 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.css({\n width: $draggee.width() + 1, // Prevent the brower from wrapping text if the width was actually a fraction of a pixel larger\n height: $draggee.height(),\n margin: 0,\n 'pointer-events': 'none'\n });\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($.proxy(function() {\n this.trigger('insertionPointChange');\n this.settings.onInsertionPointChange();\n }, this));\n },\n\n /**\n * On Sort Change event\n */\n onSortChange: function() {\n Garnish.requestAnimationFrame($.proxy(function() {\n this.trigger('sortChange');\n this.settings.onSortChange();\n }, 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 */\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\tvar windowWidth = Garnish.$win.width();\n\n\t\t\tthis.$hud.css({\n left: '-' + windowWidth + 'px',\n\t\t\t});\n\n this.show();\n\n this.addListener(this.$body, 'submit', '_handleSubmit');\n this.addListener(this.$shade, 'tap,click', 'hide');\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 Garnish.escManager.register(this, 'hide');\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($.proxy(this, 'updateSizeAndPositionInternal'));\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 this.disable();\n\n this.$hud.hide();\n this.$shade.hide();\n\n this.showing = false;\n //this.windowWidth = null;\n //this.windowHeight = null;\n //this.scrollTop = null;\n //this.scrollLeft = null;\n //this.mainWidth = null;\n //this.mainHeight = null;\n\n delete Garnish.HUD.activeHUDs[this._namespace];\n\n Garnish.escManager.unregister(this);\n\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 }\n }\n);\n\n/** global: Garnish */\n/**\n * Menu\n */\nGarnish.Menu = Garnish.Base.extend(\n {\n settings: null,\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.Menu.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('The \\'attachToElement\\' setting is deprecated. Use \\'anchor\\' instead.');\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 // Prevent this from causing the menu button to blur\n ev.preventDefault();\n });\n },\n\n addOptions: function($options) {\n this.$options = this.$options.add($options);\n $options.data('menu', this);\n\n $options.each($.proxy(function(optionKey, option) {\n $(option).attr({\n 'role': 'option',\n 'tabindex': '-1',\n 'id': this.menuId + '-option-' + optionKey\n });\n }, this));\n\n this.addListener($options, 'click', 'selectOption');\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('minWidth', this._anchorWidth - (this.$container.outerWidth() - this.$container.width()));\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 = this._windowHeight + this._windowScrollTop - this._anchorOffsetBottom;\n\n if (bottomClearance >= this._menuHeight || (topClearance < this._menuHeight && bottomClearance >= topClearance)) {\n this.$container.css({\n top: this._anchorOffsetBottom,\n maxHeight: bottomClearance - this.settings.windowSpacing\n });\n } else {\n this.$container.css({\n top: this._anchorOffset.top - Math.min(this._menuHeight, topClearance - this.settings.windowSpacing),\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 }\n else {\n // Figure out which options are actually possible\n var rightClearance = this._windowWidth + this._windowScrollLeft - (this._anchorOffset.left + this._menuWidth),\n leftClearance = this._anchorOffsetRight - this._menuWidth;\n\n if (align === 'right' && leftClearance >= 0 || rightClearance < 0) {\n this._alignRight();\n }\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 // 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.escManager.register(this, 'hide');\n this.addListener(Garnish.$scrollContainer, 'scroll', 'setPositionRelativeToAnchor');\n },\n\n hide: function() {\n this.$menuList.attr('aria-hidden', 'true');\n\n this.$container.velocity('fadeOut', {duration: Garnish.FX_DURATION}, $.proxy(function() {\n this.$container.detach();\n }, this));\n\n Garnish.escManager.unregister(this);\n this.removeListener(Garnish.$scrollContainer, 'scroll');\n\n this.trigger('hide');\n },\n\n selectOption: function(ev) {\n this.settings.onOptionSelect(ev.currentTarget);\n this.trigger('optionselect', {selectedOption: ev.currentTarget});\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: this._windowWidth - (this._anchorOffset.left + this._anchorWidth),\n left: 'auto'\n });\n },\n\n _alignCenter: function() {\n var left = Math.round((this._anchorOffset.left + this._anchorWidth / 2) - (this._menuWidth / 2));\n\n if (left < 0) {\n left = 0;\n }\n\n this.$container.css('left', left);\n }\n\n },\n {\n defaults: {\n anchor: null,\n windowSpacing: 5,\n onOptionSelect: $.noop\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, settings) {\n this.$btn = $(btn);\n\n // Is this already a menu button?\n if (this.$btn.data('menubtn')) {\n // Grab the old MenuBtn's menu container\n var $menu = this.$btn.data('menubtn').menu.$container;\n\n Garnish.log('Double-instantiating a menu button on an element');\n this.$btn.data('menubtn').destroy();\n }\n else {\n var $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 = new Garnish.Menu($menu, {\n anchor: (this.settings.menuAnchor || this.$btn),\n onOptionSelect: $.proxy(this, 'onOptionSelect')\n });\n\n this.$btn.attr({\n 'tabindex': 0,\n 'role': 'combobox',\n 'aria-owns': this.menu.menuId,\n 'aria-haspopup': 'true',\n 'aria-expanded': 'false'\n });\n\n this.menu.on('hide', $.proxy(this, 'onMenuHide'));\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(ev) {\n if (this.showingMenu) {\n this.hideMenu();\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 var $currentOption = this.menu.$options.filter('.hover');\n\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 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, $.proxy(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 }, 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, $.proxy(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 }, 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)) {\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($.proxy(function() {\n this.addListener(Garnish.$doc, 'mousedown', 'onMouseDown');\n }, 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($.proxy(function() {\n this.setFocus($elem);\n }, 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($.proxy(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 }, 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, '&');\n\n // < and >\n val = val.replace(/</g, '<');\n val = val.replace(/>/g, '>');\n\n // Spaces\n val = val.replace(/ /g, ' ');\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($.proxy(this, 'checkInput'), 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($.proxy(this, 'checkInput'), 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: $.proxy(this, '_handleResizeStart'),\n onDrag: $.proxy(this, '_handleResize')\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: $.proxy(function() {\n this.$container.velocity('fadeIn', {\n complete: $.proxy(function() {\n this.updateSizeAndPosition();\n this.onFadeIn();\n }, this)\n });\n }, 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.settings.hideOnEsc) {\n Garnish.escManager.register(this, 'hide');\n }\n\n if (!this.visible) {\n this.visible = true;\n Garnish.Modal.visibleModal = this;\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 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: $.proxy(this, 'onFadeOut')\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\n if (this.settings.hideOnEsc) {\n Garnish.escManager.unregister(this);\n }\n\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 class=\"' + this.settings.charsLeftClass + '\"/>').insertAfter(this.$input);\n this.updateCharsLeft();\n }\n\n this.addListener(this.$input, 'textchange', 'onTextChange');\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 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 = ' ';\n for (var i = 1; i < this.$input.prop('rows'); i++) {\n val += '<br/> ';\n }\n }\n else {\n // Ampersand entities\n val = val.replace(/&/g, '&');\n\n // < and >\n val = val.replace(/</g, '<');\n val = val.replace(/>/g, '>');\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 += ' ';\n }\n return replace + ' ';\n });\n\n // Line breaks\n val = val.replace(/[\\n\\r]$/g, '<br/> ');\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.text(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 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 * Pill\n */\nGarnish.Pill = Garnish.Base.extend(\n {\n $outerContainer: null,\n $innerContainer: null,\n $btns: null,\n $selectedBtn: null,\n $input: null,\n\n init: function(outerContainer) {\n this.$outerContainer = $(outerContainer);\n\n // Is this already a pill?\n if (this.$outerContainer.data('pill')) {\n Garnish.log('Double-instantiating a pill on an element');\n this.$outerContainer.data('pill').destroy();\n }\n\n this.$outerContainer.data('pill', this);\n\n this.$innerContainer = this.$outerContainer.find('.btngroup:first');\n this.$btns = this.$innerContainer.find('.btn');\n this.$selectedBtn = this.$btns.filter('.active:first');\n this.$input = this.$outerContainer.find('input:first');\n\n Garnish.preventOutlineOnMouseFocus(this.$innerContainer);\n this.addListener(this.$btns, 'mousedown', 'onMouseDown');\n this.addListener(this.$innerContainer, 'keydown', 'onKeyDown');\n },\n\n select: function(btn) {\n this.$selectedBtn.removeClass('active');\n var $btn = $(btn);\n $btn.addClass('active');\n this.$input.val($btn.attr('data-value'));\n this.$selectedBtn = $btn;\n },\n\n selectNext: function() {\n if (!this.$selectedBtn.length) {\n this.select(this.$btns[this.$btns.length - 1]);\n }\n else {\n var nextIndex = this._getSelectedBtnIndex() + 1;\n\n if (typeof this.$btns[nextIndex] !== 'undefined') {\n this.select(this.$btns[nextIndex]);\n }\n }\n },\n\n selectPrev: function() {\n if (!this.$selectedBtn.length) {\n this.select(this.$btns[0]);\n }\n else {\n var prevIndex = this._getSelectedBtnIndex() - 1;\n\n if (typeof this.$btns[prevIndex] !== 'undefined') {\n this.select(this.$btns[prevIndex]);\n }\n }\n },\n\n onMouseDown: function(ev) {\n this.select(ev.currentTarget);\n },\n\n _getSelectedBtnIndex: function() {\n if (typeof this.$selectedBtn[0] !== 'undefined') {\n return $.inArray(this.$selectedBtn[0], this.$btns);\n }\n else {\n return -1;\n }\n },\n\n onKeyDown: function(ev) {\n switch (ev.keyCode) {\n case Garnish.RIGHT_KEY: {\n if (Garnish.ltr) {\n this.selectNext();\n }\n else {\n this.selectPrev();\n }\n\n ev.preventDefault();\n break;\n }\n\n case Garnish.LEFT_KEY: {\n if (Garnish.ltr) {\n this.selectPrev();\n }\n else {\n this.selectNext();\n }\n\n ev.preventDefault();\n break;\n }\n }\n },\n\n /**\n * Destroy\n */\n destroy: function() {\n this.$outerContainer.removeData('pill');\n this.base();\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);\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);\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);\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 if (preventScroll) {\n var scrollLeft = Garnish.$doc.scrollLeft(),\n scrollTop = Garnish.$doc.scrollTop();\n $item.focus();\n window.scrollTo(scrollLeft, scrollTop);\n }\n else {\n $item.focus();\n }\n\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($.proxy(function() {\n this.deselectOthers($item);\n }, 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);\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);\n }\n else {\n this.deselectAll();\n this.selectItem($item, true);\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($.proxy(function() {\n this.callbackFrame = null;\n this.trigger('selectionChange');\n this.settings.onSelectionChange();\n }, 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.Menu.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})(jQuery);\n"]}