diff --git a/src/definitions/modules/dropdown.js b/src/definitions/modules/dropdown.js index 8b2de047f..ad4210f49 100644 --- a/src/definitions/modules/dropdown.js +++ b/src/definitions/modules/dropdown.js @@ -338,8 +338,10 @@ $.fn.dropdown = function(parameters) { ; if( module.can.show() && !module.is.active() ) { module.debug('Showing dropdown'); - if(module.is.multiple() && !module.has.search() && module.is.allFiltered()) { - return true; + if(module.is.multiple()) { + if(!module.has.search() && module.is.allFiltered()) { + return true; + } } module.animate.show(function() { if( module.can.click() ) { @@ -506,47 +508,60 @@ $.fn.dropdown = function(parameters) { filter: function(searchTerm) { var - $results = $(), - escapedTerm = module.escape.regExp(searchTerm), - exactRegExp = new RegExp('^' + escapedTerm, 'igm'), - allItemsFiltered + $results = $(), + allItemsFiltered, + escapedTerm, + beginsWithRegExp ; - module.verbose('Searching for matching values'); - $item - .each(function(){ - var - $choice = $(this), - text, - value - ; - if(settings.match == 'both' || settings.match == 'text') { - text = String(module.get.choiceText($choice, false)); - - if(text.match(exactRegExp)) { - $results = $results.add($choice); - return true; - } - else if(settings.fullTextSearch && module.fuzzySearch(searchTerm, text)) { - $results = $results.add($choice); - return true; + searchTerm = (searchTerm !== undefined) + ? searchTerm + : module.get.query() + ; + escapedTerm = module.escape.regExp(searchTerm); + beginsWithRegExp = new RegExp('^' + escapedTerm, 'igm'); + if(module.has.maxSelections()) { + return; + } + if(searchTerm === '') { + $results = $item; + } + else { + 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 = $results.add($choice); + return true; + } + else if(settings.fullTextSearch && module.fuzzySearch(searchTerm, text)) { + $results = $results.add($choice); + return true; + } } - } - if(settings.match == 'both' || settings.match == 'value') { - value = String(module.get.choiceValue($choice, text)); + if(settings.match == 'both' || settings.match == 'value') { + value = String(module.get.choiceValue($choice, text)); - if(value.match(exactRegExp)) { - $results = $results.add($choice); - return true; - } - else if(settings.fullTextSearch && module.fuzzySearch(searchTerm, value)) { - $results = $results.add($choice); - return true; + if(value.search(beginsWithRegExp) !== -1) { + $results = $results.add($choice); + return true; + } + else if(settings.fullTextSearch && module.fuzzySearch(searchTerm, value)) { + $results = $results.add($choice); + return true; + } } - } - }) - ; + }) + ; + } - module.debug('Setting filter', searchTerm); + module.debug('Showing only matched items', searchTerm); module.remove.filteredItem(); $item .not($results) @@ -1207,6 +1222,17 @@ $.fn.dropdown = function(parameters) { query: function() { return $.trim($search.val()); }, + selectionCount: function() { + var + values = module.get.values() + ; + return ( module.is.multiple() && $.isArray(values)) + ? values.length + : (module.get.value() !== '') + ? 1 + : 1 + ; + }, userValues: function() { var values = module.get.values() @@ -1229,7 +1255,7 @@ $.fn.dropdown = function(parameters) { range, rangeLength ; - if ('selectionStart' in input) { + if('selectionStart' in input) { return input.selectionStart; } else if (document.selection) { @@ -1429,6 +1455,29 @@ $.fn.dropdown = function(parameters) { } }, + check: { + maxSelections: function(selectionCount) { + selectionCount = (selectionCount !== undefined) + ? selectionCount + : module.get.selectionCount() + ; + if(selectionCount >= settings.maxSelections) { + module.debug('Maximum selection count reached'); + $item.addClass(className.filtered); + module.add.message(message.maxSelections); + return true; + } + else { + module.remove.message(); + module.remove.filteredItem(); + if(module.is.searchSelection()) { + module.filter(); + } + } + return false; + } + }, + restore: { defaults: function() { module.restore.defaultText(); @@ -1720,6 +1769,7 @@ $.fn.dropdown = function(parameters) { settings.onChange.call(element, value, text, $selected); } } + module.check.maxSelections(); }, active: function() { $module @@ -1759,10 +1809,11 @@ $.fn.dropdown = function(parameters) { isFiltered = $selected.hasClass(className.filtered), isActive = $selected.hasClass(className.active), + isUserValue = $selected.hasClass(className.addition), shouldAnimate = (isMultiple && $selectedItem.length == 1) ; if(isMultiple) { - if(!isActive) { + if(!isActive || isUserValue) { if(settings.useLabels) { module.add.label(selectedValue, selectedText, shouldAnimate); module.set.value(selectedValue, selectedText, $selected); @@ -1830,7 +1881,7 @@ $.fn.dropdown = function(parameters) { message: function(message) { var $message = $menu.children(selector.message), - html = settings.templates.message(message) + html = settings.templates.message(module.add.variables(message)) ; if($message.length > 0) { $message @@ -1879,6 +1930,9 @@ $.fn.dropdown = function(parameters) { $addition = $menu.children(selector.addition), html ; + if(module.has.maxSelections()) { + return; + } if(value === '' || alreadyHasValue) { $addition.remove(); return; @@ -1906,20 +1960,21 @@ $.fn.dropdown = function(parameters) { }, variables: function(message) { var - hasCount = (message.search('{count}') !== -1), - hasTerm = (message.search('{term}') !== -1), + hasCount = (message.search('{count}') !== -1), + hasMaxCount = (message.search('{maxCount}') !== -1), + hasTerm = (message.search('{term}') !== -1), values, count, query ; if(hasCount) { - values = module.get.values(); - count = $.isArray(values) - ? values.length - : 1 - ; + count = module.get.selectionCount(); message = message.replace('{count}', count); } + if(hasMaxCount) { + count = module.get.selectionCount(); + message = message.replace('{maxCount}', settings.maxSelections); + } if(hasTerm) { query = module.get.query(); message = message.replace('{term}', query); @@ -1942,6 +1997,9 @@ $.fn.dropdown = function(parameters) { $item.removeClass(className.active); }, filteredItem: function() { + if( module.has.maxSelections() ) { + return; + } if(settings.useLabels) { $item.not('.' + className.active).removeClass(className.filtered); } @@ -2004,6 +2062,7 @@ $.fn.dropdown = function(parameters) { .trigger('change') ; } + module.check.maxSelections(); }, delimitedValue: function(removedValue, values) { if(typeof values != 'string') { @@ -2097,6 +2156,9 @@ $.fn.dropdown = function(parameters) { ; return ($labels.filter('[data-value="' + value +'"]').length > 0); }, + maxSelections: function() { + return (settings.maxSelections && module.get.selectionCount() >= settings.maxSelections); + }, value: function(value) { var values = module.get.values(), @@ -2131,7 +2193,7 @@ $.fn.dropdown = function(parameters) { return (document.activeElement === $search[0]); }, allFiltered: function() { - return(module.is.multiple() || module.has.search()) && ($item.filter('.' + className.filtered).length === $item.length); + return(module.is.multiple() || module.has.search()) && $menu.children(selector.message).length === 0 && ($item.filter('.' + className.filtered).length === $item.length); }, hidden: function($subMenu) { return ($subMenu) @@ -2539,12 +2601,14 @@ $.fn.dropdown.settings = { sortSelect : false, // sort selection on init forceSelection : true, // force a choice on blur with search selection + + maxSelections : 5, // When set to a number limits the number of selections to this count useLabels : true, // whether multiple select should filter currently active selections from choices transition : 'auto', // auto transition will slide down or up based on direction duration : 200, // duration of transition - allowAdditions : false, // whether multiple select should allow user added values + allowAdditions : true, // whether multiple select should allow user added values delimiter : ',', // when multiselect uses normal the values will be delmited with this character glyphWidth : 1.0714, // widest glyph width in em (W is 1.0714 em) used to calculate multiselect input width @@ -2576,9 +2640,10 @@ $.fn.dropdown.settings = { namespace : 'dropdown', message: { - addResult : 'Add {term}', - count : '{count} selected', - noResults : 'No results found.' + addResult : 'Add {term}', + count : '{count} selected', + maxSelections : 'Max {maxCount} selections', + noResults : 'No results found.' }, error : {