semantic-ui-dropdown
Advanced tools
Comparing version
{ | ||
"name": "semantic-ui-dropdown", | ||
"description": "Dropdown - Semantic UI", | ||
"homepage": "http://beta.semantic-ui.com", | ||
"homepage": "http://www.semantic-ui.com", | ||
"author": { | ||
@@ -9,9 +9,22 @@ "name": "Jack Lukic", | ||
}, | ||
"ignore": ["docs", "node", "server", "spec", "src", "test"], | ||
"keywords": ["semantic", "ui", "css3", "framework"], | ||
"license": ["http://semantic-ui.mit-license.org/"], | ||
"main": ["dropdown.js", "dropdown.css"], | ||
"dependencies": { | ||
"jquery": ">=1.8" | ||
} | ||
"ignore": [ | ||
"docs", | ||
"node", | ||
"server", | ||
"spec", | ||
"src", | ||
"test" | ||
], | ||
"keywords": [ | ||
"semantic", | ||
"ui", | ||
"css3", | ||
"framework" | ||
], | ||
"license": [ | ||
"http://semantic-ui.mit-license.org/" | ||
], | ||
"main": [ | ||
"dropdown.css" | ||
] | ||
} |
@@ -11,9 +11,10 @@ { | ||
}], | ||
"keywords": ["semantic", "ui", "css", "framework"], | ||
"keywords": [ | ||
"semantic", | ||
"ui", | ||
"css", | ||
"framework" | ||
], | ||
"license": "MIT", | ||
"dependencies": { | ||
"jquery": "x.x.x" | ||
}, | ||
"main": "dropdown.js", | ||
"version": "1.0.0" | ||
"version": "1.9.0" | ||
} |
964
dropdown.js
@@ -54,3 +54,3 @@ /* | ||
$combo = ($module.prev().find(selector.text).size() > 0) | ||
$combo = ($module.prev().find(selector.text).length > 0) | ||
? $module.prev().find(selector.text) | ||
@@ -64,5 +64,7 @@ : $module.prev(), | ||
itemActivated = false, | ||
element = this, | ||
instance = $module.data(moduleNamespace), | ||
elementNamespace, | ||
id, | ||
observer, | ||
@@ -76,6 +78,15 @@ module | ||
module.debug('Initializing dropdown', settings); | ||
module.setup.layout(); | ||
if( module.is.alreadySetup() ) { | ||
module.error(error.alreadySetup); | ||
} | ||
else { | ||
module.setup.layout(); | ||
} | ||
module.save.defaults(); | ||
module.set.selected(); | ||
module.create.id(); | ||
if(hasTouch) { | ||
@@ -101,2 +112,3 @@ module.bind.touchEvents(); | ||
module.verbose('Destroying previous dropdown for', $module); | ||
module.remove.tabbable(); | ||
$module | ||
@@ -106,9 +118,21 @@ .off(eventNamespace) | ||
; | ||
$menu | ||
.off(eventNamespace) | ||
; | ||
$document | ||
.off(elementNamespace) | ||
; | ||
}, | ||
observeChanges: function() { | ||
if(MutationObserver !== undefined) { | ||
if('MutationObserver' in window) { | ||
observer = new MutationObserver(function(mutations) { | ||
module.debug('DOM tree modified, updating selector cache'); | ||
module.refresh(); | ||
if( module.is.selectMutation(mutations) ) { | ||
module.debug('<select> modified, recreating menu'); | ||
module.setup.select(); | ||
} | ||
else { | ||
module.debug('DOM tree modified, updating selector cache'); | ||
module.refresh(); | ||
} | ||
}); | ||
@@ -123,2 +147,23 @@ observer.observe(element, { | ||
create: { | ||
id: function() { | ||
module.verbose('Creating unique id for element'); | ||
id = module.get.uniqueID(); | ||
elementNamespace = '.' + id; | ||
} | ||
}, | ||
search: function() { | ||
var | ||
query | ||
; | ||
query = $search.val(); | ||
module.verbose('Searching for query', query); | ||
module.filter(query); | ||
if(module.is.searchSelection() && module.can.show() ) { | ||
module.show(); | ||
} | ||
}, | ||
setup: { | ||
@@ -137,23 +182,3 @@ | ||
if(settings.allowTab) { | ||
if( module.is.searchable() ) { | ||
module.debug('Searchable dropdown initialized'); | ||
$search | ||
.val('') | ||
.attr('tabindex', 0) | ||
; | ||
$menu | ||
.attr('tabindex', '-1') | ||
; | ||
} | ||
else { | ||
module.debug('Simple selection dropdown initialized'); | ||
if(!$module.attr('tabindex') ) { | ||
$module | ||
.attr('tabindex', 0) | ||
; | ||
$menu | ||
.attr('tabindex', '-1') | ||
; | ||
} | ||
} | ||
module.set.tabbable(); | ||
} | ||
@@ -163,20 +188,23 @@ }, | ||
var | ||
selectValues = module.get.selectValues() | ||
selectValues = module.get.selectValues() | ||
; | ||
module.debug('Dropdown initialized on a select', selectValues); | ||
// see if select exists inside a dropdown | ||
$input = $module; | ||
if($input.parents(selector.dropdown).size() > 0) { | ||
module.debug('Creating dropdown menu only from template'); | ||
if( $module.is('select') ) { | ||
$input = $module; | ||
} | ||
// see if select is placed correctly already | ||
if($input.parent(selector.dropdown).length > 0) { | ||
module.debug('UI dropdown already exists. Creating dropdown menu only'); | ||
$module = $input.closest(selector.dropdown); | ||
if($module.find('.' + className.dropdown).size() === 0) { | ||
$('<div />') | ||
$menu = $module.children(selector.menu); | ||
if($menu.length === 0) { | ||
$menu = $('<div />') | ||
.addClass(className.menu) | ||
.html( settings.templates.menu( selectValues )) | ||
.appendTo($module) | ||
; | ||
} | ||
$menu.html( settings.templates.menu( selectValues )); | ||
} | ||
else { | ||
module.debug('Creating entire dropdown from template'); | ||
module.debug('Creating entire dropdown from select'); | ||
$module = $('<div />') | ||
@@ -199,5 +227,10 @@ .attr('class', $input.attr('class') ) | ||
refresh: function() { | ||
module.verbose('Refreshing selector cache'); | ||
$text = $module.find(selector.text); | ||
$search = $module.find(selector.search); | ||
$input = $module.find(selector.input); | ||
$combo = ($module.prev().find(selector.text).length > 0) | ||
? $module.prev().find(selector.text) | ||
: $module.prev() | ||
; | ||
$menu = $module.children(selector.menu); | ||
@@ -217,5 +250,12 @@ $item = $menu.find(selector.item); | ||
show: function() { | ||
module.debug('Checking if dropdown can show'); | ||
if( !module.is.active() ) { | ||
show: function(callback) { | ||
callback = $.isFunction(callback) | ||
? callback | ||
: function(){} | ||
; | ||
if( module.is.searchSelection() && module.is.allFiltered() ) { | ||
return; | ||
} | ||
if( module.can.show() && !module.is.active() ) { | ||
module.debug('Showing dropdown'); | ||
module.animate.show(function() { | ||
@@ -226,15 +266,20 @@ if( module.can.click() ) { | ||
module.set.visible(); | ||
callback.call(element); | ||
}); | ||
$.proxy(settings.onShow, element)(); | ||
settings.onShow.call(element); | ||
} | ||
}, | ||
hide: function() { | ||
hide: function(callback) { | ||
callback = $.isFunction(callback) | ||
? callback | ||
: function(){} | ||
; | ||
if( module.is.active() ) { | ||
module.debug('Hiding dropdown'); | ||
module.animate.hide(function() { | ||
module.remove.filteredItem(); | ||
module.remove.visible(); | ||
callback.call(element); | ||
}); | ||
$.proxy(settings.onHide, element)(); | ||
settings.onHide.call(element); | ||
} | ||
@@ -254,10 +299,5 @@ }, | ||
var | ||
$subMenus = $menu.find(selector.menu), | ||
$activeSubMenu = $subMenus.has(selector.item + '.' + className.active) | ||
$subMenus = $menu.find(selector.menu) | ||
; | ||
$subMenus | ||
.not($activeSubMenu) | ||
.removeClass(className.visible) | ||
.removeAttr('style') | ||
; | ||
$subMenus.transition('hide'); | ||
}, | ||
@@ -278,4 +318,7 @@ | ||
touchEvents: function() { | ||
module.debug('Touch device detected binding touch events'); | ||
if( !module.is.searchSelection() ) { | ||
module.debug('Touch device detected binding additional touch events'); | ||
if( module.is.searchSelection() ) { | ||
// do nothing special yet | ||
} | ||
else { | ||
$module | ||
@@ -285,5 +328,4 @@ .on('touchstart' + eventNamespace, module.event.test.toggle) | ||
} | ||
$module | ||
$menu | ||
.on('touchstart' + eventNamespace, selector.item, module.event.item.mouseenter) | ||
.on('touchstart' + eventNamespace, selector.item, module.event.item.click) | ||
; | ||
@@ -295,4 +337,8 @@ }, | ||
$module | ||
.on('focus' + eventNamespace, selector.search, module.event.searchFocus) | ||
.on('blur' + eventNamespace, selector.search, module.event.searchBlur) | ||
.on('mousedown' + eventNamespace, selector.menu, module.event.menu.activate) | ||
.on('mouseup' + eventNamespace, selector.menu, module.event.menu.deactivate) | ||
.on('click' + eventNamespace, selector.search, module.show) | ||
.on('focus' + eventNamespace, selector.search, module.event.searchFocus) | ||
.on('blur' + eventNamespace, selector.search, module.event.searchBlur) | ||
.on('click' + eventNamespace, selector.text, module.event.searchTextFocus) | ||
; | ||
@@ -318,11 +364,9 @@ } | ||
$module | ||
.on('mousedown', module.event.mousedown) | ||
.on('mouseup', module.event.mouseup) | ||
.on('focus' + eventNamespace, module.event.focus) | ||
.on('blur' + eventNamespace, module.event.blur) | ||
.on('mousedown' + eventNamespace, module.event.mousedown) | ||
.on('mouseup' + eventNamespace, module.event.mouseup) | ||
.on('focus' + eventNamespace, module.event.focus) | ||
.on('blur' + eventNamespace, module.event.blur) | ||
; | ||
} | ||
$module | ||
.on('mousedown' + eventNamespace, selector.item, module.event.item.mousedown) | ||
.on('mouseup' + eventNamespace, selector.item, module.event.item.mouseup) | ||
$menu | ||
.on('mouseenter' + eventNamespace, selector.item, module.event.item.mouseenter) | ||
@@ -337,8 +381,8 @@ .on('mouseleave' + eventNamespace, selector.item, module.event.item.mouseleave) | ||
$document | ||
.on('touchstart' + eventNamespace, module.event.test.touch) | ||
.on('touchmove' + eventNamespace, module.event.test.touch) | ||
.on('touchstart' + elementNamespace, module.event.test.touch) | ||
.on('touchmove' + elementNamespace, module.event.test.touch) | ||
; | ||
} | ||
$document | ||
.on('click' + eventNamespace, module.event.test.hide) | ||
.on('click' + elementNamespace, module.event.test.hide) | ||
; | ||
@@ -353,8 +397,8 @@ } | ||
$document | ||
.off('touchstart' + eventNamespace) | ||
.off('touchmove' + eventNamespace) | ||
.off('touchstart' + elementNamespace) | ||
.off('touchmove' + elementNamespace) | ||
; | ||
} | ||
$document | ||
.off('click' + eventNamespace) | ||
.off('click' + elementNamespace) | ||
; | ||
@@ -367,6 +411,8 @@ } | ||
$results = $(), | ||
exactRegExp = new RegExp('(?:\s|^)' + searchTerm, 'i'), | ||
fullTextRegExp = new RegExp(searchTerm, 'i'), | ||
$filteredItems | ||
escapedTerm = module.escape.regExp(searchTerm), | ||
exactRegExp = new RegExp('^' + escapedTerm, 'igm'), | ||
fullTextRegExp = new RegExp(escapedTerm, 'ig'), | ||
allItemsFiltered | ||
; | ||
module.verbose('Searching for matching values'); | ||
$item | ||
@@ -376,18 +422,10 @@ .each(function(){ | ||
$choice = $(this), | ||
text = ( $choice.data(metadata.text) !== undefined ) | ||
? $choice.data(metadata.text) | ||
: (settings.preserveHTML) | ||
? $choice.html() | ||
: $choice.text(), | ||
value = ( $choice.data(metadata.value) !== undefined) | ||
? $choice.data(metadata.value) | ||
: (typeof text === 'string') | ||
? text.toLowerCase() | ||
: text | ||
text = String(module.get.choiceText($choice, false)), | ||
value = String(module.get.choiceValue($choice, text)) | ||
; | ||
if( exactRegExp.test( text ) || exactRegExp.test( value ) ) { | ||
if( text.match(exactRegExp) || value.match(exactRegExp) ) { | ||
$results = $results.add($choice); | ||
} | ||
else if(settings.fullTextSearch) { | ||
if( fullTextRegExp.test( text ) || fullTextRegExp.test( value ) ) { | ||
if( text.match(fullTextRegExp) || value.match(fullTextRegExp) ) { | ||
$results = $results.add($choice); | ||
@@ -398,8 +436,12 @@ } | ||
; | ||
$filteredItems = $item.not($results); | ||
module.debug('Setting filter', searchTerm); | ||
module.remove.filteredItem(); | ||
module.remove.selectedItem(); | ||
$filteredItems | ||
$item | ||
.not($results) | ||
.addClass(className.filtered) | ||
; | ||
module.verbose('Selecting first non-filtered element'); | ||
module.remove.selectedItem(); | ||
$item | ||
@@ -410,4 +452,33 @@ .not('.' + className.filtered) | ||
; | ||
if( module.is.allFiltered() ) { | ||
module.debug('All items filtered, hiding dropdown', searchTerm); | ||
if(module.is.searchSelection()) { | ||
module.hide(); | ||
} | ||
settings.onNoResults.call(element, searchTerm); | ||
} | ||
}, | ||
focusSearch: function() { | ||
if( module.is.search() ) { | ||
$search | ||
.focus() | ||
; | ||
} | ||
}, | ||
forceSelection: function() { | ||
var | ||
$currentlySelected = $item.not(className.filtered).filter('.' + className.selected).eq(0), | ||
$activeItem = $item.filter('.' + className.active).eq(0), | ||
$selectedItem = ($currentlySelected.length > 0) | ||
? $currentlySelected | ||
: $activeItem, | ||
hasSelected = ($selectedItem.size() > 0) | ||
; | ||
if(hasSelected) { | ||
module.event.item.click.call($selectedItem); | ||
} | ||
}, | ||
event: { | ||
@@ -422,3 +493,3 @@ // prevents focus callback from occuring on mousedown | ||
focus: function() { | ||
if(!activated) { | ||
if(!activated && module.is.hidden()) { | ||
module.show(); | ||
@@ -428,3 +499,6 @@ } | ||
blur: function(event) { | ||
if(!activated) { | ||
var | ||
pageLostFocus = (document.activeElement === this) | ||
; | ||
if(!activated && !pageLostFocus) { | ||
module.hide(); | ||
@@ -438,69 +512,114 @@ } | ||
searchBlur: function(event) { | ||
if(!itemActivated) { | ||
module.hide(); | ||
var | ||
pageLostFocus = (document.activeElement === this) | ||
; | ||
if(!itemActivated && !pageLostFocus) { | ||
if(settings.forceSelection) { | ||
module.forceSelection(); | ||
} | ||
else { | ||
module.hide(); | ||
} | ||
} | ||
}, | ||
searchTextFocus: function(event) { | ||
activated = true; | ||
$search.focus(); | ||
}, | ||
input: function(event) { | ||
var | ||
query = $search.val() | ||
; | ||
if(module.is.searchSelection()) { | ||
$text.addClass(className.filtered); | ||
module.set.filtered(); | ||
} | ||
module.filter(query); | ||
clearTimeout(module.timer); | ||
module.timer = setTimeout(module.search, settings.delay.search); | ||
}, | ||
keydown: function(event) { | ||
var | ||
$selectedItem = $item.not(className.filtered).filter('.' + className.selected).eq(0), | ||
$visibleItems = $item.not('.' + className.filtered), | ||
$currentlySelected = $item.not(className.filtered).filter('.' + className.selected).eq(0), | ||
$activeItem = $menu.children('.' + className.active).eq(0), | ||
$selectedItem = ($currentlySelected.length > 0) | ||
? $currentlySelected | ||
: $activeItem, | ||
$visibleItems = ($selectedItem.length > 0) | ||
? $selectedItem.siblings(':not(.' + className.filtered +')').andSelf() | ||
: $menu.children(':not(.' + className.filtered +')'), | ||
$subMenu = $selectedItem.children(selector.menu), | ||
$parentMenu = $selectedItem.closest(selector.menu), | ||
isSubMenuItem = $parentMenu[0] !== $menu[0], | ||
inVisibleMenu = $parentMenu.is(':visible'), | ||
pressedKey = event.which, | ||
keys = { | ||
enter : 13, | ||
escape : 27, | ||
upArrow : 38, | ||
downArrow : 40 | ||
enter : 13, | ||
escape : 27, | ||
leftArrow : 37, | ||
upArrow : 38, | ||
rightArrow : 39, | ||
downArrow : 40 | ||
}, | ||
selectedClass = className.selected, | ||
currentIndex = $visibleItems.index( $selectedItem ), | ||
hasSelectedItem = ($selectedItem.size() > 0), | ||
hasSubMenu = ($subMenu.length> 0), | ||
hasSelectedItem = ($selectedItem.length > 0), | ||
lastVisibleIndex = ($visibleItems.size() - 1), | ||
$nextItem, | ||
newIndex | ||
; | ||
// default to activated choice if no selection present | ||
if(!hasSelectedItem) { | ||
$selectedItem = $item.filter('.' + className.active).eq(0); | ||
hasSelectedItem = ($selectedItem.size() > 0); | ||
} | ||
// close shortcuts | ||
if(pressedKey == keys.escape) { | ||
module.verbose('Escape key pressed, closing dropdown'); | ||
$search.blur(); | ||
module.hide(); | ||
} | ||
// result shortcuts | ||
// visible menu keyboard shortcuts | ||
if(module.is.visible()) { | ||
// enter (select or sub-menu) | ||
if(pressedKey == keys.enter && hasSelectedItem) { | ||
module.verbose('Enter key pressed, choosing selected item'); | ||
if(module.is.searchable()) { | ||
module.verbose('Removing focus from search input'); | ||
$search.blur(); | ||
if(hasSubMenu && !settings.allowCategorySelection) { | ||
module.verbose('Pressed enter on unselectable category, opening sub menu'); | ||
pressedKey = keys.rightArrow; | ||
} | ||
$.proxy(module.event.item.click, $selectedItem)(event); | ||
else { | ||
module.verbose('Enter key pressed, choosing selected item'); | ||
module.event.item.click.call($selectedItem, event); | ||
} | ||
} | ||
// left arrow (hide sub-menu) | ||
if(pressedKey == keys.leftArrow) { | ||
if(isSubMenuItem) { | ||
module.verbose('Left key pressed, closing sub-menu'); | ||
module.animate.hide(false, $parentMenu); | ||
$selectedItem | ||
.removeClass(className.selected) | ||
; | ||
$parentMenu | ||
.closest(selector.item) | ||
.addClass(className.selected) | ||
; | ||
} | ||
event.preventDefault(); | ||
return false; | ||
} | ||
else if(pressedKey == keys.upArrow) { | ||
if(!hasSelectedItem) { | ||
$nextItem = $visibleItems.eq(0); | ||
// right arrow (show sub-menu) | ||
if(pressedKey == keys.rightArrow) { | ||
if(hasSubMenu) { | ||
module.verbose('Right key pressed, opening sub-menu'); | ||
module.animate.show(false, $subMenu); | ||
$selectedItem | ||
.removeClass(className.selected) | ||
; | ||
$subMenu | ||
.find(selector.item).eq(0) | ||
.addClass(className.selected) | ||
; | ||
} | ||
event.preventDefault(); | ||
} | ||
// up arrow (traverse menu up) | ||
if(pressedKey == keys.upArrow) { | ||
$nextItem = (hasSelectedItem && inVisibleMenu) | ||
? $selectedItem.prevAll(selector.item + ':not(.' + className.filtered + ')').eq(0) | ||
: $item.eq(0) | ||
; | ||
if($visibleItems.index( $nextItem ) < 0) { | ||
module.verbose('Up key pressed but reached top of current menu'); | ||
return; | ||
} | ||
else { | ||
$nextItem = $selectedItem.prevAll(selector.item + ':not(.' + className.filtered + ')').eq(0); | ||
} | ||
if(currentIndex !== 0) { | ||
module.verbose('Up key pressed, changing active item'); | ||
$item | ||
.removeClass(selectedClass) | ||
$selectedItem | ||
.removeClass(className.selected) | ||
; | ||
$nextItem | ||
.addClass(selectedClass) | ||
.addClass(className.selected) | ||
; | ||
@@ -511,16 +630,19 @@ module.set.scrollPosition($nextItem); | ||
} | ||
else if(pressedKey == keys.downArrow) { | ||
if(!hasSelectedItem) { | ||
$nextItem = $visibleItems.eq(0); | ||
// down arrow (traverse menu down) | ||
if(pressedKey == keys.downArrow) { | ||
$nextItem = (hasSelectedItem && inVisibleMenu) | ||
? $nextItem = $selectedItem.nextAll(selector.item + ':not(.' + className.filtered + ')').eq(0) | ||
: $item.eq(0) | ||
; | ||
if($nextItem.length === 0) { | ||
module.verbose('Down key pressed but reached bottom of current menu'); | ||
return; | ||
} | ||
else { | ||
$nextItem = $selectedItem.nextAll(selector.item + ':not(.' + className.filtered + ')').eq(0); | ||
} | ||
if(currentIndex + 1 < $visibleItems.size() ) { | ||
module.verbose('Down key pressed, changing active item'); | ||
$item | ||
.removeClass(selectedClass) | ||
.removeClass(className.selected) | ||
; | ||
$nextItem | ||
.addClass(selectedClass) | ||
.addClass(className.selected) | ||
; | ||
@@ -533,5 +655,17 @@ module.set.scrollPosition($nextItem); | ||
else { | ||
// enter (open menu) | ||
if(pressedKey == keys.enter) { | ||
module.verbose('Enter key pressed, showing dropdown'); | ||
module.show(); | ||
} | ||
// escape (close menu) | ||
if(pressedKey == keys.escape) { | ||
module.verbose('Escape key pressed, closing dropdown'); | ||
module.hide(); | ||
} | ||
// down arrow (open menu) | ||
if(pressedKey == keys.downArrow) { | ||
module.verbose('Down key pressed, showing dropdown'); | ||
module.show(); | ||
} | ||
} | ||
@@ -561,75 +695,64 @@ }, | ||
item: { | ||
mousedown: function() { | ||
menu: { | ||
activate: function() { | ||
itemActivated = true; | ||
}, | ||
mouseup: function() { | ||
deactivate: function() { | ||
itemActivated = false; | ||
}, | ||
} | ||
}, | ||
item: { | ||
mouseenter: function(event) { | ||
var | ||
$currentMenu = $(this).find(selector.menu), | ||
$otherMenus = $(this).siblings(selector.item).children(selector.menu) | ||
$subMenu = $(this).children(selector.menu), | ||
$otherMenus = $(this).siblings(selector.item).children(selector.menu) | ||
; | ||
if( $currentMenu.size() > 0 ) { | ||
if( $subMenu.length > 0 ) { | ||
clearTimeout(module.itemTimer); | ||
module.itemTimer = setTimeout(function() { | ||
module.animate.hide(false, $otherMenus); | ||
module.verbose('Showing sub-menu', $currentMenu); | ||
module.animate.show(false, $currentMenu); | ||
}, settings.delay.show * 2); | ||
module.verbose('Showing sub-menu', $subMenu); | ||
$.each($otherMenus, function() { | ||
module.animate.hide(false, $(this)); | ||
}); | ||
module.animate.show(false, $subMenu); | ||
}, settings.delay.show); | ||
event.preventDefault(); | ||
} | ||
}, | ||
mouseleave: function(event) { | ||
var | ||
$currentMenu = $(this).find(selector.menu) | ||
$subMenu = $(this).children(selector.menu) | ||
; | ||
if($currentMenu.size() > 0) { | ||
if($subMenu.length > 0) { | ||
clearTimeout(module.itemTimer); | ||
module.itemTimer = setTimeout(function() { | ||
module.verbose('Hiding sub-menu', $currentMenu); | ||
module.animate.hide(false, $currentMenu); | ||
module.verbose('Hiding sub-menu', $subMenu); | ||
module.animate.hide(false, $subMenu); | ||
}, settings.delay.hide); | ||
} | ||
}, | ||
click: function (event) { | ||
var | ||
$choice = $(this), | ||
text = ( $choice.data(metadata.text) !== undefined ) | ||
? $choice.data(metadata.text) | ||
: (settings.preserveHTML) | ||
? $choice.html() | ||
: $choice.text(), | ||
value = ( $choice.data(metadata.value) !== undefined) | ||
? $choice.data(metadata.value) | ||
: (typeof text === 'string') | ||
? text.toLowerCase() | ||
: text, | ||
$choice = $(this), | ||
$target = (event) | ||
? $(event.target) | ||
: $(''), | ||
$subMenu = $choice.find(selector.menu), | ||
text = module.get.choiceText($choice), | ||
value = module.get.choiceValue($choice, text), | ||
callback = function() { | ||
$search.val(''); | ||
module.remove.searchTerm(); | ||
module.determine.selectAction(text, value); | ||
$.proxy(settings.onChange, element)(value, text, $choice); | ||
}, | ||
openingSubMenu = ($choice.find(selector.menu).size() > 0) | ||
hasSubMenu = ($subMenu.length > 0), | ||
isBubbledEvent = ($subMenu.find($target).length > 0) | ||
; | ||
if( !openingSubMenu ) { | ||
if(event.type == 'touchstart') { | ||
$choice.one('click', callback); | ||
} | ||
else { | ||
callback(); | ||
} | ||
if(!isBubbledEvent && (!hasSubMenu || settings.allowCategorySelection)) { | ||
callback(); | ||
} | ||
} | ||
}, | ||
resetStyle: function() { | ||
$(this).removeAttr('style'); | ||
} | ||
}, | ||
@@ -653,4 +776,7 @@ | ||
eventInModule: function(event, callback) { | ||
callback = callback || function(){}; | ||
if( $(event.target).closest($module).size() === 0 ) { | ||
callback = $.isFunction(callback) | ||
? callback | ||
: function(){} | ||
; | ||
if( $(event.target).closest($module).length === 0 ) { | ||
module.verbose('Triggering event', callback); | ||
@@ -666,4 +792,7 @@ callback(); | ||
eventInMenu: function(event, callback) { | ||
callback = callback || function(){}; | ||
if( $(event.target).closest($menu).size() === 0 ) { | ||
callback = $.isFunction(callback) | ||
? callback | ||
: function(){} | ||
; | ||
if( $(event.target).closest($menu).length === 0 ) { | ||
module.verbose('Triggering event', callback); | ||
@@ -684,7 +813,3 @@ callback(); | ||
hide: function() { | ||
module.hide(); | ||
}, | ||
select: function(text, value) { | ||
activate: function(text, value) { | ||
value = (value !== undefined) | ||
@@ -695,7 +820,8 @@ ? value | ||
module.set.selected(value); | ||
module.set.value(value); | ||
module.hide(); | ||
module.hide(function() { | ||
module.remove.filteredItem(); | ||
}); | ||
}, | ||
activate: function(text, value) { | ||
select: function(text, value) { | ||
value = (value !== undefined) | ||
@@ -706,4 +832,5 @@ ? value | ||
module.set.selected(value); | ||
module.set.value(value); | ||
module.hide(); | ||
module.hide(function() { | ||
module.remove.filteredItem(); | ||
}); | ||
}, | ||
@@ -717,4 +844,11 @@ | ||
module.set.selected(value); | ||
module.set.value(value); | ||
module.hide(); | ||
module.hide(function() { | ||
module.remove.filteredItem(); | ||
}); | ||
}, | ||
hide: function() { | ||
module.hide(function() { | ||
module.remove.filteredItem(); | ||
}); | ||
} | ||
@@ -729,3 +863,3 @@ | ||
value: function() { | ||
return ($input.size() > 0) | ||
return ($input.length > 0) | ||
? $input.val() | ||
@@ -735,2 +869,31 @@ : $module.data(metadata.value) | ||
}, | ||
choiceText: function($choice, preserveHTML) { | ||
preserveHTML = (preserveHTML !== undefined) | ||
? preserveHTML | ||
: settings.preserveHTML | ||
; | ||
if($choice !== undefined) { | ||
if($choice.find(selector.menu).length > 0) { | ||
module.verbose('Retreiving text of element with sub-menu'); | ||
$choice = $choice.clone(); | ||
$choice.find(selector.menu).remove(); | ||
$choice.find(selector.menuIcon).remove(); | ||
} | ||
return ($choice.data(metadata.text) !== undefined) | ||
? $choice.data(metadata.text) | ||
: (preserveHTML) | ||
? $choice.html().trim() | ||
: $choice.text().trim() | ||
; | ||
} | ||
}, | ||
choiceValue: function($choice, choiceText) { | ||
choiceText = choiceText || module.get.choiceText($choice); | ||
return ($choice.data(metadata.value) !== undefined) | ||
? $choice.data(metadata.value) | ||
: (typeof choiceText === 'string') | ||
? choiceText.toLowerCase().trim() | ||
: choiceText.trim() | ||
; | ||
}, | ||
inputEvent: function() { | ||
@@ -752,6 +915,8 @@ var | ||
var | ||
select = { | ||
values : {} | ||
} | ||
select = {} | ||
; | ||
select.values = (settings.sortSelect) | ||
? {} // properties will be sorted in object when re-accessed | ||
: [] // properties will keep original order in array | ||
; | ||
$module | ||
@@ -770,9 +935,28 @@ .find('option') | ||
else { | ||
select.values[value] = name; | ||
if(settings.sortSelect) { | ||
select.values[value] = { | ||
name : name, | ||
value : value | ||
}; | ||
} | ||
else { | ||
select.values.push({ | ||
name: name, | ||
value: value | ||
}); | ||
} | ||
} | ||
}) | ||
; | ||
module.debug('Retrieved values from select', select); | ||
if(settings.sortSelect) { | ||
module.debug('Retrieved and sorted values from select', select); | ||
} | ||
else { | ||
module.debug('Retreived values from select', select); | ||
} | ||
return select; | ||
}, | ||
activeItem: function() { | ||
return $item.filter('.' + className.active); | ||
}, | ||
item: function(value, strict) { | ||
@@ -797,15 +981,7 @@ var | ||
$choice = $(this), | ||
optionText = ( $choice.data(metadata.text) !== undefined ) | ||
? $choice.data(metadata.text) | ||
: (settings.preserveHTML) | ||
? $choice.html() | ||
: $choice.text(), | ||
optionValue = ( $choice.data(metadata.value) !== undefined ) | ||
? $choice.data(metadata.value) | ||
: (typeof optionText === 'string') | ||
? optionText.toLowerCase() | ||
: optionText | ||
optionText = module.get.choiceText($choice), | ||
optionValue = module.get.choiceValue($choice, optionText) | ||
; | ||
if(strict) { | ||
module.debug('Ambiguous dropdown value using strict type check', value); | ||
module.verbose('Ambiguous dropdown value using strict type check', $choice, value); | ||
if( optionValue === value ) { | ||
@@ -835,2 +1011,5 @@ $selectedItem = $(this); | ||
return $selectedItem || false; | ||
}, | ||
uniqueID: function() { | ||
return (Math.random().toString(16) + '000000000').substr(2,8); | ||
} | ||
@@ -850,2 +1029,3 @@ }, | ||
module.set.text(defaultText); | ||
$text.addClass(className.placeholder); | ||
}, | ||
@@ -858,4 +1038,9 @@ defaultValue: function() { | ||
module.debug('Restoring default value', defaultValue); | ||
module.set.selected(defaultValue); | ||
module.set.value(defaultValue); | ||
if(defaultValue.length) { | ||
module.set.selected(defaultValue); | ||
} | ||
else { | ||
module.remove.activeItem(); | ||
module.remove.selectedItem(); | ||
} | ||
} | ||
@@ -868,2 +1053,3 @@ } | ||
module.save.defaultText(); | ||
module.save.placeholderText(); | ||
module.save.defaultValue(); | ||
@@ -876,11 +1062,61 @@ }, | ||
$module.data(metadata.defaultText, $text.text() ); | ||
}, | ||
placeholderText: function() { | ||
if($text.hasClass(className.placeholder)) { | ||
$module.data(metadata.placeholderText, $text.text()); | ||
} | ||
} | ||
}, | ||
clear: function() { | ||
var | ||
placeholderText = $module.data(metadata.placeholderText) | ||
; | ||
module.set.text(placeholderText); | ||
module.set.value(''); | ||
module.remove.activeItem(); | ||
module.remove.selectedItem(); | ||
$text.addClass(className.placeholder); | ||
}, | ||
set: { | ||
scrollPosition: function($item) { | ||
filtered: function() { | ||
var | ||
$item = $item || module.get.item(), | ||
hasActive = ($item && $item.size() > 0), | ||
searchValue = $search.val(), | ||
hasSearchValue = (typeof searchValue === 'string' && searchValue.length > 0) | ||
; | ||
if(hasSearchValue) { | ||
$text.addClass(className.filtered); | ||
} | ||
else { | ||
$text.removeClass(className.filtered); | ||
} | ||
}, | ||
tabbable: function() { | ||
if( module.is.searchable() ) { | ||
module.debug('Searchable dropdown initialized'); | ||
$search | ||
.val('') | ||
.attr('tabindex', 0) | ||
; | ||
$menu | ||
.attr('tabindex', '-1') | ||
; | ||
} | ||
else { | ||
module.debug('Simple selection dropdown initialized'); | ||
if(!$module.attr('tabindex') ) { | ||
$module | ||
.attr('tabindex', 0) | ||
; | ||
$menu | ||
.attr('tabindex', '-1') | ||
; | ||
} | ||
} | ||
}, | ||
scrollPosition: function($item, forceScroll) { | ||
var | ||
edgeTolerance = 5, | ||
hasActive, | ||
offset, | ||
@@ -895,3 +1131,16 @@ itemHeight, | ||
; | ||
$item = $item || module.get.activeItem(); | ||
hasActive = ($item && $item.length > 0); | ||
forceScroll = (forceScroll !== undefined) | ||
? forceScroll | ||
: false | ||
; | ||
if($item && hasActive) { | ||
if(!$menu.hasClass(className.visible)) { | ||
$menu.addClass(className.loading); | ||
} | ||
menuHeight = $menu.height(); | ||
@@ -905,6 +1154,7 @@ itemHeight = $item.height(); | ||
abovePage = ((offset - edgeTolerance) < menuScroll); | ||
if(abovePage || belowPage) { | ||
module.debug('Scrolling to active item'); | ||
module.debug('Scrolling to active item', offset); | ||
if(abovePage || belowPage || forceScroll) { | ||
$menu | ||
.scrollTop(offset) | ||
.removeClass(className.loading) | ||
; | ||
@@ -940,3 +1190,3 @@ } | ||
module.debug('Adding selected value to hidden input', value, $input); | ||
if($input.size() > 0) { | ||
if($input.length > 0) { | ||
$input | ||
@@ -962,12 +1212,7 @@ .val(value) | ||
$selectedItem = module.get.item(value), | ||
selectedText | ||
selectedText, | ||
selectedValue | ||
; | ||
if($selectedItem) { | ||
module.debug('Setting selected menu item to', $selectedItem); | ||
selectedText = ($selectedItem.data(metadata.text) !== undefined) | ||
? $selectedItem.data(metadata.text) | ||
: (settings.preserveHTML) | ||
? $selectedItem.html() | ||
: $selectedItem.text() | ||
; | ||
module.remove.activeItem(); | ||
@@ -979,3 +1224,7 @@ module.remove.selectedItem(); | ||
; | ||
selectedText = module.get.choiceText($selectedItem); | ||
selectedValue = module.get.choiceValue($selectedItem, selectedText); | ||
module.set.text(selectedText); | ||
module.set.value(selectedValue); | ||
settings.onChange.call(element, value, selectedText, $selectedItem); | ||
} | ||
@@ -998,4 +1247,27 @@ } | ||
}, | ||
searchTerm: function() { | ||
$search.val(''); | ||
}, | ||
selectedItem: function() { | ||
$item.removeClass(className.selected); | ||
}, | ||
tabbable: function() { | ||
if( module.is.searchable() ) { | ||
module.debug('Searchable dropdown initialized'); | ||
$search | ||
.attr('tabindex', '-1') | ||
; | ||
$menu | ||
.attr('tabindex', '-1') | ||
; | ||
} | ||
else { | ||
module.debug('Simple selection dropdown initialized'); | ||
$module | ||
.attr('tabindex', '-1') | ||
; | ||
$menu | ||
.attr('tabindex', '-1') | ||
; | ||
} | ||
} | ||
@@ -1005,2 +1277,35 @@ }, | ||
is: { | ||
active: function() { | ||
return $module.hasClass(className.active); | ||
}, | ||
alreadySetup: function() { | ||
return ($module.is('select') && $module.parent(selector.dropdown).length > 0); | ||
}, | ||
animating: function($subMenu) { | ||
return ($subMenu) | ||
? $subMenu.is(':animated') || $subMenu.transition && $subMenu.transition('is animating') | ||
: $menu.is(':animated') || $menu.transition && $menu.transition('is animating') | ||
; | ||
}, | ||
allFiltered: function() { | ||
return ($item.filter('.' + className.filtered).length === $item.length); | ||
}, | ||
hidden: function($subMenu) { | ||
return ($subMenu) | ||
? $subMenu.is(':hidden') | ||
: $menu.is(':hidden') | ||
; | ||
}, | ||
selectMutation: function(mutations) { | ||
var | ||
selectChanged = false | ||
; | ||
$.each(mutations, function(index, mutation) { | ||
if(mutation.target && $(mutation.target).is('select')) { | ||
selectChanged = true; | ||
return true; | ||
} | ||
}); | ||
return selectChanged; | ||
}, | ||
search: function() { | ||
@@ -1010,3 +1315,3 @@ return $module.hasClass(className.search); | ||
searchable: function() { | ||
return ($search.size() > 0); | ||
return ($search.length > 0); | ||
}, | ||
@@ -1019,11 +1324,5 @@ searchSelection: function() { | ||
}, | ||
animated: function($subMenu) { | ||
return ($subMenu) | ||
? $subMenu.is(':animated') || $subMenu.transition && $subMenu.transition('is animating') | ||
: $menu.is(':animated') || $menu.transition && $menu.transition('is animating') | ||
; | ||
upward: function() { | ||
return $module.hasClass(className.upward); | ||
}, | ||
active: function() { | ||
return $module.hasClass(className.active); | ||
}, | ||
visible: function($subMenu) { | ||
@@ -1034,8 +1333,2 @@ return ($subMenu) | ||
; | ||
}, | ||
hidden: function($subMenu) { | ||
return ($subMenu) | ||
? $subMenu.is(':hidden') | ||
: $menu.is(':hidden') | ||
; | ||
} | ||
@@ -1060,12 +1353,24 @@ }, | ||
: function() { | ||
module.hideSubMenus(); | ||
module.hideOthers(); | ||
module.set.active(); | ||
module.set.scrollPosition(); | ||
} | ||
; | ||
callback = callback || function(){}; | ||
callback = $.isFunction(callback) | ||
? callback | ||
: function(){} | ||
; | ||
module.set.scrollPosition(module.get.activeItem(), true); | ||
module.verbose('Doing menu show animation', $currentMenu); | ||
if( module.is.hidden($currentMenu) ) { | ||
if( module.is.hidden($currentMenu) || module.is.animating($currentMenu) ) { | ||
if(settings.transition == 'auto') { | ||
settings.transition = module.is.upward() | ||
? 'slide up' | ||
: 'slide down' | ||
; | ||
module.verbose('Automatically determining animation based on animation direction', settings.transition); | ||
} | ||
if(settings.transition == 'none') { | ||
$.proxy(callback, element)(); | ||
callback.call(element); | ||
} | ||
@@ -1075,8 +1380,10 @@ else if($.fn.transition !== undefined && $module.transition('is supported')) { | ||
.transition({ | ||
animation : settings.transition + ' in', | ||
duration : settings.duration, | ||
queue : true, | ||
start : start, | ||
complete : function() { | ||
$.proxy(callback, element)(); | ||
animation : settings.transition + ' in', | ||
debug : settings.debug, | ||
verbose : settings.verbose, | ||
duration : settings.duration, | ||
queue : true, | ||
onStart : start, | ||
onComplete : function() { | ||
callback.call(element); | ||
} | ||
@@ -1100,4 +1407,4 @@ }) | ||
.slideDown(100, 'easeOutQuad', function() { | ||
$.proxy(module.event.resetStyle, this)(); | ||
$.proxy(callback, element)(); | ||
module.event.resetStyle.call(this); | ||
callback.call(element); | ||
}) | ||
@@ -1112,4 +1419,4 @@ ; | ||
.fadeIn(settings.duration, function() { | ||
$.proxy(module.event.resetStyle, this)(); | ||
$.proxy(callback, element)(); | ||
module.event.resetStyle.call(this); | ||
callback.call(element); | ||
}) | ||
@@ -1126,2 +1433,5 @@ ; | ||
$currentMenu = $subMenu || $menu, | ||
duration = ($subMenu) | ||
? (settings.duration * 0.9) | ||
: settings.duration, | ||
start = ($subMenu) | ||
@@ -1133,12 +1443,24 @@ ? function() {} | ||
} | ||
module.hideSubMenus(); | ||
module.focusSearch(); | ||
module.remove.active(); | ||
} | ||
; | ||
callback = callback || function(){}; | ||
if( module.is.visible($currentMenu) ) { | ||
callback = $.isFunction(callback) | ||
? callback | ||
: function(){} | ||
; | ||
if( module.is.visible($currentMenu) || module.is.animating($currentMenu) ) { | ||
module.verbose('Doing menu hide animation', $currentMenu); | ||
if(settings.transition == 'auto') { | ||
settings.transition = module.is.upward() | ||
? 'slide up' | ||
: 'slide down' | ||
; | ||
} | ||
$input.trigger('blur'); | ||
if(settings.transition == 'none') { | ||
$.proxy(callback, element)(); | ||
callback.call(element); | ||
} | ||
@@ -1148,8 +1470,10 @@ else if($.fn.transition !== undefined && $module.transition('is supported')) { | ||
.transition({ | ||
animation : settings.transition + ' out', | ||
duration : settings.duration, | ||
queue : true, | ||
start : start, | ||
complete : function() { | ||
$.proxy(callback, element)(); | ||
animation : settings.transition + ' out', | ||
duration : settings.duration, | ||
debug : settings.debug, | ||
verbose : settings.verbose, | ||
queue : true, | ||
onStart : start, | ||
onComplete : function() { | ||
callback.call(element); | ||
} | ||
@@ -1173,4 +1497,4 @@ }) | ||
.slideUp(100, 'easeOutQuad', function() { | ||
$.proxy(module.event.resetStyle, this)(); | ||
$.proxy(callback, element)(); | ||
module.event.resetStyle.call(this); | ||
callback.call(element); | ||
}) | ||
@@ -1185,4 +1509,4 @@ ; | ||
.fadeOut(150, function() { | ||
$.proxy(module.event.resetStyle, this)(); | ||
$.proxy(callback, element)(); | ||
module.event.resetStyle.call(this); | ||
callback.call(element); | ||
}) | ||
@@ -1211,2 +1535,9 @@ ; | ||
escape: { | ||
regExp: function(text) { | ||
text = String(text); | ||
return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); | ||
} | ||
}, | ||
setting: function(name, value) { | ||
@@ -1376,3 +1707,3 @@ module.debug('Changing setting', name, value); | ||
if(instance !== undefined) { | ||
module.destroy(); | ||
instance.invoke('destroy'); | ||
} | ||
@@ -1392,28 +1723,34 @@ module.initialize(); | ||
debug : false, | ||
verbose : true, | ||
performance : true, | ||
debug : false, | ||
verbose : true, | ||
performance : true, | ||
on : 'click', | ||
action : 'activate', | ||
on : 'click', | ||
action : 'activate', | ||
allowTab : true, | ||
fullTextSearch : true, | ||
preserveHTML : true, | ||
allowTab : true, | ||
fullTextSearch : false, | ||
preserveHTML : true, | ||
sortSelect : false, | ||
delay : { | ||
show : 200, | ||
hide : 300, | ||
touch : 50 | ||
allowCategorySelection : false, | ||
delay : { | ||
hide : 300, | ||
show : 200, | ||
search : 50, | ||
touch : 50 | ||
}, | ||
transition : 'slide down', | ||
forceSelection: true, | ||
transition : 'auto', | ||
duration : 250, | ||
/* Callbacks */ | ||
onNoResults : function(searchTerm){}, | ||
onChange : function(value, text){}, | ||
onShow : function(){}, | ||
onHide : function(){}, | ||
onChange : function(value, text){}, | ||
onShow : function(){}, | ||
onHide : function(){}, | ||
/* Component */ | ||
@@ -1425,12 +1762,14 @@ | ||
error : { | ||
action : 'You called a dropdown action that was not defined', | ||
method : 'The method you called is not defined.', | ||
transition : 'The requested transition was not found' | ||
action : 'You called a dropdown action that was not defined', | ||
alreadySetup : 'Once a select has been initialized behaviors must be called on the created ui dropdown', | ||
method : 'The method you called is not defined.', | ||
transition : 'The requested transition was not found' | ||
}, | ||
metadata: { | ||
defaultText : 'defaultText', | ||
defaultValue : 'defaultValue', | ||
text : 'text', | ||
value : 'value' | ||
defaultText : 'defaultText', | ||
defaultValue : 'defaultValue', | ||
placeholderText : 'placeholderText', | ||
text : 'text', | ||
value : 'value' | ||
}, | ||
@@ -1440,7 +1779,8 @@ | ||
dropdown : '.ui.dropdown', | ||
text : '> .text:not(.icon)', | ||
input : '> input[type="hidden"], > select', | ||
search : '> .search, .menu > .search > input, .menu > input.search', | ||
item : '.item', | ||
menu : '.menu', | ||
item : '.item' | ||
menuIcon : '.dropdown.icon', | ||
search : '> input.search, .menu > .search > input, .menu > input.search', | ||
text : '> .text:not(.icon)' | ||
}, | ||
@@ -1454,2 +1794,3 @@ | ||
filtered : 'filtered', | ||
loading : 'loading', | ||
menu : 'menu', | ||
@@ -1460,2 +1801,3 @@ placeholder : 'default', | ||
selection : 'selection', | ||
upward : 'upward', | ||
visible : 'visible' | ||
@@ -1474,9 +1816,4 @@ } | ||
; | ||
$.each(select.values, function(value, name) { | ||
if(value === name) { | ||
html += '<div class="item">' + name + '</div>'; | ||
} | ||
else { | ||
html += '<div class="item" data-value="' + value + '">' + name + '</div>'; | ||
} | ||
$.each(select.values, function(index, option) { | ||
html += '<div class="item" data-value="' + option.value + '">' + option.name + '</div>'; | ||
}); | ||
@@ -1499,9 +1836,4 @@ return html; | ||
html += '<div class="menu">'; | ||
$.each(select.values, function(value, name) { | ||
if(value === name) { | ||
html += '<div class="item">' + name + '</div>'; | ||
} | ||
else { | ||
html += '<div class="item" data-value="' + value + '">' + name + '</div>'; | ||
} | ||
$.each(select.values, function(index, option) { | ||
html += '<div class="item" data-value="' + option.value + '">' + option.name + '</div>'; | ||
}); | ||
@@ -1522,2 +1854,2 @@ html += '</div>'; | ||
})( jQuery, window , document ); | ||
})( jQuery, window , document ); |
/* | ||
* # Semantic UI | ||
* # Semantic UI - 1.9.0 | ||
* https://github.com/Semantic-Org/Semantic-UI | ||
* http://beta.semantic-ui.com/ | ||
* http://www.semantic-ui.com/ | ||
* | ||
@@ -11,2 +11,2 @@ * Copyright 2014 Contributors | ||
*/ | ||
!function(e,t,n,i){"use strict";e.fn.dropdown=function(t){var o,s=e(this),a=e(n),r=s.selector||"",u="ontouchstart"in n.documentElement,c=(new Date).getTime(),d=[],l=arguments[0],v="string"==typeof l,f=[].slice.call(arguments,1);return s.each(function(){var n,m,h=e.isPlainObject(t)?e.extend(!0,{},e.fn.dropdown.settings,t):e.extend({},e.fn.dropdown.settings),p=h.className,g=h.metadata,b=h.namespace,w=h.selector,y=h.error,x="."+b,T="module-"+b,C=e(this),k=C.find(w.text),S=C.find(w.search),z=C.find(w.input),E=C.prev().find(w.text).size()>0?C.prev().find(w.text):C.prev(),D=C.children(w.menu),M=D.find(w.item),A=!1,O=!1,I=this,Q=C.data(T);m={initialize:function(){m.debug("Initializing dropdown",h),m.setup.layout(),m.save.defaults(),m.set.selected(),u&&m.bind.touchEvents(),m.bind.mouseEvents(),m.bind.keyboardEvents(),m.observeChanges(),m.instantiate()},instantiate:function(){m.verbose("Storing instance of dropdown",m),Q=m,C.data(T,m)},destroy:function(){m.verbose("Destroying previous dropdown for",C),C.off(x).removeData(T)},observeChanges:function(){MutationObserver!==i&&(n=new MutationObserver(function(){m.debug("DOM tree modified, updating selector cache"),m.refresh()}),n.observe(I,{childList:!0,subtree:!0}),m.debug("Setting up mutation observer",n))},setup:{layout:function(){C.is("select")&&m.setup.select(),m.is.search()&&!m.is.searchable()&&(S=e("<input />").addClass(p.search).insertBefore(k)),h.allowTab&&(m.is.searchable()?(m.debug("Searchable dropdown initialized"),S.val("").attr("tabindex",0),D.attr("tabindex","-1")):(m.debug("Simple selection dropdown initialized"),C.attr("tabindex")||(C.attr("tabindex",0),D.attr("tabindex","-1"))))},select:function(){var t=m.get.selectValues();m.debug("Dropdown initialized on a select",t),z=C,z.parents(w.dropdown).size()>0?(m.debug("Creating dropdown menu only from template"),C=z.closest(w.dropdown),0===C.find("."+p.dropdown).size()&&e("<div />").addClass(p.menu).html(h.templates.menu(t)).appendTo(C)):(m.debug("Creating entire dropdown from template"),C=e("<div />").attr("class",z.attr("class")).addClass(p.selection).addClass(p.dropdown).html(h.templates.dropdown(t)).insertBefore(z),z.removeAttr("class").prependTo(C)),m.refresh()}},refresh:function(){k=C.find(w.text),S=C.find(w.search),z=C.find(w.input),D=C.children(w.menu),M=D.find(w.item)},toggle:function(){m.verbose("Toggling menu visibility"),m.is.active()?m.hide():m.show()},show:function(){m.debug("Checking if dropdown can show"),m.is.active()||(m.animate.show(function(){m.can.click()&&m.bind.intent(),m.set.visible()}),e.proxy(h.onShow,I)())},hide:function(){m.is.active()&&(m.debug("Hiding dropdown"),m.animate.hide(function(){m.remove.filteredItem(),m.remove.visible()}),e.proxy(h.onHide,I)())},hideOthers:function(){m.verbose("Finding other dropdowns to hide"),s.not(C).has(w.menu+":visible:not(."+p.animating+")").dropdown("hide")},hideSubMenus:function(){var e=D.find(w.menu),t=e.has(w.item+"."+p.active);e.not(t).removeClass(p.visible).removeAttr("style")},bind:{keyboardEvents:function(){m.debug("Binding keyboard events"),C.on("keydown"+x,m.event.keydown),m.is.searchable()&&C.on(m.get.inputEvent(),w.search,m.event.input)},touchEvents:function(){m.debug("Touch device detected binding touch events"),m.is.searchSelection()||C.on("touchstart"+x,m.event.test.toggle),C.on("touchstart"+x,w.item,m.event.item.mouseenter).on("touchstart"+x,w.item,m.event.item.click)},mouseEvents:function(){m.verbose("Mouse detected binding mouse events"),m.is.searchSelection()?C.on("focus"+x,w.search,m.event.searchFocus).on("blur"+x,w.search,m.event.searchBlur):("click"==h.on?C.on("click"+x,m.event.test.toggle):"hover"==h.on?C.on("mouseenter"+x,m.delay.show).on("mouseleave"+x,m.delay.hide):C.on(h.on+x,m.toggle),C.on("mousedown",m.event.mousedown).on("mouseup",m.event.mouseup).on("focus"+x,m.event.focus).on("blur"+x,m.event.blur)),C.on("mousedown"+x,w.item,m.event.item.mousedown).on("mouseup"+x,w.item,m.event.item.mouseup).on("mouseenter"+x,w.item,m.event.item.mouseenter).on("mouseleave"+x,w.item,m.event.item.mouseleave).on("click"+x,w.item,m.event.item.click)},intent:function(){m.verbose("Binding hide intent event to document"),u&&a.on("touchstart"+x,m.event.test.touch).on("touchmove"+x,m.event.test.touch),a.on("click"+x,m.event.test.hide)}},unbind:{intent:function(){m.verbose("Removing hide intent event from document"),u&&a.off("touchstart"+x).off("touchmove"+x),a.off("click"+x)}},filter:function(t){var n,o=e(),s=new RegExp("(?:s|^)"+t,"i"),a=new RegExp(t,"i");M.each(function(){var t=e(this),n=t.data(g.text)!==i?t.data(g.text):h.preserveHTML?t.html():t.text(),r=t.data(g.value)!==i?t.data(g.value):"string"==typeof n?n.toLowerCase():n;s.test(n)||s.test(r)?o=o.add(t):h.fullTextSearch&&(a.test(n)||a.test(r))&&(o=o.add(t))}),n=M.not(o),m.remove.filteredItem(),m.remove.selectedItem(),n.addClass(p.filtered),M.not("."+p.filtered).eq(0).addClass(p.selected)},event:{mousedown:function(){A=!0},mouseup:function(){A=!1},focus:function(){A||m.show()},blur:function(){A||m.hide()},searchFocus:function(){A=!0,m.show()},searchBlur:function(){O||m.hide()},input:function(){var e=S.val();m.is.searchSelection()&&k.addClass(p.filtered),m.filter(e)},keydown:function(t){var n,i=M.not(p.filtered).filter("."+p.selected).eq(0),o=M.not("."+p.filtered),s=t.which,a={enter:13,escape:27,upArrow:38,downArrow:40},r=p.selected,u=o.index(i),c=i.size()>0;if(c||(i=M.filter("."+p.active).eq(0),c=i.size()>0),s==a.escape&&(m.verbose("Escape key pressed, closing dropdown"),S.blur(),m.hide()),m.is.visible()){if(s==a.enter&&c)return m.verbose("Enter key pressed, choosing selected item"),m.is.searchable()&&(m.verbose("Removing focus from search input"),S.blur()),e.proxy(m.event.item.click,i)(t),t.preventDefault(),!1;s==a.upArrow?(n=c?i.prevAll(w.item+":not(."+p.filtered+")").eq(0):o.eq(0),0!==u&&(m.verbose("Up key pressed, changing active item"),M.removeClass(r),n.addClass(r),m.set.scrollPosition(n)),t.preventDefault()):s==a.downArrow&&(n=c?i.nextAll(w.item+":not(."+p.filtered+")").eq(0):o.eq(0),u+1<o.size()&&(m.verbose("Down key pressed, changing active item"),M.removeClass(r),n.addClass(r),m.set.scrollPosition(n)),t.preventDefault())}else s==a.enter&&m.show()},test:{toggle:function(e){m.determine.eventInMenu(e,m.toggle)&&e.preventDefault()},touch:function(e){m.determine.eventInMenu(e,function(){"touchstart"==e.type?m.timer=setTimeout(m.hide,h.delay.touch):"touchmove"==e.type&&clearTimeout(m.timer)}),e.stopPropagation()},hide:function(e){m.determine.eventInModule(e,m.hide)}},item:{mousedown:function(){O=!0},mouseup:function(){O=!1},mouseenter:function(t){var n=e(this).find(w.menu),i=e(this).siblings(w.item).children(w.menu);n.size()>0&&(clearTimeout(m.itemTimer),m.itemTimer=setTimeout(function(){m.animate.hide(!1,i),m.verbose("Showing sub-menu",n),m.animate.show(!1,n)},2*h.delay.show),t.preventDefault())},mouseleave:function(){var t=e(this).find(w.menu);t.size()>0&&(clearTimeout(m.itemTimer),m.itemTimer=setTimeout(function(){m.verbose("Hiding sub-menu",t),m.animate.hide(!1,t)},h.delay.hide))},click:function(t){var n=e(this),o=n.data(g.text)!==i?n.data(g.text):h.preserveHTML?n.html():n.text(),s=n.data(g.value)!==i?n.data(g.value):"string"==typeof o?o.toLowerCase():o,a=function(){S.val(""),m.determine.selectAction(o,s),e.proxy(h.onChange,I)(s,o,n)},r=n.find(w.menu).size()>0;r||("touchstart"==t.type?n.one("click",a):a())}},resetStyle:function(){e(this).removeAttr("style")}},determine:{selectAction:function(t,n){m.verbose("Determining action",h.action),e.isFunction(m.action[h.action])?(m.verbose("Triggering preset action",h.action,t,n),m.action[h.action](t,n)):e.isFunction(h.action)?(m.verbose("Triggering user action",h.action,t,n),h.action(t,n)):m.error(y.action,h.action)},eventInModule:function(t,n){return n=n||function(){},0===e(t.target).closest(C).size()?(m.verbose("Triggering event",n),n(),!0):(m.verbose("Event occurred in dropdown, canceling callback"),!1)},eventInMenu:function(t,n){return n=n||function(){},0===e(t.target).closest(D).size()?(m.verbose("Triggering event",n),n(),!0):(m.verbose("Event occurred in dropdown menu, canceling callback"),!1)}},action:{nothing:function(){},hide:function(){m.hide()},select:function(e,t){t=t!==i?t:e,m.set.selected(t),m.set.value(t),m.hide()},activate:function(e,t){t=t!==i?t:e,m.set.selected(t),m.set.value(t),m.hide()},combo:function(e,t){t=t!==i?t:e,m.set.selected(t),m.set.value(t),m.hide()}},get:{text:function(){return k.text()},value:function(){return z.size()>0?z.val():C.data(g.value)},inputEvent:function(){var e=S[0];return e?e.oninput!==i?"input":e.onpropertychange!==i?"propertychange":"keyup":!1},selectValues:function(){var t={values:{}};return C.find("option").each(function(){var n=e(this).html(),o=e(this).attr("value")!==i?e(this).attr("value"):n;""===o?t.placeholder=n:t.values[o]=n}),m.debug("Retrieved values from select",t),t},item:function(t,n){var o=!1;return t=t!==i?t:m.get.value()!==i?m.get.value():m.get.text(),n=""===t||0===t?!0:n||!1,t!==i?M.each(function(){var s=e(this),a=s.data(g.text)!==i?s.data(g.text):h.preserveHTML?s.html():s.text(),r=s.data(g.value)!==i?s.data(g.value):"string"==typeof a?a.toLowerCase():a;n?(m.debug("Ambiguous dropdown value using strict type check",t),r===t?o=e(this):o||a!==t||(o=e(this))):r==t?(m.verbose("Found select item by value",r,t),o=e(this)):o||a!=t||(m.verbose("Found select item by text",a,t),o=e(this))}):t=m.get.text(),o||!1}},restore:{defaults:function(){m.restore.defaultText(),m.restore.defaultValue()},defaultText:function(){var e=C.data(g.defaultText);m.debug("Restoring default text",e),m.set.text(e)},defaultValue:function(){var e=C.data(g.defaultValue);e!==i&&(m.debug("Restoring default value",e),m.set.selected(e),m.set.value(e))}},save:{defaults:function(){m.save.defaultText(),m.save.defaultValue()},defaultValue:function(){C.data(g.defaultValue,m.get.value())},defaultText:function(){C.data(g.defaultText,k.text())}},set:{scrollPosition:function(e){var t,n,i,o,s,a,r,u,e=e||m.get.item(),c=e&&e.size()>0,d=5;e&&c&&(a=D.height(),n=e.height(),s=D.scrollTop(),o=D.offset().top,i=e.offset().top,t=s-o+i,u=t+d>s+a,r=s>t-d,(r||u)&&(m.debug("Scrolling to active item"),D.scrollTop(t)))},text:function(e){"combo"==h.action?(m.debug("Changing combo button text",e,E),h.preserveHTML?E.html(e):E.text(e)):"select"!==h.action&&(m.debug("Changing text",e,k),k.removeClass(p.filtered).removeClass(p.placeholder),h.preserveHTML?k.html(e):k.text(e))},value:function(e){m.debug("Adding selected value to hidden input",e,z),z.size()>0?z.val(e).trigger("change"):C.data(g.value,e)},active:function(){C.addClass(p.active)},visible:function(){C.addClass(p.visible)},selected:function(e){var t,n=m.get.item(e);n&&(m.debug("Setting selected menu item to",n),t=n.data(g.text)!==i?n.data(g.text):h.preserveHTML?n.html():n.text(),m.remove.activeItem(),m.remove.selectedItem(),n.addClass(p.active).addClass(p.selected),m.set.text(t))}},remove:{active:function(){C.removeClass(p.active)},visible:function(){C.removeClass(p.visible)},activeItem:function(){M.removeClass(p.active)},filteredItem:function(){M.removeClass(p.filtered)},selectedItem:function(){M.removeClass(p.selected)}},is:{search:function(){return C.hasClass(p.search)},searchable:function(){return S.size()>0},searchSelection:function(){return m.is.searchable()&&S.parent().is(C)},selection:function(){return C.hasClass(p.selection)},animated:function(e){return e?e.is(":animated")||e.transition&&e.transition("is animating"):D.is(":animated")||D.transition&&D.transition("is animating")},active:function(){return C.hasClass(p.active)},visible:function(e){return e?e.is(":visible"):D.is(":visible")},hidden:function(e){return e?e.is(":hidden"):D.is(":hidden")}},can:{click:function(){return u||"click"==h.on},show:function(){return!C.hasClass(p.disabled)}},animate:{show:function(t,n){var o=n||D,s=n?function(){}:function(){m.hideOthers(),m.set.active(),m.set.scrollPosition()};t=t||function(){},m.verbose("Doing menu show animation",o),m.is.hidden(o)&&("none"==h.transition?e.proxy(t,I)():e.fn.transition!==i&&C.transition("is supported")?o.transition({animation:h.transition+" in",duration:h.duration,queue:!0,start:s,complete:function(){e.proxy(t,I)()}}):"slide down"==h.transition?(s(),o.hide().clearQueue().children().clearQueue().css("opacity",0).delay(50).animate({opacity:1},h.duration,"easeOutQuad",m.event.resetStyle).end().slideDown(100,"easeOutQuad",function(){e.proxy(m.event.resetStyle,this)(),e.proxy(t,I)()})):"fade"==h.transition?(s(),o.hide().clearQueue().fadeIn(h.duration,function(){e.proxy(m.event.resetStyle,this)(),e.proxy(t,I)()})):m.error(y.transition,h.transition))},hide:function(t,n){var o=n||D,s=n?function(){}:function(){m.can.click()&&m.unbind.intent(),m.hideSubMenus(),m.remove.active()};t=t||function(){},m.is.visible(o)&&(m.verbose("Doing menu hide animation",o),"none"==h.transition?e.proxy(t,I)():e.fn.transition!==i&&C.transition("is supported")?o.transition({animation:h.transition+" out",duration:h.duration,queue:!0,start:s,complete:function(){e.proxy(t,I)()}}):"slide down"==h.transition?(s(),o.show().clearQueue().children().clearQueue().css("opacity",1).animate({opacity:0},100,"easeOutQuad",m.event.resetStyle).end().delay(50).slideUp(100,"easeOutQuad",function(){e.proxy(m.event.resetStyle,this)(),e.proxy(t,I)()})):"fade"==h.transition?(s(),o.show().clearQueue().fadeOut(150,function(){e.proxy(m.event.resetStyle,this)(),e.proxy(t,I)()})):m.error(y.transition))}},delay:{show:function(){m.verbose("Delaying show event to ensure user intent"),clearTimeout(m.timer),m.timer=setTimeout(m.show,h.delay.show)},hide:function(){m.verbose("Delaying hide event to ensure user intent"),clearTimeout(m.timer),m.timer=setTimeout(m.hide,h.delay.hide)}},setting:function(t,n){if(m.debug("Changing setting",t,n),e.isPlainObject(t))e.extend(!0,h,t);else{if(n===i)return h[t];h[t]=n}},internal:function(t,n){if(e.isPlainObject(t))e.extend(!0,m,t);else{if(n===i)return m[t];m[t]=n}},debug:function(){h.debug&&(h.performance?m.performance.log(arguments):(m.debug=Function.prototype.bind.call(console.info,console,h.name+":"),m.debug.apply(console,arguments)))},verbose:function(){h.verbose&&h.debug&&(h.performance?m.performance.log(arguments):(m.verbose=Function.prototype.bind.call(console.info,console,h.name+":"),m.verbose.apply(console,arguments)))},error:function(){m.error=Function.prototype.bind.call(console.error,console,h.name+":"),m.error.apply(console,arguments)},performance:{log:function(e){var t,n,i;h.performance&&(t=(new Date).getTime(),i=c||t,n=t-i,c=t,d.push({Name:e[0],Arguments:[].slice.call(e,1)||"",Element:I,"Execution Time":n})),clearTimeout(m.performance.timer),m.performance.timer=setTimeout(m.performance.display,100)},display:function(){var t=h.name+":",n=0;c=!1,clearTimeout(m.performance.timer),e.each(d,function(e,t){n+=t["Execution Time"]}),t+=" "+n+"ms",r&&(t+=" '"+r+"'"),(console.group!==i||console.table!==i)&&d.length>0&&(console.groupCollapsed(t),console.table?console.table(d):e.each(d,function(e,t){console.log(t.Name+": "+t["Execution Time"]+"ms")}),console.groupEnd()),d=[]}},invoke:function(t,n,s){var a,r,u,c=Q;return n=n||f,s=I||s,"string"==typeof t&&c!==i&&(t=t.split(/[\. ]/),a=t.length-1,e.each(t,function(n,o){var s=n!=a?o+t[n+1].charAt(0).toUpperCase()+t[n+1].slice(1):t;if(e.isPlainObject(c[s])&&n!=a)c=c[s];else{if(c[s]!==i)return r=c[s],!1;if(!e.isPlainObject(c[o])||n==a)return c[o]!==i?(r=c[o],!1):(m.error(y.method,t),!1);c=c[o]}})),e.isFunction(r)?u=r.apply(s,n):r!==i&&(u=r),e.isArray(o)?o.push(u):o!==i?o=[o,u]:u!==i&&(o=u),r}},v?(Q===i&&m.initialize(),m.invoke(l)):(Q!==i&&m.destroy(),m.initialize())}),o!==i?o:this},e.fn.dropdown.settings={debug:!1,verbose:!0,performance:!0,on:"click",action:"activate",allowTab:!0,fullTextSearch:!0,preserveHTML:!0,delay:{show:200,hide:300,touch:50},transition:"slide down",duration:250,onChange:function(){},onShow:function(){},onHide:function(){},name:"Dropdown",namespace:"dropdown",error:{action:"You called a dropdown action that was not defined",method:"The method you called is not defined.",transition:"The requested transition was not found"},metadata:{defaultText:"defaultText",defaultValue:"defaultValue",text:"text",value:"value"},selector:{dropdown:".ui.dropdown",text:"> .text:not(.icon)",input:'> input[type="hidden"], > select',search:"> .search, .menu > .search > input, .menu > input.search",menu:".menu",item:".item"},className:{active:"active",animating:"animating",disabled:"disabled",dropdown:"ui dropdown",filtered:"filtered",menu:"menu",placeholder:"default",search:"search",selected:"selected",selection:"selection",visible:"visible"}},e.fn.dropdown.settings.templates={menu:function(t){var n=(t.placeholder||!1,t.values||{},"");return e.each(t.values,function(e,t){n+=e===t?'<div class="item">'+t+"</div>":'<div class="item" data-value="'+e+'">'+t+"</div>"}),n},dropdown:function(t){var n=t.placeholder||!1,i=(t.values||{},"");return i+='<i class="dropdown icon"></i>',i+=t.placeholder?'<div class="default text">'+n+"</div>":'<div class="text"></div>',i+='<div class="menu">',e.each(t.values,function(e,t){i+=e===t?'<div class="item">'+t+"</div>":'<div class="item" data-value="'+e+'">'+t+"</div>"}),i+="</div>"}},e.extend(e.easing,{easeOutQuad:function(e,t,n,i,o){return-i*(t/=o)*(t-2)+n}})}(jQuery,window,document); | ||
!function(e,t,n,i){"use strict";e.fn.dropdown=function(o){var a,r=e(this),s=e(n),c=r.selector||"",l="ontouchstart"in n.documentElement,u=(new Date).getTime(),d=[],f=arguments[0],v="string"==typeof f,h=[].slice.call(arguments,1);return r.each(function(){var m,g,p,b,w=e.isPlainObject(o)?e.extend(!0,{},e.fn.dropdown.settings,o):e.extend({},e.fn.dropdown.settings),y=w.className,x=w.metadata,T=w.namespace,S=w.selector,C=w.error,k="."+T,I="module-"+T,E=e(this),D=E.find(S.text),A=E.find(S.search),F=E.find(S.input),M=E.prev().find(S.text).length>0?E.prev().find(S.text):E.prev(),q=E.children(S.menu),O=q.find(S.item),V=!1,z=!1,Q=this,R=E.data(I);b={initialize:function(){b.debug("Initializing dropdown",w),b.is.alreadySetup()?b.error(C.alreadySetup):b.setup.layout(),b.save.defaults(),b.set.selected(),b.create.id(),l&&b.bind.touchEvents(),b.bind.mouseEvents(),b.bind.keyboardEvents(),b.observeChanges(),b.instantiate()},instantiate:function(){b.verbose("Storing instance of dropdown",b),R=b,E.data(I,b)},destroy:function(){b.verbose("Destroying previous dropdown for",E),b.remove.tabbable(),E.off(k).removeData(I),q.off(k),s.off(m)},observeChanges:function(){"MutationObserver"in t&&(p=new MutationObserver(function(e){b.is.selectMutation(e)?(b.debug("<select> modified, recreating menu"),b.setup.select()):(b.debug("DOM tree modified, updating selector cache"),b.refresh())}),p.observe(Q,{childList:!0,subtree:!0}),b.debug("Setting up mutation observer",p))},create:{id:function(){b.verbose("Creating unique id for element"),g=b.get.uniqueID(),m="."+g}},search:function(){var e;e=A.val(),b.verbose("Searching for query",e),b.filter(e),b.is.searchSelection()&&b.can.show()&&b.show()},setup:{layout:function(){E.is("select")&&b.setup.select(),b.is.search()&&!b.is.searchable()&&(A=e("<input />").addClass(y.search).insertBefore(D)),w.allowTab&&b.set.tabbable()},select:function(){var t=b.get.selectValues();b.debug("Dropdown initialized on a select",t),E.is("select")&&(F=E),F.parent(S.dropdown).length>0?(b.debug("UI dropdown already exists. Creating dropdown menu only"),E=F.closest(S.dropdown),q=E.children(S.menu),0===q.length&&(q=e("<div />").addClass(y.menu).appendTo(E)),q.html(w.templates.menu(t))):(b.debug("Creating entire dropdown from select"),E=e("<div />").attr("class",F.attr("class")).addClass(y.selection).addClass(y.dropdown).html(w.templates.dropdown(t)).insertBefore(F),F.removeAttr("class").prependTo(E)),b.refresh()}},refresh:function(){b.verbose("Refreshing selector cache"),D=E.find(S.text),A=E.find(S.search),F=E.find(S.input),M=E.prev().find(S.text).length>0?E.prev().find(S.text):E.prev(),q=E.children(S.menu),O=q.find(S.item)},toggle:function(){b.verbose("Toggling menu visibility"),b.is.active()?b.hide():b.show()},show:function(t){t=e.isFunction(t)?t:function(){},b.is.searchSelection()&&b.is.allFiltered()||b.can.show()&&!b.is.active()&&(b.debug("Showing dropdown"),b.animate.show(function(){b.can.click()&&b.bind.intent(),b.set.visible(),t.call(Q)}),w.onShow.call(Q))},hide:function(t){t=e.isFunction(t)?t:function(){},b.is.active()&&(b.debug("Hiding dropdown"),b.animate.hide(function(){b.remove.visible(),t.call(Q)}),w.onHide.call(Q))},hideOthers:function(){b.verbose("Finding other dropdowns to hide"),r.not(E).has(S.menu+":visible:not(."+y.animating+")").dropdown("hide")},hideSubMenus:function(){var e=q.find(S.menu);e.transition("hide")},bind:{keyboardEvents:function(){b.debug("Binding keyboard events"),E.on("keydown"+k,b.event.keydown),b.is.searchable()&&E.on(b.get.inputEvent(),S.search,b.event.input)},touchEvents:function(){b.debug("Touch device detected binding additional touch events"),b.is.searchSelection()||E.on("touchstart"+k,b.event.test.toggle),q.on("touchstart"+k,S.item,b.event.item.mouseenter)},mouseEvents:function(){b.verbose("Mouse detected binding mouse events"),b.is.searchSelection()?E.on("mousedown"+k,S.menu,b.event.menu.activate).on("mouseup"+k,S.menu,b.event.menu.deactivate).on("click"+k,S.search,b.show).on("focus"+k,S.search,b.event.searchFocus).on("blur"+k,S.search,b.event.searchBlur).on("click"+k,S.text,b.event.searchTextFocus):("click"==w.on?E.on("click"+k,b.event.test.toggle):"hover"==w.on?E.on("mouseenter"+k,b.delay.show).on("mouseleave"+k,b.delay.hide):E.on(w.on+k,b.toggle),E.on("mousedown"+k,b.event.mousedown).on("mouseup"+k,b.event.mouseup).on("focus"+k,b.event.focus).on("blur"+k,b.event.blur)),q.on("mouseenter"+k,S.item,b.event.item.mouseenter).on("mouseleave"+k,S.item,b.event.item.mouseleave).on("click"+k,S.item,b.event.item.click)},intent:function(){b.verbose("Binding hide intent event to document"),l&&s.on("touchstart"+m,b.event.test.touch).on("touchmove"+m,b.event.test.touch),s.on("click"+m,b.event.test.hide)}},unbind:{intent:function(){b.verbose("Removing hide intent event from document"),l&&s.off("touchstart"+m).off("touchmove"+m),s.off("click"+m)}},filter:function(t){var n=e(),i=b.escape.regExp(t),o=new RegExp("^"+i,"igm"),a=new RegExp(i,"ig");b.verbose("Searching for matching values"),O.each(function(){var t=e(this),i=String(b.get.choiceText(t,!1)),r=String(b.get.choiceValue(t,i));i.match(o)||r.match(o)?n=n.add(t):w.fullTextSearch&&(i.match(a)||r.match(a))&&(n=n.add(t))}),b.debug("Setting filter",t),b.remove.filteredItem(),O.not(n).addClass(y.filtered),b.verbose("Selecting first non-filtered element"),b.remove.selectedItem(),O.not("."+y.filtered).eq(0).addClass(y.selected),b.is.allFiltered()&&(b.debug("All items filtered, hiding dropdown",t),b.is.searchSelection()&&b.hide(),w.onNoResults.call(Q,t))},focusSearch:function(){b.is.search()&&A.focus()},forceSelection:function(){var e=O.not(y.filtered).filter("."+y.selected).eq(0),t=O.filter("."+y.active).eq(0),n=e.length>0?e:t,i=n.size()>0;i&&b.event.item.click.call(n)},event:{mousedown:function(){V=!0},mouseup:function(){V=!1},focus:function(){!V&&b.is.hidden()&&b.show()},blur:function(){var e=n.activeElement===this;V||e||b.hide()},searchFocus:function(){V=!0,b.show()},searchBlur:function(){var e=n.activeElement===this;z||e||(w.forceSelection?b.forceSelection():b.hide())},searchTextFocus:function(){V=!0,A.focus()},input:function(){b.is.searchSelection()&&b.set.filtered(),clearTimeout(b.timer),b.timer=setTimeout(b.search,w.delay.search)},keydown:function(e){{var t,n=O.not(y.filtered).filter("."+y.selected).eq(0),i=q.children("."+y.active).eq(0),o=n.length>0?n:i,a=o.length>0?o.siblings(":not(."+y.filtered+")").andSelf():q.children(":not(."+y.filtered+")"),r=o.children(S.menu),s=o.closest(S.menu),c=s[0]!==q[0],l=s.is(":visible"),u=e.which,d={enter:13,escape:27,leftArrow:37,upArrow:38,rightArrow:39,downArrow:40},f=r.length>0,v=o.length>0;a.size()-1}if(b.is.visible()){if(u==d.enter&&v&&(f&&!w.allowCategorySelection?(b.verbose("Pressed enter on unselectable category, opening sub menu"),u=d.rightArrow):(b.verbose("Enter key pressed, choosing selected item"),b.event.item.click.call(o,e))),u==d.leftArrow&&(c&&(b.verbose("Left key pressed, closing sub-menu"),b.animate.hide(!1,s),o.removeClass(y.selected),s.closest(S.item).addClass(y.selected)),e.preventDefault()),u==d.rightArrow&&(f&&(b.verbose("Right key pressed, opening sub-menu"),b.animate.show(!1,r),o.removeClass(y.selected),r.find(S.item).eq(0).addClass(y.selected)),e.preventDefault()),u==d.upArrow){if(t=v&&l?o.prevAll(S.item+":not(."+y.filtered+")").eq(0):O.eq(0),a.index(t)<0)return void b.verbose("Up key pressed but reached top of current menu");b.verbose("Up key pressed, changing active item"),o.removeClass(y.selected),t.addClass(y.selected),b.set.scrollPosition(t),e.preventDefault()}if(u==d.downArrow){if(t=v&&l?t=o.nextAll(S.item+":not(."+y.filtered+")").eq(0):O.eq(0),0===t.length)return void b.verbose("Down key pressed but reached bottom of current menu");b.verbose("Down key pressed, changing active item"),O.removeClass(y.selected),t.addClass(y.selected),b.set.scrollPosition(t),e.preventDefault()}}else u==d.enter&&(b.verbose("Enter key pressed, showing dropdown"),b.show()),u==d.escape&&(b.verbose("Escape key pressed, closing dropdown"),b.hide()),u==d.downArrow&&(b.verbose("Down key pressed, showing dropdown"),b.show())},test:{toggle:function(e){b.determine.eventInMenu(e,b.toggle)&&e.preventDefault()},touch:function(e){b.determine.eventInMenu(e,function(){"touchstart"==e.type?b.timer=setTimeout(b.hide,w.delay.touch):"touchmove"==e.type&&clearTimeout(b.timer)}),e.stopPropagation()},hide:function(e){b.determine.eventInModule(e,b.hide)}},menu:{activate:function(){z=!0},deactivate:function(){z=!1}},item:{mouseenter:function(t){var n=e(this).children(S.menu),i=e(this).siblings(S.item).children(S.menu);n.length>0&&(clearTimeout(b.itemTimer),b.itemTimer=setTimeout(function(){b.verbose("Showing sub-menu",n),e.each(i,function(){b.animate.hide(!1,e(this))}),b.animate.show(!1,n)},w.delay.show),t.preventDefault())},mouseleave:function(){var t=e(this).children(S.menu);t.length>0&&(clearTimeout(b.itemTimer),b.itemTimer=setTimeout(function(){b.verbose("Hiding sub-menu",t),b.animate.hide(!1,t)},w.delay.hide))},click:function(t){var n=e(this),i=e(t?t.target:""),o=n.find(S.menu),a=b.get.choiceText(n),r=b.get.choiceValue(n,a),s=function(){b.remove.searchTerm(),b.determine.selectAction(a,r)},c=o.length>0,l=o.find(i).length>0;l||c&&!w.allowCategorySelection||s()}},resetStyle:function(){e(this).removeAttr("style")}},determine:{selectAction:function(t,n){b.verbose("Determining action",w.action),e.isFunction(b.action[w.action])?(b.verbose("Triggering preset action",w.action,t,n),b.action[w.action](t,n)):e.isFunction(w.action)?(b.verbose("Triggering user action",w.action,t,n),w.action(t,n)):b.error(C.action,w.action)},eventInModule:function(t,n){return n=e.isFunction(n)?n:function(){},0===e(t.target).closest(E).length?(b.verbose("Triggering event",n),n(),!0):(b.verbose("Event occurred in dropdown, canceling callback"),!1)},eventInMenu:function(t,n){return n=e.isFunction(n)?n:function(){},0===e(t.target).closest(q).length?(b.verbose("Triggering event",n),n(),!0):(b.verbose("Event occurred in dropdown menu, canceling callback"),!1)}},action:{nothing:function(){},activate:function(e,t){t=t!==i?t:e,b.set.selected(t),b.hide(function(){b.remove.filteredItem()})},select:function(e,t){t=t!==i?t:e,b.set.selected(t),b.hide(function(){b.remove.filteredItem()})},combo:function(e,t){t=t!==i?t:e,b.set.selected(t),b.hide(function(){b.remove.filteredItem()})},hide:function(){b.hide(function(){b.remove.filteredItem()})}},get:{text:function(){return D.text()},value:function(){return F.length>0?F.val():E.data(x.value)},choiceText:function(e,t){return t=t!==i?t:w.preserveHTML,e!==i?(e.find(S.menu).length>0&&(b.verbose("Retreiving text of element with sub-menu"),e=e.clone(),e.find(S.menu).remove(),e.find(S.menuIcon).remove()),e.data(x.text)!==i?e.data(x.text):t?e.html().trim():e.text().trim()):void 0},choiceValue:function(e,t){return t=t||b.get.choiceText(e),e.data(x.value)!==i?e.data(x.value):"string"==typeof t?t.toLowerCase().trim():t.trim()},inputEvent:function(){var e=A[0];return e?e.oninput!==i?"input":e.onpropertychange!==i?"propertychange":"keyup":!1},selectValues:function(){var t={};return t.values=w.sortSelect?{}:[],E.find("option").each(function(){var n=e(this).html(),o=e(this).attr("value")!==i?e(this).attr("value"):n;""===o?t.placeholder=n:w.sortSelect?t.values[o]={name:n,value:o}:t.values.push({name:n,value:o})}),w.sortSelect?b.debug("Retrieved and sorted values from select",t):b.debug("Retreived values from select",t),t},activeItem:function(){return O.filter("."+y.active)},item:function(t,n){var o=!1;return t=t!==i?t:b.get.value()!==i?b.get.value():b.get.text(),n=""===t||0===t?!0:n||!1,t!==i?O.each(function(){var i=e(this),a=b.get.choiceText(i),r=b.get.choiceValue(i,a);n?(b.verbose("Ambiguous dropdown value using strict type check",i,t),r===t?o=e(this):o||a!==t||(o=e(this))):r==t?(b.verbose("Found select item by value",r,t),o=e(this)):o||a!=t||(b.verbose("Found select item by text",a,t),o=e(this))}):t=b.get.text(),o||!1},uniqueID:function(){return(Math.random().toString(16)+"000000000").substr(2,8)}},restore:{defaults:function(){b.restore.defaultText(),b.restore.defaultValue()},defaultText:function(){var e=E.data(x.defaultText);b.debug("Restoring default text",e),b.set.text(e),D.addClass(y.placeholder)},defaultValue:function(){var e=E.data(x.defaultValue);e!==i&&(b.debug("Restoring default value",e),e.length?b.set.selected(e):(b.remove.activeItem(),b.remove.selectedItem()))}},save:{defaults:function(){b.save.defaultText(),b.save.placeholderText(),b.save.defaultValue()},defaultValue:function(){E.data(x.defaultValue,b.get.value())},defaultText:function(){E.data(x.defaultText,D.text())},placeholderText:function(){D.hasClass(y.placeholder)&&E.data(x.placeholderText,D.text())}},clear:function(){var e=E.data(x.placeholderText);b.set.text(e),b.set.value(""),b.remove.activeItem(),b.remove.selectedItem(),D.addClass(y.placeholder)},set:{filtered:function(){var e=A.val(),t="string"==typeof e&&e.length>0;t?D.addClass(y.filtered):D.removeClass(y.filtered)},tabbable:function(){b.is.searchable()?(b.debug("Searchable dropdown initialized"),A.val("").attr("tabindex",0),q.attr("tabindex","-1")):(b.debug("Simple selection dropdown initialized"),E.attr("tabindex")||(E.attr("tabindex",0),q.attr("tabindex","-1")))},scrollPosition:function(e,t){var n,o,a,r,s,c,l,u,d,f=5;e=e||b.get.activeItem(),n=e&&e.length>0,t=t!==i?t:!1,e&&n&&(q.hasClass(y.visible)||q.addClass(y.loading),l=q.height(),a=e.height(),c=q.scrollTop(),s=q.offset().top,r=e.offset().top,o=c-s+r,d=o+f>c+l,u=c>o-f,b.debug("Scrolling to active item",o),(u||d||t)&&q.scrollTop(o).removeClass(y.loading))},text:function(e){"combo"==w.action?(b.debug("Changing combo button text",e,M),w.preserveHTML?M.html(e):M.text(e)):"select"!==w.action&&(b.debug("Changing text",e,D),D.removeClass(y.filtered).removeClass(y.placeholder),w.preserveHTML?D.html(e):D.text(e))},value:function(e){b.debug("Adding selected value to hidden input",e,F),F.length>0?F.val(e).trigger("change"):E.data(x.value,e)},active:function(){E.addClass(y.active)},visible:function(){E.addClass(y.visible)},selected:function(e){var t,n,i=b.get.item(e);i&&(b.debug("Setting selected menu item to",i),b.remove.activeItem(),b.remove.selectedItem(),i.addClass(y.active).addClass(y.selected),t=b.get.choiceText(i),n=b.get.choiceValue(i,t),b.set.text(t),b.set.value(n),w.onChange.call(Q,e,t,i))}},remove:{active:function(){E.removeClass(y.active)},visible:function(){E.removeClass(y.visible)},activeItem:function(){O.removeClass(y.active)},filteredItem:function(){O.removeClass(y.filtered)},searchTerm:function(){A.val("")},selectedItem:function(){O.removeClass(y.selected)},tabbable:function(){b.is.searchable()?(b.debug("Searchable dropdown initialized"),A.attr("tabindex","-1"),q.attr("tabindex","-1")):(b.debug("Simple selection dropdown initialized"),E.attr("tabindex","-1"),q.attr("tabindex","-1"))}},is:{active:function(){return E.hasClass(y.active)},alreadySetup:function(){return E.is("select")&&E.parent(S.dropdown).length>0},animating:function(e){return e?e.is(":animated")||e.transition&&e.transition("is animating"):q.is(":animated")||q.transition&&q.transition("is animating")},allFiltered:function(){return O.filter("."+y.filtered).length===O.length},hidden:function(e){return e?e.is(":hidden"):q.is(":hidden")},selectMutation:function(t){var n=!1;return e.each(t,function(t,i){return i.target&&e(i.target).is("select")?(n=!0,!0):void 0}),n},search:function(){return E.hasClass(y.search)},searchable:function(){return A.length>0},searchSelection:function(){return b.is.searchable()&&A.parent().is(E)},selection:function(){return E.hasClass(y.selection)},upward:function(){return E.hasClass(y.upward)},visible:function(e){return e?e.is(":visible"):q.is(":visible")}},can:{click:function(){return l||"click"==w.on},show:function(){return!E.hasClass(y.disabled)}},animate:{show:function(t,n){var o=n||q,a=n?function(){}:function(){b.hideSubMenus(),b.hideOthers(),b.set.active()};t=e.isFunction(t)?t:function(){},b.set.scrollPosition(b.get.activeItem(),!0),b.verbose("Doing menu show animation",o),(b.is.hidden(o)||b.is.animating(o))&&("auto"==w.transition&&(w.transition=b.is.upward()?"slide up":"slide down",b.verbose("Automatically determining animation based on animation direction",w.transition)),"none"==w.transition?t.call(Q):e.fn.transition!==i&&E.transition("is supported")?o.transition({animation:w.transition+" in",debug:w.debug,verbose:w.verbose,duration:w.duration,queue:!0,onStart:a,onComplete:function(){t.call(Q)}}):"slide down"==w.transition?(a(),o.hide().clearQueue().children().clearQueue().css("opacity",0).delay(50).animate({opacity:1},w.duration,"easeOutQuad",b.event.resetStyle).end().slideDown(100,"easeOutQuad",function(){b.event.resetStyle.call(this),t.call(Q)})):"fade"==w.transition?(a(),o.hide().clearQueue().fadeIn(w.duration,function(){b.event.resetStyle.call(this),t.call(Q)})):b.error(C.transition,w.transition))},hide:function(t,n){var o=n||q,a=(n?.9*w.duration:w.duration,n?function(){}:function(){b.can.click()&&b.unbind.intent(),b.focusSearch(),b.remove.active()});t=e.isFunction(t)?t:function(){},(b.is.visible(o)||b.is.animating(o))&&(b.verbose("Doing menu hide animation",o),"auto"==w.transition&&(w.transition=b.is.upward()?"slide up":"slide down"),F.trigger("blur"),"none"==w.transition?t.call(Q):e.fn.transition!==i&&E.transition("is supported")?o.transition({animation:w.transition+" out",duration:w.duration,debug:w.debug,verbose:w.verbose,queue:!0,onStart:a,onComplete:function(){t.call(Q)}}):"slide down"==w.transition?(a(),o.show().clearQueue().children().clearQueue().css("opacity",1).animate({opacity:0},100,"easeOutQuad",b.event.resetStyle).end().delay(50).slideUp(100,"easeOutQuad",function(){b.event.resetStyle.call(this),t.call(Q)})):"fade"==w.transition?(a(),o.show().clearQueue().fadeOut(150,function(){b.event.resetStyle.call(this),t.call(Q)})):b.error(C.transition))}},delay:{show:function(){b.verbose("Delaying show event to ensure user intent"),clearTimeout(b.timer),b.timer=setTimeout(b.show,w.delay.show)},hide:function(){b.verbose("Delaying hide event to ensure user intent"),clearTimeout(b.timer),b.timer=setTimeout(b.hide,w.delay.hide)}},escape:{regExp:function(e){return e=String(e),e.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&")}},setting:function(t,n){if(b.debug("Changing setting",t,n),e.isPlainObject(t))e.extend(!0,w,t);else{if(n===i)return w[t];w[t]=n}},internal:function(t,n){if(e.isPlainObject(t))e.extend(!0,b,t);else{if(n===i)return b[t];b[t]=n}},debug:function(){w.debug&&(w.performance?b.performance.log(arguments):(b.debug=Function.prototype.bind.call(console.info,console,w.name+":"),b.debug.apply(console,arguments)))},verbose:function(){w.verbose&&w.debug&&(w.performance?b.performance.log(arguments):(b.verbose=Function.prototype.bind.call(console.info,console,w.name+":"),b.verbose.apply(console,arguments)))},error:function(){b.error=Function.prototype.bind.call(console.error,console,w.name+":"),b.error.apply(console,arguments)},performance:{log:function(e){var t,n,i;w.performance&&(t=(new Date).getTime(),i=u||t,n=t-i,u=t,d.push({Name:e[0],Arguments:[].slice.call(e,1)||"",Element:Q,"Execution Time":n})),clearTimeout(b.performance.timer),b.performance.timer=setTimeout(b.performance.display,100)},display:function(){var t=w.name+":",n=0;u=!1,clearTimeout(b.performance.timer),e.each(d,function(e,t){n+=t["Execution Time"]}),t+=" "+n+"ms",c&&(t+=" '"+c+"'"),(console.group!==i||console.table!==i)&&d.length>0&&(console.groupCollapsed(t),console.table?console.table(d):e.each(d,function(e,t){console.log(t.Name+": "+t["Execution Time"]+"ms")}),console.groupEnd()),d=[]}},invoke:function(t,n,o){var r,s,c,l=R;return n=n||h,o=Q||o,"string"==typeof t&&l!==i&&(t=t.split(/[\. ]/),r=t.length-1,e.each(t,function(n,o){var a=n!=r?o+t[n+1].charAt(0).toUpperCase()+t[n+1].slice(1):t;if(e.isPlainObject(l[a])&&n!=r)l=l[a];else{if(l[a]!==i)return s=l[a],!1;if(!e.isPlainObject(l[o])||n==r)return l[o]!==i?(s=l[o],!1):(b.error(C.method,t),!1);l=l[o]}})),e.isFunction(s)?c=s.apply(o,n):s!==i&&(c=s),e.isArray(a)?a.push(c):a!==i?a=[a,c]:c!==i&&(a=c),s}},v?(R===i&&b.initialize(),b.invoke(f)):(R!==i&&R.invoke("destroy"),b.initialize())}),a!==i?a:this},e.fn.dropdown.settings={debug:!1,verbose:!0,performance:!0,on:"click",action:"activate",allowTab:!0,fullTextSearch:!1,preserveHTML:!0,sortSelect:!1,allowCategorySelection:!1,delay:{hide:300,show:200,search:50,touch:50},forceSelection:!0,transition:"auto",duration:250,onNoResults:function(){},onChange:function(){},onShow:function(){},onHide:function(){},name:"Dropdown",namespace:"dropdown",error:{action:"You called a dropdown action that was not defined",alreadySetup:"Once a select has been initialized behaviors must be called on the created ui dropdown",method:"The method you called is not defined.",transition:"The requested transition was not found"},metadata:{defaultText:"defaultText",defaultValue:"defaultValue",placeholderText:"placeholderText",text:"text",value:"value"},selector:{dropdown:".ui.dropdown",input:'> input[type="hidden"], > select',item:".item",menu:".menu",menuIcon:".dropdown.icon",search:"> input.search, .menu > .search > input, .menu > input.search",text:"> .text:not(.icon)"},className:{active:"active",animating:"animating",disabled:"disabled",dropdown:"ui dropdown",filtered:"filtered",loading:"loading",menu:"menu",placeholder:"default",search:"search",selected:"selected",selection:"selection",upward:"upward",visible:"visible"}},e.fn.dropdown.settings.templates={menu:function(t){var n=(t.placeholder||!1,t.values||{},"");return e.each(t.values,function(e,t){n+='<div class="item" data-value="'+t.value+'">'+t.name+"</div>"}),n},dropdown:function(t){var n=t.placeholder||!1,i=(t.values||{},"");return i+='<i class="dropdown icon"></i>',i+=t.placeholder?'<div class="default text">'+n+"</div>":'<div class="text"></div>',i+='<div class="menu">',e.each(t.values,function(e,t){i+='<div class="item" data-value="'+t.value+'">'+t.name+"</div>"}),i+="</div>"}},e.extend(e.easing,{easeOutQuad:function(e,t,n,i,o){return-i*(t/=o)*(t-2)+n}})}(jQuery,window,document); |
964
index.js
@@ -56,3 +56,3 @@ /* | ||
$combo = ($module.prev().find(selector.text).size() > 0) | ||
$combo = ($module.prev().find(selector.text).length > 0) | ||
? $module.prev().find(selector.text) | ||
@@ -66,5 +66,7 @@ : $module.prev(), | ||
itemActivated = false, | ||
element = this, | ||
instance = $module.data(moduleNamespace), | ||
elementNamespace, | ||
id, | ||
observer, | ||
@@ -78,6 +80,15 @@ module | ||
module.debug('Initializing dropdown', settings); | ||
module.setup.layout(); | ||
if( module.is.alreadySetup() ) { | ||
module.error(error.alreadySetup); | ||
} | ||
else { | ||
module.setup.layout(); | ||
} | ||
module.save.defaults(); | ||
module.set.selected(); | ||
module.create.id(); | ||
if(hasTouch) { | ||
@@ -103,2 +114,3 @@ module.bind.touchEvents(); | ||
module.verbose('Destroying previous dropdown for', $module); | ||
module.remove.tabbable(); | ||
$module | ||
@@ -108,9 +120,21 @@ .off(eventNamespace) | ||
; | ||
$menu | ||
.off(eventNamespace) | ||
; | ||
$document | ||
.off(elementNamespace) | ||
; | ||
}, | ||
observeChanges: function() { | ||
if(MutationObserver !== undefined) { | ||
if('MutationObserver' in window) { | ||
observer = new MutationObserver(function(mutations) { | ||
module.debug('DOM tree modified, updating selector cache'); | ||
module.refresh(); | ||
if( module.is.selectMutation(mutations) ) { | ||
module.debug('<select> modified, recreating menu'); | ||
module.setup.select(); | ||
} | ||
else { | ||
module.debug('DOM tree modified, updating selector cache'); | ||
module.refresh(); | ||
} | ||
}); | ||
@@ -125,2 +149,23 @@ observer.observe(element, { | ||
create: { | ||
id: function() { | ||
module.verbose('Creating unique id for element'); | ||
id = module.get.uniqueID(); | ||
elementNamespace = '.' + id; | ||
} | ||
}, | ||
search: function() { | ||
var | ||
query | ||
; | ||
query = $search.val(); | ||
module.verbose('Searching for query', query); | ||
module.filter(query); | ||
if(module.is.searchSelection() && module.can.show() ) { | ||
module.show(); | ||
} | ||
}, | ||
setup: { | ||
@@ -139,23 +184,3 @@ | ||
if(settings.allowTab) { | ||
if( module.is.searchable() ) { | ||
module.debug('Searchable dropdown initialized'); | ||
$search | ||
.val('') | ||
.attr('tabindex', 0) | ||
; | ||
$menu | ||
.attr('tabindex', '-1') | ||
; | ||
} | ||
else { | ||
module.debug('Simple selection dropdown initialized'); | ||
if(!$module.attr('tabindex') ) { | ||
$module | ||
.attr('tabindex', 0) | ||
; | ||
$menu | ||
.attr('tabindex', '-1') | ||
; | ||
} | ||
} | ||
module.set.tabbable(); | ||
} | ||
@@ -165,20 +190,23 @@ }, | ||
var | ||
selectValues = module.get.selectValues() | ||
selectValues = module.get.selectValues() | ||
; | ||
module.debug('Dropdown initialized on a select', selectValues); | ||
// see if select exists inside a dropdown | ||
$input = $module; | ||
if($input.parents(selector.dropdown).size() > 0) { | ||
module.debug('Creating dropdown menu only from template'); | ||
if( $module.is('select') ) { | ||
$input = $module; | ||
} | ||
// see if select is placed correctly already | ||
if($input.parent(selector.dropdown).length > 0) { | ||
module.debug('UI dropdown already exists. Creating dropdown menu only'); | ||
$module = $input.closest(selector.dropdown); | ||
if($module.find('.' + className.dropdown).size() === 0) { | ||
$('<div />') | ||
$menu = $module.children(selector.menu); | ||
if($menu.length === 0) { | ||
$menu = $('<div />') | ||
.addClass(className.menu) | ||
.html( settings.templates.menu( selectValues )) | ||
.appendTo($module) | ||
; | ||
} | ||
$menu.html( settings.templates.menu( selectValues )); | ||
} | ||
else { | ||
module.debug('Creating entire dropdown from template'); | ||
module.debug('Creating entire dropdown from select'); | ||
$module = $('<div />') | ||
@@ -201,5 +229,10 @@ .attr('class', $input.attr('class') ) | ||
refresh: function() { | ||
module.verbose('Refreshing selector cache'); | ||
$text = $module.find(selector.text); | ||
$search = $module.find(selector.search); | ||
$input = $module.find(selector.input); | ||
$combo = ($module.prev().find(selector.text).length > 0) | ||
? $module.prev().find(selector.text) | ||
: $module.prev() | ||
; | ||
$menu = $module.children(selector.menu); | ||
@@ -219,5 +252,12 @@ $item = $menu.find(selector.item); | ||
show: function() { | ||
module.debug('Checking if dropdown can show'); | ||
if( !module.is.active() ) { | ||
show: function(callback) { | ||
callback = $.isFunction(callback) | ||
? callback | ||
: function(){} | ||
; | ||
if( module.is.searchSelection() && module.is.allFiltered() ) { | ||
return; | ||
} | ||
if( module.can.show() && !module.is.active() ) { | ||
module.debug('Showing dropdown'); | ||
module.animate.show(function() { | ||
@@ -228,15 +268,20 @@ if( module.can.click() ) { | ||
module.set.visible(); | ||
callback.call(element); | ||
}); | ||
$.proxy(settings.onShow, element)(); | ||
settings.onShow.call(element); | ||
} | ||
}, | ||
hide: function() { | ||
hide: function(callback) { | ||
callback = $.isFunction(callback) | ||
? callback | ||
: function(){} | ||
; | ||
if( module.is.active() ) { | ||
module.debug('Hiding dropdown'); | ||
module.animate.hide(function() { | ||
module.remove.filteredItem(); | ||
module.remove.visible(); | ||
callback.call(element); | ||
}); | ||
$.proxy(settings.onHide, element)(); | ||
settings.onHide.call(element); | ||
} | ||
@@ -256,10 +301,5 @@ }, | ||
var | ||
$subMenus = $menu.find(selector.menu), | ||
$activeSubMenu = $subMenus.has(selector.item + '.' + className.active) | ||
$subMenus = $menu.find(selector.menu) | ||
; | ||
$subMenus | ||
.not($activeSubMenu) | ||
.removeClass(className.visible) | ||
.removeAttr('style') | ||
; | ||
$subMenus.transition('hide'); | ||
}, | ||
@@ -280,4 +320,7 @@ | ||
touchEvents: function() { | ||
module.debug('Touch device detected binding touch events'); | ||
if( !module.is.searchSelection() ) { | ||
module.debug('Touch device detected binding additional touch events'); | ||
if( module.is.searchSelection() ) { | ||
// do nothing special yet | ||
} | ||
else { | ||
$module | ||
@@ -287,5 +330,4 @@ .on('touchstart' + eventNamespace, module.event.test.toggle) | ||
} | ||
$module | ||
$menu | ||
.on('touchstart' + eventNamespace, selector.item, module.event.item.mouseenter) | ||
.on('touchstart' + eventNamespace, selector.item, module.event.item.click) | ||
; | ||
@@ -297,4 +339,8 @@ }, | ||
$module | ||
.on('focus' + eventNamespace, selector.search, module.event.searchFocus) | ||
.on('blur' + eventNamespace, selector.search, module.event.searchBlur) | ||
.on('mousedown' + eventNamespace, selector.menu, module.event.menu.activate) | ||
.on('mouseup' + eventNamespace, selector.menu, module.event.menu.deactivate) | ||
.on('click' + eventNamespace, selector.search, module.show) | ||
.on('focus' + eventNamespace, selector.search, module.event.searchFocus) | ||
.on('blur' + eventNamespace, selector.search, module.event.searchBlur) | ||
.on('click' + eventNamespace, selector.text, module.event.searchTextFocus) | ||
; | ||
@@ -320,11 +366,9 @@ } | ||
$module | ||
.on('mousedown', module.event.mousedown) | ||
.on('mouseup', module.event.mouseup) | ||
.on('focus' + eventNamespace, module.event.focus) | ||
.on('blur' + eventNamespace, module.event.blur) | ||
.on('mousedown' + eventNamespace, module.event.mousedown) | ||
.on('mouseup' + eventNamespace, module.event.mouseup) | ||
.on('focus' + eventNamespace, module.event.focus) | ||
.on('blur' + eventNamespace, module.event.blur) | ||
; | ||
} | ||
$module | ||
.on('mousedown' + eventNamespace, selector.item, module.event.item.mousedown) | ||
.on('mouseup' + eventNamespace, selector.item, module.event.item.mouseup) | ||
$menu | ||
.on('mouseenter' + eventNamespace, selector.item, module.event.item.mouseenter) | ||
@@ -339,8 +383,8 @@ .on('mouseleave' + eventNamespace, selector.item, module.event.item.mouseleave) | ||
$document | ||
.on('touchstart' + eventNamespace, module.event.test.touch) | ||
.on('touchmove' + eventNamespace, module.event.test.touch) | ||
.on('touchstart' + elementNamespace, module.event.test.touch) | ||
.on('touchmove' + elementNamespace, module.event.test.touch) | ||
; | ||
} | ||
$document | ||
.on('click' + eventNamespace, module.event.test.hide) | ||
.on('click' + elementNamespace, module.event.test.hide) | ||
; | ||
@@ -355,8 +399,8 @@ } | ||
$document | ||
.off('touchstart' + eventNamespace) | ||
.off('touchmove' + eventNamespace) | ||
.off('touchstart' + elementNamespace) | ||
.off('touchmove' + elementNamespace) | ||
; | ||
} | ||
$document | ||
.off('click' + eventNamespace) | ||
.off('click' + elementNamespace) | ||
; | ||
@@ -369,6 +413,8 @@ } | ||
$results = $(), | ||
exactRegExp = new RegExp('(?:\s|^)' + searchTerm, 'i'), | ||
fullTextRegExp = new RegExp(searchTerm, 'i'), | ||
$filteredItems | ||
escapedTerm = module.escape.regExp(searchTerm), | ||
exactRegExp = new RegExp('^' + escapedTerm, 'igm'), | ||
fullTextRegExp = new RegExp(escapedTerm, 'ig'), | ||
allItemsFiltered | ||
; | ||
module.verbose('Searching for matching values'); | ||
$item | ||
@@ -378,18 +424,10 @@ .each(function(){ | ||
$choice = $(this), | ||
text = ( $choice.data(metadata.text) !== undefined ) | ||
? $choice.data(metadata.text) | ||
: (settings.preserveHTML) | ||
? $choice.html() | ||
: $choice.text(), | ||
value = ( $choice.data(metadata.value) !== undefined) | ||
? $choice.data(metadata.value) | ||
: (typeof text === 'string') | ||
? text.toLowerCase() | ||
: text | ||
text = String(module.get.choiceText($choice, false)), | ||
value = String(module.get.choiceValue($choice, text)) | ||
; | ||
if( exactRegExp.test( text ) || exactRegExp.test( value ) ) { | ||
if( text.match(exactRegExp) || value.match(exactRegExp) ) { | ||
$results = $results.add($choice); | ||
} | ||
else if(settings.fullTextSearch) { | ||
if( fullTextRegExp.test( text ) || fullTextRegExp.test( value ) ) { | ||
if( text.match(fullTextRegExp) || value.match(fullTextRegExp) ) { | ||
$results = $results.add($choice); | ||
@@ -400,8 +438,12 @@ } | ||
; | ||
$filteredItems = $item.not($results); | ||
module.debug('Setting filter', searchTerm); | ||
module.remove.filteredItem(); | ||
module.remove.selectedItem(); | ||
$filteredItems | ||
$item | ||
.not($results) | ||
.addClass(className.filtered) | ||
; | ||
module.verbose('Selecting first non-filtered element'); | ||
module.remove.selectedItem(); | ||
$item | ||
@@ -412,4 +454,33 @@ .not('.' + className.filtered) | ||
; | ||
if( module.is.allFiltered() ) { | ||
module.debug('All items filtered, hiding dropdown', searchTerm); | ||
if(module.is.searchSelection()) { | ||
module.hide(); | ||
} | ||
settings.onNoResults.call(element, searchTerm); | ||
} | ||
}, | ||
focusSearch: function() { | ||
if( module.is.search() ) { | ||
$search | ||
.focus() | ||
; | ||
} | ||
}, | ||
forceSelection: function() { | ||
var | ||
$currentlySelected = $item.not(className.filtered).filter('.' + className.selected).eq(0), | ||
$activeItem = $item.filter('.' + className.active).eq(0), | ||
$selectedItem = ($currentlySelected.length > 0) | ||
? $currentlySelected | ||
: $activeItem, | ||
hasSelected = ($selectedItem.size() > 0) | ||
; | ||
if(hasSelected) { | ||
module.event.item.click.call($selectedItem); | ||
} | ||
}, | ||
event: { | ||
@@ -424,3 +495,3 @@ // prevents focus callback from occuring on mousedown | ||
focus: function() { | ||
if(!activated) { | ||
if(!activated && module.is.hidden()) { | ||
module.show(); | ||
@@ -430,3 +501,6 @@ } | ||
blur: function(event) { | ||
if(!activated) { | ||
var | ||
pageLostFocus = (document.activeElement === this) | ||
; | ||
if(!activated && !pageLostFocus) { | ||
module.hide(); | ||
@@ -440,69 +514,114 @@ } | ||
searchBlur: function(event) { | ||
if(!itemActivated) { | ||
module.hide(); | ||
var | ||
pageLostFocus = (document.activeElement === this) | ||
; | ||
if(!itemActivated && !pageLostFocus) { | ||
if(settings.forceSelection) { | ||
module.forceSelection(); | ||
} | ||
else { | ||
module.hide(); | ||
} | ||
} | ||
}, | ||
searchTextFocus: function(event) { | ||
activated = true; | ||
$search.focus(); | ||
}, | ||
input: function(event) { | ||
var | ||
query = $search.val() | ||
; | ||
if(module.is.searchSelection()) { | ||
$text.addClass(className.filtered); | ||
module.set.filtered(); | ||
} | ||
module.filter(query); | ||
clearTimeout(module.timer); | ||
module.timer = setTimeout(module.search, settings.delay.search); | ||
}, | ||
keydown: function(event) { | ||
var | ||
$selectedItem = $item.not(className.filtered).filter('.' + className.selected).eq(0), | ||
$visibleItems = $item.not('.' + className.filtered), | ||
$currentlySelected = $item.not(className.filtered).filter('.' + className.selected).eq(0), | ||
$activeItem = $menu.children('.' + className.active).eq(0), | ||
$selectedItem = ($currentlySelected.length > 0) | ||
? $currentlySelected | ||
: $activeItem, | ||
$visibleItems = ($selectedItem.length > 0) | ||
? $selectedItem.siblings(':not(.' + className.filtered +')').andSelf() | ||
: $menu.children(':not(.' + className.filtered +')'), | ||
$subMenu = $selectedItem.children(selector.menu), | ||
$parentMenu = $selectedItem.closest(selector.menu), | ||
isSubMenuItem = $parentMenu[0] !== $menu[0], | ||
inVisibleMenu = $parentMenu.is(':visible'), | ||
pressedKey = event.which, | ||
keys = { | ||
enter : 13, | ||
escape : 27, | ||
upArrow : 38, | ||
downArrow : 40 | ||
enter : 13, | ||
escape : 27, | ||
leftArrow : 37, | ||
upArrow : 38, | ||
rightArrow : 39, | ||
downArrow : 40 | ||
}, | ||
selectedClass = className.selected, | ||
currentIndex = $visibleItems.index( $selectedItem ), | ||
hasSelectedItem = ($selectedItem.size() > 0), | ||
hasSubMenu = ($subMenu.length> 0), | ||
hasSelectedItem = ($selectedItem.length > 0), | ||
lastVisibleIndex = ($visibleItems.size() - 1), | ||
$nextItem, | ||
newIndex | ||
; | ||
// default to activated choice if no selection present | ||
if(!hasSelectedItem) { | ||
$selectedItem = $item.filter('.' + className.active).eq(0); | ||
hasSelectedItem = ($selectedItem.size() > 0); | ||
} | ||
// close shortcuts | ||
if(pressedKey == keys.escape) { | ||
module.verbose('Escape key pressed, closing dropdown'); | ||
$search.blur(); | ||
module.hide(); | ||
} | ||
// result shortcuts | ||
// visible menu keyboard shortcuts | ||
if(module.is.visible()) { | ||
// enter (select or sub-menu) | ||
if(pressedKey == keys.enter && hasSelectedItem) { | ||
module.verbose('Enter key pressed, choosing selected item'); | ||
if(module.is.searchable()) { | ||
module.verbose('Removing focus from search input'); | ||
$search.blur(); | ||
if(hasSubMenu && !settings.allowCategorySelection) { | ||
module.verbose('Pressed enter on unselectable category, opening sub menu'); | ||
pressedKey = keys.rightArrow; | ||
} | ||
$.proxy(module.event.item.click, $selectedItem)(event); | ||
else { | ||
module.verbose('Enter key pressed, choosing selected item'); | ||
module.event.item.click.call($selectedItem, event); | ||
} | ||
} | ||
// left arrow (hide sub-menu) | ||
if(pressedKey == keys.leftArrow) { | ||
if(isSubMenuItem) { | ||
module.verbose('Left key pressed, closing sub-menu'); | ||
module.animate.hide(false, $parentMenu); | ||
$selectedItem | ||
.removeClass(className.selected) | ||
; | ||
$parentMenu | ||
.closest(selector.item) | ||
.addClass(className.selected) | ||
; | ||
} | ||
event.preventDefault(); | ||
return false; | ||
} | ||
else if(pressedKey == keys.upArrow) { | ||
if(!hasSelectedItem) { | ||
$nextItem = $visibleItems.eq(0); | ||
// right arrow (show sub-menu) | ||
if(pressedKey == keys.rightArrow) { | ||
if(hasSubMenu) { | ||
module.verbose('Right key pressed, opening sub-menu'); | ||
module.animate.show(false, $subMenu); | ||
$selectedItem | ||
.removeClass(className.selected) | ||
; | ||
$subMenu | ||
.find(selector.item).eq(0) | ||
.addClass(className.selected) | ||
; | ||
} | ||
event.preventDefault(); | ||
} | ||
// up arrow (traverse menu up) | ||
if(pressedKey == keys.upArrow) { | ||
$nextItem = (hasSelectedItem && inVisibleMenu) | ||
? $selectedItem.prevAll(selector.item + ':not(.' + className.filtered + ')').eq(0) | ||
: $item.eq(0) | ||
; | ||
if($visibleItems.index( $nextItem ) < 0) { | ||
module.verbose('Up key pressed but reached top of current menu'); | ||
return; | ||
} | ||
else { | ||
$nextItem = $selectedItem.prevAll(selector.item + ':not(.' + className.filtered + ')').eq(0); | ||
} | ||
if(currentIndex !== 0) { | ||
module.verbose('Up key pressed, changing active item'); | ||
$item | ||
.removeClass(selectedClass) | ||
$selectedItem | ||
.removeClass(className.selected) | ||
; | ||
$nextItem | ||
.addClass(selectedClass) | ||
.addClass(className.selected) | ||
; | ||
@@ -513,16 +632,19 @@ module.set.scrollPosition($nextItem); | ||
} | ||
else if(pressedKey == keys.downArrow) { | ||
if(!hasSelectedItem) { | ||
$nextItem = $visibleItems.eq(0); | ||
// down arrow (traverse menu down) | ||
if(pressedKey == keys.downArrow) { | ||
$nextItem = (hasSelectedItem && inVisibleMenu) | ||
? $nextItem = $selectedItem.nextAll(selector.item + ':not(.' + className.filtered + ')').eq(0) | ||
: $item.eq(0) | ||
; | ||
if($nextItem.length === 0) { | ||
module.verbose('Down key pressed but reached bottom of current menu'); | ||
return; | ||
} | ||
else { | ||
$nextItem = $selectedItem.nextAll(selector.item + ':not(.' + className.filtered + ')').eq(0); | ||
} | ||
if(currentIndex + 1 < $visibleItems.size() ) { | ||
module.verbose('Down key pressed, changing active item'); | ||
$item | ||
.removeClass(selectedClass) | ||
.removeClass(className.selected) | ||
; | ||
$nextItem | ||
.addClass(selectedClass) | ||
.addClass(className.selected) | ||
; | ||
@@ -535,5 +657,17 @@ module.set.scrollPosition($nextItem); | ||
else { | ||
// enter (open menu) | ||
if(pressedKey == keys.enter) { | ||
module.verbose('Enter key pressed, showing dropdown'); | ||
module.show(); | ||
} | ||
// escape (close menu) | ||
if(pressedKey == keys.escape) { | ||
module.verbose('Escape key pressed, closing dropdown'); | ||
module.hide(); | ||
} | ||
// down arrow (open menu) | ||
if(pressedKey == keys.downArrow) { | ||
module.verbose('Down key pressed, showing dropdown'); | ||
module.show(); | ||
} | ||
} | ||
@@ -563,75 +697,64 @@ }, | ||
item: { | ||
mousedown: function() { | ||
menu: { | ||
activate: function() { | ||
itemActivated = true; | ||
}, | ||
mouseup: function() { | ||
deactivate: function() { | ||
itemActivated = false; | ||
}, | ||
} | ||
}, | ||
item: { | ||
mouseenter: function(event) { | ||
var | ||
$currentMenu = $(this).find(selector.menu), | ||
$otherMenus = $(this).siblings(selector.item).children(selector.menu) | ||
$subMenu = $(this).children(selector.menu), | ||
$otherMenus = $(this).siblings(selector.item).children(selector.menu) | ||
; | ||
if( $currentMenu.size() > 0 ) { | ||
if( $subMenu.length > 0 ) { | ||
clearTimeout(module.itemTimer); | ||
module.itemTimer = setTimeout(function() { | ||
module.animate.hide(false, $otherMenus); | ||
module.verbose('Showing sub-menu', $currentMenu); | ||
module.animate.show(false, $currentMenu); | ||
}, settings.delay.show * 2); | ||
module.verbose('Showing sub-menu', $subMenu); | ||
$.each($otherMenus, function() { | ||
module.animate.hide(false, $(this)); | ||
}); | ||
module.animate.show(false, $subMenu); | ||
}, settings.delay.show); | ||
event.preventDefault(); | ||
} | ||
}, | ||
mouseleave: function(event) { | ||
var | ||
$currentMenu = $(this).find(selector.menu) | ||
$subMenu = $(this).children(selector.menu) | ||
; | ||
if($currentMenu.size() > 0) { | ||
if($subMenu.length > 0) { | ||
clearTimeout(module.itemTimer); | ||
module.itemTimer = setTimeout(function() { | ||
module.verbose('Hiding sub-menu', $currentMenu); | ||
module.animate.hide(false, $currentMenu); | ||
module.verbose('Hiding sub-menu', $subMenu); | ||
module.animate.hide(false, $subMenu); | ||
}, settings.delay.hide); | ||
} | ||
}, | ||
click: function (event) { | ||
var | ||
$choice = $(this), | ||
text = ( $choice.data(metadata.text) !== undefined ) | ||
? $choice.data(metadata.text) | ||
: (settings.preserveHTML) | ||
? $choice.html() | ||
: $choice.text(), | ||
value = ( $choice.data(metadata.value) !== undefined) | ||
? $choice.data(metadata.value) | ||
: (typeof text === 'string') | ||
? text.toLowerCase() | ||
: text, | ||
$choice = $(this), | ||
$target = (event) | ||
? $(event.target) | ||
: $(''), | ||
$subMenu = $choice.find(selector.menu), | ||
text = module.get.choiceText($choice), | ||
value = module.get.choiceValue($choice, text), | ||
callback = function() { | ||
$search.val(''); | ||
module.remove.searchTerm(); | ||
module.determine.selectAction(text, value); | ||
$.proxy(settings.onChange, element)(value, text, $choice); | ||
}, | ||
openingSubMenu = ($choice.find(selector.menu).size() > 0) | ||
hasSubMenu = ($subMenu.length > 0), | ||
isBubbledEvent = ($subMenu.find($target).length > 0) | ||
; | ||
if( !openingSubMenu ) { | ||
if(event.type == 'touchstart') { | ||
$choice.one('click', callback); | ||
} | ||
else { | ||
callback(); | ||
} | ||
if(!isBubbledEvent && (!hasSubMenu || settings.allowCategorySelection)) { | ||
callback(); | ||
} | ||
} | ||
}, | ||
resetStyle: function() { | ||
$(this).removeAttr('style'); | ||
} | ||
}, | ||
@@ -655,4 +778,7 @@ | ||
eventInModule: function(event, callback) { | ||
callback = callback || function(){}; | ||
if( $(event.target).closest($module).size() === 0 ) { | ||
callback = $.isFunction(callback) | ||
? callback | ||
: function(){} | ||
; | ||
if( $(event.target).closest($module).length === 0 ) { | ||
module.verbose('Triggering event', callback); | ||
@@ -668,4 +794,7 @@ callback(); | ||
eventInMenu: function(event, callback) { | ||
callback = callback || function(){}; | ||
if( $(event.target).closest($menu).size() === 0 ) { | ||
callback = $.isFunction(callback) | ||
? callback | ||
: function(){} | ||
; | ||
if( $(event.target).closest($menu).length === 0 ) { | ||
module.verbose('Triggering event', callback); | ||
@@ -686,7 +815,3 @@ callback(); | ||
hide: function() { | ||
module.hide(); | ||
}, | ||
select: function(text, value) { | ||
activate: function(text, value) { | ||
value = (value !== undefined) | ||
@@ -697,7 +822,8 @@ ? value | ||
module.set.selected(value); | ||
module.set.value(value); | ||
module.hide(); | ||
module.hide(function() { | ||
module.remove.filteredItem(); | ||
}); | ||
}, | ||
activate: function(text, value) { | ||
select: function(text, value) { | ||
value = (value !== undefined) | ||
@@ -708,4 +834,5 @@ ? value | ||
module.set.selected(value); | ||
module.set.value(value); | ||
module.hide(); | ||
module.hide(function() { | ||
module.remove.filteredItem(); | ||
}); | ||
}, | ||
@@ -719,4 +846,11 @@ | ||
module.set.selected(value); | ||
module.set.value(value); | ||
module.hide(); | ||
module.hide(function() { | ||
module.remove.filteredItem(); | ||
}); | ||
}, | ||
hide: function() { | ||
module.hide(function() { | ||
module.remove.filteredItem(); | ||
}); | ||
} | ||
@@ -731,3 +865,3 @@ | ||
value: function() { | ||
return ($input.size() > 0) | ||
return ($input.length > 0) | ||
? $input.val() | ||
@@ -737,2 +871,31 @@ : $module.data(metadata.value) | ||
}, | ||
choiceText: function($choice, preserveHTML) { | ||
preserveHTML = (preserveHTML !== undefined) | ||
? preserveHTML | ||
: settings.preserveHTML | ||
; | ||
if($choice !== undefined) { | ||
if($choice.find(selector.menu).length > 0) { | ||
module.verbose('Retreiving text of element with sub-menu'); | ||
$choice = $choice.clone(); | ||
$choice.find(selector.menu).remove(); | ||
$choice.find(selector.menuIcon).remove(); | ||
} | ||
return ($choice.data(metadata.text) !== undefined) | ||
? $choice.data(metadata.text) | ||
: (preserveHTML) | ||
? $choice.html().trim() | ||
: $choice.text().trim() | ||
; | ||
} | ||
}, | ||
choiceValue: function($choice, choiceText) { | ||
choiceText = choiceText || module.get.choiceText($choice); | ||
return ($choice.data(metadata.value) !== undefined) | ||
? $choice.data(metadata.value) | ||
: (typeof choiceText === 'string') | ||
? choiceText.toLowerCase().trim() | ||
: choiceText.trim() | ||
; | ||
}, | ||
inputEvent: function() { | ||
@@ -754,6 +917,8 @@ var | ||
var | ||
select = { | ||
values : {} | ||
} | ||
select = {} | ||
; | ||
select.values = (settings.sortSelect) | ||
? {} // properties will be sorted in object when re-accessed | ||
: [] // properties will keep original order in array | ||
; | ||
$module | ||
@@ -772,9 +937,28 @@ .find('option') | ||
else { | ||
select.values[value] = name; | ||
if(settings.sortSelect) { | ||
select.values[value] = { | ||
name : name, | ||
value : value | ||
}; | ||
} | ||
else { | ||
select.values.push({ | ||
name: name, | ||
value: value | ||
}); | ||
} | ||
} | ||
}) | ||
; | ||
module.debug('Retrieved values from select', select); | ||
if(settings.sortSelect) { | ||
module.debug('Retrieved and sorted values from select', select); | ||
} | ||
else { | ||
module.debug('Retreived values from select', select); | ||
} | ||
return select; | ||
}, | ||
activeItem: function() { | ||
return $item.filter('.' + className.active); | ||
}, | ||
item: function(value, strict) { | ||
@@ -799,15 +983,7 @@ var | ||
$choice = $(this), | ||
optionText = ( $choice.data(metadata.text) !== undefined ) | ||
? $choice.data(metadata.text) | ||
: (settings.preserveHTML) | ||
? $choice.html() | ||
: $choice.text(), | ||
optionValue = ( $choice.data(metadata.value) !== undefined ) | ||
? $choice.data(metadata.value) | ||
: (typeof optionText === 'string') | ||
? optionText.toLowerCase() | ||
: optionText | ||
optionText = module.get.choiceText($choice), | ||
optionValue = module.get.choiceValue($choice, optionText) | ||
; | ||
if(strict) { | ||
module.debug('Ambiguous dropdown value using strict type check', value); | ||
module.verbose('Ambiguous dropdown value using strict type check', $choice, value); | ||
if( optionValue === value ) { | ||
@@ -837,2 +1013,5 @@ $selectedItem = $(this); | ||
return $selectedItem || false; | ||
}, | ||
uniqueID: function() { | ||
return (Math.random().toString(16) + '000000000').substr(2,8); | ||
} | ||
@@ -852,2 +1031,3 @@ }, | ||
module.set.text(defaultText); | ||
$text.addClass(className.placeholder); | ||
}, | ||
@@ -860,4 +1040,9 @@ defaultValue: function() { | ||
module.debug('Restoring default value', defaultValue); | ||
module.set.selected(defaultValue); | ||
module.set.value(defaultValue); | ||
if(defaultValue.length) { | ||
module.set.selected(defaultValue); | ||
} | ||
else { | ||
module.remove.activeItem(); | ||
module.remove.selectedItem(); | ||
} | ||
} | ||
@@ -870,2 +1055,3 @@ } | ||
module.save.defaultText(); | ||
module.save.placeholderText(); | ||
module.save.defaultValue(); | ||
@@ -878,11 +1064,61 @@ }, | ||
$module.data(metadata.defaultText, $text.text() ); | ||
}, | ||
placeholderText: function() { | ||
if($text.hasClass(className.placeholder)) { | ||
$module.data(metadata.placeholderText, $text.text()); | ||
} | ||
} | ||
}, | ||
clear: function() { | ||
var | ||
placeholderText = $module.data(metadata.placeholderText) | ||
; | ||
module.set.text(placeholderText); | ||
module.set.value(''); | ||
module.remove.activeItem(); | ||
module.remove.selectedItem(); | ||
$text.addClass(className.placeholder); | ||
}, | ||
set: { | ||
scrollPosition: function($item) { | ||
filtered: function() { | ||
var | ||
$item = $item || module.get.item(), | ||
hasActive = ($item && $item.size() > 0), | ||
searchValue = $search.val(), | ||
hasSearchValue = (typeof searchValue === 'string' && searchValue.length > 0) | ||
; | ||
if(hasSearchValue) { | ||
$text.addClass(className.filtered); | ||
} | ||
else { | ||
$text.removeClass(className.filtered); | ||
} | ||
}, | ||
tabbable: function() { | ||
if( module.is.searchable() ) { | ||
module.debug('Searchable dropdown initialized'); | ||
$search | ||
.val('') | ||
.attr('tabindex', 0) | ||
; | ||
$menu | ||
.attr('tabindex', '-1') | ||
; | ||
} | ||
else { | ||
module.debug('Simple selection dropdown initialized'); | ||
if(!$module.attr('tabindex') ) { | ||
$module | ||
.attr('tabindex', 0) | ||
; | ||
$menu | ||
.attr('tabindex', '-1') | ||
; | ||
} | ||
} | ||
}, | ||
scrollPosition: function($item, forceScroll) { | ||
var | ||
edgeTolerance = 5, | ||
hasActive, | ||
offset, | ||
@@ -897,3 +1133,16 @@ itemHeight, | ||
; | ||
$item = $item || module.get.activeItem(); | ||
hasActive = ($item && $item.length > 0); | ||
forceScroll = (forceScroll !== undefined) | ||
? forceScroll | ||
: false | ||
; | ||
if($item && hasActive) { | ||
if(!$menu.hasClass(className.visible)) { | ||
$menu.addClass(className.loading); | ||
} | ||
menuHeight = $menu.height(); | ||
@@ -907,6 +1156,7 @@ itemHeight = $item.height(); | ||
abovePage = ((offset - edgeTolerance) < menuScroll); | ||
if(abovePage || belowPage) { | ||
module.debug('Scrolling to active item'); | ||
module.debug('Scrolling to active item', offset); | ||
if(abovePage || belowPage || forceScroll) { | ||
$menu | ||
.scrollTop(offset) | ||
.removeClass(className.loading) | ||
; | ||
@@ -942,3 +1192,3 @@ } | ||
module.debug('Adding selected value to hidden input', value, $input); | ||
if($input.size() > 0) { | ||
if($input.length > 0) { | ||
$input | ||
@@ -964,12 +1214,7 @@ .val(value) | ||
$selectedItem = module.get.item(value), | ||
selectedText | ||
selectedText, | ||
selectedValue | ||
; | ||
if($selectedItem) { | ||
module.debug('Setting selected menu item to', $selectedItem); | ||
selectedText = ($selectedItem.data(metadata.text) !== undefined) | ||
? $selectedItem.data(metadata.text) | ||
: (settings.preserveHTML) | ||
? $selectedItem.html() | ||
: $selectedItem.text() | ||
; | ||
module.remove.activeItem(); | ||
@@ -981,3 +1226,7 @@ module.remove.selectedItem(); | ||
; | ||
selectedText = module.get.choiceText($selectedItem); | ||
selectedValue = module.get.choiceValue($selectedItem, selectedText); | ||
module.set.text(selectedText); | ||
module.set.value(selectedValue); | ||
settings.onChange.call(element, value, selectedText, $selectedItem); | ||
} | ||
@@ -1000,4 +1249,27 @@ } | ||
}, | ||
searchTerm: function() { | ||
$search.val(''); | ||
}, | ||
selectedItem: function() { | ||
$item.removeClass(className.selected); | ||
}, | ||
tabbable: function() { | ||
if( module.is.searchable() ) { | ||
module.debug('Searchable dropdown initialized'); | ||
$search | ||
.attr('tabindex', '-1') | ||
; | ||
$menu | ||
.attr('tabindex', '-1') | ||
; | ||
} | ||
else { | ||
module.debug('Simple selection dropdown initialized'); | ||
$module | ||
.attr('tabindex', '-1') | ||
; | ||
$menu | ||
.attr('tabindex', '-1') | ||
; | ||
} | ||
} | ||
@@ -1007,2 +1279,35 @@ }, | ||
is: { | ||
active: function() { | ||
return $module.hasClass(className.active); | ||
}, | ||
alreadySetup: function() { | ||
return ($module.is('select') && $module.parent(selector.dropdown).length > 0); | ||
}, | ||
animating: function($subMenu) { | ||
return ($subMenu) | ||
? $subMenu.is(':animated') || $subMenu.transition && $subMenu.transition('is animating') | ||
: $menu.is(':animated') || $menu.transition && $menu.transition('is animating') | ||
; | ||
}, | ||
allFiltered: function() { | ||
return ($item.filter('.' + className.filtered).length === $item.length); | ||
}, | ||
hidden: function($subMenu) { | ||
return ($subMenu) | ||
? $subMenu.is(':hidden') | ||
: $menu.is(':hidden') | ||
; | ||
}, | ||
selectMutation: function(mutations) { | ||
var | ||
selectChanged = false | ||
; | ||
$.each(mutations, function(index, mutation) { | ||
if(mutation.target && $(mutation.target).is('select')) { | ||
selectChanged = true; | ||
return true; | ||
} | ||
}); | ||
return selectChanged; | ||
}, | ||
search: function() { | ||
@@ -1012,3 +1317,3 @@ return $module.hasClass(className.search); | ||
searchable: function() { | ||
return ($search.size() > 0); | ||
return ($search.length > 0); | ||
}, | ||
@@ -1021,11 +1326,5 @@ searchSelection: function() { | ||
}, | ||
animated: function($subMenu) { | ||
return ($subMenu) | ||
? $subMenu.is(':animated') || $subMenu.transition && $subMenu.transition('is animating') | ||
: $menu.is(':animated') || $menu.transition && $menu.transition('is animating') | ||
; | ||
upward: function() { | ||
return $module.hasClass(className.upward); | ||
}, | ||
active: function() { | ||
return $module.hasClass(className.active); | ||
}, | ||
visible: function($subMenu) { | ||
@@ -1036,8 +1335,2 @@ return ($subMenu) | ||
; | ||
}, | ||
hidden: function($subMenu) { | ||
return ($subMenu) | ||
? $subMenu.is(':hidden') | ||
: $menu.is(':hidden') | ||
; | ||
} | ||
@@ -1062,12 +1355,24 @@ }, | ||
: function() { | ||
module.hideSubMenus(); | ||
module.hideOthers(); | ||
module.set.active(); | ||
module.set.scrollPosition(); | ||
} | ||
; | ||
callback = callback || function(){}; | ||
callback = $.isFunction(callback) | ||
? callback | ||
: function(){} | ||
; | ||
module.set.scrollPosition(module.get.activeItem(), true); | ||
module.verbose('Doing menu show animation', $currentMenu); | ||
if( module.is.hidden($currentMenu) ) { | ||
if( module.is.hidden($currentMenu) || module.is.animating($currentMenu) ) { | ||
if(settings.transition == 'auto') { | ||
settings.transition = module.is.upward() | ||
? 'slide up' | ||
: 'slide down' | ||
; | ||
module.verbose('Automatically determining animation based on animation direction', settings.transition); | ||
} | ||
if(settings.transition == 'none') { | ||
$.proxy(callback, element)(); | ||
callback.call(element); | ||
} | ||
@@ -1077,8 +1382,10 @@ else if($.fn.transition !== undefined && $module.transition('is supported')) { | ||
.transition({ | ||
animation : settings.transition + ' in', | ||
duration : settings.duration, | ||
queue : true, | ||
start : start, | ||
complete : function() { | ||
$.proxy(callback, element)(); | ||
animation : settings.transition + ' in', | ||
debug : settings.debug, | ||
verbose : settings.verbose, | ||
duration : settings.duration, | ||
queue : true, | ||
onStart : start, | ||
onComplete : function() { | ||
callback.call(element); | ||
} | ||
@@ -1102,4 +1409,4 @@ }) | ||
.slideDown(100, 'easeOutQuad', function() { | ||
$.proxy(module.event.resetStyle, this)(); | ||
$.proxy(callback, element)(); | ||
module.event.resetStyle.call(this); | ||
callback.call(element); | ||
}) | ||
@@ -1114,4 +1421,4 @@ ; | ||
.fadeIn(settings.duration, function() { | ||
$.proxy(module.event.resetStyle, this)(); | ||
$.proxy(callback, element)(); | ||
module.event.resetStyle.call(this); | ||
callback.call(element); | ||
}) | ||
@@ -1128,2 +1435,5 @@ ; | ||
$currentMenu = $subMenu || $menu, | ||
duration = ($subMenu) | ||
? (settings.duration * 0.9) | ||
: settings.duration, | ||
start = ($subMenu) | ||
@@ -1135,12 +1445,24 @@ ? function() {} | ||
} | ||
module.hideSubMenus(); | ||
module.focusSearch(); | ||
module.remove.active(); | ||
} | ||
; | ||
callback = callback || function(){}; | ||
if( module.is.visible($currentMenu) ) { | ||
callback = $.isFunction(callback) | ||
? callback | ||
: function(){} | ||
; | ||
if( module.is.visible($currentMenu) || module.is.animating($currentMenu) ) { | ||
module.verbose('Doing menu hide animation', $currentMenu); | ||
if(settings.transition == 'auto') { | ||
settings.transition = module.is.upward() | ||
? 'slide up' | ||
: 'slide down' | ||
; | ||
} | ||
$input.trigger('blur'); | ||
if(settings.transition == 'none') { | ||
$.proxy(callback, element)(); | ||
callback.call(element); | ||
} | ||
@@ -1150,8 +1472,10 @@ else if($.fn.transition !== undefined && $module.transition('is supported')) { | ||
.transition({ | ||
animation : settings.transition + ' out', | ||
duration : settings.duration, | ||
queue : true, | ||
start : start, | ||
complete : function() { | ||
$.proxy(callback, element)(); | ||
animation : settings.transition + ' out', | ||
duration : settings.duration, | ||
debug : settings.debug, | ||
verbose : settings.verbose, | ||
queue : true, | ||
onStart : start, | ||
onComplete : function() { | ||
callback.call(element); | ||
} | ||
@@ -1175,4 +1499,4 @@ }) | ||
.slideUp(100, 'easeOutQuad', function() { | ||
$.proxy(module.event.resetStyle, this)(); | ||
$.proxy(callback, element)(); | ||
module.event.resetStyle.call(this); | ||
callback.call(element); | ||
}) | ||
@@ -1187,4 +1511,4 @@ ; | ||
.fadeOut(150, function() { | ||
$.proxy(module.event.resetStyle, this)(); | ||
$.proxy(callback, element)(); | ||
module.event.resetStyle.call(this); | ||
callback.call(element); | ||
}) | ||
@@ -1213,2 +1537,9 @@ ; | ||
escape: { | ||
regExp: function(text) { | ||
text = String(text); | ||
return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); | ||
} | ||
}, | ||
setting: function(name, value) { | ||
@@ -1378,3 +1709,3 @@ module.debug('Changing setting', name, value); | ||
if(instance !== undefined) { | ||
module.destroy(); | ||
instance.invoke('destroy'); | ||
} | ||
@@ -1394,28 +1725,34 @@ module.initialize(); | ||
debug : false, | ||
verbose : true, | ||
performance : true, | ||
debug : false, | ||
verbose : true, | ||
performance : true, | ||
on : 'click', | ||
action : 'activate', | ||
on : 'click', | ||
action : 'activate', | ||
allowTab : true, | ||
fullTextSearch : true, | ||
preserveHTML : true, | ||
allowTab : true, | ||
fullTextSearch : false, | ||
preserveHTML : true, | ||
sortSelect : false, | ||
delay : { | ||
show : 200, | ||
hide : 300, | ||
touch : 50 | ||
allowCategorySelection : false, | ||
delay : { | ||
hide : 300, | ||
show : 200, | ||
search : 50, | ||
touch : 50 | ||
}, | ||
transition : 'slide down', | ||
forceSelection: true, | ||
transition : 'auto', | ||
duration : 250, | ||
/* Callbacks */ | ||
onNoResults : function(searchTerm){}, | ||
onChange : function(value, text){}, | ||
onShow : function(){}, | ||
onHide : function(){}, | ||
onChange : function(value, text){}, | ||
onShow : function(){}, | ||
onHide : function(){}, | ||
/* Component */ | ||
@@ -1427,12 +1764,14 @@ | ||
error : { | ||
action : 'You called a dropdown action that was not defined', | ||
method : 'The method you called is not defined.', | ||
transition : 'The requested transition was not found' | ||
action : 'You called a dropdown action that was not defined', | ||
alreadySetup : 'Once a select has been initialized behaviors must be called on the created ui dropdown', | ||
method : 'The method you called is not defined.', | ||
transition : 'The requested transition was not found' | ||
}, | ||
metadata: { | ||
defaultText : 'defaultText', | ||
defaultValue : 'defaultValue', | ||
text : 'text', | ||
value : 'value' | ||
defaultText : 'defaultText', | ||
defaultValue : 'defaultValue', | ||
placeholderText : 'placeholderText', | ||
text : 'text', | ||
value : 'value' | ||
}, | ||
@@ -1442,7 +1781,8 @@ | ||
dropdown : '.ui.dropdown', | ||
text : '> .text:not(.icon)', | ||
input : '> input[type="hidden"], > select', | ||
search : '> .search, .menu > .search > input, .menu > input.search', | ||
item : '.item', | ||
menu : '.menu', | ||
item : '.item' | ||
menuIcon : '.dropdown.icon', | ||
search : '> input.search, .menu > .search > input, .menu > input.search', | ||
text : '> .text:not(.icon)' | ||
}, | ||
@@ -1456,2 +1796,3 @@ | ||
filtered : 'filtered', | ||
loading : 'loading', | ||
menu : 'menu', | ||
@@ -1462,2 +1803,3 @@ placeholder : 'default', | ||
selection : 'selection', | ||
upward : 'upward', | ||
visible : 'visible' | ||
@@ -1476,9 +1818,4 @@ } | ||
; | ||
$.each(select.values, function(value, name) { | ||
if(value === name) { | ||
html += '<div class="item">' + name + '</div>'; | ||
} | ||
else { | ||
html += '<div class="item" data-value="' + value + '">' + name + '</div>'; | ||
} | ||
$.each(select.values, function(index, option) { | ||
html += '<div class="item" data-value="' + option.value + '">' + option.name + '</div>'; | ||
}); | ||
@@ -1501,9 +1838,4 @@ return html; | ||
html += '<div class="menu">'; | ||
$.each(select.values, function(value, name) { | ||
if(value === name) { | ||
html += '<div class="item">' + name + '</div>'; | ||
} | ||
else { | ||
html += '<div class="item" data-value="' + value + '">' + name + '</div>'; | ||
} | ||
$.each(select.values, function(index, option) { | ||
html += '<div class="item" data-value="' + option.value + '">' + option.name + '</div>'; | ||
}); | ||
@@ -1524,2 +1856,2 @@ html += '</div>'; | ||
})( require("jquery"), window , document ); | ||
})( require("jquery"), window , document ); |
{ | ||
"name": "semantic-ui-dropdown", | ||
"version": "1.0.0", | ||
"version": "1.9.0", | ||
"title": "Semantic UI - Dropdown", | ||
@@ -11,3 +11,3 @@ "description": "Single component release of dropdown", | ||
"type": "git", | ||
"url": "git@github.com:Semantic-Org/UI-Dropdown.git" | ||
"url": "https://github.com/Semantic-Org/UI-Dropdown.git" | ||
}, | ||
@@ -17,7 +17,3 @@ "bugs": { | ||
}, | ||
"dependencies": { | ||
"jquery": "x.x.x" | ||
}, | ||
"devDependencies": {}, | ||
"main": "index.js" | ||
"devDependencies": {} | ||
} |
@@ -19,6 +19,12 @@ # Semantic Dropdown | ||
#### To install with Meteor | ||
``` | ||
meteor add semantic:ui-dropdown | ||
``` | ||
## Addendum | ||
This element's definitions (required class names, html structures) are available in the [Beta UI Docs](http://beta.semantic-ui.com) | ||
This element's definitions (required class names, html structures) are available in the [UI Docs](http://www.semantic-ui.com) | ||
Please consider checking out [all the benefits to theming](http://learnsemantic.com/guide/expert.html) before using these stand-alone releases. | ||
Please consider checking out [all the benefits to theming](http://www.learnsemantic.com/guide/expert.html) before using these stand-alone releases. |
@@ -1,3 +0,82 @@ | ||
### Version 1.0.0 - XX XX, 2014 | ||
### UI Changes | ||
- **Input** - Input with dropdowns is now much easier, see docs. `action input` and `labeled input` now use `display: flex`. `ui action input` now supports `<button>` tag usage (!) which support `flex` but not `table-cell` | ||
- **Dropdown** - `search selection dropdown` will now close the menu when a `dropdown icon` is clicked | ||
- **Dropdown** - Added new dropdown setting, `forceSelection` which forces `search selection` to a selected value on blur. Defaults to `true`. | ||
- **Form Validation** - Dropdown and checkbox will now validate after interaction with `on: 'blur'` | ||
- **Form** - Lightened error dropdown hover text color to be more legible | ||
- **Dropdown** - Upward dropdown now has upward arrow icon | ||
### Version 1.8.1 - January 26, 2015 | ||
- **Input** - `ui labeled input` now uses `flex` added example in ui docs with dropdown | ||
### Version 1.8.0 - January 23, 2015 | ||
- **Dropdown** - Dropdown now stores `placeholder text` (prompt text) as separate from `default text` (text set on page load). You can now reset placeholder conditions using `$('.ui.dropdown').dropdown('clear');`` | ||
- **Dropdown** - Keyboard navigation will now allow opening of sub menus with right/left arrow. Enter will open sub-menus on an unselectable category (`allowCategorySelection: false`) as well. | ||
- **Dropdown** - Mutation observers will now observe changed in `<select>` values after initialization, and will automatically update dropdown menu when changed | ||
- **Dropdown** - Dropdown behavior `set selected` will now also call `set value` automatically, so you do not have to invoke two behaviors to update a `selection dropdown` **Thanks @mktm** | ||
- **Dropdown** - Dropdown no longer will not show menu when no `item` are present in menu. Dropdown will now only filter results for `ui search dropdown` #1632 **Thanks PSyton**. | ||
- **Dropdown** - Dropdown will now produce an error if behaviors on an initialized `<select>` are not invoked on `ui dropdown` | ||
- **Dropdown** - Fixed bug where link items would not open in sub-menus due to `event.preventDefault` | ||
- **Label** - Fixed `ui corner label` appearing on-top of `ui dropdown` menu due to issue in z-index heirarchy | ||
### Version 1.7.0 - January 14, 2015 | ||
- **Dropdown** - Javascript Dropdown can now be disabled by adding ``disabled` class. No need to call `destroy`. **Thanks Psyton** | ||
- **Dropdown** - Search dropdown input can now have backgrounds. Fixes issues with autocompleted search dropdowns which have forced yellow "autocompleted" bg. | ||
- **Dropdown** - Fix issue with search selection not correctly matching when values are not strings | ||
- **Dropdown** - New `upward dropdown` variation, which opens its menu upward. Default animation now uses ``settings.transition = 'auto'` and determines direction of animation based on menu direction | ||
- **Dropdown** - Dropdown matching fields without values now trims whitespace by default | ||
- **Dropdown** - `restore defaults` will now set placeholder styling and remove active elemenet. Added example in docs. | ||
- **Dropdown** - Fixed bug where sub menus may sometimes have dropdown icon overlap text | ||
- **Dropdown** - Fixes dropdown search input from filtering text values when input is inside menu, i.e "In-Menu Search" | ||
- **Dropdown** - Fix issue with search selection not correctly creating RegExp when select values are not strings **Thanks @alufers** | ||
- **Dropdown** - Fix issue with `left floated` and `right floated` content sometimes not applying correctly | ||
### Version 1.6.0 - January 05, 2015 | ||
- **Form** - ``ui search dropdown`` inside a form has incorrect focus style | ||
### Version 1.5.0 - December 30, 2014 | ||
- **Dropdown** - New setting ``allowCategorySelection`` lets menu items with sub menus be selected. Added example in docs. | ||
- **Dropdown/Search** - Fixed issues with ``ui search`` and ``ui search dropdown`` using ``RegExp test`` which [advances pointer on match](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test) causing results to display incorrectly | ||
### Version 1.4.1 - December 23, 2014 | ||
- **Dropdown** - ``<select>`` elements will now preserve original ``<option>`` order by default. Added ``sortSelect`` setting (disabled by default) to automatically sort ``<option>`` on initialization | ||
- **Button** - Fixes issue with ``will-change`` property added to ``ui button`` causing layout z-indexing issues (dropdown button) | ||
### Version 1.4.0 - December 22, 2014 | ||
- **Menu** - Fix border radius of dropdown menu inside `ui vertical menu` | ||
- **Menu** - Fix formatting of ``ui selection dropdown`` inside ``menu`` | ||
### Version 1.3.0 - December 17, 2014 | ||
- **Dropdown** - Dropdown can now specify which direction a menu should appear left/right, dropdown icons can also appear on the left | ||
- **Dropdown** - Full text search now defaults to ``false``, meaning search terms will return only results beginning with letters | ||
- **Dropdown** - Search Dropdown is now much more responsive, js improvements and input throttling added.Throttling defaults to `50ms` and can be modified with settings ``delay.search`` | ||
- **Dropdown** - Search Dropdown now correctly replaces placeholder text when backspacing to empty value | ||
- **Dropdown** - Search Dropdown now has a callback when all results filtered ``onNoResults`` | ||
- **Dropdown** - Search dropdown will now strip html before searching values when searching html | ||
- **Dropdown** - Search now has keyboard shortcut to open dropdown on arrow down | ||
- **Dropdown** - Dropdown now always scrolls to active element on menu open, calculates position with new ``loading`` class | ||
- **Dropdown** - Fix bug in position of sub menus with ``floating dropdown`` | ||
- **All UI** - Adds error message when triggering an invalid module behavior i.e. typos ``$('.dropdown').dropdown('hid');`` | ||
### Version 1.2.0 - December 08, 2014 | ||
- **Dropdown** - Fixes bug with dropdown converted from ``select`` that use ``<option`` values with capital letters not being selectable | ||
- Fixed documentation on dropdown actions, form field widths, form validation types, and many odds & ends | ||
### Version 1.1.0 - December 02, 2014 | ||
- **Dropdown** - Dropdown ``onChange`` callback now fires when calling ``setSelected`` programatically. | ||
- **Dropdown** - Fix ``action input`` used inside ``ui dropdown`` to appear correctly **Thanks ordepdev** | ||
### Version 1.0.0 - November 24, 2014 | ||
- **Dropdown** - Sub menus inside dropdowns now need a wrapping div **text** around sub-menu descriptions | ||
@@ -10,2 +89,14 @@ - **Dropdown** - New dropdown type, searchable selection for large lists of choices | ||
### Version 0.18.0 - June 6, 2014 | ||
- **Dropdown** - Fixes dropdown 'is animating' with dropdowns when CSS animations were not included **Thanks nathankot** | ||
### Version 0.17.0 - May 9, 2014 | ||
- **Dropdown** - Dropdowns can now receive focus and be navigated with a keyboard **Thanks Musatov** | ||
### Version 0.15.1 - Mar 14, 2014 | ||
- **Dropdown** - Typo in dropdown css was causing selection dropdowns not to appear | ||
### Version 0.15.0 - Mar 14, 2014 | ||
@@ -12,0 +103,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Wildcard dependency
QualityPackage has a dependency with a floating version range. This can cause issues if the dependency publishes a new major version.
Found 1 instance in 1 package
200790
27.8%0
-100%11
10%4430
23.4%0
-100%30
25%1
Infinity%- Removed
- Removed