Passed
Branch develop (893f38)
by Hans Erik
07:18
created

build/media/libraries/redcore/media/redcore/lib/jquery-ui/jquery-ui.js   F

Complexity

Total Complexity 3363
Complexity/F 3.62

Size

Lines of Code 14616
Function Count 930

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
wmc 3363
c 0
b 0
f 0
dl 0
loc 14616
rs 2.4
cc 0
nc 0
mnd 7
bc 2364
fnc 930
bpm 2.5419
cpm 3.6161
noi 90

507 Functions

Rating   Name   Duplication   Size   Complexity  
B $.widget(ꞌui.accordionꞌ)._refresh 0 99 4
A $.widget(ꞌui.autocompleteꞌ)._search 0 7 1
B $.extend._isInRange 0 25 4
B $.position.getScrollInfo 0 14 7
A $.ui.ddmanager.dragStart 0 8 1
A $.Widget.disable 0 3 1
B $.widget(ꞌui.tabsꞌ).load 0 52 4
C $.widget(ꞌui.resizableꞌ)._mouseDrag 0 60 11
A $.widget(ꞌui.mouseꞌ)._mouseDrag 0 1 1
A $.widget(ꞌui.resizableꞌ)._mouseCapture 0 13 4
A $.extend.iso8601Week 0 12 1
C $.widget(ꞌui.accordionꞌ)._eventHandler 0 56 11
B $.extend._determineDate 0 54 9
A $.widget(ꞌui.selectableꞌ)._destroy 0 8 1
A $.widget(ꞌui.spinnerꞌ)._start 0 11 4
A $.widget(ꞌui.spinnerꞌ)._value 0 14 4
A $.extend._attachDatepicker 0 16 4
C $.ui.position.flip.top 0 35 14
A $.fn.extend.disableSelection 0 6 2
A $.ui.ddmanager.dragStop 0 7 2
D $.widget(ꞌui.menuꞌ)._keydown 0 93 22
B $.widget(ꞌui.dialogꞌ)._makeDraggable 0 34 1
A $.widget(ꞌui.menuꞌ).select 0 10 2
B jquery-ui.js ➔ Datepicker 0 87 1
B $.widget(ꞌui.tabsꞌ)._refresh 0 34 2
A $.Widget.enable 0 3 1
A $.widget(ꞌui.tabsꞌ)._getList 0 3 1
B $.extend._enableDatepicker 0 24 5
B $.widget(ꞌui.sliderꞌ)._createHandles 0 26 3
A stringParsers.parse 0 8 1
C $.widget(ꞌui.sortableꞌ)._getItemsAsjQuery 0 31 11
B $.widget(ꞌui.menuꞌ)._destroy 0 36 1
B $.each 0 43 2
B $.widget(ꞌui.spinnerꞌ)._events.mousedown .ui-spinner-button 0 44 4
C $.widget(ꞌui.mouseꞌ)._mouseDown 0 54 12
F $.extend._generateHTML 0 182 80
A $.widget(ꞌui.spinnerꞌ)._precision 0 7 2
A $.fn.addBack 0 5 2
C $.widget(ꞌui.tabsꞌ)._eventHandler 0 46 16
A $.widget(ꞌui.tabsꞌ)._panelKeydown 0 11 4
A $.widget(ꞌui.progressbarꞌ)._destroy 0 10 1
A $.widget(ꞌui.spinnerꞌ)._events.blur 0 12 3
A $.Widget._on 0 52 3
B $.extend._restrictMinMax 0 6 5
C $.widget(ꞌui.droppableꞌ)._drop 0 38 7
D spaces.hsla.to 0 36 10
B $.widget(ꞌui.dialogꞌ)._size 0 44 5
A $.widget(ꞌui.menuꞌ).previous 0 3 1
B $.effects.effect.pulsate 0 46 6
F $.extend.parseDate 0 162 37
A $.widget(ꞌui.draggableꞌ)._trigger 0 9 2
A $.widget(ꞌui.sliderꞌ)._stop 0 12 3
C $.widget(ꞌui.sliderꞌ)._setOption 0 55 13
A $.widget(ꞌui.autocompleteꞌ)._resizeMenu 0 9 1
A $.widget(ꞌui.accordionꞌ)._setupEvents 0 16 2
A $.widget(ꞌui.sortableꞌ)._destroy 0 11 2
B $.widget(ꞌui.spinnerꞌ)._events.mousewheel 0 17 5
B $.widget(ꞌui.spinnerꞌ)._parse 0 7 7
B $.effects.effect.puff 0 32 3
A $.widget(ꞌui.sortableꞌ)._create 0 22 3
F $.widget(ꞌui.sortableꞌ)._clear 0 109 29
B $.widget(ꞌui.autocompleteꞌ)._move 0 13 6
B $.ui.plugin.add(ꞌresizableꞌ).stop 0 36 6
A $.widget(ꞌui.sortableꞌ)._rearrange 0 19 4
B $.widget(ꞌui.sortableꞌ)._adjustOffsetFromHelper 0 20 7
A $.widget(ꞌui.resizableꞌ).ui 0 11 1
A $.widget(ꞌui.dialogꞌ)._minHeight 0 7 2
A $.widget(ꞌui.spinnerꞌ)._refresh 0 8 1
D $.fn.extend.zIndex 0 28 10
A $.widget(ꞌui.mouseꞌ)._mouseDelayMet 0 3 1
A $.ui.ddmanager.drop 0 23 1
F $.extend._hideDatepicker 0 44 17
B $.widget(ꞌui.tabsꞌ)._handlePageNav 0 10 5
A $.extend.restore 0 17 4
A $.fn.extend.enableSelection 0 3 1
A jquery-ui.js ➔ parseCss 0 3 1
A $.widget(ꞌui.menuꞌ).isLastItem 0 3 1
A $.widget(ꞌui.autocompleteꞌ)._renderItemData 0 3 1
B $.widget(ꞌui.dialogꞌ)._setOptions 0 24 3
D $.Widget.option 0 39 9
A $.widget(ꞌui.sliderꞌ)._mouseStart 0 3 1
A $.widget(ꞌui.draggableꞌ)._destroy 0 4 1
A $.widget(ꞌui.menuꞌ).refresh 0 60 3
A $.widget(ꞌui.sliderꞌ)._mouseStop 0 13 1
B $.widget(ꞌui.autocompleteꞌ)._initSource 0 30 3
A $.widget(ꞌui.sortableꞌ)._getDragVerticalDirection 0 4 2
A $.widget(ꞌui.dialogꞌ)._createButtonPane 0 10 1
A $.widget(ꞌui.tabsꞌ)._sanitizeSelector 0 3 2
A $.widget(ꞌui.draggableꞌ)._clear 0 8 3
A $.widget(ꞌui.spinnerꞌ)._stop 0 11 2
F $.effects.effect.bounce 0 96 18
D $.extend._updateDatepicker 0 37 9
B $.widget(ꞌui.sortableꞌ).serialize 0 20 3
A $.Widget.widget 0 3 1
B $.widget(ꞌui.tabsꞌ)._create 0 53 5
D $.ui.position.fit.left 0 37 10
B spaces.hsla.from 0 18 5
A $.widget(ꞌui.dialogꞌ)._init 0 5 2
A $.extend._widgetDatepicker 0 3 1
A $.widget(ꞌui.accordionꞌ)._toggleComplete 0 15 2
C $.effects.effect.blind 0 62 11
C $.widget(ꞌui.accordionꞌ).refresh 0 31 8
A $.widget(ꞌui.tabsꞌ)._findActive 0 3 2
A $.widget(ꞌui.draggableꞌ)._mouseUp 0 13 2
A $.ui.ddmanager.drag 0 54 2
F $.ui.plugin.add(ꞌresizableꞌ).resize 0 55 21
A $.widget(ꞌui.tabsꞌ)._getIndex 0 8 2
C $.widget(ꞌui.buttonꞌ)._resetButton 0 42 13
B $.widget(ꞌui.sliderꞌ)._mouseCapture 0 58 5
A $.widget(ꞌui.autocompleteꞌ)._renderItem 0 5 1
A $.widget(ꞌui.sortableꞌ)._uiHash 0 12 2
B $.extend._attachHandlers 0 33 1
A $.extend.Bounce 0 7 2
A $.widget(ꞌui.sortableꞌ)._cacheHelperProportions 0 6 1
A $.extend._getNumberOfMonths 0 4 3
A $.extend.Sine 0 3 1
A jQuery.cssHooks.borderColor.expand 0 8 1
B $.widget(ꞌui.menuꞌ).previousPage 0 22 4
B $.widget(ꞌui.accordionꞌ)._animate 0 54 5
A $.widget(ꞌui.menuꞌ)._startOpening 0 14 2
A jquery-ui.js ➔ getOffsets 0 6 3
B $.widget(ꞌui.droppableꞌ)._over 0 17 5
A $.widget(ꞌui.sortableꞌ)._cacheMargins 0 6 1
C $.widget(ꞌui.draggableꞌ)._mouseStop 0 34 14
B $.widget(ꞌui.selectableꞌ)._mouseStop 0 30 1
A $.widget(ꞌui.sortableꞌ).toArray 0 11 1
B $.effects.effect.transfer 0 30 4
A $.extend._clearDate 0 4 1
C $.widget(ꞌui.sortableꞌ).refreshPositions 0 43 12
A $.widget(ꞌui.dialogꞌ)._appendTo 0 7 4
B $.extend.createWrapper 0 74 6
A $.extend._getDate 0 6 4
C $.widget(ꞌui.draggableꞌ)._convertPositionTo 0 30 8
A $.widget(ꞌui.spinnerꞌ)._precisionOf 0 5 2
C $.widget(ꞌui.tabsꞌ)._setOption 0 31 8
B $.widget(ꞌui.tabsꞌ).refresh 0 34 6
A $.widget(ꞌui.resizableꞌ)._change.sw 0 3 1
B $.ui.plugin.add(ꞌdraggableꞌ).stop 0 37 1
D $.ui.position.fit.top 0 37 10
A $.Widget._off 0 4 1
A $.widget(ꞌui.spinnerꞌ).widget 0 3 1
A $.widget(ꞌui.spinnerꞌ)._events.keydown 0 5 3
A $.widget(ꞌui.buttonꞌ)._destroy 0 13 2
A $.extend._tidyDialog 0 3 1
B $.widget(ꞌui.resizableꞌ)._updateCache 0 15 5
B jQuery.extend.transition 0 35 2
A $.widget(ꞌui.accordionꞌ)._processPanels 0 9 1
A $.widget(ꞌui.mouseꞌ)._mouseStop 0 1 1
A $.widget(ꞌui.menuꞌ).next 0 3 1
A $.fn.removeData.constructor 0 9 1
A jquery-ui.js ➔ isOverAxis 0 3 1
A $.Widget._setOptions 0 9 2
A $.Widget 0 1 1
D $.extend._optionDatepicker 0 46 17
A $.widget(ꞌui.autocompleteꞌ).close 0 4 1
A $.widget(ꞌui.sliderꞌ)._value 0 6 1
A jquery-ui.js ➔ 0 13 2
A $.widget(ꞌui.sortableꞌ)._connectWith 0 4 2
A $.widget(ꞌui.droppableꞌ)._destroy 0 12 3
A $.widget(ꞌui.accordionꞌ)._destroyIcons 0 6 1
B jquery-ui.js ➔ styleDifference 0 17 6
A $.widget(ꞌui.resizableꞌ)._change.se 0 3 1
B color.hook 0 48 1
B $.widget(ꞌui.draggableꞌ)._create 0 15 5
C $.effects.effect.fold 0 59 9
A $.widget(ꞌui.buttonsetꞌ)._create 0 3 1
A $.widget(ꞌui.dialogꞌ)._createTitlebar 0 48 1
A $.widget(ꞌui.spinnerꞌ)._stepUp 0 6 2
A $.widget(ꞌui.spinnerꞌ)._repeat 0 10 1
B $.widget(ꞌui.dialogꞌ)._createOverlay 0 33 3
A $.widget(ꞌui.spinnerꞌ)._spin 0 14 4
A $.widget(ꞌui.progressbarꞌ)._percentage 0 3 2
B $.fn.extend.effect 0 45 5
A $.widget(ꞌui.dialogꞌ)._createWrapper 0 53 2
A $.widget(ꞌui.spinnerꞌ)._stepDown 0 6 2
C $.widget(ꞌui.tabsꞌ)._tabKeydown 0 60 13
A $.widget(ꞌui.draggableꞌ)._cacheHelperProportions 0 6 1
C jQuery.extend.parse 0 72 9
A $.widget(ꞌui.sortableꞌ)._getDragHorizontalDirection 0 4 2
B $.widget(ꞌui.autocompleteꞌ)._appendTo 0 19 6
A $.widget(ꞌui.resizableꞌ)._change.ne 0 3 1
A $.widget(ꞌui.sliderꞌ)._valueMax 0 3 1
F $.widget(ꞌui.sliderꞌ)._refreshValue 0 56 19
C jquery-ui.js ➔ standardAnimationOption 0 24 9
C $.widget(ꞌui.sortableꞌ)._mouseStop 0 34 11
B $.widget(ꞌui.tabsꞌ)._setupHeightStyle 0 34 3
A $.widget(ꞌui.tabsꞌ)._tabId 0 3 1
A $.Widget._hoverable 0 11 1
B $.widget(ꞌui.resizableꞌ)._updateRatio 0 23 5
A $.widget(ꞌui.accordionꞌ)._getCreateEventData 0 7 3
F $.widget(ꞌui.resizableꞌ)._respectSize 0 44 21
D jquery-ui.js ➔ getElementStyles 0 26 10
B $.widget(ꞌui.sliderꞌ)._trimAlignValue 0 19 6
A $.widget(ꞌui.menuꞌ).isFirstItem 0 3 1
A $.widget(ꞌui.autocompleteꞌ)._destroy 0 8 1
A $.extend._get 0 4 2
A $.widget(ꞌui.dialogꞌ).widget 0 3 1
A $.widget(ꞌui.draggableꞌ)._getRelativeOffset 0 13 2
A $.extend._daylightSavingAdjust 0 7 3
D $.widget(ꞌui.buttonꞌ)._determineButtonType 0 37 10
F $.widget(ꞌui.resizableꞌ)._mouseStop 0 42 9
A jquery-ui.js ➔ ??? 0 3 1
A $.widget(ꞌui.draggableꞌ)._cacheMargins 0 8 1
B $.widget(ꞌui.accordionꞌ)._destroy 0 39 2
D $.widget(ꞌui.buttonꞌ)._create 0 137 9
A $.widget(ꞌui.autocompleteꞌ)._searchTimeout 0 10 1
F $.widget(ꞌui.resizableꞌ)._mouseStart 0 45 9
B $.widget(ꞌui.mouseꞌ)._mouseMove 0 19 9
A $.extend.plugin.add 0 8 2
D $.effects.effect.slide 0 47 10
A $.widget(ꞌui.menuꞌ).collapseAll 0 18 1
A $.widget(ꞌui.spinnerꞌ)._events.mouseenter .ui-spinner-button 0 11 4
B $.widget(ꞌui.droppableꞌ)._create 0 35 2
A jQuery.extend.blend 0 14 2
A $.extend.removeWrapper 0 15 4
B jquery-ui.js ➔ stringParse 0 39 3
C $.widget(ꞌui.accordionꞌ)._keydown 0 38 12
A $.widget(ꞌui.tabsꞌ)._getCreateEventData 0 6 2
A $.ui.plugin.add(ꞌdraggableꞌ).start 0 18 1
B $.widget(ꞌui.droppableꞌ)._out 0 17 5
A $.extend._setDateDatepicker 0 8 2
A $.extend.Elastic 0 4 3
A $.widget(ꞌui.mouseꞌ)._mouseStart 0 1 1
A $.widget(ꞌui.tabsꞌ)._activate 0 21 3
A $.widget(ꞌui.sliderꞌ)._setupEvents 0 7 1
A $.widget(ꞌui.sortableꞌ)._trigger 0 5 2
B $.extend._checkExternalClick 0 17 10
A $.widget(ꞌui.menuꞌ)._hasScroll 0 3 1
C $.widget(ꞌui.sortableꞌ)._intersectsWith 0 30 7
B $.extend._disableDatepicker 0 25 5
A $.position.scrollbarWidth 0 22 3
A $.extend._newInst 0 9 2
A $.Widget._setOption 0 13 2
A jQuery.extend.is 0 21 1
C $.effects.effect.clip 0 50 7
D $.widget(ꞌui.accordionꞌ)._setOption 0 35 10
B $.extend.hasScroll 0 22 5
F $.widget(ꞌui.resizableꞌ)._updateVirtualBoundaries 0 34 11
A $.widget(ꞌui.tabsꞌ)._getPanelForTab 0 4 1
A $.widget(ꞌui.sortableꞌ)._getRelativeOffset 0 13 2
C $.widget(ꞌui.draggableꞌ)._getParentOffset 0 27 8
A $.widget(ꞌui.dialogꞌ)._moveToTop 0 7 3
A $.fn.extend.removeUniqueId 0 7 1
A $.widget(ꞌui.resizableꞌ)._change.w 0 4 1
A $.widget(ꞌui.menuꞌ)._close 0 14 3
A $.extend._notifyChange 0 7 3
A $.widget(ꞌui.buttonꞌ)._setOption 0 11 3
B $.widget(ꞌui.spinnerꞌ)._create 0 26 2
A $.fn.extend.uniqueId 0 7 1
A $.extend.focusable 0 3 1
A $.extend.Back 0 3 1
B jquery-ui.js ➔ bindHover 0 24 1
A $.extend.setMode 0 6 3
A $.widget(ꞌui.menuꞌ)._activate 0 9 3
A $.extend._canAdjustMonth 0 10 3
A $.widget(ꞌui.droppableꞌ)._activate 0 9 3
A $.widget(ꞌui.tabsꞌ)._findNextTab 0 19 3
A jquery-ui.js ➔ isFloating 0 3 1
A $.effects.animateClass 0 74 1
A $.widget(ꞌui.selectableꞌ)._mouseStart 0 68 3
A $.position.getWithinInfo 0 15 3
A $.widget(ꞌui.mouseꞌ)._mouseDistanceMet 0 7 1
A $.widget(ꞌui.progressbarꞌ)._setOptions 0 10 1
A $.widget(ꞌui.mouseꞌ)._mouseUp 0 17 3
A $.widget(ꞌui.progressbarꞌ)._constrainedValue 0 15 4
A $.widget(ꞌui.autocompleteꞌ).search 0 16 4
A $.widget(ꞌui.sortableꞌ)._setOption 0 10 2
D $.widget(ꞌui.sortableꞌ)._convertPositionTo 0 25 9
A $.widget(ꞌui.draggableꞌ)._getHandle 0 5 2
A $.widget(ꞌui.sortableꞌ).refresh 0 5 1
A $.widget(ꞌui.sliderꞌ)._create 0 20 1
A $.extend._getInst 0 8 2
A $.widget(ꞌui.droppableꞌ)._setOption 0 9 3
B $.extend._doKeyUp 0 21 5
A $.extend._getDateDatepicker 0 7 4
A $.widget(ꞌui.dialogꞌ)._destroyOverlay 0 15 4
A jQuery.extend.toRgbaString 0 13 2
B $.widget(ꞌui.spinnerꞌ)._keydown 0 21 5
B $.widget(ꞌui.autocompleteꞌ).__response 0 13 6
A $.widget(ꞌui.tabsꞌ)._createPanel 0 6 1
A $.extend._getFormatConfig 0 8 2
A $.extend._getFirstDayOfMonth 0 3 1
A $.widget(ꞌui.menuꞌ).blur 0 14 3
A $.widget(ꞌui.dialogꞌ).options.position.using 0 6 2
A $.widget(ꞌui.spinnerꞌ)._increment 0 11 3
A $.widget(ꞌui.sortableꞌ)._removeCurrentsFromItems 0 14 1
A $.widget(ꞌui.buttonsetꞌ)._destroy 0 10 1
A $.widget(ꞌui.tabsꞌ)._processTabs 0 64 1
A jQuery.extend._space 0 10 1
A jquery-ui.js ➔ isLocal 0 9 1
A $.widget(ꞌui.spinnerꞌ)._events.focus 0 3 1
A $.widget(ꞌui.accordionꞌ)._createIcons 0 12 2
A $(document).mouseup 0 3 1
B $.widget(ꞌui.dialogꞌ)._destroy 0 27 4
B $.widget(ꞌui.menuꞌ)._create 0 104 2
A $.widget(ꞌui.spinnerꞌ)._buttonHtml 0 9 1
B $.extend._destroyDatepicker 0 23 5
A $.widget(ꞌui.menuꞌ).collapse 0 8 3
A jquery-ui.js ➔ radioGroup 0 17 3
B $.Widget._trigger 0 28 5
C $.widget(ꞌui.sortableꞌ)._refreshItems 0 42 12
C $.widget(ꞌui.draggableꞌ)._setContainment 0 56 9
A $.widget(ꞌui.menuꞌ)._setOption 0 8 2
B $.extend._autoSize 0 26 6
B $.widget(ꞌui.sliderꞌ)._values 0 23 5
A $.widget(ꞌui.dialogꞌ)._unblockFrames 0 6 2
D $.extend._dialogDatepicker 0 41 8
A $.widget(ꞌui.resizableꞌ)._change.n 0 4 1
B $.extend.plugin.call 0 13 6
B $.widget(ꞌui.draggableꞌ)._mouseCapture 0 28 6
A $.widget(ꞌui.resizableꞌ)._change.e 0 3 1
A $.expr.createPseudo 0 5 1
A $.widget(ꞌui.accordionꞌ)._findActive 0 3 2
A $.widget(ꞌui.accordionꞌ)._panelKeyDown 0 5 3
C $.widget(ꞌui.sortableꞌ)._getParentOffset 0 28 8
B $.widget(ꞌui.spinnerꞌ)._draw 0 29 4
B $.widget(ꞌui.menuꞌ)._move 0 19 8
A $.widget(ꞌui.progressbarꞌ)._create 0 18 1
A $.widget(ꞌui.spinnerꞌ)._getCreateOptions 0 13 1
A $.extend._isDisabledDatepicker 0 11 4
A $.widget(ꞌui.dialogꞌ)._allowInteraction 0 9 2
B $.widget(ꞌui.sliderꞌ)._change 0 17 5
C $.widget(ꞌui.tabsꞌ)._initialActive 0 42 13
A $.extend._formatDate 0 11 4
A $.Widget._focusable 0 11 1
C $.effects.effect.explode 0 80 10
D $.extend.formatDate 0 86 24
C $.widget(ꞌui.sliderꞌ).values 0 32 7
A $.widget(ꞌui.spinnerꞌ).value 0 6 2
A $.widget(ꞌui.sliderꞌ)._handleEvents.click 0 3 1
B $.widget(ꞌui.autocompleteꞌ)._setOption 0 12 6
A $.widget(ꞌui.droppableꞌ).ui 0 8 1
B $.Widget._createWidget 0 35 4
B $.widget(ꞌui.progressbarꞌ)._refreshValue 0 35 6
A $.widget(ꞌui.dialogꞌ).open 0 23 3
B $.extend._setDate 0 17 6
A $.widget(ꞌui.autocompleteꞌ)._value 0 3 1
C $.widget.extend 0 25 7
F $.widget(ꞌui.draggableꞌ)._generatePosition 0 77 24
A $.widget(ꞌui.resizableꞌ)._propagate 0 4 1
A $.extend._refreshDatepicker 0 6 2
A $.widget(ꞌui.menuꞌ)._itemRole 0 6 1
A $.widget(ꞌui.menuꞌ)._open 0 16 1
A $.widget(ꞌui.spinnerꞌ)._destroy 0 11 1
A $.widget(ꞌui.autocompleteꞌ).options.messages.results 0 4 2
A $.widget(ꞌui.autocompleteꞌ)._change 0 5 2
C $.widget(ꞌui.dialogꞌ).close 0 34 7
B $.widget(ꞌui.buttonꞌ).refresh 0 31 6
A $.extend._updateAlternate 0 11 2
A $.extend._shouldFocusInput 0 3 1
A $.effects.effect.fade 0 13 1
A $.widget(ꞌui.mouseꞌ)._mouseDestroy 0 8 2
A $.widget(ꞌui.sliderꞌ)._refresh 0 6 1
D $.widget(ꞌui.draggableꞌ)._mouseDrag 0 32 9
F $.widget(ꞌui.sortableꞌ)._contactContainers 0 99 24
A $.widget(ꞌui.sliderꞌ)._handleEvents.keyup 0 10 2
B $.widget(ꞌui.sortableꞌ)._intersectsWithPointer 0 17 8
B $.widget(ꞌui.sortableꞌ)._createPlaceholder 0 56 3
A $.widget(ꞌui.progressbarꞌ).value 0 8 2
B $.widget(ꞌui.resizableꞌ)._destroy 0 29 2
F $.widget(ꞌui.sortableꞌ)._generatePosition 0 66 24
A $.widget(ꞌui.sliderꞌ)._start 0 11 3
A jquery-ui.js ➔ getNextTabId 0 3 1
A $.widget(ꞌui.resizableꞌ)._change.nw 0 3 1
C $.widget(ꞌui.sliderꞌ)._createRange 0 41 12
C $.extend._setDateFromField 0 24 8
A $.extend.Circ 0 3 1
A $.widget(ꞌui.dialogꞌ)._position 0 11 3
A $.widget(ꞌui.menuꞌ).expand 0 16 3
B $.extend._findPos 0 12 6
A $.extend._selectDay 0 15 3
A $.widget(ꞌui.dialogꞌ).moveToTop 0 3 1
D jquery-ui.js ➔ clamp 0 25 9
B $.widget(ꞌui.tabsꞌ).disable 0 21 5
B $.widget(ꞌui.draggableꞌ)._mouseStart 0 85 6
C $.extend._checkOffset 0 20 14
A $.widget(ꞌui.menuꞌ)._scrollIntoView 0 17 4
B $.widget(ꞌui.selectableꞌ)._mouseDrag 0 92 4
A jquery-ui.js ➔ isNumber 0 3 1
B jquery-ui.js ➔ getDimensions 0 29 4
B $.widget.bridge 0 45 1
A $.widget(ꞌui.spinnerꞌ)._uiSpinnerHtml 0 3 1
A jquery-ui.js ➔ num 0 3 1
A $.extend._inlineDatepicker 0 18 3
B $.widget(ꞌui.tabsꞌ)._toggle 0 61 6
F $.widget(ꞌui.sortableꞌ)._mouseStart 0 133 17
A $.widget(ꞌui.autocompleteꞌ)._keyEvent 0 8 3
A jQuery.Color 0 3 1
A jquery-ui.js ➔ extendRemove 0 9 3
A $.widget(ꞌui.draggableꞌ).cancel 0 11 2
A $.widget(ꞌui.autocompleteꞌ)._normalize 0 18 4
B $.widget(ꞌui.dialogꞌ)._focusTabbable 0 22 5
B $.fn.extend.scrollParent 0 14 6
A 0 15 1
C $.effects.effect.drop 0 48 12
A $.cleanData 0 9 3
C $.widget(ꞌui.sliderꞌ)._normValueFromMouse 0 31 7
A $.widget(ꞌui.spinnerꞌ)._format 0 8 4
F $.fn.position 0 179 9
A $.widget(ꞌui.sliderꞌ)._destroy 0 16 2
A $.extend.escapeRegex 0 3 1
C $.widget(ꞌui.menuꞌ).focus 0 37 7
A $.widget(ꞌui.sliderꞌ)._valueMin 0 3 1
B $.widget(ꞌui.accordionꞌ)._create 0 19 5
B $.extend.getBaseline 0 19 9
A $.extend._adjustDate 0 12 3
B $.widget(ꞌui.menuꞌ).nextPage 0 24 5
F $.widget(ꞌui.resizableꞌ)._create 0 169 12
A $.widget(ꞌui.draggableꞌ)._uiHash 0 8 1
A $.widget(ꞌui.dialogꞌ)._title 0 6 2
A $.extend._doKeyPress 0 10 3
A $.widget(ꞌui.buttonꞌ).widget 0 3 1
A $.widget(ꞌui.sliderꞌ).value 0 10 2
A $.fn.extend.switchClass 0 6 1
A $.widget(ꞌui.tabsꞌ)._focusNextTab 0 5 1
F $.extend._showDatepicker 0 79 20
B $.ui.plugin.add(ꞌdraggableꞌ).drag 0 99 1
A $.extend.filter 0 6 1
A jquery-ui.js ➔ visible 0 6 1
A $.widget(ꞌui.tabsꞌ)._destroy 0 53 3
B $.Widget.destroy 0 25 1
A $.widget(ꞌui.mouseꞌ)._mouseInit 0 17 1
A $.widget(ꞌui.autocompleteꞌ)._suggest 0 17 2
B jquery-ui.js ➔ focusable 0 20 8
B $.effects.effect.highlight 0 33 2
A $.fn.removeData 0 7 2
A $.widget(ꞌui.dialogꞌ)._keepFocus 0 16 1
A $.fn.extend.cssUnit 0 11 1
A $.Widget._delay 0 8 1
B $.widget(ꞌui.accordionꞌ)._toggle 0 45 6
F $.widget(ꞌui.sortableꞌ)._mouseDrag 0 120 33
B $.widget(ꞌui.spinnerꞌ)._adjustValue 0 26 6
A $.extend._changeDatepicker 0 3 1
A $.extend.save 0 7 3
B $.widget(ꞌui.resizableꞌ)._renderProxy 0 27 2
A jQuery.extend.toHexString 0 15 2
F $.widget(ꞌui.dialogꞌ)._setOption 0 68 20
F jquery-ui.js ➔ _normalizeArguments 0 51 11
A $.extend._connectDatepicker 0 17 3
C $.widget(ꞌui.sliderꞌ)._slide 0 41 15
B $.widget(ꞌui.resizableꞌ)._proportionallyResize 0 31 5
A $.widget(ꞌui.tabsꞌ)._ajaxSettings 0 10 1
A $.widget(ꞌui.droppableꞌ)._deactivate 0 9 3
A $.extend._getMinMaxDate 0 3 1
A $.widget(ꞌui.sortableꞌ)._intersectsWithSides 0 14 3
B $.widget(ꞌui.draggableꞌ)._createHelper 0 16 7
B $.widget(ꞌui.autocompleteꞌ)._create 0 262 5
A $.widget(ꞌui.mouseꞌ)._mouseCapture 0 1 1
A $.extend.tabbable 0 5 1
A $.widget(ꞌui.buttonsetꞌ)._init 0 3 1
F $.extend._attachments 0 46 12
D $.extend._doKeyDown 0 96 40
B $.widget(ꞌui.dialogꞌ)._create 0 35 5
F $.widget(ꞌui.sortableꞌ)._setContainment 0 30 9
B $.widget(ꞌui.tabsꞌ).enable 0 22 4
A $.widget(ꞌui.autocompleteꞌ)._renderMenu 0 6 1
A $.extend._gotoToday 0 18 3
A $.extend._getDefaultDate 0 4 1
D $.widget(ꞌui.spinnerꞌ)._setOption 0 34 10
A $.widget(ꞌui.autocompleteꞌ)._close 0 8 2
A $.widget(ꞌui.dialogꞌ)._makeResizable 0 47 2
C $.widget(ꞌui.sliderꞌ)._handleEvents.keydown 0 63 23
A $.extend.setTransition 0 10 1
C $.ui.position.flip.left 0 35 12
A $.ui.position.flipfit.left 0 4 1
F $.extend._generateMonthYearHeader 0 70 22
A $.extend._selectMonthYear 0 11 3
A jQuery.extend.toString 0 3 2
A $.ui.position.flipfit.top 0 4 1
F $.effects.effect.size 0 206 17
C $.extend._possibleChars 0 41 14
A $.widget(ꞌui.dialogꞌ).isOpen 0 3 1
A $.extend._getDaysInMonth 0 3 1
A $.widget(ꞌui.progressbarꞌ)._setOption 0 8 2
A $.widget(ꞌui.autocompleteꞌ).widget 0 3 1
B $.widget(ꞌui.dialogꞌ)._createButtons 0 38 4
B $.widget(ꞌui.selectableꞌ)._create 0 37 1
B $.widget(ꞌui.draggableꞌ)._adjustOffsetFromHelper 0 20 7
A $.widget(ꞌui.sliderꞌ)._detectOrientation 0 3 2
C $.extend._selectDate 0 29 8
A jquery-ui.js ➔ hue2rgb 0 13 4
C $.widget(ꞌui.sortableꞌ).cancel 0 49 11
A $.widget(ꞌui.resizableꞌ)._change.s 0 3 1
D $.ui.ddmanager.prepareOffsets 0 38 10
A $.widget(ꞌui.buttonsetꞌ)._setOption 0 7 2
A $.widget(ꞌui.dialogꞌ)._blockFrames 0 14 1
C $.widget(ꞌui.tabsꞌ)._setupDisabled 0 24 7
C $.ui.plugin.add(ꞌresizableꞌ).start 0 45 8
A jquery-ui.js ➔ each 0 8 1
A $.widget(ꞌui.buttonsetꞌ).refresh 0 22 3
A $.widget(ꞌui.autocompleteꞌ)._response 0 14 1
C $.widget(ꞌui.sortableꞌ)._mouseCapture 0 46 9
A jquery-ui.js ➔ formResetHandler 0 6 1
A jquery-ui.js ➔ modifier 0 10 1
A $.widget(ꞌui.sliderꞌ)._mouseDrag 0 8 1
A jQuery.extend.toHslaString 0 20 2
A $.widget(ꞌui.accordionꞌ)._activate 0 17 2
B $.widget 0 112 5
B $.effects.effect.shake 0 57 8
C $.ui.intersect 0 43 7
A $.widget(ꞌui.tabsꞌ)._setupEvents 0 20 2
C $.fn.datepicker 0 34 11
A $.extend.setDefaults 0 4 1
C $.widget(ꞌui.sortableꞌ)._createHelper 0 24 10
A $.extend.noWeekends 0 4 1
C $.effects.effect.scale 0 61 10
B $.extend._adjustInstDate 0 13 6

How to fix   Complexity   

Complexity

Complex classes like build/media/libraries/redcore/media/redcore/lib/jquery-ui/jquery-ui.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
/*! jQuery UI - v1.10.4 - 2014-10-28
2
* http://jqueryui.com
3
* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.position.js, jquery.ui.draggable.js, jquery.ui.droppable.js, jquery.ui.resizable.js, jquery.ui.selectable.js, jquery.ui.sortable.js, jquery.ui.accordion.js, jquery.ui.autocomplete.js, jquery.ui.button.js, jquery.ui.datepicker.js, jquery.ui.dialog.js, jquery.ui.menu.js, jquery.ui.progressbar.js, jquery.ui.slider.js, jquery.ui.spinner.js, jquery.ui.tabs.js, jquery.ui.effect.js, jquery.ui.effect-blind.js, jquery.ui.effect-bounce.js, jquery.ui.effect-clip.js, jquery.ui.effect-drop.js, jquery.ui.effect-explode.js, jquery.ui.effect-fade.js, jquery.ui.effect-fold.js, jquery.ui.effect-highlight.js, jquery.ui.effect-pulsate.js, jquery.ui.effect-scale.js, jquery.ui.effect-shake.js, jquery.ui.effect-slide.js, jquery.ui.effect-transfer.js
4
* Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */
5
6
(function( $, undefined ) {
7
8
var uuid = 0,
9
	runiqueId = /^ui-id-\d+$/;
10
11
// $.ui might exist from components with no dependencies, e.g., $.ui.position
12
$.ui = $.ui || {};
13
14
$.extend( $.ui, {
15
	version: "1.10.4",
16
17
	keyCode: {
18
		BACKSPACE: 8,
19
		COMMA: 188,
20
		DELETE: 46,
21
		DOWN: 40,
22
		END: 35,
23
		ENTER: 13,
24
		ESCAPE: 27,
25
		HOME: 36,
26
		LEFT: 37,
27
		NUMPAD_ADD: 107,
28
		NUMPAD_DECIMAL: 110,
29
		NUMPAD_DIVIDE: 111,
30
		NUMPAD_ENTER: 108,
31
		NUMPAD_MULTIPLY: 106,
32
		NUMPAD_SUBTRACT: 109,
33
		PAGE_DOWN: 34,
34
		PAGE_UP: 33,
35
		PERIOD: 190,
36
		RIGHT: 39,
37
		SPACE: 32,
38
		TAB: 9,
39
		UP: 38
40
	}
41
});
42
43
// plugins
44
$.fn.extend({
45
	focus: (function( orig ) {
46
		return function( delay, fn ) {
47
			return typeof delay === "number" ?
48
				this.each(function() {
49
					var elem = this;
50
					setTimeout(function() {
51
						$( elem ).focus();
52
						if ( fn ) {
53
							fn.call( elem );
54
						}
55
					}, delay );
56
				}) :
57
				orig.apply( this, arguments );
58
		};
59
	})( $.fn.focus ),
60
61
	scrollParent: function() {
62
		var scrollParent;
63
		if (($.ui.ie && (/(static|relative)/).test(this.css("position"))) || (/absolute/).test(this.css("position"))) {
64
			scrollParent = this.parents().filter(function() {
65
				return (/(relative|absolute|fixed)/).test($.css(this,"position")) && (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x"));
66
			}).eq(0);
67
		} else {
68
			scrollParent = this.parents().filter(function() {
69
				return (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x"));
70
			}).eq(0);
71
		}
72
73
		return (/fixed/).test(this.css("position")) || !scrollParent.length ? $(document) : scrollParent;
74
	},
75
76
	zIndex: function( zIndex ) {
77
		if ( zIndex !== undefined ) {
78
			return this.css( "zIndex", zIndex );
79
		}
80
81
		if ( this.length ) {
82
			var elem = $( this[ 0 ] ), position, value;
83
			while ( elem.length && elem[ 0 ] !== document ) {
84
				// Ignore z-index if position is set to a value where z-index is ignored by the browser
85
				// This makes behavior of this function consistent across browsers
86
				// WebKit always returns auto if the element is positioned
87
				position = elem.css( "position" );
88
				if ( position === "absolute" || position === "relative" || position === "fixed" ) {
89
					// IE returns 0 when zIndex is not specified
90
					// other browsers return a string
91
					// we ignore the case of nested elements with an explicit value of 0
92
					// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
93
					value = parseInt( elem.css( "zIndex" ), 10 );
94
					if ( !isNaN( value ) && value !== 0 ) {
95
						return value;
96
					}
97
				}
98
				elem = elem.parent();
99
			}
100
		}
101
102
		return 0;
103
	},
104
105
	uniqueId: function() {
106
		return this.each(function() {
107
			if ( !this.id ) {
108
				this.id = "ui-id-" + (++uuid);
109
			}
110
		});
111
	},
112
113
	removeUniqueId: function() {
114
		return this.each(function() {
115
			if ( runiqueId.test( this.id ) ) {
116
				$( this ).removeAttr( "id" );
117
			}
118
		});
119
	}
120
});
121
122
// selectors
123
function focusable( element, isTabIndexNotNaN ) {
124
	var map, mapName, img,
125
		nodeName = element.nodeName.toLowerCase();
126
	if ( "area" === nodeName ) {
127
		map = element.parentNode;
128
		mapName = map.name;
129
		if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
130
			return false;
131
		}
132
		img = $( "img[usemap=#" + mapName + "]" )[0];
133
		return !!img && visible( img );
134
	}
135
	return ( /input|select|textarea|button|object/.test( nodeName ) ?
136
		!element.disabled :
137
		"a" === nodeName ?
138
			element.href || isTabIndexNotNaN :
139
			isTabIndexNotNaN) &&
140
		// the element and all of its ancestors must be visible
141
		visible( element );
142
}
143
144
function visible( element ) {
145
	return $.expr.filters.visible( element ) &&
146
		!$( element ).parents().addBack().filter(function() {
147
			return $.css( this, "visibility" ) === "hidden";
148
		}).length;
149
}
150
151
$.extend( $.expr[ ":" ], {
152
	data: $.expr.createPseudo ?
153
		$.expr.createPseudo(function( dataName ) {
154
			return function( elem ) {
155
				return !!$.data( elem, dataName );
156
			};
157
		}) :
158
		// support: jQuery <1.8
159
		function( elem, i, match ) {
160
			return !!$.data( elem, match[ 3 ] );
161
		},
162
163
	focusable: function( element ) {
164
		return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
165
	},
166
167
	tabbable: function( element ) {
168
		var tabIndex = $.attr( element, "tabindex" ),
169
			isTabIndexNaN = isNaN( tabIndex );
170
		return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
171
	}
172
});
173
174
// support: jQuery <1.8
175
if ( !$( "<a>" ).outerWidth( 1 ).jquery ) {
176
	$.each( [ "Width", "Height" ], function( i, name ) {
177
		var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
178
			type = name.toLowerCase(),
179
			orig = {
180
				innerWidth: $.fn.innerWidth,
181
				innerHeight: $.fn.innerHeight,
182
				outerWidth: $.fn.outerWidth,
183
				outerHeight: $.fn.outerHeight
184
			};
185
186
		function reduce( elem, size, border, margin ) {
187
			$.each( side, function() {
188
				size -= parseFloat( $.css( elem, "padding" + this ) ) || 0;
189
				if ( border ) {
190
					size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;
191
				}
192
				if ( margin ) {
193
					size -= parseFloat( $.css( elem, "margin" + this ) ) || 0;
194
				}
195
			});
196
			return size;
197
		}
198
199
		$.fn[ "inner" + name ] = function( size ) {
200
			if ( size === undefined ) {
201
				return orig[ "inner" + name ].call( this );
202
			}
203
204
			return this.each(function() {
205
				$( this ).css( type, reduce( this, size ) + "px" );
206
			});
207
		};
208
209
		$.fn[ "outer" + name] = function( size, margin ) {
210
			if ( typeof size !== "number" ) {
211
				return orig[ "outer" + name ].call( this, size );
212
			}
213
214
			return this.each(function() {
215
				$( this).css( type, reduce( this, size, true, margin ) + "px" );
216
			});
217
		};
218
	});
219
}
220
221
// support: jQuery <1.8
222
if ( !$.fn.addBack ) {
223
	$.fn.addBack = function( selector ) {
224
		return this.add( selector == null ?
225
			this.prevObject : this.prevObject.filter( selector )
226
		);
227
	};
228
}
229
230
// support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413)
231
if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) {
232
	$.fn.removeData = (function( removeData ) {
233
		return function( key ) {
234
			if ( arguments.length ) {
235
				return removeData.call( this, $.camelCase( key ) );
236
			} else {
237
				return removeData.call( this );
238
			}
239
		};
240
	})( $.fn.removeData );
241
}
242
243
244
245
246
247
// deprecated
248
$.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() );
0 ignored issues
show
Bug introduced by
The variable navigator seems to be never declared. If this is a global, consider adding a /** global: navigator */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
249
250
$.support.selectstart = "onselectstart" in document.createElement( "div" );
251
$.fn.extend({
252
	disableSelection: function() {
253
		return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
254
			".ui-disableSelection", function( event ) {
255
				event.preventDefault();
256
			});
257
	},
258
259
	enableSelection: function() {
260
		return this.unbind( ".ui-disableSelection" );
261
	}
262
});
263
264
$.extend( $.ui, {
265
	// $.ui.plugin is deprecated. Use $.widget() extensions instead.
266
	plugin: {
267
		add: function( module, option, set ) {
268
			var i,
269
				proto = $.ui[ module ].prototype;
270
			for ( i in set ) {
271
				proto.plugins[ i ] = proto.plugins[ i ] || [];
272
				proto.plugins[ i ].push( [ option, set[ i ] ] );
273
			}
274
		},
275
		call: function( instance, name, args ) {
276
			var i,
277
				set = instance.plugins[ name ];
278
			if ( !set || !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) {
279
				return;
280
			}
281
282
			for ( i = 0; i < set.length; i++ ) {
283
				if ( instance.options[ set[ i ][ 0 ] ] ) {
284
					set[ i ][ 1 ].apply( instance.element, args );
285
				}
286
			}
287
		}
288
	},
289
290
	// only used by resizable
291
	hasScroll: function( el, a ) {
292
293
		//If overflow is hidden, the element might have extra content, but the user wants to hide it
294
		if ( $( el ).css( "overflow" ) === "hidden") {
295
			return false;
296
		}
297
298
		var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
299
			has = false;
0 ignored issues
show
Unused Code introduced by
The assignment to variable has seems to be never used. Consider removing it.
Loading history...
300
301
		if ( el[ scroll ] > 0 ) {
302
			return true;
303
		}
304
305
		// TODO: determine which cases actually cause this to happen
306
		// if the element doesn't have the scroll set, see if it's possible to
307
		// set the scroll
308
		el[ scroll ] = 1;
309
		has = ( el[ scroll ] > 0 );
310
		el[ scroll ] = 0;
311
		return has;
312
	}
313
});
314
315
})( jQuery );
316
(function( $, undefined ) {
317
318
var uuid = 0,
319
	slice = Array.prototype.slice,
320
	_cleanData = $.cleanData;
321
$.cleanData = function( elems ) {
322
	for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
323
		try {
324
			$( elem ).triggerHandler( "remove" );
325
		// http://bugs.jquery.com/ticket/8235
326
		} catch( e ) {}
327
	}
328
	_cleanData( elems );
329
};
330
331
$.widget = function( name, base, prototype ) {
332
	var fullName, existingConstructor, constructor, basePrototype,
333
		// proxiedPrototype allows the provided prototype to remain unmodified
334
		// so that it can be used as a mixin for multiple widgets (#8876)
335
		proxiedPrototype = {},
336
		namespace = name.split( "." )[ 0 ];
337
338
	name = name.split( "." )[ 1 ];
339
	fullName = namespace + "-" + name;
340
341
	if ( !prototype ) {
342
		prototype = base;
343
		base = $.Widget;
344
	}
345
346
	// create selector for plugin
347
	$.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
348
		return !!$.data( elem, fullName );
349
	};
350
351
	$[ namespace ] = $[ namespace ] || {};
352
	existingConstructor = $[ namespace ][ name ];
353
	constructor = $[ namespace ][ name ] = function( options, element ) {
354
		// allow instantiation without "new" keyword
355
		if ( !this._createWidget ) {
356
			return new constructor( options, element );
0 ignored issues
show
Coding Style Best Practice introduced by
By convention, constructors like constructor should be capitalized.
Loading history...
357
		}
358
359
		// allow instantiation without initializing for simple inheritance
360
		// must use "new" keyword (the code above always passes args)
361
		if ( arguments.length ) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if arguments.length is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
362
			this._createWidget( options, element );
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
363
		}
364
	};
365
	// extend with the existing constructor to carry over any static properties
366
	$.extend( constructor, existingConstructor, {
367
		version: prototype.version,
368
		// copy the object used to create the prototype in case we need to
369
		// redefine the widget later
370
		_proto: $.extend( {}, prototype ),
371
		// track widgets that inherit from this widget in case this widget is
372
		// redefined after a widget inherits from it
373
		_childConstructors: []
374
	});
375
376
	basePrototype = new base();
0 ignored issues
show
Coding Style Best Practice introduced by
By convention, constructors like base should be capitalized.
Loading history...
377
	// we need to make the options hash a property directly on the new instance
378
	// otherwise we'll modify the options hash on the prototype that we're
379
	// inheriting from
380
	basePrototype.options = $.widget.extend( {}, basePrototype.options );
381
	$.each( prototype, function( prop, value ) {
382
		if ( !$.isFunction( value ) ) {
383
			proxiedPrototype[ prop ] = value;
384
			return;
385
		}
386
		proxiedPrototype[ prop ] = (function() {
387
			var _super = function() {
388
					return base.prototype[ prop ].apply( this, arguments );
389
				},
390
				_superApply = function( args ) {
391
					return base.prototype[ prop ].apply( this, args );
392
				};
393
			return function() {
394
				var __super = this._super,
395
					__superApply = this._superApply,
396
					returnValue;
397
398
				this._super = _super;
399
				this._superApply = _superApply;
400
401
				returnValue = value.apply( this, arguments );
402
403
				this._super = __super;
404
				this._superApply = __superApply;
405
406
				return returnValue;
407
			};
408
		})();
409
	});
410
	constructor.prototype = $.widget.extend( basePrototype, {
411
		// TODO: remove support for widgetEventPrefix
412
		// always use the name + a colon as the prefix, e.g., draggable:start
413
		// don't prefix for widgets that aren't DOM-based
414
		widgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name
415
	}, proxiedPrototype, {
416
		constructor: constructor,
417
		namespace: namespace,
418
		widgetName: name,
419
		widgetFullName: fullName
420
	});
421
422
	// If this widget is being redefined then we need to find all widgets that
423
	// are inheriting from it and redefine all of them so that they inherit from
424
	// the new version of this widget. We're essentially trying to replace one
425
	// level in the prototype chain.
426
	if ( existingConstructor ) {
427
		$.each( existingConstructor._childConstructors, function( i, child ) {
428
			var childPrototype = child.prototype;
429
430
			// redefine the child widget using the same prototype that was
431
			// originally used, but inherit from the new version of the base
432
			$.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
433
		});
434
		// remove the list of existing child constructors from the old constructor
435
		// so the old child constructors can be garbage collected
436
		delete existingConstructor._childConstructors;
437
	} else {
438
		base._childConstructors.push( constructor );
439
	}
440
441
	$.widget.bridge( name, constructor );
442
};
443
444
$.widget.extend = function( target ) {
445
	var input = slice.call( arguments, 1 ),
446
		inputIndex = 0,
447
		inputLength = input.length,
448
		key,
449
		value;
450
	for ( ; inputIndex < inputLength; inputIndex++ ) {
451
		for ( key in input[ inputIndex ] ) {
452
			value = input[ inputIndex ][ key ];
453
			if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
454
				// Clone objects
455
				if ( $.isPlainObject( value ) ) {
456
					target[ key ] = $.isPlainObject( target[ key ] ) ?
457
						$.widget.extend( {}, target[ key ], value ) :
458
						// Don't extend strings, arrays, etc. with objects
459
						$.widget.extend( {}, value );
460
				// Copy everything else by reference
461
				} else {
462
					target[ key ] = value;
463
				}
464
			}
465
		}
466
	}
467
	return target;
468
};
469
470
$.widget.bridge = function( name, object ) {
471
	var fullName = object.prototype.widgetFullName || name;
472
	$.fn[ name ] = function( options ) {
473
		var isMethodCall = typeof options === "string",
474
			args = slice.call( arguments, 1 ),
475
			returnValue = this;
476
477
		// allow multiple hashes to be passed on init
478
		options = !isMethodCall && args.length ?
479
			$.widget.extend.apply( null, [ options ].concat(args) ) :
480
			options;
481
482
		if ( isMethodCall ) {
483
			this.each(function() {
484
				var methodValue,
485
					instance = $.data( this, fullName );
486
				if ( !instance ) {
487
					return $.error( "cannot call methods on " + name + " prior to initialization; " +
488
						"attempted to call method '" + options + "'" );
489
				}
490
				if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
491
					return $.error( "no such method '" + options + "' for " + name + " widget instance" );
492
				}
493
				methodValue = instance[ options ].apply( instance, args );
494
				if ( methodValue !== instance && methodValue !== undefined ) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if methodValue !== instance...thodValue !== undefined is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
495
					returnValue = methodValue && methodValue.jquery ?
496
						returnValue.pushStack( methodValue.get() ) :
497
						methodValue;
498
					return false;
499
				}
500
			});
501
		} else {
502
			this.each(function() {
503
				var instance = $.data( this, fullName );
504
				if ( instance ) {
505
					instance.option( options || {} )._init();
506
				} else {
507
					$.data( this, fullName, new object( options, this ) );
0 ignored issues
show
Coding Style Best Practice introduced by
By convention, constructors like object should be capitalized.
Loading history...
508
				}
509
			});
510
		}
511
512
		return returnValue;
513
	};
514
};
515
516
$.Widget = function( /* options, element */ ) {};
517
$.Widget._childConstructors = [];
518
519
$.Widget.prototype = {
520
	widgetName: "widget",
521
	widgetEventPrefix: "",
522
	defaultElement: "<div>",
523
	options: {
524
		disabled: false,
525
526
		// callbacks
527
		create: null
528
	},
529
	_createWidget: function( options, element ) {
530
		element = $( element || this.defaultElement || this )[ 0 ];
531
		this.element = $( element );
532
		this.uuid = uuid++;
533
		this.eventNamespace = "." + this.widgetName + this.uuid;
534
		this.options = $.widget.extend( {},
535
			this.options,
536
			this._getCreateOptions(),
537
			options );
538
539
		this.bindings = $();
540
		this.hoverable = $();
541
		this.focusable = $();
542
543
		if ( element !== this ) {
544
			$.data( element, this.widgetFullName, this );
545
			this._on( true, this.element, {
546
				remove: function( event ) {
547
					if ( event.target === element ) {
548
						this.destroy();
549
					}
550
				}
551
			});
552
			this.document = $( element.style ?
553
				// element within the document
554
				element.ownerDocument :
555
				// element is window or document
556
				element.document || element );
557
			this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
558
		}
559
560
		this._create();
561
		this._trigger( "create", null, this._getCreateEventData() );
562
		this._init();
563
	},
564
	_getCreateOptions: $.noop,
565
	_getCreateEventData: $.noop,
566
	_create: $.noop,
567
	_init: $.noop,
568
569
	destroy: function() {
570
		this._destroy();
571
		// we can probably remove the unbind calls in 2.0
572
		// all event bindings should go through this._on()
573
		this.element
574
			.unbind( this.eventNamespace )
575
			// 1.9 BC for #7810
576
			// TODO remove dual storage
577
			.removeData( this.widgetName )
578
			.removeData( this.widgetFullName )
579
			// support: jquery <1.6.3
580
			// http://bugs.jquery.com/ticket/9413
581
			.removeData( $.camelCase( this.widgetFullName ) );
582
		this.widget()
583
			.unbind( this.eventNamespace )
584
			.removeAttr( "aria-disabled" )
585
			.removeClass(
586
				this.widgetFullName + "-disabled " +
587
				"ui-state-disabled" );
588
589
		// clean up events and states
590
		this.bindings.unbind( this.eventNamespace );
591
		this.hoverable.removeClass( "ui-state-hover" );
592
		this.focusable.removeClass( "ui-state-focus" );
593
	},
594
	_destroy: $.noop,
595
596
	widget: function() {
597
		return this.element;
598
	},
599
600
	option: function( key, value ) {
601
		var options = key,
602
			parts,
603
			curOption,
604
			i;
605
606
		if ( arguments.length === 0 ) {
607
			// don't return a reference to the internal hash
608
			return $.widget.extend( {}, this.options );
609
		}
610
611
		if ( typeof key === "string" ) {
612
			// handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
613
			options = {};
614
			parts = key.split( "." );
615
			key = parts.shift();
616
			if ( parts.length ) {
617
				curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
618
				for ( i = 0; i < parts.length - 1; i++ ) {
619
					curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
620
					curOption = curOption[ parts[ i ] ];
621
				}
622
				key = parts.pop();
623
				if ( arguments.length === 1 ) {
624
					return curOption[ key ] === undefined ? null : curOption[ key ];
625
				}
626
				curOption[ key ] = value;
627
			} else {
628
				if ( arguments.length === 1 ) {
629
					return this.options[ key ] === undefined ? null : this.options[ key ];
630
				}
631
				options[ key ] = value;
632
			}
633
		}
634
635
		this._setOptions( options );
636
637
		return this;
638
	},
639
	_setOptions: function( options ) {
640
		var key;
641
642
		for ( key in options ) {
643
			this._setOption( key, options[ key ] );
644
		}
645
646
		return this;
647
	},
648
	_setOption: function( key, value ) {
649
		this.options[ key ] = value;
650
651
		if ( key === "disabled" ) {
652
			this.widget()
653
				.toggleClass( this.widgetFullName + "-disabled ui-state-disabled", !!value )
654
				.attr( "aria-disabled", value );
655
			this.hoverable.removeClass( "ui-state-hover" );
656
			this.focusable.removeClass( "ui-state-focus" );
657
		}
658
659
		return this;
660
	},
661
662
	enable: function() {
663
		return this._setOption( "disabled", false );
664
	},
665
	disable: function() {
666
		return this._setOption( "disabled", true );
667
	},
668
669
	_on: function( suppressDisabledCheck, element, handlers ) {
670
		var delegateElement,
671
			instance = this;
672
673
		// no suppressDisabledCheck flag, shuffle arguments
674
		if ( typeof suppressDisabledCheck !== "boolean" ) {
675
			handlers = element;
676
			element = suppressDisabledCheck;
677
			suppressDisabledCheck = false;
678
		}
679
680
		// no element argument, shuffle and use this.element
681
		if ( !handlers ) {
682
			handlers = element;
683
			element = this.element;
684
			delegateElement = this.widget();
685
		} else {
686
			// accept selectors, DOM elements
687
			element = delegateElement = $( element );
688
			this.bindings = this.bindings.add( element );
689
		}
690
691
		$.each( handlers, function( event, handler ) {
692
			function handlerProxy() {
693
				// allow widgets to customize the disabled handling
694
				// - disabled as an array instead of boolean
695
				// - disabled class as method for disabling individual parts
696
				if ( !suppressDisabledCheck &&
697
						( instance.options.disabled === true ||
698
							$( this ).hasClass( "ui-state-disabled" ) ) ) {
699
					return;
700
				}
701
				return ( typeof handler === "string" ? instance[ handler ] : handler )
702
					.apply( instance, arguments );
703
			}
704
705
			// copy the guid so direct unbinding works
706
			if ( typeof handler !== "string" ) {
707
				handlerProxy.guid = handler.guid =
708
					handler.guid || handlerProxy.guid || $.guid++;
709
			}
710
711
			var match = event.match( /^(\w+)\s*(.*)$/ ),
712
				eventName = match[1] + instance.eventNamespace,
713
				selector = match[2];
714
			if ( selector ) {
715
				delegateElement.delegate( selector, eventName, handlerProxy );
716
			} else {
717
				element.bind( eventName, handlerProxy );
718
			}
719
		});
720
	},
721
722
	_off: function( element, eventName ) {
723
		eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace;
724
		element.unbind( eventName ).undelegate( eventName );
725
	},
726
727
	_delay: function( handler, delay ) {
728
		function handlerProxy() {
729
			return ( typeof handler === "string" ? instance[ handler ] : handler )
730
				.apply( instance, arguments );
731
		}
732
		var instance = this;
733
		return setTimeout( handlerProxy, delay || 0 );
734
	},
735
736
	_hoverable: function( element ) {
737
		this.hoverable = this.hoverable.add( element );
738
		this._on( element, {
739
			mouseenter: function( event ) {
740
				$( event.currentTarget ).addClass( "ui-state-hover" );
741
			},
742
			mouseleave: function( event ) {
743
				$( event.currentTarget ).removeClass( "ui-state-hover" );
744
			}
745
		});
746
	},
747
748
	_focusable: function( element ) {
749
		this.focusable = this.focusable.add( element );
750
		this._on( element, {
751
			focusin: function( event ) {
752
				$( event.currentTarget ).addClass( "ui-state-focus" );
753
			},
754
			focusout: function( event ) {
755
				$( event.currentTarget ).removeClass( "ui-state-focus" );
756
			}
757
		});
758
	},
759
760
	_trigger: function( type, event, data ) {
761
		var prop, orig,
762
			callback = this.options[ type ];
763
764
		data = data || {};
765
		event = $.Event( event );
766
		event.type = ( type === this.widgetEventPrefix ?
767
			type :
768
			this.widgetEventPrefix + type ).toLowerCase();
769
		// the original event may come from any element
770
		// so we need to reset the target on the new event
771
		event.target = this.element[ 0 ];
772
773
		// copy original event properties over to the new event
774
		orig = event.originalEvent;
775
		if ( orig ) {
776
			for ( prop in orig ) {
777
				if ( !( prop in event ) ) {
778
					event[ prop ] = orig[ prop ];
779
				}
780
			}
781
		}
782
783
		this.element.trigger( event, data );
784
		return !( $.isFunction( callback ) &&
785
			callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
786
			event.isDefaultPrevented() );
787
	}
788
};
789
790
$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
791
	$.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
792
		if ( typeof options === "string" ) {
793
			options = { effect: options };
794
		}
795
		var hasOptions,
796
			effectName = !options ?
797
				method :
798
				options === true || typeof options === "number" ?
799
					defaultEffect :
800
					options.effect || defaultEffect;
801
		options = options || {};
802
		if ( typeof options === "number" ) {
803
			options = { duration: options };
804
		}
805
		hasOptions = !$.isEmptyObject( options );
806
		options.complete = callback;
807
		if ( options.delay ) {
808
			element.delay( options.delay );
809
		}
810
		if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
811
			element[ method ]( options );
812
		} else if ( effectName !== method && element[ effectName ] ) {
813
			element[ effectName ]( options.duration, options.easing, callback );
814
		} else {
815
			element.queue(function( next ) {
816
				$( this )[ method ]();
817
				if ( callback ) {
818
					callback.call( element[ 0 ] );
819
				}
820
				next();
821
			});
822
		}
823
	};
824
});
825
826
})( jQuery );
827
(function( $, undefined ) {
0 ignored issues
show
Unused Code introduced by
The parameter undefined is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
828
829
var mouseHandled = false;
830
$( document ).mouseup( function() {
831
	mouseHandled = false;
832
});
833
834
$.widget("ui.mouse", {
835
	version: "1.10.4",
836
	options: {
837
		cancel: "input,textarea,button,select,option",
838
		distance: 1,
839
		delay: 0
840
	},
841
	_mouseInit: function() {
842
		var that = this;
843
844
		this.element
845
			.bind("mousedown."+this.widgetName, function(event) {
846
				return that._mouseDown(event);
847
			})
848
			.bind("click."+this.widgetName, function(event) {
849
				if (true === $.data(event.target, that.widgetName + ".preventClickEvent")) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if true === $.data(event.ta...+ ".preventClickEvent") is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
850
					$.removeData(event.target, that.widgetName + ".preventClickEvent");
851
					event.stopImmediatePropagation();
852
					return false;
853
				}
854
			});
855
856
		this.started = false;
857
	},
858
859
	// TODO: make sure destroying one instance of mouse doesn't mess with
860
	// other instances of mouse
861
	_mouseDestroy: function() {
862
		this.element.unbind("."+this.widgetName);
863
		if ( this._mouseMoveDelegate ) {
864
			$(document)
865
				.unbind("mousemove."+this.widgetName, this._mouseMoveDelegate)
866
				.unbind("mouseup."+this.widgetName, this._mouseUpDelegate);
867
		}
868
	},
869
870
	_mouseDown: function(event) {
871
		// don't let more than one widget handle mouseStart
872
		if( mouseHandled ) { return; }
873
874
		// we may have missed mouseup (out of window)
875
		(this._mouseStarted && this._mouseUp(event));
876
877
		this._mouseDownEvent = event;
878
879
		var that = this,
880
			btnIsLeft = (event.which === 1),
881
			// event.target.nodeName works around a bug in IE 8 with
882
			// disabled inputs (#7620)
883
			elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);
884
		if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
885
			return true;
886
		}
887
888
		this.mouseDelayMet = !this.options.delay;
889
		if (!this.mouseDelayMet) {
890
			this._mouseDelayTimer = setTimeout(function() {
891
				that.mouseDelayMet = true;
892
			}, this.options.delay);
893
		}
894
895
		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
896
			this._mouseStarted = (this._mouseStart(event) !== false);
897
			if (!this._mouseStarted) {
898
				event.preventDefault();
899
				return true;
900
			}
901
		}
902
903
		// Click event may never have fired (Gecko & Opera)
904
		if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) {
905
			$.removeData(event.target, this.widgetName + ".preventClickEvent");
906
		}
907
908
		// these delegates are required to keep context
909
		this._mouseMoveDelegate = function(event) {
910
			return that._mouseMove(event);
911
		};
912
		this._mouseUpDelegate = function(event) {
913
			return that._mouseUp(event);
914
		};
915
		$(document)
916
			.bind("mousemove."+this.widgetName, this._mouseMoveDelegate)
917
			.bind("mouseup."+this.widgetName, this._mouseUpDelegate);
918
919
		event.preventDefault();
920
921
		mouseHandled = true;
922
		return true;
923
	},
924
925
	_mouseMove: function(event) {
926
		// IE mouseup check - mouseup happened when mouse was out of window
927
		if ($.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) {
928
			return this._mouseUp(event);
929
		}
930
931
		if (this._mouseStarted) {
932
			this._mouseDrag(event);
933
			return event.preventDefault();
934
		}
935
936
		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
937
			this._mouseStarted =
938
				(this._mouseStart(this._mouseDownEvent, event) !== false);
939
			(this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
940
		}
941
942
		return !this._mouseStarted;
943
	},
944
945
	_mouseUp: function(event) {
946
		$(document)
947
			.unbind("mousemove."+this.widgetName, this._mouseMoveDelegate)
948
			.unbind("mouseup."+this.widgetName, this._mouseUpDelegate);
949
950
		if (this._mouseStarted) {
951
			this._mouseStarted = false;
952
953
			if (event.target === this._mouseDownEvent.target) {
954
				$.data(event.target, this.widgetName + ".preventClickEvent", true);
955
			}
956
957
			this._mouseStop(event);
958
		}
959
960
		return false;
961
	},
962
963
	_mouseDistanceMet: function(event) {
964
		return (Math.max(
965
				Math.abs(this._mouseDownEvent.pageX - event.pageX),
966
				Math.abs(this._mouseDownEvent.pageY - event.pageY)
967
			) >= this.options.distance
968
		);
969
	},
970
971
	_mouseDelayMet: function(/* event */) {
972
		return this.mouseDelayMet;
973
	},
974
975
	// These are placeholder methods, to be overriden by extending plugin
976
	_mouseStart: function(/* event */) {},
977
	_mouseDrag: function(/* event */) {},
978
	_mouseStop: function(/* event */) {},
979
	_mouseCapture: function(/* event */) { return true; }
980
});
981
982
})(jQuery);
983
(function( $, undefined ) {
984
985
$.ui = $.ui || {};
986
987
var cachedScrollbarWidth,
988
	max = Math.max,
989
	abs = Math.abs,
990
	round = Math.round,
991
	rhorizontal = /left|center|right/,
992
	rvertical = /top|center|bottom/,
993
	roffset = /[\+\-]\d+(\.[\d]+)?%?/,
994
	rposition = /^\w+/,
995
	rpercent = /%$/,
996
	_position = $.fn.position;
997
998
function getOffsets( offsets, width, height ) {
999
	return [
1000
		parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
1001
		parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
1002
	];
1003
}
1004
1005
function parseCss( element, property ) {
1006
	return parseInt( $.css( element, property ), 10 ) || 0;
1007
}
1008
1009
function getDimensions( elem ) {
1010
	var raw = elem[0];
1011
	if ( raw.nodeType === 9 ) {
1012
		return {
1013
			width: elem.width(),
1014
			height: elem.height(),
1015
			offset: { top: 0, left: 0 }
1016
		};
1017
	}
1018
	if ( $.isWindow( raw ) ) {
1019
		return {
1020
			width: elem.width(),
1021
			height: elem.height(),
1022
			offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
1023
		};
1024
	}
1025
	if ( raw.preventDefault ) {
1026
		return {
1027
			width: 0,
1028
			height: 0,
1029
			offset: { top: raw.pageY, left: raw.pageX }
1030
		};
1031
	}
1032
	return {
1033
		width: elem.outerWidth(),
1034
		height: elem.outerHeight(),
1035
		offset: elem.offset()
1036
	};
1037
}
1038
1039
$.position = {
1040
	scrollbarWidth: function() {
1041
		if ( cachedScrollbarWidth !== undefined ) {
1042
			return cachedScrollbarWidth;
1043
		}
1044
		var w1, w2,
1045
			div = $( "<div style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>" ),
1046
			innerDiv = div.children()[0];
1047
1048
		$( "body" ).append( div );
1049
		w1 = innerDiv.offsetWidth;
1050
		div.css( "overflow", "scroll" );
1051
1052
		w2 = innerDiv.offsetWidth;
1053
1054
		if ( w1 === w2 ) {
1055
			w2 = div[0].clientWidth;
1056
		}
1057
1058
		div.remove();
1059
1060
		return (cachedScrollbarWidth = w1 - w2);
1061
	},
1062
	getScrollInfo: function( within ) {
1063
		var overflowX = within.isWindow || within.isDocument ? "" :
1064
				within.element.css( "overflow-x" ),
1065
			overflowY = within.isWindow || within.isDocument ? "" :
1066
				within.element.css( "overflow-y" ),
1067
			hasOverflowX = overflowX === "scroll" ||
1068
				( overflowX === "auto" && within.width < within.element[0].scrollWidth ),
1069
			hasOverflowY = overflowY === "scroll" ||
1070
				( overflowY === "auto" && within.height < within.element[0].scrollHeight );
1071
		return {
1072
			width: hasOverflowY ? $.position.scrollbarWidth() : 0,
1073
			height: hasOverflowX ? $.position.scrollbarWidth() : 0
1074
		};
1075
	},
1076
	getWithinInfo: function( element ) {
1077
		var withinElement = $( element || window ),
1078
			isWindow = $.isWindow( withinElement[0] ),
1079
			isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9;
1080
		return {
1081
			element: withinElement,
1082
			isWindow: isWindow,
1083
			isDocument: isDocument,
1084
			offset: withinElement.offset() || { left: 0, top: 0 },
1085
			scrollLeft: withinElement.scrollLeft(),
1086
			scrollTop: withinElement.scrollTop(),
1087
			width: isWindow ? withinElement.width() : withinElement.outerWidth(),
1088
			height: isWindow ? withinElement.height() : withinElement.outerHeight()
1089
		};
1090
	}
1091
};
1092
1093
$.fn.position = function( options ) {
1094
	if ( !options || !options.of ) {
1095
		return _position.apply( this, arguments );
1096
	}
1097
1098
	// make a copy, we don't want to modify arguments
1099
	options = $.extend( {}, options );
1100
1101
	var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
1102
		target = $( options.of ),
1103
		within = $.position.getWithinInfo( options.within ),
1104
		scrollInfo = $.position.getScrollInfo( within ),
1105
		collision = ( options.collision || "flip" ).split( " " ),
1106
		offsets = {};
1107
1108
	dimensions = getDimensions( target );
1109
	if ( target[0].preventDefault ) {
1110
		// force left top to allow flipping
1111
		options.at = "left top";
1112
	}
1113
	targetWidth = dimensions.width;
1114
	targetHeight = dimensions.height;
1115
	targetOffset = dimensions.offset;
1116
	// clone to reuse original targetOffset later
1117
	basePosition = $.extend( {}, targetOffset );
1118
1119
	// force my and at to have valid horizontal and vertical positions
1120
	// if a value is missing or invalid, it will be converted to center
1121
	$.each( [ "my", "at" ], function() {
1122
		var pos = ( options[ this ] || "" ).split( " " ),
1123
			horizontalOffset,
1124
			verticalOffset;
1125
1126
		if ( pos.length === 1) {
1127
			pos = rhorizontal.test( pos[ 0 ] ) ?
1128
				pos.concat( [ "center" ] ) :
1129
				rvertical.test( pos[ 0 ] ) ?
1130
					[ "center" ].concat( pos ) :
1131
					[ "center", "center" ];
1132
		}
1133
		pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
1134
		pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
1135
1136
		// calculate offsets
1137
		horizontalOffset = roffset.exec( pos[ 0 ] );
1138
		verticalOffset = roffset.exec( pos[ 1 ] );
1139
		offsets[ this ] = [
1140
			horizontalOffset ? horizontalOffset[ 0 ] : 0,
1141
			verticalOffset ? verticalOffset[ 0 ] : 0
1142
		];
1143
1144
		// reduce to just the positions without the offsets
1145
		options[ this ] = [
1146
			rposition.exec( pos[ 0 ] )[ 0 ],
1147
			rposition.exec( pos[ 1 ] )[ 0 ]
1148
		];
1149
	});
1150
1151
	// normalize collision option
1152
	if ( collision.length === 1 ) {
1153
		collision[ 1 ] = collision[ 0 ];
1154
	}
1155
1156
	if ( options.at[ 0 ] === "right" ) {
1157
		basePosition.left += targetWidth;
1158
	} else if ( options.at[ 0 ] === "center" ) {
1159
		basePosition.left += targetWidth / 2;
1160
	}
1161
1162
	if ( options.at[ 1 ] === "bottom" ) {
1163
		basePosition.top += targetHeight;
1164
	} else if ( options.at[ 1 ] === "center" ) {
1165
		basePosition.top += targetHeight / 2;
1166
	}
1167
1168
	atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
1169
	basePosition.left += atOffset[ 0 ];
1170
	basePosition.top += atOffset[ 1 ];
1171
1172
	return this.each(function() {
1173
		var collisionPosition, using,
1174
			elem = $( this ),
1175
			elemWidth = elem.outerWidth(),
1176
			elemHeight = elem.outerHeight(),
1177
			marginLeft = parseCss( this, "marginLeft" ),
1178
			marginTop = parseCss( this, "marginTop" ),
1179
			collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width,
1180
			collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height,
1181
			position = $.extend( {}, basePosition ),
1182
			myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
1183
1184
		if ( options.my[ 0 ] === "right" ) {
1185
			position.left -= elemWidth;
1186
		} else if ( options.my[ 0 ] === "center" ) {
1187
			position.left -= elemWidth / 2;
1188
		}
1189
1190
		if ( options.my[ 1 ] === "bottom" ) {
1191
			position.top -= elemHeight;
1192
		} else if ( options.my[ 1 ] === "center" ) {
1193
			position.top -= elemHeight / 2;
1194
		}
1195
1196
		position.left += myOffset[ 0 ];
1197
		position.top += myOffset[ 1 ];
1198
1199
		// if the browser doesn't support fractions, then round for consistent results
1200
		if ( !$.support.offsetFractions ) {
1201
			position.left = round( position.left );
1202
			position.top = round( position.top );
1203
		}
1204
1205
		collisionPosition = {
1206
			marginLeft: marginLeft,
1207
			marginTop: marginTop
1208
		};
1209
1210
		$.each( [ "left", "top" ], function( i, dir ) {
1211
			if ( $.ui.position[ collision[ i ] ] ) {
1212
				$.ui.position[ collision[ i ] ][ dir ]( position, {
1213
					targetWidth: targetWidth,
1214
					targetHeight: targetHeight,
1215
					elemWidth: elemWidth,
1216
					elemHeight: elemHeight,
1217
					collisionPosition: collisionPosition,
1218
					collisionWidth: collisionWidth,
1219
					collisionHeight: collisionHeight,
1220
					offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
1221
					my: options.my,
1222
					at: options.at,
1223
					within: within,
1224
					elem : elem
1225
				});
1226
			}
1227
		});
1228
1229
		if ( options.using ) {
1230
			// adds feedback as second argument to using callback, if present
1231
			using = function( props ) {
1232
				var left = targetOffset.left - position.left,
1233
					right = left + targetWidth - elemWidth,
1234
					top = targetOffset.top - position.top,
1235
					bottom = top + targetHeight - elemHeight,
1236
					feedback = {
1237
						target: {
1238
							element: target,
1239
							left: targetOffset.left,
1240
							top: targetOffset.top,
1241
							width: targetWidth,
1242
							height: targetHeight
1243
						},
1244
						element: {
1245
							element: elem,
1246
							left: position.left,
1247
							top: position.top,
1248
							width: elemWidth,
1249
							height: elemHeight
1250
						},
1251
						horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
1252
						vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
1253
					};
1254
				if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
1255
					feedback.horizontal = "center";
1256
				}
1257
				if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
1258
					feedback.vertical = "middle";
1259
				}
1260
				if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
1261
					feedback.important = "horizontal";
1262
				} else {
1263
					feedback.important = "vertical";
1264
				}
1265
				options.using.call( this, props, feedback );
1266
			};
1267
		}
1268
1269
		elem.offset( $.extend( position, { using: using } ) );
0 ignored issues
show
Bug introduced by
The variable using does not seem to be initialized in case options.using on line 1229 is false. Are you sure this can never be the case?
Loading history...
1270
	});
1271
};
1272
1273
$.ui.position = {
1274
	fit: {
1275
		left: function( position, data ) {
1276
			var within = data.within,
1277
				withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
1278
				outerWidth = within.width,
1279
				collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1280
				overLeft = withinOffset - collisionPosLeft,
1281
				overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
1282
				newOverRight;
1283
1284
			// element is wider than within
1285
			if ( data.collisionWidth > outerWidth ) {
1286
				// element is initially over the left side of within
1287
				if ( overLeft > 0 && overRight <= 0 ) {
1288
					newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset;
1289
					position.left += overLeft - newOverRight;
1290
				// element is initially over right side of within
1291
				} else if ( overRight > 0 && overLeft <= 0 ) {
1292
					position.left = withinOffset;
1293
				// element is initially over both left and right sides of within
1294
				} else {
1295
					if ( overLeft > overRight ) {
1296
						position.left = withinOffset + outerWidth - data.collisionWidth;
1297
					} else {
1298
						position.left = withinOffset;
1299
					}
1300
				}
1301
			// too far left -> align with left edge
1302
			} else if ( overLeft > 0 ) {
1303
				position.left += overLeft;
1304
			// too far right -> align with right edge
1305
			} else if ( overRight > 0 ) {
1306
				position.left -= overRight;
1307
			// adjust based on position and margin
1308
			} else {
1309
				position.left = max( position.left - collisionPosLeft, position.left );
1310
			}
1311
		},
1312
		top: function( position, data ) {
1313
			var within = data.within,
1314
				withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
1315
				outerHeight = data.within.height,
1316
				collisionPosTop = position.top - data.collisionPosition.marginTop,
1317
				overTop = withinOffset - collisionPosTop,
1318
				overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
1319
				newOverBottom;
1320
1321
			// element is taller than within
1322
			if ( data.collisionHeight > outerHeight ) {
1323
				// element is initially over the top of within
1324
				if ( overTop > 0 && overBottom <= 0 ) {
1325
					newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset;
1326
					position.top += overTop - newOverBottom;
1327
				// element is initially over bottom of within
1328
				} else if ( overBottom > 0 && overTop <= 0 ) {
1329
					position.top = withinOffset;
1330
				// element is initially over both top and bottom of within
1331
				} else {
1332
					if ( overTop > overBottom ) {
1333
						position.top = withinOffset + outerHeight - data.collisionHeight;
1334
					} else {
1335
						position.top = withinOffset;
1336
					}
1337
				}
1338
			// too far up -> align with top
1339
			} else if ( overTop > 0 ) {
1340
				position.top += overTop;
1341
			// too far down -> align with bottom edge
1342
			} else if ( overBottom > 0 ) {
1343
				position.top -= overBottom;
1344
			// adjust based on position and margin
1345
			} else {
1346
				position.top = max( position.top - collisionPosTop, position.top );
1347
			}
1348
		}
1349
	},
1350
	flip: {
1351
		left: function( position, data ) {
1352
			var within = data.within,
1353
				withinOffset = within.offset.left + within.scrollLeft,
1354
				outerWidth = within.width,
1355
				offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
1356
				collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1357
				overLeft = collisionPosLeft - offsetLeft,
1358
				overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
1359
				myOffset = data.my[ 0 ] === "left" ?
1360
					-data.elemWidth :
1361
					data.my[ 0 ] === "right" ?
1362
						data.elemWidth :
1363
						0,
1364
				atOffset = data.at[ 0 ] === "left" ?
1365
					data.targetWidth :
1366
					data.at[ 0 ] === "right" ?
1367
						-data.targetWidth :
1368
						0,
1369
				offset = -2 * data.offset[ 0 ],
1370
				newOverRight,
1371
				newOverLeft;
1372
1373
			if ( overLeft < 0 ) {
1374
				newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset;
1375
				if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
1376
					position.left += myOffset + atOffset + offset;
1377
				}
1378
			}
1379
			else if ( overRight > 0 ) {
1380
				newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft;
1381
				if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
1382
					position.left += myOffset + atOffset + offset;
1383
				}
1384
			}
1385
		},
1386
		top: function( position, data ) {
1387
			var within = data.within,
1388
				withinOffset = within.offset.top + within.scrollTop,
1389
				outerHeight = within.height,
1390
				offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
1391
				collisionPosTop = position.top - data.collisionPosition.marginTop,
1392
				overTop = collisionPosTop - offsetTop,
1393
				overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
1394
				top = data.my[ 1 ] === "top",
1395
				myOffset = top ?
1396
					-data.elemHeight :
1397
					data.my[ 1 ] === "bottom" ?
1398
						data.elemHeight :
1399
						0,
1400
				atOffset = data.at[ 1 ] === "top" ?
1401
					data.targetHeight :
1402
					data.at[ 1 ] === "bottom" ?
1403
						-data.targetHeight :
1404
						0,
1405
				offset = -2 * data.offset[ 1 ],
1406
				newOverTop,
1407
				newOverBottom;
1408
			if ( overTop < 0 ) {
1409
				newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset;
1410
				if ( ( position.top + myOffset + atOffset + offset) > overTop && ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) ) {
1411
					position.top += myOffset + atOffset + offset;
1412
				}
1413
			}
1414
			else if ( overBottom > 0 ) {
1415
				newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop;
1416
				if ( ( position.top + myOffset + atOffset + offset) > overBottom && ( newOverTop > 0 || abs( newOverTop ) < overBottom ) ) {
1417
					position.top += myOffset + atOffset + offset;
1418
				}
1419
			}
1420
		}
1421
	},
1422
	flipfit: {
1423
		left: function() {
1424
			$.ui.position.flip.left.apply( this, arguments );
1425
			$.ui.position.fit.left.apply( this, arguments );
1426
		},
1427
		top: function() {
1428
			$.ui.position.flip.top.apply( this, arguments );
1429
			$.ui.position.fit.top.apply( this, arguments );
1430
		}
1431
	}
1432
};
1433
1434
// fraction support test
1435
(function () {
1436
	var testElement, testElementParent, testElementStyle, offsetLeft, i,
1437
		body = document.getElementsByTagName( "body" )[ 0 ],
1438
		div = document.createElement( "div" );
1439
1440
	//Create a "fake body" for testing based on method used in jQuery.support
1441
	testElement = document.createElement( body ? "div" : "body" );
1442
	testElementStyle = {
1443
		visibility: "hidden",
1444
		width: 0,
1445
		height: 0,
1446
		border: 0,
1447
		margin: 0,
1448
		background: "none"
1449
	};
1450
	if ( body ) {
1451
		$.extend( testElementStyle, {
1452
			position: "absolute",
1453
			left: "-1000px",
1454
			top: "-1000px"
1455
		});
1456
	}
1457
	for ( i in testElementStyle ) {
1458
		testElement.style[ i ] = testElementStyle[ i ];
1459
	}
1460
	testElement.appendChild( div );
1461
	testElementParent = body || document.documentElement;
1462
	testElementParent.insertBefore( testElement, testElementParent.firstChild );
1463
1464
	div.style.cssText = "position: absolute; left: 10.7432222px;";
1465
1466
	offsetLeft = $( div ).offset().left;
1467
	$.support.offsetFractions = offsetLeft > 10 && offsetLeft < 11;
1468
1469
	testElement.innerHTML = "";
1470
	testElementParent.removeChild( testElement );
1471
})();
1472
1473
}( jQuery ) );
1474
(function( $, undefined ) {
0 ignored issues
show
Unused Code introduced by
The parameter undefined is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
1475
1476
$.widget("ui.draggable", $.ui.mouse, {
1477
	version: "1.10.4",
1478
	widgetEventPrefix: "drag",
1479
	options: {
1480
		addClasses: true,
1481
		appendTo: "parent",
1482
		axis: false,
1483
		connectToSortable: false,
1484
		containment: false,
1485
		cursor: "auto",
1486
		cursorAt: false,
1487
		grid: false,
1488
		handle: false,
1489
		helper: "original",
1490
		iframeFix: false,
1491
		opacity: false,
1492
		refreshPositions: false,
1493
		revert: false,
1494
		revertDuration: 500,
1495
		scope: "default",
1496
		scroll: true,
1497
		scrollSensitivity: 20,
1498
		scrollSpeed: 20,
1499
		snap: false,
1500
		snapMode: "both",
1501
		snapTolerance: 20,
1502
		stack: false,
1503
		zIndex: false,
1504
1505
		// callbacks
1506
		drag: null,
1507
		start: null,
1508
		stop: null
1509
	},
1510
	_create: function() {
1511
1512
		if (this.options.helper === "original" && !(/^(?:r|a|f)/).test(this.element.css("position"))) {
1513
			this.element[0].style.position = "relative";
1514
		}
1515
		if (this.options.addClasses){
1516
			this.element.addClass("ui-draggable");
1517
		}
1518
		if (this.options.disabled){
1519
			this.element.addClass("ui-draggable-disabled");
1520
		}
1521
1522
		this._mouseInit();
1523
1524
	},
1525
1526
	_destroy: function() {
1527
		this.element.removeClass( "ui-draggable ui-draggable-dragging ui-draggable-disabled" );
1528
		this._mouseDestroy();
1529
	},
1530
1531
	_mouseCapture: function(event) {
1532
1533
		var o = this.options;
1534
1535
		// among others, prevent a drag on a resizable-handle
1536
		if (this.helper || o.disabled || $(event.target).closest(".ui-resizable-handle").length > 0) {
1537
			return false;
1538
		}
1539
1540
		//Quit if we're not on a valid handle
1541
		this.handle = this._getHandle(event);
1542
		if (!this.handle) {
1543
			return false;
1544
		}
1545
1546
		$(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
1547
			$("<div class='ui-draggable-iframeFix' style='background: #fff;'></div>")
1548
			.css({
1549
				width: this.offsetWidth+"px", height: this.offsetHeight+"px",
1550
				position: "absolute", opacity: "0.001", zIndex: 1000
1551
			})
1552
			.css($(this).offset())
1553
			.appendTo("body");
1554
		});
1555
1556
		return true;
1557
1558
	},
1559
1560
	_mouseStart: function(event) {
1561
1562
		var o = this.options;
1563
1564
		//Create and append the visible helper
1565
		this.helper = this._createHelper(event);
1566
1567
		this.helper.addClass("ui-draggable-dragging");
1568
1569
		//Cache the helper size
1570
		this._cacheHelperProportions();
1571
1572
		//If ddmanager is used for droppables, set the global draggable
1573
		if($.ui.ddmanager) {
1574
			$.ui.ddmanager.current = this;
1575
		}
1576
1577
		/*
1578
		 * - Position generation -
1579
		 * This block generates everything position related - it's the core of draggables.
1580
		 */
1581
1582
		//Cache the margins of the original element
1583
		this._cacheMargins();
1584
1585
		//Store the helper's css position
1586
		this.cssPosition = this.helper.css( "position" );
1587
		this.scrollParent = this.helper.scrollParent();
1588
		this.offsetParent = this.helper.offsetParent();
1589
		this.offsetParentCssPosition = this.offsetParent.css( "position" );
1590
1591
		//The element's absolute position on the page minus margins
1592
		this.offset = this.positionAbs = this.element.offset();
1593
		this.offset = {
1594
			top: this.offset.top - this.margins.top,
1595
			left: this.offset.left - this.margins.left
1596
		};
1597
1598
		//Reset scroll cache
1599
		this.offset.scroll = false;
1600
1601
		$.extend(this.offset, {
1602
			click: { //Where the click happened, relative to the element
1603
				left: event.pageX - this.offset.left,
1604
				top: event.pageY - this.offset.top
1605
			},
1606
			parent: this._getParentOffset(),
1607
			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
1608
		});
1609
1610
		//Generate the original position
1611
		this.originalPosition = this.position = this._generatePosition(event);
1612
		this.originalPageX = event.pageX;
1613
		this.originalPageY = event.pageY;
1614
1615
		//Adjust the mouse offset relative to the helper if "cursorAt" is supplied
1616
		(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
1617
1618
		//Set a containment if given in the options
1619
		this._setContainment();
1620
1621
		//Trigger event + callbacks
1622
		if(this._trigger("start", event) === false) {
1623
			this._clear();
1624
			return false;
1625
		}
1626
1627
		//Recache the helper size
1628
		this._cacheHelperProportions();
1629
1630
		//Prepare the droppable offsets
1631
		if ($.ui.ddmanager && !o.dropBehaviour) {
1632
			$.ui.ddmanager.prepareOffsets(this, event);
1633
		}
1634
1635
1636
		this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
1637
1638
		//If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003)
1639
		if ( $.ui.ddmanager ) {
1640
			$.ui.ddmanager.dragStart(this, event);
1641
		}
1642
1643
		return true;
1644
	},
1645
1646
	_mouseDrag: function(event, noPropagation) {
1647
		// reset any necessary cached properties (see #5009)
1648
		if ( this.offsetParentCssPosition === "fixed" ) {
1649
			this.offset.parent = this._getParentOffset();
1650
		}
1651
1652
		//Compute the helpers position
1653
		this.position = this._generatePosition(event);
1654
		this.positionAbs = this._convertPositionTo("absolute");
1655
1656
		//Call plugins and callbacks and use the resulting position if something is returned
1657
		if (!noPropagation) {
1658
			var ui = this._uiHash();
1659
			if(this._trigger("drag", event, ui) === false) {
1660
				this._mouseUp({});
1661
				return false;
1662
			}
1663
			this.position = ui.position;
1664
		}
1665
1666
		if(!this.options.axis || this.options.axis !== "y") {
1667
			this.helper[0].style.left = this.position.left+"px";
1668
		}
1669
		if(!this.options.axis || this.options.axis !== "x") {
1670
			this.helper[0].style.top = this.position.top+"px";
1671
		}
1672
		if($.ui.ddmanager) {
1673
			$.ui.ddmanager.drag(this, event);
1674
		}
1675
1676
		return false;
1677
	},
1678
1679
	_mouseStop: function(event) {
1680
1681
		//If we are using droppables, inform the manager about the drop
1682
		var that = this,
1683
			dropped = false;
1684
		if ($.ui.ddmanager && !this.options.dropBehaviour) {
1685
			dropped = $.ui.ddmanager.drop(this, event);
1686
		}
1687
1688
		//if a drop comes from outside (a sortable)
1689
		if(this.dropped) {
1690
			dropped = this.dropped;
1691
			this.dropped = false;
1692
		}
1693
1694
		//if the original element is no longer in the DOM don't bother to continue (see #8269)
1695
		if ( this.options.helper === "original" && !$.contains( this.element[ 0 ].ownerDocument, this.element[ 0 ] ) ) {
1696
			return false;
1697
		}
1698
1699
		if((this.options.revert === "invalid" && !dropped) || (this.options.revert === "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
1700
			$(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
1701
				if(that._trigger("stop", event) !== false) {
1702
					that._clear();
1703
				}
1704
			});
1705
		} else {
1706
			if(this._trigger("stop", event) !== false) {
1707
				this._clear();
1708
			}
1709
		}
1710
1711
		return false;
1712
	},
1713
1714
	_mouseUp: function(event) {
1715
		//Remove frame helpers
1716
		$("div.ui-draggable-iframeFix").each(function() {
1717
			this.parentNode.removeChild(this);
1718
		});
1719
1720
		//If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003)
1721
		if( $.ui.ddmanager ) {
1722
			$.ui.ddmanager.dragStop(this, event);
1723
		}
1724
1725
		return $.ui.mouse.prototype._mouseUp.call(this, event);
1726
	},
1727
1728
	cancel: function() {
1729
1730
		if(this.helper.is(".ui-draggable-dragging")) {
1731
			this._mouseUp({});
1732
		} else {
1733
			this._clear();
1734
		}
1735
1736
		return this;
1737
1738
	},
1739
1740
	_getHandle: function(event) {
1741
		return this.options.handle ?
1742
			!!$( event.target ).closest( this.element.find( this.options.handle ) ).length :
1743
			true;
1744
	},
1745
1746
	_createHelper: function(event) {
1747
1748
		var o = this.options,
1749
			helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper === "clone" ? this.element.clone().removeAttr("id") : this.element);
1750
1751
		if(!helper.parents("body").length) {
1752
			helper.appendTo((o.appendTo === "parent" ? this.element[0].parentNode : o.appendTo));
1753
		}
1754
1755
		if(helper[0] !== this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) {
1756
			helper.css("position", "absolute");
1757
		}
1758
1759
		return helper;
1760
1761
	},
1762
1763
	_adjustOffsetFromHelper: function(obj) {
1764
		if (typeof obj === "string") {
1765
			obj = obj.split(" ");
1766
		}
1767
		if ($.isArray(obj)) {
1768
			obj = {left: +obj[0], top: +obj[1] || 0};
1769
		}
1770
		if ("left" in obj) {
1771
			this.offset.click.left = obj.left + this.margins.left;
1772
		}
1773
		if ("right" in obj) {
1774
			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
1775
		}
1776
		if ("top" in obj) {
1777
			this.offset.click.top = obj.top + this.margins.top;
1778
		}
1779
		if ("bottom" in obj) {
1780
			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
1781
		}
1782
	},
1783
1784
	_getParentOffset: function() {
1785
1786
		//Get the offsetParent and cache its position
1787
		var po = this.offsetParent.offset();
1788
1789
		// This is a special case where we need to modify a offset calculated on start, since the following happened:
1790
		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
1791
		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
1792
		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
1793
		if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
1794
			po.left += this.scrollParent.scrollLeft();
1795
			po.top += this.scrollParent.scrollTop();
1796
		}
1797
1798
		//This needs to be actually done for all browsers, since pageX/pageY includes this information
1799
		//Ugly IE fix
1800
		if((this.offsetParent[0] === document.body) ||
1801
			(this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) {
1802
			po = { top: 0, left: 0 };
1803
		}
1804
1805
		return {
1806
			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
1807
			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
1808
		};
1809
1810
	},
1811
1812
	_getRelativeOffset: function() {
1813
1814
		if(this.cssPosition === "relative") {
1815
			var p = this.element.position();
1816
			return {
1817
				top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
1818
				left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
1819
			};
1820
		} else {
1821
			return { top: 0, left: 0 };
1822
		}
1823
1824
	},
1825
1826
	_cacheMargins: function() {
1827
		this.margins = {
1828
			left: (parseInt(this.element.css("marginLeft"),10) || 0),
1829
			top: (parseInt(this.element.css("marginTop"),10) || 0),
1830
			right: (parseInt(this.element.css("marginRight"),10) || 0),
1831
			bottom: (parseInt(this.element.css("marginBottom"),10) || 0)
1832
		};
1833
	},
1834
1835
	_cacheHelperProportions: function() {
1836
		this.helperProportions = {
1837
			width: this.helper.outerWidth(),
1838
			height: this.helper.outerHeight()
1839
		};
1840
	},
1841
1842
	_setContainment: function() {
1843
1844
		var over, c, ce,
1845
			o = this.options;
1846
1847
		if ( !o.containment ) {
1848
			this.containment = null;
1849
			return;
1850
		}
1851
1852
		if ( o.containment === "window" ) {
1853
			this.containment = [
1854
				$( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
1855
				$( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top,
1856
				$( window ).scrollLeft() + $( window ).width() - this.helperProportions.width - this.margins.left,
1857
				$( window ).scrollTop() + ( $( window ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top
1858
			];
1859
			return;
1860
		}
1861
1862
		if ( o.containment === "document") {
1863
			this.containment = [
1864
				0,
1865
				0,
1866
				$( document ).width() - this.helperProportions.width - this.margins.left,
1867
				( $( document ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top
1868
			];
1869
			return;
1870
		}
1871
1872
		if ( o.containment.constructor === Array ) {
1873
			this.containment = o.containment;
1874
			return;
1875
		}
1876
1877
		if ( o.containment === "parent" ) {
1878
			o.containment = this.helper[ 0 ].parentNode;
1879
		}
1880
1881
		c = $( o.containment );
1882
		ce = c[ 0 ];
1883
1884
		if( !ce ) {
1885
			return;
1886
		}
1887
1888
		over = c.css( "overflow" ) !== "hidden";
1889
1890
		this.containment = [
1891
			( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ),
1892
			( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingTop" ), 10 ) || 0 ) ,
1893
			( over ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) - ( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) - ( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) - this.helperProportions.width - this.margins.left - this.margins.right,
1894
			( over ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) - ( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) - ( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) - this.helperProportions.height - this.margins.top  - this.margins.bottom
1895
		];
1896
		this.relative_container = c;
1897
	},
1898
1899
	_convertPositionTo: function(d, pos) {
1900
1901
		if(!pos) {
1902
			pos = this.position;
1903
		}
1904
1905
		var mod = d === "absolute" ? 1 : -1,
1906
			scroll = this.cssPosition === "absolute" && !( this.scrollParent[ 0 ] !== document && $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ? this.offsetParent : this.scrollParent;
1907
1908
		//Cache the scroll
1909
		if (!this.offset.scroll) {
1910
			this.offset.scroll = {top : scroll.scrollTop(), left : scroll.scrollLeft()};
1911
		}
1912
1913
		return {
1914
			top: (
1915
				pos.top	+																// The absolute mouse position
1916
				this.offset.relative.top * mod +										// Only for relative positioned nodes: Relative offset from element to offset parent
1917
				this.offset.parent.top * mod -										// The offsetParent's offset without borders (offset + border)
1918
				( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : this.offset.scroll.top ) * mod )
1919
			),
1920
			left: (
1921
				pos.left +																// The absolute mouse position
1922
				this.offset.relative.left * mod +										// Only for relative positioned nodes: Relative offset from element to offset parent
1923
				this.offset.parent.left * mod	-										// The offsetParent's offset without borders (offset + border)
1924
				( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : this.offset.scroll.left ) * mod )
1925
			)
1926
		};
1927
1928
	},
1929
1930
	_generatePosition: function(event) {
1931
1932
		var containment, co, top, left,
1933
			o = this.options,
1934
			scroll = this.cssPosition === "absolute" && !( this.scrollParent[ 0 ] !== document && $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ? this.offsetParent : this.scrollParent,
1935
			pageX = event.pageX,
1936
			pageY = event.pageY;
1937
1938
		//Cache the scroll
1939
		if (!this.offset.scroll) {
1940
			this.offset.scroll = {top : scroll.scrollTop(), left : scroll.scrollLeft()};
1941
		}
1942
1943
		/*
1944
		 * - Position constraining -
1945
		 * Constrain the position to a mix of grid, containment.
1946
		 */
1947
1948
		// If we are not dragging yet, we won't check for options
1949
		if ( this.originalPosition ) {
1950
			if ( this.containment ) {
1951
				if ( this.relative_container ){
1952
					co = this.relative_container.offset();
1953
					containment = [
1954
						this.containment[ 0 ] + co.left,
1955
						this.containment[ 1 ] + co.top,
1956
						this.containment[ 2 ] + co.left,
1957
						this.containment[ 3 ] + co.top
1958
					];
1959
				}
1960
				else {
1961
					containment = this.containment;
1962
				}
1963
1964
				if(event.pageX - this.offset.click.left < containment[0]) {
1965
					pageX = containment[0] + this.offset.click.left;
1966
				}
1967
				if(event.pageY - this.offset.click.top < containment[1]) {
1968
					pageY = containment[1] + this.offset.click.top;
1969
				}
1970
				if(event.pageX - this.offset.click.left > containment[2]) {
1971
					pageX = containment[2] + this.offset.click.left;
1972
				}
1973
				if(event.pageY - this.offset.click.top > containment[3]) {
1974
					pageY = containment[3] + this.offset.click.top;
1975
				}
1976
			}
1977
1978
			if(o.grid) {
1979
				//Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950)
1980
				top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY;
1981
				pageY = containment ? ((top - this.offset.click.top >= containment[1] || top - this.offset.click.top > containment[3]) ? top : ((top - this.offset.click.top >= containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
1982
1983
				left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX;
1984
				pageX = containment ? ((left - this.offset.click.left >= containment[0] || left - this.offset.click.left > containment[2]) ? left : ((left - this.offset.click.left >= containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
1985
			}
1986
1987
		}
1988
1989
		return {
1990
			top: (
1991
				pageY -																	// The absolute mouse position
1992
				this.offset.click.top	-												// Click offset (relative to the element)
1993
				this.offset.relative.top -												// Only for relative positioned nodes: Relative offset from element to offset parent
1994
				this.offset.parent.top +												// The offsetParent's offset without borders (offset + border)
1995
				( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : this.offset.scroll.top )
1996
			),
1997
			left: (
1998
				pageX -																	// The absolute mouse position
1999
				this.offset.click.left -												// Click offset (relative to the element)
2000
				this.offset.relative.left -												// Only for relative positioned nodes: Relative offset from element to offset parent
2001
				this.offset.parent.left +												// The offsetParent's offset without borders (offset + border)
2002
				( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : this.offset.scroll.left )
2003
			)
2004
		};
2005
2006
	},
2007
2008
	_clear: function() {
2009
		this.helper.removeClass("ui-draggable-dragging");
2010
		if(this.helper[0] !== this.element[0] && !this.cancelHelperRemoval) {
2011
			this.helper.remove();
2012
		}
2013
		this.helper = null;
2014
		this.cancelHelperRemoval = false;
2015
	},
2016
2017
	// From now on bulk stuff - mainly helpers
2018
2019
	_trigger: function(type, event, ui) {
2020
		ui = ui || this._uiHash();
2021
		$.ui.plugin.call(this, type, [event, ui]);
2022
		//The absolute position has to be recalculated after plugins
2023
		if(type === "drag") {
2024
			this.positionAbs = this._convertPositionTo("absolute");
2025
		}
2026
		return $.Widget.prototype._trigger.call(this, type, event, ui);
2027
	},
2028
2029
	plugins: {},
2030
2031
	_uiHash: function() {
2032
		return {
2033
			helper: this.helper,
2034
			position: this.position,
2035
			originalPosition: this.originalPosition,
2036
			offset: this.positionAbs
2037
		};
2038
	}
2039
2040
});
2041
2042
$.ui.plugin.add("draggable", "connectToSortable", {
2043
	start: function(event, ui) {
2044
2045
		var inst = $(this).data("ui-draggable"), o = inst.options,
2046
			uiSortable = $.extend({}, ui, { item: inst.element });
2047
		inst.sortables = [];
2048
		$(o.connectToSortable).each(function() {
2049
			var sortable = $.data(this, "ui-sortable");
2050
			if (sortable && !sortable.options.disabled) {
2051
				inst.sortables.push({
2052
					instance: sortable,
2053
					shouldRevert: sortable.options.revert
2054
				});
2055
				sortable.refreshPositions();	// Call the sortable's refreshPositions at drag start to refresh the containerCache since the sortable container cache is used in drag and needs to be up to date (this will ensure it's initialised as well as being kept in step with any changes that might have happened on the page).
2056
				sortable._trigger("activate", event, uiSortable);
2057
			}
2058
		});
2059
2060
	},
2061
	stop: function(event, ui) {
2062
2063
		//If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
2064
		var inst = $(this).data("ui-draggable"),
2065
			uiSortable = $.extend({}, ui, { item: inst.element });
2066
2067
		$.each(inst.sortables, function() {
2068
			if(this.instance.isOver) {
2069
2070
				this.instance.isOver = 0;
2071
2072
				inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
2073
				this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
2074
2075
				//The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: "valid/invalid"
2076
				if(this.shouldRevert) {
2077
					this.instance.options.revert = this.shouldRevert;
2078
				}
2079
2080
				//Trigger the stop of the sortable
2081
				this.instance._mouseStop(event);
2082
2083
				this.instance.options.helper = this.instance.options._helper;
2084
2085
				//If the helper has been the original item, restore properties in the sortable
2086
				if(inst.options.helper === "original") {
2087
					this.instance.currentItem.css({ top: "auto", left: "auto" });
2088
				}
2089
2090
			} else {
2091
				this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
2092
				this.instance._trigger("deactivate", event, uiSortable);
2093
			}
2094
2095
		});
2096
2097
	},
2098
	drag: function(event, ui) {
2099
2100
		var inst = $(this).data("ui-draggable"), that = this;
2101
2102
		$.each(inst.sortables, function() {
2103
2104
			var innermostIntersecting = false,
2105
				thisSortable = this;
2106
2107
			//Copy over some variables to allow calling the sortable's native _intersectsWith
2108
			this.instance.positionAbs = inst.positionAbs;
2109
			this.instance.helperProportions = inst.helperProportions;
2110
			this.instance.offset.click = inst.offset.click;
2111
2112
			if(this.instance._intersectsWith(this.instance.containerCache)) {
2113
				innermostIntersecting = true;
2114
				$.each(inst.sortables, function () {
2115
					this.instance.positionAbs = inst.positionAbs;
2116
					this.instance.helperProportions = inst.helperProportions;
2117
					this.instance.offset.click = inst.offset.click;
2118
					if (this !== thisSortable &&
2119
						this.instance._intersectsWith(this.instance.containerCache) &&
2120
						$.contains(thisSortable.instance.element[0], this.instance.element[0])
2121
					) {
2122
						innermostIntersecting = false;
2123
					}
2124
					return innermostIntersecting;
2125
				});
2126
			}
2127
2128
2129
			if(innermostIntersecting) {
2130
				//If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
2131
				if(!this.instance.isOver) {
2132
2133
					this.instance.isOver = 1;
2134
					//Now we fake the start of dragging for the sortable instance,
2135
					//by cloning the list group item, appending it to the sortable and using it as inst.currentItem
2136
					//We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
2137
					this.instance.currentItem = $(that).clone().removeAttr("id").appendTo(this.instance.element).data("ui-sortable-item", true);
2138
					this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
2139
					this.instance.options.helper = function() { return ui.helper[0]; };
2140
2141
					event.target = this.instance.currentItem[0];
2142
					this.instance._mouseCapture(event, true);
2143
					this.instance._mouseStart(event, true, true);
2144
2145
					//Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
2146
					this.instance.offset.click.top = inst.offset.click.top;
2147
					this.instance.offset.click.left = inst.offset.click.left;
2148
					this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
2149
					this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
2150
2151
					inst._trigger("toSortable", event);
2152
					inst.dropped = this.instance.element; //draggable revert needs that
2153
					//hack so receive/update callbacks work (mostly)
2154
					inst.currentItem = inst.element;
2155
					this.instance.fromOutside = inst;
2156
2157
				}
2158
2159
				//Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
2160
				if(this.instance.currentItem) {
2161
					this.instance._mouseDrag(event);
2162
				}
2163
2164
			} else {
2165
2166
				//If it doesn't intersect with the sortable, and it intersected before,
2167
				//we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
2168
				if(this.instance.isOver) {
2169
2170
					this.instance.isOver = 0;
2171
					this.instance.cancelHelperRemoval = true;
2172
2173
					//Prevent reverting on this forced stop
2174
					this.instance.options.revert = false;
2175
2176
					// The out event needs to be triggered independently
2177
					this.instance._trigger("out", event, this.instance._uiHash(this.instance));
2178
2179
					this.instance._mouseStop(event, true);
2180
					this.instance.options.helper = this.instance.options._helper;
2181
2182
					//Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
2183
					this.instance.currentItem.remove();
2184
					if(this.instance.placeholder) {
2185
						this.instance.placeholder.remove();
2186
					}
2187
2188
					inst._trigger("fromSortable", event);
2189
					inst.dropped = false; //draggable revert needs that
2190
				}
2191
2192
			}
2193
2194
		});
2195
2196
	}
2197
});
2198
2199
$.ui.plugin.add("draggable", "cursor", {
2200
	start: function() {
2201
		var t = $("body"), o = $(this).data("ui-draggable").options;
2202
		if (t.css("cursor")) {
2203
			o._cursor = t.css("cursor");
2204
		}
2205
		t.css("cursor", o.cursor);
2206
	},
2207
	stop: function() {
2208
		var o = $(this).data("ui-draggable").options;
2209
		if (o._cursor) {
2210
			$("body").css("cursor", o._cursor);
2211
		}
2212
	}
2213
});
2214
2215
$.ui.plugin.add("draggable", "opacity", {
2216
	start: function(event, ui) {
2217
		var t = $(ui.helper), o = $(this).data("ui-draggable").options;
2218
		if(t.css("opacity")) {
2219
			o._opacity = t.css("opacity");
2220
		}
2221
		t.css("opacity", o.opacity);
2222
	},
2223
	stop: function(event, ui) {
2224
		var o = $(this).data("ui-draggable").options;
2225
		if(o._opacity) {
2226
			$(ui.helper).css("opacity", o._opacity);
2227
		}
2228
	}
2229
});
2230
2231
$.ui.plugin.add("draggable", "scroll", {
2232
	start: function() {
2233
		var i = $(this).data("ui-draggable");
2234
		if(i.scrollParent[0] !== document && i.scrollParent[0].tagName !== "HTML") {
2235
			i.overflowOffset = i.scrollParent.offset();
2236
		}
2237
	},
2238
	drag: function( event ) {
2239
2240
		var i = $(this).data("ui-draggable"), o = i.options, scrolled = false;
2241
2242
		if(i.scrollParent[0] !== document && i.scrollParent[0].tagName !== "HTML") {
2243
2244
			if(!o.axis || o.axis !== "x") {
2245
				if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) {
2246
					i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
2247
				} else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity) {
2248
					i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
2249
				}
2250
			}
2251
2252
			if(!o.axis || o.axis !== "y") {
2253
				if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) {
2254
					i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
2255
				} else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity) {
2256
					i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
2257
				}
2258
			}
2259
2260
		} else {
2261
2262
			if(!o.axis || o.axis !== "x") {
2263
				if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) {
2264
					scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
2265
				} else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) {
2266
					scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
2267
				}
2268
			}
2269
2270
			if(!o.axis || o.axis !== "y") {
2271
				if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) {
2272
					scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
2273
				} else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) {
2274
					scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
2275
				}
2276
			}
2277
2278
		}
2279
2280
		if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
2281
			$.ui.ddmanager.prepareOffsets(i, event);
2282
		}
2283
2284
	}
2285
});
2286
2287
$.ui.plugin.add("draggable", "snap", {
2288
	start: function() {
2289
2290
		var i = $(this).data("ui-draggable"),
2291
			o = i.options;
2292
2293
		i.snapElements = [];
2294
2295
		$(o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap).each(function() {
2296
			var $t = $(this),
2297
				$o = $t.offset();
2298
			if(this !== i.element[0]) {
2299
				i.snapElements.push({
2300
					item: this,
2301
					width: $t.outerWidth(), height: $t.outerHeight(),
2302
					top: $o.top, left: $o.left
2303
				});
2304
			}
2305
		});
2306
2307
	},
2308
	drag: function(event, ui) {
2309
2310
		var ts, bs, ls, rs, l, r, t, b, i, first,
2311
			inst = $(this).data("ui-draggable"),
2312
			o = inst.options,
2313
			d = o.snapTolerance,
2314
			x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
2315
			y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
2316
2317
		for (i = inst.snapElements.length - 1; i >= 0; i--){
2318
2319
			l = inst.snapElements[i].left;
2320
			r = l + inst.snapElements[i].width;
2321
			t = inst.snapElements[i].top;
2322
			b = t + inst.snapElements[i].height;
2323
2324
			if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d || !$.contains( inst.snapElements[ i ].item.ownerDocument, inst.snapElements[ i ].item ) ) {
2325
				if(inst.snapElements[i].snapping) {
2326
					(inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
2327
				}
2328
				inst.snapElements[i].snapping = false;
2329
				continue;
2330
			}
2331
2332
			if(o.snapMode !== "inner") {
2333
				ts = Math.abs(t - y2) <= d;
2334
				bs = Math.abs(b - y1) <= d;
2335
				ls = Math.abs(l - x2) <= d;
2336
				rs = Math.abs(r - x1) <= d;
2337
				if(ts) {
2338
					ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
2339
				}
2340
				if(bs) {
2341
					ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
2342
				}
2343
				if(ls) {
2344
					ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
2345
				}
2346
				if(rs) {
2347
					ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
2348
				}
2349
			}
2350
2351
			first = (ts || bs || ls || rs);
2352
2353
			if(o.snapMode !== "outer") {
2354
				ts = Math.abs(t - y1) <= d;
2355
				bs = Math.abs(b - y2) <= d;
2356
				ls = Math.abs(l - x1) <= d;
2357
				rs = Math.abs(r - x2) <= d;
2358
				if(ts) {
2359
					ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
2360
				}
2361
				if(bs) {
2362
					ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
2363
				}
2364
				if(ls) {
2365
					ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
2366
				}
2367
				if(rs) {
2368
					ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
2369
				}
2370
			}
2371
2372
			if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) {
2373
				(inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
2374
			}
2375
			inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
2376
2377
		}
2378
2379
	}
2380
});
2381
2382
$.ui.plugin.add("draggable", "stack", {
2383
	start: function() {
2384
		var min,
2385
			o = this.data("ui-draggable").options,
2386
			group = $.makeArray($(o.stack)).sort(function(a,b) {
2387
				return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
2388
			});
2389
2390
		if (!group.length) { return; }
2391
2392
		min = parseInt($(group[0]).css("zIndex"), 10) || 0;
2393
		$(group).each(function(i) {
2394
			$(this).css("zIndex", min + i);
2395
		});
2396
		this.css("zIndex", (min + group.length));
2397
	}
2398
});
2399
2400
$.ui.plugin.add("draggable", "zIndex", {
2401
	start: function(event, ui) {
2402
		var t = $(ui.helper), o = $(this).data("ui-draggable").options;
2403
		if(t.css("zIndex")) {
2404
			o._zIndex = t.css("zIndex");
2405
		}
2406
		t.css("zIndex", o.zIndex);
2407
	},
2408
	stop: function(event, ui) {
2409
		var o = $(this).data("ui-draggable").options;
2410
		if(o._zIndex) {
2411
			$(ui.helper).css("zIndex", o._zIndex);
2412
		}
2413
	}
2414
});
2415
2416
})(jQuery);
2417
(function( $, undefined ) {
0 ignored issues
show
Unused Code introduced by
The parameter undefined is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
2418
2419
function isOverAxis( x, reference, size ) {
2420
	return ( x > reference ) && ( x < ( reference + size ) );
2421
}
2422
2423
$.widget("ui.droppable", {
2424
	version: "1.10.4",
2425
	widgetEventPrefix: "drop",
2426
	options: {
2427
		accept: "*",
2428
		activeClass: false,
2429
		addClasses: true,
2430
		greedy: false,
2431
		hoverClass: false,
2432
		scope: "default",
2433
		tolerance: "intersect",
2434
2435
		// callbacks
2436
		activate: null,
2437
		deactivate: null,
2438
		drop: null,
2439
		out: null,
2440
		over: null
2441
	},
2442
	_create: function() {
2443
2444
		var proportions,
2445
			o = this.options,
2446
			accept = o.accept;
2447
2448
		this.isover = false;
2449
		this.isout = true;
2450
2451
		this.accept = $.isFunction(accept) ? accept : function(d) {
2452
			return d.is(accept);
2453
		};
2454
2455
		this.proportions = function( /* valueToWrite */ ) {
2456
			if ( arguments.length ) {
2457
				// Store the droppable's proportions
2458
				proportions = arguments[ 0 ];
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
2459
			} else {
2460
				// Retrieve or derive the droppable's proportions
2461
				return proportions ?
2462
					proportions :
2463
					proportions = {
2464
						width: this.element[ 0 ].offsetWidth,
2465
						height: this.element[ 0 ].offsetHeight
2466
					};
2467
			}
2468
		};
2469
2470
		// Add the reference and positions to the manager
2471
		$.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
2472
		$.ui.ddmanager.droppables[o.scope].push(this);
2473
2474
		(o.addClasses && this.element.addClass("ui-droppable"));
2475
2476
	},
2477
2478
	_destroy: function() {
2479
		var i = 0,
2480
			drop = $.ui.ddmanager.droppables[this.options.scope];
2481
2482
		for ( ; i < drop.length; i++ ) {
2483
			if ( drop[i] === this ) {
2484
				drop.splice(i, 1);
2485
			}
2486
		}
2487
2488
		this.element.removeClass("ui-droppable ui-droppable-disabled");
2489
	},
2490
2491
	_setOption: function(key, value) {
2492
2493
		if(key === "accept") {
2494
			this.accept = $.isFunction(value) ? value : function(d) {
2495
				return d.is(value);
2496
			};
2497
		}
2498
		$.Widget.prototype._setOption.apply(this, arguments);
2499
	},
2500
2501
	_activate: function(event) {
2502
		var draggable = $.ui.ddmanager.current;
2503
		if(this.options.activeClass) {
2504
			this.element.addClass(this.options.activeClass);
2505
		}
2506
		if(draggable){
2507
			this._trigger("activate", event, this.ui(draggable));
2508
		}
2509
	},
2510
2511
	_deactivate: function(event) {
2512
		var draggable = $.ui.ddmanager.current;
2513
		if(this.options.activeClass) {
2514
			this.element.removeClass(this.options.activeClass);
2515
		}
2516
		if(draggable){
2517
			this._trigger("deactivate", event, this.ui(draggable));
2518
		}
2519
	},
2520
2521
	_over: function(event) {
2522
2523
		var draggable = $.ui.ddmanager.current;
2524
2525
		// Bail if draggable and droppable are same element
2526
		if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) {
2527
			return;
2528
		}
2529
2530
		if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
2531
			if(this.options.hoverClass) {
2532
				this.element.addClass(this.options.hoverClass);
2533
			}
2534
			this._trigger("over", event, this.ui(draggable));
2535
		}
2536
2537
	},
2538
2539
	_out: function(event) {
2540
2541
		var draggable = $.ui.ddmanager.current;
2542
2543
		// Bail if draggable and droppable are same element
2544
		if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) {
2545
			return;
2546
		}
2547
2548
		if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
2549
			if(this.options.hoverClass) {
2550
				this.element.removeClass(this.options.hoverClass);
2551
			}
2552
			this._trigger("out", event, this.ui(draggable));
2553
		}
2554
2555
	},
2556
2557
	_drop: function(event,custom) {
2558
2559
		var draggable = custom || $.ui.ddmanager.current,
2560
			childrenIntersection = false;
2561
2562
		// Bail if draggable and droppable are same element
2563
		if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) {
2564
			return false;
2565
		}
2566
2567
		this.element.find(":data(ui-droppable)").not(".ui-draggable-dragging").each(function() {
2568
			var inst = $.data(this, "ui-droppable");
2569
			if(
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if inst.options.greedy && !...inst.options.tolerance) is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
2570
				inst.options.greedy &&
2571
				!inst.options.disabled &&
2572
				inst.options.scope === draggable.options.scope &&
2573
				inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element)) &&
2574
				$.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
2575
			) { childrenIntersection = true; return false; }
2576
		});
2577
		if(childrenIntersection) {
2578
			return false;
2579
		}
2580
2581
		if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
2582
			if(this.options.activeClass) {
2583
				this.element.removeClass(this.options.activeClass);
2584
			}
2585
			if(this.options.hoverClass) {
2586
				this.element.removeClass(this.options.hoverClass);
2587
			}
2588
			this._trigger("drop", event, this.ui(draggable));
2589
			return this.element;
2590
		}
2591
2592
		return false;
2593
2594
	},
2595
2596
	ui: function(c) {
2597
		return {
2598
			draggable: (c.currentItem || c.element),
2599
			helper: c.helper,
2600
			position: c.position,
2601
			offset: c.positionAbs
2602
		};
2603
	}
2604
2605
});
2606
2607
$.ui.intersect = function(draggable, droppable, toleranceMode) {
2608
2609
	if (!droppable.offset) {
2610
		return false;
2611
	}
2612
2613
	var draggableLeft, draggableTop,
2614
		x1 = (draggable.positionAbs || draggable.position.absolute).left,
2615
		y1 = (draggable.positionAbs || draggable.position.absolute).top,
2616
		x2 = x1 + draggable.helperProportions.width,
2617
		y2 = y1 + draggable.helperProportions.height,
2618
		l = droppable.offset.left,
2619
		t = droppable.offset.top,
2620
		r = l + droppable.proportions().width,
2621
		b = t + droppable.proportions().height;
2622
2623
	switch (toleranceMode) {
2624
		case "fit":
2625
			return (l <= x1 && x2 <= r && t <= y1 && y2 <= b);
2626
		case "intersect":
2627
			return (l < x1 + (draggable.helperProportions.width / 2) && // Right Half
2628
				x2 - (draggable.helperProportions.width / 2) < r && // Left Half
2629
				t < y1 + (draggable.helperProportions.height / 2) && // Bottom Half
2630
				y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
2631
		case "pointer":
2632
			draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left);
2633
			draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top);
2634
			return isOverAxis( draggableTop, t, droppable.proportions().height ) && isOverAxis( draggableLeft, l, droppable.proportions().width );
2635
		case "touch":
2636
			return (
2637
				(y1 >= t && y1 <= b) ||	// Top edge touching
2638
				(y2 >= t && y2 <= b) ||	// Bottom edge touching
2639
				(y1 < t && y2 > b)		// Surrounded vertically
2640
			) && (
2641
				(x1 >= l && x1 <= r) ||	// Left edge touching
2642
				(x2 >= l && x2 <= r) ||	// Right edge touching
2643
				(x1 < l && x2 > r)		// Surrounded horizontally
2644
			);
2645
		default:
2646
			return false;
2647
		}
2648
2649
};
2650
2651
/*
2652
	This manager tracks offsets of draggables and droppables
2653
*/
2654
$.ui.ddmanager = {
2655
	current: null,
2656
	droppables: { "default": [] },
2657
	prepareOffsets: function(t, event) {
2658
2659
		var i, j,
2660
			m = $.ui.ddmanager.droppables[t.options.scope] || [],
2661
			type = event ? event.type : null, // workaround for #2317
2662
			list = (t.currentItem || t.element).find(":data(ui-droppable)").addBack();
2663
2664
		droppablesLoop: for (i = 0; i < m.length; i++) {
2665
2666
			//No disabled and non-accepted
2667
			if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) {
2668
				continue;
2669
			}
2670
2671
			// Filter out elements in the current dragged item
2672
			for (j=0; j < list.length; j++) {
2673
				if(list[j] === m[i].element[0]) {
2674
					m[i].proportions().height = 0;
2675
					continue droppablesLoop;
2676
				}
2677
			}
2678
2679
			m[i].visible = m[i].element.css("display") !== "none";
2680
			if(!m[i].visible) {
2681
				continue;
2682
			}
2683
2684
			//Activate the droppable if used directly from draggables
2685
			if(type === "mousedown") {
2686
				m[i]._activate.call(m[i], event);
2687
			}
2688
2689
			m[ i ].offset = m[ i ].element.offset();
2690
			m[ i ].proportions({ width: m[ i ].element[ 0 ].offsetWidth, height: m[ i ].element[ 0 ].offsetHeight });
2691
2692
		}
2693
2694
	},
2695
	drop: function(draggable, event) {
2696
2697
		var dropped = false;
2698
		// Create a copy of the droppables in case the list changes during the drop (#9116)
2699
		$.each(($.ui.ddmanager.droppables[draggable.options.scope] || []).slice(), function() {
2700
2701
			if(!this.options) {
2702
				return;
2703
			}
2704
			if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance)) {
2705
				dropped = this._drop.call(this, event) || dropped;
2706
			}
2707
2708
			if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
2709
				this.isout = true;
2710
				this.isover = false;
2711
				this._deactivate.call(this, event);
2712
			}
2713
2714
		});
2715
		return dropped;
2716
2717
	},
2718
	dragStart: function( draggable, event ) {
2719
		//Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003)
2720
		draggable.element.parentsUntil( "body" ).bind( "scroll.droppable", function() {
2721
			if( !draggable.options.refreshPositions ) {
2722
				$.ui.ddmanager.prepareOffsets( draggable, event );
2723
			}
2724
		});
2725
	},
2726
	drag: function(draggable, event) {
2727
2728
		//If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
2729
		if(draggable.options.refreshPositions) {
2730
			$.ui.ddmanager.prepareOffsets(draggable, event);
2731
		}
2732
2733
		//Run through all droppables and check their positions based on specific tolerance options
2734
		$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
2735
2736
			if(this.options.disabled || this.greedyChild || !this.visible) {
2737
				return;
2738
			}
2739
2740
			var parentInstance, scope, parent,
2741
				intersects = $.ui.intersect(draggable, this, this.options.tolerance),
2742
				c = !intersects && this.isover ? "isout" : (intersects && !this.isover ? "isover" : null);
2743
			if(!c) {
2744
				return;
2745
			}
2746
2747
			if (this.options.greedy) {
2748
				// find droppable parents with same scope
2749
				scope = this.options.scope;
2750
				parent = this.element.parents(":data(ui-droppable)").filter(function () {
2751
					return $.data(this, "ui-droppable").options.scope === scope;
2752
				});
2753
2754
				if (parent.length) {
2755
					parentInstance = $.data(parent[0], "ui-droppable");
2756
					parentInstance.greedyChild = (c === "isover");
2757
				}
2758
			}
2759
2760
			// we just moved into a greedy child
2761
			if (parentInstance && c === "isover") {
2762
				parentInstance.isover = false;
2763
				parentInstance.isout = true;
2764
				parentInstance._out.call(parentInstance, event);
2765
			}
2766
2767
			this[c] = true;
2768
			this[c === "isout" ? "isover" : "isout"] = false;
2769
			this[c === "isover" ? "_over" : "_out"].call(this, event);
2770
2771
			// we just moved out of a greedy child
2772
			if (parentInstance && c === "isout") {
2773
				parentInstance.isout = false;
2774
				parentInstance.isover = true;
2775
				parentInstance._over.call(parentInstance, event);
2776
			}
2777
		});
2778
2779
	},
2780
	dragStop: function( draggable, event ) {
2781
		draggable.element.parentsUntil( "body" ).unbind( "scroll.droppable" );
2782
		//Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003)
2783
		if( !draggable.options.refreshPositions ) {
2784
			$.ui.ddmanager.prepareOffsets( draggable, event );
2785
		}
2786
	}
2787
};
2788
2789
})(jQuery);
2790
(function( $, undefined ) {
0 ignored issues
show
Unused Code introduced by
The parameter undefined is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
2791
2792
function num(v) {
2793
	return parseInt(v, 10) || 0;
2794
}
2795
2796
function isNumber(value) {
2797
	return !isNaN(parseInt(value, 10));
2798
}
2799
2800
$.widget("ui.resizable", $.ui.mouse, {
2801
	version: "1.10.4",
2802
	widgetEventPrefix: "resize",
2803
	options: {
2804
		alsoResize: false,
2805
		animate: false,
2806
		animateDuration: "slow",
2807
		animateEasing: "swing",
2808
		aspectRatio: false,
2809
		autoHide: false,
2810
		containment: false,
2811
		ghost: false,
2812
		grid: false,
2813
		handles: "e,s,se",
2814
		helper: false,
2815
		maxHeight: null,
2816
		maxWidth: null,
2817
		minHeight: 10,
2818
		minWidth: 10,
2819
		// See #7960
2820
		zIndex: 90,
2821
2822
		// callbacks
2823
		resize: null,
2824
		start: null,
2825
		stop: null
2826
	},
2827
	_create: function() {
2828
2829
		var n, i, handle, axis, hname,
2830
			that = this,
2831
			o = this.options;
2832
		this.element.addClass("ui-resizable");
2833
2834
		$.extend(this, {
2835
			_aspectRatio: !!(o.aspectRatio),
2836
			aspectRatio: o.aspectRatio,
2837
			originalElement: this.element,
2838
			_proportionallyResizeElements: [],
2839
			_helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null
2840
		});
2841
2842
		//Wrap the element if it cannot hold child nodes
2843
		if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
2844
2845
			//Create a wrapper element and set the wrapper to the new current internal element
2846
			this.element.wrap(
2847
				$("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({
2848
					position: this.element.css("position"),
2849
					width: this.element.outerWidth(),
2850
					height: this.element.outerHeight(),
2851
					top: this.element.css("top"),
2852
					left: this.element.css("left")
2853
				})
2854
			);
2855
2856
			//Overwrite the original this.element
2857
			this.element = this.element.parent().data(
2858
				"ui-resizable", this.element.data("ui-resizable")
2859
			);
2860
2861
			this.elementIsWrapper = true;
2862
2863
			//Move margins to the wrapper
2864
			this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
2865
			this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
2866
2867
			//Prevent Safari textarea resize
2868
			this.originalResizeStyle = this.originalElement.css("resize");
2869
			this.originalElement.css("resize", "none");
2870
2871
			//Push the actual element to our proportionallyResize internal array
2872
			this._proportionallyResizeElements.push(this.originalElement.css({ position: "static", zoom: 1, display: "block" }));
2873
2874
			// avoid IE jump (hard set the margin)
2875
			this.originalElement.css({ margin: this.originalElement.css("margin") });
2876
2877
			// fix handlers offset
2878
			this._proportionallyResize();
2879
2880
		}
2881
2882
		this.handles = o.handles || (!$(".ui-resizable-handle", this.element).length ? "e,s,se" : { n: ".ui-resizable-n", e: ".ui-resizable-e", s: ".ui-resizable-s", w: ".ui-resizable-w", se: ".ui-resizable-se", sw: ".ui-resizable-sw", ne: ".ui-resizable-ne", nw: ".ui-resizable-nw" });
2883
		if(this.handles.constructor === String) {
2884
2885
			if ( this.handles === "all") {
2886
				this.handles = "n,e,s,w,se,sw,ne,nw";
2887
			}
2888
2889
			n = this.handles.split(",");
2890
			this.handles = {};
2891
2892
			for(i = 0; i < n.length; i++) {
2893
2894
				handle = $.trim(n[i]);
2895
				hname = "ui-resizable-"+handle;
2896
				axis = $("<div class='ui-resizable-handle " + hname + "'></div>");
2897
2898
				// Apply zIndex to all handles - see #7960
2899
				axis.css({ zIndex: o.zIndex });
2900
2901
				//TODO : What's going on here?
2902
				if ("se" === handle) {
2903
					axis.addClass("ui-icon ui-icon-gripsmall-diagonal-se");
2904
				}
2905
2906
				//Insert into internal handles object and append to element
2907
				this.handles[handle] = ".ui-resizable-"+handle;
2908
				this.element.append(axis);
2909
			}
2910
2911
		}
2912
2913
		this._renderAxis = function(target) {
2914
2915
			var i, axis, padPos, padWrapper;
2916
2917
			target = target || this.element;
2918
2919
			for(i in this.handles) {
2920
2921
				if(this.handles[i].constructor === String) {
2922
					this.handles[i] = $(this.handles[i], this.element).show();
2923
				}
2924
2925
				//Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
2926
				if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
2927
2928
					axis = $(this.handles[i], this.element);
2929
2930
					//Checking the correct pad and border
2931
					padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
2932
2933
					//The padding type i have to apply...
2934
					padPos = [ "padding",
2935
						/ne|nw|n/.test(i) ? "Top" :
2936
						/se|sw|s/.test(i) ? "Bottom" :
2937
						/^e$/.test(i) ? "Right" : "Left" ].join("");
2938
2939
					target.css(padPos, padWrapper);
2940
2941
					this._proportionallyResize();
2942
2943
				}
2944
2945
				//TODO: What's that good for? There's not anything to be executed left
2946
				if(!$(this.handles[i]).length) {
2947
					continue;
0 ignored issues
show
Unused Code introduced by
This continue has no effect on the loop flow and can be removed.
Loading history...
2948
				}
2949
			}
2950
		};
2951
2952
		//TODO: make renderAxis a prototype function
2953
		this._renderAxis(this.element);
2954
2955
		this._handles = $(".ui-resizable-handle", this.element)
2956
			.disableSelection();
2957
2958
		//Matching axis name
2959
		this._handles.mouseover(function() {
2960
			if (!that.resizing) {
2961
				if (this.className) {
2962
					axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
2963
				}
2964
				//Axis, default = se
2965
				that.axis = axis && axis[1] ? axis[1] : "se";
0 ignored issues
show
Bug introduced by
The variable axis seems to not be initialized for all possible execution paths.
Loading history...
2966
			}
2967
		});
2968
2969
		//If we want to auto hide the elements
2970
		if (o.autoHide) {
2971
			this._handles.hide();
2972
			$(this.element)
2973
				.addClass("ui-resizable-autohide")
2974
				.mouseenter(function() {
2975
					if (o.disabled) {
2976
						return;
2977
					}
2978
					$(this).removeClass("ui-resizable-autohide");
2979
					that._handles.show();
2980
				})
2981
				.mouseleave(function(){
2982
					if (o.disabled) {
2983
						return;
2984
					}
2985
					if (!that.resizing) {
2986
						$(this).addClass("ui-resizable-autohide");
2987
						that._handles.hide();
2988
					}
2989
				});
2990
		}
2991
2992
		//Initialize the mouse interaction
2993
		this._mouseInit();
2994
2995
	},
2996
2997
	_destroy: function() {
2998
2999
		this._mouseDestroy();
3000
3001
		var wrapper,
3002
			_destroy = function(exp) {
3003
				$(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
3004
					.removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove();
3005
			};
3006
3007
		//TODO: Unwrap at same DOM position
3008
		if (this.elementIsWrapper) {
3009
			_destroy(this.element);
3010
			wrapper = this.element;
3011
			this.originalElement.css({
3012
				position: wrapper.css("position"),
3013
				width: wrapper.outerWidth(),
3014
				height: wrapper.outerHeight(),
3015
				top: wrapper.css("top"),
3016
				left: wrapper.css("left")
3017
			}).insertAfter( wrapper );
3018
			wrapper.remove();
3019
		}
3020
3021
		this.originalElement.css("resize", this.originalResizeStyle);
3022
		_destroy(this.originalElement);
3023
3024
		return this;
3025
	},
3026
3027
	_mouseCapture: function(event) {
3028
		var i, handle,
3029
			capture = false;
3030
3031
		for (i in this.handles) {
3032
			handle = $(this.handles[i])[0];
3033
			if (handle === event.target || $.contains(handle, event.target)) {
3034
				capture = true;
3035
			}
3036
		}
3037
3038
		return !this.options.disabled && capture;
3039
	},
3040
3041
	_mouseStart: function(event) {
3042
3043
		var curleft, curtop, cursor,
3044
			o = this.options,
3045
			iniPos = this.element.position(),
3046
			el = this.element;
3047
3048
		this.resizing = true;
3049
3050
		// bugfix for http://dev.jquery.com/ticket/1749
3051
		if ( (/absolute/).test( el.css("position") ) ) {
3052
			el.css({ position: "absolute", top: el.css("top"), left: el.css("left") });
3053
		} else if (el.is(".ui-draggable")) {
3054
			el.css({ position: "absolute", top: iniPos.top, left: iniPos.left });
3055
		}
3056
3057
		this._renderProxy();
3058
3059
		curleft = num(this.helper.css("left"));
3060
		curtop = num(this.helper.css("top"));
3061
3062
		if (o.containment) {
3063
			curleft += $(o.containment).scrollLeft() || 0;
3064
			curtop += $(o.containment).scrollTop() || 0;
3065
		}
3066
3067
		//Store needed variables
3068
		this.offset = this.helper.offset();
3069
		this.position = { left: curleft, top: curtop };
3070
		this.size = this._helper ? { width: this.helper.width(), height: this.helper.height() } : { width: el.width(), height: el.height() };
3071
		this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
3072
		this.originalPosition = { left: curleft, top: curtop };
3073
		this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
3074
		this.originalMousePosition = { left: event.pageX, top: event.pageY };
3075
3076
		//Aspect Ratio
3077
		this.aspectRatio = (typeof o.aspectRatio === "number") ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
3078
3079
		cursor = $(".ui-resizable-" + this.axis).css("cursor");
3080
		$("body").css("cursor", cursor === "auto" ? this.axis + "-resize" : cursor);
3081
3082
		el.addClass("ui-resizable-resizing");
3083
		this._propagate("start", event);
3084
		return true;
3085
	},
3086
3087
	_mouseDrag: function(event) {
3088
3089
		//Increase performance, avoid regex
3090
		var data,
3091
			el = this.helper, props = {},
3092
			smp = this.originalMousePosition,
3093
			a = this.axis,
3094
			prevTop = this.position.top,
3095
			prevLeft = this.position.left,
3096
			prevWidth = this.size.width,
3097
			prevHeight = this.size.height,
3098
			dx = (event.pageX-smp.left)||0,
3099
			dy = (event.pageY-smp.top)||0,
3100
			trigger = this._change[a];
3101
3102
		if (!trigger) {
3103
			return false;
3104
		}
3105
3106
		// Calculate the attrs that will be change
3107
		data = trigger.apply(this, [event, dx, dy]);
3108
3109
		// Put this in the mouseDrag handler since the user can start pressing shift while resizing
3110
		this._updateVirtualBoundaries(event.shiftKey);
3111
		if (this._aspectRatio || event.shiftKey) {
3112
			data = this._updateRatio(data, event);
3113
		}
3114
3115
		data = this._respectSize(data, event);
3116
3117
		this._updateCache(data);
3118
3119
		// plugins callbacks need to be called first
3120
		this._propagate("resize", event);
3121
3122
		if (this.position.top !== prevTop) {
3123
			props.top = this.position.top + "px";
3124
		}
3125
		if (this.position.left !== prevLeft) {
3126
			props.left = this.position.left + "px";
3127
		}
3128
		if (this.size.width !== prevWidth) {
3129
			props.width = this.size.width + "px";
3130
		}
3131
		if (this.size.height !== prevHeight) {
3132
			props.height = this.size.height + "px";
3133
		}
3134
		el.css(props);
3135
3136
		if (!this._helper && this._proportionallyResizeElements.length) {
3137
			this._proportionallyResize();
3138
		}
3139
3140
		// Call the user callback if the element was resized
3141
		if ( ! $.isEmptyObject(props) ) {
3142
			this._trigger("resize", event, this.ui());
3143
		}
3144
3145
		return false;
3146
	},
3147
3148
	_mouseStop: function(event) {
3149
3150
		this.resizing = false;
3151
		var pr, ista, soffseth, soffsetw, s, left, top,
3152
			o = this.options, that = this;
3153
3154
		if(this._helper) {
3155
3156
			pr = this._proportionallyResizeElements;
3157
			ista = pr.length && (/textarea/i).test(pr[0].nodeName);
3158
			soffseth = ista && $.ui.hasScroll(pr[0], "left") /* TODO - jump height */ ? 0 : that.sizeDiff.height;
3159
			soffsetw = ista ? 0 : that.sizeDiff.width;
3160
3161
			s = { width: (that.helper.width()  - soffsetw), height: (that.helper.height() - soffseth) };
3162
			left = (parseInt(that.element.css("left"), 10) + (that.position.left - that.originalPosition.left)) || null;
3163
			top = (parseInt(that.element.css("top"), 10) + (that.position.top - that.originalPosition.top)) || null;
3164
3165
			if (!o.animate) {
3166
				this.element.css($.extend(s, { top: top, left: left }));
3167
			}
3168
3169
			that.helper.height(that.size.height);
3170
			that.helper.width(that.size.width);
3171
3172
			if (this._helper && !o.animate) {
3173
				this._proportionallyResize();
3174
			}
3175
		}
3176
3177
		$("body").css("cursor", "auto");
3178
3179
		this.element.removeClass("ui-resizable-resizing");
3180
3181
		this._propagate("stop", event);
3182
3183
		if (this._helper) {
3184
			this.helper.remove();
3185
		}
3186
3187
		return false;
3188
3189
	},
3190
3191
	_updateVirtualBoundaries: function(forceAspectRatio) {
3192
		var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,
3193
			o = this.options;
3194
3195
		b = {
3196
			minWidth: isNumber(o.minWidth) ? o.minWidth : 0,
3197
			maxWidth: isNumber(o.maxWidth) ? o.maxWidth : Infinity,
3198
			minHeight: isNumber(o.minHeight) ? o.minHeight : 0,
3199
			maxHeight: isNumber(o.maxHeight) ? o.maxHeight : Infinity
3200
		};
3201
3202
		if(this._aspectRatio || forceAspectRatio) {
3203
			// We want to create an enclosing box whose aspect ration is the requested one
3204
			// First, compute the "projected" size for each dimension based on the aspect ratio and other dimension
3205
			pMinWidth = b.minHeight * this.aspectRatio;
3206
			pMinHeight = b.minWidth / this.aspectRatio;
3207
			pMaxWidth = b.maxHeight * this.aspectRatio;
3208
			pMaxHeight = b.maxWidth / this.aspectRatio;
3209
3210
			if(pMinWidth > b.minWidth) {
3211
				b.minWidth = pMinWidth;
3212
			}
3213
			if(pMinHeight > b.minHeight) {
3214
				b.minHeight = pMinHeight;
3215
			}
3216
			if(pMaxWidth < b.maxWidth) {
3217
				b.maxWidth = pMaxWidth;
3218
			}
3219
			if(pMaxHeight < b.maxHeight) {
3220
				b.maxHeight = pMaxHeight;
3221
			}
3222
		}
3223
		this._vBoundaries = b;
3224
	},
3225
3226
	_updateCache: function(data) {
3227
		this.offset = this.helper.offset();
3228
		if (isNumber(data.left)) {
3229
			this.position.left = data.left;
3230
		}
3231
		if (isNumber(data.top)) {
3232
			this.position.top = data.top;
3233
		}
3234
		if (isNumber(data.height)) {
3235
			this.size.height = data.height;
3236
		}
3237
		if (isNumber(data.width)) {
3238
			this.size.width = data.width;
3239
		}
3240
	},
3241
3242
	_updateRatio: function( data ) {
3243
3244
		var cpos = this.position,
3245
			csize = this.size,
3246
			a = this.axis;
3247
3248
		if (isNumber(data.height)) {
3249
			data.width = (data.height * this.aspectRatio);
3250
		} else if (isNumber(data.width)) {
3251
			data.height = (data.width / this.aspectRatio);
3252
		}
3253
3254
		if (a === "sw") {
3255
			data.left = cpos.left + (csize.width - data.width);
3256
			data.top = null;
3257
		}
3258
		if (a === "nw") {
3259
			data.top = cpos.top + (csize.height - data.height);
3260
			data.left = cpos.left + (csize.width - data.width);
3261
		}
3262
3263
		return data;
3264
	},
3265
3266
	_respectSize: function( data ) {
3267
3268
		var o = this._vBoundaries,
3269
			a = this.axis,
3270
			ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
3271
			isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height),
3272
			dw = this.originalPosition.left + this.originalSize.width,
3273
			dh = this.position.top + this.size.height,
3274
			cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
3275
		if (isminw) {
3276
			data.width = o.minWidth;
3277
		}
3278
		if (isminh) {
3279
			data.height = o.minHeight;
3280
		}
3281
		if (ismaxw) {
3282
			data.width = o.maxWidth;
3283
		}
3284
		if (ismaxh) {
3285
			data.height = o.maxHeight;
3286
		}
3287
3288
		if (isminw && cw) {
3289
			data.left = dw - o.minWidth;
3290
		}
3291
		if (ismaxw && cw) {
3292
			data.left = dw - o.maxWidth;
3293
		}
3294
		if (isminh && ch) {
3295
			data.top = dh - o.minHeight;
3296
		}
3297
		if (ismaxh && ch) {
3298
			data.top = dh - o.maxHeight;
3299
		}
3300
3301
		// fixing jump error on top/left - bug #2330
3302
		if (!data.width && !data.height && !data.left && data.top) {
3303
			data.top = null;
3304
		} else if (!data.width && !data.height && !data.top && data.left) {
3305
			data.left = null;
3306
		}
3307
3308
		return data;
3309
	},
3310
3311
	_proportionallyResize: function() {
3312
3313
		if (!this._proportionallyResizeElements.length) {
3314
			return;
3315
		}
3316
3317
		var i, j, borders, paddings, prel,
3318
			element = this.helper || this.element;
3319
3320
		for ( i=0; i < this._proportionallyResizeElements.length; i++) {
3321
3322
			prel = this._proportionallyResizeElements[i];
3323
3324
			if (!this.borderDif) {
3325
				this.borderDif = [];
3326
				borders = [prel.css("borderTopWidth"), prel.css("borderRightWidth"), prel.css("borderBottomWidth"), prel.css("borderLeftWidth")];
3327
				paddings = [prel.css("paddingTop"), prel.css("paddingRight"), prel.css("paddingBottom"), prel.css("paddingLeft")];
3328
3329
				for ( j = 0; j < borders.length; j++ ) {
3330
					this.borderDif[ j ] = ( parseInt( borders[ j ], 10 ) || 0 ) + ( parseInt( paddings[ j ], 10 ) || 0 );
3331
				}
3332
			}
3333
3334
			prel.css({
3335
				height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
3336
				width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
3337
			});
3338
3339
		}
3340
3341
	},
3342
3343
	_renderProxy: function() {
3344
3345
		var el = this.element, o = this.options;
3346
		this.elementOffset = el.offset();
3347
3348
		if(this._helper) {
3349
3350
			this.helper = this.helper || $("<div style='overflow:hidden;'></div>");
3351
3352
			this.helper.addClass(this._helper).css({
3353
				width: this.element.outerWidth() - 1,
3354
				height: this.element.outerHeight() - 1,
3355
				position: "absolute",
3356
				left: this.elementOffset.left +"px",
3357
				top: this.elementOffset.top +"px",
3358
				zIndex: ++o.zIndex //TODO: Don't modify option
3359
			});
3360
3361
			this.helper
3362
				.appendTo("body")
3363
				.disableSelection();
3364
3365
		} else {
3366
			this.helper = this.element;
3367
		}
3368
3369
	},
3370
3371
	_change: {
3372
		e: function(event, dx) {
3373
			return { width: this.originalSize.width + dx };
3374
		},
3375
		w: function(event, dx) {
3376
			var cs = this.originalSize, sp = this.originalPosition;
3377
			return { left: sp.left + dx, width: cs.width - dx };
3378
		},
3379
		n: function(event, dx, dy) {
3380
			var cs = this.originalSize, sp = this.originalPosition;
3381
			return { top: sp.top + dy, height: cs.height - dy };
3382
		},
3383
		s: function(event, dx, dy) {
3384
			return { height: this.originalSize.height + dy };
3385
		},
3386
		se: function(event, dx, dy) {
3387
			return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
3388
		},
3389
		sw: function(event, dx, dy) {
3390
			return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
3391
		},
3392
		ne: function(event, dx, dy) {
3393
			return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
3394
		},
3395
		nw: function(event, dx, dy) {
3396
			return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
3397
		}
3398
	},
3399
3400
	_propagate: function(n, event) {
3401
		$.ui.plugin.call(this, n, [event, this.ui()]);
3402
		(n !== "resize" && this._trigger(n, event, this.ui()));
3403
	},
3404
3405
	plugins: {},
3406
3407
	ui: function() {
3408
		return {
3409
			originalElement: this.originalElement,
3410
			element: this.element,
3411
			helper: this.helper,
3412
			position: this.position,
3413
			size: this.size,
3414
			originalSize: this.originalSize,
3415
			originalPosition: this.originalPosition
3416
		};
3417
	}
3418
3419
});
3420
3421
/*
3422
 * Resizable Extensions
3423
 */
3424
3425
$.ui.plugin.add("resizable", "animate", {
3426
3427
	stop: function( event ) {
3428
		var that = $(this).data("ui-resizable"),
3429
			o = that.options,
3430
			pr = that._proportionallyResizeElements,
3431
			ista = pr.length && (/textarea/i).test(pr[0].nodeName),
3432
			soffseth = ista && $.ui.hasScroll(pr[0], "left") /* TODO - jump height */ ? 0 : that.sizeDiff.height,
3433
			soffsetw = ista ? 0 : that.sizeDiff.width,
3434
			style = { width: (that.size.width - soffsetw), height: (that.size.height - soffseth) },
3435
			left = (parseInt(that.element.css("left"), 10) + (that.position.left - that.originalPosition.left)) || null,
3436
			top = (parseInt(that.element.css("top"), 10) + (that.position.top - that.originalPosition.top)) || null;
3437
3438
		that.element.animate(
3439
			$.extend(style, top && left ? { top: top, left: left } : {}), {
3440
				duration: o.animateDuration,
3441
				easing: o.animateEasing,
3442
				step: function() {
3443
3444
					var data = {
3445
						width: parseInt(that.element.css("width"), 10),
3446
						height: parseInt(that.element.css("height"), 10),
3447
						top: parseInt(that.element.css("top"), 10),
3448
						left: parseInt(that.element.css("left"), 10)
3449
					};
3450
3451
					if (pr && pr.length) {
3452
						$(pr[0]).css({ width: data.width, height: data.height });
3453
					}
3454
3455
					// propagating resize, and updating values for each animation step
3456
					that._updateCache(data);
3457
					that._propagate("resize", event);
3458
3459
				}
3460
			}
3461
		);
3462
	}
3463
3464
});
3465
3466
$.ui.plugin.add("resizable", "containment", {
3467
3468
	start: function() {
3469
		var element, p, co, ch, cw, width, height,
3470
			that = $(this).data("ui-resizable"),
3471
			o = that.options,
3472
			el = that.element,
3473
			oc = o.containment,
3474
			ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
3475
3476
		if (!ce) {
3477
			return;
3478
		}
3479
3480
		that.containerElement = $(ce);
3481
3482
		if (/document/.test(oc) || oc === document) {
3483
			that.containerOffset = { left: 0, top: 0 };
3484
			that.containerPosition = { left: 0, top: 0 };
3485
3486
			that.parentData = {
3487
				element: $(document), left: 0, top: 0,
3488
				width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
3489
			};
3490
		}
3491
3492
		// i'm a node, so compute top, left, right, bottom
3493
		else {
3494
			element = $(ce);
3495
			p = [];
3496
			$([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
3497
3498
			that.containerOffset = element.offset();
3499
			that.containerPosition = element.position();
3500
			that.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
3501
3502
			co = that.containerOffset;
3503
			ch = that.containerSize.height;
3504
			cw = that.containerSize.width;
3505
			width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw );
3506
			height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
3507
3508
			that.parentData = {
3509
				element: ce, left: co.left, top: co.top, width: width, height: height
3510
			};
3511
		}
3512
	},
3513
3514
	resize: function( event ) {
3515
		var woset, hoset, isParent, isOffsetRelative,
3516
			that = $(this).data("ui-resizable"),
3517
			o = that.options,
3518
			co = that.containerOffset, cp = that.position,
3519
			pRatio = that._aspectRatio || event.shiftKey,
3520
			cop = { top:0, left:0 }, ce = that.containerElement;
3521
3522
		if (ce[0] !== document && (/static/).test(ce.css("position"))) {
3523
			cop = co;
3524
		}
3525
3526
		if (cp.left < (that._helper ? co.left : 0)) {
3527
			that.size.width = that.size.width + (that._helper ? (that.position.left - co.left) : (that.position.left - cop.left));
3528
			if (pRatio) {
3529
				that.size.height = that.size.width / that.aspectRatio;
3530
			}
3531
			that.position.left = o.helper ? co.left : 0;
3532
		}
3533
3534
		if (cp.top < (that._helper ? co.top : 0)) {
3535
			that.size.height = that.size.height + (that._helper ? (that.position.top - co.top) : that.position.top);
3536
			if (pRatio) {
3537
				that.size.width = that.size.height * that.aspectRatio;
3538
			}
3539
			that.position.top = that._helper ? co.top : 0;
3540
		}
3541
3542
		that.offset.left = that.parentData.left+that.position.left;
3543
		that.offset.top = that.parentData.top+that.position.top;
3544
3545
		woset = Math.abs( (that._helper ? that.offset.left - cop.left : (that.offset.left - cop.left)) + that.sizeDiff.width );
3546
		hoset = Math.abs( (that._helper ? that.offset.top - cop.top : (that.offset.top - co.top)) + that.sizeDiff.height );
3547
3548
		isParent = that.containerElement.get(0) === that.element.parent().get(0);
3549
		isOffsetRelative = /relative|absolute/.test(that.containerElement.css("position"));
3550
3551
		if ( isParent && isOffsetRelative ) {
3552
			woset -= Math.abs( that.parentData.left );
3553
		}
3554
3555
		if (woset + that.size.width >= that.parentData.width) {
3556
			that.size.width = that.parentData.width - woset;
3557
			if (pRatio) {
3558
				that.size.height = that.size.width / that.aspectRatio;
3559
			}
3560
		}
3561
3562
		if (hoset + that.size.height >= that.parentData.height) {
3563
			that.size.height = that.parentData.height - hoset;
3564
			if (pRatio) {
3565
				that.size.width = that.size.height * that.aspectRatio;
3566
			}
3567
		}
3568
	},
3569
3570
	stop: function(){
3571
		var that = $(this).data("ui-resizable"),
3572
			o = that.options,
3573
			co = that.containerOffset,
3574
			cop = that.containerPosition,
3575
			ce = that.containerElement,
3576
			helper = $(that.helper),
3577
			ho = helper.offset(),
3578
			w = helper.outerWidth() - that.sizeDiff.width,
3579
			h = helper.outerHeight() - that.sizeDiff.height;
3580
3581
		if (that._helper && !o.animate && (/relative/).test(ce.css("position"))) {
3582
			$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
3583
		}
3584
3585
		if (that._helper && !o.animate && (/static/).test(ce.css("position"))) {
3586
			$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
3587
		}
3588
3589
	}
3590
});
3591
3592
$.ui.plugin.add("resizable", "alsoResize", {
3593
3594
	start: function () {
3595
		var that = $(this).data("ui-resizable"),
3596
			o = that.options,
3597
			_store = function (exp) {
3598
				$(exp).each(function() {
3599
					var el = $(this);
3600
					el.data("ui-resizable-alsoresize", {
3601
						width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
3602
						left: parseInt(el.css("left"), 10), top: parseInt(el.css("top"), 10)
3603
					});
3604
				});
3605
			};
3606
3607
		if (typeof(o.alsoResize) === "object" && !o.alsoResize.parentNode) {
3608
			if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
3609
			else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
3610
		}else{
3611
			_store(o.alsoResize);
3612
		}
3613
	},
3614
3615
	resize: function (event, ui) {
3616
		var that = $(this).data("ui-resizable"),
3617
			o = that.options,
3618
			os = that.originalSize,
3619
			op = that.originalPosition,
3620
			delta = {
3621
				height: (that.size.height - os.height) || 0, width: (that.size.width - os.width) || 0,
3622
				top: (that.position.top - op.top) || 0, left: (that.position.left - op.left) || 0
3623
			},
3624
3625
			_alsoResize = function (exp, c) {
3626
				$(exp).each(function() {
3627
					var el = $(this), start = $(this).data("ui-resizable-alsoresize"), style = {},
3628
						css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ["width", "height"] : ["width", "height", "top", "left"];
3629
3630
					$.each(css, function (i, prop) {
3631
						var sum = (start[prop]||0) + (delta[prop]||0);
3632
						if (sum && sum >= 0) {
3633
							style[prop] = sum || null;
3634
						}
3635
					});
3636
3637
					el.css(style);
3638
				});
3639
			};
3640
3641
		if (typeof(o.alsoResize) === "object" && !o.alsoResize.nodeType) {
3642
			$.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
3643
		}else{
3644
			_alsoResize(o.alsoResize);
3645
		}
3646
	},
3647
3648
	stop: function () {
3649
		$(this).removeData("resizable-alsoresize");
3650
	}
3651
});
3652
3653
$.ui.plugin.add("resizable", "ghost", {
3654
3655
	start: function() {
3656
3657
		var that = $(this).data("ui-resizable"), o = that.options, cs = that.size;
3658
3659
		that.ghost = that.originalElement.clone();
3660
		that.ghost
3661
			.css({ opacity: 0.25, display: "block", position: "relative", height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
3662
			.addClass("ui-resizable-ghost")
3663
			.addClass(typeof o.ghost === "string" ? o.ghost : "");
3664
3665
		that.ghost.appendTo(that.helper);
3666
3667
	},
3668
3669
	resize: function(){
3670
		var that = $(this).data("ui-resizable");
3671
		if (that.ghost) {
3672
			that.ghost.css({ position: "relative", height: that.size.height, width: that.size.width });
3673
		}
3674
	},
3675
3676
	stop: function() {
3677
		var that = $(this).data("ui-resizable");
3678
		if (that.ghost && that.helper) {
3679
			that.helper.get(0).removeChild(that.ghost.get(0));
3680
		}
3681
	}
3682
3683
});
3684
3685
$.ui.plugin.add("resizable", "grid", {
3686
3687
	resize: function() {
3688
		var that = $(this).data("ui-resizable"),
3689
			o = that.options,
3690
			cs = that.size,
3691
			os = that.originalSize,
3692
			op = that.originalPosition,
3693
			a = that.axis,
3694
			grid = typeof o.grid === "number" ? [o.grid, o.grid] : o.grid,
3695
			gridX = (grid[0]||1),
3696
			gridY = (grid[1]||1),
3697
			ox = Math.round((cs.width - os.width) / gridX) * gridX,
3698
			oy = Math.round((cs.height - os.height) / gridY) * gridY,
3699
			newWidth = os.width + ox,
3700
			newHeight = os.height + oy,
3701
			isMaxWidth = o.maxWidth && (o.maxWidth < newWidth),
3702
			isMaxHeight = o.maxHeight && (o.maxHeight < newHeight),
3703
			isMinWidth = o.minWidth && (o.minWidth > newWidth),
3704
			isMinHeight = o.minHeight && (o.minHeight > newHeight);
3705
3706
		o.grid = grid;
3707
3708
		if (isMinWidth) {
3709
			newWidth = newWidth + gridX;
3710
		}
3711
		if (isMinHeight) {
3712
			newHeight = newHeight + gridY;
3713
		}
3714
		if (isMaxWidth) {
3715
			newWidth = newWidth - gridX;
3716
		}
3717
		if (isMaxHeight) {
3718
			newHeight = newHeight - gridY;
3719
		}
3720
3721
		if (/^(se|s|e)$/.test(a)) {
3722
			that.size.width = newWidth;
3723
			that.size.height = newHeight;
3724
		} else if (/^(ne)$/.test(a)) {
3725
			that.size.width = newWidth;
3726
			that.size.height = newHeight;
3727
			that.position.top = op.top - oy;
3728
		} else if (/^(sw)$/.test(a)) {
3729
			that.size.width = newWidth;
3730
			that.size.height = newHeight;
3731
			that.position.left = op.left - ox;
3732
		} else {
3733
			if ( newHeight - gridY > 0 ) {
3734
				that.size.height = newHeight;
3735
				that.position.top = op.top - oy;
3736
			} else {
3737
				that.size.height = gridY;
3738
				that.position.top = op.top + os.height - gridY;
3739
			}
3740
			if ( newWidth - gridX > 0 ) {
3741
				that.size.width = newWidth;
3742
				that.position.left = op.left - ox;
3743
			} else {
3744
				that.size.width = gridX;
3745
				that.position.left = op.left + os.width - gridX;
3746
			}
3747
		}
3748
	}
3749
3750
});
3751
3752
})(jQuery);
3753
(function( $, undefined ) {
0 ignored issues
show
Unused Code introduced by
The parameter undefined is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
3754
3755
$.widget("ui.selectable", $.ui.mouse, {
3756
	version: "1.10.4",
3757
	options: {
3758
		appendTo: "body",
3759
		autoRefresh: true,
3760
		distance: 0,
3761
		filter: "*",
3762
		tolerance: "touch",
3763
3764
		// callbacks
3765
		selected: null,
3766
		selecting: null,
3767
		start: null,
3768
		stop: null,
3769
		unselected: null,
3770
		unselecting: null
3771
	},
3772
	_create: function() {
3773
		var selectees,
3774
			that = this;
3775
3776
		this.element.addClass("ui-selectable");
3777
3778
		this.dragged = false;
3779
3780
		// cache selectee children based on filter
3781
		this.refresh = function() {
3782
			selectees = $(that.options.filter, that.element[0]);
3783
			selectees.addClass("ui-selectee");
3784
			selectees.each(function() {
3785
				var $this = $(this),
3786
					pos = $this.offset();
3787
				$.data(this, "selectable-item", {
3788
					element: this,
3789
					$element: $this,
3790
					left: pos.left,
3791
					top: pos.top,
3792
					right: pos.left + $this.outerWidth(),
3793
					bottom: pos.top + $this.outerHeight(),
3794
					startselected: false,
3795
					selected: $this.hasClass("ui-selected"),
3796
					selecting: $this.hasClass("ui-selecting"),
3797
					unselecting: $this.hasClass("ui-unselecting")
3798
				});
3799
			});
3800
		};
3801
		this.refresh();
3802
3803
		this.selectees = selectees.addClass("ui-selectee");
3804
3805
		this._mouseInit();
3806
3807
		this.helper = $("<div class='ui-selectable-helper'></div>");
3808
	},
3809
3810
	_destroy: function() {
3811
		this.selectees
3812
			.removeClass("ui-selectee")
3813
			.removeData("selectable-item");
3814
		this.element
3815
			.removeClass("ui-selectable ui-selectable-disabled");
3816
		this._mouseDestroy();
3817
	},
3818
3819
	_mouseStart: function(event) {
3820
		var that = this,
3821
			options = this.options;
3822
3823
		this.opos = [event.pageX, event.pageY];
3824
3825
		if (this.options.disabled) {
3826
			return;
3827
		}
3828
3829
		this.selectees = $(options.filter, this.element[0]);
3830
3831
		this._trigger("start", event);
3832
3833
		$(options.appendTo).append(this.helper);
3834
		// position helper (lasso)
3835
		this.helper.css({
3836
			"left": event.pageX,
3837
			"top": event.pageY,
3838
			"width": 0,
3839
			"height": 0
3840
		});
3841
3842
		if (options.autoRefresh) {
3843
			this.refresh();
3844
		}
3845
3846
		this.selectees.filter(".ui-selected").each(function() {
3847
			var selectee = $.data(this, "selectable-item");
3848
			selectee.startselected = true;
3849
			if (!event.metaKey && !event.ctrlKey) {
3850
				selectee.$element.removeClass("ui-selected");
3851
				selectee.selected = false;
3852
				selectee.$element.addClass("ui-unselecting");
3853
				selectee.unselecting = true;
3854
				// selectable UNSELECTING callback
3855
				that._trigger("unselecting", event, {
3856
					unselecting: selectee.element
3857
				});
3858
			}
3859
		});
3860
3861
		$(event.target).parents().addBack().each(function() {
3862
			var doSelect,
3863
				selectee = $.data(this, "selectable-item");
3864
			if (selectee) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if selectee is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
3865
				doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass("ui-selected");
3866
				selectee.$element
3867
					.removeClass(doSelect ? "ui-unselecting" : "ui-selected")
3868
					.addClass(doSelect ? "ui-selecting" : "ui-unselecting");
3869
				selectee.unselecting = !doSelect;
3870
				selectee.selecting = doSelect;
3871
				selectee.selected = doSelect;
3872
				// selectable (UN)SELECTING callback
3873
				if (doSelect) {
3874
					that._trigger("selecting", event, {
3875
						selecting: selectee.element
3876
					});
3877
				} else {
3878
					that._trigger("unselecting", event, {
3879
						unselecting: selectee.element
3880
					});
3881
				}
3882
				return false;
3883
			}
3884
		});
3885
3886
	},
3887
3888
	_mouseDrag: function(event) {
3889
3890
		this.dragged = true;
3891
3892
		if (this.options.disabled) {
3893
			return;
3894
		}
3895
3896
		var tmp,
3897
			that = this,
3898
			options = this.options,
3899
			x1 = this.opos[0],
3900
			y1 = this.opos[1],
3901
			x2 = event.pageX,
3902
			y2 = event.pageY;
3903
3904
		if (x1 > x2) { tmp = x2; x2 = x1; x1 = tmp; }
3905
		if (y1 > y2) { tmp = y2; y2 = y1; y1 = tmp; }
3906
		this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});
3907
3908
		this.selectees.each(function() {
3909
			var selectee = $.data(this, "selectable-item"),
3910
				hit = false;
3911
3912
			//prevent helper from being selected if appendTo: selectable
3913
			if (!selectee || selectee.element === that.element[0]) {
3914
				return;
3915
			}
3916
3917
			if (options.tolerance === "touch") {
3918
				hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
3919
			} else if (options.tolerance === "fit") {
3920
				hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
3921
			}
3922
3923
			if (hit) {
3924
				// SELECT
3925
				if (selectee.selected) {
3926
					selectee.$element.removeClass("ui-selected");
3927
					selectee.selected = false;
3928
				}
3929
				if (selectee.unselecting) {
3930
					selectee.$element.removeClass("ui-unselecting");
3931
					selectee.unselecting = false;
3932
				}
3933
				if (!selectee.selecting) {
3934
					selectee.$element.addClass("ui-selecting");
3935
					selectee.selecting = true;
3936
					// selectable SELECTING callback
3937
					that._trigger("selecting", event, {
3938
						selecting: selectee.element
3939
					});
3940
				}
3941
			} else {
3942
				// UNSELECT
3943
				if (selectee.selecting) {
3944
					if ((event.metaKey || event.ctrlKey) && selectee.startselected) {
3945
						selectee.$element.removeClass("ui-selecting");
3946
						selectee.selecting = false;
3947
						selectee.$element.addClass("ui-selected");
3948
						selectee.selected = true;
3949
					} else {
3950
						selectee.$element.removeClass("ui-selecting");
3951
						selectee.selecting = false;
3952
						if (selectee.startselected) {
3953
							selectee.$element.addClass("ui-unselecting");
3954
							selectee.unselecting = true;
3955
						}
3956
						// selectable UNSELECTING callback
3957
						that._trigger("unselecting", event, {
3958
							unselecting: selectee.element
3959
						});
3960
					}
3961
				}
3962
				if (selectee.selected) {
3963
					if (!event.metaKey && !event.ctrlKey && !selectee.startselected) {
3964
						selectee.$element.removeClass("ui-selected");
3965
						selectee.selected = false;
3966
3967
						selectee.$element.addClass("ui-unselecting");
3968
						selectee.unselecting = true;
3969
						// selectable UNSELECTING callback
3970
						that._trigger("unselecting", event, {
3971
							unselecting: selectee.element
3972
						});
3973
					}
3974
				}
3975
			}
3976
		});
3977
3978
		return false;
3979
	},
3980
3981
	_mouseStop: function(event) {
3982
		var that = this;
3983
3984
		this.dragged = false;
3985
3986
		$(".ui-unselecting", this.element[0]).each(function() {
3987
			var selectee = $.data(this, "selectable-item");
3988
			selectee.$element.removeClass("ui-unselecting");
3989
			selectee.unselecting = false;
3990
			selectee.startselected = false;
3991
			that._trigger("unselected", event, {
3992
				unselected: selectee.element
3993
			});
3994
		});
3995
		$(".ui-selecting", this.element[0]).each(function() {
3996
			var selectee = $.data(this, "selectable-item");
3997
			selectee.$element.removeClass("ui-selecting").addClass("ui-selected");
3998
			selectee.selecting = false;
3999
			selectee.selected = true;
4000
			selectee.startselected = true;
4001
			that._trigger("selected", event, {
4002
				selected: selectee.element
4003
			});
4004
		});
4005
		this._trigger("stop", event);
4006
4007
		this.helper.remove();
4008
4009
		return false;
4010
	}
4011
4012
});
4013
4014
})(jQuery);
4015
(function( $, undefined ) {
0 ignored issues
show
Unused Code introduced by
The parameter undefined is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
4016
4017
function isOverAxis( x, reference, size ) {
4018
	return ( x > reference ) && ( x < ( reference + size ) );
4019
}
4020
4021
function isFloating(item) {
4022
	return (/left|right/).test(item.css("float")) || (/inline|table-cell/).test(item.css("display"));
4023
}
4024
4025
$.widget("ui.sortable", $.ui.mouse, {
4026
	version: "1.10.4",
4027
	widgetEventPrefix: "sort",
4028
	ready: false,
4029
	options: {
4030
		appendTo: "parent",
4031
		axis: false,
4032
		connectWith: false,
4033
		containment: false,
4034
		cursor: "auto",
4035
		cursorAt: false,
4036
		dropOnEmpty: true,
4037
		forcePlaceholderSize: false,
4038
		forceHelperSize: false,
4039
		grid: false,
4040
		handle: false,
4041
		helper: "original",
4042
		items: "> *",
4043
		opacity: false,
4044
		placeholder: false,
4045
		revert: false,
4046
		scroll: true,
4047
		scrollSensitivity: 20,
4048
		scrollSpeed: 20,
4049
		scope: "default",
4050
		tolerance: "intersect",
4051
		zIndex: 1000,
4052
4053
		// callbacks
4054
		activate: null,
4055
		beforeStop: null,
4056
		change: null,
4057
		deactivate: null,
4058
		out: null,
4059
		over: null,
4060
		receive: null,
4061
		remove: null,
4062
		sort: null,
4063
		start: null,
4064
		stop: null,
4065
		update: null
4066
	},
4067
	_create: function() {
4068
4069
		var o = this.options;
4070
		this.containerCache = {};
4071
		this.element.addClass("ui-sortable");
4072
4073
		//Get the items
4074
		this.refresh();
4075
4076
		//Let's determine if the items are being displayed horizontally
4077
		this.floating = this.items.length ? o.axis === "x" || isFloating(this.items[0].item) : false;
4078
4079
		//Let's determine the parent's offset
4080
		this.offset = this.element.offset();
4081
4082
		//Initialize mouse events for interaction
4083
		this._mouseInit();
4084
4085
		//We're ready to go
4086
		this.ready = true;
4087
4088
	},
4089
4090
	_destroy: function() {
4091
		this.element
4092
			.removeClass("ui-sortable ui-sortable-disabled");
4093
		this._mouseDestroy();
4094
4095
		for ( var i = this.items.length - 1; i >= 0; i-- ) {
4096
			this.items[i].item.removeData(this.widgetName + "-item");
4097
		}
4098
4099
		return this;
4100
	},
4101
4102
	_setOption: function(key, value){
4103
		if ( key === "disabled" ) {
4104
			this.options[ key ] = value;
4105
4106
			this.widget().toggleClass( "ui-sortable-disabled", !!value );
4107
		} else {
4108
			// Don't call widget base _setOption for disable as it adds ui-state-disabled class
4109
			$.Widget.prototype._setOption.apply(this, arguments);
4110
		}
4111
	},
4112
4113
	_mouseCapture: function(event, overrideHandle) {
4114
		var currentItem = null,
4115
			validHandle = false,
4116
			that = this;
4117
4118
		if (this.reverting) {
4119
			return false;
4120
		}
4121
4122
		if(this.options.disabled || this.options.type === "static") {
4123
			return false;
4124
		}
4125
4126
		//We have to refresh the items data once first
4127
		this._refreshItems(event);
4128
4129
		//Find out if the clicked node (or one of its parents) is a actual item in this.items
4130
		$(event.target).parents().each(function() {
4131
			if($.data(this, that.widgetName + "-item") === that) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if $.data(this, that.widgetName + "-item") === that is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
4132
				currentItem = $(this);
4133
				return false;
4134
			}
4135
		});
4136
		if($.data(event.target, that.widgetName + "-item") === that) {
4137
			currentItem = $(event.target);
4138
		}
4139
4140
		if(!currentItem) {
4141
			return false;
4142
		}
4143
		if(this.options.handle && !overrideHandle) {
4144
			$(this.options.handle, currentItem).find("*").addBack().each(function() {
4145
				if(this === event.target) {
4146
					validHandle = true;
4147
				}
4148
			});
4149
			if(!validHandle) {
4150
				return false;
4151
			}
4152
		}
4153
4154
		this.currentItem = currentItem;
4155
		this._removeCurrentsFromItems();
4156
		return true;
4157
4158
	},
4159
4160
	_mouseStart: function(event, overrideHandle, noActivation) {
4161
4162
		var i, body,
4163
			o = this.options;
4164
4165
		this.currentContainer = this;
4166
4167
		//We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
4168
		this.refreshPositions();
4169
4170
		//Create and append the visible helper
4171
		this.helper = this._createHelper(event);
4172
4173
		//Cache the helper size
4174
		this._cacheHelperProportions();
4175
4176
		/*
4177
		 * - Position generation -
4178
		 * This block generates everything position related - it's the core of draggables.
4179
		 */
4180
4181
		//Cache the margins of the original element
4182
		this._cacheMargins();
4183
4184
		//Get the next scrolling parent
4185
		this.scrollParent = this.helper.scrollParent();
4186
4187
		//The element's absolute position on the page minus margins
4188
		this.offset = this.currentItem.offset();
4189
		this.offset = {
4190
			top: this.offset.top - this.margins.top,
4191
			left: this.offset.left - this.margins.left
4192
		};
4193
4194
		$.extend(this.offset, {
4195
			click: { //Where the click happened, relative to the element
4196
				left: event.pageX - this.offset.left,
4197
				top: event.pageY - this.offset.top
4198
			},
4199
			parent: this._getParentOffset(),
4200
			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
4201
		});
4202
4203
		// Only after we got the offset, we can change the helper's position to absolute
4204
		// TODO: Still need to figure out a way to make relative sorting possible
4205
		this.helper.css("position", "absolute");
4206
		this.cssPosition = this.helper.css("position");
4207
4208
		//Generate the original position
4209
		this.originalPosition = this._generatePosition(event);
4210
		this.originalPageX = event.pageX;
4211
		this.originalPageY = event.pageY;
4212
4213
		//Adjust the mouse offset relative to the helper if "cursorAt" is supplied
4214
		(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
4215
4216
		//Cache the former DOM position
4217
		this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
4218
4219
		//If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way
4220
		if(this.helper[0] !== this.currentItem[0]) {
4221
			this.currentItem.hide();
4222
		}
4223
4224
		//Create the placeholder
4225
		this._createPlaceholder();
4226
4227
		//Set a containment if given in the options
4228
		if(o.containment) {
4229
			this._setContainment();
4230
		}
4231
4232
		if( o.cursor && o.cursor !== "auto" ) { // cursor option
4233
			body = this.document.find( "body" );
4234
4235
			// support: IE
4236
			this.storedCursor = body.css( "cursor" );
4237
			body.css( "cursor", o.cursor );
4238
4239
			this.storedStylesheet = $( "<style>*{ cursor: "+o.cursor+" !important; }</style>" ).appendTo( body );
4240
		}
4241
4242
		if(o.opacity) { // opacity option
4243
			if (this.helper.css("opacity")) {
4244
				this._storedOpacity = this.helper.css("opacity");
4245
			}
4246
			this.helper.css("opacity", o.opacity);
4247
		}
4248
4249
		if(o.zIndex) { // zIndex option
4250
			if (this.helper.css("zIndex")) {
4251
				this._storedZIndex = this.helper.css("zIndex");
4252
			}
4253
			this.helper.css("zIndex", o.zIndex);
4254
		}
4255
4256
		//Prepare scrolling
4257
		if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") {
4258
			this.overflowOffset = this.scrollParent.offset();
4259
		}
4260
4261
		//Call callbacks
4262
		this._trigger("start", event, this._uiHash());
4263
4264
		//Recache the helper size
4265
		if(!this._preserveHelperProportions) {
4266
			this._cacheHelperProportions();
4267
		}
4268
4269
4270
		//Post "activate" events to possible containers
4271
		if( !noActivation ) {
4272
			for ( i = this.containers.length - 1; i >= 0; i-- ) {
4273
				this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) );
4274
			}
4275
		}
4276
4277
		//Prepare possible droppables
4278
		if($.ui.ddmanager) {
4279
			$.ui.ddmanager.current = this;
4280
		}
4281
4282
		if ($.ui.ddmanager && !o.dropBehaviour) {
4283
			$.ui.ddmanager.prepareOffsets(this, event);
4284
		}
4285
4286
		this.dragging = true;
4287
4288
		this.helper.addClass("ui-sortable-helper");
4289
		this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
4290
		return true;
4291
4292
	},
4293
4294
	_mouseDrag: function(event) {
4295
		var i, item, itemElement, intersection,
4296
			o = this.options,
4297
			scrolled = false;
4298
4299
		//Compute the helpers position
4300
		this.position = this._generatePosition(event);
4301
		this.positionAbs = this._convertPositionTo("absolute");
4302
4303
		if (!this.lastPositionAbs) {
4304
			this.lastPositionAbs = this.positionAbs;
4305
		}
4306
4307
		//Do scrolling
4308
		if(this.options.scroll) {
4309
			if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") {
4310
4311
				if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) {
4312
					this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
4313
				} else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) {
4314
					this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
4315
				}
4316
4317
				if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) {
4318
					this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
4319
				} else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) {
4320
					this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
4321
				}
4322
4323
			} else {
4324
4325
				if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) {
4326
					scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
4327
				} else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) {
4328
					scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
4329
				}
4330
4331
				if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) {
4332
					scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
4333
				} else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) {
4334
					scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
4335
				}
4336
4337
			}
4338
4339
			if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
4340
				$.ui.ddmanager.prepareOffsets(this, event);
4341
			}
4342
		}
4343
4344
		//Regenerate the absolute position used for position checks
4345
		this.positionAbs = this._convertPositionTo("absolute");
4346
4347
		//Set the helper position
4348
		if(!this.options.axis || this.options.axis !== "y") {
4349
			this.helper[0].style.left = this.position.left+"px";
4350
		}
4351
		if(!this.options.axis || this.options.axis !== "x") {
4352
			this.helper[0].style.top = this.position.top+"px";
4353
		}
4354
4355
		//Rearrange
4356
		for (i = this.items.length - 1; i >= 0; i--) {
4357
4358
			//Cache variables and intersection, continue if no intersection
4359
			item = this.items[i];
4360
			itemElement = item.item[0];
4361
			intersection = this._intersectsWithPointer(item);
4362
			if (!intersection) {
4363
				continue;
4364
			}
4365
4366
			// Only put the placeholder inside the current Container, skip all
4367
			// items from other containers. This works because when moving
4368
			// an item from one container to another the
4369
			// currentContainer is switched before the placeholder is moved.
4370
			//
4371
			// Without this, moving items in "sub-sortables" can cause
4372
			// the placeholder to jitter beetween the outer and inner container.
4373
			if (item.instance !== this.currentContainer) {
4374
				continue;
4375
			}
4376
4377
			// cannot intersect with itself
4378
			// no useless actions that have been done before
4379
			// no action if the item moved is the parent of the item checked
4380
			if (itemElement !== this.currentItem[0] &&
4381
				this.placeholder[intersection === 1 ? "next" : "prev"]()[0] !== itemElement &&
4382
				!$.contains(this.placeholder[0], itemElement) &&
4383
				(this.options.type === "semi-dynamic" ? !$.contains(this.element[0], itemElement) : true)
4384
			) {
4385
4386
				this.direction = intersection === 1 ? "down" : "up";
4387
4388
				if (this.options.tolerance === "pointer" || this._intersectsWithSides(item)) {
4389
					this._rearrange(event, item);
4390
				} else {
4391
					break;
4392
				}
4393
4394
				this._trigger("change", event, this._uiHash());
4395
				break;
4396
			}
4397
		}
4398
4399
		//Post events to containers
4400
		this._contactContainers(event);
4401
4402
		//Interconnect with droppables
4403
		if($.ui.ddmanager) {
4404
			$.ui.ddmanager.drag(this, event);
4405
		}
4406
4407
		//Call callbacks
4408
		this._trigger("sort", event, this._uiHash());
4409
4410
		this.lastPositionAbs = this.positionAbs;
4411
		return false;
4412
4413
	},
4414
4415
	_mouseStop: function(event, noPropagation) {
4416
4417
		if(!event) {
4418
			return;
4419
		}
4420
4421
		//If we are using droppables, inform the manager about the drop
4422
		if ($.ui.ddmanager && !this.options.dropBehaviour) {
4423
			$.ui.ddmanager.drop(this, event);
4424
		}
4425
4426
		if(this.options.revert) {
4427
			var that = this,
4428
				cur = this.placeholder.offset(),
4429
				axis = this.options.axis,
4430
				animation = {};
4431
4432
			if ( !axis || axis === "x" ) {
4433
				animation.left = cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollLeft);
4434
			}
4435
			if ( !axis || axis === "y" ) {
4436
				animation.top = cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollTop);
4437
			}
4438
			this.reverting = true;
4439
			$(this.helper).animate( animation, parseInt(this.options.revert, 10) || 500, function() {
4440
				that._clear(event);
4441
			});
4442
		} else {
4443
			this._clear(event, noPropagation);
4444
		}
4445
4446
		return false;
4447
4448
	},
4449
4450
	cancel: function() {
4451
4452
		if(this.dragging) {
4453
4454
			this._mouseUp({ target: null });
4455
4456
			if(this.options.helper === "original") {
4457
				this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
4458
			} else {
4459
				this.currentItem.show();
4460
			}
4461
4462
			//Post deactivating events to containers
4463
			for (var i = this.containers.length - 1; i >= 0; i--){
4464
				this.containers[i]._trigger("deactivate", null, this._uiHash(this));
4465
				if(this.containers[i].containerCache.over) {
4466
					this.containers[i]._trigger("out", null, this._uiHash(this));
4467
					this.containers[i].containerCache.over = 0;
4468
				}
4469
			}
4470
4471
		}
4472
4473
		if (this.placeholder) {
4474
			//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
4475
			if(this.placeholder[0].parentNode) {
4476
				this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
4477
			}
4478
			if(this.options.helper !== "original" && this.helper && this.helper[0].parentNode) {
4479
				this.helper.remove();
4480
			}
4481
4482
			$.extend(this, {
4483
				helper: null,
4484
				dragging: false,
4485
				reverting: false,
4486
				_noFinalSort: null
4487
			});
4488
4489
			if(this.domPosition.prev) {
4490
				$(this.domPosition.prev).after(this.currentItem);
4491
			} else {
4492
				$(this.domPosition.parent).prepend(this.currentItem);
4493
			}
4494
		}
4495
4496
		return this;
4497
4498
	},
4499
4500
	serialize: function(o) {
4501
4502
		var items = this._getItemsAsjQuery(o && o.connected),
4503
			str = [];
4504
		o = o || {};
4505
4506
		$(items).each(function() {
4507
			var res = ($(o.item || this).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[\-=_](.+)/));
4508
			if (res) {
4509
				str.push((o.key || res[1]+"[]")+"="+(o.key && o.expression ? res[1] : res[2]));
4510
			}
4511
		});
4512
4513
		if(!str.length && o.key) {
4514
			str.push(o.key + "=");
4515
		}
4516
4517
		return str.join("&");
4518
4519
	},
4520
4521
	toArray: function(o) {
4522
4523
		var items = this._getItemsAsjQuery(o && o.connected),
4524
			ret = [];
4525
4526
		o = o || {};
4527
4528
		items.each(function() { ret.push($(o.item || this).attr(o.attribute || "id") || ""); });
4529
		return ret;
4530
4531
	},
4532
4533
	/* Be careful with the following core functions */
4534
	_intersectsWith: function(item) {
4535
4536
		var x1 = this.positionAbs.left,
4537
			x2 = x1 + this.helperProportions.width,
4538
			y1 = this.positionAbs.top,
4539
			y2 = y1 + this.helperProportions.height,
4540
			l = item.left,
4541
			r = l + item.width,
4542
			t = item.top,
4543
			b = t + item.height,
4544
			dyClick = this.offset.click.top,
4545
			dxClick = this.offset.click.left,
4546
			isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t && ( y1 + dyClick ) < b ),
4547
			isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l && ( x1 + dxClick ) < r ),
4548
			isOverElement = isOverElementHeight && isOverElementWidth;
4549
4550
		if ( this.options.tolerance === "pointer" ||
4551
			this.options.forcePointerForContainers ||
4552
			(this.options.tolerance !== "pointer" && this.helperProportions[this.floating ? "width" : "height"] > item[this.floating ? "width" : "height"])
4553
		) {
4554
			return isOverElement;
4555
		} else {
4556
4557
			return (l < x1 + (this.helperProportions.width / 2) && // Right Half
4558
				x2 - (this.helperProportions.width / 2) < r && // Left Half
4559
				t < y1 + (this.helperProportions.height / 2) && // Bottom Half
4560
				y2 - (this.helperProportions.height / 2) < b ); // Top Half
4561
4562
		}
4563
	},
4564
4565
	_intersectsWithPointer: function(item) {
4566
4567
		var isOverElementHeight = (this.options.axis === "x") || isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
4568
			isOverElementWidth = (this.options.axis === "y") || isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
4569
			isOverElement = isOverElementHeight && isOverElementWidth,
4570
			verticalDirection = this._getDragVerticalDirection(),
4571
			horizontalDirection = this._getDragHorizontalDirection();
4572
4573
		if (!isOverElement) {
4574
			return false;
4575
		}
4576
4577
		return this.floating ?
4578
			( ((horizontalDirection && horizontalDirection === "right") || verticalDirection === "down") ? 2 : 1 )
4579
			: ( verticalDirection && (verticalDirection === "down" ? 2 : 1) );
4580
4581
	},
4582
4583
	_intersectsWithSides: function(item) {
4584
4585
		var isOverBottomHalf = isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
4586
			isOverRightHalf = isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
4587
			verticalDirection = this._getDragVerticalDirection(),
4588
			horizontalDirection = this._getDragHorizontalDirection();
4589
4590
		if (this.floating && horizontalDirection) {
4591
			return ((horizontalDirection === "right" && isOverRightHalf) || (horizontalDirection === "left" && !isOverRightHalf));
4592
		} else {
4593
			return verticalDirection && ((verticalDirection === "down" && isOverBottomHalf) || (verticalDirection === "up" && !isOverBottomHalf));
4594
		}
4595
4596
	},
4597
4598
	_getDragVerticalDirection: function() {
4599
		var delta = this.positionAbs.top - this.lastPositionAbs.top;
4600
		return delta !== 0 && (delta > 0 ? "down" : "up");
4601
	},
4602
4603
	_getDragHorizontalDirection: function() {
4604
		var delta = this.positionAbs.left - this.lastPositionAbs.left;
4605
		return delta !== 0 && (delta > 0 ? "right" : "left");
4606
	},
4607
4608
	refresh: function(event) {
4609
		this._refreshItems(event);
4610
		this.refreshPositions();
4611
		return this;
4612
	},
4613
4614
	_connectWith: function() {
4615
		var options = this.options;
4616
		return options.connectWith.constructor === String ? [options.connectWith] : options.connectWith;
4617
	},
4618
4619
	_getItemsAsjQuery: function(connected) {
4620
4621
		var i, j, cur, inst,
4622
			items = [],
4623
			queries = [],
4624
			connectWith = this._connectWith();
4625
4626
		if(connectWith && connected) {
4627
			for (i = connectWith.length - 1; i >= 0; i--){
4628
				cur = $(connectWith[i]);
4629
				for ( j = cur.length - 1; j >= 0; j--){
4630
					inst = $.data(cur[j], this.widgetFullName);
4631
					if(inst && inst !== this && !inst.options.disabled) {
4632
						queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), inst]);
4633
					}
4634
				}
4635
			}
4636
		}
4637
4638
		queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), this]);
4639
4640
		function addItems() {
4641
			items.push( this );
4642
		}
4643
		for (i = queries.length - 1; i >= 0; i--){
4644
			queries[i][0].each( addItems );
4645
		}
4646
4647
		return $(items);
4648
4649
	},
4650
4651
	_removeCurrentsFromItems: function() {
4652
4653
		var list = this.currentItem.find(":data(" + this.widgetName + "-item)");
4654
4655
		this.items = $.grep(this.items, function (item) {
4656
			for (var j=0; j < list.length; j++) {
4657
				if(list[j] === item.item[0]) {
4658
					return false;
4659
				}
4660
			}
4661
			return true;
4662
		});
4663
4664
	},
4665
4666
	_refreshItems: function(event) {
4667
4668
		this.items = [];
4669
		this.containers = [this];
4670
4671
		var i, j, cur, inst, targetData, _queries, item, queriesLength,
4672
			items = this.items,
4673
			queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]],
4674
			connectWith = this._connectWith();
4675
4676
		if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down
4677
			for (i = connectWith.length - 1; i >= 0; i--){
4678
				cur = $(connectWith[i]);
4679
				for (j = cur.length - 1; j >= 0; j--){
4680
					inst = $.data(cur[j], this.widgetFullName);
4681
					if(inst && inst !== this && !inst.options.disabled) {
4682
						queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
4683
						this.containers.push(inst);
4684
					}
4685
				}
4686
			}
4687
		}
4688
4689
		for (i = queries.length - 1; i >= 0; i--) {
4690
			targetData = queries[i][1];
4691
			_queries = queries[i][0];
4692
4693
			for (j=0, queriesLength = _queries.length; j < queriesLength; j++) {
4694
				item = $(_queries[j]);
4695
4696
				item.data(this.widgetName + "-item", targetData); // Data for target checking (mouse manager)
4697
4698
				items.push({
4699
					item: item,
4700
					instance: targetData,
4701
					width: 0, height: 0,
4702
					left: 0, top: 0
4703
				});
4704
			}
4705
		}
4706
4707
	},
4708
4709
	refreshPositions: function(fast) {
4710
4711
		//This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
4712
		if(this.offsetParent && this.helper) {
4713
			this.offset.parent = this._getParentOffset();
4714
		}
4715
4716
		var i, item, t, p;
4717
4718
		for (i = this.items.length - 1; i >= 0; i--){
4719
			item = this.items[i];
4720
4721
			//We ignore calculating positions of all connected containers when we're not over them
4722
			if(item.instance !== this.currentContainer && this.currentContainer && item.item[0] !== this.currentItem[0]) {
4723
				continue;
4724
			}
4725
4726
			t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
4727
4728
			if (!fast) {
4729
				item.width = t.outerWidth();
4730
				item.height = t.outerHeight();
4731
			}
4732
4733
			p = t.offset();
4734
			item.left = p.left;
4735
			item.top = p.top;
4736
		}
4737
4738
		if(this.options.custom && this.options.custom.refreshContainers) {
4739
			this.options.custom.refreshContainers.call(this);
4740
		} else {
4741
			for (i = this.containers.length - 1; i >= 0; i--){
4742
				p = this.containers[i].element.offset();
4743
				this.containers[i].containerCache.left = p.left;
4744
				this.containers[i].containerCache.top = p.top;
4745
				this.containers[i].containerCache.width	= this.containers[i].element.outerWidth();
4746
				this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
4747
			}
4748
		}
4749
4750
		return this;
4751
	},
4752
4753
	_createPlaceholder: function(that) {
4754
		that = that || this;
4755
		var className,
4756
			o = that.options;
4757
4758
		if(!o.placeholder || o.placeholder.constructor === String) {
4759
			className = o.placeholder;
4760
			o.placeholder = {
4761
				element: function() {
4762
4763
					var nodeName = that.currentItem[0].nodeName.toLowerCase(),
4764
						element = $( "<" + nodeName + ">", that.document[0] )
4765
							.addClass(className || that.currentItem[0].className+" ui-sortable-placeholder")
4766
							.removeClass("ui-sortable-helper");
4767
4768
					if ( nodeName === "tr" ) {
4769
						that.currentItem.children().each(function() {
4770
							$( "<td>&#160;</td>", that.document[0] )
4771
								.attr( "colspan", $( this ).attr( "colspan" ) || 1 )
4772
								.appendTo( element );
4773
						});
4774
					} else if ( nodeName === "img" ) {
4775
						element.attr( "src", that.currentItem.attr( "src" ) );
4776
					}
4777
4778
					if ( !className ) {
4779
						element.css( "visibility", "hidden" );
4780
					}
4781
4782
					return element;
4783
				},
4784
				update: function(container, p) {
4785
4786
					// 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
4787
					// 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
4788
					if(className && !o.forcePlaceholderSize) {
4789
						return;
4790
					}
4791
4792
					//If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item
4793
					if(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css("paddingTop")||0, 10) - parseInt(that.currentItem.css("paddingBottom")||0, 10)); }
4794
					if(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css("paddingLeft")||0, 10) - parseInt(that.currentItem.css("paddingRight")||0, 10)); }
4795
				}
4796
			};
4797
		}
4798
4799
		//Create the placeholder
4800
		that.placeholder = $(o.placeholder.element.call(that.element, that.currentItem));
4801
4802
		//Append it after the actual current item
4803
		that.currentItem.after(that.placeholder);
4804
4805
		//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
4806
		o.placeholder.update(that, that.placeholder);
4807
4808
	},
4809
4810
	_contactContainers: function(event) {
4811
		var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, base, cur, nearBottom, floating,
4812
			innermostContainer = null,
4813
			innermostIndex = null;
4814
4815
		// get innermost container that intersects with item
4816
		for (i = this.containers.length - 1; i >= 0; i--) {
4817
4818
			// never consider a container that's located within the item itself
4819
			if($.contains(this.currentItem[0], this.containers[i].element[0])) {
4820
				continue;
4821
			}
4822
4823
			if(this._intersectsWith(this.containers[i].containerCache)) {
4824
4825
				// if we've already found a container and it's more "inner" than this, then continue
4826
				if(innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0])) {
4827
					continue;
4828
				}
4829
4830
				innermostContainer = this.containers[i];
4831
				innermostIndex = i;
4832
4833
			} else {
4834
				// container doesn't intersect. trigger "out" event if necessary
4835
				if(this.containers[i].containerCache.over) {
4836
					this.containers[i]._trigger("out", event, this._uiHash(this));
4837
					this.containers[i].containerCache.over = 0;
4838
				}
4839
			}
4840
4841
		}
4842
4843
		// if no intersecting containers found, return
4844
		if(!innermostContainer) {
4845
			return;
4846
		}
4847
4848
		// move the item into the container if it's not there already
4849
		if(this.containers.length === 1) {
4850
			if (!this.containers[innermostIndex].containerCache.over) {
4851
				this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
4852
				this.containers[innermostIndex].containerCache.over = 1;
4853
			}
4854
		} else {
4855
4856
			//When entering a new container, we will find the item with the least distance and append our item near it
4857
			dist = 10000;
4858
			itemWithLeastDistance = null;
4859
			floating = innermostContainer.floating || isFloating(this.currentItem);
4860
			posProperty = floating ? "left" : "top";
4861
			sizeProperty = floating ? "width" : "height";
4862
			base = this.positionAbs[posProperty] + this.offset.click[posProperty];
4863
			for (j = this.items.length - 1; j >= 0; j--) {
4864
				if(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) {
4865
					continue;
4866
				}
4867
				if(this.items[j].item[0] === this.currentItem[0]) {
4868
					continue;
4869
				}
4870
				if (floating && !isOverAxis(this.positionAbs.top + this.offset.click.top, this.items[j].top, this.items[j].height)) {
4871
					continue;
4872
				}
4873
				cur = this.items[j].item.offset()[posProperty];
4874
				nearBottom = false;
4875
				if(Math.abs(cur - base) > Math.abs(cur + this.items[j][sizeProperty] - base)){
4876
					nearBottom = true;
4877
					cur += this.items[j][sizeProperty];
4878
				}
4879
4880
				if(Math.abs(cur - base) < dist) {
4881
					dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j];
4882
					this.direction = nearBottom ? "up": "down";
4883
				}
4884
			}
4885
4886
			//Check if dropOnEmpty is enabled
4887
			if(!itemWithLeastDistance && !this.options.dropOnEmpty) {
4888
				return;
4889
			}
4890
4891
			if(this.currentContainer === this.containers[innermostIndex]) {
4892
				return;
4893
			}
4894
4895
			itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);
4896
			this._trigger("change", event, this._uiHash());
4897
			this.containers[innermostIndex]._trigger("change", event, this._uiHash(this));
4898
			this.currentContainer = this.containers[innermostIndex];
4899
4900
			//Update the placeholder
4901
			this.options.placeholder.update(this.currentContainer, this.placeholder);
4902
4903
			this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
4904
			this.containers[innermostIndex].containerCache.over = 1;
4905
		}
4906
4907
4908
	},
4909
4910
	_createHelper: function(event) {
4911
4912
		var o = this.options,
4913
			helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper === "clone" ? this.currentItem.clone() : this.currentItem);
4914
4915
		//Add the helper to the DOM if that didn't happen already
4916
		if(!helper.parents("body").length) {
4917
			$(o.appendTo !== "parent" ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
4918
		}
4919
4920
		if(helper[0] === this.currentItem[0]) {
4921
			this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") };
4922
		}
4923
4924
		if(!helper[0].style.width || o.forceHelperSize) {
4925
			helper.width(this.currentItem.width());
4926
		}
4927
		if(!helper[0].style.height || o.forceHelperSize) {
4928
			helper.height(this.currentItem.height());
4929
		}
4930
4931
		return helper;
4932
4933
	},
4934
4935
	_adjustOffsetFromHelper: function(obj) {
4936
		if (typeof obj === "string") {
4937
			obj = obj.split(" ");
4938
		}
4939
		if ($.isArray(obj)) {
4940
			obj = {left: +obj[0], top: +obj[1] || 0};
4941
		}
4942
		if ("left" in obj) {
4943
			this.offset.click.left = obj.left + this.margins.left;
4944
		}
4945
		if ("right" in obj) {
4946
			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
4947
		}
4948
		if ("top" in obj) {
4949
			this.offset.click.top = obj.top + this.margins.top;
4950
		}
4951
		if ("bottom" in obj) {
4952
			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
4953
		}
4954
	},
4955
4956
	_getParentOffset: function() {
4957
4958
4959
		//Get the offsetParent and cache its position
4960
		this.offsetParent = this.helper.offsetParent();
4961
		var po = this.offsetParent.offset();
4962
4963
		// This is a special case where we need to modify a offset calculated on start, since the following happened:
4964
		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
4965
		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
4966
		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
4967
		if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
4968
			po.left += this.scrollParent.scrollLeft();
4969
			po.top += this.scrollParent.scrollTop();
4970
		}
4971
4972
		// This needs to be actually done for all browsers, since pageX/pageY includes this information
4973
		// with an ugly IE fix
4974
		if( this.offsetParent[0] === document.body || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) {
4975
			po = { top: 0, left: 0 };
4976
		}
4977
4978
		return {
4979
			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
4980
			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
4981
		};
4982
4983
	},
4984
4985
	_getRelativeOffset: function() {
4986
4987
		if(this.cssPosition === "relative") {
4988
			var p = this.currentItem.position();
4989
			return {
4990
				top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
4991
				left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
4992
			};
4993
		} else {
4994
			return { top: 0, left: 0 };
4995
		}
4996
4997
	},
4998
4999
	_cacheMargins: function() {
5000
		this.margins = {
5001
			left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
5002
			top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
5003
		};
5004
	},
5005
5006
	_cacheHelperProportions: function() {
5007
		this.helperProportions = {
5008
			width: this.helper.outerWidth(),
5009
			height: this.helper.outerHeight()
5010
		};
5011
	},
5012
5013
	_setContainment: function() {
5014
5015
		var ce, co, over,
5016
			o = this.options;
5017
		if(o.containment === "parent") {
5018
			o.containment = this.helper[0].parentNode;
5019
		}
5020
		if(o.containment === "document" || o.containment === "window") {
5021
			this.containment = [
5022
				0 - this.offset.relative.left - this.offset.parent.left,
5023
				0 - this.offset.relative.top - this.offset.parent.top,
5024
				$(o.containment === "document" ? document : window).width() - this.helperProportions.width - this.margins.left,
5025
				($(o.containment === "document" ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
5026
			];
5027
		}
5028
5029
		if(!(/^(document|window|parent)$/).test(o.containment)) {
5030
			ce = $(o.containment)[0];
5031
			co = $(o.containment).offset();
5032
			over = ($(ce).css("overflow") !== "hidden");
5033
5034
			this.containment = [
5035
				co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
5036
				co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
5037
				co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
5038
				co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
5039
			];
5040
		}
5041
5042
	},
5043
5044
	_convertPositionTo: function(d, pos) {
5045
5046
		if(!pos) {
5047
			pos = this.position;
5048
		}
5049
		var mod = d === "absolute" ? 1 : -1,
5050
			scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent,
5051
			scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
5052
5053
		return {
5054
			top: (
5055
				pos.top	+																// The absolute mouse position
5056
				this.offset.relative.top * mod +										// Only for relative positioned nodes: Relative offset from element to offset parent
5057
				this.offset.parent.top * mod -											// The offsetParent's offset without borders (offset + border)
5058
				( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
5059
			),
5060
			left: (
5061
				pos.left +																// The absolute mouse position
5062
				this.offset.relative.left * mod +										// Only for relative positioned nodes: Relative offset from element to offset parent
5063
				this.offset.parent.left * mod	-										// The offsetParent's offset without borders (offset + border)
5064
				( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
5065
			)
5066
		};
5067
5068
	},
5069
5070
	_generatePosition: function(event) {
5071
5072
		var top, left,
5073
			o = this.options,
5074
			pageX = event.pageX,
5075
			pageY = event.pageY,
5076
			scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
5077
5078
		// This is another very weird special case that only happens for relative elements:
5079
		// 1. If the css position is relative
5080
		// 2. and the scroll parent is the document or similar to the offset parent
5081
		// we have to refresh the relative offset during the scroll so there are no jumps
5082
		if(this.cssPosition === "relative" && !(this.scrollParent[0] !== document && this.scrollParent[0] !== this.offsetParent[0])) {
5083
			this.offset.relative = this._getRelativeOffset();
5084
		}
5085
5086
		/*
5087
		 * - Position constraining -
5088
		 * Constrain the position to a mix of grid, containment.
5089
		 */
5090
5091
		if(this.originalPosition) { //If we are not dragging yet, we won't check for options
5092
5093
			if(this.containment) {
5094
				if(event.pageX - this.offset.click.left < this.containment[0]) {
5095
					pageX = this.containment[0] + this.offset.click.left;
5096
				}
5097
				if(event.pageY - this.offset.click.top < this.containment[1]) {
5098
					pageY = this.containment[1] + this.offset.click.top;
5099
				}
5100
				if(event.pageX - this.offset.click.left > this.containment[2]) {
5101
					pageX = this.containment[2] + this.offset.click.left;
5102
				}
5103
				if(event.pageY - this.offset.click.top > this.containment[3]) {
5104
					pageY = this.containment[3] + this.offset.click.top;
5105
				}
5106
			}
5107
5108
			if(o.grid) {
5109
				top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
5110
				pageY = this.containment ? ( (top - this.offset.click.top >= this.containment[1] && top - this.offset.click.top <= this.containment[3]) ? top : ((top - this.offset.click.top >= this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
5111
5112
				left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
5113
				pageX = this.containment ? ( (left - this.offset.click.left >= this.containment[0] && left - this.offset.click.left <= this.containment[2]) ? left : ((left - this.offset.click.left >= this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
5114
			}
5115
5116
		}
5117
5118
		return {
5119
			top: (
5120
				pageY -																// The absolute mouse position
5121
				this.offset.click.top -													// Click offset (relative to the element)
5122
				this.offset.relative.top	-											// Only for relative positioned nodes: Relative offset from element to offset parent
5123
				this.offset.parent.top +												// The offsetParent's offset without borders (offset + border)
5124
				( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
5125
			),
5126
			left: (
5127
				pageX -																// The absolute mouse position
5128
				this.offset.click.left -												// Click offset (relative to the element)
5129
				this.offset.relative.left	-											// Only for relative positioned nodes: Relative offset from element to offset parent
5130
				this.offset.parent.left +												// The offsetParent's offset without borders (offset + border)
5131
				( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
5132
			)
5133
		};
5134
5135
	},
5136
5137
	_rearrange: function(event, i, a, hardRefresh) {
5138
5139
		a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction === "down" ? i.item[0] : i.item[0].nextSibling));
5140
5141
		//Various things done here to improve the performance:
5142
		// 1. we create a setTimeout, that calls refreshPositions
5143
		// 2. on the instance, we have a counter variable, that get's higher after every append
5144
		// 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
5145
		// 4. this lets only the last addition to the timeout stack through
5146
		this.counter = this.counter ? ++this.counter : 1;
5147
		var counter = this.counter;
5148
5149
		this._delay(function() {
5150
			if(counter === this.counter) {
5151
				this.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
5152
			}
5153
		});
5154
5155
	},
5156
5157
	_clear: function(event, noPropagation) {
5158
5159
		this.reverting = false;
5160
		// We delay all events that have to be triggered to after the point where the placeholder has been removed and
5161
		// everything else normalized again
5162
		var i,
5163
			delayedTriggers = [];
5164
5165
		// We first have to update the dom position of the actual currentItem
5166
		// Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
5167
		if(!this._noFinalSort && this.currentItem.parent().length) {
5168
			this.placeholder.before(this.currentItem);
5169
		}
5170
		this._noFinalSort = null;
5171
5172
		if(this.helper[0] === this.currentItem[0]) {
5173
			for(i in this._storedCSS) {
5174
				if(this._storedCSS[i] === "auto" || this._storedCSS[i] === "static") {
5175
					this._storedCSS[i] = "";
5176
				}
5177
			}
5178
			this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
5179
		} else {
5180
			this.currentItem.show();
5181
		}
5182
5183
		if(this.fromOutside && !noPropagation) {
5184
			delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
5185
		}
5186
		if((this.fromOutside || this.domPosition.prev !== this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent !== this.currentItem.parent()[0]) && !noPropagation) {
5187
			delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
5188
		}
5189
5190
		// Check if the items Container has Changed and trigger appropriate
5191
		// events.
5192
		if (this !== this.currentContainer) {
5193
			if(!noPropagation) {
5194
				delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
5195
				delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); };  }).call(this, this.currentContainer));
5196
				delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this));  }; }).call(this, this.currentContainer));
5197
			}
5198
		}
5199
5200
5201
		//Post events to containers
5202
		function delayEvent( type, instance, container ) {
5203
			return function( event ) {
5204
				container._trigger( type, event, instance._uiHash( instance ) );
5205
			};
5206
		}
5207
		for (i = this.containers.length - 1; i >= 0; i--){
5208
			if (!noPropagation) {
5209
				delayedTriggers.push( delayEvent( "deactivate", this, this.containers[ i ] ) );
5210
			}
5211
			if(this.containers[i].containerCache.over) {
5212
				delayedTriggers.push( delayEvent( "out", this, this.containers[ i ] ) );
5213
				this.containers[i].containerCache.over = 0;
5214
			}
5215
		}
5216
5217
		//Do what was originally in plugins
5218
		if ( this.storedCursor ) {
5219
			this.document.find( "body" ).css( "cursor", this.storedCursor );
5220
			this.storedStylesheet.remove();
5221
		}
5222
		if(this._storedOpacity) {
5223
			this.helper.css("opacity", this._storedOpacity);
5224
		}
5225
		if(this._storedZIndex) {
5226
			this.helper.css("zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex);
5227
		}
5228
5229
		this.dragging = false;
5230
		if(this.cancelHelperRemoval) {
5231
			if(!noPropagation) {
5232
				this._trigger("beforeStop", event, this._uiHash());
5233
				for (i=0; i < delayedTriggers.length; i++) {
5234
					delayedTriggers[i].call(this, event);
5235
				} //Trigger all delayed events
5236
				this._trigger("stop", event, this._uiHash());
5237
			}
5238
5239
			this.fromOutside = false;
5240
			return false;
5241
		}
5242
5243
		if(!noPropagation) {
5244
			this._trigger("beforeStop", event, this._uiHash());
5245
		}
5246
5247
		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
5248
		this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
5249
5250
		if(this.helper[0] !== this.currentItem[0]) {
5251
			this.helper.remove();
5252
		}
5253
		this.helper = null;
5254
5255
		if(!noPropagation) {
5256
			for (i=0; i < delayedTriggers.length; i++) {
5257
				delayedTriggers[i].call(this, event);
5258
			} //Trigger all delayed events
5259
			this._trigger("stop", event, this._uiHash());
5260
		}
5261
5262
		this.fromOutside = false;
5263
		return true;
5264
5265
	},
5266
5267
	_trigger: function() {
5268
		if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
5269
			this.cancel();
5270
		}
5271
	},
5272
5273
	_uiHash: function(_inst) {
5274
		var inst = _inst || this;
5275
		return {
5276
			helper: inst.helper,
5277
			placeholder: inst.placeholder || $([]),
5278
			position: inst.position,
5279
			originalPosition: inst.originalPosition,
5280
			offset: inst.positionAbs,
5281
			item: inst.currentItem,
5282
			sender: _inst ? _inst.element : null
5283
		};
5284
	}
5285
5286
});
5287
5288
})(jQuery);
5289
(function( $, undefined ) {
0 ignored issues
show
Unused Code introduced by
The parameter undefined is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
5290
5291
var uid = 0,
5292
	hideProps = {},
5293
	showProps = {};
5294
5295
hideProps.height = hideProps.paddingTop = hideProps.paddingBottom =
5296
	hideProps.borderTopWidth = hideProps.borderBottomWidth = "hide";
5297
showProps.height = showProps.paddingTop = showProps.paddingBottom =
5298
	showProps.borderTopWidth = showProps.borderBottomWidth = "show";
5299
5300
$.widget( "ui.accordion", {
5301
	version: "1.10.4",
5302
	options: {
5303
		active: 0,
5304
		animate: {},
5305
		collapsible: false,
5306
		event: "click",
5307
		header: "> li > :first-child,> :not(li):even",
5308
		heightStyle: "auto",
5309
		icons: {
5310
			activeHeader: "ui-icon-triangle-1-s",
5311
			header: "ui-icon-triangle-1-e"
5312
		},
5313
5314
		// callbacks
5315
		activate: null,
5316
		beforeActivate: null
5317
	},
5318
5319
	_create: function() {
5320
		var options = this.options;
5321
		this.prevShow = this.prevHide = $();
5322
		this.element.addClass( "ui-accordion ui-widget ui-helper-reset" )
5323
			// ARIA
5324
			.attr( "role", "tablist" );
5325
5326
		// don't allow collapsible: false and active: false / null
5327
		if ( !options.collapsible && (options.active === false || options.active == null) ) {
5328
			options.active = 0;
5329
		}
5330
5331
		this._processPanels();
5332
		// handle negative values
5333
		if ( options.active < 0 ) {
5334
			options.active += this.headers.length;
5335
		}
5336
		this._refresh();
5337
	},
5338
5339
	_getCreateEventData: function() {
5340
		return {
5341
			header: this.active,
5342
			panel: !this.active.length ? $() : this.active.next(),
5343
			content: !this.active.length ? $() : this.active.next()
5344
		};
5345
	},
5346
5347
	_createIcons: function() {
5348
		var icons = this.options.icons;
5349
		if ( icons ) {
5350
			$( "<span>" )
5351
				.addClass( "ui-accordion-header-icon ui-icon " + icons.header )
5352
				.prependTo( this.headers );
5353
			this.active.children( ".ui-accordion-header-icon" )
5354
				.removeClass( icons.header )
5355
				.addClass( icons.activeHeader );
5356
			this.headers.addClass( "ui-accordion-icons" );
5357
		}
5358
	},
5359
5360
	_destroyIcons: function() {
5361
		this.headers
5362
			.removeClass( "ui-accordion-icons" )
5363
			.children( ".ui-accordion-header-icon" )
5364
				.remove();
5365
	},
5366
5367
	_destroy: function() {
5368
		var contents;
5369
5370
		// clean up main element
5371
		this.element
5372
			.removeClass( "ui-accordion ui-widget ui-helper-reset" )
5373
			.removeAttr( "role" );
5374
5375
		// clean up headers
5376
		this.headers
5377
			.removeClass( "ui-accordion-header ui-accordion-header-active ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )
5378
			.removeAttr( "role" )
5379
			.removeAttr( "aria-expanded" )
5380
			.removeAttr( "aria-selected" )
5381
			.removeAttr( "aria-controls" )
5382
			.removeAttr( "tabIndex" )
5383
			.each(function() {
5384
				if ( /^ui-accordion/.test( this.id ) ) {
5385
					this.removeAttribute( "id" );
5386
				}
5387
			});
5388
		this._destroyIcons();
5389
5390
		// clean up content panels
5391
		contents = this.headers.next()
5392
			.css( "display", "" )
5393
			.removeAttr( "role" )
5394
			.removeAttr( "aria-hidden" )
5395
			.removeAttr( "aria-labelledby" )
5396
			.removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled" )
5397
			.each(function() {
5398
				if ( /^ui-accordion/.test( this.id ) ) {
5399
					this.removeAttribute( "id" );
5400
				}
5401
			});
5402
		if ( this.options.heightStyle !== "content" ) {
5403
			contents.css( "height", "" );
5404
		}
5405
	},
5406
5407
	_setOption: function( key, value ) {
5408
		if ( key === "active" ) {
5409
			// _activate() will handle invalid values and update this.options
5410
			this._activate( value );
5411
			return;
5412
		}
5413
5414
		if ( key === "event" ) {
5415
			if ( this.options.event ) {
5416
				this._off( this.headers, this.options.event );
5417
			}
5418
			this._setupEvents( value );
5419
		}
5420
5421
		this._super( key, value );
5422
5423
		// setting collapsible: false while collapsed; open first panel
5424
		if ( key === "collapsible" && !value && this.options.active === false ) {
5425
			this._activate( 0 );
5426
		}
5427
5428
		if ( key === "icons" ) {
5429
			this._destroyIcons();
5430
			if ( value ) {
5431
				this._createIcons();
5432
			}
5433
		}
5434
5435
		// #5332 - opacity doesn't cascade to positioned elements in IE
5436
		// so we need to add the disabled class to the headers and panels
5437
		if ( key === "disabled" ) {
5438
			this.headers.add( this.headers.next() )
5439
				.toggleClass( "ui-state-disabled", !!value );
5440
		}
5441
	},
5442
5443
	_keydown: function( event ) {
5444
		if ( event.altKey || event.ctrlKey ) {
5445
			return;
5446
		}
5447
5448
		var keyCode = $.ui.keyCode,
5449
			length = this.headers.length,
5450
			currentIndex = this.headers.index( event.target ),
5451
			toFocus = false;
5452
5453
		switch ( event.keyCode ) {
0 ignored issues
show
Coding Style introduced by
As per coding-style, switch statements should have a default case.
Loading history...
5454
			case keyCode.RIGHT:
0 ignored issues
show
Bug introduced by
The variable keyCode seems to be never declared. If this is a global, consider adding a /** global: keyCode */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
5455
			case keyCode.DOWN:
5456
				toFocus = this.headers[ ( currentIndex + 1 ) % length ];
5457
				break;
5458
			case keyCode.LEFT:
5459
			case keyCode.UP:
5460
				toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
5461
				break;
5462
			case keyCode.SPACE:
5463
			case keyCode.ENTER:
5464
				this._eventHandler( event );
5465
				break;
5466
			case keyCode.HOME:
5467
				toFocus = this.headers[ 0 ];
5468
				break;
5469
			case keyCode.END:
5470
				toFocus = this.headers[ length - 1 ];
5471
				break;
5472
		}
5473
5474
		if ( toFocus ) {
5475
			$( event.target ).attr( "tabIndex", -1 );
5476
			$( toFocus ).attr( "tabIndex", 0 );
5477
			toFocus.focus();
5478
			event.preventDefault();
5479
		}
5480
	},
5481
5482
	_panelKeyDown : function( event ) {
5483
		if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) {
5484
			$( event.currentTarget ).prev().focus();
5485
		}
5486
	},
5487
5488
	refresh: function() {
5489
		var options = this.options;
5490
		this._processPanels();
5491
5492
		// was collapsed or no panel
5493
		if ( ( options.active === false && options.collapsible === true ) || !this.headers.length ) {
5494
			options.active = false;
5495
			this.active = $();
5496
		// active false only when collapsible is true
5497
		} else if ( options.active === false ) {
5498
			this._activate( 0 );
5499
		// was active, but active panel is gone
5500
		} else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
5501
			// all remaining panel are disabled
5502
			if ( this.headers.length === this.headers.find(".ui-state-disabled").length ) {
5503
				options.active = false;
5504
				this.active = $();
5505
			// activate previous panel
5506
			} else {
5507
				this._activate( Math.max( 0, options.active - 1 ) );
5508
			}
5509
		// was active, active panel still exists
5510
		} else {
5511
			// make sure active index is correct
5512
			options.active = this.headers.index( this.active );
5513
		}
5514
5515
		this._destroyIcons();
5516
5517
		this._refresh();
5518
	},
5519
5520
	_processPanels: function() {
5521
		this.headers = this.element.find( this.options.header )
5522
			.addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" );
5523
5524
		this.headers.next()
5525
			.addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" )
5526
			.filter(":not(.ui-accordion-content-active)")
5527
			.hide();
5528
	},
5529
5530
	_refresh: function() {
5531
		var maxHeight,
5532
			options = this.options,
5533
			heightStyle = options.heightStyle,
5534
			parent = this.element.parent(),
5535
			accordionId = this.accordionId = "ui-accordion-" +
5536
				(this.element.attr( "id" ) || ++uid);
5537
5538
		this.active = this._findActive( options.active )
5539
			.addClass( "ui-accordion-header-active ui-state-active ui-corner-top" )
5540
			.removeClass( "ui-corner-all" );
5541
		this.active.next()
5542
			.addClass( "ui-accordion-content-active" )
5543
			.show();
5544
5545
		this.headers
5546
			.attr( "role", "tab" )
5547
			.each(function( i ) {
5548
				var header = $( this ),
5549
					headerId = header.attr( "id" ),
5550
					panel = header.next(),
5551
					panelId = panel.attr( "id" );
5552
				if ( !headerId ) {
5553
					headerId = accordionId + "-header-" + i;
5554
					header.attr( "id", headerId );
5555
				}
5556
				if ( !panelId ) {
5557
					panelId = accordionId + "-panel-" + i;
5558
					panel.attr( "id", panelId );
5559
				}
5560
				header.attr( "aria-controls", panelId );
5561
				panel.attr( "aria-labelledby", headerId );
5562
			})
5563
			.next()
5564
				.attr( "role", "tabpanel" );
5565
5566
		this.headers
5567
			.not( this.active )
5568
			.attr({
5569
				"aria-selected": "false",
5570
				"aria-expanded": "false",
5571
				tabIndex: -1
5572
			})
5573
			.next()
5574
				.attr({
5575
					"aria-hidden": "true"
5576
				})
5577
				.hide();
5578
5579
		// make sure at least one header is in the tab order
5580
		if ( !this.active.length ) {
5581
			this.headers.eq( 0 ).attr( "tabIndex", 0 );
5582
		} else {
5583
			this.active.attr({
5584
				"aria-selected": "true",
5585
				"aria-expanded": "true",
5586
				tabIndex: 0
5587
			})
5588
			.next()
5589
				.attr({
5590
					"aria-hidden": "false"
5591
				});
5592
		}
5593
5594
		this._createIcons();
5595
5596
		this._setupEvents( options.event );
5597
5598
		if ( heightStyle === "fill" ) {
5599
			maxHeight = parent.height();
5600
			this.element.siblings( ":visible" ).each(function() {
5601
				var elem = $( this ),
5602
					position = elem.css( "position" );
5603
5604
				if ( position === "absolute" || position === "fixed" ) {
5605
					return;
5606
				}
5607
				maxHeight -= elem.outerHeight( true );
5608
			});
5609
5610
			this.headers.each(function() {
5611
				maxHeight -= $( this ).outerHeight( true );
5612
			});
5613
5614
			this.headers.next()
5615
				.each(function() {
5616
					$( this ).height( Math.max( 0, maxHeight -
5617
						$( this ).innerHeight() + $( this ).height() ) );
5618
				})
5619
				.css( "overflow", "auto" );
5620
		} else if ( heightStyle === "auto" ) {
5621
			maxHeight = 0;
5622
			this.headers.next()
5623
				.each(function() {
5624
					maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() );
5625
				})
5626
				.height( maxHeight );
5627
		}
5628
	},
5629
5630
	_activate: function( index ) {
5631
		var active = this._findActive( index )[ 0 ];
5632
5633
		// trying to activate the already active panel
5634
		if ( active === this.active[ 0 ] ) {
5635
			return;
5636
		}
5637
5638
		// trying to collapse, simulate a click on the currently active header
5639
		active = active || this.active[ 0 ];
5640
5641
		this._eventHandler({
5642
			target: active,
5643
			currentTarget: active,
5644
			preventDefault: $.noop
5645
		});
5646
	},
5647
5648
	_findActive: function( selector ) {
5649
		return typeof selector === "number" ? this.headers.eq( selector ) : $();
5650
	},
5651
5652
	_setupEvents: function( event ) {
5653
		var events = {
5654
			keydown: "_keydown"
5655
		};
5656
		if ( event ) {
5657
			$.each( event.split(" "), function( index, eventName ) {
5658
				events[ eventName ] = "_eventHandler";
5659
			});
5660
		}
5661
5662
		this._off( this.headers.add( this.headers.next() ) );
5663
		this._on( this.headers, events );
5664
		this._on( this.headers.next(), { keydown: "_panelKeyDown" });
5665
		this._hoverable( this.headers );
5666
		this._focusable( this.headers );
5667
	},
5668
5669
	_eventHandler: function( event ) {
5670
		var options = this.options,
5671
			active = this.active,
5672
			clicked = $( event.currentTarget ),
5673
			clickedIsActive = clicked[ 0 ] === active[ 0 ],
5674
			collapsing = clickedIsActive && options.collapsible,
5675
			toShow = collapsing ? $() : clicked.next(),
5676
			toHide = active.next(),
5677
			eventData = {
5678
				oldHeader: active,
5679
				oldPanel: toHide,
5680
				newHeader: collapsing ? $() : clicked,
5681
				newPanel: toShow
5682
			};
5683
5684
		event.preventDefault();
5685
5686
		if (
5687
				// click on active header, but not collapsible
5688
				( clickedIsActive && !options.collapsible ) ||
5689
				// allow canceling activation
5690
				( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
5691
			return;
5692
		}
5693
5694
		options.active = collapsing ? false : this.headers.index( clicked );
5695
5696
		// when the call to ._toggle() comes after the class changes
5697
		// it causes a very odd bug in IE 8 (see #6720)
5698
		this.active = clickedIsActive ? $() : clicked;
5699
		this._toggle( eventData );
5700
5701
		// switch classes
5702
		// corner classes on the previously active header stay after the animation
5703
		active.removeClass( "ui-accordion-header-active ui-state-active" );
5704
		if ( options.icons ) {
5705
			active.children( ".ui-accordion-header-icon" )
5706
				.removeClass( options.icons.activeHeader )
5707
				.addClass( options.icons.header );
5708
		}
5709
5710
		if ( !clickedIsActive ) {
5711
			clicked
5712
				.removeClass( "ui-corner-all" )
5713
				.addClass( "ui-accordion-header-active ui-state-active ui-corner-top" );
5714
			if ( options.icons ) {
5715
				clicked.children( ".ui-accordion-header-icon" )
5716
					.removeClass( options.icons.header )
5717
					.addClass( options.icons.activeHeader );
5718
			}
5719
5720
			clicked
5721
				.next()
5722
				.addClass( "ui-accordion-content-active" );
5723
		}
5724
	},
5725
5726
	_toggle: function( data ) {
5727
		var toShow = data.newPanel,
5728
			toHide = this.prevShow.length ? this.prevShow : data.oldPanel;
5729
5730
		// handle activating a panel during the animation for another activation
5731
		this.prevShow.add( this.prevHide ).stop( true, true );
5732
		this.prevShow = toShow;
5733
		this.prevHide = toHide;
5734
5735
		if ( this.options.animate ) {
5736
			this._animate( toShow, toHide, data );
5737
		} else {
5738
			toHide.hide();
5739
			toShow.show();
5740
			this._toggleComplete( data );
5741
		}
5742
5743
		toHide.attr({
5744
			"aria-hidden": "true"
5745
		});
5746
		toHide.prev().attr( "aria-selected", "false" );
5747
		// if we're switching panels, remove the old header from the tab order
5748
		// if we're opening from collapsed state, remove the previous header from the tab order
5749
		// if we're collapsing, then keep the collapsing header in the tab order
5750
		if ( toShow.length && toHide.length ) {
5751
			toHide.prev().attr({
5752
				"tabIndex": -1,
5753
				"aria-expanded": "false"
5754
			});
5755
		} else if ( toShow.length ) {
5756
			this.headers.filter(function() {
5757
				return $( this ).attr( "tabIndex" ) === 0;
5758
			})
5759
			.attr( "tabIndex", -1 );
5760
		}
5761
5762
		toShow
5763
			.attr( "aria-hidden", "false" )
5764
			.prev()
5765
				.attr({
5766
					"aria-selected": "true",
5767
					tabIndex: 0,
5768
					"aria-expanded": "true"
5769
				});
5770
	},
5771
5772
	_animate: function( toShow, toHide, data ) {
5773
		var total, easing, duration,
5774
			that = this,
5775
			adjust = 0,
5776
			down = toShow.length &&
5777
				( !toHide.length || ( toShow.index() < toHide.index() ) ),
5778
			animate = this.options.animate || {},
5779
			options = down && animate.down || animate,
5780
			complete = function() {
5781
				that._toggleComplete( data );
5782
			};
5783
5784
		if ( typeof options === "number" ) {
5785
			duration = options;
5786
		}
5787
		if ( typeof options === "string" ) {
5788
			easing = options;
5789
		}
5790
		// fall back from options to animation in case of partial down settings
5791
		easing = easing || options.easing || animate.easing;
5792
		duration = duration || options.duration || animate.duration;
5793
5794
		if ( !toHide.length ) {
5795
			return toShow.animate( showProps, duration, easing, complete );
5796
		}
5797
		if ( !toShow.length ) {
5798
			return toHide.animate( hideProps, duration, easing, complete );
5799
		}
5800
5801
		total = toShow.show().outerHeight();
5802
		toHide.animate( hideProps, {
5803
			duration: duration,
5804
			easing: easing,
5805
			step: function( now, fx ) {
5806
				fx.now = Math.round( now );
5807
			}
5808
		});
5809
		toShow
5810
			.hide()
5811
			.animate( showProps, {
5812
				duration: duration,
5813
				easing: easing,
5814
				complete: complete,
5815
				step: function( now, fx ) {
5816
					fx.now = Math.round( now );
5817
					if ( fx.prop !== "height" ) {
5818
						adjust += fx.now;
5819
					} else if ( that.options.heightStyle !== "content" ) {
5820
						fx.now = Math.round( total - toHide.outerHeight() - adjust );
5821
						adjust = 0;
5822
					}
5823
				}
5824
			});
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
5825
	},
5826
5827
	_toggleComplete: function( data ) {
5828
		var toHide = data.oldPanel;
5829
5830
		toHide
5831
			.removeClass( "ui-accordion-content-active" )
5832
			.prev()
5833
				.removeClass( "ui-corner-top" )
5834
				.addClass( "ui-corner-all" );
5835
5836
		// Work around for rendering bug in IE (#5421)
5837
		if ( toHide.length ) {
5838
			toHide.parent()[0].className = toHide.parent()[0].className;
5839
		}
5840
		this._trigger( "activate", null, data );
5841
	}
5842
});
5843
5844
})( jQuery );
5845
(function( $, undefined ) {
0 ignored issues
show
Unused Code introduced by
The parameter undefined is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
5846
5847
$.widget( "ui.autocomplete", {
5848
	version: "1.10.4",
5849
	defaultElement: "<input>",
5850
	options: {
5851
		appendTo: null,
5852
		autoFocus: false,
5853
		delay: 300,
5854
		minLength: 1,
5855
		position: {
5856
			my: "left top",
5857
			at: "left bottom",
5858
			collision: "none"
5859
		},
5860
		source: null,
5861
5862
		// callbacks
5863
		change: null,
5864
		close: null,
5865
		focus: null,
5866
		open: null,
5867
		response: null,
5868
		search: null,
5869
		select: null
5870
	},
5871
5872
	requestIndex: 0,
5873
	pending: 0,
5874
5875
	_create: function() {
5876
		// Some browsers only repeat keydown events, not keypress events,
5877
		// so we use the suppressKeyPress flag to determine if we've already
5878
		// handled the keydown event. #7269
5879
		// Unfortunately the code for & in keypress is the same as the up arrow,
5880
		// so we use the suppressKeyPressRepeat flag to avoid handling keypress
5881
		// events when we know the keydown event was used to modify the
5882
		// search term. #7799
5883
		var suppressKeyPress, suppressKeyPressRepeat, suppressInput,
5884
			nodeName = this.element[0].nodeName.toLowerCase(),
5885
			isTextarea = nodeName === "textarea",
5886
			isInput = nodeName === "input";
5887
5888
		this.isMultiLine =
5889
			// Textareas are always multi-line
5890
			isTextarea ? true :
5891
			// Inputs are always single-line, even if inside a contentEditable element
5892
			// IE also treats inputs as contentEditable
5893
			isInput ? false :
5894
			// All other element types are determined by whether or not they're contentEditable
5895
			this.element.prop( "isContentEditable" );
5896
5897
		this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ];
5898
		this.isNewMenu = true;
5899
5900
		this.element
5901
			.addClass( "ui-autocomplete-input" )
5902
			.attr( "autocomplete", "off" );
5903
5904
		this._on( this.element, {
5905
			keydown: function( event ) {
5906
				if ( this.element.prop( "readOnly" ) ) {
5907
					suppressKeyPress = true;
5908
					suppressInput = true;
5909
					suppressKeyPressRepeat = true;
5910
					return;
5911
				}
5912
5913
				suppressKeyPress = false;
5914
				suppressInput = false;
5915
				suppressKeyPressRepeat = false;
5916
				var keyCode = $.ui.keyCode;
5917
				switch( event.keyCode ) {
5918
				case keyCode.PAGE_UP:
0 ignored issues
show
Bug introduced by
The variable keyCode seems to be never declared. If this is a global, consider adding a /** global: keyCode */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
5919
					suppressKeyPress = true;
5920
					this._move( "previousPage", event );
5921
					break;
5922
				case keyCode.PAGE_DOWN:
5923
					suppressKeyPress = true;
5924
					this._move( "nextPage", event );
5925
					break;
5926
				case keyCode.UP:
5927
					suppressKeyPress = true;
5928
					this._keyEvent( "previous", event );
5929
					break;
5930
				case keyCode.DOWN:
5931
					suppressKeyPress = true;
5932
					this._keyEvent( "next", event );
5933
					break;
5934
				case keyCode.ENTER:
5935
				case keyCode.NUMPAD_ENTER:
5936
					// when menu is open and has focus
5937
					if ( this.menu.active ) {
5938
						// #6055 - Opera still allows the keypress to occur
5939
						// which causes forms to submit
5940
						suppressKeyPress = true;
5941
						event.preventDefault();
5942
						this.menu.select( event );
5943
					}
5944
					break;
5945
				case keyCode.TAB:
5946
					if ( this.menu.active ) {
5947
						this.menu.select( event );
5948
					}
5949
					break;
5950
				case keyCode.ESCAPE:
5951
					if ( this.menu.element.is( ":visible" ) ) {
5952
						this._value( this.term );
5953
						this.close( event );
5954
						// Different browsers have different default behavior for escape
5955
						// Single press can mean undo or clear
5956
						// Double press in IE means clear the whole form
5957
						event.preventDefault();
5958
					}
5959
					break;
5960
				default:
5961
					suppressKeyPressRepeat = true;
5962
					// search timeout should be triggered before the input value is changed
5963
					this._searchTimeout( event );
5964
					break;
5965
				}
5966
			},
5967
			keypress: function( event ) {
5968
				if ( suppressKeyPress ) {
5969
					suppressKeyPress = false;
5970
					if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
5971
						event.preventDefault();
5972
					}
5973
					return;
5974
				}
5975
				if ( suppressKeyPressRepeat ) {
5976
					return;
5977
				}
5978
5979
				// replicate some key handlers to allow them to repeat in Firefox and Opera
5980
				var keyCode = $.ui.keyCode;
5981
				switch( event.keyCode ) {
0 ignored issues
show
Coding Style introduced by
As per coding-style, switch statements should have a default case.
Loading history...
5982
				case keyCode.PAGE_UP:
0 ignored issues
show
Bug introduced by
The variable keyCode seems to be never declared. If this is a global, consider adding a /** global: keyCode */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
5983
					this._move( "previousPage", event );
5984
					break;
5985
				case keyCode.PAGE_DOWN:
5986
					this._move( "nextPage", event );
5987
					break;
5988
				case keyCode.UP:
5989
					this._keyEvent( "previous", event );
5990
					break;
5991
				case keyCode.DOWN:
5992
					this._keyEvent( "next", event );
5993
					break;
5994
				}
5995
			},
5996
			input: function( event ) {
5997
				if ( suppressInput ) {
5998
					suppressInput = false;
5999
					event.preventDefault();
6000
					return;
6001
				}
6002
				this._searchTimeout( event );
6003
			},
6004
			focus: function() {
6005
				this.selectedItem = null;
6006
				this.previous = this._value();
6007
			},
6008
			blur: function( event ) {
6009
				if ( this.cancelBlur ) {
6010
					delete this.cancelBlur;
6011
					return;
6012
				}
6013
6014
				clearTimeout( this.searching );
6015
				this.close( event );
6016
				this._change( event );
6017
			}
6018
		});
6019
6020
		this._initSource();
6021
		this.menu = $( "<ul>" )
6022
			.addClass( "ui-autocomplete ui-front" )
6023
			.appendTo( this._appendTo() )
6024
			.menu({
6025
				// disable ARIA support, the live region takes care of that
6026
				role: null
6027
			})
6028
			.hide()
6029
			.data( "ui-menu" );
6030
6031
		this._on( this.menu.element, {
6032
			mousedown: function( event ) {
6033
				// prevent moving focus out of the text field
6034
				event.preventDefault();
6035
6036
				// IE doesn't prevent moving focus even with event.preventDefault()
6037
				// so we set a flag to know when we should ignore the blur event
6038
				this.cancelBlur = true;
6039
				this._delay(function() {
6040
					delete this.cancelBlur;
6041
				});
6042
6043
				// clicking on the scrollbar causes focus to shift to the body
6044
				// but we can't detect a mouseup or a click immediately afterward
6045
				// so we have to track the next mousedown and close the menu if
6046
				// the user clicks somewhere outside of the autocomplete
6047
				var menuElement = this.menu.element[ 0 ];
6048
				if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
6049
					this._delay(function() {
6050
						var that = this;
6051
						this.document.one( "mousedown", function( event ) {
6052
							if ( event.target !== that.element[ 0 ] &&
6053
									event.target !== menuElement &&
6054
									!$.contains( menuElement, event.target ) ) {
6055
								that.close();
6056
							}
6057
						});
6058
					});
6059
				}
6060
			},
6061
			menufocus: function( event, ui ) {
6062
				// support: Firefox
6063
				// Prevent accidental activation of menu items in Firefox (#7024 #9118)
6064
				if ( this.isNewMenu ) {
6065
					this.isNewMenu = false;
6066
					if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {
6067
						this.menu.blur();
6068
6069
						this.document.one( "mousemove", function() {
6070
							$( event.target ).trigger( event.originalEvent );
6071
						});
6072
6073
						return;
6074
					}
6075
				}
6076
6077
				var item = ui.item.data( "ui-autocomplete-item" );
6078
				if ( false !== this._trigger( "focus", event, { item: item } ) ) {
6079
					// use value to match what will end up in the input, if it was a key event
6080
					if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
6081
						this._value( item.value );
6082
					}
6083
				} else {
6084
					// Normally the input is populated with the item's value as the
6085
					// menu is navigated, causing screen readers to notice a change and
6086
					// announce the item. Since the focus event was canceled, this doesn't
6087
					// happen, so we update the live region so that screen readers can
6088
					// still notice the change and announce it.
6089
					this.liveRegion.text( item.value );
6090
				}
6091
			},
6092
			menuselect: function( event, ui ) {
6093
				var item = ui.item.data( "ui-autocomplete-item" ),
6094
					previous = this.previous;
6095
6096
				// only trigger when focus was lost (click on menu)
6097
				if ( this.element[0] !== this.document[0].activeElement ) {
6098
					this.element.focus();
6099
					this.previous = previous;
6100
					// #6109 - IE triggers two focus events and the second
6101
					// is asynchronous, so we need to reset the previous
6102
					// term synchronously and asynchronously :-(
6103
					this._delay(function() {
6104
						this.previous = previous;
6105
						this.selectedItem = item;
6106
					});
6107
				}
6108
6109
				if ( false !== this._trigger( "select", event, { item: item } ) ) {
6110
					this._value( item.value );
6111
				}
6112
				// reset the term after the select event
6113
				// this allows custom select handling to work properly
6114
				this.term = this._value();
6115
6116
				this.close( event );
6117
				this.selectedItem = item;
6118
			}
6119
		});
6120
6121
		this.liveRegion = $( "<span>", {
6122
				role: "status",
6123
				"aria-live": "polite"
6124
			})
6125
			.addClass( "ui-helper-hidden-accessible" )
6126
			.insertBefore( this.element );
6127
6128
		// turning off autocomplete prevents the browser from remembering the
6129
		// value when navigating through history, so we re-enable autocomplete
6130
		// if the page is unloaded before the widget is destroyed. #7790
6131
		this._on( this.window, {
6132
			beforeunload: function() {
6133
				this.element.removeAttr( "autocomplete" );
6134
			}
6135
		});
6136
	},
6137
6138
	_destroy: function() {
6139
		clearTimeout( this.searching );
6140
		this.element
6141
			.removeClass( "ui-autocomplete-input" )
6142
			.removeAttr( "autocomplete" );
6143
		this.menu.element.remove();
6144
		this.liveRegion.remove();
6145
	},
6146
6147
	_setOption: function( key, value ) {
6148
		this._super( key, value );
6149
		if ( key === "source" ) {
6150
			this._initSource();
6151
		}
6152
		if ( key === "appendTo" ) {
6153
			this.menu.element.appendTo( this._appendTo() );
6154
		}
6155
		if ( key === "disabled" && value && this.xhr ) {
6156
			this.xhr.abort();
6157
		}
6158
	},
6159
6160
	_appendTo: function() {
6161
		var element = this.options.appendTo;
6162
6163
		if ( element ) {
6164
			element = element.jquery || element.nodeType ?
6165
				$( element ) :
6166
				this.document.find( element ).eq( 0 );
6167
		}
6168
6169
		if ( !element ) {
6170
			element = this.element.closest( ".ui-front" );
6171
		}
6172
6173
		if ( !element.length ) {
6174
			element = this.document[0].body;
6175
		}
6176
6177
		return element;
6178
	},
6179
6180
	_initSource: function() {
6181
		var array, url,
6182
			that = this;
6183
		if ( $.isArray(this.options.source) ) {
6184
			array = this.options.source;
6185
			this.source = function( request, response ) {
6186
				response( $.ui.autocomplete.filter( array, request.term ) );
6187
			};
6188
		} else if ( typeof this.options.source === "string" ) {
6189
			url = this.options.source;
6190
			this.source = function( request, response ) {
6191
				if ( that.xhr ) {
6192
					that.xhr.abort();
6193
				}
6194
				that.xhr = $.ajax({
6195
					url: url,
6196
					data: request,
6197
					dataType: "json",
6198
					success: function( data ) {
6199
						response( data );
6200
					},
6201
					error: function() {
6202
						response( [] );
6203
					}
6204
				});
6205
			};
6206
		} else {
6207
			this.source = this.options.source;
6208
		}
6209
	},
6210
6211
	_searchTimeout: function( event ) {
6212
		clearTimeout( this.searching );
6213
		this.searching = this._delay(function() {
6214
			// only search if the value has changed
6215
			if ( this.term !== this._value() ) {
6216
				this.selectedItem = null;
6217
				this.search( null, event );
6218
			}
6219
		}, this.options.delay );
6220
	},
6221
6222
	search: function( value, event ) {
6223
		value = value != null ? value : this._value();
6224
6225
		// always save the actual value, not the one passed as an argument
6226
		this.term = this._value();
6227
6228
		if ( value.length < this.options.minLength ) {
6229
			return this.close( event );
6230
		}
6231
6232
		if ( this._trigger( "search", event ) === false ) {
6233
			return;
6234
		}
6235
6236
		return this._search( value );
6237
	},
6238
6239
	_search: function( value ) {
6240
		this.pending++;
6241
		this.element.addClass( "ui-autocomplete-loading" );
6242
		this.cancelSearch = false;
6243
6244
		this.source( { term: value }, this._response() );
6245
	},
6246
6247
	_response: function() {
6248
		var index = ++this.requestIndex;
6249
6250
		return $.proxy(function( content ) {
6251
			if ( index === this.requestIndex ) {
6252
				this.__response( content );
6253
			}
6254
6255
			this.pending--;
6256
			if ( !this.pending ) {
6257
				this.element.removeClass( "ui-autocomplete-loading" );
6258
			}
6259
		}, this );
6260
	},
6261
6262
	__response: function( content ) {
6263
		if ( content ) {
6264
			content = this._normalize( content );
6265
		}
6266
		this._trigger( "response", null, { content: content } );
6267
		if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
6268
			this._suggest( content );
6269
			this._trigger( "open" );
6270
		} else {
6271
			// use ._close() instead of .close() so we don't cancel future searches
6272
			this._close();
6273
		}
6274
	},
6275
6276
	close: function( event ) {
6277
		this.cancelSearch = true;
6278
		this._close( event );
6279
	},
6280
6281
	_close: function( event ) {
6282
		if ( this.menu.element.is( ":visible" ) ) {
6283
			this.menu.element.hide();
6284
			this.menu.blur();
6285
			this.isNewMenu = true;
6286
			this._trigger( "close", event );
6287
		}
6288
	},
6289
6290
	_change: function( event ) {
6291
		if ( this.previous !== this._value() ) {
6292
			this._trigger( "change", event, { item: this.selectedItem } );
6293
		}
6294
	},
6295
6296
	_normalize: function( items ) {
6297
		// assume all items have the right format when the first item is complete
6298
		if ( items.length && items[0].label && items[0].value ) {
6299
			return items;
6300
		}
6301
		return $.map( items, function( item ) {
6302
			if ( typeof item === "string" ) {
6303
				return {
6304
					label: item,
6305
					value: item
6306
				};
6307
			}
6308
			return $.extend({
6309
				label: item.label || item.value,
6310
				value: item.value || item.label
6311
			}, item );
6312
		});
6313
	},
6314
6315
	_suggest: function( items ) {
6316
		var ul = this.menu.element.empty();
6317
		this._renderMenu( ul, items );
6318
		this.isNewMenu = true;
6319
		this.menu.refresh();
6320
6321
		// size and position menu
6322
		ul.show();
6323
		this._resizeMenu();
6324
		ul.position( $.extend({
6325
			of: this.element
6326
		}, this.options.position ));
6327
6328
		if ( this.options.autoFocus ) {
6329
			this.menu.next();
6330
		}
6331
	},
6332
6333
	_resizeMenu: function() {
6334
		var ul = this.menu.element;
6335
		ul.outerWidth( Math.max(
6336
			// Firefox wraps long text (possibly a rounding bug)
6337
			// so we add 1px to avoid the wrapping (#7513)
6338
			ul.width( "" ).outerWidth() + 1,
6339
			this.element.outerWidth()
6340
		) );
6341
	},
6342
6343
	_renderMenu: function( ul, items ) {
6344
		var that = this;
6345
		$.each( items, function( index, item ) {
6346
			that._renderItemData( ul, item );
6347
		});
6348
	},
6349
6350
	_renderItemData: function( ul, item ) {
6351
		return this._renderItem( ul, item ).data( "ui-autocomplete-item", item );
6352
	},
6353
6354
	_renderItem: function( ul, item ) {
6355
		return $( "<li>" )
6356
			.append( $( "<a>" ).text( item.label ) )
6357
			.appendTo( ul );
6358
	},
6359
6360
	_move: function( direction, event ) {
6361
		if ( !this.menu.element.is( ":visible" ) ) {
6362
			this.search( null, event );
6363
			return;
6364
		}
6365
		if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
6366
				this.menu.isLastItem() && /^next/.test( direction ) ) {
6367
			this._value( this.term );
6368
			this.menu.blur();
6369
			return;
6370
		}
6371
		this.menu[ direction ]( event );
6372
	},
6373
6374
	widget: function() {
6375
		return this.menu.element;
6376
	},
6377
6378
	_value: function() {
6379
		return this.valueMethod.apply( this.element, arguments );
6380
	},
6381
6382
	_keyEvent: function( keyEvent, event ) {
6383
		if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
6384
			this._move( keyEvent, event );
6385
6386
			// prevents moving cursor to beginning/end of the text field in some browsers
6387
			event.preventDefault();
6388
		}
6389
	}
6390
});
6391
6392
$.extend( $.ui.autocomplete, {
6393
	escapeRegex: function( value ) {
6394
		return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
6395
	},
6396
	filter: function(array, term) {
6397
		var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
6398
		return $.grep( array, function(value) {
6399
			return matcher.test( value.label || value.value || value );
6400
		});
6401
	}
6402
});
6403
6404
6405
// live region extension, adding a `messages` option
6406
// NOTE: This is an experimental API. We are still investigating
6407
// a full solution for string manipulation and internationalization.
6408
$.widget( "ui.autocomplete", $.ui.autocomplete, {
6409
	options: {
6410
		messages: {
6411
			noResults: "No search results.",
6412
			results: function( amount ) {
6413
				return amount + ( amount > 1 ? " results are" : " result is" ) +
6414
					" available, use up and down arrow keys to navigate.";
6415
			}
6416
		}
6417
	},
6418
6419
	__response: function( content ) {
6420
		var message;
6421
		this._superApply( arguments );
6422
		if ( this.options.disabled || this.cancelSearch ) {
6423
			return;
6424
		}
6425
		if ( content && content.length ) {
6426
			message = this.options.messages.results( content.length );
6427
		} else {
6428
			message = this.options.messages.noResults;
6429
		}
6430
		this.liveRegion.text( message );
6431
	}
6432
});
6433
6434
}( jQuery ));
6435
(function( $, undefined ) {
0 ignored issues
show
Unused Code introduced by
The parameter undefined is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
6436
6437
var lastActive,
6438
	baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
6439
	typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",
6440
	formResetHandler = function() {
6441
		var form = $( this );
6442
		setTimeout(function() {
6443
			form.find( ":ui-button" ).button( "refresh" );
6444
		}, 1 );
6445
	},
6446
	radioGroup = function( radio ) {
6447
		var name = radio.name,
6448
			form = radio.form,
6449
			radios = $( [] );
6450
		if ( name ) {
6451
			name = name.replace( /'/g, "\\'" );
6452
			if ( form ) {
6453
				radios = $( form ).find( "[name='" + name + "']" );
6454
			} else {
6455
				radios = $( "[name='" + name + "']", radio.ownerDocument )
6456
					.filter(function() {
6457
						return !this.form;
6458
					});
6459
			}
6460
		}
6461
		return radios;
6462
	};
6463
6464
$.widget( "ui.button", {
6465
	version: "1.10.4",
6466
	defaultElement: "<button>",
6467
	options: {
6468
		disabled: null,
6469
		text: true,
6470
		label: null,
6471
		icons: {
6472
			primary: null,
6473
			secondary: null
6474
		}
6475
	},
6476
	_create: function() {
6477
		this.element.closest( "form" )
6478
			.unbind( "reset" + this.eventNamespace )
6479
			.bind( "reset" + this.eventNamespace, formResetHandler );
6480
6481
		if ( typeof this.options.disabled !== "boolean" ) {
6482
			this.options.disabled = !!this.element.prop( "disabled" );
6483
		} else {
6484
			this.element.prop( "disabled", this.options.disabled );
6485
		}
6486
6487
		this._determineButtonType();
6488
		this.hasTitle = !!this.buttonElement.attr( "title" );
6489
6490
		var that = this,
6491
			options = this.options,
6492
			toggleButton = this.type === "checkbox" || this.type === "radio",
6493
			activeClass = !toggleButton ? "ui-state-active" : "";
6494
6495
		if ( options.label === null ) {
6496
			options.label = (this.type === "input" ? this.buttonElement.val() : this.buttonElement.html());
6497
		}
6498
6499
		this._hoverable( this.buttonElement );
6500
6501
		this.buttonElement
6502
			.addClass( baseClasses )
6503
			.attr( "role", "button" )
6504
			.bind( "mouseenter" + this.eventNamespace, function() {
6505
				if ( options.disabled ) {
6506
					return;
6507
				}
6508
				if ( this === lastActive ) {
6509
					$( this ).addClass( "ui-state-active" );
6510
				}
6511
			})
6512
			.bind( "mouseleave" + this.eventNamespace, function() {
6513
				if ( options.disabled ) {
6514
					return;
6515
				}
6516
				$( this ).removeClass( activeClass );
6517
			})
6518
			.bind( "click" + this.eventNamespace, function( event ) {
6519
				if ( options.disabled ) {
6520
					event.preventDefault();
6521
					event.stopImmediatePropagation();
6522
				}
6523
			});
6524
6525
		// Can't use _focusable() because the element that receives focus
6526
		// and the element that gets the ui-state-focus class are different
6527
		this._on({
6528
			focus: function() {
6529
				this.buttonElement.addClass( "ui-state-focus" );
6530
			},
6531
			blur: function() {
6532
				this.buttonElement.removeClass( "ui-state-focus" );
6533
			}
6534
		});
6535
6536
		if ( toggleButton ) {
6537
			this.element.bind( "change" + this.eventNamespace, function() {
6538
				that.refresh();
6539
			});
6540
		}
6541
6542
		if ( this.type === "checkbox" ) {
6543
			this.buttonElement.bind( "click" + this.eventNamespace, function() {
6544
				if ( options.disabled ) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if options.disabled is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
6545
					return false;
6546
				}
6547
			});
6548
		} else if ( this.type === "radio" ) {
6549
			this.buttonElement.bind( "click" + this.eventNamespace, function() {
6550
				if ( options.disabled ) {
6551
					return false;
6552
				}
6553
				$( this ).addClass( "ui-state-active" );
6554
				that.buttonElement.attr( "aria-pressed", "true" );
6555
6556
				var radio = that.element[ 0 ];
6557
				radioGroup( radio )
6558
					.not( radio )
6559
					.map(function() {
6560
						return $( this ).button( "widget" )[ 0 ];
6561
					})
6562
					.removeClass( "ui-state-active" )
6563
					.attr( "aria-pressed", "false" );
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
6564
			});
6565
		} else {
6566
			this.buttonElement
6567
				.bind( "mousedown" + this.eventNamespace, function() {
6568
					if ( options.disabled ) {
6569
						return false;
6570
					}
6571
					$( this ).addClass( "ui-state-active" );
6572
					lastActive = this;
6573
					that.document.one( "mouseup", function() {
6574
						lastActive = null;
6575
					});
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
6576
				})
6577
				.bind( "mouseup" + this.eventNamespace, function() {
6578
					if ( options.disabled ) {
6579
						return false;
6580
					}
6581
					$( this ).removeClass( "ui-state-active" );
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
6582
				})
6583
				.bind( "keydown" + this.eventNamespace, function(event) {
6584
					if ( options.disabled ) {
6585
						return false;
6586
					}
6587
					if ( event.keyCode === $.ui.keyCode.SPACE || event.keyCode === $.ui.keyCode.ENTER ) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if event.keyCode === $.ui.k... === $.ui.keyCode.ENTER is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
6588
						$( this ).addClass( "ui-state-active" );
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
6589
					}
6590
				})
6591
				// see #8559, we bind to blur here in case the button element loses
6592
				// focus between keydown and keyup, it would be left in an "active" state
6593
				.bind( "keyup" + this.eventNamespace + " blur" + this.eventNamespace, function() {
6594
					$( this ).removeClass( "ui-state-active" );
6595
				});
6596
6597
			if ( this.buttonElement.is("a") ) {
6598
				this.buttonElement.keyup(function(event) {
6599
					if ( event.keyCode === $.ui.keyCode.SPACE ) {
6600
						// TODO pass through original event correctly (just as 2nd argument doesn't work)
6601
						$( this ).click();
6602
					}
6603
				});
6604
			}
6605
		}
6606
6607
		// TODO: pull out $.Widget's handling for the disabled option into
6608
		// $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
6609
		// be overridden by individual plugins
6610
		this._setOption( "disabled", options.disabled );
6611
		this._resetButton();
6612
	},
6613
6614
	_determineButtonType: function() {
6615
		var ancestor, labelSelector, checked;
6616
6617
		if ( this.element.is("[type=checkbox]") ) {
6618
			this.type = "checkbox";
6619
		} else if ( this.element.is("[type=radio]") ) {
6620
			this.type = "radio";
6621
		} else if ( this.element.is("input") ) {
6622
			this.type = "input";
6623
		} else {
6624
			this.type = "button";
6625
		}
6626
6627
		if ( this.type === "checkbox" || this.type === "radio" ) {
6628
			// we don't search against the document in case the element
6629
			// is disconnected from the DOM
6630
			ancestor = this.element.parents().last();
6631
			labelSelector = "label[for='" + this.element.attr("id") + "']";
6632
			this.buttonElement = ancestor.find( labelSelector );
6633
			if ( !this.buttonElement.length ) {
6634
				ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings();
6635
				this.buttonElement = ancestor.filter( labelSelector );
6636
				if ( !this.buttonElement.length ) {
6637
					this.buttonElement = ancestor.find( labelSelector );
6638
				}
6639
			}
6640
			this.element.addClass( "ui-helper-hidden-accessible" );
6641
6642
			checked = this.element.is( ":checked" );
6643
			if ( checked ) {
6644
				this.buttonElement.addClass( "ui-state-active" );
6645
			}
6646
			this.buttonElement.prop( "aria-pressed", checked );
6647
		} else {
6648
			this.buttonElement = this.element;
6649
		}
6650
	},
6651
6652
	widget: function() {
6653
		return this.buttonElement;
6654
	},
6655
6656
	_destroy: function() {
6657
		this.element
6658
			.removeClass( "ui-helper-hidden-accessible" );
6659
		this.buttonElement
6660
			.removeClass( baseClasses + " ui-state-active " + typeClasses )
6661
			.removeAttr( "role" )
6662
			.removeAttr( "aria-pressed" )
6663
			.html( this.buttonElement.find(".ui-button-text").html() );
6664
6665
		if ( !this.hasTitle ) {
6666
			this.buttonElement.removeAttr( "title" );
6667
		}
6668
	},
6669
6670
	_setOption: function( key, value ) {
6671
		this._super( key, value );
6672
		if ( key === "disabled" ) {
6673
			this.element.prop( "disabled", !!value );
6674
			if ( value ) {
6675
				this.buttonElement.removeClass( "ui-state-focus" );
6676
			}
6677
			return;
6678
		}
6679
		this._resetButton();
6680
	},
6681
6682
	refresh: function() {
6683
		//See #8237 & #8828
6684
		var isDisabled = this.element.is( "input, button" ) ? this.element.is( ":disabled" ) : this.element.hasClass( "ui-button-disabled" );
6685
6686
		if ( isDisabled !== this.options.disabled ) {
6687
			this._setOption( "disabled", isDisabled );
6688
		}
6689
		if ( this.type === "radio" ) {
6690
			radioGroup( this.element[0] ).each(function() {
6691
				if ( $( this ).is( ":checked" ) ) {
6692
					$( this ).button( "widget" )
6693
						.addClass( "ui-state-active" )
6694
						.attr( "aria-pressed", "true" );
6695
				} else {
6696
					$( this ).button( "widget" )
6697
						.removeClass( "ui-state-active" )
6698
						.attr( "aria-pressed", "false" );
6699
				}
6700
			});
6701
		} else if ( this.type === "checkbox" ) {
6702
			if ( this.element.is( ":checked" ) ) {
6703
				this.buttonElement
6704
					.addClass( "ui-state-active" )
6705
					.attr( "aria-pressed", "true" );
6706
			} else {
6707
				this.buttonElement
6708
					.removeClass( "ui-state-active" )
6709
					.attr( "aria-pressed", "false" );
6710
			}
6711
		}
6712
	},
6713
6714
	_resetButton: function() {
6715
		if ( this.type === "input" ) {
6716
			if ( this.options.label ) {
6717
				this.element.val( this.options.label );
6718
			}
6719
			return;
6720
		}
6721
		var buttonElement = this.buttonElement.removeClass( typeClasses ),
6722
			buttonText = $( "<span></span>", this.document[0] )
6723
				.addClass( "ui-button-text" )
6724
				.html( this.options.label )
6725
				.appendTo( buttonElement.empty() )
6726
				.text(),
6727
			icons = this.options.icons,
6728
			multipleIcons = icons.primary && icons.secondary,
6729
			buttonClasses = [];
6730
6731
		if ( icons.primary || icons.secondary ) {
6732
			if ( this.options.text ) {
6733
				buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
6734
			}
6735
6736
			if ( icons.primary ) {
6737
				buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
6738
			}
6739
6740
			if ( icons.secondary ) {
6741
				buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
6742
			}
6743
6744
			if ( !this.options.text ) {
6745
				buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" );
6746
6747
				if ( !this.hasTitle ) {
6748
					buttonElement.attr( "title", $.trim( buttonText ) );
6749
				}
6750
			}
6751
		} else {
6752
			buttonClasses.push( "ui-button-text-only" );
6753
		}
6754
		buttonElement.addClass( buttonClasses.join( " " ) );
6755
	}
6756
});
6757
6758
$.widget( "ui.buttonset", {
6759
	version: "1.10.4",
6760
	options: {
6761
		items: "button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)"
6762
	},
6763
6764
	_create: function() {
6765
		this.element.addClass( "ui-buttonset" );
6766
	},
6767
6768
	_init: function() {
6769
		this.refresh();
6770
	},
6771
6772
	_setOption: function( key, value ) {
6773
		if ( key === "disabled" ) {
6774
			this.buttons.button( "option", key, value );
6775
		}
6776
6777
		this._super( key, value );
6778
	},
6779
6780
	refresh: function() {
6781
		var rtl = this.element.css( "direction" ) === "rtl";
6782
6783
		this.buttons = this.element.find( this.options.items )
6784
			.filter( ":ui-button" )
6785
				.button( "refresh" )
6786
			.end()
6787
			.not( ":ui-button" )
6788
				.button()
6789
			.end()
6790
			.map(function() {
6791
				return $( this ).button( "widget" )[ 0 ];
6792
			})
6793
				.removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
6794
				.filter( ":first" )
6795
					.addClass( rtl ? "ui-corner-right" : "ui-corner-left" )
6796
				.end()
6797
				.filter( ":last" )
6798
					.addClass( rtl ? "ui-corner-left" : "ui-corner-right" )
6799
				.end()
6800
			.end();
6801
	},
6802
6803
	_destroy: function() {
6804
		this.element.removeClass( "ui-buttonset" );
6805
		this.buttons
6806
			.map(function() {
6807
				return $( this ).button( "widget" )[ 0 ];
6808
			})
6809
				.removeClass( "ui-corner-left ui-corner-right" )
6810
			.end()
6811
			.button( "destroy" );
6812
	}
6813
});
6814
6815
}( jQuery ) );
6816
(function( $, undefined ) {
6817
6818
$.extend($.ui, { datepicker: { version: "1.10.4" } });
6819
6820
var PROP_NAME = "datepicker",
6821
	instActive;
6822
6823
/* Date picker manager.
6824
   Use the singleton instance of this class, $.datepicker, to interact with the date picker.
6825
   Settings for (groups of) date pickers are maintained in an instance object,
6826
   allowing multiple different settings on the same page. */
6827
6828
function Datepicker() {
6829
	this._curInst = null; // The current instance in use
6830
	this._keyEvent = false; // If the last event was a key event
6831
	this._disabledInputs = []; // List of date picker inputs that have been disabled
6832
	this._datepickerShowing = false; // True if the popup picker is showing , false if not
6833
	this._inDialog = false; // True if showing within a "dialog", false if not
6834
	this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division
6835
	this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class
6836
	this._appendClass = "ui-datepicker-append"; // The name of the append marker class
6837
	this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class
6838
	this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class
6839
	this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class
6840
	this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class
6841
	this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class
6842
	this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class
6843
	this.regional = []; // Available regional settings, indexed by language code
6844
	this.regional[""] = { // Default regional settings
6845
		closeText: "Done", // Display text for close link
6846
		prevText: "Prev", // Display text for previous month link
6847
		nextText: "Next", // Display text for next month link
6848
		currentText: "Today", // Display text for current month link
6849
		monthNames: ["January","February","March","April","May","June",
6850
			"July","August","September","October","November","December"], // Names of months for drop-down and formatting
6851
		monthNamesShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], // For formatting
6852
		dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], // For formatting
6853
		dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], // For formatting
6854
		dayNamesMin: ["Su","Mo","Tu","We","Th","Fr","Sa"], // Column headings for days starting at Sunday
6855
		weekHeader: "Wk", // Column header for week of the year
6856
		dateFormat: "mm/dd/yy", // See format options on parseDate
6857
		firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
6858
		isRTL: false, // True if right-to-left language, false if left-to-right
6859
		showMonthAfterYear: false, // True if the year select precedes month, false for month then year
6860
		yearSuffix: "" // Additional text to append to the year in the month headers
6861
	};
6862
	this._defaults = { // Global defaults for all the date picker instances
6863
		showOn: "focus", // "focus" for popup on focus,
6864
			// "button" for trigger button, or "both" for either
6865
		showAnim: "fadeIn", // Name of jQuery animation for popup
6866
		showOptions: {}, // Options for enhanced animations
6867
		defaultDate: null, // Used when field is blank: actual date,
6868
			// +/-number for offset from today, null for today
6869
		appendText: "", // Display text following the input box, e.g. showing the format
6870
		buttonText: "...", // Text for trigger button
6871
		buttonImage: "", // URL for trigger button image
6872
		buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
6873
		hideIfNoPrevNext: false, // True to hide next/previous month links
6874
			// if not applicable, false to just disable them
6875
		navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
6876
		gotoCurrent: false, // True if today link goes back to current selection instead
6877
		changeMonth: false, // True if month can be selected directly, false if only prev/next
6878
		changeYear: false, // True if year can be selected directly, false if only prev/next
6879
		yearRange: "c-10:c+10", // Range of years to display in drop-down,
6880
			// either relative to today's year (-nn:+nn), relative to currently displayed year
6881
			// (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
6882
		showOtherMonths: false, // True to show dates in other months, false to leave blank
6883
		selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
6884
		showWeek: false, // True to show week of the year, false to not show it
6885
		calculateWeek: this.iso8601Week, // How to calculate the week of the year,
6886
			// takes a Date and returns the number of the week for it
6887
		shortYearCutoff: "+10", // Short year values < this are in the current century,
6888
			// > this are in the previous century,
6889
			// string value starting with "+" for current year + value
6890
		minDate: null, // The earliest selectable date, or null for no limit
6891
		maxDate: null, // The latest selectable date, or null for no limit
6892
		duration: "fast", // Duration of display/closure
6893
		beforeShowDay: null, // Function that takes a date and returns an array with
6894
			// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",
6895
			// [2] = cell title (optional), e.g. $.datepicker.noWeekends
6896
		beforeShow: null, // Function that takes an input field and
6897
			// returns a set of custom settings for the date picker
6898
		onSelect: null, // Define a callback function when a date is selected
6899
		onChangeMonthYear: null, // Define a callback function when the month or year is changed
6900
		onClose: null, // Define a callback function when the datepicker is closed
6901
		numberOfMonths: 1, // Number of months to show at a time
6902
		showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
6903
		stepMonths: 1, // Number of months to step back/forward
6904
		stepBigMonths: 12, // Number of months to step back/forward for the big links
6905
		altField: "", // Selector for an alternate field to store selected dates into
6906
		altFormat: "", // The date format to use for the alternate field
6907
		constrainInput: true, // The input is constrained by the current date format
6908
		showButtonPanel: false, // True to show button panel, false to not show it
6909
		autoSize: false, // True to size the input for the date format, false to leave as is
6910
		disabled: false // The initial disabled state
6911
	};
6912
	$.extend(this._defaults, this.regional[""]);
6913
	this.dpDiv = bindHover($("<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"));
6914
}
6915
6916
$.extend(Datepicker.prototype, {
6917
	/* Class name added to elements to indicate already configured with a date picker. */
6918
	markerClassName: "hasDatepicker",
6919
6920
	//Keep track of the maximum number of rows displayed (see #7043)
6921
	maxRows: 4,
6922
6923
	// TODO rename to "widget" when switching to widget factory
6924
	_widgetDatepicker: function() {
6925
		return this.dpDiv;
6926
	},
6927
6928
	/* Override the default settings for all instances of the date picker.
6929
	 * @param  settings  object - the new settings to use as defaults (anonymous object)
6930
	 * @return the manager object
6931
	 */
6932
	setDefaults: function(settings) {
6933
		extendRemove(this._defaults, settings || {});
6934
		return this;
6935
	},
6936
6937
	/* Attach the date picker to a jQuery selection.
6938
	 * @param  target	element - the target input field or division or span
6939
	 * @param  settings  object - the new settings to use for this date picker instance (anonymous)
6940
	 */
6941
	_attachDatepicker: function(target, settings) {
6942
		var nodeName, inline, inst;
6943
		nodeName = target.nodeName.toLowerCase();
6944
		inline = (nodeName === "div" || nodeName === "span");
6945
		if (!target.id) {
6946
			this.uuid += 1;
6947
			target.id = "dp" + this.uuid;
6948
		}
6949
		inst = this._newInst($(target), inline);
6950
		inst.settings = $.extend({}, settings || {});
6951
		if (nodeName === "input") {
6952
			this._connectDatepicker(target, inst);
6953
		} else if (inline) {
6954
			this._inlineDatepicker(target, inst);
6955
		}
6956
	},
6957
6958
	/* Create a new instance object. */
6959
	_newInst: function(target, inline) {
6960
		var id = target[0].id.replace(/([^A-Za-z0-9_\-])/g, "\\\\$1"); // escape jQuery meta chars
6961
		return {id: id, input: target, // associated target
6962
			selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
6963
			drawMonth: 0, drawYear: 0, // month being drawn
6964
			inline: inline, // is datepicker inline or not
6965
			dpDiv: (!inline ? this.dpDiv : // presentation div
6966
			bindHover($("<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")))};
6967
	},
6968
6969
	/* Attach the date picker to an input field. */
6970
	_connectDatepicker: function(target, inst) {
6971
		var input = $(target);
6972
		inst.append = $([]);
6973
		inst.trigger = $([]);
6974
		if (input.hasClass(this.markerClassName)) {
6975
			return;
6976
		}
6977
		this._attachments(input, inst);
6978
		input.addClass(this.markerClassName).keydown(this._doKeyDown).
6979
			keypress(this._doKeyPress).keyup(this._doKeyUp);
6980
		this._autoSize(inst);
6981
		$.data(target, PROP_NAME, inst);
6982
		//If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
6983
		if( inst.settings.disabled ) {
6984
			this._disableDatepicker( target );
6985
		}
6986
	},
6987
6988
	/* Make attachments based on settings. */
6989
	_attachments: function(input, inst) {
6990
		var showOn, buttonText, buttonImage,
6991
			appendText = this._get(inst, "appendText"),
6992
			isRTL = this._get(inst, "isRTL");
6993
6994
		if (inst.append) {
6995
			inst.append.remove();
6996
		}
6997
		if (appendText) {
6998
			inst.append = $("<span class='" + this._appendClass + "'>" + appendText + "</span>");
6999
			input[isRTL ? "before" : "after"](inst.append);
7000
		}
7001
7002
		input.unbind("focus", this._showDatepicker);
7003
7004
		if (inst.trigger) {
7005
			inst.trigger.remove();
7006
		}
7007
7008
		showOn = this._get(inst, "showOn");
7009
		if (showOn === "focus" || showOn === "both") { // pop-up date picker when in the marked field
7010
			input.focus(this._showDatepicker);
7011
		}
7012
		if (showOn === "button" || showOn === "both") { // pop-up date picker when button clicked
7013
			buttonText = this._get(inst, "buttonText");
7014
			buttonImage = this._get(inst, "buttonImage");
7015
			inst.trigger = $(this._get(inst, "buttonImageOnly") ?
7016
				$("<img/>").addClass(this._triggerClass).
7017
					attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
7018
				$("<button type='button'></button>").addClass(this._triggerClass).
7019
					html(!buttonImage ? buttonText : $("<img/>").attr(
7020
					{ src:buttonImage, alt:buttonText, title:buttonText })));
7021
			input[isRTL ? "before" : "after"](inst.trigger);
7022
			inst.trigger.click(function() {
7023
				if ($.datepicker._datepickerShowing && $.datepicker._lastInput === input[0]) {
7024
					$.datepicker._hideDatepicker();
7025
				} else if ($.datepicker._datepickerShowing && $.datepicker._lastInput !== input[0]) {
7026
					$.datepicker._hideDatepicker();
7027
					$.datepicker._showDatepicker(input[0]);
7028
				} else {
7029
					$.datepicker._showDatepicker(input[0]);
7030
				}
7031
				return false;
7032
			});
7033
		}
7034
	},
7035
7036
	/* Apply the maximum length for the date format. */
7037
	_autoSize: function(inst) {
7038
		if (this._get(inst, "autoSize") && !inst.inline) {
7039
			var findMax, max, maxI, i,
7040
				date = new Date(2009, 12 - 1, 20), // Ensure double digits
7041
				dateFormat = this._get(inst, "dateFormat");
7042
7043
			if (dateFormat.match(/[DM]/)) {
7044
				findMax = function(names) {
7045
					max = 0;
7046
					maxI = 0;
7047
					for (i = 0; i < names.length; i++) {
0 ignored issues
show
Bug introduced by
The variable i is changed as part of the for loop for example by i++ on line 7047. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
7048
						if (names[i].length > max) {
0 ignored issues
show
Bug introduced by
The variable max is changed as part of the for loop for example by names.i.length on line 7049. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
7049
							max = names[i].length;
7050
							maxI = i;
7051
						}
7052
					}
7053
					return maxI;
7054
				};
7055
				date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
7056
					"monthNames" : "monthNamesShort"))));
7057
				date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
7058
					"dayNames" : "dayNamesShort"))) + 20 - date.getDay());
7059
			}
7060
			inst.input.attr("size", this._formatDate(inst, date).length);
7061
		}
7062
	},
7063
7064
	/* Attach an inline date picker to a div. */
7065
	_inlineDatepicker: function(target, inst) {
7066
		var divSpan = $(target);
7067
		if (divSpan.hasClass(this.markerClassName)) {
7068
			return;
7069
		}
7070
		divSpan.addClass(this.markerClassName).append(inst.dpDiv);
7071
		$.data(target, PROP_NAME, inst);
7072
		this._setDate(inst, this._getDefaultDate(inst), true);
7073
		this._updateDatepicker(inst);
7074
		this._updateAlternate(inst);
7075
		//If disabled option is true, disable the datepicker before showing it (see ticket #5665)
7076
		if( inst.settings.disabled ) {
7077
			this._disableDatepicker( target );
7078
		}
7079
		// Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
7080
		// http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
7081
		inst.dpDiv.css( "display", "block" );
7082
	},
7083
7084
	/* Pop-up the date picker in a "dialog" box.
7085
	 * @param  input element - ignored
7086
	 * @param  date	string or Date - the initial date to display
7087
	 * @param  onSelect  function - the function to call when a date is selected
7088
	 * @param  settings  object - update the dialog date picker instance's settings (anonymous object)
7089
	 * @param  pos int[2] - coordinates for the dialog's position within the screen or
7090
	 *					event - with x/y coordinates or
7091
	 *					leave empty for default (screen centre)
7092
	 * @return the manager object
7093
	 */
7094
	_dialogDatepicker: function(input, date, onSelect, settings, pos) {
7095
		var id, browserWidth, browserHeight, scrollX, scrollY,
7096
			inst = this._dialogInst; // internal instance
7097
7098
		if (!inst) {
7099
			this.uuid += 1;
7100
			id = "dp" + this.uuid;
7101
			this._dialogInput = $("<input type='text' id='" + id +
7102
				"' style='position: absolute; top: -100px; width: 0px;'/>");
7103
			this._dialogInput.keydown(this._doKeyDown);
7104
			$("body").append(this._dialogInput);
7105
			inst = this._dialogInst = this._newInst(this._dialogInput, false);
7106
			inst.settings = {};
7107
			$.data(this._dialogInput[0], PROP_NAME, inst);
7108
		}
7109
		extendRemove(inst.settings, settings || {});
7110
		date = (date && date.constructor === Date ? this._formatDate(inst, date) : date);
7111
		this._dialogInput.val(date);
7112
7113
		this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
7114
		if (!this._pos) {
7115
			browserWidth = document.documentElement.clientWidth;
7116
			browserHeight = document.documentElement.clientHeight;
7117
			scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
7118
			scrollY = document.documentElement.scrollTop || document.body.scrollTop;
7119
			this._pos = // should use actual width/height below
7120
				[(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
7121
		}
7122
7123
		// move input on screen for focus, but hidden behind dialog
7124
		this._dialogInput.css("left", (this._pos[0] + 20) + "px").css("top", this._pos[1] + "px");
7125
		inst.settings.onSelect = onSelect;
7126
		this._inDialog = true;
7127
		this.dpDiv.addClass(this._dialogClass);
7128
		this._showDatepicker(this._dialogInput[0]);
7129
		if ($.blockUI) {
7130
			$.blockUI(this.dpDiv);
7131
		}
7132
		$.data(this._dialogInput[0], PROP_NAME, inst);
7133
		return this;
7134
	},
7135
7136
	/* Detach a datepicker from its control.
7137
	 * @param  target	element - the target input field or division or span
7138
	 */
7139
	_destroyDatepicker: function(target) {
7140
		var nodeName,
7141
			$target = $(target),
7142
			inst = $.data(target, PROP_NAME);
7143
7144
		if (!$target.hasClass(this.markerClassName)) {
7145
			return;
7146
		}
7147
7148
		nodeName = target.nodeName.toLowerCase();
7149
		$.removeData(target, PROP_NAME);
7150
		if (nodeName === "input") {
7151
			inst.append.remove();
7152
			inst.trigger.remove();
7153
			$target.removeClass(this.markerClassName).
7154
				unbind("focus", this._showDatepicker).
7155
				unbind("keydown", this._doKeyDown).
7156
				unbind("keypress", this._doKeyPress).
7157
				unbind("keyup", this._doKeyUp);
7158
		} else if (nodeName === "div" || nodeName === "span") {
7159
			$target.removeClass(this.markerClassName).empty();
7160
		}
7161
	},
7162
7163
	/* Enable the date picker to a jQuery selection.
7164
	 * @param  target	element - the target input field or division or span
7165
	 */
7166
	_enableDatepicker: function(target) {
7167
		var nodeName, inline,
7168
			$target = $(target),
7169
			inst = $.data(target, PROP_NAME);
7170
7171
		if (!$target.hasClass(this.markerClassName)) {
7172
			return;
7173
		}
7174
7175
		nodeName = target.nodeName.toLowerCase();
7176
		if (nodeName === "input") {
7177
			target.disabled = false;
7178
			inst.trigger.filter("button").
7179
				each(function() { this.disabled = false; }).end().
7180
				filter("img").css({opacity: "1.0", cursor: ""});
7181
		} else if (nodeName === "div" || nodeName === "span") {
7182
			inline = $target.children("." + this._inlineClass);
7183
			inline.children().removeClass("ui-state-disabled");
7184
			inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
7185
				prop("disabled", false);
7186
		}
7187
		this._disabledInputs = $.map(this._disabledInputs,
7188
			function(value) { return (value === target ? null : value); }); // delete entry
7189
	},
7190
7191
	/* Disable the date picker to a jQuery selection.
7192
	 * @param  target	element - the target input field or division or span
7193
	 */
7194
	_disableDatepicker: function(target) {
7195
		var nodeName, inline,
7196
			$target = $(target),
7197
			inst = $.data(target, PROP_NAME);
7198
7199
		if (!$target.hasClass(this.markerClassName)) {
7200
			return;
7201
		}
7202
7203
		nodeName = target.nodeName.toLowerCase();
7204
		if (nodeName === "input") {
7205
			target.disabled = true;
7206
			inst.trigger.filter("button").
7207
				each(function() { this.disabled = true; }).end().
7208
				filter("img").css({opacity: "0.5", cursor: "default"});
7209
		} else if (nodeName === "div" || nodeName === "span") {
7210
			inline = $target.children("." + this._inlineClass);
7211
			inline.children().addClass("ui-state-disabled");
7212
			inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
7213
				prop("disabled", true);
7214
		}
7215
		this._disabledInputs = $.map(this._disabledInputs,
7216
			function(value) { return (value === target ? null : value); }); // delete entry
7217
		this._disabledInputs[this._disabledInputs.length] = target;
7218
	},
7219
7220
	/* Is the first field in a jQuery collection disabled as a datepicker?
7221
	 * @param  target	element - the target input field or division or span
7222
	 * @return boolean - true if disabled, false if enabled
7223
	 */
7224
	_isDisabledDatepicker: function(target) {
7225
		if (!target) {
7226
			return false;
7227
		}
7228
		for (var i = 0; i < this._disabledInputs.length; i++) {
7229
			if (this._disabledInputs[i] === target) {
7230
				return true;
7231
			}
7232
		}
7233
		return false;
7234
	},
7235
7236
	/* Retrieve the instance data for the target control.
7237
	 * @param  target  element - the target input field or division or span
7238
	 * @return  object - the associated instance data
7239
	 * @throws  error if a jQuery problem getting data
7240
	 */
7241
	_getInst: function(target) {
7242
		try {
7243
			return $.data(target, PROP_NAME);
7244
		}
7245
		catch (err) {
7246
			throw "Missing instance data for this datepicker";
7247
		}
7248
	},
7249
7250
	/* Update or retrieve the settings for a date picker attached to an input field or division.
7251
	 * @param  target  element - the target input field or division or span
7252
	 * @param  name	object - the new settings to update or
7253
	 *				string - the name of the setting to change or retrieve,
7254
	 *				when retrieving also "all" for all instance settings or
7255
	 *				"defaults" for all global defaults
7256
	 * @param  value   any - the new value for the setting
7257
	 *				(omit if above is an object or to retrieve a value)
7258
	 */
7259
	_optionDatepicker: function(target, name, value) {
7260
		var settings, date, minDate, maxDate,
7261
			inst = this._getInst(target);
7262
7263
		if (arguments.length === 2 && typeof name === "string") {
7264
			return (name === "defaults" ? $.extend({}, $.datepicker._defaults) :
7265
				(inst ? (name === "all" ? $.extend({}, inst.settings) :
7266
				this._get(inst, name)) : null));
7267
		}
7268
7269
		settings = name || {};
7270
		if (typeof name === "string") {
7271
			settings = {};
7272
			settings[name] = value;
7273
		}
7274
7275
		if (inst) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if inst is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
7276
			if (this._curInst === inst) {
7277
				this._hideDatepicker();
7278
			}
7279
7280
			date = this._getDateDatepicker(target, true);
7281
			minDate = this._getMinMaxDate(inst, "min");
7282
			maxDate = this._getMinMaxDate(inst, "max");
7283
			extendRemove(inst.settings, settings);
7284
			// reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
7285
			if (minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined) {
7286
				inst.settings.minDate = this._formatDate(inst, minDate);
7287
			}
7288
			if (maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined) {
7289
				inst.settings.maxDate = this._formatDate(inst, maxDate);
7290
			}
7291
			if ( "disabled" in settings ) {
7292
				if ( settings.disabled ) {
7293
					this._disableDatepicker(target);
7294
				} else {
7295
					this._enableDatepicker(target);
7296
				}
7297
			}
7298
			this._attachments($(target), inst);
7299
			this._autoSize(inst);
7300
			this._setDate(inst, date);
7301
			this._updateAlternate(inst);
7302
			this._updateDatepicker(inst);
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
7303
		}
7304
	},
7305
7306
	// change method deprecated
7307
	_changeDatepicker: function(target, name, value) {
7308
		this._optionDatepicker(target, name, value);
7309
	},
7310
7311
	/* Redraw the date picker attached to an input field or division.
7312
	 * @param  target  element - the target input field or division or span
7313
	 */
7314
	_refreshDatepicker: function(target) {
7315
		var inst = this._getInst(target);
7316
		if (inst) {
7317
			this._updateDatepicker(inst);
7318
		}
7319
	},
7320
7321
	/* Set the dates for a jQuery selection.
7322
	 * @param  target element - the target input field or division or span
7323
	 * @param  date	Date - the new date
7324
	 */
7325
	_setDateDatepicker: function(target, date) {
7326
		var inst = this._getInst(target);
7327
		if (inst) {
7328
			this._setDate(inst, date);
7329
			this._updateDatepicker(inst);
7330
			this._updateAlternate(inst);
7331
		}
7332
	},
7333
7334
	/* Get the date(s) for the first entry in a jQuery selection.
7335
	 * @param  target element - the target input field or division or span
7336
	 * @param  noDefault boolean - true if no default date is to be used
7337
	 * @return Date - the current date
7338
	 */
7339
	_getDateDatepicker: function(target, noDefault) {
7340
		var inst = this._getInst(target);
7341
		if (inst && !inst.inline) {
7342
			this._setDateFromField(inst, noDefault);
7343
		}
7344
		return (inst ? this._getDate(inst) : null);
7345
	},
7346
7347
	/* Handle keystrokes. */
7348
	_doKeyDown: function(event) {
7349
		var onSelect, dateStr, sel,
7350
			inst = $.datepicker._getInst(event.target),
7351
			handled = true,
7352
			isRTL = inst.dpDiv.is(".ui-datepicker-rtl");
7353
7354
		inst._keyEvent = true;
7355
		if ($.datepicker._datepickerShowing) {
7356
			switch (event.keyCode) {
7357
				case 9: $.datepicker._hideDatepicker();
7358
						handled = false;
7359
						break; // hide on tab out
7360
				case 13: sel = $("td." + $.datepicker._dayOverClass + ":not(." +
7361
									$.datepicker._currentClass + ")", inst.dpDiv);
7362
						if (sel[0]) {
7363
							$.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
7364
						}
7365
7366
						onSelect = $.datepicker._get(inst, "onSelect");
7367
						if (onSelect) {
7368
							dateStr = $.datepicker._formatDate(inst);
7369
7370
							// trigger custom callback
7371
							onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);
7372
						} else {
7373
							$.datepicker._hideDatepicker();
7374
						}
7375
7376
						return false; // don't submit the form
7377
				case 27: $.datepicker._hideDatepicker();
7378
						break; // hide on escape
7379
				case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
7380
							-$.datepicker._get(inst, "stepBigMonths") :
7381
							-$.datepicker._get(inst, "stepMonths")), "M");
7382
						break; // previous month/year on page up/+ ctrl
7383
				case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
7384
							+$.datepicker._get(inst, "stepBigMonths") :
7385
							+$.datepicker._get(inst, "stepMonths")), "M");
7386
						break; // next month/year on page down/+ ctrl
7387
				case 35: if (event.ctrlKey || event.metaKey) {
7388
							$.datepicker._clearDate(event.target);
7389
						}
7390
						handled = event.ctrlKey || event.metaKey;
7391
						break; // clear on ctrl or command +end
7392
				case 36: if (event.ctrlKey || event.metaKey) {
7393
							$.datepicker._gotoToday(event.target);
7394
						}
7395
						handled = event.ctrlKey || event.metaKey;
7396
						break; // current on ctrl or command +home
7397
				case 37: if (event.ctrlKey || event.metaKey) {
7398
							$.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), "D");
7399
						}
7400
						handled = event.ctrlKey || event.metaKey;
7401
						// -1 day on ctrl or command +left
7402
						if (event.originalEvent.altKey) {
7403
							$.datepicker._adjustDate(event.target, (event.ctrlKey ?
7404
								-$.datepicker._get(inst, "stepBigMonths") :
7405
								-$.datepicker._get(inst, "stepMonths")), "M");
7406
						}
7407
						// next month/year on alt +left on Mac
7408
						break;
7409
				case 38: if (event.ctrlKey || event.metaKey) {
7410
							$.datepicker._adjustDate(event.target, -7, "D");
7411
						}
7412
						handled = event.ctrlKey || event.metaKey;
7413
						break; // -1 week on ctrl or command +up
7414
				case 39: if (event.ctrlKey || event.metaKey) {
7415
							$.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), "D");
7416
						}
7417
						handled = event.ctrlKey || event.metaKey;
7418
						// +1 day on ctrl or command +right
7419
						if (event.originalEvent.altKey) {
7420
							$.datepicker._adjustDate(event.target, (event.ctrlKey ?
7421
								+$.datepicker._get(inst, "stepBigMonths") :
7422
								+$.datepicker._get(inst, "stepMonths")), "M");
7423
						}
7424
						// next month/year on alt +right
7425
						break;
7426
				case 40: if (event.ctrlKey || event.metaKey) {
7427
							$.datepicker._adjustDate(event.target, +7, "D");
7428
						}
7429
						handled = event.ctrlKey || event.metaKey;
7430
						break; // +1 week on ctrl or command +down
7431
				default: handled = false;
7432
			}
7433
		} else if (event.keyCode === 36 && event.ctrlKey) { // display the date picker on ctrl+home
7434
			$.datepicker._showDatepicker(this);
7435
		} else {
7436
			handled = false;
7437
		}
7438
7439
		if (handled) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if handled is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
7440
			event.preventDefault();
7441
			event.stopPropagation();
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
7442
		}
7443
	},
7444
7445
	/* Filter entered characters - based on date format. */
7446
	_doKeyPress: function(event) {
7447
		var chars, chr,
7448
			inst = $.datepicker._getInst(event.target);
7449
7450
		if ($.datepicker._get(inst, "constrainInput")) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if $.datepicker._get(inst, "constrainInput") is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
7451
			chars = $.datepicker._possibleChars($.datepicker._get(inst, "dateFormat"));
7452
			chr = String.fromCharCode(event.charCode == null ? event.keyCode : event.charCode);
7453
			return event.ctrlKey || event.metaKey || (chr < " " || !chars || chars.indexOf(chr) > -1);
7454
		}
7455
	},
7456
7457
	/* Synchronise manual entry and field/alternate field. */
7458
	_doKeyUp: function(event) {
7459
		var date,
7460
			inst = $.datepicker._getInst(event.target);
7461
7462
		if (inst.input.val() !== inst.lastVal) {
7463
			try {
7464
				date = $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
7465
					(inst.input ? inst.input.val() : null),
7466
					$.datepicker._getFormatConfig(inst));
7467
7468
				if (date) { // only if valid
7469
					$.datepicker._setDateFromField(inst);
7470
					$.datepicker._updateAlternate(inst);
7471
					$.datepicker._updateDatepicker(inst);
7472
				}
7473
			}
7474
			catch (err) {
0 ignored issues
show
Coding Style Comprehensibility Best Practice introduced by
Empty catch clauses should be used with caution; consider adding a comment why this is needed.
Loading history...
7475
			}
7476
		}
7477
		return true;
7478
	},
7479
7480
	/* Pop-up the date picker for a given input field.
7481
	 * If false returned from beforeShow event handler do not show.
7482
	 * @param  input  element - the input field attached to the date picker or
7483
	 *					event - if triggered by focus
7484
	 */
7485
	_showDatepicker: function(input) {
7486
		input = input.target || input;
7487
		if (input.nodeName.toLowerCase() !== "input") { // find from button/image trigger
7488
			input = $("input", input.parentNode)[0];
7489
		}
7490
7491
		if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput === input) { // already here
7492
			return;
7493
		}
7494
7495
		var inst, beforeShow, beforeShowSettings, isFixed,
7496
			offset, showAnim, duration;
7497
7498
		inst = $.datepicker._getInst(input);
7499
		if ($.datepicker._curInst && $.datepicker._curInst !== inst) {
7500
			$.datepicker._curInst.dpDiv.stop(true, true);
7501
			if ( inst && $.datepicker._datepickerShowing ) {
7502
				$.datepicker._hideDatepicker( $.datepicker._curInst.input[0] );
7503
			}
7504
		}
7505
7506
		beforeShow = $.datepicker._get(inst, "beforeShow");
7507
		beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {};
7508
		if(beforeShowSettings === false){
7509
			return;
7510
		}
7511
		extendRemove(inst.settings, beforeShowSettings);
7512
7513
		inst.lastVal = null;
7514
		$.datepicker._lastInput = input;
7515
		$.datepicker._setDateFromField(inst);
7516
7517
		if ($.datepicker._inDialog) { // hide cursor
7518
			input.value = "";
7519
		}
7520
		if (!$.datepicker._pos) { // position below input
7521
			$.datepicker._pos = $.datepicker._findPos(input);
7522
			$.datepicker._pos[1] += input.offsetHeight; // add the height
7523
		}
7524
7525
		isFixed = false;
7526
		$(input).parents().each(function() {
7527
			isFixed |= $(this).css("position") === "fixed";
7528
			return !isFixed;
7529
		});
7530
7531
		offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
7532
		$.datepicker._pos = null;
7533
		//to avoid flashes on Firefox
7534
		inst.dpDiv.empty();
7535
		// determine sizing offscreen
7536
		inst.dpDiv.css({position: "absolute", display: "block", top: "-1000px"});
7537
		$.datepicker._updateDatepicker(inst);
7538
		// fix width for dynamic number of date pickers
7539
		// and adjust position before showing
7540
		offset = $.datepicker._checkOffset(inst, offset, isFixed);
7541
		inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
7542
			"static" : (isFixed ? "fixed" : "absolute")), display: "none",
7543
			left: offset.left + "px", top: offset.top + "px"});
7544
7545
		if (!inst.inline) {
7546
			showAnim = $.datepicker._get(inst, "showAnim");
7547
			duration = $.datepicker._get(inst, "duration");
7548
			inst.dpDiv.zIndex($(input).zIndex()+1);
7549
			$.datepicker._datepickerShowing = true;
7550
7551
			if ( $.effects && $.effects.effect[ showAnim ] ) {
7552
				inst.dpDiv.show(showAnim, $.datepicker._get(inst, "showOptions"), duration);
7553
			} else {
7554
				inst.dpDiv[showAnim || "show"](showAnim ? duration : null);
7555
			}
7556
7557
			if ( $.datepicker._shouldFocusInput( inst ) ) {
7558
				inst.input.focus();
7559
			}
7560
7561
			$.datepicker._curInst = inst;
7562
		}
7563
	},
7564
7565
	/* Generate the date picker content. */
7566
	_updateDatepicker: function(inst) {
7567
		this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
7568
		instActive = inst; // for delegate hover events
7569
		inst.dpDiv.empty().append(this._generateHTML(inst));
7570
		this._attachHandlers(inst);
7571
		inst.dpDiv.find("." + this._dayOverClass + " a").mouseover();
7572
7573
		var origyearshtml,
7574
			numMonths = this._getNumberOfMonths(inst),
7575
			cols = numMonths[1],
7576
			width = 17;
7577
7578
		inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");
7579
		if (cols > 1) {
7580
			inst.dpDiv.addClass("ui-datepicker-multi-" + cols).css("width", (width * cols) + "em");
7581
		}
7582
		inst.dpDiv[(numMonths[0] !== 1 || numMonths[1] !== 1 ? "add" : "remove") +
7583
			"Class"]("ui-datepicker-multi");
7584
		inst.dpDiv[(this._get(inst, "isRTL") ? "add" : "remove") +
7585
			"Class"]("ui-datepicker-rtl");
7586
7587
		if (inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {
7588
			inst.input.focus();
7589
		}
7590
7591
		// deffered render of the years select (to avoid flashes on Firefox)
7592
		if( inst.yearshtml ){
7593
			origyearshtml = inst.yearshtml;
7594
			setTimeout(function(){
7595
				//assure that inst.yearshtml didn't change.
7596
				if( origyearshtml === inst.yearshtml && inst.yearshtml ){
7597
					inst.dpDiv.find("select.ui-datepicker-year:first").replaceWith(inst.yearshtml);
7598
				}
7599
				origyearshtml = inst.yearshtml = null;
7600
			}, 0);
7601
		}
7602
	},
7603
7604
	// #6694 - don't focus the input if it's already focused
7605
	// this breaks the change event in IE
7606
	// Support: IE and jQuery <1.9
7607
	_shouldFocusInput: function( inst ) {
7608
		return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" );
7609
	},
7610
7611
	/* Check positioning to remain on screen. */
7612
	_checkOffset: function(inst, offset, isFixed) {
7613
		var dpWidth = inst.dpDiv.outerWidth(),
7614
			dpHeight = inst.dpDiv.outerHeight(),
7615
			inputWidth = inst.input ? inst.input.outerWidth() : 0,
7616
			inputHeight = inst.input ? inst.input.outerHeight() : 0,
7617
			viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft()),
7618
			viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop());
7619
7620
		offset.left -= (this._get(inst, "isRTL") ? (dpWidth - inputWidth) : 0);
7621
		offset.left -= (isFixed && offset.left === inst.input.offset().left) ? $(document).scrollLeft() : 0;
7622
		offset.top -= (isFixed && offset.top === (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
7623
7624
		// now check if datepicker is showing outside window viewport - move to a better place if so.
7625
		offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
7626
			Math.abs(offset.left + dpWidth - viewWidth) : 0);
7627
		offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
7628
			Math.abs(dpHeight + inputHeight) : 0);
7629
7630
		return offset;
7631
	},
7632
7633
	/* Find an object's position on the screen. */
7634
	_findPos: function(obj) {
7635
		var position,
7636
			inst = this._getInst(obj),
7637
			isRTL = this._get(inst, "isRTL");
7638
7639
		while (obj && (obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden(obj))) {
7640
			obj = obj[isRTL ? "previousSibling" : "nextSibling"];
7641
		}
7642
7643
		position = $(obj).offset();
7644
		return [position.left, position.top];
7645
	},
7646
7647
	/* Hide the date picker from view.
7648
	 * @param  input  element - the input field attached to the date picker
7649
	 */
7650
	_hideDatepicker: function(input) {
7651
		var showAnim, duration, postProcess, onClose,
7652
			inst = this._curInst;
7653
7654
		if (!inst || (input && inst !== $.data(input, PROP_NAME))) {
7655
			return;
7656
		}
7657
7658
		if (this._datepickerShowing) {
7659
			showAnim = this._get(inst, "showAnim");
7660
			duration = this._get(inst, "duration");
7661
			postProcess = function() {
7662
				$.datepicker._tidyDialog(inst);
7663
			};
7664
7665
			// DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
7666
			if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) {
7667
				inst.dpDiv.hide(showAnim, $.datepicker._get(inst, "showOptions"), duration, postProcess);
7668
			} else {
7669
				inst.dpDiv[(showAnim === "slideDown" ? "slideUp" :
7670
					(showAnim === "fadeIn" ? "fadeOut" : "hide"))]((showAnim ? duration : null), postProcess);
7671
			}
7672
7673
			if (!showAnim) {
7674
				postProcess();
7675
			}
7676
			this._datepickerShowing = false;
7677
7678
			onClose = this._get(inst, "onClose");
7679
			if (onClose) {
7680
				onClose.apply((inst.input ? inst.input[0] : null), [(inst.input ? inst.input.val() : ""), inst]);
7681
			}
7682
7683
			this._lastInput = null;
7684
			if (this._inDialog) {
7685
				this._dialogInput.css({ position: "absolute", left: "0", top: "-100px" });
7686
				if ($.blockUI) {
7687
					$.unblockUI();
7688
					$("body").append(this.dpDiv);
7689
				}
7690
			}
7691
			this._inDialog = false;
7692
		}
7693
	},
7694
7695
	/* Tidy up after a dialog display. */
7696
	_tidyDialog: function(inst) {
7697
		inst.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar");
7698
	},
7699
7700
	/* Close date picker if clicked elsewhere. */
7701
	_checkExternalClick: function(event) {
7702
		if (!$.datepicker._curInst) {
7703
			return;
7704
		}
7705
7706
		var $target = $(event.target),
7707
			inst = $.datepicker._getInst($target[0]);
7708
7709
		if ( ( ( $target[0].id !== $.datepicker._mainDivId &&
7710
				$target.parents("#" + $.datepicker._mainDivId).length === 0 &&
7711
				!$target.hasClass($.datepicker.markerClassName) &&
7712
				!$target.closest("." + $.datepicker._triggerClass).length &&
7713
				$.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) ||
7714
			( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst !== inst ) ) {
7715
				$.datepicker._hideDatepicker();
7716
		}
7717
	},
7718
7719
	/* Adjust one of the date sub-fields. */
7720
	_adjustDate: function(id, offset, period) {
7721
		var target = $(id),
7722
			inst = this._getInst(target[0]);
7723
7724
		if (this._isDisabledDatepicker(target[0])) {
7725
			return;
7726
		}
7727
		this._adjustInstDate(inst, offset +
7728
			(period === "M" ? this._get(inst, "showCurrentAtPos") : 0), // undo positioning
7729
			period);
7730
		this._updateDatepicker(inst);
7731
	},
7732
7733
	/* Action for current link. */
7734
	_gotoToday: function(id) {
7735
		var date,
7736
			target = $(id),
7737
			inst = this._getInst(target[0]);
7738
7739
		if (this._get(inst, "gotoCurrent") && inst.currentDay) {
7740
			inst.selectedDay = inst.currentDay;
7741
			inst.drawMonth = inst.selectedMonth = inst.currentMonth;
7742
			inst.drawYear = inst.selectedYear = inst.currentYear;
7743
		} else {
7744
			date = new Date();
7745
			inst.selectedDay = date.getDate();
7746
			inst.drawMonth = inst.selectedMonth = date.getMonth();
7747
			inst.drawYear = inst.selectedYear = date.getFullYear();
7748
		}
7749
		this._notifyChange(inst);
7750
		this._adjustDate(target);
7751
	},
7752
7753
	/* Action for selecting a new month/year. */
7754
	_selectMonthYear: function(id, select, period) {
7755
		var target = $(id),
7756
			inst = this._getInst(target[0]);
7757
7758
		inst["selected" + (period === "M" ? "Month" : "Year")] =
7759
		inst["draw" + (period === "M" ? "Month" : "Year")] =
7760
			parseInt(select.options[select.selectedIndex].value,10);
7761
7762
		this._notifyChange(inst);
7763
		this._adjustDate(target);
7764
	},
7765
7766
	/* Action for selecting a day. */
7767
	_selectDay: function(id, month, year, td) {
7768
		var inst,
7769
			target = $(id);
7770
7771
		if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
7772
			return;
7773
		}
7774
7775
		inst = this._getInst(target[0]);
7776
		inst.selectedDay = inst.currentDay = $("a", td).html();
7777
		inst.selectedMonth = inst.currentMonth = month;
7778
		inst.selectedYear = inst.currentYear = year;
7779
		this._selectDate(id, this._formatDate(inst,
7780
			inst.currentDay, inst.currentMonth, inst.currentYear));
7781
	},
7782
7783
	/* Erase the input field and hide the date picker. */
7784
	_clearDate: function(id) {
7785
		var target = $(id);
7786
		this._selectDate(target, "");
7787
	},
7788
7789
	/* Update the input field with the selected date. */
7790
	_selectDate: function(id, dateStr) {
7791
		var onSelect,
7792
			target = $(id),
7793
			inst = this._getInst(target[0]);
7794
7795
		dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
7796
		if (inst.input) {
7797
			inst.input.val(dateStr);
7798
		}
7799
		this._updateAlternate(inst);
7800
7801
		onSelect = this._get(inst, "onSelect");
7802
		if (onSelect) {
7803
			onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);  // trigger custom callback
7804
		} else if (inst.input) {
7805
			inst.input.trigger("change"); // fire the change event
7806
		}
7807
7808
		if (inst.inline){
7809
			this._updateDatepicker(inst);
7810
		} else {
7811
			this._hideDatepicker();
7812
			this._lastInput = inst.input[0];
7813
			if (typeof(inst.input[0]) !== "object") {
7814
				inst.input.focus(); // restore focus
7815
			}
7816
			this._lastInput = null;
7817
		}
7818
	},
7819
7820
	/* Update any alternate field to synchronise with the main field. */
7821
	_updateAlternate: function(inst) {
7822
		var altFormat, date, dateStr,
7823
			altField = this._get(inst, "altField");
7824
7825
		if (altField) { // update alternate field too
7826
			altFormat = this._get(inst, "altFormat") || this._get(inst, "dateFormat");
7827
			date = this._getDate(inst);
7828
			dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
7829
			$(altField).each(function() { $(this).val(dateStr); });
7830
		}
7831
	},
7832
7833
	/* Set as beforeShowDay function to prevent selection of weekends.
7834
	 * @param  date  Date - the date to customise
7835
	 * @return [boolean, string] - is this date selectable?, what is its CSS class?
7836
	 */
7837
	noWeekends: function(date) {
7838
		var day = date.getDay();
7839
		return [(day > 0 && day < 6), ""];
7840
	},
7841
7842
	/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
7843
	 * @param  date  Date - the date to get the week for
7844
	 * @return  number - the number of the week within the year that contains this date
7845
	 */
7846
	iso8601Week: function(date) {
7847
		var time,
7848
			checkDate = new Date(date.getTime());
7849
7850
		// Find Thursday of this week starting on Monday
7851
		checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
7852
7853
		time = checkDate.getTime();
7854
		checkDate.setMonth(0); // Compare with Jan 1
7855
		checkDate.setDate(1);
7856
		return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
7857
	},
7858
7859
	/* Parse a string value into a date object.
7860
	 * See formatDate below for the possible formats.
7861
	 *
7862
	 * @param  format string - the expected format of the date
7863
	 * @param  value string - the date in the above format
7864
	 * @param  settings Object - attributes include:
7865
	 *					shortYearCutoff  number - the cutoff year for determining the century (optional)
7866
	 *					dayNamesShort	string[7] - abbreviated names of the days from Sunday (optional)
7867
	 *					dayNames		string[7] - names of the days from Sunday (optional)
7868
	 *					monthNamesShort string[12] - abbreviated names of the months (optional)
7869
	 *					monthNames		string[12] - names of the months (optional)
7870
	 * @return  Date - the extracted date value or null if value is blank
7871
	 */
7872
	parseDate: function (format, value, settings) {
7873
		if (format == null || value == null) {
7874
			throw "Invalid arguments";
7875
		}
7876
7877
		value = (typeof value === "object" ? value.toString() : value + "");
7878
		if (value === "") {
7879
			return null;
7880
		}
7881
7882
		var iFormat, dim, extra,
7883
			iValue = 0,
7884
			shortYearCutoffTemp = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff,
7885
			shortYearCutoff = (typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp :
7886
				new Date().getFullYear() % 100 + parseInt(shortYearCutoffTemp, 10)),
7887
			dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
7888
			dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
7889
			monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
7890
			monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
7891
			year = -1,
7892
			month = -1,
7893
			day = -1,
7894
			doy = -1,
7895
			literal = false,
7896
			date,
7897
			// Check whether a format character is doubled
7898
			lookAhead = function(match) {
7899
				var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
7900
				if (matches) {
7901
					iFormat++;
7902
				}
7903
				return matches;
7904
			},
7905
			// Extract a number from the string value
7906
			getNumber = function(match) {
7907
				var isDoubled = lookAhead(match),
7908
					size = (match === "@" ? 14 : (match === "!" ? 20 :
7909
					(match === "y" && isDoubled ? 4 : (match === "o" ? 3 : 2)))),
7910
					digits = new RegExp("^\\d{1," + size + "}"),
7911
					num = value.substring(iValue).match(digits);
7912
				if (!num) {
7913
					throw "Missing number at position " + iValue;
7914
				}
7915
				iValue += num[0].length;
7916
				return parseInt(num[0], 10);
7917
			},
7918
			// Extract a name from the string value and convert to an index
7919
			getName = function(match, shortNames, longNames) {
7920
				var index = -1,
7921
					names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) {
7922
						return [ [k, v] ];
7923
					}).sort(function (a, b) {
7924
						return -(a[1].length - b[1].length);
7925
					});
7926
7927
				$.each(names, function (i, pair) {
7928
					var name = pair[1];
7929
					if (value.substr(iValue, name.length).toLowerCase() === name.toLowerCase()) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if value.substr(iValue, nam... === name.toLowerCase() is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
7930
						index = pair[0];
7931
						iValue += name.length;
7932
						return false;
7933
					}
7934
				});
7935
				if (index !== -1) {
7936
					return index + 1;
7937
				} else {
7938
					throw "Unknown name at position " + iValue;
7939
				}
7940
			},
7941
			// Confirm that a literal character matches the string value
7942
			checkLiteral = function() {
7943
				if (value.charAt(iValue) !== format.charAt(iFormat)) {
7944
					throw "Unexpected literal at position " + iValue;
7945
				}
7946
				iValue++;
7947
			};
7948
7949
		for (iFormat = 0; iFormat < format.length; iFormat++) {
7950
			if (literal) {
7951
				if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
7952
					literal = false;
7953
				} else {
7954
					checkLiteral();
7955
				}
7956
			} else {
7957
				switch (format.charAt(iFormat)) {
7958
					case "d":
7959
						day = getNumber("d");
7960
						break;
7961
					case "D":
7962
						getName("D", dayNamesShort, dayNames);
7963
						break;
7964
					case "o":
7965
						doy = getNumber("o");
7966
						break;
7967
					case "m":
7968
						month = getNumber("m");
7969
						break;
7970
					case "M":
7971
						month = getName("M", monthNamesShort, monthNames);
7972
						break;
7973
					case "y":
7974
						year = getNumber("y");
7975
						break;
7976
					case "@":
7977
						date = new Date(getNumber("@"));
7978
						year = date.getFullYear();
7979
						month = date.getMonth() + 1;
7980
						day = date.getDate();
7981
						break;
7982
					case "!":
7983
						date = new Date((getNumber("!") - this._ticksTo1970) / 10000);
7984
						year = date.getFullYear();
7985
						month = date.getMonth() + 1;
7986
						day = date.getDate();
7987
						break;
7988
					case "'":
7989
						if (lookAhead("'")){
7990
							checkLiteral();
7991
						} else {
7992
							literal = true;
7993
						}
7994
						break;
7995
					default:
7996
						checkLiteral();
7997
				}
7998
			}
7999
		}
8000
8001
		if (iValue < value.length){
8002
			extra = value.substr(iValue);
8003
			if (!/^\s+/.test(extra)) {
8004
				throw "Extra/unparsed characters found in date: " + extra;
8005
			}
8006
		}
8007
8008
		if (year === -1) {
8009
			year = new Date().getFullYear();
8010
		} else if (year < 100) {
8011
			year += new Date().getFullYear() - new Date().getFullYear() % 100 +
8012
				(year <= shortYearCutoff ? 0 : -100);
8013
		}
8014
8015
		if (doy > -1) {
8016
			month = 1;
8017
			day = doy;
8018
			do {
8019
				dim = this._getDaysInMonth(year, month - 1);
8020
				if (day <= dim) {
8021
					break;
8022
				}
8023
				month++;
8024
				day -= dim;
8025
			} while (true);
8026
		}
8027
8028
		date = this._daylightSavingAdjust(new Date(year, month - 1, day));
8029
		if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) {
8030
			throw "Invalid date"; // E.g. 31/02/00
8031
		}
8032
		return date;
8033
	},
8034
8035
	/* Standard date formats. */
8036
	ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601)
8037
	COOKIE: "D, dd M yy",
8038
	ISO_8601: "yy-mm-dd",
8039
	RFC_822: "D, d M y",
8040
	RFC_850: "DD, dd-M-y",
8041
	RFC_1036: "D, d M y",
8042
	RFC_1123: "D, d M yy",
8043
	RFC_2822: "D, d M yy",
8044
	RSS: "D, d M y", // RFC 822
8045
	TICKS: "!",
8046
	TIMESTAMP: "@",
8047
	W3C: "yy-mm-dd", // ISO 8601
8048
8049
	_ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
8050
		Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
8051
8052
	/* Format a date object into a string value.
8053
	 * The format can be combinations of the following:
8054
	 * d  - day of month (no leading zero)
8055
	 * dd - day of month (two digit)
8056
	 * o  - day of year (no leading zeros)
8057
	 * oo - day of year (three digit)
8058
	 * D  - day name short
8059
	 * DD - day name long
8060
	 * m  - month of year (no leading zero)
8061
	 * mm - month of year (two digit)
8062
	 * M  - month name short
8063
	 * MM - month name long
8064
	 * y  - year (two digit)
8065
	 * yy - year (four digit)
8066
	 * @ - Unix timestamp (ms since 01/01/1970)
8067
	 * ! - Windows ticks (100ns since 01/01/0001)
8068
	 * "..." - literal text
8069
	 * '' - single quote
8070
	 *
8071
	 * @param  format string - the desired format of the date
8072
	 * @param  date Date - the date value to format
8073
	 * @param  settings Object - attributes include:
8074
	 *					dayNamesShort	string[7] - abbreviated names of the days from Sunday (optional)
8075
	 *					dayNames		string[7] - names of the days from Sunday (optional)
8076
	 *					monthNamesShort string[12] - abbreviated names of the months (optional)
8077
	 *					monthNames		string[12] - names of the months (optional)
8078
	 * @return  string - the date in the above format
8079
	 */
8080
	formatDate: function (format, date, settings) {
8081
		if (!date) {
8082
			return "";
8083
		}
8084
8085
		var iFormat,
8086
			dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
8087
			dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
8088
			monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
8089
			monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
8090
			// Check whether a format character is doubled
8091
			lookAhead = function(match) {
8092
				var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
8093
				if (matches) {
8094
					iFormat++;
8095
				}
8096
				return matches;
8097
			},
8098
			// Format a number, with leading zero if necessary
8099
			formatNumber = function(match, value, len) {
8100
				var num = "" + value;
8101
				if (lookAhead(match)) {
8102
					while (num.length < len) {
8103
						num = "0" + num;
8104
					}
8105
				}
8106
				return num;
8107
			},
8108
			// Format a name, short or long as requested
8109
			formatName = function(match, value, shortNames, longNames) {
8110
				return (lookAhead(match) ? longNames[value] : shortNames[value]);
8111
			},
8112
			output = "",
8113
			literal = false;
8114
8115
		if (date) {
8116
			for (iFormat = 0; iFormat < format.length; iFormat++) {
8117
				if (literal) {
8118
					if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
8119
						literal = false;
8120
					} else {
8121
						output += format.charAt(iFormat);
8122
					}
8123
				} else {
8124
					switch (format.charAt(iFormat)) {
8125
						case "d":
8126
							output += formatNumber("d", date.getDate(), 2);
8127
							break;
8128
						case "D":
8129
							output += formatName("D", date.getDay(), dayNamesShort, dayNames);
8130
							break;
8131
						case "o":
8132
							output += formatNumber("o",
8133
								Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);
8134
							break;
8135
						case "m":
8136
							output += formatNumber("m", date.getMonth() + 1, 2);
8137
							break;
8138
						case "M":
8139
							output += formatName("M", date.getMonth(), monthNamesShort, monthNames);
8140
							break;
8141
						case "y":
8142
							output += (lookAhead("y") ? date.getFullYear() :
8143
								(date.getYear() % 100 < 10 ? "0" : "") + date.getYear() % 100);
8144
							break;
8145
						case "@":
8146
							output += date.getTime();
8147
							break;
8148
						case "!":
8149
							output += date.getTime() * 10000 + this._ticksTo1970;
8150
							break;
8151
						case "'":
8152
							if (lookAhead("'")) {
8153
								output += "'";
8154
							} else {
8155
								literal = true;
8156
							}
8157
							break;
8158
						default:
8159
							output += format.charAt(iFormat);
8160
					}
8161
				}
8162
			}
8163
		}
8164
		return output;
8165
	},
8166
8167
	/* Extract all possible characters from the date format. */
8168
	_possibleChars: function (format) {
8169
		var iFormat,
8170
			chars = "",
8171
			literal = false,
8172
			// Check whether a format character is doubled
8173
			lookAhead = function(match) {
8174
				var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
8175
				if (matches) {
8176
					iFormat++;
8177
				}
8178
				return matches;
8179
			};
8180
8181
		for (iFormat = 0; iFormat < format.length; iFormat++) {
8182
			if (literal) {
8183
				if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
8184
					literal = false;
8185
				} else {
8186
					chars += format.charAt(iFormat);
8187
				}
8188
			} else {
8189
				switch (format.charAt(iFormat)) {
8190
					case "d": case "m": case "y": case "@":
8191
						chars += "0123456789";
8192
						break;
8193
					case "D": case "M":
8194
						return null; // Accept anything
8195
					case "'":
8196
						if (lookAhead("'")) {
8197
							chars += "'";
8198
						} else {
8199
							literal = true;
8200
						}
8201
						break;
8202
					default:
8203
						chars += format.charAt(iFormat);
8204
				}
8205
			}
8206
		}
8207
		return chars;
8208
	},
8209
8210
	/* Get a setting value, defaulting if necessary. */
8211
	_get: function(inst, name) {
8212
		return inst.settings[name] !== undefined ?
8213
			inst.settings[name] : this._defaults[name];
8214
	},
8215
8216
	/* Parse existing date and initialise date picker. */
8217
	_setDateFromField: function(inst, noDefault) {
8218
		if (inst.input.val() === inst.lastVal) {
8219
			return;
8220
		}
8221
8222
		var dateFormat = this._get(inst, "dateFormat"),
8223
			dates = inst.lastVal = inst.input ? inst.input.val() : null,
8224
			defaultDate = this._getDefaultDate(inst),
8225
			date = defaultDate,
0 ignored issues
show
Unused Code introduced by
The assignment to variable date seems to be never used. Consider removing it.
Loading history...
8226
			settings = this._getFormatConfig(inst);
8227
8228
		try {
8229
			date = this.parseDate(dateFormat, dates, settings) || defaultDate;
8230
		} catch (event) {
8231
			dates = (noDefault ? "" : dates);
8232
		}
8233
		inst.selectedDay = date.getDate();
8234
		inst.drawMonth = inst.selectedMonth = date.getMonth();
8235
		inst.drawYear = inst.selectedYear = date.getFullYear();
8236
		inst.currentDay = (dates ? date.getDate() : 0);
8237
		inst.currentMonth = (dates ? date.getMonth() : 0);
8238
		inst.currentYear = (dates ? date.getFullYear() : 0);
8239
		this._adjustInstDate(inst);
8240
	},
8241
8242
	/* Retrieve the default date shown on opening. */
8243
	_getDefaultDate: function(inst) {
8244
		return this._restrictMinMax(inst,
8245
			this._determineDate(inst, this._get(inst, "defaultDate"), new Date()));
8246
	},
8247
8248
	/* A date may be specified as an exact value or a relative one. */
8249
	_determineDate: function(inst, date, defaultDate) {
8250
		var offsetNumeric = function(offset) {
8251
				var date = new Date();
8252
				date.setDate(date.getDate() + offset);
8253
				return date;
8254
			},
8255
			offsetString = function(offset) {
8256
				try {
8257
					return $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
8258
						offset, $.datepicker._getFormatConfig(inst));
8259
				}
8260
				catch (e) {
8261
					// Ignore
8262
				}
8263
8264
				var date = (offset.toLowerCase().match(/^c/) ?
8265
					$.datepicker._getDate(inst) : null) || new Date(),
8266
					year = date.getFullYear(),
8267
					month = date.getMonth(),
8268
					day = date.getDate(),
8269
					pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,
8270
					matches = pattern.exec(offset);
8271
8272
				while (matches) {
8273
					switch (matches[2] || "d") {
0 ignored issues
show
Coding Style introduced by
As per coding-style, switch statements should have a default case.
Loading history...
8274
						case "d" : case "D" :
8275
							day += parseInt(matches[1],10); break;
8276
						case "w" : case "W" :
8277
							day += parseInt(matches[1],10) * 7; break;
8278
						case "m" : case "M" :
8279
							month += parseInt(matches[1],10);
8280
							day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
8281
							break;
8282
						case "y": case "Y" :
8283
							year += parseInt(matches[1],10);
8284
							day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
8285
							break;
8286
					}
8287
					matches = pattern.exec(offset);
8288
				}
8289
				return new Date(year, month, day);
8290
			},
8291
			newDate = (date == null || date === "" ? defaultDate : (typeof date === "string" ? offsetString(date) :
8292
				(typeof date === "number" ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
8293
8294
		newDate = (newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate);
8295
		if (newDate) {
8296
			newDate.setHours(0);
8297
			newDate.setMinutes(0);
8298
			newDate.setSeconds(0);
8299
			newDate.setMilliseconds(0);
8300
		}
8301
		return this._daylightSavingAdjust(newDate);
8302
	},
8303
8304
	/* Handle switch to/from daylight saving.
8305
	 * Hours may be non-zero on daylight saving cut-over:
8306
	 * > 12 when midnight changeover, but then cannot generate
8307
	 * midnight datetime, so jump to 1AM, otherwise reset.
8308
	 * @param  date  (Date) the date to check
8309
	 * @return  (Date) the corrected date
8310
	 */
8311
	_daylightSavingAdjust: function(date) {
8312
		if (!date) {
8313
			return null;
8314
		}
8315
		date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
8316
		return date;
8317
	},
8318
8319
	/* Set the date(s) directly. */
8320
	_setDate: function(inst, date, noChange) {
8321
		var clear = !date,
8322
			origMonth = inst.selectedMonth,
8323
			origYear = inst.selectedYear,
8324
			newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
8325
8326
		inst.selectedDay = inst.currentDay = newDate.getDate();
8327
		inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
8328
		inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
8329
		if ((origMonth !== inst.selectedMonth || origYear !== inst.selectedYear) && !noChange) {
8330
			this._notifyChange(inst);
8331
		}
8332
		this._adjustInstDate(inst);
8333
		if (inst.input) {
8334
			inst.input.val(clear ? "" : this._formatDate(inst));
8335
		}
8336
	},
8337
8338
	/* Retrieve the date(s) directly. */
8339
	_getDate: function(inst) {
8340
		var startDate = (!inst.currentYear || (inst.input && inst.input.val() === "") ? null :
8341
			this._daylightSavingAdjust(new Date(
8342
			inst.currentYear, inst.currentMonth, inst.currentDay)));
8343
			return startDate;
8344
	},
8345
8346
	/* Attach the onxxx handlers.  These are declared statically so
8347
	 * they work with static code transformers like Caja.
8348
	 */
8349
	_attachHandlers: function(inst) {
8350
		var stepMonths = this._get(inst, "stepMonths"),
8351
			id = "#" + inst.id.replace( /\\\\/g, "\\" );
8352
		inst.dpDiv.find("[data-handler]").map(function () {
8353
			var handler = {
8354
				prev: function () {
8355
					$.datepicker._adjustDate(id, -stepMonths, "M");
8356
				},
8357
				next: function () {
8358
					$.datepicker._adjustDate(id, +stepMonths, "M");
8359
				},
8360
				hide: function () {
8361
					$.datepicker._hideDatepicker();
8362
				},
8363
				today: function () {
8364
					$.datepicker._gotoToday(id);
8365
				},
8366
				selectDay: function () {
8367
					$.datepicker._selectDay(id, +this.getAttribute("data-month"), +this.getAttribute("data-year"), this);
8368
					return false;
8369
				},
8370
				selectMonth: function () {
8371
					$.datepicker._selectMonthYear(id, this, "M");
8372
					return false;
8373
				},
8374
				selectYear: function () {
8375
					$.datepicker._selectMonthYear(id, this, "Y");
8376
					return false;
8377
				}
8378
			};
8379
			$(this).bind(this.getAttribute("data-event"), handler[this.getAttribute("data-handler")]);
8380
		});
8381
	},
8382
8383
	/* Generate the HTML for the current state of the date picker. */
8384
	_generateHTML: function(inst) {
8385
		var maxDraw, prevText, prev, nextText, next, currentText, gotoDate,
8386
			controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
8387
			monthNames, monthNamesShort, beforeShowDay, showOtherMonths,
8388
			selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
8389
			cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
8390
			printDate, dRow, tbody, daySettings, otherMonth, unselectable,
8391
			tempDate = new Date(),
8392
			today = this._daylightSavingAdjust(
8393
				new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate())), // clear time
8394
			isRTL = this._get(inst, "isRTL"),
8395
			showButtonPanel = this._get(inst, "showButtonPanel"),
8396
			hideIfNoPrevNext = this._get(inst, "hideIfNoPrevNext"),
8397
			navigationAsDateFormat = this._get(inst, "navigationAsDateFormat"),
8398
			numMonths = this._getNumberOfMonths(inst),
8399
			showCurrentAtPos = this._get(inst, "showCurrentAtPos"),
8400
			stepMonths = this._get(inst, "stepMonths"),
8401
			isMultiMonth = (numMonths[0] !== 1 || numMonths[1] !== 1),
8402
			currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
8403
				new Date(inst.currentYear, inst.currentMonth, inst.currentDay))),
8404
			minDate = this._getMinMaxDate(inst, "min"),
8405
			maxDate = this._getMinMaxDate(inst, "max"),
8406
			drawMonth = inst.drawMonth - showCurrentAtPos,
8407
			drawYear = inst.drawYear;
8408
8409
		if (drawMonth < 0) {
8410
			drawMonth += 12;
8411
			drawYear--;
8412
		}
8413
		if (maxDate) {
8414
			maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
8415
				maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
8416
			maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
8417
			while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
8418
				drawMonth--;
8419
				if (drawMonth < 0) {
8420
					drawMonth = 11;
8421
					drawYear--;
8422
				}
8423
			}
8424
		}
8425
		inst.drawMonth = drawMonth;
8426
		inst.drawYear = drawYear;
8427
8428
		prevText = this._get(inst, "prevText");
8429
		prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
8430
			this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
8431
			this._getFormatConfig(inst)));
8432
8433
		prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
8434
			"<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'" +
8435
			" title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>" :
8436
			(hideIfNoPrevNext ? "" : "<a class='ui-datepicker-prev ui-corner-all ui-state-disabled' title='"+ prevText +"'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>"));
8437
8438
		nextText = this._get(inst, "nextText");
8439
		nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
8440
			this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
8441
			this._getFormatConfig(inst)));
8442
8443
		next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
8444
			"<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'" +
8445
			" title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>" :
8446
			(hideIfNoPrevNext ? "" : "<a class='ui-datepicker-next ui-corner-all ui-state-disabled' title='"+ nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>"));
8447
8448
		currentText = this._get(inst, "currentText");
8449
		gotoDate = (this._get(inst, "gotoCurrent") && inst.currentDay ? currentDate : today);
8450
		currentText = (!navigationAsDateFormat ? currentText :
8451
			this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
8452
8453
		controls = (!inst.inline ? "<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>" +
8454
			this._get(inst, "closeText") + "</button>" : "");
8455
8456
		buttonPanel = (showButtonPanel) ? "<div class='ui-datepicker-buttonpane ui-widget-content'>" + (isRTL ? controls : "") +
8457
			(this._isInRange(inst, gotoDate) ? "<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'" +
8458
			">" + currentText + "</button>" : "") + (isRTL ? "" : controls) + "</div>" : "";
8459
8460
		firstDay = parseInt(this._get(inst, "firstDay"),10);
8461
		firstDay = (isNaN(firstDay) ? 0 : firstDay);
8462
8463
		showWeek = this._get(inst, "showWeek");
8464
		dayNames = this._get(inst, "dayNames");
8465
		dayNamesMin = this._get(inst, "dayNamesMin");
8466
		monthNames = this._get(inst, "monthNames");
8467
		monthNamesShort = this._get(inst, "monthNamesShort");
8468
		beforeShowDay = this._get(inst, "beforeShowDay");
8469
		showOtherMonths = this._get(inst, "showOtherMonths");
8470
		selectOtherMonths = this._get(inst, "selectOtherMonths");
8471
		defaultDate = this._getDefaultDate(inst);
8472
		html = "";
8473
		dow;
0 ignored issues
show
Bug introduced by
The variable dow seems to be never initialized.
Loading history...
8474
		for (row = 0; row < numMonths[0]; row++) {
8475
			group = "";
8476
			this.maxRows = 4;
8477
			for (col = 0; col < numMonths[1]; col++) {
8478
				selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
8479
				cornerClass = " ui-corner-all";
8480
				calender = "";
8481
				if (isMultiMonth) {
8482
					calender += "<div class='ui-datepicker-group";
8483
					if (numMonths[1] > 1) {
8484
						switch (col) {
8485
							case 0: calender += " ui-datepicker-group-first";
8486
								cornerClass = " ui-corner-" + (isRTL ? "right" : "left"); break;
8487
							case numMonths[1]-1: calender += " ui-datepicker-group-last";
0 ignored issues
show
Bug introduced by
The variable numMonths seems to be never declared. If this is a global, consider adding a /** global: numMonths */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
8488
								cornerClass = " ui-corner-" + (isRTL ? "left" : "right"); break;
8489
							default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;
8490
						}
8491
					}
8492
					calender += "'>";
8493
				}
8494
				calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" +
8495
					(/all|left/.test(cornerClass) && row === 0 ? (isRTL ? next : prev) : "") +
8496
					(/all|right/.test(cornerClass) && row === 0 ? (isRTL ? prev : next) : "") +
8497
					this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
8498
					row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
8499
					"</div><table class='ui-datepicker-calendar'><thead>" +
8500
					"<tr>";
8501
				thead = (showWeek ? "<th class='ui-datepicker-week-col'>" + this._get(inst, "weekHeader") + "</th>" : "");
8502
				for (dow = 0; dow < 7; dow++) { // days of the week
8503
					day = (dow + firstDay) % 7;
8504
					thead += "<th" + ((dow + firstDay + 6) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "") + ">" +
8505
						"<span title='" + dayNames[day] + "'>" + dayNamesMin[day] + "</span></th>";
8506
				}
8507
				calender += thead + "</tr></thead><tbody>";
8508
				daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
8509
				if (drawYear === inst.selectedYear && drawMonth === inst.selectedMonth) {
8510
					inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
8511
				}
8512
				leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
8513
				curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
8514
				numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)
8515
				this.maxRows = numRows;
8516
				printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
8517
				for (dRow = 0; dRow < numRows; dRow++) { // create date picker rows
8518
					calender += "<tr>";
8519
					tbody = (!showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
8520
						this._get(inst, "calculateWeek")(printDate) + "</td>");
8521
					for (dow = 0; dow < 7; dow++) { // create date picker days
8522
						daySettings = (beforeShowDay ?
8523
							beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, ""]);
8524
						otherMonth = (printDate.getMonth() !== drawMonth);
8525
						unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
8526
							(minDate && printDate < minDate) || (maxDate && printDate > maxDate);
8527
						tbody += "<td class='" +
8528
							((dow + firstDay + 6) % 7 >= 5 ? " ui-datepicker-week-end" : "") + // highlight weekends
8529
							(otherMonth ? " ui-datepicker-other-month" : "") + // highlight days from other months
8530
							((printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent) || // user pressed key
8531
							(defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime()) ?
8532
							// or defaultDate is current printedDate and defaultDate is selectedDate
8533
							" " + this._dayOverClass : "") + // highlight selected day
8534
							(unselectable ? " " + this._unselectableClass + " ui-state-disabled": "") +  // highlight unselectable days
8535
							(otherMonth && !showOtherMonths ? "" : " " + daySettings[1] + // highlight custom dates
8536
							(printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "") + // highlight selected day
8537
							(printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "")) + "'" + // highlight today (if different)
8538
							((!otherMonth || showOtherMonths) && daySettings[2] ? " title='" + daySettings[2].replace(/'/g, "&#39;") + "'" : "") + // cell title
8539
							(unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'") + ">" + // actions
8540
							(otherMonth && !showOtherMonths ? "&#xa0;" : // display for other months
8541
							(unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" +
8542
							(printDate.getTime() === today.getTime() ? " ui-state-highlight" : "") +
8543
							(printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "") + // highlight selected day
8544
							(otherMonth ? " ui-priority-secondary" : "") + // distinguish dates from other months
8545
							"' href='#'>" + printDate.getDate() + "</a>")) + "</td>"; // display selectable date
8546
						printDate.setDate(printDate.getDate() + 1);
8547
						printDate = this._daylightSavingAdjust(printDate);
8548
					}
8549
					calender += tbody + "</tr>";
8550
				}
8551
				drawMonth++;
8552
				if (drawMonth > 11) {
8553
					drawMonth = 0;
8554
					drawYear++;
8555
				}
8556
				calender += "</tbody></table>" + (isMultiMonth ? "</div>" +
8557
							((numMonths[0] > 0 && col === numMonths[1]-1) ? "<div class='ui-datepicker-row-break'></div>" : "") : "");
8558
				group += calender;
8559
			}
8560
			html += group;
8561
		}
8562
		html += buttonPanel;
8563
		inst._keyEvent = false;
8564
		return html;
8565
	},
8566
8567
	/* Generate the month and year header. */
8568
	_generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
8569
			secondary, monthNames, monthNamesShort) {
8570
8571
		var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
8572
			changeMonth = this._get(inst, "changeMonth"),
8573
			changeYear = this._get(inst, "changeYear"),
8574
			showMonthAfterYear = this._get(inst, "showMonthAfterYear"),
8575
			html = "<div class='ui-datepicker-title'>",
8576
			monthHtml = "";
8577
8578
		// month selection
8579
		if (secondary || !changeMonth) {
8580
			monthHtml += "<span class='ui-datepicker-month'>" + monthNames[drawMonth] + "</span>";
8581
		} else {
8582
			inMinYear = (minDate && minDate.getFullYear() === drawYear);
8583
			inMaxYear = (maxDate && maxDate.getFullYear() === drawYear);
8584
			monthHtml += "<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>";
8585
			for ( month = 0; month < 12; month++) {
8586
				if ((!inMinYear || month >= minDate.getMonth()) && (!inMaxYear || month <= maxDate.getMonth())) {
8587
					monthHtml += "<option value='" + month + "'" +
8588
						(month === drawMonth ? " selected='selected'" : "") +
8589
						">" + monthNamesShort[month] + "</option>";
8590
				}
8591
			}
8592
			monthHtml += "</select>";
8593
		}
8594
8595
		if (!showMonthAfterYear) {
8596
			html += monthHtml + (secondary || !(changeMonth && changeYear) ? "&#xa0;" : "");
8597
		}
8598
8599
		// year selection
8600
		if ( !inst.yearshtml ) {
8601
			inst.yearshtml = "";
8602
			if (secondary || !changeYear) {
8603
				html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
8604
			} else {
8605
				// determine range of years to display
8606
				years = this._get(inst, "yearRange").split(":");
8607
				thisYear = new Date().getFullYear();
8608
				determineYear = function(value) {
8609
					var year = (value.match(/c[+\-].*/) ? drawYear + parseInt(value.substring(1), 10) :
8610
						(value.match(/[+\-].*/) ? thisYear + parseInt(value, 10) :
8611
						parseInt(value, 10)));
8612
					return (isNaN(year) ? thisYear : year);
8613
				};
8614
				year = determineYear(years[0]);
8615
				endYear = Math.max(year, determineYear(years[1] || ""));
8616
				year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
8617
				endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
8618
				inst.yearshtml += "<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";
8619
				for (; year <= endYear; year++) {
8620
					inst.yearshtml += "<option value='" + year + "'" +
8621
						(year === drawYear ? " selected='selected'" : "") +
8622
						">" + year + "</option>";
8623
				}
8624
				inst.yearshtml += "</select>";
8625
8626
				html += inst.yearshtml;
8627
				inst.yearshtml = null;
8628
			}
8629
		}
8630
8631
		html += this._get(inst, "yearSuffix");
8632
		if (showMonthAfterYear) {
8633
			html += (secondary || !(changeMonth && changeYear) ? "&#xa0;" : "") + monthHtml;
8634
		}
8635
		html += "</div>"; // Close datepicker_header
8636
		return html;
8637
	},
8638
8639
	/* Adjust one of the date sub-fields. */
8640
	_adjustInstDate: function(inst, offset, period) {
8641
		var year = inst.drawYear + (period === "Y" ? offset : 0),
8642
			month = inst.drawMonth + (period === "M" ? offset : 0),
8643
			day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + (period === "D" ? offset : 0),
8644
			date = this._restrictMinMax(inst, this._daylightSavingAdjust(new Date(year, month, day)));
8645
8646
		inst.selectedDay = date.getDate();
8647
		inst.drawMonth = inst.selectedMonth = date.getMonth();
8648
		inst.drawYear = inst.selectedYear = date.getFullYear();
8649
		if (period === "M" || period === "Y") {
8650
			this._notifyChange(inst);
8651
		}
8652
	},
8653
8654
	/* Ensure a date is within any min/max bounds. */
8655
	_restrictMinMax: function(inst, date) {
8656
		var minDate = this._getMinMaxDate(inst, "min"),
8657
			maxDate = this._getMinMaxDate(inst, "max"),
8658
			newDate = (minDate && date < minDate ? minDate : date);
8659
		return (maxDate && newDate > maxDate ? maxDate : newDate);
8660
	},
8661
8662
	/* Notify change of month/year. */
8663
	_notifyChange: function(inst) {
8664
		var onChange = this._get(inst, "onChangeMonthYear");
8665
		if (onChange) {
8666
			onChange.apply((inst.input ? inst.input[0] : null),
8667
				[inst.selectedYear, inst.selectedMonth + 1, inst]);
8668
		}
8669
	},
8670
8671
	/* Determine the number of months to show. */
8672
	_getNumberOfMonths: function(inst) {
8673
		var numMonths = this._get(inst, "numberOfMonths");
8674
		return (numMonths == null ? [1, 1] : (typeof numMonths === "number" ? [1, numMonths] : numMonths));
8675
	},
8676
8677
	/* Determine the current maximum date - ensure no time components are set. */
8678
	_getMinMaxDate: function(inst, minMax) {
8679
		return this._determineDate(inst, this._get(inst, minMax + "Date"), null);
8680
	},
8681
8682
	/* Find the number of days in a given month. */
8683
	_getDaysInMonth: function(year, month) {
8684
		return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();
8685
	},
8686
8687
	/* Find the day of the week of the first of a month. */
8688
	_getFirstDayOfMonth: function(year, month) {
8689
		return new Date(year, month, 1).getDay();
8690
	},
8691
8692
	/* Determines if we should allow a "next/prev" month display change. */
8693
	_canAdjustMonth: function(inst, offset, curYear, curMonth) {
8694
		var numMonths = this._getNumberOfMonths(inst),
8695
			date = this._daylightSavingAdjust(new Date(curYear,
8696
			curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
8697
8698
		if (offset < 0) {
8699
			date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
8700
		}
8701
		return this._isInRange(inst, date);
8702
	},
8703
8704
	/* Is the given date in the accepted range? */
8705
	_isInRange: function(inst, date) {
8706
		var yearSplit, currentYear,
8707
			minDate = this._getMinMaxDate(inst, "min"),
8708
			maxDate = this._getMinMaxDate(inst, "max"),
8709
			minYear = null,
8710
			maxYear = null,
8711
			years = this._get(inst, "yearRange");
8712
			if (years){
8713
				yearSplit = years.split(":");
8714
				currentYear = new Date().getFullYear();
8715
				minYear = parseInt(yearSplit[0], 10);
8716
				maxYear = parseInt(yearSplit[1], 10);
8717
				if ( yearSplit[0].match(/[+\-].*/) ) {
8718
					minYear += currentYear;
8719
				}
8720
				if ( yearSplit[1].match(/[+\-].*/) ) {
8721
					maxYear += currentYear;
8722
				}
8723
			}
8724
8725
		return ((!minDate || date.getTime() >= minDate.getTime()) &&
8726
			(!maxDate || date.getTime() <= maxDate.getTime()) &&
8727
			(!minYear || date.getFullYear() >= minYear) &&
8728
			(!maxYear || date.getFullYear() <= maxYear));
8729
	},
8730
8731
	/* Provide the configuration settings for formatting/parsing. */
8732
	_getFormatConfig: function(inst) {
8733
		var shortYearCutoff = this._get(inst, "shortYearCutoff");
8734
		shortYearCutoff = (typeof shortYearCutoff !== "string" ? shortYearCutoff :
8735
			new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
8736
		return {shortYearCutoff: shortYearCutoff,
8737
			dayNamesShort: this._get(inst, "dayNamesShort"), dayNames: this._get(inst, "dayNames"),
8738
			monthNamesShort: this._get(inst, "monthNamesShort"), monthNames: this._get(inst, "monthNames")};
8739
	},
8740
8741
	/* Format the given date for display. */
8742
	_formatDate: function(inst, day, month, year) {
8743
		if (!day) {
8744
			inst.currentDay = inst.selectedDay;
8745
			inst.currentMonth = inst.selectedMonth;
8746
			inst.currentYear = inst.selectedYear;
8747
		}
8748
		var date = (day ? (typeof day === "object" ? day :
8749
			this._daylightSavingAdjust(new Date(year, month, day))) :
8750
			this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
8751
		return this.formatDate(this._get(inst, "dateFormat"), date, this._getFormatConfig(inst));
8752
	}
8753
});
8754
8755
/*
8756
 * Bind hover events for datepicker elements.
8757
 * Done via delegate so the binding only occurs once in the lifetime of the parent div.
8758
 * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
8759
 */
8760
function bindHover(dpDiv) {
8761
	var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
8762
	return dpDiv.delegate(selector, "mouseout", function() {
8763
			$(this).removeClass("ui-state-hover");
8764
			if (this.className.indexOf("ui-datepicker-prev") !== -1) {
8765
				$(this).removeClass("ui-datepicker-prev-hover");
8766
			}
8767
			if (this.className.indexOf("ui-datepicker-next") !== -1) {
8768
				$(this).removeClass("ui-datepicker-next-hover");
8769
			}
8770
		})
8771
		.delegate(selector, "mouseover", function(){
8772
			if (!$.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0])) {
8773
				$(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");
8774
				$(this).addClass("ui-state-hover");
8775
				if (this.className.indexOf("ui-datepicker-prev") !== -1) {
8776
					$(this).addClass("ui-datepicker-prev-hover");
8777
				}
8778
				if (this.className.indexOf("ui-datepicker-next") !== -1) {
8779
					$(this).addClass("ui-datepicker-next-hover");
8780
				}
8781
			}
8782
		});
8783
}
8784
8785
/* jQuery extend now ignores nulls! */
8786
function extendRemove(target, props) {
8787
	$.extend(target, props);
8788
	for (var name in props) {
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
8789
		if (props[name] == null) {
8790
			target[name] = props[name];
8791
		}
8792
	}
8793
	return target;
8794
}
8795
8796
/* Invoke the datepicker functionality.
8797
   @param  options  string - a command, optionally followed by additional parameters or
8798
					Object - settings for attaching new datepicker functionality
8799
   @return  jQuery object */
8800
$.fn.datepicker = function(options){
8801
8802
	/* Verify an empty collection wasn't passed - Fixes #6976 */
8803
	if ( !this.length ) {
8804
		return this;
8805
	}
8806
8807
	/* Initialise the date picker. */
8808
	if (!$.datepicker.initialized) {
8809
		$(document).mousedown($.datepicker._checkExternalClick);
8810
		$.datepicker.initialized = true;
8811
	}
8812
8813
	/* Append datepicker main container to body if not exist. */
8814
	if ($("#"+$.datepicker._mainDivId).length === 0) {
8815
		$("body").append($.datepicker.dpDiv);
8816
	}
8817
8818
	var otherArgs = Array.prototype.slice.call(arguments, 1);
8819
	if (typeof options === "string" && (options === "isDisabled" || options === "getDate" || options === "widget")) {
8820
		return $.datepicker["_" + options + "Datepicker"].
8821
			apply($.datepicker, [this[0]].concat(otherArgs));
8822
	}
8823
	if (options === "option" && arguments.length === 2 && typeof arguments[1] === "string") {
8824
		return $.datepicker["_" + options + "Datepicker"].
8825
			apply($.datepicker, [this[0]].concat(otherArgs));
8826
	}
8827
	return this.each(function() {
8828
		typeof options === "string" ?
8829
			$.datepicker["_" + options + "Datepicker"].
8830
				apply($.datepicker, [this].concat(otherArgs)) :
8831
			$.datepicker._attachDatepicker(this, options);
8832
	});
8833
};
8834
8835
$.datepicker = new Datepicker(); // singleton instance
8836
$.datepicker.initialized = false;
8837
$.datepicker.uuid = new Date().getTime();
8838
$.datepicker.version = "1.10.4";
8839
8840
})(jQuery);
8841
(function( $, undefined ) {
0 ignored issues
show
Unused Code introduced by
The parameter undefined is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
8842
8843
var sizeRelatedOptions = {
8844
		buttons: true,
8845
		height: true,
8846
		maxHeight: true,
8847
		maxWidth: true,
8848
		minHeight: true,
8849
		minWidth: true,
8850
		width: true
8851
	},
8852
	resizableRelatedOptions = {
8853
		maxHeight: true,
8854
		maxWidth: true,
8855
		minHeight: true,
8856
		minWidth: true
8857
	};
8858
8859
$.widget( "ui.dialog", {
8860
	version: "1.10.4",
8861
	options: {
8862
		appendTo: "body",
8863
		autoOpen: true,
8864
		buttons: [],
8865
		closeOnEscape: true,
8866
		closeText: "close",
8867
		dialogClass: "",
8868
		draggable: true,
8869
		hide: null,
8870
		height: "auto",
8871
		maxHeight: null,
8872
		maxWidth: null,
8873
		minHeight: 150,
8874
		minWidth: 150,
8875
		modal: false,
8876
		position: {
8877
			my: "center",
8878
			at: "center",
8879
			of: window,
8880
			collision: "fit",
8881
			// Ensure the titlebar is always visible
8882
			using: function( pos ) {
8883
				var topOffset = $( this ).css( pos ).offset().top;
8884
				if ( topOffset < 0 ) {
8885
					$( this ).css( "top", pos.top - topOffset );
8886
				}
8887
			}
8888
		},
8889
		resizable: true,
8890
		show: null,
8891
		title: null,
8892
		width: 300,
8893
8894
		// callbacks
8895
		beforeClose: null,
8896
		close: null,
8897
		drag: null,
8898
		dragStart: null,
8899
		dragStop: null,
8900
		focus: null,
8901
		open: null,
8902
		resize: null,
8903
		resizeStart: null,
8904
		resizeStop: null
8905
	},
8906
8907
	_create: function() {
8908
		this.originalCss = {
8909
			display: this.element[0].style.display,
8910
			width: this.element[0].style.width,
8911
			minHeight: this.element[0].style.minHeight,
8912
			maxHeight: this.element[0].style.maxHeight,
8913
			height: this.element[0].style.height
8914
		};
8915
		this.originalPosition = {
8916
			parent: this.element.parent(),
8917
			index: this.element.parent().children().index( this.element )
8918
		};
8919
		this.originalTitle = this.element.attr("title");
8920
		this.options.title = this.options.title || this.originalTitle;
8921
8922
		this._createWrapper();
8923
8924
		this.element
8925
			.show()
8926
			.removeAttr("title")
8927
			.addClass("ui-dialog-content ui-widget-content")
8928
			.appendTo( this.uiDialog );
8929
8930
		this._createTitlebar();
8931
		this._createButtonPane();
8932
8933
		if ( this.options.draggable && $.fn.draggable ) {
8934
			this._makeDraggable();
8935
		}
8936
		if ( this.options.resizable && $.fn.resizable ) {
8937
			this._makeResizable();
8938
		}
8939
8940
		this._isOpen = false;
8941
	},
8942
8943
	_init: function() {
8944
		if ( this.options.autoOpen ) {
8945
			this.open();
8946
		}
8947
	},
8948
8949
	_appendTo: function() {
8950
		var element = this.options.appendTo;
8951
		if ( element && (element.jquery || element.nodeType) ) {
8952
			return $( element );
8953
		}
8954
		return this.document.find( element || "body" ).eq( 0 );
8955
	},
8956
8957
	_destroy: function() {
8958
		var next,
8959
			originalPosition = this.originalPosition;
8960
8961
		this._destroyOverlay();
8962
8963
		this.element
8964
			.removeUniqueId()
8965
			.removeClass("ui-dialog-content ui-widget-content")
8966
			.css( this.originalCss )
8967
			// Without detaching first, the following becomes really slow
8968
			.detach();
8969
8970
		this.uiDialog.stop( true, true ).remove();
8971
8972
		if ( this.originalTitle ) {
8973
			this.element.attr( "title", this.originalTitle );
8974
		}
8975
8976
		next = originalPosition.parent.children().eq( originalPosition.index );
8977
		// Don't try to place the dialog next to itself (#8613)
8978
		if ( next.length && next[0] !== this.element[0] ) {
8979
			next.before( this.element );
8980
		} else {
8981
			originalPosition.parent.append( this.element );
8982
		}
8983
	},
8984
8985
	widget: function() {
8986
		return this.uiDialog;
8987
	},
8988
8989
	disable: $.noop,
8990
	enable: $.noop,
8991
8992
	close: function( event ) {
8993
		var activeElement,
8994
			that = this;
8995
8996
		if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) {
8997
			return;
8998
		}
8999
9000
		this._isOpen = false;
9001
		this._destroyOverlay();
9002
9003
		if ( !this.opener.filter(":focusable").focus().length ) {
9004
9005
			// support: IE9
9006
			// IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe>
9007
			try {
9008
				activeElement = this.document[ 0 ].activeElement;
9009
9010
				// Support: IE9, IE10
9011
				// If the <body> is blurred, IE will switch windows, see #4520
9012
				if ( activeElement && activeElement.nodeName.toLowerCase() !== "body" ) {
9013
9014
					// Hiding a focused element doesn't trigger blur in WebKit
9015
					// so in case we have nothing to focus on, explicitly blur the active element
9016
					// https://bugs.webkit.org/show_bug.cgi?id=47182
9017
					$( activeElement ).blur();
9018
				}
9019
			} catch ( error ) {}
0 ignored issues
show
Coding Style Comprehensibility Best Practice introduced by
Empty catch clauses should be used with caution; consider adding a comment why this is needed.
Loading history...
9020
		}
9021
9022
		this._hide( this.uiDialog, this.options.hide, function() {
9023
			that._trigger( "close", event );
9024
		});
9025
	},
9026
9027
	isOpen: function() {
9028
		return this._isOpen;
9029
	},
9030
9031
	moveToTop: function() {
9032
		this._moveToTop();
9033
	},
9034
9035
	_moveToTop: function( event, silent ) {
9036
		var moved = !!this.uiDialog.nextAll(":visible").insertBefore( this.uiDialog ).length;
9037
		if ( moved && !silent ) {
9038
			this._trigger( "focus", event );
9039
		}
9040
		return moved;
9041
	},
9042
9043
	open: function() {
9044
		var that = this;
9045
		if ( this._isOpen ) {
9046
			if ( this._moveToTop() ) {
9047
				this._focusTabbable();
9048
			}
9049
			return;
9050
		}
9051
9052
		this._isOpen = true;
9053
		this.opener = $( this.document[0].activeElement );
9054
9055
		this._size();
9056
		this._position();
9057
		this._createOverlay();
9058
		this._moveToTop( null, true );
9059
		this._show( this.uiDialog, this.options.show, function() {
9060
			that._focusTabbable();
9061
			that._trigger("focus");
9062
		});
9063
9064
		this._trigger("open");
9065
	},
9066
9067
	_focusTabbable: function() {
9068
		// Set focus to the first match:
9069
		// 1. First element inside the dialog matching [autofocus]
9070
		// 2. Tabbable element inside the content element
9071
		// 3. Tabbable element inside the buttonpane
9072
		// 4. The close button
9073
		// 5. The dialog itself
9074
		var hasFocus = this.element.find("[autofocus]");
9075
		if ( !hasFocus.length ) {
9076
			hasFocus = this.element.find(":tabbable");
9077
		}
9078
		if ( !hasFocus.length ) {
9079
			hasFocus = this.uiDialogButtonPane.find(":tabbable");
9080
		}
9081
		if ( !hasFocus.length ) {
9082
			hasFocus = this.uiDialogTitlebarClose.filter(":tabbable");
9083
		}
9084
		if ( !hasFocus.length ) {
9085
			hasFocus = this.uiDialog;
9086
		}
9087
		hasFocus.eq( 0 ).focus();
9088
	},
9089
9090
	_keepFocus: function( event ) {
9091
		function checkFocus() {
9092
			var activeElement = this.document[0].activeElement,
9093
				isActive = this.uiDialog[0] === activeElement ||
9094
					$.contains( this.uiDialog[0], activeElement );
9095
			if ( !isActive ) {
9096
				this._focusTabbable();
9097
			}
9098
		}
9099
		event.preventDefault();
9100
		checkFocus.call( this );
9101
		// support: IE
9102
		// IE <= 8 doesn't prevent moving focus even with event.preventDefault()
9103
		// so we check again later
9104
		this._delay( checkFocus );
9105
	},
9106
9107
	_createWrapper: function() {
9108
		this.uiDialog = $("<div>")
9109
			.addClass( "ui-dialog ui-widget ui-widget-content ui-corner-all ui-front " +
9110
				this.options.dialogClass )
9111
			.hide()
9112
			.attr({
9113
				// Setting tabIndex makes the div focusable
9114
				tabIndex: -1,
9115
				role: "dialog"
9116
			})
9117
			.appendTo( this._appendTo() );
9118
9119
		this._on( this.uiDialog, {
9120
			keydown: function( event ) {
9121
				if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
9122
						event.keyCode === $.ui.keyCode.ESCAPE ) {
9123
					event.preventDefault();
9124
					this.close( event );
9125
					return;
9126
				}
9127
9128
				// prevent tabbing out of dialogs
9129
				if ( event.keyCode !== $.ui.keyCode.TAB ) {
9130
					return;
9131
				}
9132
				var tabbables = this.uiDialog.find(":tabbable"),
9133
					first = tabbables.filter(":first"),
9134
					last  = tabbables.filter(":last");
9135
9136
				if ( ( event.target === last[0] || event.target === this.uiDialog[0] ) && !event.shiftKey ) {
9137
					first.focus( 1 );
9138
					event.preventDefault();
9139
				} else if ( ( event.target === first[0] || event.target === this.uiDialog[0] ) && event.shiftKey ) {
9140
					last.focus( 1 );
9141
					event.preventDefault();
9142
				}
9143
			},
9144
			mousedown: function( event ) {
9145
				if ( this._moveToTop( event ) ) {
9146
					this._focusTabbable();
9147
				}
9148
			}
9149
		});
9150
9151
		// We assume that any existing aria-describedby attribute means
9152
		// that the dialog content is marked up properly
9153
		// otherwise we brute force the content as the description
9154
		if ( !this.element.find("[aria-describedby]").length ) {
9155
			this.uiDialog.attr({
9156
				"aria-describedby": this.element.uniqueId().attr("id")
9157
			});
9158
		}
9159
	},
9160
9161
	_createTitlebar: function() {
9162
		var uiDialogTitle;
9163
9164
		this.uiDialogTitlebar = $("<div>")
9165
			.addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix")
9166
			.prependTo( this.uiDialog );
9167
		this._on( this.uiDialogTitlebar, {
9168
			mousedown: function( event ) {
9169
				// Don't prevent click on close button (#8838)
9170
				// Focusing a dialog that is partially scrolled out of view
9171
				// causes the browser to scroll it into view, preventing the click event
9172
				if ( !$( event.target ).closest(".ui-dialog-titlebar-close") ) {
9173
					// Dialog isn't getting focus when dragging (#8063)
9174
					this.uiDialog.focus();
9175
				}
9176
			}
9177
		});
9178
9179
		// support: IE
9180
		// Use type="button" to prevent enter keypresses in textboxes from closing the
9181
		// dialog in IE (#9312)
9182
		this.uiDialogTitlebarClose = $( "<button type='button'></button>" )
9183
			.button({
9184
				label: this.options.closeText,
9185
				icons: {
9186
					primary: "ui-icon-closethick"
9187
				},
9188
				text: false
9189
			})
9190
			.addClass("ui-dialog-titlebar-close")
9191
			.appendTo( this.uiDialogTitlebar );
9192
		this._on( this.uiDialogTitlebarClose, {
9193
			click: function( event ) {
9194
				event.preventDefault();
9195
				this.close( event );
9196
			}
9197
		});
9198
9199
		uiDialogTitle = $("<span>")
9200
			.uniqueId()
9201
			.addClass("ui-dialog-title")
9202
			.prependTo( this.uiDialogTitlebar );
9203
		this._title( uiDialogTitle );
9204
9205
		this.uiDialog.attr({
9206
			"aria-labelledby": uiDialogTitle.attr("id")
9207
		});
9208
	},
9209
9210
	_title: function( title ) {
9211
		if ( !this.options.title ) {
9212
			title.html("&#160;");
9213
		}
9214
		title.text( this.options.title );
9215
	},
9216
9217
	_createButtonPane: function() {
9218
		this.uiDialogButtonPane = $("<div>")
9219
			.addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix");
9220
9221
		this.uiButtonSet = $("<div>")
9222
			.addClass("ui-dialog-buttonset")
9223
			.appendTo( this.uiDialogButtonPane );
9224
9225
		this._createButtons();
9226
	},
9227
9228
	_createButtons: function() {
9229
		var that = this,
9230
			buttons = this.options.buttons;
9231
9232
		// if we already have a button pane, remove it
9233
		this.uiDialogButtonPane.remove();
9234
		this.uiButtonSet.empty();
9235
9236
		if ( $.isEmptyObject( buttons ) || ($.isArray( buttons ) && !buttons.length) ) {
9237
			this.uiDialog.removeClass("ui-dialog-buttons");
9238
			return;
9239
		}
9240
9241
		$.each( buttons, function( name, props ) {
9242
			var click, buttonOptions;
9243
			props = $.isFunction( props ) ?
9244
				{ click: props, text: name } :
9245
				props;
9246
			// Default to a non-submitting button
9247
			props = $.extend( { type: "button" }, props );
9248
			// Change the context for the click callback to be the main element
9249
			click = props.click;
9250
			props.click = function() {
9251
				click.apply( that.element[0], arguments );
9252
			};
9253
			buttonOptions = {
9254
				icons: props.icons,
9255
				text: props.showText
9256
			};
9257
			delete props.icons;
9258
			delete props.showText;
9259
			$( "<button></button>", props )
9260
				.button( buttonOptions )
9261
				.appendTo( that.uiButtonSet );
9262
		});
9263
		this.uiDialog.addClass("ui-dialog-buttons");
9264
		this.uiDialogButtonPane.appendTo( this.uiDialog );
9265
	},
9266
9267
	_makeDraggable: function() {
9268
		var that = this,
9269
			options = this.options;
9270
9271
		function filteredUi( ui ) {
9272
			return {
9273
				position: ui.position,
9274
				offset: ui.offset
9275
			};
9276
		}
9277
9278
		this.uiDialog.draggable({
9279
			cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
9280
			handle: ".ui-dialog-titlebar",
9281
			containment: "document",
9282
			start: function( event, ui ) {
9283
				$( this ).addClass("ui-dialog-dragging");
9284
				that._blockFrames();
9285
				that._trigger( "dragStart", event, filteredUi( ui ) );
9286
			},
9287
			drag: function( event, ui ) {
9288
				that._trigger( "drag", event, filteredUi( ui ) );
9289
			},
9290
			stop: function( event, ui ) {
9291
				options.position = [
9292
					ui.position.left - that.document.scrollLeft(),
9293
					ui.position.top - that.document.scrollTop()
9294
				];
9295
				$( this ).removeClass("ui-dialog-dragging");
9296
				that._unblockFrames();
9297
				that._trigger( "dragStop", event, filteredUi( ui ) );
9298
			}
9299
		});
9300
	},
9301
9302
	_makeResizable: function() {
9303
		var that = this,
9304
			options = this.options,
9305
			handles = options.resizable,
9306
			// .ui-resizable has position: relative defined in the stylesheet
9307
			// but dialogs have to use absolute or fixed positioning
9308
			position = this.uiDialog.css("position"),
9309
			resizeHandles = typeof handles === "string" ?
9310
				handles	:
9311
				"n,e,s,w,se,sw,ne,nw";
9312
9313
		function filteredUi( ui ) {
9314
			return {
9315
				originalPosition: ui.originalPosition,
9316
				originalSize: ui.originalSize,
9317
				position: ui.position,
9318
				size: ui.size
9319
			};
9320
		}
9321
9322
		this.uiDialog.resizable({
9323
			cancel: ".ui-dialog-content",
9324
			containment: "document",
9325
			alsoResize: this.element,
9326
			maxWidth: options.maxWidth,
9327
			maxHeight: options.maxHeight,
9328
			minWidth: options.minWidth,
9329
			minHeight: this._minHeight(),
9330
			handles: resizeHandles,
9331
			start: function( event, ui ) {
9332
				$( this ).addClass("ui-dialog-resizing");
9333
				that._blockFrames();
9334
				that._trigger( "resizeStart", event, filteredUi( ui ) );
9335
			},
9336
			resize: function( event, ui ) {
9337
				that._trigger( "resize", event, filteredUi( ui ) );
9338
			},
9339
			stop: function( event, ui ) {
9340
				options.height = $( this ).height();
9341
				options.width = $( this ).width();
9342
				$( this ).removeClass("ui-dialog-resizing");
9343
				that._unblockFrames();
9344
				that._trigger( "resizeStop", event, filteredUi( ui ) );
9345
			}
9346
		})
9347
		.css( "position", position );
9348
	},
9349
9350
	_minHeight: function() {
9351
		var options = this.options;
9352
9353
		return options.height === "auto" ?
9354
			options.minHeight :
9355
			Math.min( options.minHeight, options.height );
9356
	},
9357
9358
	_position: function() {
9359
		// Need to show the dialog to get the actual offset in the position plugin
9360
		var isVisible = this.uiDialog.is(":visible");
9361
		if ( !isVisible ) {
9362
			this.uiDialog.show();
9363
		}
9364
		this.uiDialog.position( this.options.position );
9365
		if ( !isVisible ) {
9366
			this.uiDialog.hide();
9367
		}
9368
	},
9369
9370
	_setOptions: function( options ) {
9371
		var that = this,
9372
			resize = false,
9373
			resizableOptions = {};
9374
9375
		$.each( options, function( key, value ) {
9376
			that._setOption( key, value );
9377
9378
			if ( key in sizeRelatedOptions ) {
9379
				resize = true;
9380
			}
9381
			if ( key in resizableRelatedOptions ) {
9382
				resizableOptions[ key ] = value;
9383
			}
9384
		});
9385
9386
		if ( resize ) {
9387
			this._size();
9388
			this._position();
9389
		}
9390
		if ( this.uiDialog.is(":data(ui-resizable)") ) {
9391
			this.uiDialog.resizable( "option", resizableOptions );
9392
		}
9393
	},
9394
9395
	_setOption: function( key, value ) {
9396
		var isDraggable, isResizable,
9397
			uiDialog = this.uiDialog;
9398
9399
		if ( key === "dialogClass" ) {
9400
			uiDialog
9401
				.removeClass( this.options.dialogClass )
9402
				.addClass( value );
9403
		}
9404
9405
		if ( key === "disabled" ) {
9406
			return;
9407
		}
9408
9409
		this._super( key, value );
9410
9411
		if ( key === "appendTo" ) {
9412
			this.uiDialog.appendTo( this._appendTo() );
9413
		}
9414
9415
		if ( key === "buttons" ) {
9416
			this._createButtons();
9417
		}
9418
9419
		if ( key === "closeText" ) {
9420
			this.uiDialogTitlebarClose.button({
9421
				// Ensure that we always pass a string
9422
				label: "" + value
9423
			});
9424
		}
9425
9426
		if ( key === "draggable" ) {
9427
			isDraggable = uiDialog.is(":data(ui-draggable)");
9428
			if ( isDraggable && !value ) {
9429
				uiDialog.draggable("destroy");
9430
			}
9431
9432
			if ( !isDraggable && value ) {
9433
				this._makeDraggable();
9434
			}
9435
		}
9436
9437
		if ( key === "position" ) {
9438
			this._position();
9439
		}
9440
9441
		if ( key === "resizable" ) {
9442
			// currently resizable, becoming non-resizable
9443
			isResizable = uiDialog.is(":data(ui-resizable)");
9444
			if ( isResizable && !value ) {
9445
				uiDialog.resizable("destroy");
9446
			}
9447
9448
			// currently resizable, changing handles
9449
			if ( isResizable && typeof value === "string" ) {
9450
				uiDialog.resizable( "option", "handles", value );
9451
			}
9452
9453
			// currently non-resizable, becoming resizable
9454
			if ( !isResizable && value !== false ) {
9455
				this._makeResizable();
9456
			}
9457
		}
9458
9459
		if ( key === "title" ) {
9460
			this._title( this.uiDialogTitlebar.find(".ui-dialog-title") );
9461
		}
9462
	},
9463
9464
	_size: function() {
9465
		// If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
9466
		// divs will both have width and height set, so we need to reset them
9467
		var nonContentHeight, minContentHeight, maxContentHeight,
9468
			options = this.options;
9469
9470
		// Reset content sizing
9471
		this.element.show().css({
9472
			width: "auto",
9473
			minHeight: 0,
9474
			maxHeight: "none",
9475
			height: 0
9476
		});
9477
9478
		if ( options.minWidth > options.width ) {
9479
			options.width = options.minWidth;
9480
		}
9481
9482
		// reset wrapper sizing
9483
		// determine the height of all the non-content elements
9484
		nonContentHeight = this.uiDialog.css({
9485
				height: "auto",
9486
				width: options.width
9487
			})
9488
			.outerHeight();
9489
		minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
9490
		maxContentHeight = typeof options.maxHeight === "number" ?
9491
			Math.max( 0, options.maxHeight - nonContentHeight ) :
9492
			"none";
9493
9494
		if ( options.height === "auto" ) {
9495
			this.element.css({
9496
				minHeight: minContentHeight,
9497
				maxHeight: maxContentHeight,
9498
				height: "auto"
9499
			});
9500
		} else {
9501
			this.element.height( Math.max( 0, options.height - nonContentHeight ) );
9502
		}
9503
9504
		if (this.uiDialog.is(":data(ui-resizable)") ) {
9505
			this.uiDialog.resizable( "option", "minHeight", this._minHeight() );
9506
		}
9507
	},
9508
9509
	_blockFrames: function() {
9510
		this.iframeBlocks = this.document.find( "iframe" ).map(function() {
9511
			var iframe = $( this );
9512
9513
			return $( "<div>" )
9514
				.css({
9515
					position: "absolute",
9516
					width: iframe.outerWidth(),
9517
					height: iframe.outerHeight()
9518
				})
9519
				.appendTo( iframe.parent() )
9520
				.offset( iframe.offset() )[0];
9521
		});
9522
	},
9523
9524
	_unblockFrames: function() {
9525
		if ( this.iframeBlocks ) {
9526
			this.iframeBlocks.remove();
9527
			delete this.iframeBlocks;
9528
		}
9529
	},
9530
9531
	_allowInteraction: function( event ) {
9532
		if ( $( event.target ).closest(".ui-dialog").length ) {
9533
			return true;
9534
		}
9535
9536
		// TODO: Remove hack when datepicker implements
9537
		// the .ui-front logic (#8989)
9538
		return !!$( event.target ).closest(".ui-datepicker").length;
9539
	},
9540
9541
	_createOverlay: function() {
9542
		if ( !this.options.modal ) {
9543
			return;
9544
		}
9545
9546
		var that = this,
9547
			widgetFullName = this.widgetFullName;
9548
		if ( !$.ui.dialog.overlayInstances ) {
9549
			// Prevent use of anchors and inputs.
9550
			// We use a delay in case the overlay is created from an
9551
			// event that we're going to be cancelling. (#2804)
9552
			this._delay(function() {
9553
				// Handle .dialog().dialog("close") (#4065)
9554
				if ( $.ui.dialog.overlayInstances ) {
9555
					this.document.bind( "focusin.dialog", function( event ) {
9556
						if ( !that._allowInteraction( event ) ) {
9557
							event.preventDefault();
9558
							$(".ui-dialog:visible:last .ui-dialog-content")
9559
								.data( widgetFullName )._focusTabbable();
9560
						}
9561
					});
9562
				}
9563
			});
9564
		}
9565
9566
		this.overlay = $("<div>")
9567
			.addClass("ui-widget-overlay ui-front")
9568
			.appendTo( this._appendTo() );
9569
		this._on( this.overlay, {
9570
			mousedown: "_keepFocus"
9571
		});
9572
		$.ui.dialog.overlayInstances++;
9573
	},
9574
9575
	_destroyOverlay: function() {
9576
		if ( !this.options.modal ) {
9577
			return;
9578
		}
9579
9580
		if ( this.overlay ) {
9581
			$.ui.dialog.overlayInstances--;
9582
9583
			if ( !$.ui.dialog.overlayInstances ) {
9584
				this.document.unbind( "focusin.dialog" );
9585
			}
9586
			this.overlay.remove();
9587
			this.overlay = null;
9588
		}
9589
	}
9590
});
9591
9592
$.ui.dialog.overlayInstances = 0;
9593
9594
// DEPRECATED
9595
if ( $.uiBackCompat !== false ) {
9596
	// position option with array notation
9597
	// just override with old implementation
9598
	$.widget( "ui.dialog", $.ui.dialog, {
9599
		_position: function() {
9600
			var position = this.options.position,
9601
				myAt = [],
0 ignored issues
show
Unused Code introduced by
The assignment to variable myAt seems to be never used. Consider removing it.
Loading history...
9602
				offset = [ 0, 0 ],
9603
				isVisible;
9604
9605
			if ( position ) {
9606
				if ( typeof position === "string" || (typeof position === "object" && "0" in position ) ) {
9607
					myAt = position.split ? position.split(" ") : [ position[0], position[1] ];
9608
					if ( myAt.length === 1 ) {
9609
						myAt[1] = myAt[0];
9610
					}
9611
9612
					$.each( [ "left", "top" ], function( i, offsetPosition ) {
9613
						if ( +myAt[ i ] === myAt[ i ] ) {
9614
							offset[ i ] = myAt[ i ];
9615
							myAt[ i ] = offsetPosition;
9616
						}
9617
					});
9618
9619
					position = {
9620
						my: myAt[0] + (offset[0] < 0 ? offset[0] : "+" + offset[0]) + " " +
9621
							myAt[1] + (offset[1] < 0 ? offset[1] : "+" + offset[1]),
9622
						at: myAt.join(" ")
9623
					};
9624
				}
9625
9626
				position = $.extend( {}, $.ui.dialog.prototype.options.position, position );
9627
			} else {
9628
				position = $.ui.dialog.prototype.options.position;
9629
			}
9630
9631
			// need to show the dialog to get the actual offset in the position plugin
9632
			isVisible = this.uiDialog.is(":visible");
9633
			if ( !isVisible ) {
9634
				this.uiDialog.show();
9635
			}
9636
			this.uiDialog.position( position );
9637
			if ( !isVisible ) {
9638
				this.uiDialog.hide();
9639
			}
9640
		}
9641
	});
9642
}
9643
9644
}( jQuery ) );
9645
(function( $, undefined ) {
0 ignored issues
show
Unused Code introduced by
The parameter undefined is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
9646
9647
$.widget( "ui.menu", {
9648
	version: "1.10.4",
9649
	defaultElement: "<ul>",
9650
	delay: 300,
9651
	options: {
9652
		icons: {
9653
			submenu: "ui-icon-carat-1-e"
9654
		},
9655
		menus: "ul",
9656
		position: {
9657
			my: "left top",
9658
			at: "right top"
9659
		},
9660
		role: "menu",
9661
9662
		// callbacks
9663
		blur: null,
9664
		focus: null,
9665
		select: null
9666
	},
9667
9668
	_create: function() {
9669
		this.activeMenu = this.element;
9670
		// flag used to prevent firing of the click handler
9671
		// as the event bubbles up through nested menus
9672
		this.mouseHandled = false;
9673
		this.element
9674
			.uniqueId()
9675
			.addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" )
9676
			.toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length )
9677
			.attr({
9678
				role: this.options.role,
9679
				tabIndex: 0
9680
			})
9681
			// need to catch all clicks on disabled menu
9682
			// not possible through _on
9683
			.bind( "click" + this.eventNamespace, $.proxy(function( event ) {
9684
				if ( this.options.disabled ) {
9685
					event.preventDefault();
9686
				}
9687
			}, this ));
9688
9689
		if ( this.options.disabled ) {
9690
			this.element
9691
				.addClass( "ui-state-disabled" )
9692
				.attr( "aria-disabled", "true" );
9693
		}
9694
9695
		this._on({
9696
			// Prevent focus from sticking to links inside menu after clicking
9697
			// them (focus should always stay on UL during navigation).
9698
			"mousedown .ui-menu-item > a": function( event ) {
9699
				event.preventDefault();
9700
			},
9701
			"click .ui-state-disabled > a": function( event ) {
9702
				event.preventDefault();
9703
			},
9704
			"click .ui-menu-item:has(a)": function( event ) {
9705
				var target = $( event.target ).closest( ".ui-menu-item" );
9706
				if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) {
9707
					this.select( event );
9708
9709
					// Only set the mouseHandled flag if the event will bubble, see #9469.
9710
					if ( !event.isPropagationStopped() ) {
9711
						this.mouseHandled = true;
9712
					}
9713
9714
					// Open submenu on click
9715
					if ( target.has( ".ui-menu" ).length ) {
9716
						this.expand( event );
9717
					} else if ( !this.element.is( ":focus" ) && $( this.document[ 0 ].activeElement ).closest( ".ui-menu" ).length ) {
9718
9719
						// Redirect focus to the menu
9720
						this.element.trigger( "focus", [ true ] );
9721
9722
						// If the active item is on the top level, let it stay active.
9723
						// Otherwise, blur the active item since it is no longer visible.
9724
						if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {
9725
							clearTimeout( this.timer );
9726
						}
9727
					}
9728
				}
9729
			},
9730
			"mouseenter .ui-menu-item": function( event ) {
9731
				var target = $( event.currentTarget );
9732
				// Remove ui-state-active class from siblings of the newly focused menu item
9733
				// to avoid a jump caused by adjacent elements both having a class with a border
9734
				target.siblings().children( ".ui-state-active" ).removeClass( "ui-state-active" );
9735
				this.focus( event, target );
9736
			},
9737
			mouseleave: "collapseAll",
9738
			"mouseleave .ui-menu": "collapseAll",
9739
			focus: function( event, keepActiveItem ) {
9740
				// If there's already an active item, keep it active
9741
				// If not, activate the first item
9742
				var item = this.active || this.element.children( ".ui-menu-item" ).eq( 0 );
9743
9744
				if ( !keepActiveItem ) {
9745
					this.focus( event, item );
9746
				}
9747
			},
9748
			blur: function( event ) {
9749
				this._delay(function() {
9750
					if ( !$.contains( this.element[0], this.document[0].activeElement ) ) {
9751
						this.collapseAll( event );
9752
					}
9753
				});
9754
			},
9755
			keydown: "_keydown"
9756
		});
9757
9758
		this.refresh();
9759
9760
		// Clicks outside of a menu collapse any open menus
9761
		this._on( this.document, {
9762
			click: function( event ) {
9763
				if ( !$( event.target ).closest( ".ui-menu" ).length ) {
9764
					this.collapseAll( event );
9765
				}
9766
9767
				// Reset the mouseHandled flag
9768
				this.mouseHandled = false;
9769
			}
9770
		});
9771
	},
9772
9773
	_destroy: function() {
9774
		// Destroy (sub)menus
9775
		this.element
9776
			.removeAttr( "aria-activedescendant" )
9777
			.find( ".ui-menu" ).addBack()
9778
				.removeClass( "ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons" )
9779
				.removeAttr( "role" )
9780
				.removeAttr( "tabIndex" )
9781
				.removeAttr( "aria-labelledby" )
9782
				.removeAttr( "aria-expanded" )
9783
				.removeAttr( "aria-hidden" )
9784
				.removeAttr( "aria-disabled" )
9785
				.removeUniqueId()
9786
				.show();
9787
9788
		// Destroy menu items
9789
		this.element.find( ".ui-menu-item" )
9790
			.removeClass( "ui-menu-item" )
9791
			.removeAttr( "role" )
9792
			.removeAttr( "aria-disabled" )
9793
			.children( "a" )
9794
				.removeUniqueId()
9795
				.removeClass( "ui-corner-all ui-state-hover" )
9796
				.removeAttr( "tabIndex" )
9797
				.removeAttr( "role" )
9798
				.removeAttr( "aria-haspopup" )
9799
				.children().each( function() {
9800
					var elem = $( this );
9801
					if ( elem.data( "ui-menu-submenu-carat" ) ) {
9802
						elem.remove();
9803
					}
9804
				});
9805
9806
		// Destroy menu dividers
9807
		this.element.find( ".ui-menu-divider" ).removeClass( "ui-menu-divider ui-widget-content" );
9808
	},
9809
9810
	_keydown: function( event ) {
9811
		var match, prev, character, skip, regex,
9812
			preventDefault = true;
9813
9814
		function escape( value ) {
9815
			return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
9816
		}
9817
9818
		switch ( event.keyCode ) {
9819
		case $.ui.keyCode.PAGE_UP:
9820
			this.previousPage( event );
9821
			break;
9822
		case $.ui.keyCode.PAGE_DOWN:
9823
			this.nextPage( event );
9824
			break;
9825
		case $.ui.keyCode.HOME:
9826
			this._move( "first", "first", event );
9827
			break;
9828
		case $.ui.keyCode.END:
9829
			this._move( "last", "last", event );
9830
			break;
9831
		case $.ui.keyCode.UP:
9832
			this.previous( event );
9833
			break;
9834
		case $.ui.keyCode.DOWN:
9835
			this.next( event );
9836
			break;
9837
		case $.ui.keyCode.LEFT:
9838
			this.collapse( event );
9839
			break;
9840
		case $.ui.keyCode.RIGHT:
9841
			if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
9842
				this.expand( event );
9843
			}
9844
			break;
9845
		case $.ui.keyCode.ENTER:
9846
		case $.ui.keyCode.SPACE:
9847
			this._activate( event );
9848
			break;
9849
		case $.ui.keyCode.ESCAPE:
9850
			this.collapse( event );
9851
			break;
9852
		default:
9853
			preventDefault = false;
9854
			prev = this.previousFilter || "";
9855
			character = String.fromCharCode( event.keyCode );
9856
			skip = false;
9857
9858
			clearTimeout( this.filterTimer );
9859
9860
			if ( character === prev ) {
9861
				skip = true;
9862
			} else {
9863
				character = prev + character;
9864
			}
9865
9866
			regex = new RegExp( "^" + escape( character ), "i" );
9867
			match = this.activeMenu.children( ".ui-menu-item" ).filter(function() {
9868
				return regex.test( $( this ).children( "a" ).text() );
9869
			});
9870
			match = skip && match.index( this.active.next() ) !== -1 ?
9871
				this.active.nextAll( ".ui-menu-item" ) :
9872
				match;
9873
9874
			// If no matches on the current filter, reset to the last character pressed
9875
			// to move down the menu to the first item that starts with that character
9876
			if ( !match.length ) {
9877
				character = String.fromCharCode( event.keyCode );
9878
				regex = new RegExp( "^" + escape( character ), "i" );
9879
				match = this.activeMenu.children( ".ui-menu-item" ).filter(function() {
9880
					return regex.test( $( this ).children( "a" ).text() );
9881
				});
9882
			}
9883
9884
			if ( match.length ) {
9885
				this.focus( event, match );
9886
				if ( match.length > 1 ) {
9887
					this.previousFilter = character;
9888
					this.filterTimer = this._delay(function() {
9889
						delete this.previousFilter;
9890
					}, 1000 );
9891
				} else {
9892
					delete this.previousFilter;
9893
				}
9894
			} else {
9895
				delete this.previousFilter;
9896
			}
9897
		}
9898
9899
		if ( preventDefault ) {
9900
			event.preventDefault();
9901
		}
9902
	},
9903
9904
	_activate: function( event ) {
9905
		if ( !this.active.is( ".ui-state-disabled" ) ) {
9906
			if ( this.active.children( "a[aria-haspopup='true']" ).length ) {
9907
				this.expand( event );
9908
			} else {
9909
				this.select( event );
9910
			}
9911
		}
9912
	},
9913
9914
	refresh: function() {
9915
		var menus,
9916
			icon = this.options.icons.submenu,
9917
			submenus = this.element.find( this.options.menus );
9918
9919
		this.element.toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length );
9920
9921
		// Initialize nested menus
9922
		submenus.filter( ":not(.ui-menu)" )
9923
			.addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" )
9924
			.hide()
9925
			.attr({
9926
				role: this.options.role,
9927
				"aria-hidden": "true",
9928
				"aria-expanded": "false"
9929
			})
9930
			.each(function() {
9931
				var menu = $( this ),
9932
					item = menu.prev( "a" ),
9933
					submenuCarat = $( "<span>" )
9934
						.addClass( "ui-menu-icon ui-icon " + icon )
9935
						.data( "ui-menu-submenu-carat", true );
9936
9937
				item
9938
					.attr( "aria-haspopup", "true" )
9939
					.prepend( submenuCarat );
9940
				menu.attr( "aria-labelledby", item.attr( "id" ) );
9941
			});
9942
9943
		menus = submenus.add( this.element );
9944
9945
		// Don't refresh list items that are already adapted
9946
		menus.children( ":not(.ui-menu-item):has(a)" )
9947
			.addClass( "ui-menu-item" )
9948
			.attr( "role", "presentation" )
9949
			.children( "a" )
9950
				.uniqueId()
9951
				.addClass( "ui-corner-all" )
9952
				.attr({
9953
					tabIndex: -1,
9954
					role: this._itemRole()
9955
				});
9956
9957
		// Initialize unlinked menu-items containing spaces and/or dashes only as dividers
9958
		menus.children( ":not(.ui-menu-item)" ).each(function() {
9959
			var item = $( this );
9960
			// hyphen, em dash, en dash
9961
			if ( !/[^\-\u2014\u2013\s]/.test( item.text() ) ) {
9962
				item.addClass( "ui-widget-content ui-menu-divider" );
9963
			}
9964
		});
9965
9966
		// Add aria-disabled attribute to any disabled menu item
9967
		menus.children( ".ui-state-disabled" ).attr( "aria-disabled", "true" );
9968
9969
		// If the active item has been removed, blur the menu
9970
		if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
9971
			this.blur();
9972
		}
9973
	},
9974
9975
	_itemRole: function() {
9976
		return {
9977
			menu: "menuitem",
9978
			listbox: "option"
9979
		}[ this.options.role ];
9980
	},
9981
9982
	_setOption: function( key, value ) {
9983
		if ( key === "icons" ) {
9984
			this.element.find( ".ui-menu-icon" )
9985
				.removeClass( this.options.icons.submenu )
9986
				.addClass( value.submenu );
9987
		}
9988
		this._super( key, value );
9989
	},
9990
9991
	focus: function( event, item ) {
9992
		var nested, focused;
9993
		this.blur( event, event && event.type === "focus" );
9994
9995
		this._scrollIntoView( item );
9996
9997
		this.active = item.first();
9998
		focused = this.active.children( "a" ).addClass( "ui-state-focus" );
9999
		// Only update aria-activedescendant if there's a role
10000
		// otherwise we assume focus is managed elsewhere
10001
		if ( this.options.role ) {
10002
			this.element.attr( "aria-activedescendant", focused.attr( "id" ) );
10003
		}
10004
10005
		// Highlight active parent menu item, if any
10006
		this.active
10007
			.parent()
10008
			.closest( ".ui-menu-item" )
10009
			.children( "a:first" )
10010
			.addClass( "ui-state-active" );
10011
10012
		if ( event && event.type === "keydown" ) {
10013
			this._close();
10014
		} else {
10015
			this.timer = this._delay(function() {
10016
				this._close();
10017
			}, this.delay );
10018
		}
10019
10020
		nested = item.children( ".ui-menu" );
10021
		if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) {
10022
			this._startOpening(nested);
10023
		}
10024
		this.activeMenu = item.parent();
10025
10026
		this._trigger( "focus", event, { item: item } );
10027
	},
10028
10029
	_scrollIntoView: function( item ) {
10030
		var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
10031
		if ( this._hasScroll() ) {
10032
			borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0;
10033
			paddingTop = parseFloat( $.css( this.activeMenu[0], "paddingTop" ) ) || 0;
10034
			offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
10035
			scroll = this.activeMenu.scrollTop();
10036
			elementHeight = this.activeMenu.height();
10037
			itemHeight = item.height();
10038
10039
			if ( offset < 0 ) {
10040
				this.activeMenu.scrollTop( scroll + offset );
10041
			} else if ( offset + itemHeight > elementHeight ) {
10042
				this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
10043
			}
10044
		}
10045
	},
10046
10047
	blur: function( event, fromFocus ) {
10048
		if ( !fromFocus ) {
10049
			clearTimeout( this.timer );
10050
		}
10051
10052
		if ( !this.active ) {
10053
			return;
10054
		}
10055
10056
		this.active.children( "a" ).removeClass( "ui-state-focus" );
10057
		this.active = null;
10058
10059
		this._trigger( "blur", event, { item: this.active } );
10060
	},
10061
10062
	_startOpening: function( submenu ) {
10063
		clearTimeout( this.timer );
10064
10065
		// Don't open if already open fixes a Firefox bug that caused a .5 pixel
10066
		// shift in the submenu position when mousing over the carat icon
10067
		if ( submenu.attr( "aria-hidden" ) !== "true" ) {
10068
			return;
10069
		}
10070
10071
		this.timer = this._delay(function() {
10072
			this._close();
10073
			this._open( submenu );
10074
		}, this.delay );
10075
	},
10076
10077
	_open: function( submenu ) {
10078
		var position = $.extend({
10079
			of: this.active
10080
		}, this.options.position );
10081
10082
		clearTimeout( this.timer );
10083
		this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )
10084
			.hide()
10085
			.attr( "aria-hidden", "true" );
10086
10087
		submenu
10088
			.show()
10089
			.removeAttr( "aria-hidden" )
10090
			.attr( "aria-expanded", "true" )
10091
			.position( position );
10092
	},
10093
10094
	collapseAll: function( event, all ) {
10095
		clearTimeout( this.timer );
10096
		this.timer = this._delay(function() {
10097
			// If we were passed an event, look for the submenu that contains the event
10098
			var currentMenu = all ? this.element :
10099
				$( event && event.target ).closest( this.element.find( ".ui-menu" ) );
10100
10101
			// If we found no valid submenu ancestor, use the main menu to close all sub menus anyway
10102
			if ( !currentMenu.length ) {
10103
				currentMenu = this.element;
10104
			}
10105
10106
			this._close( currentMenu );
10107
10108
			this.blur( event );
10109
			this.activeMenu = currentMenu;
10110
		}, this.delay );
10111
	},
10112
10113
	// With no arguments, closes the currently active menu - if nothing is active
10114
	// it closes all menus.  If passed an argument, it will search for menus BELOW
10115
	_close: function( startMenu ) {
10116
		if ( !startMenu ) {
10117
			startMenu = this.active ? this.active.parent() : this.element;
10118
		}
10119
10120
		startMenu
10121
			.find( ".ui-menu" )
10122
				.hide()
10123
				.attr( "aria-hidden", "true" )
10124
				.attr( "aria-expanded", "false" )
10125
			.end()
10126
			.find( "a.ui-state-active" )
10127
				.removeClass( "ui-state-active" );
10128
	},
10129
10130
	collapse: function( event ) {
10131
		var newItem = this.active &&
10132
			this.active.parent().closest( ".ui-menu-item", this.element );
10133
		if ( newItem && newItem.length ) {
10134
			this._close();
10135
			this.focus( event, newItem );
10136
		}
10137
	},
10138
10139
	expand: function( event ) {
10140
		var newItem = this.active &&
10141
			this.active
10142
				.children( ".ui-menu " )
10143
				.children( ".ui-menu-item" )
10144
				.first();
10145
10146
		if ( newItem && newItem.length ) {
10147
			this._open( newItem.parent() );
10148
10149
			// Delay so Firefox will not hide activedescendant change in expanding submenu from AT
10150
			this._delay(function() {
10151
				this.focus( event, newItem );
10152
			});
10153
		}
10154
	},
10155
10156
	next: function( event ) {
10157
		this._move( "next", "first", event );
10158
	},
10159
10160
	previous: function( event ) {
10161
		this._move( "prev", "last", event );
10162
	},
10163
10164
	isFirstItem: function() {
10165
		return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
10166
	},
10167
10168
	isLastItem: function() {
10169
		return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
10170
	},
10171
10172
	_move: function( direction, filter, event ) {
10173
		var next;
10174
		if ( this.active ) {
10175
			if ( direction === "first" || direction === "last" ) {
10176
				next = this.active
10177
					[ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
10178
					.eq( -1 );
10179
			} else {
10180
				next = this.active
10181
					[ direction + "All" ]( ".ui-menu-item" )
10182
					.eq( 0 );
10183
			}
10184
		}
10185
		if ( !next || !next.length || !this.active ) {
10186
			next = this.activeMenu.children( ".ui-menu-item" )[ filter ]();
10187
		}
10188
10189
		this.focus( event, next );
10190
	},
10191
10192
	nextPage: function( event ) {
10193
		var item, base, height;
10194
10195
		if ( !this.active ) {
10196
			this.next( event );
10197
			return;
10198
		}
10199
		if ( this.isLastItem() ) {
10200
			return;
10201
		}
10202
		if ( this._hasScroll() ) {
10203
			base = this.active.offset().top;
10204
			height = this.element.height();
10205
			this.active.nextAll( ".ui-menu-item" ).each(function() {
10206
				item = $( this );
10207
				return item.offset().top - base - height < 0;
10208
			});
10209
10210
			this.focus( event, item );
10211
		} else {
10212
			this.focus( event, this.activeMenu.children( ".ui-menu-item" )
10213
				[ !this.active ? "first" : "last" ]() );
10214
		}
10215
	},
10216
10217
	previousPage: function( event ) {
10218
		var item, base, height;
10219
		if ( !this.active ) {
10220
			this.next( event );
10221
			return;
10222
		}
10223
		if ( this.isFirstItem() ) {
10224
			return;
10225
		}
10226
		if ( this._hasScroll() ) {
10227
			base = this.active.offset().top;
10228
			height = this.element.height();
10229
			this.active.prevAll( ".ui-menu-item" ).each(function() {
10230
				item = $( this );
10231
				return item.offset().top - base + height > 0;
10232
			});
10233
10234
			this.focus( event, item );
10235
		} else {
10236
			this.focus( event, this.activeMenu.children( ".ui-menu-item" ).first() );
10237
		}
10238
	},
10239
10240
	_hasScroll: function() {
10241
		return this.element.outerHeight() < this.element.prop( "scrollHeight" );
10242
	},
10243
10244
	select: function( event ) {
10245
		// TODO: It should never be possible to not have an active item at this
10246
		// point, but the tests don't trigger mouseenter before click.
10247
		this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
10248
		var ui = { item: this.active };
10249
		if ( !this.active.has( ".ui-menu" ).length ) {
10250
			this.collapseAll( event, true );
10251
		}
10252
		this._trigger( "select", event, ui );
10253
	}
10254
});
10255
10256
}( jQuery ));
10257
(function( $, undefined ) {
10258
10259
$.widget( "ui.progressbar", {
10260
	version: "1.10.4",
10261
	options: {
10262
		max: 100,
10263
		value: 0,
10264
10265
		change: null,
10266
		complete: null
10267
	},
10268
10269
	min: 0,
10270
10271
	_create: function() {
10272
		// Constrain initial value
10273
		this.oldValue = this.options.value = this._constrainedValue();
10274
10275
		this.element
10276
			.addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
10277
			.attr({
10278
				// Only set static values, aria-valuenow and aria-valuemax are
10279
				// set inside _refreshValue()
10280
				role: "progressbar",
10281
				"aria-valuemin": this.min
10282
			});
10283
10284
		this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
10285
			.appendTo( this.element );
10286
10287
		this._refreshValue();
10288
	},
10289
10290
	_destroy: function() {
10291
		this.element
10292
			.removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
10293
			.removeAttr( "role" )
10294
			.removeAttr( "aria-valuemin" )
10295
			.removeAttr( "aria-valuemax" )
10296
			.removeAttr( "aria-valuenow" );
10297
10298
		this.valueDiv.remove();
10299
	},
10300
10301
	value: function( newValue ) {
10302
		if ( newValue === undefined ) {
10303
			return this.options.value;
10304
		}
10305
10306
		this.options.value = this._constrainedValue( newValue );
10307
		this._refreshValue();
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
10308
	},
10309
10310
	_constrainedValue: function( newValue ) {
10311
		if ( newValue === undefined ) {
10312
			newValue = this.options.value;
10313
		}
10314
10315
		this.indeterminate = newValue === false;
10316
10317
		// sanitize value
10318
		if ( typeof newValue !== "number" ) {
10319
			newValue = 0;
10320
		}
10321
10322
		return this.indeterminate ? false :
10323
			Math.min( this.options.max, Math.max( this.min, newValue ) );
10324
	},
10325
10326
	_setOptions: function( options ) {
10327
		// Ensure "value" option is set after other values (like max)
10328
		var value = options.value;
10329
		delete options.value;
10330
10331
		this._super( options );
10332
10333
		this.options.value = this._constrainedValue( value );
10334
		this._refreshValue();
10335
	},
10336
10337
	_setOption: function( key, value ) {
10338
		if ( key === "max" ) {
10339
			// Don't allow a max less than min
10340
			value = Math.max( this.min, value );
10341
		}
10342
10343
		this._super( key, value );
10344
	},
10345
10346
	_percentage: function() {
10347
		return this.indeterminate ? 100 : 100 * ( this.options.value - this.min ) / ( this.options.max - this.min );
10348
	},
10349
10350
	_refreshValue: function() {
10351
		var value = this.options.value,
10352
			percentage = this._percentage();
10353
10354
		this.valueDiv
10355
			.toggle( this.indeterminate || value > this.min )
10356
			.toggleClass( "ui-corner-right", value === this.options.max )
10357
			.width( percentage.toFixed(0) + "%" );
10358
10359
		this.element.toggleClass( "ui-progressbar-indeterminate", this.indeterminate );
10360
10361
		if ( this.indeterminate ) {
10362
			this.element.removeAttr( "aria-valuenow" );
10363
			if ( !this.overlayDiv ) {
10364
				this.overlayDiv = $( "<div class='ui-progressbar-overlay'></div>" ).appendTo( this.valueDiv );
10365
			}
10366
		} else {
10367
			this.element.attr({
10368
				"aria-valuemax": this.options.max,
10369
				"aria-valuenow": value
10370
			});
10371
			if ( this.overlayDiv ) {
10372
				this.overlayDiv.remove();
10373
				this.overlayDiv = null;
10374
			}
10375
		}
10376
10377
		if ( this.oldValue !== value ) {
10378
			this.oldValue = value;
10379
			this._trigger( "change" );
10380
		}
10381
		if ( value === this.options.max ) {
10382
			this._trigger( "complete" );
10383
		}
10384
	}
10385
});
10386
10387
})( jQuery );
10388
(function( $, undefined ) {
0 ignored issues
show
Unused Code introduced by
The parameter undefined is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
10389
10390
// number of pages in a slider
10391
// (how many times can you page up/down to go through the whole range)
10392
var numPages = 5;
10393
10394
$.widget( "ui.slider", $.ui.mouse, {
10395
	version: "1.10.4",
10396
	widgetEventPrefix: "slide",
10397
10398
	options: {
10399
		animate: false,
10400
		distance: 0,
10401
		max: 100,
10402
		min: 0,
10403
		orientation: "horizontal",
10404
		range: false,
10405
		step: 1,
10406
		value: 0,
10407
		values: null,
10408
10409
		// callbacks
10410
		change: null,
10411
		slide: null,
10412
		start: null,
10413
		stop: null
10414
	},
10415
10416
	_create: function() {
10417
		this._keySliding = false;
10418
		this._mouseSliding = false;
10419
		this._animateOff = true;
10420
		this._handleIndex = null;
10421
		this._detectOrientation();
10422
		this._mouseInit();
10423
10424
		this.element
10425
			.addClass( "ui-slider" +
10426
				" ui-slider-" + this.orientation +
10427
				" ui-widget" +
10428
				" ui-widget-content" +
10429
				" ui-corner-all");
10430
10431
		this._refresh();
10432
		this._setOption( "disabled", this.options.disabled );
10433
10434
		this._animateOff = false;
10435
	},
10436
10437
	_refresh: function() {
10438
		this._createRange();
10439
		this._createHandles();
10440
		this._setupEvents();
10441
		this._refreshValue();
10442
	},
10443
10444
	_createHandles: function() {
10445
		var i, handleCount,
10446
			options = this.options,
10447
			existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ),
10448
			handle = "<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",
10449
			handles = [];
10450
10451
		handleCount = ( options.values && options.values.length ) || 1;
10452
10453
		if ( existingHandles.length > handleCount ) {
10454
			existingHandles.slice( handleCount ).remove();
10455
			existingHandles = existingHandles.slice( 0, handleCount );
10456
		}
10457
10458
		for ( i = existingHandles.length; i < handleCount; i++ ) {
10459
			handles.push( handle );
10460
		}
10461
10462
		this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) );
10463
10464
		this.handle = this.handles.eq( 0 );
10465
10466
		this.handles.each(function( i ) {
10467
			$( this ).data( "ui-slider-handle-index", i );
10468
		});
10469
	},
10470
10471
	_createRange: function() {
10472
		var options = this.options,
10473
			classes = "";
10474
10475
		if ( options.range ) {
10476
			if ( options.range === true ) {
10477
				if ( !options.values ) {
10478
					options.values = [ this._valueMin(), this._valueMin() ];
10479
				} else if ( options.values.length && options.values.length !== 2 ) {
10480
					options.values = [ options.values[0], options.values[0] ];
10481
				} else if ( $.isArray( options.values ) ) {
10482
					options.values = options.values.slice(0);
10483
				}
10484
			}
10485
10486
			if ( !this.range || !this.range.length ) {
10487
				this.range = $( "<div></div>" )
10488
					.appendTo( this.element );
10489
10490
				classes = "ui-slider-range" +
10491
				// note: this isn't the most fittingly semantic framework class for this element,
10492
				// but worked best visually with a variety of themes
10493
				" ui-widget-header ui-corner-all";
10494
			} else {
10495
				this.range.removeClass( "ui-slider-range-min ui-slider-range-max" )
10496
					// Handle range switching from true to min/max
10497
					.css({
10498
						"left": "",
10499
						"bottom": ""
10500
					});
10501
			}
10502
10503
			this.range.addClass( classes +
10504
				( ( options.range === "min" || options.range === "max" ) ? " ui-slider-range-" + options.range : "" ) );
10505
		} else {
10506
			if ( this.range ) {
10507
				this.range.remove();
10508
			}
10509
			this.range = null;
10510
		}
10511
	},
10512
10513
	_setupEvents: function() {
10514
		var elements = this.handles.add( this.range ).filter( "a" );
10515
		this._off( elements );
10516
		this._on( elements, this._handleEvents );
10517
		this._hoverable( elements );
10518
		this._focusable( elements );
10519
	},
10520
10521
	_destroy: function() {
10522
		this.handles.remove();
10523
		if ( this.range ) {
10524
			this.range.remove();
10525
		}
10526
10527
		this.element
10528
			.removeClass( "ui-slider" +
10529
				" ui-slider-horizontal" +
10530
				" ui-slider-vertical" +
10531
				" ui-widget" +
10532
				" ui-widget-content" +
10533
				" ui-corner-all" );
10534
10535
		this._mouseDestroy();
10536
	},
10537
10538
	_mouseCapture: function( event ) {
10539
		var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,
10540
			that = this,
10541
			o = this.options;
10542
10543
		if ( o.disabled ) {
10544
			return false;
10545
		}
10546
10547
		this.elementSize = {
10548
			width: this.element.outerWidth(),
10549
			height: this.element.outerHeight()
10550
		};
10551
		this.elementOffset = this.element.offset();
10552
10553
		position = { x: event.pageX, y: event.pageY };
10554
		normValue = this._normValueFromMouse( position );
10555
		distance = this._valueMax() - this._valueMin() + 1;
10556
		this.handles.each(function( i ) {
10557
			var thisDistance = Math.abs( normValue - that.values(i) );
10558
			if (( distance > thisDistance ) ||
10559
				( distance === thisDistance &&
10560
					(i === that._lastChangedValue || that.values(i) === o.min ))) {
10561
				distance = thisDistance;
10562
				closestHandle = $( this );
10563
				index = i;
10564
			}
10565
		});
10566
10567
		allowed = this._start( event, index );
10568
		if ( allowed === false ) {
10569
			return false;
10570
		}
10571
		this._mouseSliding = true;
10572
10573
		this._handleIndex = index;
10574
10575
		closestHandle
10576
			.addClass( "ui-state-active" )
10577
			.focus();
10578
10579
		offset = closestHandle.offset();
10580
		mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" );
10581
		this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
10582
			left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
10583
			top: event.pageY - offset.top -
10584
				( closestHandle.height() / 2 ) -
10585
				( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
10586
				( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
10587
				( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
10588
		};
10589
10590
		if ( !this.handles.hasClass( "ui-state-hover" ) ) {
10591
			this._slide( event, index, normValue );
10592
		}
10593
		this._animateOff = true;
10594
		return true;
10595
	},
10596
10597
	_mouseStart: function() {
10598
		return true;
10599
	},
10600
10601
	_mouseDrag: function( event ) {
10602
		var position = { x: event.pageX, y: event.pageY },
10603
			normValue = this._normValueFromMouse( position );
10604
10605
		this._slide( event, this._handleIndex, normValue );
10606
10607
		return false;
10608
	},
10609
10610
	_mouseStop: function( event ) {
10611
		this.handles.removeClass( "ui-state-active" );
10612
		this._mouseSliding = false;
10613
10614
		this._stop( event, this._handleIndex );
10615
		this._change( event, this._handleIndex );
10616
10617
		this._handleIndex = null;
10618
		this._clickOffset = null;
10619
		this._animateOff = false;
10620
10621
		return false;
10622
	},
10623
10624
	_detectOrientation: function() {
10625
		this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
10626
	},
10627
10628
	_normValueFromMouse: function( position ) {
10629
		var pixelTotal,
10630
			pixelMouse,
10631
			percentMouse,
10632
			valueTotal,
10633
			valueMouse;
10634
10635
		if ( this.orientation === "horizontal" ) {
10636
			pixelTotal = this.elementSize.width;
10637
			pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
10638
		} else {
10639
			pixelTotal = this.elementSize.height;
10640
			pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
10641
		}
10642
10643
		percentMouse = ( pixelMouse / pixelTotal );
10644
		if ( percentMouse > 1 ) {
10645
			percentMouse = 1;
10646
		}
10647
		if ( percentMouse < 0 ) {
10648
			percentMouse = 0;
10649
		}
10650
		if ( this.orientation === "vertical" ) {
10651
			percentMouse = 1 - percentMouse;
10652
		}
10653
10654
		valueTotal = this._valueMax() - this._valueMin();
10655
		valueMouse = this._valueMin() + percentMouse * valueTotal;
10656
10657
		return this._trimAlignValue( valueMouse );
10658
	},
10659
10660
	_start: function( event, index ) {
10661
		var uiHash = {
10662
			handle: this.handles[ index ],
10663
			value: this.value()
10664
		};
10665
		if ( this.options.values && this.options.values.length ) {
10666
			uiHash.value = this.values( index );
10667
			uiHash.values = this.values();
10668
		}
10669
		return this._trigger( "start", event, uiHash );
10670
	},
10671
10672
	_slide: function( event, index, newVal ) {
10673
		var otherVal,
10674
			newValues,
10675
			allowed;
10676
10677
		if ( this.options.values && this.options.values.length ) {
10678
			otherVal = this.values( index ? 0 : 1 );
10679
10680
			if ( ( this.options.values.length === 2 && this.options.range === true ) &&
10681
					( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
10682
				) {
10683
				newVal = otherVal;
10684
			}
10685
10686
			if ( newVal !== this.values( index ) ) {
10687
				newValues = this.values();
10688
				newValues[ index ] = newVal;
10689
				// A slide can be canceled by returning false from the slide callback
10690
				allowed = this._trigger( "slide", event, {
10691
					handle: this.handles[ index ],
10692
					value: newVal,
10693
					values: newValues
10694
				} );
10695
				otherVal = this.values( index ? 0 : 1 );
0 ignored issues
show
Unused Code introduced by
The assignment to variable otherVal seems to be never used. Consider removing it.
Loading history...
10696
				if ( allowed !== false ) {
10697
					this.values( index, newVal );
10698
				}
10699
			}
10700
		} else {
10701
			if ( newVal !== this.value() ) {
10702
				// A slide can be canceled by returning false from the slide callback
10703
				allowed = this._trigger( "slide", event, {
10704
					handle: this.handles[ index ],
10705
					value: newVal
10706
				} );
10707
				if ( allowed !== false ) {
10708
					this.value( newVal );
10709
				}
10710
			}
10711
		}
10712
	},
10713
10714
	_stop: function( event, index ) {
10715
		var uiHash = {
10716
			handle: this.handles[ index ],
10717
			value: this.value()
10718
		};
10719
		if ( this.options.values && this.options.values.length ) {
10720
			uiHash.value = this.values( index );
10721
			uiHash.values = this.values();
10722
		}
10723
10724
		this._trigger( "stop", event, uiHash );
10725
	},
10726
10727
	_change: function( event, index ) {
10728
		if ( !this._keySliding && !this._mouseSliding ) {
10729
			var uiHash = {
10730
				handle: this.handles[ index ],
10731
				value: this.value()
10732
			};
10733
			if ( this.options.values && this.options.values.length ) {
10734
				uiHash.value = this.values( index );
10735
				uiHash.values = this.values();
10736
			}
10737
10738
			//store the last changed value index for reference when handles overlap
10739
			this._lastChangedValue = index;
10740
10741
			this._trigger( "change", event, uiHash );
10742
		}
10743
	},
10744
10745
	value: function( newValue ) {
10746
		if ( arguments.length ) {
10747
			this.options.value = this._trimAlignValue( newValue );
10748
			this._refreshValue();
10749
			this._change( null, 0 );
10750
			return;
10751
		}
10752
10753
		return this._value();
10754
	},
10755
10756
	values: function( index, newValue ) {
10757
		var vals,
10758
			newValues,
10759
			i;
10760
10761
		if ( arguments.length > 1 ) {
10762
			this.options.values[ index ] = this._trimAlignValue( newValue );
10763
			this._refreshValue();
10764
			this._change( null, index );
10765
			return;
10766
		}
10767
10768
		if ( arguments.length ) {
10769
			if ( $.isArray( arguments[ 0 ] ) ) {
10770
				vals = this.options.values;
10771
				newValues = arguments[ 0 ];
10772
				for ( i = 0; i < vals.length; i += 1 ) {
10773
					vals[ i ] = this._trimAlignValue( newValues[ i ] );
10774
					this._change( null, i );
10775
				}
10776
				this._refreshValue();
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
10777
			} else {
10778
				if ( this.options.values && this.options.values.length ) {
10779
					return this._values( index );
10780
				} else {
10781
					return this.value();
10782
				}
10783
			}
10784
		} else {
10785
			return this._values();
10786
		}
10787
	},
10788
10789
	_setOption: function( key, value ) {
10790
		var i,
10791
			valsLength = 0;
10792
10793
		if ( key === "range" && this.options.range === true ) {
10794
			if ( value === "min" ) {
10795
				this.options.value = this._values( 0 );
10796
				this.options.values = null;
10797
			} else if ( value === "max" ) {
10798
				this.options.value = this._values( this.options.values.length-1 );
10799
				this.options.values = null;
10800
			}
10801
		}
10802
10803
		if ( $.isArray( this.options.values ) ) {
10804
			valsLength = this.options.values.length;
10805
		}
10806
10807
		$.Widget.prototype._setOption.apply( this, arguments );
10808
10809
		switch ( key ) {
0 ignored issues
show
Coding Style introduced by
As per coding-style, switch statements should have a default case.
Loading history...
10810
			case "orientation":
10811
				this._detectOrientation();
10812
				this.element
10813
					.removeClass( "ui-slider-horizontal ui-slider-vertical" )
10814
					.addClass( "ui-slider-" + this.orientation );
10815
				this._refreshValue();
10816
				break;
10817
			case "value":
10818
				this._animateOff = true;
10819
				this._refreshValue();
10820
				this._change( null, 0 );
10821
				this._animateOff = false;
10822
				break;
10823
			case "values":
10824
				this._animateOff = true;
10825
				this._refreshValue();
10826
				for ( i = 0; i < valsLength; i += 1 ) {
10827
					this._change( null, i );
10828
				}
10829
				this._animateOff = false;
10830
				break;
10831
			case "min":
10832
			case "max":
10833
				this._animateOff = true;
10834
				this._refreshValue();
10835
				this._animateOff = false;
10836
				break;
10837
			case "range":
10838
				this._animateOff = true;
10839
				this._refresh();
10840
				this._animateOff = false;
10841
				break;
10842
		}
10843
	},
10844
10845
	//internal value getter
10846
	// _value() returns value trimmed by min and max, aligned by step
10847
	_value: function() {
10848
		var val = this.options.value;
10849
		val = this._trimAlignValue( val );
10850
10851
		return val;
10852
	},
10853
10854
	//internal values getter
10855
	// _values() returns array of values trimmed by min and max, aligned by step
10856
	// _values( index ) returns single value trimmed by min and max, aligned by step
10857
	_values: function( index ) {
10858
		var val,
10859
			vals,
10860
			i;
10861
10862
		if ( arguments.length ) {
10863
			val = this.options.values[ index ];
10864
			val = this._trimAlignValue( val );
10865
10866
			return val;
10867
		} else if ( this.options.values && this.options.values.length ) {
10868
			// .slice() creates a copy of the array
10869
			// this copy gets trimmed by min and max and then returned
10870
			vals = this.options.values.slice();
10871
			for ( i = 0; i < vals.length; i+= 1) {
10872
				vals[ i ] = this._trimAlignValue( vals[ i ] );
10873
			}
10874
10875
			return vals;
10876
		} else {
10877
			return [];
10878
		}
10879
	},
10880
10881
	// returns the step-aligned value that val is closest to, between (inclusive) min and max
10882
	_trimAlignValue: function( val ) {
10883
		if ( val <= this._valueMin() ) {
10884
			return this._valueMin();
10885
		}
10886
		if ( val >= this._valueMax() ) {
10887
			return this._valueMax();
10888
		}
10889
		var step = ( this.options.step > 0 ) ? this.options.step : 1,
10890
			valModStep = (val - this._valueMin()) % step,
10891
			alignValue = val - valModStep;
10892
10893
		if ( Math.abs(valModStep) * 2 >= step ) {
10894
			alignValue += ( valModStep > 0 ) ? step : ( -step );
10895
		}
10896
10897
		// Since JavaScript has problems with large floats, round
10898
		// the final value to 5 digits after the decimal point (see #4124)
10899
		return parseFloat( alignValue.toFixed(5) );
10900
	},
10901
10902
	_valueMin: function() {
10903
		return this.options.min;
10904
	},
10905
10906
	_valueMax: function() {
10907
		return this.options.max;
10908
	},
10909
10910
	_refreshValue: function() {
10911
		var lastValPercent, valPercent, value, valueMin, valueMax,
10912
			oRange = this.options.range,
10913
			o = this.options,
10914
			that = this,
10915
			animate = ( !this._animateOff ) ? o.animate : false,
10916
			_set = {};
10917
10918
		if ( this.options.values && this.options.values.length ) {
10919
			this.handles.each(function( i ) {
10920
				valPercent = ( that.values(i) - that._valueMin() ) / ( that._valueMax() - that._valueMin() ) * 100;
10921
				_set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
10922
				$( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
10923
				if ( that.options.range === true ) {
10924
					if ( that.orientation === "horizontal" ) {
10925
						if ( i === 0 ) {
10926
							that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
10927
						}
10928
						if ( i === 1 ) {
10929
							that.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
10930
						}
10931
					} else {
10932
						if ( i === 0 ) {
10933
							that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
10934
						}
10935
						if ( i === 1 ) {
10936
							that.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
10937
						}
10938
					}
10939
				}
10940
				lastValPercent = valPercent;
10941
			});
10942
		} else {
10943
			value = this.value();
10944
			valueMin = this._valueMin();
10945
			valueMax = this._valueMax();
10946
			valPercent = ( valueMax !== valueMin ) ?
10947
					( value - valueMin ) / ( valueMax - valueMin ) * 100 :
10948
					0;
10949
			_set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
10950
			this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
10951
10952
			if ( oRange === "min" && this.orientation === "horizontal" ) {
10953
				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
10954
			}
10955
			if ( oRange === "max" && this.orientation === "horizontal" ) {
10956
				this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
10957
			}
10958
			if ( oRange === "min" && this.orientation === "vertical" ) {
10959
				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
10960
			}
10961
			if ( oRange === "max" && this.orientation === "vertical" ) {
10962
				this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
10963
			}
10964
		}
10965
	},
10966
10967
	_handleEvents: {
10968
		keydown: function( event ) {
10969
			var allowed, curVal, newVal, step,
10970
				index = $( event.target ).data( "ui-slider-handle-index" );
10971
10972
			switch ( event.keyCode ) {
0 ignored issues
show
Coding Style introduced by
As per coding-style, switch statements should have a default case.
Loading history...
10973
				case $.ui.keyCode.HOME:
10974
				case $.ui.keyCode.END:
10975
				case $.ui.keyCode.PAGE_UP:
10976
				case $.ui.keyCode.PAGE_DOWN:
10977
				case $.ui.keyCode.UP:
10978
				case $.ui.keyCode.RIGHT:
10979
				case $.ui.keyCode.DOWN:
10980
				case $.ui.keyCode.LEFT:
10981
					event.preventDefault();
10982
					if ( !this._keySliding ) {
10983
						this._keySliding = true;
10984
						$( event.target ).addClass( "ui-state-active" );
10985
						allowed = this._start( event, index );
10986
						if ( allowed === false ) {
10987
							return;
10988
						}
10989
					}
10990
					break;
10991
			}
10992
10993
			step = this.options.step;
10994
			if ( this.options.values && this.options.values.length ) {
10995
				curVal = newVal = this.values( index );
10996
			} else {
10997
				curVal = newVal = this.value();
10998
			}
10999
11000
			switch ( event.keyCode ) {
0 ignored issues
show
Coding Style introduced by
As per coding-style, switch statements should have a default case.
Loading history...
11001
				case $.ui.keyCode.HOME:
11002
					newVal = this._valueMin();
11003
					break;
11004
				case $.ui.keyCode.END:
11005
					newVal = this._valueMax();
11006
					break;
11007
				case $.ui.keyCode.PAGE_UP:
11008
					newVal = this._trimAlignValue( curVal + ( (this._valueMax() - this._valueMin()) / numPages ) );
11009
					break;
11010
				case $.ui.keyCode.PAGE_DOWN:
11011
					newVal = this._trimAlignValue( curVal - ( (this._valueMax() - this._valueMin()) / numPages ) );
11012
					break;
11013
				case $.ui.keyCode.UP:
11014
				case $.ui.keyCode.RIGHT:
11015
					if ( curVal === this._valueMax() ) {
11016
						return;
11017
					}
11018
					newVal = this._trimAlignValue( curVal + step );
11019
					break;
11020
				case $.ui.keyCode.DOWN:
11021
				case $.ui.keyCode.LEFT:
11022
					if ( curVal === this._valueMin() ) {
11023
						return;
11024
					}
11025
					newVal = this._trimAlignValue( curVal - step );
11026
					break;
11027
			}
11028
11029
			this._slide( event, index, newVal );
11030
		},
11031
		click: function( event ) {
11032
			event.preventDefault();
11033
		},
11034
		keyup: function( event ) {
11035
			var index = $( event.target ).data( "ui-slider-handle-index" );
11036
11037
			if ( this._keySliding ) {
11038
				this._keySliding = false;
11039
				this._stop( event, index );
11040
				this._change( event, index );
11041
				$( event.target ).removeClass( "ui-state-active" );
11042
			}
11043
		}
11044
	}
11045
11046
});
11047
11048
}(jQuery));
11049
(function( $ ) {
11050
11051
function modifier( fn ) {
11052
	return function() {
11053
		var previous = this.element.val();
11054
		fn.apply( this, arguments );
11055
		this._refresh();
11056
		if ( previous !== this.element.val() ) {
11057
			this._trigger( "change" );
11058
		}
11059
	};
11060
}
11061
11062
$.widget( "ui.spinner", {
11063
	version: "1.10.4",
11064
	defaultElement: "<input>",
11065
	widgetEventPrefix: "spin",
11066
	options: {
11067
		culture: null,
11068
		icons: {
11069
			down: "ui-icon-triangle-1-s",
11070
			up: "ui-icon-triangle-1-n"
11071
		},
11072
		incremental: true,
11073
		max: null,
11074
		min: null,
11075
		numberFormat: null,
11076
		page: 10,
11077
		step: 1,
11078
11079
		change: null,
11080
		spin: null,
11081
		start: null,
11082
		stop: null
11083
	},
11084
11085
	_create: function() {
11086
		// handle string values that need to be parsed
11087
		this._setOption( "max", this.options.max );
11088
		this._setOption( "min", this.options.min );
11089
		this._setOption( "step", this.options.step );
11090
11091
		// Only format if there is a value, prevents the field from being marked
11092
		// as invalid in Firefox, see #9573.
11093
		if ( this.value() !== "" ) {
11094
			// Format the value, but don't constrain.
11095
			this._value( this.element.val(), true );
11096
		}
11097
11098
		this._draw();
11099
		this._on( this._events );
11100
		this._refresh();
11101
11102
		// turning off autocomplete prevents the browser from remembering the
11103
		// value when navigating through history, so we re-enable autocomplete
11104
		// if the page is unloaded before the widget is destroyed. #7790
11105
		this._on( this.window, {
11106
			beforeunload: function() {
11107
				this.element.removeAttr( "autocomplete" );
11108
			}
11109
		});
11110
	},
11111
11112
	_getCreateOptions: function() {
11113
		var options = {},
11114
			element = this.element;
11115
11116
		$.each( [ "min", "max", "step" ], function( i, option ) {
11117
			var value = element.attr( option );
11118
			if ( value !== undefined && value.length ) {
11119
				options[ option ] = value;
11120
			}
11121
		});
11122
11123
		return options;
11124
	},
11125
11126
	_events: {
11127
		keydown: function( event ) {
11128
			if ( this._start( event ) && this._keydown( event ) ) {
11129
				event.preventDefault();
11130
			}
11131
		},
11132
		keyup: "_stop",
11133
		focus: function() {
11134
			this.previous = this.element.val();
11135
		},
11136
		blur: function( event ) {
11137
			if ( this.cancelBlur ) {
11138
				delete this.cancelBlur;
11139
				return;
11140
			}
11141
11142
			this._stop();
11143
			this._refresh();
11144
			if ( this.previous !== this.element.val() ) {
11145
				this._trigger( "change", event );
11146
			}
11147
		},
11148
		mousewheel: function( event, delta ) {
11149
			if ( !delta ) {
11150
				return;
11151
			}
11152
			if ( !this.spinning && !this._start( event ) ) {
11153
				return false;
11154
			}
11155
11156
			this._spin( (delta > 0 ? 1 : -1) * this.options.step, event );
11157
			clearTimeout( this.mousewheelTimer );
11158
			this.mousewheelTimer = this._delay(function() {
11159
				if ( this.spinning ) {
11160
					this._stop( event );
11161
				}
11162
			}, 100 );
11163
			event.preventDefault();
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
11164
		},
11165
		"mousedown .ui-spinner-button": function( event ) {
11166
			var previous;
11167
11168
			// We never want the buttons to have focus; whenever the user is
11169
			// interacting with the spinner, the focus should be on the input.
11170
			// If the input is focused then this.previous is properly set from
11171
			// when the input first received focus. If the input is not focused
11172
			// then we need to set this.previous based on the value before spinning.
11173
			previous = this.element[0] === this.document[0].activeElement ?
11174
				this.previous : this.element.val();
11175
			function checkFocus() {
11176
				var isActive = this.element[0] === this.document[0].activeElement;
11177
				if ( !isActive ) {
11178
					this.element.focus();
11179
					this.previous = previous;
11180
					// support: IE
11181
					// IE sets focus asynchronously, so we need to check if focus
11182
					// moved off of the input because the user clicked on the button.
11183
					this._delay(function() {
11184
						this.previous = previous;
11185
					});
11186
				}
11187
			}
11188
11189
			// ensure focus is on (or stays on) the text field
11190
			event.preventDefault();
11191
			checkFocus.call( this );
11192
11193
			// support: IE
11194
			// IE doesn't prevent moving focus even with event.preventDefault()
11195
			// so we set a flag to know when we should ignore the blur event
11196
			// and check (again) if focus moved off of the input.
11197
			this.cancelBlur = true;
11198
			this._delay(function() {
11199
				delete this.cancelBlur;
11200
				checkFocus.call( this );
11201
			});
11202
11203
			if ( this._start( event ) === false ) {
11204
				return;
11205
			}
11206
11207
			this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
11208
		},
11209
		"mouseup .ui-spinner-button": "_stop",
11210
		"mouseenter .ui-spinner-button": function( event ) {
11211
			// button will add ui-state-active if mouse was down while mouseleave and kept down
11212
			if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) {
11213
				return;
11214
			}
11215
11216
			if ( this._start( event ) === false ) {
11217
				return false;
11218
			}
11219
			this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
11220
		},
11221
		// TODO: do we really want to consider this a stop?
11222
		// shouldn't we just stop the repeater and wait until mouseup before
11223
		// we trigger the stop event?
11224
		"mouseleave .ui-spinner-button": "_stop"
11225
	},
11226
11227
	_draw: function() {
11228
		var uiSpinner = this.uiSpinner = this.element
11229
			.addClass( "ui-spinner-input" )
11230
			.attr( "autocomplete", "off" )
11231
			.wrap( this._uiSpinnerHtml() )
11232
			.parent()
11233
				// add buttons
11234
				.append( this._buttonHtml() );
11235
11236
		this.element.attr( "role", "spinbutton" );
11237
11238
		// button bindings
11239
		this.buttons = uiSpinner.find( ".ui-spinner-button" )
11240
			.attr( "tabIndex", -1 )
11241
			.button()
11242
			.removeClass( "ui-corner-all" );
11243
11244
		// IE 6 doesn't understand height: 50% for the buttons
11245
		// unless the wrapper has an explicit height
11246
		if ( this.buttons.height() > Math.ceil( uiSpinner.height() * 0.5 ) &&
11247
				uiSpinner.height() > 0 ) {
11248
			uiSpinner.height( uiSpinner.height() );
11249
		}
11250
11251
		// disable spinner if element was already disabled
11252
		if ( this.options.disabled ) {
11253
			this.disable();
11254
		}
11255
	},
11256
11257
	_keydown: function( event ) {
11258
		var options = this.options,
11259
			keyCode = $.ui.keyCode;
11260
11261
		switch ( event.keyCode ) {
0 ignored issues
show
Coding Style introduced by
As per coding-style, switch statements should have a default case.
Loading history...
11262
		case keyCode.UP:
0 ignored issues
show
Bug introduced by
The variable keyCode seems to be never declared. If this is a global, consider adding a /** global: keyCode */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
11263
			this._repeat( null, 1, event );
11264
			return true;
11265
		case keyCode.DOWN:
11266
			this._repeat( null, -1, event );
11267
			return true;
11268
		case keyCode.PAGE_UP:
11269
			this._repeat( null, options.page, event );
11270
			return true;
11271
		case keyCode.PAGE_DOWN:
11272
			this._repeat( null, -options.page, event );
11273
			return true;
11274
		}
11275
11276
		return false;
11277
	},
11278
11279
	_uiSpinnerHtml: function() {
11280
		return "<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>";
11281
	},
11282
11283
	_buttonHtml: function() {
11284
		return "" +
11285
			"<a class='ui-spinner-button ui-spinner-up ui-corner-tr'>" +
11286
				"<span class='ui-icon " + this.options.icons.up + "'>&#9650;</span>" +
11287
			"</a>" +
11288
			"<a class='ui-spinner-button ui-spinner-down ui-corner-br'>" +
11289
				"<span class='ui-icon " + this.options.icons.down + "'>&#9660;</span>" +
11290
			"</a>";
11291
	},
11292
11293
	_start: function( event ) {
11294
		if ( !this.spinning && this._trigger( "start", event ) === false ) {
11295
			return false;
11296
		}
11297
11298
		if ( !this.counter ) {
11299
			this.counter = 1;
11300
		}
11301
		this.spinning = true;
11302
		return true;
11303
	},
11304
11305
	_repeat: function( i, steps, event ) {
11306
		i = i || 500;
11307
11308
		clearTimeout( this.timer );
11309
		this.timer = this._delay(function() {
11310
			this._repeat( 40, steps, event );
11311
		}, i );
11312
11313
		this._spin( steps * this.options.step, event );
11314
	},
11315
11316
	_spin: function( step, event ) {
11317
		var value = this.value() || 0;
11318
11319
		if ( !this.counter ) {
11320
			this.counter = 1;
11321
		}
11322
11323
		value = this._adjustValue( value + step * this._increment( this.counter ) );
11324
11325
		if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false) {
11326
			this._value( value );
11327
			this.counter++;
11328
		}
11329
	},
11330
11331
	_increment: function( i ) {
11332
		var incremental = this.options.incremental;
11333
11334
		if ( incremental ) {
11335
			return $.isFunction( incremental ) ?
11336
				incremental( i ) :
11337
				Math.floor( i*i*i/50000 - i*i/500 + 17*i/200 + 1 );
11338
		}
11339
11340
		return 1;
11341
	},
11342
11343
	_precision: function() {
11344
		var precision = this._precisionOf( this.options.step );
11345
		if ( this.options.min !== null ) {
11346
			precision = Math.max( precision, this._precisionOf( this.options.min ) );
11347
		}
11348
		return precision;
11349
	},
11350
11351
	_precisionOf: function( num ) {
11352
		var str = num.toString(),
11353
			decimal = str.indexOf( "." );
11354
		return decimal === -1 ? 0 : str.length - decimal - 1;
11355
	},
11356
11357
	_adjustValue: function( value ) {
11358
		var base, aboveMin,
11359
			options = this.options;
11360
11361
		// make sure we're at a valid step
11362
		// - find out where we are relative to the base (min or 0)
11363
		base = options.min !== null ? options.min : 0;
11364
		aboveMin = value - base;
11365
		// - round to the nearest step
11366
		aboveMin = Math.round(aboveMin / options.step) * options.step;
11367
		// - rounding is based on 0, so adjust back to our base
11368
		value = base + aboveMin;
11369
11370
		// fix precision from bad JS floating point math
11371
		value = parseFloat( value.toFixed( this._precision() ) );
11372
11373
		// clamp the value
11374
		if ( options.max !== null && value > options.max) {
11375
			return options.max;
11376
		}
11377
		if ( options.min !== null && value < options.min ) {
11378
			return options.min;
11379
		}
11380
11381
		return value;
11382
	},
11383
11384
	_stop: function( event ) {
11385
		if ( !this.spinning ) {
11386
			return;
11387
		}
11388
11389
		clearTimeout( this.timer );
11390
		clearTimeout( this.mousewheelTimer );
11391
		this.counter = 0;
11392
		this.spinning = false;
11393
		this._trigger( "stop", event );
11394
	},
11395
11396
	_setOption: function( key, value ) {
11397
		if ( key === "culture" || key === "numberFormat" ) {
11398
			var prevValue = this._parse( this.element.val() );
11399
			this.options[ key ] = value;
11400
			this.element.val( this._format( prevValue ) );
11401
			return;
11402
		}
11403
11404
		if ( key === "max" || key === "min" || key === "step" ) {
11405
			if ( typeof value === "string" ) {
11406
				value = this._parse( value );
11407
			}
11408
		}
11409
		if ( key === "icons" ) {
11410
			this.buttons.first().find( ".ui-icon" )
11411
				.removeClass( this.options.icons.up )
11412
				.addClass( value.up );
11413
			this.buttons.last().find( ".ui-icon" )
11414
				.removeClass( this.options.icons.down )
11415
				.addClass( value.down );
11416
		}
11417
11418
		this._super( key, value );
11419
11420
		if ( key === "disabled" ) {
11421
			if ( value ) {
11422
				this.element.prop( "disabled", true );
11423
				this.buttons.button( "disable" );
11424
			} else {
11425
				this.element.prop( "disabled", false );
11426
				this.buttons.button( "enable" );
11427
			}
11428
		}
11429
	},
11430
11431
	_setOptions: modifier(function( options ) {
11432
		this._super( options );
11433
		this._value( this.element.val() );
11434
	}),
11435
11436
	_parse: function( val ) {
11437
		if ( typeof val === "string" && val !== "" ) {
11438
			val = window.Globalize && this.options.numberFormat ?
11439
				Globalize.parseFloat( val, 10, this.options.culture ) : +val;
0 ignored issues
show
Bug introduced by
The variable Globalize seems to be never declared. If this is a global, consider adding a /** global: Globalize */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
11440
		}
11441
		return val === "" || isNaN( val ) ? null : val;
11442
	},
11443
11444
	_format: function( value ) {
11445
		if ( value === "" ) {
11446
			return "";
11447
		}
11448
		return window.Globalize && this.options.numberFormat ?
11449
			Globalize.format( value, this.options.numberFormat, this.options.culture ) :
0 ignored issues
show
Bug introduced by
The variable Globalize seems to be never declared. If this is a global, consider adding a /** global: Globalize */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
11450
			value;
11451
	},
11452
11453
	_refresh: function() {
11454
		this.element.attr({
11455
			"aria-valuemin": this.options.min,
11456
			"aria-valuemax": this.options.max,
11457
			// TODO: what should we do with values that can't be parsed?
11458
			"aria-valuenow": this._parse( this.element.val() )
11459
		});
11460
	},
11461
11462
	// update the value without triggering change
11463
	_value: function( value, allowAny ) {
11464
		var parsed;
11465
		if ( value !== "" ) {
11466
			parsed = this._parse( value );
11467
			if ( parsed !== null ) {
11468
				if ( !allowAny ) {
11469
					parsed = this._adjustValue( parsed );
11470
				}
11471
				value = this._format( parsed );
11472
			}
11473
		}
11474
		this.element.val( value );
11475
		this._refresh();
11476
	},
11477
11478
	_destroy: function() {
11479
		this.element
11480
			.removeClass( "ui-spinner-input" )
11481
			.prop( "disabled", false )
11482
			.removeAttr( "autocomplete" )
11483
			.removeAttr( "role" )
11484
			.removeAttr( "aria-valuemin" )
11485
			.removeAttr( "aria-valuemax" )
11486
			.removeAttr( "aria-valuenow" );
11487
		this.uiSpinner.replaceWith( this.element );
11488
	},
11489
11490
	stepUp: modifier(function( steps ) {
11491
		this._stepUp( steps );
11492
	}),
11493
	_stepUp: function( steps ) {
11494
		if ( this._start() ) {
11495
			this._spin( (steps || 1) * this.options.step );
11496
			this._stop();
11497
		}
11498
	},
11499
11500
	stepDown: modifier(function( steps ) {
11501
		this._stepDown( steps );
11502
	}),
11503
	_stepDown: function( steps ) {
11504
		if ( this._start() ) {
11505
			this._spin( (steps || 1) * -this.options.step );
11506
			this._stop();
11507
		}
11508
	},
11509
11510
	pageUp: modifier(function( pages ) {
11511
		this._stepUp( (pages || 1) * this.options.page );
11512
	}),
11513
11514
	pageDown: modifier(function( pages ) {
11515
		this._stepDown( (pages || 1) * this.options.page );
11516
	}),
11517
11518
	value: function( newVal ) {
11519
		if ( !arguments.length ) {
11520
			return this._parse( this.element.val() );
11521
		}
11522
		modifier( this._value ).call( this, newVal );
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
11523
	},
11524
11525
	widget: function() {
11526
		return this.uiSpinner;
11527
	}
11528
});
11529
11530
}( jQuery ) );
11531
(function( $, undefined ) {
11532
11533
var tabId = 0,
11534
	rhash = /#.*$/;
11535
11536
function getNextTabId() {
11537
	return ++tabId;
11538
}
11539
11540
function isLocal( anchor ) {
11541
	// support: IE7
11542
	// IE7 doesn't normalize the href property when set via script (#9317)
11543
	anchor = anchor.cloneNode( false );
11544
11545
	return anchor.hash.length > 1 &&
11546
		decodeURIComponent( anchor.href.replace( rhash, "" ) ) ===
11547
			decodeURIComponent( location.href.replace( rhash, "" ) );
11548
}
11549
11550
$.widget( "ui.tabs", {
11551
	version: "1.10.4",
11552
	delay: 300,
11553
	options: {
11554
		active: null,
11555
		collapsible: false,
11556
		event: "click",
11557
		heightStyle: "content",
11558
		hide: null,
11559
		show: null,
11560
11561
		// callbacks
11562
		activate: null,
11563
		beforeActivate: null,
11564
		beforeLoad: null,
11565
		load: null
11566
	},
11567
11568
	_create: function() {
11569
		var that = this,
11570
			options = this.options;
11571
11572
		this.running = false;
11573
11574
		this.element
11575
			.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" )
11576
			.toggleClass( "ui-tabs-collapsible", options.collapsible )
11577
			// Prevent users from focusing disabled tabs via click
11578
			.delegate( ".ui-tabs-nav > li", "mousedown" + this.eventNamespace, function( event ) {
11579
				if ( $( this ).is( ".ui-state-disabled" ) ) {
11580
					event.preventDefault();
11581
				}
11582
			})
11583
			// support: IE <9
11584
			// Preventing the default action in mousedown doesn't prevent IE
11585
			// from focusing the element, so if the anchor gets focused, blur.
11586
			// We don't have to worry about focusing the previously focused
11587
			// element since clicking on a non-focusable element should focus
11588
			// the body anyway.
11589
			.delegate( ".ui-tabs-anchor", "focus" + this.eventNamespace, function() {
11590
				if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) {
11591
					this.blur();
11592
				}
11593
			});
11594
11595
		this._processTabs();
11596
		options.active = this._initialActive();
11597
11598
		// Take disabling tabs via class attribute from HTML
11599
		// into account and update option properly.
11600
		if ( $.isArray( options.disabled ) ) {
11601
			options.disabled = $.unique( options.disabled.concat(
11602
				$.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {
11603
					return that.tabs.index( li );
11604
				})
11605
			) ).sort();
11606
		}
11607
11608
		// check for length avoids error when initializing empty list
11609
		if ( this.options.active !== false && this.anchors.length ) {
11610
			this.active = this._findActive( options.active );
11611
		} else {
11612
			this.active = $();
11613
		}
11614
11615
		this._refresh();
11616
11617
		if ( this.active.length ) {
11618
			this.load( options.active );
11619
		}
11620
	},
11621
11622
	_initialActive: function() {
11623
		var active = this.options.active,
11624
			collapsible = this.options.collapsible,
11625
			locationHash = location.hash.substring( 1 );
11626
11627
		if ( active === null ) {
11628
			// check the fragment identifier in the URL
11629
			if ( locationHash ) {
11630
				this.tabs.each(function( i, tab ) {
11631
					if ( $( tab ).attr( "aria-controls" ) === locationHash ) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if $(tab).attr("aria-controls") === locationHash is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
11632
						active = i;
11633
						return false;
11634
					}
11635
				});
11636
			}
11637
11638
			// check for a tab marked active via a class
11639
			if ( active === null ) {
11640
				active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );
11641
			}
11642
11643
			// no active tab, set to false
11644
			if ( active === null || active === -1 ) {
11645
				active = this.tabs.length ? 0 : false;
11646
			}
11647
		}
11648
11649
		// handle numbers: negative, out of range
11650
		if ( active !== false ) {
11651
			active = this.tabs.index( this.tabs.eq( active ) );
11652
			if ( active === -1 ) {
11653
				active = collapsible ? false : 0;
11654
			}
11655
		}
11656
11657
		// don't allow collapsible: false and active: false
11658
		if ( !collapsible && active === false && this.anchors.length ) {
11659
			active = 0;
11660
		}
11661
11662
		return active;
11663
	},
11664
11665
	_getCreateEventData: function() {
11666
		return {
11667
			tab: this.active,
11668
			panel: !this.active.length ? $() : this._getPanelForTab( this.active )
11669
		};
11670
	},
11671
11672
	_tabKeydown: function( event ) {
11673
		var focusedTab = $( this.document[0].activeElement ).closest( "li" ),
11674
			selectedIndex = this.tabs.index( focusedTab ),
11675
			goingForward = true;
11676
11677
		if ( this._handlePageNav( event ) ) {
11678
			return;
11679
		}
11680
11681
		switch ( event.keyCode ) {
11682
			case $.ui.keyCode.RIGHT:
11683
			case $.ui.keyCode.DOWN:
11684
				selectedIndex++;
11685
				break;
11686
			case $.ui.keyCode.UP:
11687
			case $.ui.keyCode.LEFT:
11688
				goingForward = false;
11689
				selectedIndex--;
11690
				break;
11691
			case $.ui.keyCode.END:
11692
				selectedIndex = this.anchors.length - 1;
11693
				break;
11694
			case $.ui.keyCode.HOME:
11695
				selectedIndex = 0;
11696
				break;
11697
			case $.ui.keyCode.SPACE:
11698
				// Activate only, no collapsing
11699
				event.preventDefault();
11700
				clearTimeout( this.activating );
11701
				this._activate( selectedIndex );
11702
				return;
11703
			case $.ui.keyCode.ENTER:
11704
				// Toggle (cancel delayed activation, allow collapsing)
11705
				event.preventDefault();
11706
				clearTimeout( this.activating );
11707
				// Determine if we should collapse or activate
11708
				this._activate( selectedIndex === this.options.active ? false : selectedIndex );
11709
				return;
11710
			default:
11711
				return;
11712
		}
11713
11714
		// Focus the appropriate tab, based on which key was pressed
11715
		event.preventDefault();
11716
		clearTimeout( this.activating );
11717
		selectedIndex = this._focusNextTab( selectedIndex, goingForward );
11718
11719
		// Navigating with control key will prevent automatic activation
11720
		if ( !event.ctrlKey ) {
11721
			// Update aria-selected immediately so that AT think the tab is already selected.
11722
			// Otherwise AT may confuse the user by stating that they need to activate the tab,
11723
			// but the tab will already be activated by the time the announcement finishes.
11724
			focusedTab.attr( "aria-selected", "false" );
11725
			this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );
11726
11727
			this.activating = this._delay(function() {
11728
				this.option( "active", selectedIndex );
11729
			}, this.delay );
11730
		}
11731
	},
11732
11733
	_panelKeydown: function( event ) {
11734
		if ( this._handlePageNav( event ) ) {
11735
			return;
11736
		}
11737
11738
		// Ctrl+up moves focus to the current tab
11739
		if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {
11740
			event.preventDefault();
11741
			this.active.focus();
11742
		}
11743
	},
11744
11745
	// Alt+page up/down moves focus to the previous/next tab (and activates)
11746
	_handlePageNav: function( event ) {
11747
		if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {
11748
			this._activate( this._focusNextTab( this.options.active - 1, false ) );
11749
			return true;
11750
		}
11751
		if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if event.altKey && event.ke... $.ui.keyCode.PAGE_DOWN is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
11752
			this._activate( this._focusNextTab( this.options.active + 1, true ) );
11753
			return true;
11754
		}
11755
	},
11756
11757
	_findNextTab: function( index, goingForward ) {
11758
		var lastTabIndex = this.tabs.length - 1;
11759
11760
		function constrain() {
11761
			if ( index > lastTabIndex ) {
11762
				index = 0;
11763
			}
11764
			if ( index < 0 ) {
11765
				index = lastTabIndex;
11766
			}
11767
			return index;
11768
		}
11769
11770
		while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {
11771
			index = goingForward ? index + 1 : index - 1;
11772
		}
11773
11774
		return index;
11775
	},
11776
11777
	_focusNextTab: function( index, goingForward ) {
11778
		index = this._findNextTab( index, goingForward );
11779
		this.tabs.eq( index ).focus();
11780
		return index;
11781
	},
11782
11783
	_setOption: function( key, value ) {
11784
		if ( key === "active" ) {
11785
			// _activate() will handle invalid values and update this.options
11786
			this._activate( value );
11787
			return;
11788
		}
11789
11790
		if ( key === "disabled" ) {
11791
			// don't use the widget factory's disabled handling
11792
			this._setupDisabled( value );
11793
			return;
11794
		}
11795
11796
		this._super( key, value);
11797
11798
		if ( key === "collapsible" ) {
11799
			this.element.toggleClass( "ui-tabs-collapsible", value );
11800
			// Setting collapsible: false while collapsed; open first panel
11801
			if ( !value && this.options.active === false ) {
11802
				this._activate( 0 );
11803
			}
11804
		}
11805
11806
		if ( key === "event" ) {
11807
			this._setupEvents( value );
11808
		}
11809
11810
		if ( key === "heightStyle" ) {
11811
			this._setupHeightStyle( value );
11812
		}
11813
	},
11814
11815
	_tabId: function( tab ) {
11816
		return tab.attr( "aria-controls" ) || "ui-tabs-" + getNextTabId();
11817
	},
11818
11819
	_sanitizeSelector: function( hash ) {
11820
		return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : "";
11821
	},
11822
11823
	refresh: function() {
11824
		var options = this.options,
11825
			lis = this.tablist.children( ":has(a[href])" );
11826
11827
		// get disabled tabs from class attribute from HTML
11828
		// this will get converted to a boolean if needed in _refresh()
11829
		options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {
11830
			return lis.index( tab );
11831
		});
11832
11833
		this._processTabs();
11834
11835
		// was collapsed or no tabs
11836
		if ( options.active === false || !this.anchors.length ) {
11837
			options.active = false;
11838
			this.active = $();
11839
		// was active, but active tab is gone
11840
		} else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {
11841
			// all remaining tabs are disabled
11842
			if ( this.tabs.length === options.disabled.length ) {
11843
				options.active = false;
11844
				this.active = $();
11845
			// activate previous tab
11846
			} else {
11847
				this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );
11848
			}
11849
		// was active, active tab still exists
11850
		} else {
11851
			// make sure active index is correct
11852
			options.active = this.tabs.index( this.active );
11853
		}
11854
11855
		this._refresh();
11856
	},
11857
11858
	_refresh: function() {
11859
		this._setupDisabled( this.options.disabled );
11860
		this._setupEvents( this.options.event );
11861
		this._setupHeightStyle( this.options.heightStyle );
11862
11863
		this.tabs.not( this.active ).attr({
11864
			"aria-selected": "false",
11865
			tabIndex: -1
11866
		});
11867
		this.panels.not( this._getPanelForTab( this.active ) )
11868
			.hide()
11869
			.attr({
11870
				"aria-expanded": "false",
11871
				"aria-hidden": "true"
11872
			});
11873
11874
		// Make sure one tab is in the tab order
11875
		if ( !this.active.length ) {
11876
			this.tabs.eq( 0 ).attr( "tabIndex", 0 );
11877
		} else {
11878
			this.active
11879
				.addClass( "ui-tabs-active ui-state-active" )
11880
				.attr({
11881
					"aria-selected": "true",
11882
					tabIndex: 0
11883
				});
11884
			this._getPanelForTab( this.active )
11885
				.show()
11886
				.attr({
11887
					"aria-expanded": "true",
11888
					"aria-hidden": "false"
11889
				});
11890
		}
11891
	},
11892
11893
	_processTabs: function() {
11894
		var that = this;
11895
11896
		this.tablist = this._getList()
11897
			.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
11898
			.attr( "role", "tablist" );
11899
11900
		this.tabs = this.tablist.find( "> li:has(a[href])" )
11901
			.addClass( "ui-state-default ui-corner-top" )
11902
			.attr({
11903
				role: "tab",
11904
				tabIndex: -1
11905
			});
11906
11907
		this.anchors = this.tabs.map(function() {
11908
				return $( "a", this )[ 0 ];
11909
			})
11910
			.addClass( "ui-tabs-anchor" )
11911
			.attr({
11912
				role: "presentation",
11913
				tabIndex: -1
11914
			});
11915
11916
		this.panels = $();
11917
11918
		this.anchors.each(function( i, anchor ) {
11919
			var selector, panel, panelId,
11920
				anchorId = $( anchor ).uniqueId().attr( "id" ),
11921
				tab = $( anchor ).closest( "li" ),
11922
				originalAriaControls = tab.attr( "aria-controls" );
11923
11924
			// inline tab
11925
			if ( isLocal( anchor ) ) {
11926
				selector = anchor.hash;
11927
				panel = that.element.find( that._sanitizeSelector( selector ) );
11928
			// remote tab
11929
			} else {
11930
				panelId = that._tabId( tab );
11931
				selector = "#" + panelId;
11932
				panel = that.element.find( selector );
11933
				if ( !panel.length ) {
11934
					panel = that._createPanel( panelId );
11935
					panel.insertAfter( that.panels[ i - 1 ] || that.tablist );
11936
				}
11937
				panel.attr( "aria-live", "polite" );
11938
			}
11939
11940
			if ( panel.length) {
11941
				that.panels = that.panels.add( panel );
11942
			}
11943
			if ( originalAriaControls ) {
11944
				tab.data( "ui-tabs-aria-controls", originalAriaControls );
11945
			}
11946
			tab.attr({
11947
				"aria-controls": selector.substring( 1 ),
11948
				"aria-labelledby": anchorId
11949
			});
11950
			panel.attr( "aria-labelledby", anchorId );
11951
		});
11952
11953
		this.panels
11954
			.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
11955
			.attr( "role", "tabpanel" );
11956
	},
11957
11958
	// allow overriding how to find the list for rare usage scenarios (#7715)
11959
	_getList: function() {
11960
		return this.tablist || this.element.find( "ol,ul" ).eq( 0 );
11961
	},
11962
11963
	_createPanel: function( id ) {
11964
		return $( "<div>" )
11965
			.attr( "id", id )
11966
			.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
11967
			.data( "ui-tabs-destroy", true );
11968
	},
11969
11970
	_setupDisabled: function( disabled ) {
11971
		if ( $.isArray( disabled ) ) {
11972
			if ( !disabled.length ) {
11973
				disabled = false;
11974
			} else if ( disabled.length === this.anchors.length ) {
11975
				disabled = true;
11976
			}
11977
		}
11978
11979
		// disable tabs
11980
		for ( var i = 0, li; ( li = this.tabs[ i ] ); i++ ) {
11981
			if ( disabled === true || $.inArray( i, disabled ) !== -1 ) {
11982
				$( li )
11983
					.addClass( "ui-state-disabled" )
11984
					.attr( "aria-disabled", "true" );
11985
			} else {
11986
				$( li )
11987
					.removeClass( "ui-state-disabled" )
11988
					.removeAttr( "aria-disabled" );
11989
			}
11990
		}
11991
11992
		this.options.disabled = disabled;
11993
	},
11994
11995
	_setupEvents: function( event ) {
11996
		var events = {
11997
			click: function( event ) {
11998
				event.preventDefault();
11999
			}
12000
		};
12001
		if ( event ) {
12002
			$.each( event.split(" "), function( index, eventName ) {
12003
				events[ eventName ] = "_eventHandler";
12004
			});
12005
		}
12006
12007
		this._off( this.anchors.add( this.tabs ).add( this.panels ) );
12008
		this._on( this.anchors, events );
12009
		this._on( this.tabs, { keydown: "_tabKeydown" } );
12010
		this._on( this.panels, { keydown: "_panelKeydown" } );
12011
12012
		this._focusable( this.tabs );
12013
		this._hoverable( this.tabs );
12014
	},
12015
12016
	_setupHeightStyle: function( heightStyle ) {
12017
		var maxHeight,
12018
			parent = this.element.parent();
12019
12020
		if ( heightStyle === "fill" ) {
12021
			maxHeight = parent.height();
12022
			maxHeight -= this.element.outerHeight() - this.element.height();
12023
12024
			this.element.siblings( ":visible" ).each(function() {
12025
				var elem = $( this ),
12026
					position = elem.css( "position" );
12027
12028
				if ( position === "absolute" || position === "fixed" ) {
12029
					return;
12030
				}
12031
				maxHeight -= elem.outerHeight( true );
12032
			});
12033
12034
			this.element.children().not( this.panels ).each(function() {
12035
				maxHeight -= $( this ).outerHeight( true );
12036
			});
12037
12038
			this.panels.each(function() {
12039
				$( this ).height( Math.max( 0, maxHeight -
12040
					$( this ).innerHeight() + $( this ).height() ) );
12041
			})
12042
			.css( "overflow", "auto" );
12043
		} else if ( heightStyle === "auto" ) {
12044
			maxHeight = 0;
12045
			this.panels.each(function() {
12046
				maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
12047
			}).height( maxHeight );
12048
		}
12049
	},
12050
12051
	_eventHandler: function( event ) {
12052
		var options = this.options,
12053
			active = this.active,
12054
			anchor = $( event.currentTarget ),
12055
			tab = anchor.closest( "li" ),
12056
			clickedIsActive = tab[ 0 ] === active[ 0 ],
12057
			collapsing = clickedIsActive && options.collapsible,
12058
			toShow = collapsing ? $() : this._getPanelForTab( tab ),
12059
			toHide = !active.length ? $() : this._getPanelForTab( active ),
12060
			eventData = {
12061
				oldTab: active,
12062
				oldPanel: toHide,
12063
				newTab: collapsing ? $() : tab,
12064
				newPanel: toShow
12065
			};
12066
12067
		event.preventDefault();
12068
12069
		if ( tab.hasClass( "ui-state-disabled" ) ||
12070
				// tab is already loading
12071
				tab.hasClass( "ui-tabs-loading" ) ||
12072
				// can't switch durning an animation
12073
				this.running ||
12074
				// click on active header, but not collapsible
12075
				( clickedIsActive && !options.collapsible ) ||
12076
				// allow canceling activation
12077
				( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
12078
			return;
12079
		}
12080
12081
		options.active = collapsing ? false : this.tabs.index( tab );
12082
12083
		this.active = clickedIsActive ? $() : tab;
12084
		if ( this.xhr ) {
12085
			this.xhr.abort();
12086
		}
12087
12088
		if ( !toHide.length && !toShow.length ) {
12089
			$.error( "jQuery UI Tabs: Mismatching fragment identifier." );
12090
		}
12091
12092
		if ( toShow.length ) {
12093
			this.load( this.tabs.index( tab ), event );
12094
		}
12095
		this._toggle( event, eventData );
12096
	},
12097
12098
	// handles show/hide for selecting tabs
12099
	_toggle: function( event, eventData ) {
12100
		var that = this,
12101
			toShow = eventData.newPanel,
12102
			toHide = eventData.oldPanel;
12103
12104
		this.running = true;
12105
12106
		function complete() {
12107
			that.running = false;
12108
			that._trigger( "activate", event, eventData );
12109
		}
12110
12111
		function show() {
12112
			eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" );
12113
12114
			if ( toShow.length && that.options.show ) {
12115
				that._show( toShow, that.options.show, complete );
12116
			} else {
12117
				toShow.show();
12118
				complete();
12119
			}
12120
		}
12121
12122
		// start out by hiding, then showing, then completing
12123
		if ( toHide.length && this.options.hide ) {
12124
			this._hide( toHide, this.options.hide, function() {
12125
				eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
12126
				show();
12127
			});
12128
		} else {
12129
			eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
12130
			toHide.hide();
12131
			show();
12132
		}
12133
12134
		toHide.attr({
12135
			"aria-expanded": "false",
12136
			"aria-hidden": "true"
12137
		});
12138
		eventData.oldTab.attr( "aria-selected", "false" );
12139
		// If we're switching tabs, remove the old tab from the tab order.
12140
		// If we're opening from collapsed state, remove the previous tab from the tab order.
12141
		// If we're collapsing, then keep the collapsing tab in the tab order.
12142
		if ( toShow.length && toHide.length ) {
12143
			eventData.oldTab.attr( "tabIndex", -1 );
12144
		} else if ( toShow.length ) {
12145
			this.tabs.filter(function() {
12146
				return $( this ).attr( "tabIndex" ) === 0;
12147
			})
12148
			.attr( "tabIndex", -1 );
12149
		}
12150
12151
		toShow.attr({
12152
			"aria-expanded": "true",
12153
			"aria-hidden": "false"
12154
		});
12155
		eventData.newTab.attr({
12156
			"aria-selected": "true",
12157
			tabIndex: 0
12158
		});
12159
	},
12160
12161
	_activate: function( index ) {
12162
		var anchor,
12163
			active = this._findActive( index );
12164
12165
		// trying to activate the already active panel
12166
		if ( active[ 0 ] === this.active[ 0 ] ) {
12167
			return;
12168
		}
12169
12170
		// trying to collapse, simulate a click on the current active header
12171
		if ( !active.length ) {
12172
			active = this.active;
12173
		}
12174
12175
		anchor = active.find( ".ui-tabs-anchor" )[ 0 ];
12176
		this._eventHandler({
12177
			target: anchor,
12178
			currentTarget: anchor,
12179
			preventDefault: $.noop
12180
		});
12181
	},
12182
12183
	_findActive: function( index ) {
12184
		return index === false ? $() : this.tabs.eq( index );
12185
	},
12186
12187
	_getIndex: function( index ) {
12188
		// meta-function to give users option to provide a href string instead of a numerical index.
12189
		if ( typeof index === "string" ) {
12190
			index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) );
12191
		}
12192
12193
		return index;
12194
	},
12195
12196
	_destroy: function() {
12197
		if ( this.xhr ) {
12198
			this.xhr.abort();
12199
		}
12200
12201
		this.element.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" );
12202
12203
		this.tablist
12204
			.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
12205
			.removeAttr( "role" );
12206
12207
		this.anchors
12208
			.removeClass( "ui-tabs-anchor" )
12209
			.removeAttr( "role" )
12210
			.removeAttr( "tabIndex" )
12211
			.removeUniqueId();
12212
12213
		this.tabs.add( this.panels ).each(function() {
12214
			if ( $.data( this, "ui-tabs-destroy" ) ) {
12215
				$( this ).remove();
12216
			} else {
12217
				$( this )
12218
					.removeClass( "ui-state-default ui-state-active ui-state-disabled " +
12219
						"ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel" )
12220
					.removeAttr( "tabIndex" )
12221
					.removeAttr( "aria-live" )
12222
					.removeAttr( "aria-busy" )
12223
					.removeAttr( "aria-selected" )
12224
					.removeAttr( "aria-labelledby" )
12225
					.removeAttr( "aria-hidden" )
12226
					.removeAttr( "aria-expanded" )
12227
					.removeAttr( "role" );
12228
			}
12229
		});
12230
12231
		this.tabs.each(function() {
12232
			var li = $( this ),
12233
				prev = li.data( "ui-tabs-aria-controls" );
12234
			if ( prev ) {
12235
				li
12236
					.attr( "aria-controls", prev )
12237
					.removeData( "ui-tabs-aria-controls" );
12238
			} else {
12239
				li.removeAttr( "aria-controls" );
12240
			}
12241
		});
12242
12243
		this.panels.show();
12244
12245
		if ( this.options.heightStyle !== "content" ) {
12246
			this.panels.css( "height", "" );
12247
		}
12248
	},
12249
12250
	enable: function( index ) {
12251
		var disabled = this.options.disabled;
12252
		if ( disabled === false ) {
12253
			return;
12254
		}
12255
12256
		if ( index === undefined ) {
12257
			disabled = false;
12258
		} else {
12259
			index = this._getIndex( index );
12260
			if ( $.isArray( disabled ) ) {
12261
				disabled = $.map( disabled, function( num ) {
12262
					return num !== index ? num : null;
12263
				});
12264
			} else {
12265
				disabled = $.map( this.tabs, function( li, num ) {
12266
					return num !== index ? num : null;
12267
				});
12268
			}
12269
		}
12270
		this._setupDisabled( disabled );
12271
	},
12272
12273
	disable: function( index ) {
12274
		var disabled = this.options.disabled;
12275
		if ( disabled === true ) {
12276
			return;
12277
		}
12278
12279
		if ( index === undefined ) {
12280
			disabled = true;
12281
		} else {
12282
			index = this._getIndex( index );
12283
			if ( $.inArray( index, disabled ) !== -1 ) {
12284
				return;
12285
			}
12286
			if ( $.isArray( disabled ) ) {
12287
				disabled = $.merge( [ index ], disabled ).sort();
12288
			} else {
12289
				disabled = [ index ];
12290
			}
12291
		}
12292
		this._setupDisabled( disabled );
12293
	},
12294
12295
	load: function( index, event ) {
12296
		index = this._getIndex( index );
12297
		var that = this,
12298
			tab = this.tabs.eq( index ),
12299
			anchor = tab.find( ".ui-tabs-anchor" ),
12300
			panel = this._getPanelForTab( tab ),
12301
			eventData = {
12302
				tab: tab,
12303
				panel: panel
12304
			};
12305
12306
		// not remote
12307
		if ( isLocal( anchor[ 0 ] ) ) {
12308
			return;
12309
		}
12310
12311
		this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );
12312
12313
		// support: jQuery <1.8
12314
		// jQuery <1.8 returns false if the request is canceled in beforeSend,
12315
		// but as of 1.8, $.ajax() always returns a jqXHR object.
12316
		if ( this.xhr && this.xhr.statusText !== "canceled" ) {
12317
			tab.addClass( "ui-tabs-loading" );
12318
			panel.attr( "aria-busy", "true" );
12319
12320
			this.xhr
12321
				.success(function( response ) {
12322
					// support: jQuery <1.8
12323
					// http://bugs.jquery.com/ticket/11778
12324
					setTimeout(function() {
12325
						panel.html( response );
12326
						that._trigger( "load", event, eventData );
12327
					}, 1 );
12328
				})
12329
				.complete(function( jqXHR, status ) {
12330
					// support: jQuery <1.8
12331
					// http://bugs.jquery.com/ticket/11778
12332
					setTimeout(function() {
12333
						if ( status === "abort" ) {
12334
							that.panels.stop( false, true );
12335
						}
12336
12337
						tab.removeClass( "ui-tabs-loading" );
12338
						panel.removeAttr( "aria-busy" );
12339
12340
						if ( jqXHR === that.xhr ) {
12341
							delete that.xhr;
12342
						}
12343
					}, 1 );
12344
				});
12345
		}
12346
	},
12347
12348
	_ajaxSettings: function( anchor, event, eventData ) {
12349
		var that = this;
12350
		return {
12351
			url: anchor.attr( "href" ),
12352
			beforeSend: function( jqXHR, settings ) {
12353
				return that._trigger( "beforeLoad", event,
12354
					$.extend( { jqXHR : jqXHR, ajaxSettings: settings }, eventData ) );
12355
			}
12356
		};
12357
	},
12358
12359
	_getPanelForTab: function( tab ) {
12360
		var id = $( tab ).attr( "aria-controls" );
12361
		return this.element.find( this._sanitizeSelector( "#" + id ) );
12362
	}
12363
});
12364
12365
})( jQuery );
12366
(function($, undefined) {
12367
12368
var dataSpace = "ui-effects-";
12369
12370
$.effects = {
12371
	effect: {}
12372
};
12373
12374
/*!
12375
 * jQuery Color Animations v2.1.2
12376
 * https://github.com/jquery/jquery-color
12377
 *
12378
 * Copyright 2013 jQuery Foundation and other contributors
12379
 * Released under the MIT license.
12380
 * http://jquery.org/license
12381
 *
12382
 * Date: Wed Jan 16 08:47:09 2013 -0600
12383
 */
12384
(function( jQuery, undefined ) {
12385
12386
	var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",
12387
12388
	// plusequals test for += 100 -= 100
12389
	rplusequals = /^([\-+])=\s*(\d+\.?\d*)/,
12390
	// a set of RE's that can match strings and generate color tuples.
12391
	stringParsers = [{
12392
			re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
12393
			parse: function( execResult ) {
12394
				return [
12395
					execResult[ 1 ],
12396
					execResult[ 2 ],
12397
					execResult[ 3 ],
12398
					execResult[ 4 ]
12399
				];
12400
			}
12401
		}, {
12402
			re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
12403
			parse: function( execResult ) {
12404
				return [
12405
					execResult[ 1 ] * 2.55,
12406
					execResult[ 2 ] * 2.55,
12407
					execResult[ 3 ] * 2.55,
12408
					execResult[ 4 ]
12409
				];
12410
			}
12411
		}, {
12412
			// this regex ignores A-F because it's compared against an already lowercased string
12413
			re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,
12414
			parse: function( execResult ) {
12415
				return [
12416
					parseInt( execResult[ 1 ], 16 ),
12417
					parseInt( execResult[ 2 ], 16 ),
12418
					parseInt( execResult[ 3 ], 16 )
12419
				];
12420
			}
12421
		}, {
12422
			// this regex ignores A-F because it's compared against an already lowercased string
12423
			re: /#([a-f0-9])([a-f0-9])([a-f0-9])/,
12424
			parse: function( execResult ) {
12425
				return [
12426
					parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),
12427
					parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),
12428
					parseInt( execResult[ 3 ] + execResult[ 3 ], 16 )
12429
				];
12430
			}
12431
		}, {
12432
			re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
12433
			space: "hsla",
12434
			parse: function( execResult ) {
12435
				return [
12436
					execResult[ 1 ],
12437
					execResult[ 2 ] / 100,
12438
					execResult[ 3 ] / 100,
12439
					execResult[ 4 ]
12440
				];
12441
			}
12442
		}],
12443
12444
	// jQuery.Color( )
12445
	color = jQuery.Color = function( color, green, blue, alpha ) {
12446
		return new jQuery.Color.fn.parse( color, green, blue, alpha );
12447
	},
12448
	spaces = {
12449
		rgba: {
12450
			props: {
12451
				red: {
12452
					idx: 0,
12453
					type: "byte"
12454
				},
12455
				green: {
12456
					idx: 1,
12457
					type: "byte"
12458
				},
12459
				blue: {
12460
					idx: 2,
12461
					type: "byte"
12462
				}
12463
			}
12464
		},
12465
12466
		hsla: {
12467
			props: {
12468
				hue: {
12469
					idx: 0,
12470
					type: "degrees"
12471
				},
12472
				saturation: {
12473
					idx: 1,
12474
					type: "percent"
12475
				},
12476
				lightness: {
12477
					idx: 2,
12478
					type: "percent"
12479
				}
12480
			}
12481
		}
12482
	},
12483
	propTypes = {
12484
		"byte": {
12485
			floor: true,
12486
			max: 255
12487
		},
12488
		"percent": {
12489
			max: 1
12490
		},
12491
		"degrees": {
12492
			mod: 360,
12493
			floor: true
12494
		}
12495
	},
12496
	support = color.support = {},
12497
12498
	// element for support tests
12499
	supportElem = jQuery( "<p>" )[ 0 ],
12500
12501
	// colors = jQuery.Color.names
12502
	colors,
12503
12504
	// local aliases of functions called often
12505
	each = jQuery.each;
12506
12507
// determine rgba support immediately
12508
supportElem.style.cssText = "background-color:rgba(1,1,1,.5)";
12509
support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1;
12510
12511
// define cache name and alpha properties
12512
// for rgba and hsla spaces
12513
each( spaces, function( spaceName, space ) {
12514
	space.cache = "_" + spaceName;
12515
	space.props.alpha = {
12516
		idx: 3,
12517
		type: "percent",
12518
		def: 1
12519
	};
12520
});
12521
12522
function clamp( value, prop, allowEmpty ) {
12523
	var type = propTypes[ prop.type ] || {};
12524
12525
	if ( value == null ) {
12526
		return (allowEmpty || !prop.def) ? null : prop.def;
12527
	}
12528
12529
	// ~~ is an short way of doing floor for positive numbers
12530
	value = type.floor ? ~~value : parseFloat( value );
12531
12532
	// IE will pass in empty strings as value for alpha,
12533
	// which will hit this case
12534
	if ( isNaN( value ) ) {
12535
		return prop.def;
12536
	}
12537
12538
	if ( type.mod ) {
12539
		// we add mod before modding to make sure that negatives values
12540
		// get converted properly: -10 -> 350
12541
		return (value + type.mod) % type.mod;
12542
	}
12543
12544
	// for now all property types without mod have min and max
12545
	return 0 > value ? 0 : type.max < value ? type.max : value;
12546
}
12547
12548
function stringParse( string ) {
12549
	var inst = color(),
12550
		rgba = inst._rgba = [];
12551
12552
	string = string.toLowerCase();
12553
12554
	each( stringParsers, function( i, parser ) {
12555
		var parsed,
12556
			match = parser.re.exec( string ),
12557
			values = match && parser.parse( match ),
12558
			spaceName = parser.space || "rgba";
12559
12560
		if ( values ) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if values is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
12561
			parsed = inst[ spaceName ]( values );
12562
12563
			// if this was an rgba parse the assignment might happen twice
12564
			// oh well....
12565
			inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ];
12566
			rgba = inst._rgba = parsed._rgba;
12567
12568
			// exit each( stringParsers ) here because we matched
12569
			return false;
12570
		}
12571
	});
12572
12573
	// Found a stringParser that handled it
12574
	if ( rgba.length ) {
12575
12576
		// if this came from a parsed string, force "transparent" when alpha is 0
12577
		// chrome, (and maybe others) return "transparent" as rgba(0,0,0,0)
12578
		if ( rgba.join() === "0,0,0,0" ) {
12579
			jQuery.extend( rgba, colors.transparent );
12580
		}
12581
		return inst;
12582
	}
12583
12584
	// named colors
12585
	return colors[ string ];
12586
}
12587
12588
color.fn = jQuery.extend( color.prototype, {
12589
	parse: function( red, green, blue, alpha ) {
12590
		if ( red === undefined ) {
12591
			this._rgba = [ null, null, null, null ];
12592
			return this;
12593
		}
12594
		if ( red.jquery || red.nodeType ) {
12595
			red = jQuery( red ).css( green );
12596
			green = undefined;
12597
		}
12598
12599
		var inst = this,
12600
			type = jQuery.type( red ),
12601
			rgba = this._rgba = [];
12602
12603
		// more than 1 argument specified - assume ( red, green, blue, alpha )
12604
		if ( green !== undefined ) {
12605
			red = [ red, green, blue, alpha ];
12606
			type = "array";
12607
		}
12608
12609
		if ( type === "string" ) {
12610
			return this.parse( stringParse( red ) || colors._default );
12611
		}
12612
12613
		if ( type === "array" ) {
12614
			each( spaces.rgba.props, function( key, prop ) {
12615
				rgba[ prop.idx ] = clamp( red[ prop.idx ], prop );
12616
			});
12617
			return this;
12618
		}
12619
12620
		if ( type === "object" ) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if type === "object" is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
12621
			if ( red instanceof color ) {
12622
				each( spaces, function( spaceName, space ) {
12623
					if ( red[ space.cache ] ) {
12624
						inst[ space.cache ] = red[ space.cache ].slice();
12625
					}
12626
				});
12627
			} else {
12628
				each( spaces, function( spaceName, space ) {
12629
					var cache = space.cache;
12630
					each( space.props, function( key, prop ) {
12631
12632
						// if the cache doesn't exist, and we know how to convert
12633
						if ( !inst[ cache ] && space.to ) {
12634
12635
							// if the value was null, we don't need to copy it
12636
							// if the key was alpha, we don't need to copy it either
12637
							if ( key === "alpha" || red[ key ] == null ) {
12638
								return;
12639
							}
12640
							inst[ cache ] = space.to( inst._rgba );
12641
						}
12642
12643
						// this is the only case where we allow nulls for ALL properties.
12644
						// call clamp with alwaysAllowEmpty
12645
						inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true );
12646
					});
12647
12648
					// everything defined but alpha?
12649
					if ( inst[ cache ] && jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) {
12650
						// use the default of 1
12651
						inst[ cache ][ 3 ] = 1;
12652
						if ( space.from ) {
12653
							inst._rgba = space.from( inst[ cache ] );
12654
						}
12655
					}
12656
				});
12657
			}
12658
			return this;
12659
		}
12660
	},
12661
	is: function( compare ) {
12662
		var is = color( compare ),
12663
			same = true,
12664
			inst = this;
12665
12666
		each( spaces, function( _, space ) {
12667
			var localCache,
12668
				isCache = is[ space.cache ];
12669
			if (isCache) {
12670
				localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || [];
12671
				each( space.props, function( _, prop ) {
12672
					if ( isCache[ prop.idx ] != null ) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if isCache.prop.idx != null is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
12673
						same = ( isCache[ prop.idx ] === localCache[ prop.idx ] );
12674
						return same;
12675
					}
12676
				});
12677
			}
12678
			return same;
12679
		});
12680
		return same;
12681
	},
12682
	_space: function() {
12683
		var used = [],
12684
			inst = this;
12685
		each( spaces, function( spaceName, space ) {
12686
			if ( inst[ space.cache ] ) {
12687
				used.push( spaceName );
12688
			}
12689
		});
12690
		return used.pop();
12691
	},
12692
	transition: function( other, distance ) {
12693
		var end = color( other ),
12694
			spaceName = end._space(),
12695
			space = spaces[ spaceName ],
12696
			startColor = this.alpha() === 0 ? color( "transparent" ) : this,
12697
			start = startColor[ space.cache ] || space.to( startColor._rgba ),
12698
			result = start.slice();
12699
12700
		end = end[ space.cache ];
12701
		each( space.props, function( key, prop ) {
12702
			var index = prop.idx,
12703
				startValue = start[ index ],
12704
				endValue = end[ index ],
12705
				type = propTypes[ prop.type ] || {};
12706
12707
			// if null, don't override start value
12708
			if ( endValue === null ) {
12709
				return;
12710
			}
12711
			// if null - use end
12712
			if ( startValue === null ) {
12713
				result[ index ] = endValue;
12714
			} else {
12715
				if ( type.mod ) {
12716
					if ( endValue - startValue > type.mod / 2 ) {
12717
						startValue += type.mod;
12718
					} else if ( startValue - endValue > type.mod / 2 ) {
12719
						startValue -= type.mod;
12720
					}
12721
				}
12722
				result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop );
12723
			}
12724
		});
12725
		return this[ spaceName ]( result );
12726
	},
12727
	blend: function( opaque ) {
12728
		// if we are already opaque - return ourself
12729
		if ( this._rgba[ 3 ] === 1 ) {
12730
			return this;
12731
		}
12732
12733
		var rgb = this._rgba.slice(),
12734
			a = rgb.pop(),
12735
			blend = color( opaque )._rgba;
12736
12737
		return color( jQuery.map( rgb, function( v, i ) {
12738
			return ( 1 - a ) * blend[ i ] + a * v;
12739
		}));
12740
	},
12741
	toRgbaString: function() {
12742
		var prefix = "rgba(",
12743
			rgba = jQuery.map( this._rgba, function( v, i ) {
12744
				return v == null ? ( i > 2 ? 1 : 0 ) : v;
12745
			});
12746
12747
		if ( rgba[ 3 ] === 1 ) {
12748
			rgba.pop();
12749
			prefix = "rgb(";
12750
		}
12751
12752
		return prefix + rgba.join() + ")";
12753
	},
12754
	toHslaString: function() {
12755
		var prefix = "hsla(",
12756
			hsla = jQuery.map( this.hsla(), function( v, i ) {
12757
				if ( v == null ) {
12758
					v = i > 2 ? 1 : 0;
12759
				}
12760
12761
				// catch 1 and 2
12762
				if ( i && i < 3 ) {
12763
					v = Math.round( v * 100 ) + "%";
12764
				}
12765
				return v;
12766
			});
12767
12768
		if ( hsla[ 3 ] === 1 ) {
12769
			hsla.pop();
12770
			prefix = "hsl(";
12771
		}
12772
		return prefix + hsla.join() + ")";
12773
	},
12774
	toHexString: function( includeAlpha ) {
12775
		var rgba = this._rgba.slice(),
12776
			alpha = rgba.pop();
12777
12778
		if ( includeAlpha ) {
12779
			rgba.push( ~~( alpha * 255 ) );
12780
		}
12781
12782
		return "#" + jQuery.map( rgba, function( v ) {
12783
12784
			// default to 0 when nulls exist
12785
			v = ( v || 0 ).toString( 16 );
12786
			return v.length === 1 ? "0" + v : v;
12787
		}).join("");
12788
	},
12789
	toString: function() {
12790
		return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString();
12791
	}
12792
});
12793
color.fn.parse.prototype = color.fn;
12794
12795
// hsla conversions adapted from:
12796
// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021
12797
12798
function hue2rgb( p, q, h ) {
12799
	h = ( h + 1 ) % 1;
12800
	if ( h * 6 < 1 ) {
12801
		return p + (q - p) * h * 6;
12802
	}
12803
	if ( h * 2 < 1) {
12804
		return q;
12805
	}
12806
	if ( h * 3 < 2 ) {
12807
		return p + (q - p) * ((2/3) - h) * 6;
12808
	}
12809
	return p;
12810
}
12811
12812
spaces.hsla.to = function ( rgba ) {
12813
	if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) {
12814
		return [ null, null, null, rgba[ 3 ] ];
12815
	}
12816
	var r = rgba[ 0 ] / 255,
12817
		g = rgba[ 1 ] / 255,
12818
		b = rgba[ 2 ] / 255,
12819
		a = rgba[ 3 ],
12820
		max = Math.max( r, g, b ),
12821
		min = Math.min( r, g, b ),
12822
		diff = max - min,
12823
		add = max + min,
12824
		l = add * 0.5,
12825
		h, s;
12826
12827
	if ( min === max ) {
12828
		h = 0;
12829
	} else if ( r === max ) {
12830
		h = ( 60 * ( g - b ) / diff ) + 360;
12831
	} else if ( g === max ) {
12832
		h = ( 60 * ( b - r ) / diff ) + 120;
12833
	} else {
12834
		h = ( 60 * ( r - g ) / diff ) + 240;
12835
	}
12836
12837
	// chroma (diff) == 0 means greyscale which, by definition, saturation = 0%
12838
	// otherwise, saturation is based on the ratio of chroma (diff) to lightness (add)
12839
	if ( diff === 0 ) {
12840
		s = 0;
12841
	} else if ( l <= 0.5 ) {
12842
		s = diff / add;
12843
	} else {
12844
		s = diff / ( 2 - add );
12845
	}
12846
	return [ Math.round(h) % 360, s, l, a == null ? 1 : a ];
12847
};
12848
12849
spaces.hsla.from = function ( hsla ) {
12850
	if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) {
12851
		return [ null, null, null, hsla[ 3 ] ];
12852
	}
12853
	var h = hsla[ 0 ] / 360,
12854
		s = hsla[ 1 ],
12855
		l = hsla[ 2 ],
12856
		a = hsla[ 3 ],
12857
		q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s,
12858
		p = 2 * l - q;
12859
12860
	return [
12861
		Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ),
12862
		Math.round( hue2rgb( p, q, h ) * 255 ),
12863
		Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ),
12864
		a
12865
	];
12866
};
12867
12868
12869
each( spaces, function( spaceName, space ) {
12870
	var props = space.props,
12871
		cache = space.cache,
12872
		to = space.to,
12873
		from = space.from;
12874
12875
	// makes rgba() and hsla()
12876
	color.fn[ spaceName ] = function( value ) {
12877
12878
		// generate a cache for this space if it doesn't exist
12879
		if ( to && !this[ cache ] ) {
12880
			this[ cache ] = to( this._rgba );
12881
		}
12882
		if ( value === undefined ) {
12883
			return this[ cache ].slice();
12884
		}
12885
12886
		var ret,
12887
			type = jQuery.type( value ),
12888
			arr = ( type === "array" || type === "object" ) ? value : arguments,
12889
			local = this[ cache ].slice();
12890
12891
		each( props, function( key, prop ) {
12892
			var val = arr[ type === "object" ? key : prop.idx ];
12893
			if ( val == null ) {
12894
				val = local[ prop.idx ];
12895
			}
12896
			local[ prop.idx ] = clamp( val, prop );
12897
		});
12898
12899
		if ( from ) {
12900
			ret = color( from( local ) );
12901
			ret[ cache ] = local;
12902
			return ret;
12903
		} else {
12904
			return color( local );
12905
		}
12906
	};
12907
12908
	// makes red() green() blue() alpha() hue() saturation() lightness()
12909
	each( props, function( key, prop ) {
12910
		// alpha is included in more than one space
12911
		if ( color.fn[ key ] ) {
12912
			return;
12913
		}
12914
		color.fn[ key ] = function( value ) {
12915
			var vtype = jQuery.type( value ),
12916
				fn = ( key === "alpha" ? ( this._hsla ? "hsla" : "rgba" ) : spaceName ),
12917
				local = this[ fn ](),
12918
				cur = local[ prop.idx ],
12919
				match;
12920
12921
			if ( vtype === "undefined" ) {
12922
				return cur;
12923
			}
12924
12925
			if ( vtype === "function" ) {
12926
				value = value.call( this, cur );
12927
				vtype = jQuery.type( value );
12928
			}
12929
			if ( value == null && prop.empty ) {
12930
				return this;
12931
			}
12932
			if ( vtype === "string" ) {
12933
				match = rplusequals.exec( value );
12934
				if ( match ) {
12935
					value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 );
12936
				}
12937
			}
12938
			local[ prop.idx ] = value;
12939
			return this[ fn ]( local );
12940
		};
12941
	});
12942
});
12943
12944
// add cssHook and .fx.step function for each named hook.
12945
// accept a space separated string of properties
12946
color.hook = function( hook ) {
12947
	var hooks = hook.split( " " );
12948
	each( hooks, function( i, hook ) {
12949
		jQuery.cssHooks[ hook ] = {
12950
			set: function( elem, value ) {
12951
				var parsed, curElem,
12952
					backgroundColor = "";
12953
12954
				if ( value !== "transparent" && ( jQuery.type( value ) !== "string" || ( parsed = stringParse( value ) ) ) ) {
12955
					value = color( parsed || value );
12956
					if ( !support.rgba && value._rgba[ 3 ] !== 1 ) {
12957
						curElem = hook === "backgroundColor" ? elem.parentNode : elem;
12958
						while (
12959
							(backgroundColor === "" || backgroundColor === "transparent") &&
12960
							curElem && curElem.style
12961
						) {
12962
							try {
12963
								backgroundColor = jQuery.css( curElem, "backgroundColor" );
12964
								curElem = curElem.parentNode;
12965
							} catch ( e ) {
0 ignored issues
show
Coding Style Comprehensibility Best Practice introduced by
Empty catch clauses should be used with caution; consider adding a comment why this is needed.
Loading history...
12966
							}
12967
						}
12968
12969
						value = value.blend( backgroundColor && backgroundColor !== "transparent" ?
12970
							backgroundColor :
12971
							"_default" );
12972
					}
12973
12974
					value = value.toRgbaString();
12975
				}
12976
				try {
12977
					elem.style[ hook ] = value;
12978
				} catch( e ) {
12979
					// wrapped to prevent IE from throwing errors on "invalid" values like 'auto' or 'inherit'
12980
				}
12981
			}
12982
		};
12983
		jQuery.fx.step[ hook ] = function( fx ) {
12984
			if ( !fx.colorInit ) {
12985
				fx.start = color( fx.elem, hook );
12986
				fx.end = color( fx.end );
12987
				fx.colorInit = true;
12988
			}
12989
			jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) );
12990
		};
12991
	});
12992
12993
};
12994
12995
color.hook( stepHooks );
12996
12997
jQuery.cssHooks.borderColor = {
12998
	expand: function( value ) {
12999
		var expanded = {};
13000
13001
		each( [ "Top", "Right", "Bottom", "Left" ], function( i, part ) {
13002
			expanded[ "border" + part + "Color" ] = value;
13003
		});
13004
		return expanded;
13005
	}
13006
};
13007
13008
// Basic color names only.
13009
// Usage of any of the other color names requires adding yourself or including
13010
// jquery.color.svg-names.js.
13011
colors = jQuery.Color.names = {
13012
	// 4.1. Basic color keywords
13013
	aqua: "#00ffff",
13014
	black: "#000000",
13015
	blue: "#0000ff",
13016
	fuchsia: "#ff00ff",
13017
	gray: "#808080",
13018
	green: "#008000",
13019
	lime: "#00ff00",
13020
	maroon: "#800000",
13021
	navy: "#000080",
13022
	olive: "#808000",
13023
	purple: "#800080",
13024
	red: "#ff0000",
13025
	silver: "#c0c0c0",
13026
	teal: "#008080",
13027
	white: "#ffffff",
13028
	yellow: "#ffff00",
13029
13030
	// 4.2.3. "transparent" color keyword
13031
	transparent: [ null, null, null, 0 ],
13032
13033
	_default: "#ffffff"
13034
};
13035
13036
})( jQuery );
13037
13038
13039
/******************************************************************************/
13040
/****************************** CLASS ANIMATIONS ******************************/
13041
/******************************************************************************/
13042
(function() {
13043
13044
var classAnimationActions = [ "add", "remove", "toggle" ],
13045
	shorthandStyles = {
13046
		border: 1,
13047
		borderBottom: 1,
13048
		borderColor: 1,
13049
		borderLeft: 1,
13050
		borderRight: 1,
13051
		borderTop: 1,
13052
		borderWidth: 1,
13053
		margin: 1,
13054
		padding: 1
13055
	};
13056
13057
$.each([ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], function( _, prop ) {
13058
	$.fx.step[ prop ] = function( fx ) {
13059
		if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) {
13060
			jQuery.style( fx.elem, prop, fx.end );
13061
			fx.setAttr = true;
13062
		}
13063
	};
13064
});
13065
13066
function getElementStyles( elem ) {
13067
	var key, len,
13068
		style = elem.ownerDocument.defaultView ?
13069
			elem.ownerDocument.defaultView.getComputedStyle( elem, null ) :
13070
			elem.currentStyle,
13071
		styles = {};
13072
13073
	if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) {
13074
		len = style.length;
13075
		while ( len-- ) {
13076
			key = style[ len ];
13077
			if ( typeof style[ key ] === "string" ) {
13078
				styles[ $.camelCase( key ) ] = style[ key ];
13079
			}
13080
		}
13081
	// support: Opera, IE <9
13082
	} else {
13083
		for ( key in style ) {
13084
			if ( typeof style[ key ] === "string" ) {
13085
				styles[ key ] = style[ key ];
13086
			}
13087
		}
13088
	}
13089
13090
	return styles;
13091
}
13092
13093
13094
function styleDifference( oldStyle, newStyle ) {
13095
	var diff = {},
13096
		name, value;
13097
13098
	for ( name in newStyle ) {
13099
		value = newStyle[ name ];
13100
		if ( oldStyle[ name ] !== value ) {
13101
			if ( !shorthandStyles[ name ] ) {
13102
				if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {
13103
					diff[ name ] = value;
13104
				}
13105
			}
13106
		}
13107
	}
13108
13109
	return diff;
13110
}
13111
13112
// support: jQuery <1.8
13113
if ( !$.fn.addBack ) {
13114
	$.fn.addBack = function( selector ) {
13115
		return this.add( selector == null ?
13116
			this.prevObject : this.prevObject.filter( selector )
13117
		);
13118
	};
13119
}
13120
13121
$.effects.animateClass = function( value, duration, easing, callback ) {
13122
	var o = $.speed( duration, easing, callback );
13123
13124
	return this.queue( function() {
13125
		var animated = $( this ),
13126
			baseClass = animated.attr( "class" ) || "",
13127
			applyClassChange,
13128
			allAnimations = o.children ? animated.find( "*" ).addBack() : animated;
13129
13130
		// map the animated objects to store the original styles.
13131
		allAnimations = allAnimations.map(function() {
13132
			var el = $( this );
13133
			return {
13134
				el: el,
13135
				start: getElementStyles( this )
13136
			};
13137
		});
13138
13139
		// apply class change
13140
		applyClassChange = function() {
13141
			$.each( classAnimationActions, function(i, action) {
13142
				if ( value[ action ] ) {
13143
					animated[ action + "Class" ]( value[ action ] );
13144
				}
13145
			});
13146
		};
13147
		applyClassChange();
13148
13149
		// map all animated objects again - calculate new styles and diff
13150
		allAnimations = allAnimations.map(function() {
13151
			this.end = getElementStyles( this.el[ 0 ] );
13152
			this.diff = styleDifference( this.start, this.end );
13153
			return this;
13154
		});
13155
13156
		// apply original class
13157
		animated.attr( "class", baseClass );
13158
13159
		// map all animated objects again - this time collecting a promise
13160
		allAnimations = allAnimations.map(function() {
13161
			var styleInfo = this,
13162
				dfd = $.Deferred(),
13163
				opts = $.extend({}, o, {
13164
					queue: false,
13165
					complete: function() {
13166
						dfd.resolve( styleInfo );
13167
					}
13168
				});
13169
13170
			this.el.animate( this.diff, opts );
13171
			return dfd.promise();
13172
		});
13173
13174
		// once all animations have completed:
13175
		$.when.apply( $, allAnimations.get() ).done(function() {
13176
13177
			// set the final class
13178
			applyClassChange();
13179
13180
			// for each animated element,
13181
			// clear all css properties that were animated
13182
			$.each( arguments, function() {
13183
				var el = this.el;
13184
				$.each( this.diff, function(key) {
13185
					el.css( key, "" );
13186
				});
13187
			});
13188
13189
			// this is guarnteed to be there if you use jQuery.speed()
13190
			// it also handles dequeuing the next anim...
13191
			o.complete.call( animated[ 0 ] );
13192
		});
13193
	});
13194
};
13195
13196
$.fn.extend({
13197
	addClass: (function( orig ) {
13198
		return function( classNames, speed, easing, callback ) {
13199
			return speed ?
13200
				$.effects.animateClass.call( this,
13201
					{ add: classNames }, speed, easing, callback ) :
13202
				orig.apply( this, arguments );
13203
		};
13204
	})( $.fn.addClass ),
13205
13206
	removeClass: (function( orig ) {
13207
		return function( classNames, speed, easing, callback ) {
13208
			return arguments.length > 1 ?
13209
				$.effects.animateClass.call( this,
13210
					{ remove: classNames }, speed, easing, callback ) :
13211
				orig.apply( this, arguments );
13212
		};
13213
	})( $.fn.removeClass ),
13214
13215
	toggleClass: (function( orig ) {
13216
		return function( classNames, force, speed, easing, callback ) {
13217
			if ( typeof force === "boolean" || force === undefined ) {
13218
				if ( !speed ) {
13219
					// without speed parameter
13220
					return orig.apply( this, arguments );
13221
				} else {
13222
					return $.effects.animateClass.call( this,
13223
						(force ? { add: classNames } : { remove: classNames }),
13224
						speed, easing, callback );
13225
				}
13226
			} else {
13227
				// without force parameter
13228
				return $.effects.animateClass.call( this,
13229
					{ toggle: classNames }, force, speed, easing );
13230
			}
13231
		};
13232
	})( $.fn.toggleClass ),
13233
13234
	switchClass: function( remove, add, speed, easing, callback) {
13235
		return $.effects.animateClass.call( this, {
13236
			add: add,
13237
			remove: remove
13238
		}, speed, easing, callback );
13239
	}
13240
});
13241
13242
})();
13243
13244
/******************************************************************************/
13245
/*********************************** EFFECTS **********************************/
13246
/******************************************************************************/
13247
13248
(function() {
13249
13250
$.extend( $.effects, {
13251
	version: "1.10.4",
13252
13253
	// Saves a set of properties in a data storage
13254
	save: function( element, set ) {
13255
		for( var i=0; i < set.length; i++ ) {
13256
			if ( set[ i ] !== null ) {
13257
				element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );
13258
			}
13259
		}
13260
	},
13261
13262
	// Restores a set of previously saved properties from a data storage
13263
	restore: function( element, set ) {
13264
		var val, i;
13265
		for( i=0; i < set.length; i++ ) {
13266
			if ( set[ i ] !== null ) {
13267
				val = element.data( dataSpace + set[ i ] );
13268
				// support: jQuery 1.6.2
13269
				// http://bugs.jquery.com/ticket/9917
13270
				// jQuery 1.6.2 incorrectly returns undefined for any falsy value.
13271
				// We can't differentiate between "" and 0 here, so we just assume
13272
				// empty string since it's likely to be a more common value...
13273
				if ( val === undefined ) {
13274
					val = "";
13275
				}
13276
				element.css( set[ i ], val );
13277
			}
13278
		}
13279
	},
13280
13281
	setMode: function( el, mode ) {
13282
		if (mode === "toggle") {
13283
			mode = el.is( ":hidden" ) ? "show" : "hide";
13284
		}
13285
		return mode;
13286
	},
13287
13288
	// Translates a [top,left] array into a baseline value
13289
	// this should be a little more flexible in the future to handle a string & hash
13290
	getBaseline: function( origin, original ) {
13291
		var y, x;
13292
		switch ( origin[ 0 ] ) {
13293
			case "top": y = 0; break;
13294
			case "middle": y = 0.5; break;
13295
			case "bottom": y = 1; break;
13296
			default: y = origin[ 0 ] / original.height;
13297
		}
13298
		switch ( origin[ 1 ] ) {
13299
			case "left": x = 0; break;
13300
			case "center": x = 0.5; break;
13301
			case "right": x = 1; break;
13302
			default: x = origin[ 1 ] / original.width;
13303
		}
13304
		return {
13305
			x: x,
13306
			y: y
13307
		};
13308
	},
13309
13310
	// Wraps the element around a wrapper that copies position properties
13311
	createWrapper: function( element ) {
13312
13313
		// if the element is already wrapped, return it
13314
		if ( element.parent().is( ".ui-effects-wrapper" )) {
13315
			return element.parent();
13316
		}
13317
13318
		// wrap the element
13319
		var props = {
13320
				width: element.outerWidth(true),
13321
				height: element.outerHeight(true),
13322
				"float": element.css( "float" )
13323
			},
13324
			wrapper = $( "<div></div>" )
13325
				.addClass( "ui-effects-wrapper" )
13326
				.css({
13327
					fontSize: "100%",
13328
					background: "transparent",
13329
					border: "none",
13330
					margin: 0,
13331
					padding: 0
13332
				}),
13333
			// Store the size in case width/height are defined in % - Fixes #5245
13334
			size = {
13335
				width: element.width(),
13336
				height: element.height()
13337
			},
13338
			active = document.activeElement;
13339
13340
		// support: Firefox
13341
		// Firefox incorrectly exposes anonymous content
13342
		// https://bugzilla.mozilla.org/show_bug.cgi?id=561664
13343
		try {
13344
			active.id;
0 ignored issues
show
introduced by
The result of the property access to active.id is not used.
Loading history...
13345
		} catch( e ) {
13346
			active = document.body;
13347
		}
13348
13349
		element.wrap( wrapper );
13350
13351
		// Fixes #7595 - Elements lose focus when wrapped.
13352
		if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
13353
			$( active ).focus();
13354
		}
13355
13356
		wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually lose the reference to the wrapped element
13357
13358
		// transfer positioning properties to the wrapper
13359
		if ( element.css( "position" ) === "static" ) {
13360
			wrapper.css({ position: "relative" });
13361
			element.css({ position: "relative" });
13362
		} else {
13363
			$.extend( props, {
13364
				position: element.css( "position" ),
13365
				zIndex: element.css( "z-index" )
13366
			});
13367
			$.each([ "top", "left", "bottom", "right" ], function(i, pos) {
13368
				props[ pos ] = element.css( pos );
13369
				if ( isNaN( parseInt( props[ pos ], 10 ) ) ) {
13370
					props[ pos ] = "auto";
13371
				}
13372
			});
13373
			element.css({
13374
				position: "relative",
13375
				top: 0,
13376
				left: 0,
13377
				right: "auto",
13378
				bottom: "auto"
13379
			});
13380
		}
13381
		element.css(size);
13382
13383
		return wrapper.css( props ).show();
13384
	},
13385
13386
	removeWrapper: function( element ) {
13387
		var active = document.activeElement;
13388
13389
		if ( element.parent().is( ".ui-effects-wrapper" ) ) {
13390
			element.parent().replaceWith( element );
13391
13392
			// Fixes #7595 - Elements lose focus when wrapped.
13393
			if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
13394
				$( active ).focus();
13395
			}
13396
		}
13397
13398
13399
		return element;
13400
	},
13401
13402
	setTransition: function( element, list, factor, value ) {
13403
		value = value || {};
13404
		$.each( list, function( i, x ) {
13405
			var unit = element.cssUnit( x );
13406
			if ( unit[ 0 ] > 0 ) {
13407
				value[ x ] = unit[ 0 ] * factor + unit[ 1 ];
13408
			}
13409
		});
13410
		return value;
13411
	}
13412
});
13413
13414
// return an effect options object for the given parameters:
13415
function _normalizeArguments( effect, options, speed, callback ) {
13416
13417
	// allow passing all options as the first parameter
13418
	if ( $.isPlainObject( effect ) ) {
13419
		options = effect;
13420
		effect = effect.effect;
13421
	}
13422
13423
	// convert to an object
13424
	effect = { effect: effect };
13425
13426
	// catch (effect, null, ...)
13427
	if ( options == null ) {
13428
		options = {};
13429
	}
13430
13431
	// catch (effect, callback)
13432
	if ( $.isFunction( options ) ) {
13433
		callback = options;
13434
		speed = null;
13435
		options = {};
13436
	}
13437
13438
	// catch (effect, speed, ?)
13439
	if ( typeof options === "number" || $.fx.speeds[ options ] ) {
13440
		callback = speed;
13441
		speed = options;
13442
		options = {};
13443
	}
13444
13445
	// catch (effect, options, callback)
13446
	if ( $.isFunction( speed ) ) {
13447
		callback = speed;
13448
		speed = null;
13449
	}
13450
13451
	// add options to effect
13452
	if ( options ) {
13453
		$.extend( effect, options );
13454
	}
13455
13456
	speed = speed || options.duration;
13457
	effect.duration = $.fx.off ? 0 :
13458
		typeof speed === "number" ? speed :
13459
		speed in $.fx.speeds ? $.fx.speeds[ speed ] :
13460
		$.fx.speeds._default;
13461
13462
	effect.complete = callback || options.complete;
13463
13464
	return effect;
13465
}
13466
13467
function standardAnimationOption( option ) {
13468
	// Valid standard speeds (nothing, number, named speed)
13469
	if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) {
13470
		return true;
13471
	}
13472
13473
	// Invalid strings - treat as "normal" speed
13474
	if ( typeof option === "string" && !$.effects.effect[ option ] ) {
13475
		return true;
13476
	}
13477
13478
	// Complete callback
13479
	if ( $.isFunction( option ) ) {
13480
		return true;
13481
	}
13482
13483
	// Options hash (but not naming an effect)
13484
	if ( typeof option === "object" && !option.effect ) {
13485
		return true;
13486
	}
13487
13488
	// Didn't match any standard API
13489
	return false;
13490
}
13491
13492
$.fn.extend({
13493
	effect: function( /* effect, options, speed, callback */ ) {
13494
		var args = _normalizeArguments.apply( this, arguments ),
13495
			mode = args.mode,
13496
			queue = args.queue,
13497
			effectMethod = $.effects.effect[ args.effect ];
13498
13499
		if ( $.fx.off || !effectMethod ) {
13500
			// delegate to the original method (e.g., .show()) if possible
13501
			if ( mode ) {
13502
				return this[ mode ]( args.duration, args.complete );
13503
			} else {
13504
				return this.each( function() {
13505
					if ( args.complete ) {
13506
						args.complete.call( this );
13507
					}
13508
				});
13509
			}
13510
		}
13511
13512
		function run( next ) {
13513
			var elem = $( this ),
13514
				complete = args.complete,
13515
				mode = args.mode;
13516
13517
			function done() {
13518
				if ( $.isFunction( complete ) ) {
13519
					complete.call( elem[0] );
13520
				}
13521
				if ( $.isFunction( next ) ) {
13522
					next();
13523
				}
13524
			}
13525
13526
			// If the element already has the correct final state, delegate to
13527
			// the core methods so the internal tracking of "olddisplay" works.
13528
			if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) {
13529
				elem[ mode ]();
13530
				done();
13531
			} else {
13532
				effectMethod.call( elem[0], args, done );
13533
			}
13534
		}
13535
13536
		return queue === false ? this.each( run ) : this.queue( queue || "fx", run );
13537
	},
13538
13539
	show: (function( orig ) {
13540
		return function( option ) {
13541
			if ( standardAnimationOption( option ) ) {
13542
				return orig.apply( this, arguments );
13543
			} else {
13544
				var args = _normalizeArguments.apply( this, arguments );
13545
				args.mode = "show";
13546
				return this.effect.call( this, args );
13547
			}
13548
		};
13549
	})( $.fn.show ),
13550
13551
	hide: (function( orig ) {
13552
		return function( option ) {
13553
			if ( standardAnimationOption( option ) ) {
13554
				return orig.apply( this, arguments );
13555
			} else {
13556
				var args = _normalizeArguments.apply( this, arguments );
13557
				args.mode = "hide";
13558
				return this.effect.call( this, args );
13559
			}
13560
		};
13561
	})( $.fn.hide ),
13562
13563
	toggle: (function( orig ) {
13564
		return function( option ) {
13565
			if ( standardAnimationOption( option ) || typeof option === "boolean" ) {
13566
				return orig.apply( this, arguments );
13567
			} else {
13568
				var args = _normalizeArguments.apply( this, arguments );
13569
				args.mode = "toggle";
13570
				return this.effect.call( this, args );
13571
			}
13572
		};
13573
	})( $.fn.toggle ),
13574
13575
	// helper functions
13576
	cssUnit: function(key) {
13577
		var style = this.css( key ),
13578
			val = [];
13579
13580
		$.each( [ "em", "px", "%", "pt" ], function( i, unit ) {
13581
			if ( style.indexOf( unit ) > 0 ) {
13582
				val = [ parseFloat( style ), unit ];
13583
			}
13584
		});
13585
		return val;
13586
	}
13587
});
13588
13589
})();
13590
13591
/******************************************************************************/
13592
/*********************************** EASING ***********************************/
13593
/******************************************************************************/
13594
13595
(function() {
13596
13597
// based on easing equations from Robert Penner (http://www.robertpenner.com/easing)
13598
13599
var baseEasings = {};
13600
13601
$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) {
13602
	baseEasings[ name ] = function( p ) {
13603
		return Math.pow( p, i + 2 );
13604
	};
13605
});
13606
13607
$.extend( baseEasings, {
13608
	Sine: function ( p ) {
13609
		return 1 - Math.cos( p * Math.PI / 2 );
13610
	},
13611
	Circ: function ( p ) {
13612
		return 1 - Math.sqrt( 1 - p * p );
13613
	},
13614
	Elastic: function( p ) {
13615
		return p === 0 || p === 1 ? p :
13616
			-Math.pow( 2, 8 * (p - 1) ) * Math.sin( ( (p - 1) * 80 - 7.5 ) * Math.PI / 15 );
13617
	},
13618
	Back: function( p ) {
13619
		return p * p * ( 3 * p - 2 );
13620
	},
13621
	Bounce: function ( p ) {
13622
		var pow2,
13623
			bounce = 4;
13624
13625
		while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}
0 ignored issues
show
Comprehensibility Documentation Best Practice introduced by
This code block is empty. Consider removing it or adding a comment to explain.
Loading history...
13626
		return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );
13627
	}
13628
});
13629
13630
$.each( baseEasings, function( name, easeIn ) {
13631
	$.easing[ "easeIn" + name ] = easeIn;
13632
	$.easing[ "easeOut" + name ] = function( p ) {
13633
		return 1 - easeIn( 1 - p );
13634
	};
13635
	$.easing[ "easeInOut" + name ] = function( p ) {
13636
		return p < 0.5 ?
13637
			easeIn( p * 2 ) / 2 :
13638
			1 - easeIn( p * -2 + 2 ) / 2;
13639
	};
13640
});
13641
13642
})();
13643
13644
})(jQuery);
13645
(function( $, undefined ) {
0 ignored issues
show
Unused Code introduced by
The parameter undefined is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
13646
13647
var rvertical = /up|down|vertical/,
13648
	rpositivemotion = /up|left|vertical|horizontal/;
13649
13650
$.effects.effect.blind = function( o, done ) {
13651
	// Create element
13652
	var el = $( this ),
13653
		props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
13654
		mode = $.effects.setMode( el, o.mode || "hide" ),
13655
		direction = o.direction || "up",
13656
		vertical = rvertical.test( direction ),
13657
		ref = vertical ? "height" : "width",
13658
		ref2 = vertical ? "top" : "left",
13659
		motion = rpositivemotion.test( direction ),
13660
		animation = {},
13661
		show = mode === "show",
13662
		wrapper, distance, margin;
13663
13664
	// if already wrapped, the wrapper's properties are my property. #6245
13665
	if ( el.parent().is( ".ui-effects-wrapper" ) ) {
13666
		$.effects.save( el.parent(), props );
13667
	} else {
13668
		$.effects.save( el, props );
13669
	}
13670
	el.show();
13671
	wrapper = $.effects.createWrapper( el ).css({
13672
		overflow: "hidden"
13673
	});
13674
13675
	distance = wrapper[ ref ]();
13676
	margin = parseFloat( wrapper.css( ref2 ) ) || 0;
13677
13678
	animation[ ref ] = show ? distance : 0;
13679
	if ( !motion ) {
13680
		el
13681
			.css( vertical ? "bottom" : "right", 0 )
13682
			.css( vertical ? "top" : "left", "auto" )
13683
			.css({ position: "absolute" });
13684
13685
		animation[ ref2 ] = show ? margin : distance + margin;
13686
	}
13687
13688
	// start at 0 if we are showing
13689
	if ( show ) {
13690
		wrapper.css( ref, 0 );
13691
		if ( ! motion ) {
13692
			wrapper.css( ref2, margin + distance );
13693
		}
13694
	}
13695
13696
	// Animate
13697
	wrapper.animate( animation, {
13698
		duration: o.duration,
13699
		easing: o.easing,
13700
		queue: false,
13701
		complete: function() {
13702
			if ( mode === "hide" ) {
13703
				el.hide();
13704
			}
13705
			$.effects.restore( el, props );
13706
			$.effects.removeWrapper( el );
13707
			done();
13708
		}
13709
	});
13710
13711
};
13712
13713
})(jQuery);
13714
(function( $, undefined ) {
0 ignored issues
show
Unused Code introduced by
The parameter undefined is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
13715
13716
$.effects.effect.bounce = function( o, done ) {
13717
	var el = $( this ),
13718
		props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
13719
13720
		// defaults:
13721
		mode = $.effects.setMode( el, o.mode || "effect" ),
13722
		hide = mode === "hide",
13723
		show = mode === "show",
13724
		direction = o.direction || "up",
13725
		distance = o.distance,
13726
		times = o.times || 5,
13727
13728
		// number of internal animations
13729
		anims = times * 2 + ( show || hide ? 1 : 0 ),
13730
		speed = o.duration / anims,
13731
		easing = o.easing,
13732
13733
		// utility:
13734
		ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
13735
		motion = ( direction === "up" || direction === "left" ),
13736
		i,
13737
		upAnim,
13738
		downAnim,
13739
13740
		// we will need to re-assemble the queue to stack our animations in place
13741
		queue = el.queue(),
13742
		queuelen = queue.length;
13743
13744
	// Avoid touching opacity to prevent clearType and PNG issues in IE
13745
	if ( show || hide ) {
13746
		props.push( "opacity" );
13747
	}
13748
13749
	$.effects.save( el, props );
13750
	el.show();
13751
	$.effects.createWrapper( el ); // Create Wrapper
13752
13753
	// default distance for the BIGGEST bounce is the outer Distance / 3
13754
	if ( !distance ) {
13755
		distance = el[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3;
13756
	}
13757
13758
	if ( show ) {
13759
		downAnim = { opacity: 1 };
13760
		downAnim[ ref ] = 0;
13761
13762
		// if we are showing, force opacity 0 and set the initial position
13763
		// then do the "first" animation
13764
		el.css( "opacity", 0 )
13765
			.css( ref, motion ? -distance * 2 : distance * 2 )
13766
			.animate( downAnim, speed, easing );
13767
	}
13768
13769
	// start at the smallest distance if we are hiding
13770
	if ( hide ) {
13771
		distance = distance / Math.pow( 2, times - 1 );
13772
	}
13773
13774
	downAnim = {};
13775
	downAnim[ ref ] = 0;
13776
	// Bounces up/down/left/right then back to 0 -- times * 2 animations happen here
13777
	for ( i = 0; i < times; i++ ) {
13778
		upAnim = {};
13779
		upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
13780
13781
		el.animate( upAnim, speed, easing )
13782
			.animate( downAnim, speed, easing );
13783
13784
		distance = hide ? distance * 2 : distance / 2;
13785
	}
13786
13787
	// Last Bounce when Hiding
13788
	if ( hide ) {
13789
		upAnim = { opacity: 0 };
13790
		upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
13791
13792
		el.animate( upAnim, speed, easing );
13793
	}
13794
13795
	el.queue(function() {
13796
		if ( hide ) {
13797
			el.hide();
13798
		}
13799
		$.effects.restore( el, props );
13800
		$.effects.removeWrapper( el );
13801
		done();
13802
	});
13803
13804
	// inject all the animations we just queued to be first in line (after "inprogress")
13805
	if ( queuelen > 1) {
13806
		queue.splice.apply( queue,
13807
			[ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
13808
	}
13809
	el.dequeue();
13810
13811
};
13812
13813
})(jQuery);
13814
(function( $, undefined ) {
0 ignored issues
show
Unused Code introduced by
The parameter undefined is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
13815
13816
$.effects.effect.clip = function( o, done ) {
13817
	// Create element
13818
	var el = $( this ),
13819
		props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
13820
		mode = $.effects.setMode( el, o.mode || "hide" ),
13821
		show = mode === "show",
13822
		direction = o.direction || "vertical",
13823
		vert = direction === "vertical",
13824
		size = vert ? "height" : "width",
13825
		position = vert ? "top" : "left",
13826
		animation = {},
13827
		wrapper, animate, distance;
13828
13829
	// Save & Show
13830
	$.effects.save( el, props );
13831
	el.show();
13832
13833
	// Create Wrapper
13834
	wrapper = $.effects.createWrapper( el ).css({
13835
		overflow: "hidden"
13836
	});
13837
	animate = ( el[0].tagName === "IMG" ) ? wrapper : el;
13838
	distance = animate[ size ]();
13839
13840
	// Shift
13841
	if ( show ) {
13842
		animate.css( size, 0 );
13843
		animate.css( position, distance / 2 );
13844
	}
13845
13846
	// Create Animation Object:
13847
	animation[ size ] = show ? distance : 0;
13848
	animation[ position ] = show ? 0 : distance / 2;
13849
13850
	// Animate
13851
	animate.animate( animation, {
13852
		queue: false,
13853
		duration: o.duration,
13854
		easing: o.easing,
13855
		complete: function() {
13856
			if ( !show ) {
13857
				el.hide();
13858
			}
13859
			$.effects.restore( el, props );
13860
			$.effects.removeWrapper( el );
13861
			done();
13862
		}
13863
	});
13864
13865
};
13866
13867
})(jQuery);
13868
(function( $, undefined ) {
0 ignored issues
show
Unused Code introduced by
The parameter undefined is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
13869
13870
$.effects.effect.drop = function( o, done ) {
13871
13872
	var el = $( this ),
13873
		props = [ "position", "top", "bottom", "left", "right", "opacity", "height", "width" ],
13874
		mode = $.effects.setMode( el, o.mode || "hide" ),
13875
		show = mode === "show",
13876
		direction = o.direction || "left",
13877
		ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
13878
		motion = ( direction === "up" || direction === "left" ) ? "pos" : "neg",
13879
		animation = {
13880
			opacity: show ? 1 : 0
13881
		},
13882
		distance;
13883
13884
	// Adjust
13885
	$.effects.save( el, props );
13886
	el.show();
13887
	$.effects.createWrapper( el );
13888
13889
	distance = o.distance || el[ ref === "top" ? "outerHeight": "outerWidth" ]( true ) / 2;
13890
13891
	if ( show ) {
13892
		el
13893
			.css( "opacity", 0 )
13894
			.css( ref, motion === "pos" ? -distance : distance );
13895
	}
13896
13897
	// Animation
13898
	animation[ ref ] = ( show ?
13899
		( motion === "pos" ? "+=" : "-=" ) :
13900
		( motion === "pos" ? "-=" : "+=" ) ) +
13901
		distance;
13902
13903
	// Animate
13904
	el.animate( animation, {
13905
		queue: false,
13906
		duration: o.duration,
13907
		easing: o.easing,
13908
		complete: function() {
13909
			if ( mode === "hide" ) {
13910
				el.hide();
13911
			}
13912
			$.effects.restore( el, props );
13913
			$.effects.removeWrapper( el );
13914
			done();
13915
		}
13916
	});
13917
};
13918
13919
})(jQuery);
13920
(function( $, undefined ) {
0 ignored issues
show
Unused Code introduced by
The parameter undefined is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
13921
13922
$.effects.effect.explode = function( o, done ) {
13923
13924
	var rows = o.pieces ? Math.round( Math.sqrt( o.pieces ) ) : 3,
13925
		cells = rows,
13926
		el = $( this ),
13927
		mode = $.effects.setMode( el, o.mode || "hide" ),
13928
		show = mode === "show",
13929
13930
		// show and then visibility:hidden the element before calculating offset
13931
		offset = el.show().css( "visibility", "hidden" ).offset(),
13932
13933
		// width and height of a piece
13934
		width = Math.ceil( el.outerWidth() / cells ),
13935
		height = Math.ceil( el.outerHeight() / rows ),
13936
		pieces = [],
13937
13938
		// loop
13939
		i, j, left, top, mx, my;
13940
13941
	// children animate complete:
13942
	function childComplete() {
13943
		pieces.push( this );
13944
		if ( pieces.length === rows * cells ) {
13945
			animComplete();
13946
		}
13947
	}
13948
13949
	// clone the element for each row and cell.
13950
	for( i = 0; i < rows ; i++ ) { // ===>
13951
		top = offset.top + i * height;
13952
		my = i - ( rows - 1 ) / 2 ;
13953
13954
		for( j = 0; j < cells ; j++ ) { // |||
13955
			left = offset.left + j * width;
13956
			mx = j - ( cells - 1 ) / 2 ;
13957
13958
			// Create a clone of the now hidden main element that will be absolute positioned
13959
			// within a wrapper div off the -left and -top equal to size of our pieces
13960
			el
13961
				.clone()
13962
				.appendTo( "body" )
13963
				.wrap( "<div></div>" )
13964
				.css({
13965
					position: "absolute",
13966
					visibility: "visible",
13967
					left: -j * width,
13968
					top: -i * height
13969
				})
13970
13971
			// select the wrapper - make it overflow: hidden and absolute positioned based on
13972
			// where the original was located +left and +top equal to the size of pieces
13973
				.parent()
13974
				.addClass( "ui-effects-explode" )
13975
				.css({
13976
					position: "absolute",
13977
					overflow: "hidden",
13978
					width: width,
13979
					height: height,
13980
					left: left + ( show ? mx * width : 0 ),
13981
					top: top + ( show ? my * height : 0 ),
13982
					opacity: show ? 0 : 1
13983
				}).animate({
13984
					left: left + ( show ? 0 : mx * width ),
13985
					top: top + ( show ? 0 : my * height ),
13986
					opacity: show ? 1 : 0
13987
				}, o.duration || 500, o.easing, childComplete );
13988
		}
13989
	}
13990
13991
	function animComplete() {
13992
		el.css({
13993
			visibility: "visible"
13994
		});
13995
		$( pieces ).remove();
13996
		if ( !show ) {
13997
			el.hide();
13998
		}
13999
		done();
14000
	}
14001
};
14002
14003
})(jQuery);
14004
(function( $, undefined ) {
0 ignored issues
show
Unused Code introduced by
The parameter undefined is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
14005
14006
$.effects.effect.fade = function( o, done ) {
14007
	var el = $( this ),
14008
		mode = $.effects.setMode( el, o.mode || "toggle" );
14009
14010
	el.animate({
14011
		opacity: mode
14012
	}, {
14013
		queue: false,
14014
		duration: o.duration,
14015
		easing: o.easing,
14016
		complete: done
14017
	});
14018
};
14019
14020
})( jQuery );
14021
(function( $, undefined ) {
0 ignored issues
show
Unused Code introduced by
The parameter undefined is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
14022
14023
$.effects.effect.fold = function( o, done ) {
14024
14025
	// Create element
14026
	var el = $( this ),
14027
		props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
14028
		mode = $.effects.setMode( el, o.mode || "hide" ),
14029
		show = mode === "show",
14030
		hide = mode === "hide",
14031
		size = o.size || 15,
14032
		percent = /([0-9]+)%/.exec( size ),
14033
		horizFirst = !!o.horizFirst,
14034
		widthFirst = show !== horizFirst,
14035
		ref = widthFirst ? [ "width", "height" ] : [ "height", "width" ],
14036
		duration = o.duration / 2,
14037
		wrapper, distance,
14038
		animation1 = {},
14039
		animation2 = {};
14040
14041
	$.effects.save( el, props );
14042
	el.show();
14043
14044
	// Create Wrapper
14045
	wrapper = $.effects.createWrapper( el ).css({
14046
		overflow: "hidden"
14047
	});
14048
	distance = widthFirst ?
14049
		[ wrapper.width(), wrapper.height() ] :
14050
		[ wrapper.height(), wrapper.width() ];
14051
14052
	if ( percent ) {
14053
		size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ];
14054
	}
14055
	if ( show ) {
14056
		wrapper.css( horizFirst ? {
14057
			height: 0,
14058
			width: size
14059
		} : {
14060
			height: size,
14061
			width: 0
14062
		});
14063
	}
14064
14065
	// Animation
14066
	animation1[ ref[ 0 ] ] = show ? distance[ 0 ] : size;
14067
	animation2[ ref[ 1 ] ] = show ? distance[ 1 ] : 0;
14068
14069
	// Animate
14070
	wrapper
14071
		.animate( animation1, duration, o.easing )
14072
		.animate( animation2, duration, o.easing, function() {
14073
			if ( hide ) {
14074
				el.hide();
14075
			}
14076
			$.effects.restore( el, props );
14077
			$.effects.removeWrapper( el );
14078
			done();
14079
		});
14080
14081
};
14082
14083
})(jQuery);
14084
(function( $, undefined ) {
0 ignored issues
show
Unused Code introduced by
The parameter undefined is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
14085
14086
$.effects.effect.highlight = function( o, done ) {
14087
	var elem = $( this ),
14088
		props = [ "backgroundImage", "backgroundColor", "opacity" ],
14089
		mode = $.effects.setMode( elem, o.mode || "show" ),
14090
		animation = {
14091
			backgroundColor: elem.css( "backgroundColor" )
14092
		};
14093
14094
	if (mode === "hide") {
14095
		animation.opacity = 0;
14096
	}
14097
14098
	$.effects.save( elem, props );
14099
14100
	elem
14101
		.show()
14102
		.css({
14103
			backgroundImage: "none",
14104
			backgroundColor: o.color || "#ffff99"
14105
		})
14106
		.animate( animation, {
14107
			queue: false,
14108
			duration: o.duration,
14109
			easing: o.easing,
14110
			complete: function() {
14111
				if ( mode === "hide" ) {
14112
					elem.hide();
14113
				}
14114
				$.effects.restore( elem, props );
14115
				done();
14116
			}
14117
		});
14118
};
14119
14120
})(jQuery);
14121
(function( $, undefined ) {
0 ignored issues
show
Unused Code introduced by
The parameter undefined is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
14122
14123
$.effects.effect.pulsate = function( o, done ) {
14124
	var elem = $( this ),
14125
		mode = $.effects.setMode( elem, o.mode || "show" ),
14126
		show = mode === "show",
14127
		hide = mode === "hide",
14128
		showhide = ( show || mode === "hide" ),
14129
14130
		// showing or hiding leaves of the "last" animation
14131
		anims = ( ( o.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ),
14132
		duration = o.duration / anims,
14133
		animateTo = 0,
14134
		queue = elem.queue(),
14135
		queuelen = queue.length,
14136
		i;
14137
14138
	if ( show || !elem.is(":visible")) {
14139
		elem.css( "opacity", 0 ).show();
14140
		animateTo = 1;
14141
	}
14142
14143
	// anims - 1 opacity "toggles"
14144
	for ( i = 1; i < anims; i++ ) {
14145
		elem.animate({
14146
			opacity: animateTo
14147
		}, duration, o.easing );
14148
		animateTo = 1 - animateTo;
14149
	}
14150
14151
	elem.animate({
14152
		opacity: animateTo
14153
	}, duration, o.easing);
14154
14155
	elem.queue(function() {
14156
		if ( hide ) {
14157
			elem.hide();
14158
		}
14159
		done();
14160
	});
14161
14162
	// We just queued up "anims" animations, we need to put them next in the queue
14163
	if ( queuelen > 1 ) {
14164
		queue.splice.apply( queue,
14165
			[ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
14166
	}
14167
	elem.dequeue();
14168
};
14169
14170
})(jQuery);
14171
(function( $, undefined ) {
0 ignored issues
show
Unused Code introduced by
The parameter undefined is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
14172
14173
$.effects.effect.puff = function( o, done ) {
14174
	var elem = $( this ),
14175
		mode = $.effects.setMode( elem, o.mode || "hide" ),
14176
		hide = mode === "hide",
14177
		percent = parseInt( o.percent, 10 ) || 150,
14178
		factor = percent / 100,
14179
		original = {
14180
			height: elem.height(),
14181
			width: elem.width(),
14182
			outerHeight: elem.outerHeight(),
14183
			outerWidth: elem.outerWidth()
14184
		};
14185
14186
	$.extend( o, {
14187
		effect: "scale",
14188
		queue: false,
14189
		fade: true,
14190
		mode: mode,
14191
		complete: done,
14192
		percent: hide ? percent : 100,
14193
		from: hide ?
14194
			original :
14195
			{
14196
				height: original.height * factor,
14197
				width: original.width * factor,
14198
				outerHeight: original.outerHeight * factor,
14199
				outerWidth: original.outerWidth * factor
14200
			}
14201
	});
14202
14203
	elem.effect( o );
14204
};
14205
14206
$.effects.effect.scale = function( o, done ) {
14207
14208
	// Create element
14209
	var el = $( this ),
14210
		options = $.extend( true, {}, o ),
14211
		mode = $.effects.setMode( el, o.mode || "effect" ),
14212
		percent = parseInt( o.percent, 10 ) ||
14213
			( parseInt( o.percent, 10 ) === 0 ? 0 : ( mode === "hide" ? 0 : 100 ) ),
14214
		direction = o.direction || "both",
14215
		origin = o.origin,
14216
		original = {
14217
			height: el.height(),
14218
			width: el.width(),
14219
			outerHeight: el.outerHeight(),
14220
			outerWidth: el.outerWidth()
14221
		},
14222
		factor = {
14223
			y: direction !== "horizontal" ? (percent / 100) : 1,
14224
			x: direction !== "vertical" ? (percent / 100) : 1
14225
		};
14226
14227
	// We are going to pass this effect to the size effect:
14228
	options.effect = "size";
14229
	options.queue = false;
14230
	options.complete = done;
14231
14232
	// Set default origin and restore for show/hide
14233
	if ( mode !== "effect" ) {
14234
		options.origin = origin || ["middle","center"];
14235
		options.restore = true;
14236
	}
14237
14238
	options.from = o.from || ( mode === "show" ? {
14239
		height: 0,
14240
		width: 0,
14241
		outerHeight: 0,
14242
		outerWidth: 0
14243
	} : original );
14244
	options.to = {
14245
		height: original.height * factor.y,
14246
		width: original.width * factor.x,
14247
		outerHeight: original.outerHeight * factor.y,
14248
		outerWidth: original.outerWidth * factor.x
14249
	};
14250
14251
	// Fade option to support puff
14252
	if ( options.fade ) {
14253
		if ( mode === "show" ) {
14254
			options.from.opacity = 0;
14255
			options.to.opacity = 1;
14256
		}
14257
		if ( mode === "hide" ) {
14258
			options.from.opacity = 1;
14259
			options.to.opacity = 0;
14260
		}
14261
	}
14262
14263
	// Animate
14264
	el.effect( options );
14265
14266
};
14267
14268
$.effects.effect.size = function( o, done ) {
14269
14270
	// Create element
14271
	var original, baseline, factor,
14272
		el = $( this ),
14273
		props0 = [ "position", "top", "bottom", "left", "right", "width", "height", "overflow", "opacity" ],
14274
14275
		// Always restore
14276
		props1 = [ "position", "top", "bottom", "left", "right", "overflow", "opacity" ],
14277
14278
		// Copy for children
14279
		props2 = [ "width", "height", "overflow" ],
14280
		cProps = [ "fontSize" ],
14281
		vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ],
14282
		hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ],
14283
14284
		// Set options
14285
		mode = $.effects.setMode( el, o.mode || "effect" ),
14286
		restore = o.restore || mode !== "effect",
14287
		scale = o.scale || "both",
14288
		origin = o.origin || [ "middle", "center" ],
14289
		position = el.css( "position" ),
14290
		props = restore ? props0 : props1,
14291
		zero = {
14292
			height: 0,
14293
			width: 0,
14294
			outerHeight: 0,
14295
			outerWidth: 0
14296
		};
14297
14298
	if ( mode === "show" ) {
14299
		el.show();
14300
	}
14301
	original = {
14302
		height: el.height(),
14303
		width: el.width(),
14304
		outerHeight: el.outerHeight(),
14305
		outerWidth: el.outerWidth()
14306
	};
14307
14308
	if ( o.mode === "toggle" && mode === "show" ) {
14309
		el.from = o.to || zero;
14310
		el.to = o.from || original;
14311
	} else {
14312
		el.from = o.from || ( mode === "show" ? zero : original );
14313
		el.to = o.to || ( mode === "hide" ? zero : original );
14314
	}
14315
14316
	// Set scaling factor
14317
	factor = {
14318
		from: {
14319
			y: el.from.height / original.height,
14320
			x: el.from.width / original.width
14321
		},
14322
		to: {
14323
			y: el.to.height / original.height,
14324
			x: el.to.width / original.width
14325
		}
14326
	};
14327
14328
	// Scale the css box
14329
	if ( scale === "box" || scale === "both" ) {
14330
14331
		// Vertical props scaling
14332
		if ( factor.from.y !== factor.to.y ) {
14333
			props = props.concat( vProps );
14334
			el.from = $.effects.setTransition( el, vProps, factor.from.y, el.from );
14335
			el.to = $.effects.setTransition( el, vProps, factor.to.y, el.to );
14336
		}
14337
14338
		// Horizontal props scaling
14339
		if ( factor.from.x !== factor.to.x ) {
14340
			props = props.concat( hProps );
14341
			el.from = $.effects.setTransition( el, hProps, factor.from.x, el.from );
14342
			el.to = $.effects.setTransition( el, hProps, factor.to.x, el.to );
14343
		}
14344
	}
14345
14346
	// Scale the content
14347
	if ( scale === "content" || scale === "both" ) {
14348
14349
		// Vertical props scaling
14350
		if ( factor.from.y !== factor.to.y ) {
14351
			props = props.concat( cProps ).concat( props2 );
14352
			el.from = $.effects.setTransition( el, cProps, factor.from.y, el.from );
14353
			el.to = $.effects.setTransition( el, cProps, factor.to.y, el.to );
14354
		}
14355
	}
14356
14357
	$.effects.save( el, props );
14358
	el.show();
14359
	$.effects.createWrapper( el );
14360
	el.css( "overflow", "hidden" ).css( el.from );
14361
14362
	// Adjust
14363
	if (origin) { // Calculate baseline shifts
14364
		baseline = $.effects.getBaseline( origin, original );
14365
		el.from.top = ( original.outerHeight - el.outerHeight() ) * baseline.y;
14366
		el.from.left = ( original.outerWidth - el.outerWidth() ) * baseline.x;
14367
		el.to.top = ( original.outerHeight - el.to.outerHeight ) * baseline.y;
14368
		el.to.left = ( original.outerWidth - el.to.outerWidth ) * baseline.x;
14369
	}
14370
	el.css( el.from ); // set top & left
14371
14372
	// Animate
14373
	if ( scale === "content" || scale === "both" ) { // Scale the children
14374
14375
		// Add margins/font-size
14376
		vProps = vProps.concat([ "marginTop", "marginBottom" ]).concat(cProps);
14377
		hProps = hProps.concat([ "marginLeft", "marginRight" ]);
14378
		props2 = props0.concat(vProps).concat(hProps);
14379
14380
		el.find( "*[width]" ).each( function(){
14381
			var child = $( this ),
14382
				c_original = {
14383
					height: child.height(),
14384
					width: child.width(),
14385
					outerHeight: child.outerHeight(),
14386
					outerWidth: child.outerWidth()
14387
				};
14388
			if (restore) {
14389
				$.effects.save(child, props2);
14390
			}
14391
14392
			child.from = {
14393
				height: c_original.height * factor.from.y,
14394
				width: c_original.width * factor.from.x,
14395
				outerHeight: c_original.outerHeight * factor.from.y,
14396
				outerWidth: c_original.outerWidth * factor.from.x
14397
			};
14398
			child.to = {
14399
				height: c_original.height * factor.to.y,
14400
				width: c_original.width * factor.to.x,
14401
				outerHeight: c_original.height * factor.to.y,
14402
				outerWidth: c_original.width * factor.to.x
14403
			};
14404
14405
			// Vertical props scaling
14406
			if ( factor.from.y !== factor.to.y ) {
14407
				child.from = $.effects.setTransition( child, vProps, factor.from.y, child.from );
14408
				child.to = $.effects.setTransition( child, vProps, factor.to.y, child.to );
14409
			}
14410
14411
			// Horizontal props scaling
14412
			if ( factor.from.x !== factor.to.x ) {
14413
				child.from = $.effects.setTransition( child, hProps, factor.from.x, child.from );
14414
				child.to = $.effects.setTransition( child, hProps, factor.to.x, child.to );
14415
			}
14416
14417
			// Animate children
14418
			child.css( child.from );
14419
			child.animate( child.to, o.duration, o.easing, function() {
14420
14421
				// Restore children
14422
				if ( restore ) {
14423
					$.effects.restore( child, props2 );
14424
				}
14425
			});
14426
		});
14427
	}
14428
14429
	// Animate
14430
	el.animate( el.to, {
14431
		queue: false,
14432
		duration: o.duration,
14433
		easing: o.easing,
14434
		complete: function() {
14435
			if ( el.to.opacity === 0 ) {
14436
				el.css( "opacity", el.from.opacity );
14437
			}
14438
			if( mode === "hide" ) {
14439
				el.hide();
14440
			}
14441
			$.effects.restore( el, props );
14442
			if ( !restore ) {
14443
14444
				// we need to calculate our new positioning based on the scaling
14445
				if ( position === "static" ) {
14446
					el.css({
14447
						position: "relative",
14448
						top: el.to.top,
14449
						left: el.to.left
14450
					});
14451
				} else {
14452
					$.each([ "top", "left" ], function( idx, pos ) {
14453
						el.css( pos, function( _, str ) {
14454
							var val = parseInt( str, 10 ),
14455
								toRef = idx ? el.to.left : el.to.top;
14456
14457
							// if original was "auto", recalculate the new value from wrapper
14458
							if ( str === "auto" ) {
14459
								return toRef + "px";
14460
							}
14461
14462
							return val + toRef + "px";
14463
						});
14464
					});
14465
				}
14466
			}
14467
14468
			$.effects.removeWrapper( el );
14469
			done();
14470
		}
14471
	});
14472
14473
};
14474
14475
})(jQuery);
14476
(function( $, undefined ) {
0 ignored issues
show
Unused Code introduced by
The parameter undefined is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
14477
14478
$.effects.effect.shake = function( o, done ) {
14479
14480
	var el = $( this ),
14481
		props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
14482
		mode = $.effects.setMode( el, o.mode || "effect" ),
14483
		direction = o.direction || "left",
14484
		distance = o.distance || 20,
14485
		times = o.times || 3,
14486
		anims = times * 2 + 1,
14487
		speed = Math.round(o.duration/anims),
14488
		ref = (direction === "up" || direction === "down") ? "top" : "left",
14489
		positiveMotion = (direction === "up" || direction === "left"),
14490
		animation = {},
14491
		animation1 = {},
14492
		animation2 = {},
14493
		i,
14494
14495
		// we will need to re-assemble the queue to stack our animations in place
14496
		queue = el.queue(),
14497
		queuelen = queue.length;
14498
14499
	$.effects.save( el, props );
14500
	el.show();
14501
	$.effects.createWrapper( el );
14502
14503
	// Animation
14504
	animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance;
14505
	animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2;
14506
	animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2;
14507
14508
	// Animate
14509
	el.animate( animation, speed, o.easing );
14510
14511
	// Shakes
14512
	for ( i = 1; i < times; i++ ) {
14513
		el.animate( animation1, speed, o.easing ).animate( animation2, speed, o.easing );
14514
	}
14515
	el
14516
		.animate( animation1, speed, o.easing )
14517
		.animate( animation, speed / 2, o.easing )
14518
		.queue(function() {
14519
			if ( mode === "hide" ) {
14520
				el.hide();
14521
			}
14522
			$.effects.restore( el, props );
14523
			$.effects.removeWrapper( el );
14524
			done();
14525
		});
14526
14527
	// inject all the animations we just queued to be first in line (after "inprogress")
14528
	if ( queuelen > 1) {
14529
		queue.splice.apply( queue,
14530
			[ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
14531
	}
14532
	el.dequeue();
14533
14534
};
14535
14536
})(jQuery);
14537
(function( $, undefined ) {
0 ignored issues
show
Unused Code introduced by
The parameter undefined is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
14538
14539
$.effects.effect.slide = function( o, done ) {
14540
14541
	// Create element
14542
	var el = $( this ),
14543
		props = [ "position", "top", "bottom", "left", "right", "width", "height" ],
14544
		mode = $.effects.setMode( el, o.mode || "show" ),
14545
		show = mode === "show",
14546
		direction = o.direction || "left",
14547
		ref = (direction === "up" || direction === "down") ? "top" : "left",
14548
		positiveMotion = (direction === "up" || direction === "left"),
14549
		distance,
14550
		animation = {};
14551
14552
	// Adjust
14553
	$.effects.save( el, props );
14554
	el.show();
14555
	distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true );
14556
14557
	$.effects.createWrapper( el ).css({
14558
		overflow: "hidden"
14559
	});
14560
14561
	if ( show ) {
14562
		el.css( ref, positiveMotion ? (isNaN(distance) ? "-" + distance : -distance) : distance );
14563
	}
14564
14565
	// Animation
14566
	animation[ ref ] = ( show ?
14567
		( positiveMotion ? "+=" : "-=") :
14568
		( positiveMotion ? "-=" : "+=")) +
14569
		distance;
14570
14571
	// Animate
14572
	el.animate( animation, {
14573
		queue: false,
14574
		duration: o.duration,
14575
		easing: o.easing,
14576
		complete: function() {
14577
			if ( mode === "hide" ) {
14578
				el.hide();
14579
			}
14580
			$.effects.restore( el, props );
14581
			$.effects.removeWrapper( el );
14582
			done();
14583
		}
14584
	});
14585
};
14586
14587
})(jQuery);
14588
(function( $, undefined ) {
0 ignored issues
show
Unused Code introduced by
The parameter undefined is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
14589
14590
$.effects.effect.transfer = function( o, done ) {
14591
	var elem = $( this ),
14592
		target = $( o.to ),
14593
		targetFixed = target.css( "position" ) === "fixed",
14594
		body = $("body"),
14595
		fixTop = targetFixed ? body.scrollTop() : 0,
14596
		fixLeft = targetFixed ? body.scrollLeft() : 0,
14597
		endPosition = target.offset(),
14598
		animation = {
14599
			top: endPosition.top - fixTop ,
14600
			left: endPosition.left - fixLeft ,
14601
			height: target.innerHeight(),
14602
			width: target.innerWidth()
14603
		},
14604
		startPosition = elem.offset(),
14605
		transfer = $( "<div class='ui-effects-transfer'></div>" )
14606
			.appendTo( document.body )
14607
			.addClass( o.className )
14608
			.css({
14609
				top: startPosition.top - fixTop ,
14610
				left: startPosition.left - fixLeft ,
14611
				height: elem.innerHeight(),
14612
				width: elem.innerWidth(),
14613
				position: targetFixed ? "fixed" : "absolute"
14614
			})
14615
			.animate( animation, o.duration, o.easing, function() {
14616
				transfer.remove();
14617
				done();
14618
			});
14619
};
14620
14621
})(jQuery);
14622