http://git-wip-us.apache.org/repos/asf/incubator-senssoft/blob/6a2b3459/semantic/dist/components/dropdown.js ---------------------------------------------------------------------- diff --git a/semantic/dist/components/dropdown.js b/semantic/dist/components/dropdown.js deleted file mode 100644 index 9c0983c..0000000 --- a/semantic/dist/components/dropdown.js +++ /dev/null @@ -1,3741 +0,0 @@ -/*! - * # Semantic UI 2.2.6 - Dropdown - * http://github.com/semantic-org/semantic-ui/ - * - * - * Released under the MIT license - * http://opensource.org/licenses/MIT - * - */ - -;(function ($, window, document, undefined) { - -"use strict"; - -window = (typeof window != 'undefined' && window.Math == Math) - ? window - : (typeof self != 'undefined' && self.Math == Math) - ? self - : Function('return this')() -; - -$.fn.dropdown = function(parameters) { - var - $allModules = $(this), - $document = $(document), - - moduleSelector = $allModules.selector || '', - - hasTouch = ('ontouchstart' in document.documentElement), - time = new Date().getTime(), - performance = [], - - query = arguments[0], - methodInvoked = (typeof query == 'string'), - queryArguments = [].slice.call(arguments, 1), - returnedValue - ; - - $allModules - .each(function(elementIndex) { - var - settings = ( $.isPlainObject(parameters) ) - ? $.extend(true, {}, $.fn.dropdown.settings, parameters) - : $.extend({}, $.fn.dropdown.settings), - - className = settings.className, - message = settings.message, - fields = settings.fields, - keys = settings.keys, - metadata = settings.metadata, - namespace = settings.namespace, - regExp = settings.regExp, - selector = settings.selector, - error = settings.error, - templates = settings.templates, - - eventNamespace = '.' + namespace, - moduleNamespace = 'module-' + namespace, - - $module = $(this), - $context = $(settings.context), - $text = $module.find(selector.text), - $search = $module.find(selector.search), - $sizer = $module.find(selector.sizer), - $input = $module.find(selector.input), - $icon = $module.find(selector.icon), - - $combo = ($module.prev().find(selector.text).length > 0) - ? $module.prev().find(selector.text) - : $module.prev(), - - $menu = $module.children(selector.menu), - $item = $menu.find(selector.item), - - activated = false, - itemActivated = false, - internalChange = false, - element = this, - instance = $module.data(moduleNamespace), - - initialLoad, - pageLostFocus, - willRefocus, - elementNamespace, - id, - selectObserver, - menuObserver, - module - ; - - module = { - - initialize: function() { - module.debug('Initializing dropdown', settings); - - if( module.is.alreadySetup() ) { - module.setup.reference(); - } - else { - module.setup.layout(); - module.refreshData(); - - module.save.defaults(); - module.restore.selected(); - - module.create.id(); - module.bind.events(); - - module.observeChanges(); - module.instantiate(); - } - - }, - - instantiate: function() { - module.verbose('Storing instance of dropdown', module); - instance = module; - $module - .data(moduleNamespace, module) - ; - }, - - destroy: function() { - module.verbose('Destroying previous dropdown', $module); - module.remove.tabbable(); - $module - .off(eventNamespace) - .removeData(moduleNamespace) - ; - $menu - .off(eventNamespace) - ; - $document - .off(elementNamespace) - ; - module.disconnect.menuObserver(); - module.disconnect.selectObserver(); - }, - - observeChanges: function() { - if('MutationObserver' in window) { - selectObserver = new MutationObserver(module.event.select.mutation); - menuObserver = new MutationObserver(module.event.menu.mutation); - module.debug('Setting up mutation observer', selectObserver, menuObserver); - module.observe.select(); - module.observe.menu(); - } - }, - - disconnect: { - menuObserver: function() { - if(menuObserver) { - menuObserver.disconnect(); - } - }, - selectObserver: function() { - if(selectObserver) { - selectObserver.disconnect(); - } - } - }, - observe: { - select: function() { - if(module.has.input()) { - selectObserver.observe($input[0], { - childList : true, - subtree : true - }); - } - }, - menu: function() { - if(module.has.menu()) { - menuObserver.observe($menu[0], { - childList : true, - subtree : true - }); - } - } - }, - - create: { - id: function() { - id = (Math.random().toString(16) + '000000000').substr(2, 8); - elementNamespace = '.' + id; - module.verbose('Creating unique id for element', id); - }, - userChoice: function(values) { - var - $userChoices, - $userChoice, - isUserValue, - html - ; - values = values || module.get.userValues(); - if(!values) { - return false; - } - values = $.isArray(values) - ? values - : [values] - ; - $.each(values, function(index, value) { - if(module.get.item(value) === false) { - html = settings.templates.addition( module.add.variables(message.addResult, value) ); - $userChoice = $('<div />') - .html(html) - .attr('data-' + metadata.value, value) - .attr('data-' + metadata.text, value) - .addClass(className.addition) - .addClass(className.item) - ; - if(settings.hideAdditions) { - $userChoice.addClass(className.hidden); - } - $userChoices = ($userChoices === undefined) - ? $userChoice - : $userChoices.add($userChoice) - ; - module.verbose('Creating user choices for value', value, $userChoice); - } - }); - return $userChoices; - }, - userLabels: function(value) { - var - userValues = module.get.userValues() - ; - if(userValues) { - module.debug('Adding user labels', userValues); - $.each(userValues, function(index, value) { - module.verbose('Adding custom user value'); - module.add.label(value, value); - }); - } - }, - menu: function() { - $menu = $('<div />') - .addClass(className.menu) - .appendTo($module) - ; - }, - sizer: function() { - $sizer = $('<span />') - .addClass(className.sizer) - .insertAfter($search) - ; - } - }, - - search: function(query) { - query = (query !== undefined) - ? query - : module.get.query() - ; - module.verbose('Searching for query', query); - if(module.has.minCharacters(query)) { - module.filter(query); - } - else { - module.hide(); - } - }, - - select: { - firstUnfiltered: function() { - module.verbose('Selecting first non-filtered element'); - module.remove.selectedItem(); - $item - .not(selector.unselectable) - .not(selector.addition + selector.hidden) - .eq(0) - .addClass(className.selected) - ; - }, - nextAvailable: function($selected) { - $selected = $selected.eq(0); - var - $nextAvailable = $selected.nextAll(selector.item).not(selector.unselectable).eq(0), - $prevAvailable = $selected.prevAll(selector.item).not(selector.unselectable).eq(0), - hasNext = ($nextAvailable.length > 0) - ; - if(hasNext) { - module.verbose('Moving selection to', $nextAvailable); - $nextAvailable.addClass(className.selected); - } - else { - module.verbose('Moving selection to', $prevAvailable); - $prevAvailable.addClass(className.selected); - } - } - }, - - setup: { - api: function() { - var - apiSettings = { - debug : settings.debug, - urlData : { - value : module.get.value(), - query : module.get.query() - }, - on : false - } - ; - module.verbose('First request, initializing API'); - $module - .api(apiSettings) - ; - }, - layout: function() { - if( $module.is('select') ) { - module.setup.select(); - module.setup.returnedObject(); - } - if( !module.has.menu() ) { - module.create.menu(); - } - if( module.is.search() && !module.has.search() ) { - module.verbose('Adding search input'); - $search = $('<input />') - .addClass(className.search) - .prop('autocomplete', 'off') - .insertBefore($text) - ; - } - if( module.is.multiple() && module.is.searchSelection() && !module.has.sizer()) { - module.create.sizer(); - } - if(settings.allowTab) { - module.set.tabbable(); - } - }, - select: function() { - var - selectValues = module.get.selectValues() - ; - module.debug('Dropdown initialized on a select', selectValues); - 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.has.menu() ) { - module.create.menu(); - } - $menu = $module.children(selector.menu); - module.setup.menu(selectValues); - } - else { - module.debug('Creating entire dropdown from select'); - $module = $('<div />') - .attr('class', $input.attr('class') ) - .addClass(className.selection) - .addClass(className.dropdown) - .html( templates.dropdown(selectValues) ) - .insertBefore($input) - ; - if($input.hasClass(className.multiple) && $input.prop('multiple') === false) { - module.error(error.missingMultiple); - $input.prop('multiple', true); - } - if($input.is('[multiple]')) { - module.set.multiple(); - } - if ($input.prop('disabled')) { - module.debug('Disabling dropdown'); - $module.addClass(className.disabled); - } - $input - .removeAttr('class') - .detach() - .prependTo($module) - ; - } - module.refresh(); - }, - menu: function(values) { - $menu.html( templates.menu(values, fields)); - $item = $menu.find(selector.item); - }, - reference: function() { - module.debug('Dropdown behavior was called on select, replacing with closest dropdown'); - // replace module reference - $module = $module.parent(selector.dropdown); - module.refresh(); - module.setup.returnedObject(); - // invoke method in context of current instance - if(methodInvoked) { - instance = module; - module.invoke(query); - } - }, - returnedObject: function() { - var - $firstModules = $allModules.slice(0, elementIndex), - $lastModules = $allModules.slice(elementIndex + 1) - ; - // adjust all modules to use correct reference - $allModules = $firstModules.add($module).add($lastModules); - } - }, - - refresh: function() { - module.refreshSelectors(); - module.refreshData(); - }, - - refreshItems: function() { - $item = $menu.find(selector.item); - }, - - refreshSelectors: function() { - module.verbose('Refreshing selector cache'); - $text = $module.find(selector.text); - $search = $module.find(selector.search); - $input = $module.find(selector.input); - $icon = $module.find(selector.icon); - $combo = ($module.prev().find(selector.text).length > 0) - ? $module.prev().find(selector.text) - : $module.prev() - ; - $menu = $module.children(selector.menu); - $item = $menu.find(selector.item); - }, - - refreshData: function() { - module.verbose('Refreshing cached metadata'); - $item - .removeData(metadata.text) - .removeData(metadata.value) - ; - }, - - clearData: function() { - module.verbose('Clearing metadata'); - $item - .removeData(metadata.text) - .removeData(metadata.value) - ; - $module - .removeData(metadata.defaultText) - .removeData(metadata.defaultValue) - .removeData(metadata.placeholderText) - ; - }, - - toggle: function() { - module.verbose('Toggling menu visibility'); - if( !module.is.active() ) { - module.show(); - } - else { - module.hide(); - } - }, - - show: function(callback) { - callback = $.isFunction(callback) - ? callback - : function(){} - ; - if( module.can.show() && !module.is.active() ) { - module.debug('Showing dropdown'); - if(module.has.message() && !(module.has.maxSelections() || module.has.allResultsFiltered()) ) { - module.remove.message(); - } - if(module.is.allFiltered()) { - return true; - } - if(settings.onShow.call(element) !== false) { - module.animate.show(function() { - if( module.can.click() ) { - module.bind.intent(); - } - if(module.has.menuSearch()) { - module.focusSearch(); - } - module.set.visible(); - callback.call(element); - }); - } - } - }, - - hide: function(callback) { - callback = $.isFunction(callback) - ? callback - : function(){} - ; - if( module.is.active() ) { - module.debug('Hiding dropdown'); - if(settings.onHide.call(element) !== false) { - module.animate.hide(function() { - module.remove.visible(); - callback.call(element); - }); - } - } - }, - - hideOthers: function() { - module.verbose('Finding other dropdowns to hide'); - $allModules - .not($module) - .has(selector.menu + '.' + className.visible) - .dropdown('hide') - ; - }, - - hideMenu: function() { - module.verbose('Hiding menu instantaneously'); - module.remove.active(); - module.remove.visible(); - $menu.transition('hide'); - }, - - hideSubMenus: function() { - var - $subMenus = $menu.children(selector.item).find(selector.menu) - ; - module.verbose('Hiding sub menus', $subMenus); - $subMenus.transition('hide'); - }, - - bind: { - events: function() { - if(hasTouch) { - module.bind.touchEvents(); - } - module.bind.keyboardEvents(); - module.bind.inputEvents(); - module.bind.mouseEvents(); - }, - touchEvents: function() { - module.debug('Touch device detected binding additional touch events'); - if( module.is.searchSelection() ) { - // do nothing special yet - } - else if( module.is.single() ) { - $module - .on('touchstart' + eventNamespace, module.event.test.toggle) - ; - } - $menu - .on('touchstart' + eventNamespace, selector.item, module.event.item.mouseenter) - ; - }, - keyboardEvents: function() { - module.verbose('Binding keyboard events'); - $module - .on('keydown' + eventNamespace, module.event.keydown) - ; - if( module.has.search() ) { - $module - .on(module.get.inputEvent() + eventNamespace, selector.search, module.event.input) - ; - } - if( module.is.multiple() ) { - $document - .on('keydown' + elementNamespace, module.event.document.keydown) - ; - } - }, - inputEvents: function() { - module.verbose('Binding input change events'); - $module - .on('change' + eventNamespace, selector.input, module.event.change) - ; - }, - mouseEvents: function() { - module.verbose('Binding mouse events'); - if(module.is.multiple()) { - $module - .on('click' + eventNamespace, selector.label, module.event.label.click) - .on('click' + eventNamespace, selector.remove, module.event.remove.click) - ; - } - if( module.is.searchSelection() ) { - $module - .on('mousedown' + eventNamespace, module.event.mousedown) - .on('mouseup' + eventNamespace, module.event.mouseup) - .on('mousedown' + eventNamespace, selector.menu, module.event.menu.mousedown) - .on('mouseup' + eventNamespace, selector.menu, module.event.menu.mouseup) - .on('click' + eventNamespace, selector.icon, module.event.icon.click) - .on('focus' + eventNamespace, selector.search, module.event.search.focus) - .on('click' + eventNamespace, selector.search, module.event.search.focus) - .on('blur' + eventNamespace, selector.search, module.event.search.blur) - .on('click' + eventNamespace, selector.text, module.event.text.focus) - ; - if(module.is.multiple()) { - $module - .on('click' + eventNamespace, module.event.click) - ; - } - } - else { - if(settings.on == 'click') { - $module - .on('click' + eventNamespace, selector.icon, module.event.icon.click) - .on('click' + eventNamespace, module.event.test.toggle) - ; - } - else if(settings.on == 'hover') { - $module - .on('mouseenter' + eventNamespace, module.delay.show) - .on('mouseleave' + eventNamespace, module.delay.hide) - ; - } - else { - $module - .on(settings.on + eventNamespace, module.toggle) - ; - } - $module - .on('mousedown' + eventNamespace, module.event.mousedown) - .on('mouseup' + eventNamespace, module.event.mouseup) - .on('focus' + eventNamespace, module.event.focus) - .on('blur' + eventNamespace, module.event.blur) - ; - } - $menu - .on('mouseenter' + eventNamespace, selector.item, module.event.item.mouseenter) - .on('mouseleave' + eventNamespace, selector.item, module.event.item.mouseleave) - .on('click' + eventNamespace, selector.item, module.event.item.click) - ; - }, - intent: function() { - module.verbose('Binding hide intent event to document'); - if(hasTouch) { - $document - .on('touchstart' + elementNamespace, module.event.test.touch) - .on('touchmove' + elementNamespace, module.event.test.touch) - ; - } - $document - .on('click' + elementNamespace, module.event.test.hide) - ; - } - }, - - unbind: { - intent: function() { - module.verbose('Removing hide intent event from document'); - if(hasTouch) { - $document - .off('touchstart' + elementNamespace) - .off('touchmove' + elementNamespace) - ; - } - $document - .off('click' + elementNamespace) - ; - } - }, - - filter: function(query) { - var - searchTerm = (query !== undefined) - ? query - : module.get.query(), - afterFiltered = function() { - if(module.is.multiple()) { - module.filterActive(); - } - module.select.firstUnfiltered(); - if( module.has.allResultsFiltered() ) { - if( settings.onNoResults.call(element, searchTerm) ) { - if(settings.allowAdditions) { - if(settings.hideAdditions) { - module.verbose('User addition with no menu, setting empty style'); - module.set.empty(); - module.hideMenu(); - } - } - else { - module.verbose('All items filtered, showing message', searchTerm); - module.add.message(message.noResults); - } - } - else { - module.verbose('All items filtered, hiding dropdown', searchTerm); - module.hideMenu(); - } - } - else { - module.remove.empty(); - module.remove.message(); - } - if(settings.allowAdditions) { - module.add.userSuggestion(query); - } - if(module.is.searchSelection() && module.can.show() && module.is.focusedOnSearch() ) { - module.show(); - } - } - ; - if(settings.useLabels && module.has.maxSelections()) { - return; - } - if(settings.apiSettings) { - if( module.can.useAPI() ) { - module.queryRemote(searchTerm, function() { - afterFiltered(); - }); - } - else { - module.error(error.noAPI); - } - } - else { - module.filterItems(searchTerm); - afterFiltered(); - } - }, - - queryRemote: function(query, callback) { - var - apiSettings = { - errorDuration : false, - cache : 'local', - throttle : settings.throttle, - urlData : { - query: query - }, - onError: function() { - module.add.message(message.serverError); - callback(); - }, - onFailure: function() { - module.add.message(message.serverError); - callback(); - }, - onSuccess : function(response) { - module.remove.message(); - module.setup.menu({ - values: response[fields.remoteValues] - }); - callback(); - } - } - ; - if( !$module.api('get request') ) { - module.setup.api(); - } - apiSettings = $.extend(true, {}, apiSettings, settings.apiSettings); - $module - .api('setting', apiSettings) - .api('query') - ; - }, - - filterItems: function(query) { - var - searchTerm = (query !== undefined) - ? query - : module.get.query(), - results = null, - escapedTerm = module.escape.regExp(searchTerm), - beginsWithRegExp = new RegExp('^' + escapedTerm, 'igm') - ; - // avoid loop if we're matching nothing - if( module.has.query() ) { - results = []; - - module.verbose('Searching for matching values', searchTerm); - $item - .each(function(){ - var - $choice = $(this), - text, - value - ; - if(settings.match == 'both' || settings.match == 'text') { - text = String(module.get.choiceText($choice, false)); - if(text.search(beginsWithRegExp) !== -1) { - results.push(this); - return true; - } - else if (settings.fullTextSearch === 'exact' && module.exactSearch(searchTerm, text)) { - results.push(this); - return true; - } - else if (settings.fullTextSearch === true && module.fuzzySearch(searchTerm, text)) { - results.push(this); - return true; - } - } - if(settings.match == 'both' || settings.match == 'value') { - value = String(module.get.choiceValue($choice, text)); - - if(value.search(beginsWithRegExp) !== -1) { - results.push(this); - return true; - } - else if(settings.fullTextSearch && module.fuzzySearch(searchTerm, value)) { - results.push(this); - return true; - } - } - }) - ; - } - module.debug('Showing only matched items', searchTerm); - module.remove.filteredItem(); - if(results) { - $item - .not(results) - .addClass(className.filtered) - ; - } - }, - - fuzzySearch: function(query, term) { - var - termLength = term.length, - queryLength = query.length - ; - query = query.toLowerCase(); - term = term.toLowerCase(); - if(queryLength > termLength) { - return false; - } - if(queryLength === termLength) { - return (query === term); - } - search: for (var characterIndex = 0, nextCharacterIndex = 0; characterIndex < queryLength; characterIndex++) { - var - queryCharacter = query.charCodeAt(characterIndex) - ; - while(nextCharacterIndex < termLength) { - if(term.charCodeAt(nextCharacterIndex++) === queryCharacter) { - continue search; - } - } - return false; - } - return true; - }, - exactSearch: function (query, term) { - query = query.toLowerCase(); - term = term.toLowerCase(); - if(term.indexOf(query) > -1) { - return true; - } - return false; - }, - filterActive: function() { - if(settings.useLabels) { - $item.filter('.' + className.active) - .addClass(className.filtered) - ; - } - }, - - focusSearch: function(skipHandler) { - if( module.has.search() && !module.is.focusedOnSearch() ) { - if(skipHandler) { - $module.off('focus' + eventNamespace, selector.search); - $search.focus(); - $module.on('focus' + eventNamespace, selector.search, module.event.search.focus); - } - else { - $search.focus(); - } - } - }, - - forceSelection: function() { - var - $currentlySelected = $item.not(className.filtered).filter('.' + className.selected).eq(0), - $activeItem = $item.not(className.filtered).filter('.' + className.active).eq(0), - $selectedItem = ($currentlySelected.length > 0) - ? $currentlySelected - : $activeItem, - hasSelected = ($selectedItem.length > 0) - ; - if(hasSelected) { - module.debug('Forcing partial selection to selected item', $selectedItem); - module.event.item.click.call($selectedItem, {}, true); - return; - } - else { - if(settings.allowAdditions) { - module.set.selected(module.get.query()); - module.remove.searchTerm(); - } - else { - module.remove.searchTerm(); - } - } - }, - - event: { - change: function() { - if(!internalChange) { - module.debug('Input changed, updating selection'); - module.set.selected(); - } - }, - focus: function() { - if(settings.showOnFocus && !activated && module.is.hidden() && !pageLostFocus) { - module.show(); - } - }, - blur: function(event) { - pageLostFocus = (document.activeElement === this); - if(!activated && !pageLostFocus) { - module.remove.activeLabel(); - module.hide(); - } - }, - mousedown: function() { - if(module.is.searchSelection()) { - // prevent menu hiding on immediate re-focus - willRefocus = true; - } - else { - // prevents focus callback from occurring on mousedown - activated = true; - } - }, - mouseup: function() { - if(module.is.searchSelection()) { - // prevent menu hiding on immediate re-focus - willRefocus = false; - } - else { - activated = false; - } - }, - click: function(event) { - var - $target = $(event.target) - ; - // focus search - if($target.is($module)) { - if(!module.is.focusedOnSearch()) { - module.focusSearch(); - } - else { - module.show(); - } - } - }, - search: { - focus: function() { - activated = true; - if(module.is.multiple()) { - module.remove.activeLabel(); - } - if(settings.showOnFocus) { - module.search(); - } - }, - blur: function(event) { - pageLostFocus = (document.activeElement === this); - if(!willRefocus) { - if(!itemActivated && !pageLostFocus) { - if(settings.forceSelection) { - module.forceSelection(); - } - module.hide(); - } - } - willRefocus = false; - } - }, - icon: { - click: function(event) { - module.toggle(); - } - }, - text: { - focus: function(event) { - activated = true; - module.focusSearch(); - } - }, - input: function(event) { - if(module.is.multiple() || module.is.searchSelection()) { - module.set.filtered(); - } - clearTimeout(module.timer); - module.timer = setTimeout(module.search, settings.delay.search); - }, - label: { - click: function(event) { - var - $label = $(this), - $labels = $module.find(selector.label), - $activeLabels = $labels.filter('.' + className.active), - $nextActive = $label.nextAll('.' + className.active), - $prevActive = $label.prevAll('.' + className.active), - $range = ($nextActive.length > 0) - ? $label.nextUntil($nextActive).add($activeLabels).add($label) - : $label.prevUntil($prevActive).add($activeLabels).add($label) - ; - if(event.shiftKey) { - $activeLabels.removeClass(className.active); - $range.addClass(className.active); - } - else if(event.ctrlKey) { - $label.toggleClass(className.active); - } - else { - $activeLabels.removeClass(className.active); - $label.addClass(className.active); - } - settings.onLabelSelect.apply(this, $labels.filter('.' + className.active)); - } - }, - remove: { - click: function() { - var - $label = $(this).parent() - ; - if( $label.hasClass(className.active) ) { - // remove all selected labels - module.remove.activeLabels(); - } - else { - // remove this label only - module.remove.activeLabels( $label ); - } - } - }, - test: { - toggle: function(event) { - var - toggleBehavior = (module.is.multiple()) - ? module.show - : module.toggle - ; - if(module.is.bubbledLabelClick(event) || module.is.bubbledIconClick(event)) { - return; - } - if( module.determine.eventOnElement(event, toggleBehavior) ) { - event.preventDefault(); - } - }, - touch: function(event) { - module.determine.eventOnElement(event, function() { - if(event.type == 'touchstart') { - module.timer = setTimeout(function() { - module.hide(); - }, settings.delay.touch); - } - else if(event.type == 'touchmove') { - clearTimeout(module.timer); - } - }); - event.stopPropagation(); - }, - hide: function(event) { - module.determine.eventInModule(event, module.hide); - } - }, - select: { - mutation: function(mutations) { - module.debug('<select> modified, recreating menu'); - module.setup.select(); - } - }, - menu: { - mutation: function(mutations) { - var - mutation = mutations[0], - $addedNode = mutation.addedNodes - ? $(mutation.addedNodes[0]) - : $(false), - $removedNode = mutation.removedNodes - ? $(mutation.removedNodes[0]) - : $(false), - $changedNodes = $addedNode.add($removedNode), - isUserAddition = $changedNodes.is(selector.addition) || $changedNodes.closest(selector.addition).length > 0, - isMessage = $changedNodes.is(selector.message) || $changedNodes.closest(selector.message).length > 0 - ; - if(isUserAddition || isMessage) { - module.debug('Updating item selector cache'); - module.refreshItems(); - } - else { - module.debug('Menu modified, updating selector cache'); - module.refresh(); - } - }, - mousedown: function() { - itemActivated = true; - }, - mouseup: function() { - itemActivated = false; - } - }, - item: { - mouseenter: function(event) { - var - $target = $(event.target), - $item = $(this), - $subMenu = $item.children(selector.menu), - $otherMenus = $item.siblings(selector.item).children(selector.menu), - hasSubMenu = ($subMenu.length > 0), - isBubbledEvent = ($subMenu.find($target).length > 0) - ; - if( !isBubbledEvent && hasSubMenu ) { - clearTimeout(module.itemTimer); - module.itemTimer = setTimeout(function() { - 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 - $subMenu = $(this).children(selector.menu) - ; - if($subMenu.length > 0) { - clearTimeout(module.itemTimer); - module.itemTimer = setTimeout(function() { - module.verbose('Hiding sub-menu', $subMenu); - module.animate.hide(false, $subMenu); - }, settings.delay.hide); - } - }, - click: function (event, skipRefocus) { - var - $choice = $(this), - $target = (event) - ? $(event.target) - : $(''), - $subMenu = $choice.find(selector.menu), - text = module.get.choiceText($choice), - value = module.get.choiceValue($choice, text), - hasSubMenu = ($subMenu.length > 0), - isBubbledEvent = ($subMenu.find($target).length > 0) - ; - if(!isBubbledEvent && (!hasSubMenu || settings.allowCategorySelection)) { - if(module.is.searchSelection()) { - if(settings.allowAdditions) { - module.remove.userAddition(); - } - module.remove.searchTerm(); - if(!module.is.focusedOnSearch() && !(skipRefocus == true)) { - module.focusSearch(true); - } - } - if(!settings.useLabels) { - module.remove.filteredItem(); - module.set.scrollPosition($choice); - } - module.determine.selectAction.call(this, text, value); - } - } - }, - - document: { - // label selection should occur even when element has no focus - keydown: function(event) { - var - pressedKey = event.which, - isShortcutKey = module.is.inObject(pressedKey, keys) - ; - if(isShortcutKey) { - var - $label = $module.find(selector.label), - $activeLabel = $label.filter('.' + className.active), - activeValue = $activeLabel.data(metadata.value), - labelIndex = $label.index($activeLabel), - labelCount = $label.length, - hasActiveLabel = ($activeLabel.length > 0), - hasMultipleActive = ($activeLabel.length > 1), - isFirstLabel = (labelIndex === 0), - isLastLabel = (labelIndex + 1 == labelCount), - isSearch = module.is.searchSelection(), - isFocusedOnSearch = module.is.focusedOnSearch(), - isFocused = module.is.focused(), - caretAtStart = (isFocusedOnSearch && module.get.caretPosition() === 0), - $nextLabel - ; - if(isSearch && !hasActiveLabel && !isFocusedOnSearch) { - return; - } - - if(pressedKey == keys.leftArrow) { - // activate previous label - if((isFocused || caretAtStart) && !hasActiveLabel) { - module.verbose('Selecting previous label'); - $label.last().addClass(className.active); - } - else if(hasActiveLabel) { - if(!event.shiftKey) { - module.verbose('Selecting previous label'); - $label.removeClass(className.active); - } - else { - module.verbose('Adding previous label to selection'); - } - if(isFirstLabel && !hasMultipleActive) { - $activeLabel.addClass(className.active); - } - else { - $activeLabel.prev(selector.siblingLabel) - .addClass(className.active) - .end() - ; - } - event.preventDefault(); - } - } - else if(pressedKey == keys.rightArrow) { - // activate first label - if(isFocused && !hasActiveLabel) { - $label.first().addClass(className.active); - } - // activate next label - if(hasActiveLabel) { - if(!event.shiftKey) { - module.verbose('Selecting next label'); - $label.removeClass(className.active); - } - else { - module.verbose('Adding next label to selection'); - } - if(isLastLabel) { - if(isSearch) { - if(!isFocusedOnSearch) { - module.focusSearch(); - } - else { - $label.removeClass(className.active); - } - } - else if(hasMultipleActive) { - $activeLabel.next(selector.siblingLabel).addClass(className.active); - } - else { - $activeLabel.addClass(className.active); - } - } - else { - $activeLabel.next(selector.siblingLabel).addClass(className.active); - } - event.preventDefault(); - } - } - else if(pressedKey == keys.deleteKey || pressedKey == keys.backspace) { - if(hasActiveLabel) { - module.verbose('Removing active labels'); - if(isLastLabel) { - if(isSearch && !isFocusedOnSearch) { - module.focusSearch(); - } - } - $activeLabel.last().next(selector.siblingLabel).addClass(className.active); - module.remove.activeLabels($activeLabel); - event.preventDefault(); - } - else if(caretAtStart && !hasActiveLabel && pressedKey == keys.backspace) { - module.verbose('Removing last label on input backspace'); - $activeLabel = $label.last().addClass(className.active); - module.remove.activeLabels($activeLabel); - } - } - else { - $activeLabel.removeClass(className.active); - } - } - } - }, - - keydown: function(event) { - var - pressedKey = event.which, - isShortcutKey = module.is.inObject(pressedKey, keys) - ; - if(isShortcutKey) { - var - $currentlySelected = $item.not(selector.unselectable).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 +')').addBack() - : $menu.children(':not(.' + className.filtered +')'), - $subMenu = $selectedItem.children(selector.menu), - $parentMenu = $selectedItem.closest(selector.menu), - inVisibleMenu = ($parentMenu.hasClass(className.visible) || $parentMenu.hasClass(className.animating) || $parentMenu.parent(selector.menu).length > 0), - hasSubMenu = ($subMenu.length> 0), - hasSelectedItem = ($selectedItem.length > 0), - selectedIsSelectable = ($selectedItem.not(selector.unselectable).length > 0), - delimiterPressed = (pressedKey == keys.delimiter && settings.allowAdditions && module.is.multiple()), - isAdditionWithoutMenu = (settings.allowAdditions && settings.hideAdditions && (pressedKey == keys.enter || delimiterPressed) && selectedIsSelectable), - $nextItem, - isSubMenuItem, - newIndex - ; - // allow selection with menu closed - if(isAdditionWithoutMenu) { - module.verbose('Selecting item from keyboard shortcut', $selectedItem); - module.event.item.click.call($selectedItem, event); - if(module.is.searchSelection()) { - module.remove.searchTerm(); - } - } - - // visible menu keyboard shortcuts - if( module.is.visible() ) { - - // enter (select or open sub-menu) - if(pressedKey == keys.enter || delimiterPressed) { - if(pressedKey == keys.enter && hasSelectedItem && hasSubMenu && !settings.allowCategorySelection) { - module.verbose('Pressed enter on unselectable category, opening sub menu'); - pressedKey = keys.rightArrow; - } - else if(selectedIsSelectable) { - module.verbose('Selecting item from keyboard shortcut', $selectedItem); - module.event.item.click.call($selectedItem, event); - if(module.is.searchSelection()) { - module.remove.searchTerm(); - } - } - event.preventDefault(); - } - - // sub-menu actions - if(hasSelectedItem) { - - if(pressedKey == keys.leftArrow) { - - isSubMenuItem = ($parentMenu[0] !== $menu[0]); - - 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(); - } - } - - // 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(' + selector.unselectable + ')').eq(0) - : $item.eq(0) - ; - if($visibleItems.index( $nextItem ) < 0) { - module.verbose('Up key pressed but reached top of current menu'); - event.preventDefault(); - return; - } - else { - module.verbose('Up key pressed, changing active item'); - $selectedItem - .removeClass(className.selected) - ; - $nextItem - .addClass(className.selected) - ; - module.set.scrollPosition($nextItem); - if(settings.selectOnKeydown && module.is.single()) { - module.set.selectedItem($nextItem); - } - } - event.preventDefault(); - } - - // down arrow (traverse menu down) - if(pressedKey == keys.downArrow) { - $nextItem = (hasSelectedItem && inVisibleMenu) - ? $nextItem = $selectedItem.nextAll(selector.item + ':not(' + selector.unselectable + ')').eq(0) - : $item.eq(0) - ; - if($nextItem.length === 0) { - module.verbose('Down key pressed but reached bottom of current menu'); - event.preventDefault(); - return; - } - else { - module.verbose('Down key pressed, changing active item'); - $item - .removeClass(className.selected) - ; - $nextItem - .addClass(className.selected) - ; - module.set.scrollPosition($nextItem); - if(settings.selectOnKeydown && module.is.single()) { - module.set.selectedItem($nextItem); - } - } - event.preventDefault(); - } - - // page down (show next page) - if(pressedKey == keys.pageUp) { - module.scrollPage('up'); - event.preventDefault(); - } - if(pressedKey == keys.pageDown) { - module.scrollPage('down'); - event.preventDefault(); - } - - // escape (close menu) - if(pressedKey == keys.escape) { - module.verbose('Escape key pressed, closing dropdown'); - module.hide(); - } - - } - else { - // delimiter key - if(delimiterPressed) { - event.preventDefault(); - } - // down arrow (open menu) - if(pressedKey == keys.downArrow && !module.is.visible()) { - module.verbose('Down key pressed, showing dropdown'); - module.select.firstUnfiltered(); - module.show(); - event.preventDefault(); - } - } - } - else { - if( !module.has.search() ) { - module.set.selectedLetter( String.fromCharCode(pressedKey) ); - } - } - } - }, - - trigger: { - change: function() { - var - events = document.createEvent('HTMLEvents'), - inputElement = $input[0] - ; - if(inputElement) { - module.verbose('Triggering native change event'); - events.initEvent('change', true, false); - inputElement.dispatchEvent(events); - } - } - }, - - determine: { - selectAction: function(text, value) { - module.verbose('Determining action', settings.action); - if( $.isFunction( module.action[settings.action] ) ) { - module.verbose('Triggering preset action', settings.action, text, value); - module.action[ settings.action ].call(element, text, value, this); - } - else if( $.isFunction(settings.action) ) { - module.verbose('Triggering user action', settings.action, text, value); - settings.action.call(element, text, value, this); - } - else { - module.error(error.action, settings.action); - } - }, - eventInModule: function(event, callback) { - var - $target = $(event.target), - inDocument = ($target.closest(document.documentElement).length > 0), - inModule = ($target.closest($module).length > 0) - ; - callback = $.isFunction(callback) - ? callback - : function(){} - ; - if(inDocument && !inModule) { - module.verbose('Triggering event', callback); - callback(); - return true; - } - else { - module.verbose('Event occurred in dropdown, canceling callback'); - return false; - } - }, - eventOnElement: function(event, callback) { - var - $target = $(event.target), - $label = $target.closest(selector.siblingLabel), - inVisibleDOM = document.body.contains(event.target), - notOnLabel = ($module.find($label).length === 0), - notInMenu = ($target.closest($menu).length === 0) - ; - callback = $.isFunction(callback) - ? callback - : function(){} - ; - if(inVisibleDOM && notOnLabel && notInMenu) { - module.verbose('Triggering event', callback); - callback(); - return true; - } - else { - module.verbose('Event occurred in dropdown menu, canceling callback'); - return false; - } - } - }, - - action: { - - nothing: function() {}, - - activate: function(text, value, element) { - value = (value !== undefined) - ? value - : text - ; - if( module.can.activate( $(element) ) ) { - module.set.selected(value, $(element)); - if(module.is.multiple() && !module.is.allFiltered()) { - return; - } - else { - module.hideAndClear(); - } - } - }, - - select: function(text, value, element) { - value = (value !== undefined) - ? value - : text - ; - if( module.can.activate( $(element) ) ) { - module.set.value(value, $(element)); - if(module.is.multiple() && !module.is.allFiltered()) { - return; - } - else { - module.hideAndClear(); - } - } - }, - - combo: function(text, value, element) { - value = (value !== undefined) - ? value - : text - ; - module.set.selected(value, $(element)); - module.hideAndClear(); - }, - - hide: function(text, value, element) { - module.set.value(value, text); - module.hideAndClear(); - } - - }, - - get: { - id: function() { - return id; - }, - defaultText: function() { - return $module.data(metadata.defaultText); - }, - defaultValue: function() { - return $module.data(metadata.defaultValue); - }, - placeholderText: function() { - return $module.data(metadata.placeholderText) || ''; - }, - text: function() { - return $text.text(); - }, - query: function() { - return $.trim($search.val()); - }, - searchWidth: function(value) { - value = (value !== undefined) - ? value - : $search.val() - ; - $sizer.text(value); - // prevent rounding issues - return Math.ceil( $sizer.width() + 1); - }, - selectionCount: function() { - var - values = module.get.values(), - count - ; - count = ( module.is.multiple() ) - ? $.isArray(values) - ? values.length - : 0 - : (module.get.value() !== '') - ? 1 - : 0 - ; - return count; - }, - transition: function($subMenu) { - return (settings.transition == 'auto') - ? module.is.upward($subMenu) - ? 'slide up' - : 'slide down' - : settings.transition - ; - }, - userValues: function() { - var - values = module.get.values() - ; - if(!values) { - return false; - } - values = $.isArray(values) - ? values - : [values] - ; - return $.grep(values, function(value) { - return (module.get.item(value) === false); - }); - }, - uniqueArray: function(array) { - return $.grep(array, function (value, index) { - return $.inArray(value, array) === index; - }); - }, - caretPosition: function() { - var - input = $search.get(0), - range, - rangeLength - ; - if('selectionStart' in input) { - return input.selectionStart; - } - else if (document.selection) { - input.focus(); - range = document.selection.createRange(); - rangeLength = range.text.length; - range.moveStart('character', -input.value.length); - return range.text.length - rangeLength; - } - }, - value: function() { - var - value = ($input.length > 0) - ? $input.val() - : $module.data(metadata.value), - isEmptyMultiselect = ($.isArray(value) && value.length === 1 && value[0] === '') - ; - // prevents placeholder element from being selected when multiple - return (value === undefined || isEmptyMultiselect) - ? '' - : value - ; - }, - values: function() { - var - value = module.get.value() - ; - if(value === '') { - return ''; - } - return ( !module.has.selectInput() && module.is.multiple() ) - ? (typeof value == 'string') // delimited string - ? value.split(settings.delimiter) - : '' - : value - ; - }, - remoteValues: function() { - var - values = module.get.values(), - remoteValues = false - ; - if(values) { - if(typeof values == 'string') { - values = [values]; - } - $.each(values, function(index, value) { - var - name = module.read.remoteData(value) - ; - module.verbose('Restoring value from session data', name, value); - if(name) { - if(!remoteValues) { - remoteValues = {}; - } - remoteValues[value] = name; - } - }); - } - return remoteValues; - }, - choiceText: function($choice, preserveHTML) { - preserveHTML = (preserveHTML !== undefined) - ? preserveHTML - : settings.preserveHTML - ; - if($choice) { - if($choice.find(selector.menu).length > 0) { - module.verbose('Retrieving 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) - ? $.trim($choice.html()) - : $.trim($choice.text()) - ; - } - }, - choiceValue: function($choice, choiceText) { - choiceText = choiceText || module.get.choiceText($choice); - if(!$choice) { - return false; - } - return ($choice.data(metadata.value) !== undefined) - ? String( $choice.data(metadata.value) ) - : (typeof choiceText === 'string') - ? $.trim(choiceText.toLowerCase()) - : String(choiceText) - ; - }, - inputEvent: function() { - var - input = $search[0] - ; - if(input) { - return (input.oninput !== undefined) - ? 'input' - : (input.onpropertychange !== undefined) - ? 'propertychange' - : 'keyup' - ; - } - return false; - }, - selectValues: function() { - var - select = {} - ; - select.values = []; - $module - .find('option') - .each(function() { - var - $option = $(this), - name = $option.html(), - disabled = $option.attr('disabled'), - value = ( $option.attr('value') !== undefined ) - ? $option.attr('value') - : name - ; - if(settings.placeholder === 'auto' && value === '') { - select.placeholder = name; - } - else { - select.values.push({ - name : name, - value : value, - disabled : disabled - }); - } - }) - ; - if(settings.placeholder && settings.placeholder !== 'auto') { - module.debug('Setting placeholder value to', settings.placeholder); - select.placeholder = settings.placeholder; - } - if(settings.sortSelect) { - select.values.sort(function(a, b) { - return (a.name > b.name) - ? 1 - : -1 - ; - }); - module.debug('Retrieved and sorted values from select', select); - } - else { - module.debug('Retrieved values from select', select); - } - return select; - }, - activeItem: function() { - return $item.filter('.' + className.active); - }, - selectedItem: function() { - var - $selectedItem = $item.not(selector.unselectable).filter('.' + className.selected) - ; - return ($selectedItem.length > 0) - ? $selectedItem - : $item.eq(0) - ; - }, - itemWithAdditions: function(value) { - var - $items = module.get.item(value), - $userItems = module.create.userChoice(value), - hasUserItems = ($userItems && $userItems.length > 0) - ; - if(hasUserItems) { - $items = ($items.length > 0) - ? $items.add($userItems) - : $userItems - ; - } - return $items; - }, - item: function(value, strict) { - var - $selectedItem = false, - shouldSearch, - isMultiple - ; - value = (value !== undefined) - ? value - : ( module.get.values() !== undefined) - ? module.get.values() - : module.get.text() - ; - shouldSearch = (isMultiple) - ? (value.length > 0) - : (value !== undefined && value !== null) - ; - isMultiple = (module.is.multiple() && $.isArray(value)); - strict = (value === '' || value === 0) - ? true - : strict || false - ; - if(shouldSearch) { - $item - .each(function() { - var - $choice = $(this), - optionText = module.get.choiceText($choice), - optionValue = module.get.choiceValue($choice, optionText) - ; - // safe early exit - if(optionValue === null || optionValue === undefined) { - return; - } - if(isMultiple) { - if($.inArray( String(optionValue), value) !== -1 || $.inArray(optionText, value) !== -1) { - $selectedItem = ($selectedItem) - ? $selectedItem.add($choice) - : $choice - ; - } - } - else if(strict) { - module.verbose('Ambiguous dropdown value using strict type check', $choice, value); - if( optionValue === value || optionText === value) { - $selectedItem = $choice; - return true; - } - } - else { - if( String(optionValue) == String(value) || optionText == value) { - module.verbose('Found select item by value', optionValue, value); - $selectedItem = $choice; - return true; - } - } - }) - ; - } - return $selectedItem; - } - }, - - check: { - maxSelections: function(selectionCount) { - if(settings.maxSelections) { - selectionCount = (selectionCount !== undefined) - ? selectionCount - : module.get.selectionCount() - ; - if(selectionCount >= settings.maxSelections) { - module.debug('Maximum selection count reached'); - if(settings.useLabels) { - $item.addClass(className.filtered); - module.add.message(message.maxSelections); - } - return true; - } - else { - module.verbose('No longer at maximum selection count'); - module.remove.message(); - module.remove.filteredItem(); - if(module.is.searchSelection()) { - module.filterItems(); - } - return false; - } - } - return true; - } - }, - - restore: { - defaults: function() { - module.clear(); - module.restore.defaultText(); - module.restore.defaultValue(); - }, - defaultText: function() { - var - defaultText = module.get.defaultText(), - placeholderText = module.get.placeholderText - ; - if(defaultText === placeholderText) { - module.debug('Restoring default placeholder text', defaultText); - module.set.placeholderText(defaultText); - } - else { - module.debug('Restoring default text', defaultText); - module.set.text(defaultText); - } - }, - placeholderText: function() { - module.set.placeholderText(); - }, - defaultValue: function() { - var - defaultValue = module.get.defaultValue() - ; - if(defaultValue !== undefined) { - module.debug('Restoring default value', defaultValue); - if(defaultValue !== '') { - module.set.value(defaultValue); - module.set.selected(); - } - else { - module.remove.activeItem(); - module.remove.selectedItem(); - } - } - }, - labels: function() { - if(settings.allowAdditions) { - if(!settings.useLabels) { - module.error(error.labels); - settings.useLabels = true; - } - module.debug('Restoring selected values'); - module.create.userLabels(); - } - module.check.maxSelections(); - }, - selected: function() { - module.restore.values(); - if(module.is.multiple()) { - module.debug('Restoring previously selected values and labels'); - module.restore.labels(); - } - else { - module.debug('Restoring previously selected values'); - } - }, - values: function() { - // prevents callbacks from occurring on initial load - module.set.initialLoad(); - if(settings.apiSettings && settings.saveRemoteData && module.get.remoteValues()) { - module.restore.remoteValues(); - } - else { - module.set.selected(); - } - module.remove.initialLoad(); - }, - remoteValues: function() { - var - values = module.get.remoteValues() - ; - module.debug('Recreating selected from session data', values); - if(values) { - if( module.is.single() ) { - $.each(values, function(value, name) { - module.set.text(name); - }); - } - else { - $.each(values, function(value, name) { - module.add.label(value, name); - }); - } - } - } - }, - - read: { - remoteData: function(value) { - var - name - ; - if(window.Storage === undefined) { - module.error(error.noStorage); - return; - } - name = sessionStorage.getItem(value); - return (name !== undefined) - ? name - : false - ; - } - }, - - save: { - defaults: function() { - module.save.defaultText(); - module.save.placeholderText(); - module.save.defaultValue(); - }, - defaultValue: function() { - var - value = module.get.value() - ; - module.verbose('Saving default value as', value); - $module.data(metadata.defaultValue, value); - }, - defaultText: function() { - var - text = module.get.text() - ; - module.verbose('Saving default text as', text); - $module.data(metadata.defaultText, text); - }, - placeholderText: function() { - var - text - ; - if(settings.placeholder !== false && $text.hasClass(className.placeholder)) { - text = module.get.text(); - module.verbose('Saving placeholder text as', text); - $module.data(metadata.placeholderText, text); - } - }, - remoteData: function(name, value) { - if(window.Storage === undefined) { - module.error(error.noStorage); - return; - } - module.verbose('Saving remote data to session storage', value, name); - sessionStorage.setItem(value, name); - } - }, - - clear: function() { - if(module.is.multiple() && settings.useLabels) { - module.remove.labels(); - } - else { - module.remove.activeItem(); - module.remove.selectedItem(); - } - module.set.placeholderText(); - module.clearValue(); - }, - - clearValue: function() { - module.set.value(''); - }, - - scrollPage: function(direction, $selectedItem) { - var - $currentItem = $selectedItem || module.get.selectedItem(), - $menu = $currentItem.closest(selector.menu), - menuHeight = $menu.outerHeight(), - currentScroll = $menu.scrollTop(), - itemHeight = $item.eq(0).outerHeight(), - itemsPerPage = Math.floor(menuHeight / itemHeight), - maxScroll = $menu.prop('scrollHeight'), - newScroll = (direction == 'up') - ? currentScroll - (itemHeight * itemsPerPage) - : currentScroll + (itemHeight * itemsPerPage), - $selectableItem = $item.not(selector.unselectable), - isWithinRange, - $nextSelectedItem, - elementIndex - ; - elementIndex = (direction == 'up') - ? $selectableItem.index($currentItem) - itemsPerPage - : $selectableItem.index($currentItem) + itemsPerPage - ; - isWithinRange = (direction == 'up') - ? (elementIndex >= 0) - : (elementIndex < $selectableItem.length) - ; - $nextSelectedItem = (isWithinRange) - ? $selectableItem.eq(elementIndex) - : (direction == 'up') - ? $selectableItem.first() - : $selectableItem.last() - ; - if($nextSelectedItem.length > 0) { - module.debug('Scrolling page', direction, $nextSelectedItem); - $currentItem - .removeClass(className.selected) - ; - $nextSelectedItem - .addClass(className.selected) - ; - if(settings.selectOnKeydown && module.is.single()) { - module.set.selectedItem($nextSelectedItem); - } - $menu - .scrollTop(newScroll) - ; - } - }, - - set: { - filtered: function() { - var - isMultiple = module.is.multiple(), - isSearch = module.is.searchSelection(), - isSearchMultiple = (isMultiple && isSearch), - searchValue = (isSearch) - ? module.get.query() - : '', - hasSearchValue = (typeof searchValue === 'string' && searchValue.length > 0), - searchWidth = module.get.searchWidth(), - valueIsSet = searchValue !== '' - ; - if(isMultiple && hasSearchValue) { - module.verbose('Adjusting input width', searchWidth, settings.glyphWidth); - $search.css('width', searchWidth); - } - if(hasSearchValue || (isSearchMultiple && valueIsSet)) { - module.verbose('Hiding placeholder text'); - $text.addClass(className.filtered); - } - else if(!isMultiple || (isSearchMultiple && !valueIsSet)) { - module.verbose('Showing placeholder text'); - $text.removeClass(className.filtered); - } - }, - empty: function() { - $module.addClass(className.empty); - }, - loading: function() { - $module.addClass(className.loading); - }, - placeholderText: function(text) { - text = text || module.get.placeholderText(); - module.debug('Setting placeholder text', text); - module.set.text(text); - $text.addClass(className.placeholder); - }, - tabbable: function() { - if( module.has.search() ) { - module.debug('Added tabindex to searchable dropdown'); - $search - .val('') - .attr('tabindex', 0) - ; - $menu - .attr('tabindex', -1) - ; - } - else { - module.debug('Added tabindex to dropdown'); - if( $module.attr('tabindex') === undefined) { - $module - .attr('tabindex', 0) - ; - $menu - .attr('tabindex', -1) - ; - } - } - }, - initialLoad: function() { - module.verbose('Setting initial load'); - initialLoad = true; - }, - activeItem: function($item) { - if( settings.allowAdditions && $item.filter(selector.addition).length > 0 ) { - $item.addClass(className.filtered); - } - else { - $item.addClass(className.active); - } - }, - partialSearch: function(text) { - var - length = module.get.query().length - ; - $search.val( text.substr(0 , length)); - }, - scrollPosition: function($item, forceScroll) { - var - edgeTolerance = 5, - $menu, - hasActive, - offset, - itemHeight, - itemOffset, - menuOffset, - menuScroll, - menuHeight, - abovePage, - belowPage - ; - - $item = $item || module.get.selectedItem(); - $menu = $item.closest(selector.menu); - hasActive = ($item && $item.length > 0); - forceScroll = (forceScroll !== undefined) - ? forceScroll - : false - ; - if($item && $menu.length > 0 && hasActive) { - itemOffset = $item.position().top; - - $menu.addClass(className.loading); - menuScroll = $menu.scrollTop(); - menuOffset = $menu.offset().top; - itemOffset = $item.offset().top; - offset = menuScroll - menuOffset + itemOffset; - if(!forceScroll) { - menuHeight = $menu.height(); - belowPage = menuScroll + menuHeight < (offset + edgeTolerance); - abovePage = ((offset - edgeTolerance) < menuScroll); - } - module.debug('Scrolling to active item', offset); - if(forceScroll || abovePage || belowPage) { - $menu.scrollTop(offset); - } - $menu.removeClass(className.loading); - } - }, - text: function(text) { - if(settings.action !== 'select') { - if(settings.action == 'combo') { - module.debug('Changing combo button text', text, $combo); - if(settings.preserveHTML) { - $combo.html(text); - } - else { - $combo.text(text); - } - } - else { - if(text !== module.get.placeholderText()) { - $text.removeClass(className.placeholder); - } - module.debug('Changing text', text, $text); - $text - .removeClass(className.filtered) - ; - if(settings.preserveHTML) { - $text.html(text); - } - else { - $text.text(text); - } - } - } - }, - selectedItem: function($item) { - var - value = module.get.choiceValue($item), - text = module.get.choiceText($item, false) - ; - module.debug('Setting user selection to item', $item); - module.remove.activeItem(); - module.set.partialSearch(text); - module.set.activeItem($item); - module.set.selected(value, $item); - module.set.text(text); - }, - selectedLetter: function(letter) { - var - $selectedItem = $item.filter('.' + className.selected), - alreadySelectedLetter = $selectedItem.length > 0 && module.has.firstLetter($selectedItem, letter), - $nextValue = false, - $nextItem - ; - // check next of same letter - if(alreadySelectedLetter) { - $nextItem = $selectedItem.nextAll($item).eq(0); - if( module.has.firstLetter($nextItem, letter) ) { - $nextValue = $nextItem; - } - } - // check all values - if(!$nextValue) { - $item - .each(function(){ - if(module.has.firstLetter($(this), letter)) { - $nextValue = $(this); - return false; - } - }) - ; - } - // set next value - if($nextValue) { - module.verbose('Scrolling to next value with letter', letter); - module.set.scrollPosition($nextValue); - $selectedItem.removeClass(className.selected); - $nextValue.addClass(className.selected); - if(settings.selectOnKeydown && module.is.single()) { - module.set.selectedItem($nextValue); - } - } - }, - direction: function($menu) { - if(settings.direction == 'auto') { - if(module.is.onScreen($menu)) { - module.remove.upward($menu); - } - else { - module.set.upward($menu); - } - } - else if(settings.direction == 'upward') { - module.set.upward($menu); - } - }, - upward: function($menu) { - var $element = $menu || $module; - $element.addClass(className.upward); - }, - value: function(value, text, $selected) { - var - escapedValue = module.escape.value(value), - hasInput = ($input.length > 0), - isAddition = !module.has.value(value), - currentValue = module.get.values(), - stringValue = (value !== undefined) - ? String(value) - : value, - newValue - ; - if(hasInput) { - if(!settings.allowReselection && stringValue == currentValue) { - module.verbose('Skipping value update already same value', value, currentValue); - if(!module.is.initialLoad()) { - return; - } - } - - if( module.is.single() && module.has.selectInput() && module.can.extendSelect() ) { - module.debug('Adding user option', value); - module.add.optionValue(value); - } - module.debug('Updating input value', escapedValue, currentValue); - internalChange = true; - $input - .val(escapedValue) - ; - if(settings.fireOnInit === false && module.is.initialLoad()) { - module.debug('Input native change event ignored on initial load'); - } - else { - module.trigger.change(); - } - internalChange = false; - } - else { - module.verbose('Storing value in metadata', escapedValue, $input); - if(escapedValue !== currentValue) { - $module.data(metadata.value, stringValue); - } - } - if(settings.fireOnInit === false && module.is.initialLoad()) { - module.verbose('No callback on initial load', settings.onChange); - } - else { - settings.onChange.call(element, value, text, $selected); - } - }, - active: function() { - $module - .addClass(className.active) - ; - }, - multiple: function() { - $module.addClass(className.multiple); - }, - visible: function() { - $module.addClass(className.visible); - }, - exactly: function(value, $selectedItem) { - module.debug('Setting selected to exact values'); - module.clear(); - module.set.selected(value, $selectedItem); - }, - selected: function(value, $selectedItem) { - var - isMultiple = module.is.multiple(), - $userSelectedItem - ; - $selectedItem = (settings.allowAdditions) - ? $selectedItem || module.get.itemWithAdditions(value) - : $selectedItem || module.get.item(value) - ; - if(!$selectedItem) { - return; - } -
<TRUNCATED>