diff --git a/dist/select.css b/dist/select.css index 5d5f72e94..8c9573742 100644 --- a/dist/select.css +++ b/dist/select.css @@ -1,4 +1,4 @@ -/*! ui-select@0.20.1 https://github.com/bdb-opensource/ui-select (MIT License) */ +/*! ui-select@0.20.3 https://github.com/bdb-opensource/ui-select (MIT License) */ /* Style when highlighting a search. */ .ui-select-highlight { font-weight: bold; diff --git a/dist/select.js b/dist/select.js index cddc91cbd..ed7913bf8 100644 --- a/dist/select.js +++ b/dist/select.js @@ -1,4 +1,4 @@ -/*! ui-select@0.20.1 https://github.com/bdb-opensource/ui-select (MIT License) */ +/*! ui-select@0.20.3 https://github.com/bdb-opensource/ui-select (MIT License) */ (function () { "use strict"; var KEY = { @@ -242,23 +242,21 @@ uis.directive('uiSelectChoices', var parserResult = RepeatParser.parse(tAttrs.repeat); - var choices = tElement.querySelectorAll('.ui-select-choices-row'); + // find the row within the only group (i.e. ignore the null choice) + var choices = angular.element(groups[0]).querySelectorAll('.ui-select-choices-row'); if (choices.length !== 1) { throw uiSelectMinErr('rows', "Expected 1 .ui-select-choices-row but got '{0}'.", choices.length); } choices.attr('ng-repeat', parserResult.repeatExpression(groupByExp)); + choices.attr('ng-click', '$select.select(' + parserResult.itemName + ',$select.skipFocusser,$event)'); - var rowsInner = tElement.querySelectorAll('.ui-select-choices-row-inner'); + var rowsInner = angular.element(choices[0]).querySelectorAll('.ui-select-choices-row-inner'); if (rowsInner.length !== 1) { throw uiSelectMinErr('rows', "Expected 1 .ui-select-choices-row-inner but got '{0}'.", rowsInner.length); } rowsInner.attr('uis-transclude-append', ''); //Adding uisTranscludeAppend directive to row element after choices element has ngRepeat - // If IE8 then need to target rowsInner to apply the ng-click attr as choices will not capture the event. - var clickTarget = $window.document.addEventListener ? choices : rowsInner; - clickTarget.attr('ng-click', '$select.select(' + parserResult.itemName + ',$select.skipFocusser,$event)'); - return function link(scope, element, attrs, $select) { $select.parseRepeatAttr(attrs.repeat, groupByExp, groupFilterExp); //Result ready at $select.parserResult $select.disableChoiceExpression = attrs.uiDisableChoice; @@ -293,7 +291,6 @@ uis.directive('uiSelectChoices', attrs.$observe('nullValue', function(value) { value = scope.$eval(value); $select.nullValue = value !== undefined ? value : null; - $select.refreshItems(); }); attrs.$observe('nullLabel', function(value) { @@ -373,6 +370,7 @@ function uiSelectCtrl($scope, $element, $timeout, $filter, $$uisDebounce, Repeat ctrl.cancelEvent = cancelEvent; ctrl.clear = clear; ctrl.close = close; + ctrl.displayNullValue = displayNullValue; ctrl.findGroupByName = findGroupByName; ctrl.focusSearchInput = focusSearchInput; ctrl.getPlaceholder = getPlaceholder; @@ -409,7 +407,7 @@ function uiSelectCtrl($scope, $element, $timeout, $filter, $$uisDebounce, Repeat //#region Controller Functions function isEmpty() { var selected = ctrl.selected; - return isNil(selected) || selected === '' || selected.$$null || (ctrl.multiple && !selected.length); + return isNil(selected) || selected === '' || selected === ctrl.nullValue || (ctrl.multiple && !selected.length); } function getSelectedText() { @@ -458,9 +456,7 @@ function uiSelectCtrl($scope, $element, $timeout, $filter, $$uisDebounce, Repeat var active = -1; var selected = ctrl.selected; var parserResult = ctrl.parserResult; - if (angular.equals(selected, ctrl.nullValue)) { - active = _findIndex(ctrl.items, isNullValue); - } else if (parserResult && ctrl.items.length) { + if (parserResult && ctrl.items.length) { // If tracked by option.field.id, ng-model={field: {id}}, and items [{field: {id}, oopsNotSelected: true}], // angular.equals will not find the ng-model, thus leaving unselected, due to oopsNotSelected. var trackedValue = parserResult.getTrackedValue($scope, selected); @@ -469,10 +465,10 @@ function uiSelectCtrl($scope, $element, $timeout, $filter, $$uisDebounce, Repeat }); } - // If we don't have an active index, select first enabled non-generated null item. - if (active < 0) { + // If we don't have an active index and we're not displaying the "none" option, select first enabled item. + if (active < 0 && !ctrl.displayNullValue()) { active = _findIndex(ctrl.items, function(item) { - return !item.$$null && !_isItemDisabled(item); + return !_isItemDisabled(item); }); } @@ -491,10 +487,6 @@ function uiSelectCtrl($scope, $element, $timeout, $filter, $$uisDebounce, Repeat return result; } - function isNullValue(item) { - return item.$$null || angular.equals(item[ctrl.itemProperty], ctrl.nullValue); - } - // When the user clicks on ui-select, displays the dropdown list function activate(initSearchValue, avoidReset) { if (!ctrl.disabled && !ctrl.open) { @@ -524,6 +516,10 @@ function uiSelectCtrl($scope, $element, $timeout, $filter, $$uisDebounce, Repeat } } + function displayNullValue() { + return !ctrl.multiple && !ctrl.taggingLabel && !ctrl.required && (!ctrl.search || ctrl.nullLabel.toLowerCase().indexOf(ctrl.search) > -1); + } + function focusSearchInput(initSearchValue) { ctrl.search = initSearchValue || ctrl.search; ctrl.searchInput[0].focus(); @@ -568,16 +564,6 @@ function uiSelectCtrl($scope, $element, $timeout, $filter, $$uisDebounce, Repeat }); } - function createNullItem() { - var nullItem = {$$null: true}; - nullItem[ctrl.itemProperty] = ctrl.nullValue; - return nullItem; - } - - function needsNullItem(items) { - return !ctrl.taggingLabel && !ctrl.required && (!ctrl.search || ctrl.nullLabel.toLowerCase().indexOf(ctrl.search) > -1) && !items.some(isNullValue); - } - function onOriginalSourceChange(newVal, oldVal) { if (newVal !== oldVal) { createArrayFromObject(); @@ -627,11 +613,6 @@ function uiSelectCtrl($scope, $element, $timeout, $filter, $$uisDebounce, Repeat function updateFlatItems(items) { ctrl.items = items; - - // Insert our null item at the head of the items - if (needsNullItem(items)) { - items.unshift(createNullItem()); - } } function updateGroups(items) { @@ -663,14 +644,6 @@ function uiSelectCtrl($scope, $element, $timeout, $filter, $$uisDebounce, Repeat items = ctrl.items = ctrl.groups.reduce(function(items, group) { return items.concat(group.items); }, []); - - // Insert our null item at the head of the list if we dont have an item that represents null. - if (needsNullItem(items)) { - var group = ctrl.groups[0] || (ctrl.groups[0] = {name: '', items: []}); - var nullItem = createNullItem(); - group.items.unshift(nullItem); - items.unshift(nullItem); - } } } @@ -941,6 +914,8 @@ function uiSelectCtrl($scope, $element, $timeout, $filter, $$uisDebounce, Repeat function _handleDropDownSelection(key, shiftKey) { var processed = true; + var minActiveIndex = displayNullValue() ? -1 : 0; + switch (key) { case KEY.DOWN: case KEY.UP: @@ -951,28 +926,33 @@ function uiSelectCtrl($scope, $element, $timeout, $filter, $$uisDebounce, Repeat var len = ctrl.items.length; do { ctrl.activeIndex += key === KEY.UP ? -1 : 1; - } while (ctrl.activeIndex > 0 && ctrl.activeIndex < len && _isItemDisabled(ctrl.items[ctrl.activeIndex])); + } while (ctrl.activeIndex > minActiveIndex && ctrl.activeIndex < len && _isItemDisabled(ctrl.items[ctrl.activeIndex])); - ctrl.activeIndex = Math.max(0, Math.min(len - 1, ctrl.activeIndex)); + ctrl.activeIndex = Math.max(minActiveIndex, Math.min(len - 1, ctrl.activeIndex)); } break; case KEY.TAB: if (!ctrl.multiple || ctrl.open) { - select(ctrl.items[ctrl.activeIndex], true); + if(ctrl.activeIndex === -1 && displayNullValue()){ + select(ctrl.nullValue, true); + } else { + select(ctrl.items[ctrl.activeIndex], true); + } tabNavigate(shiftKey); } break; case KEY.ENTER: - if (ctrl.open && (ctrl.tagging.isActivated || ctrl.activeIndex >= 0)) { + if(ctrl.open && ctrl.activeIndex === -1 && displayNullValue()) { + select(ctrl.nullValue, ctrl.skipFocusser); + } else if (ctrl.open && (ctrl.tagging.isActivated || ctrl.activeIndex >= 0)) { // Make sure at least one dropdown item is highlighted before adding if not in tagging mode select(ctrl.items[ctrl.activeIndex], ctrl.skipFocusser); } else { // In case its the search input in 'multiple' mode activate(false, true); } - break; case KEY.ESC: close(); @@ -1110,8 +1090,9 @@ function uiSelectCtrl($scope, $element, $timeout, $filter, $$uisDebounce, Repeat throw uiSelectMinErr('choices', "Expected multiple .ui-select-choices-row but got '{0}'.", choices.length); } + // When searching for the highlighted item by activeIndex add 1 for the "none" option if rendered + var highlighted = choices[ctrl.activeIndex + (displayNullValue() ? 1 : 0)]; // Bail out if we can't find the highlighted row. - var highlighted = choices[ctrl.activeIndex]; if (!highlighted) { return; } var posY = highlighted.offsetTop + highlighted.clientHeight - container[0].scrollTop; @@ -2185,11 +2166,6 @@ uis.directive('uiSelectSingle', ['$timeout','$compile', function($timeout, $comp return inputValue; } - // Allow the null value to be considered a valid model value - if (inputValue.$$null) { - return inputValue[$select.itemProperty]; - } - var locals = {}; locals[$select.parserResult.itemName] = inputValue; return $select.parserResult.modelMapper(scope, locals); @@ -2584,7 +2560,7 @@ uis.service('uisRepeatParser', ['uiSelectMinErr', '$parse', function(uiSelectMin }]); }()); -angular.module("ui.select").run(["$templateCache", function($templateCache) {$templateCache.put("bootstrap/choices.tpl.html","