diff --git a/src/uiSelectController.js b/src/uiSelectController.js index c0a1a94ac..17d299d5a 100644 --- a/src/uiSelectController.js +++ b/src/uiSelectController.js @@ -36,7 +36,6 @@ uis.controller('uiSelectCtrl', ctrl.tagging = {isActivated: false, fct: undefined}; ctrl.taggingTokens = {isActivated: false, tokens: undefined}; ctrl.lockChoiceExpression = undefined; // Initialized inside uiSelectMatch directive link function - ctrl.clickTriggeredSelect = false; ctrl.$filter = $filter; ctrl.searchInput = $element.querySelectorAll('input.ui-select-search'); @@ -239,7 +238,7 @@ uis.controller('uiSelectCtrl', // When the user selects an item with ENTER or clicks the dropdown - ctrl.select = function(item, skipFocusser, $event) { + ctrl.select = function(item, skipFocusser) { if (item === undefined || !item._uiSelectChoiceDisabled) { if ( ! ctrl.items && ! ctrl.search ) return; @@ -299,9 +298,6 @@ uis.controller('uiSelectCtrl', if (ctrl.closeOnSelect) { ctrl.close(skipFocusser); } - if ($event && $event.type === 'click') { - ctrl.clickTriggeredSelect = true; - } } } }; @@ -466,10 +462,11 @@ uis.controller('uiSelectCtrl', // If tagging try to split by tokens and add items ctrl.searchInput.on('paste', function (e) { - var data = e.originalEvent.clipboardData.getData('text/plain'); + var data = (e.originalEvent || e).clipboardData.getData('text/plain'); if (data && data.length > 0 && ctrl.taggingTokens.isActivated && ctrl.tagging.fct) { var items = data.split(ctrl.taggingTokens.tokens[0]); // split by first token only if (items && items.length > 0) { + _removeDuplicates(items); angular.forEach(items, function (item) { var newItem = ctrl.tagging.fct(item); if (newItem) { @@ -488,6 +485,22 @@ uis.controller('uiSelectCtrl', }); }); + function _removeDuplicates(arr) { + var index = 0; + while(index < arr.length){ + var item = arr[index]; + if(_count(arr, item).length > 1){ + arr.splice(index, 1); + } else { + index++; + } + } + + function _count(a, item){ + return a.filter(function(arrItem) { return angular.equals(item, arrItem); }); + } + } + // See https://github.com/ivaynberg/select2/blob/3.4.6/select2.js#L1431 function _ensureHighlightVisible() { var container = $element.querySelectorAll('.ui-select-choices-content'); diff --git a/src/uiSelectDirective.js b/src/uiSelectDirective.js index fc6cc4138..ad62850c1 100644 --- a/src/uiSelectDirective.js +++ b/src/uiSelectDirective.js @@ -143,7 +143,7 @@ uis.directive('uiSelect', contains = element[0].contains(e.target); } - if (!contains && !$select.clickTriggeredSelect) { + if (!contains) { //Will lose focus only with certain targets var focusableControls = ['input','button','textarea']; var targetScope = angular.element(e.target).scope(); //To check if target is other ui-select @@ -152,7 +152,6 @@ uis.directive('uiSelect', $select.close(skipFocusser); scope.$digest(); } - $select.clickTriggeredSelect = false; } // See Click everywhere but here event http://stackoverflow.com/questions/12931369 diff --git a/src/uiSelectMultipleDirective.js b/src/uiSelectMultipleDirective.js index b1e997ec5..27926b9d8 100644 --- a/src/uiSelectMultipleDirective.js +++ b/src/uiSelectMultipleDirective.js @@ -155,8 +155,13 @@ uis.directive('uiSelectMultiple', ['uiSelectMinErr','$timeout', function(uiSelec }; scope.$on('uis:select', function (event, item) { - $select.selected.push(item); - $selectMultiple.updateModel(); + // The model should be updated so that selected items may be removed, however + // this should be done after the onDocumentClick handler has run so that the + // item's list item is still in the DOM. + $timeout(function () { + $select.selected.push(item); + $selectMultiple.updateModel(); + }); }); scope.$on('uis:activate', function () { diff --git a/test/select.spec.js b/test/select.spec.js index 2ba86fb2a..ba7440b46 100644 --- a/test/select.spec.js +++ b/test/select.spec.js @@ -1035,6 +1035,7 @@ describe('ui-select tests', function() { clickItem(el, 'Samantha'); clickItem(el, 'Adrian'); + $timeout.flush(); el.find('.ui-select-match-item').first().find('.ui-select-match-close').click(); $timeout.flush(); @@ -1065,6 +1066,7 @@ describe('ui-select tests', function() { clickItem(el, 'Samantha'); clickItem(el, 'Adrian'); + $timeout.flush(); el.find('.ui-select-match-item').first().find('.ui-select-match-close').click(); $timeout.flush(); @@ -1120,6 +1122,7 @@ describe('ui-select tests', function() { setSearchText(el, 'idontexist'); triggerKeydown(searchInput, Key.Enter); + $timeout.flush(); expect($(el).scope().$select.selected).toEqual(['idontexist']); }); @@ -1358,6 +1361,7 @@ describe('ui-select tests', function() { var el = createUiSelectMultiple(); expect(scope.selection.selectedMultiple instanceof Array).toBe(false); clickItem(el, 'Samantha'); + $timeout.flush(); expect(scope.selection.selectedMultiple instanceof Array).toBe(true); }); @@ -1547,6 +1551,7 @@ describe('ui-select tests', function() { var searchInput = el.find('.ui-select-search'); clickItem(el, 'Wladimir'); + $timeout.flush(); expect(scope.selection.selectedMultiple).toEqual([scope.people[5], scope.people[4]]); //Samantha & Wladimir }); @@ -1605,6 +1610,7 @@ describe('ui-select tests', function() { triggerKeydown(searchInput, Key.Down) triggerKeydown(searchInput, Key.Enter) + $timeout.flush(); expect(scope.selection.selectedMultiple.length).toEqual(2); }); @@ -1707,6 +1713,7 @@ describe('ui-select tests', function() { var searchInput = el.find('.ui-select-search'); clickItem(el, 'Natasha'); + $timeout.flush(); expect(el.scope().$select.selected).toEqual([scope.people[4], scope.people[5], scope.people[7]]); scope.selection.selectedMultiple = ['wladimir@email.com', 'samantha@email.com', 'natasha@email.com']; @@ -1743,6 +1750,7 @@ describe('ui-select tests', function() { setSearchText(el, 'n') clickItem(el, 'Nicole'); + $timeout.flush(); expect(el.find('.ui-select-match-item [uis-transclude-append]:not(.ng-hide)').text()) .toBe("Wladimir Samantha Nicole "); @@ -1775,6 +1783,7 @@ describe('ui-select tests', function() { .toBe("Wladimir Samantha "); clickItem(el, 'Nicole'); + $timeout.flush(); expect(el.find('.ui-select-match-item [uis-transclude-append]:not(.ng-hide)').text()) .toBe("Wladimir Samantha Nicole "); @@ -1804,6 +1813,7 @@ describe('ui-select tests', function() { } clickItem(el, 'Nicole'); + $timeout.flush(); expect(scope.counter).toBe(1); @@ -1866,6 +1876,7 @@ describe('ui-select tests', function() { var el = createUiSelectMultiple({tagging: 'taggingFunc', taggingTokens: ",|ENTER"}); clickMatch(el); triggerPaste(el.find('input'), 'tag1'); + $timeout.flush(); expect($(el).scope().$select.selected.length).toBe(1); }); @@ -1883,6 +1894,7 @@ describe('ui-select tests', function() { var el = createUiSelectMultiple({tagging: 'taggingFunc', taggingTokens: ",|ENTER"}); clickMatch(el); triggerPaste(el.find('input'), ',tag1,tag2,tag3,,tag5,'); + $timeout.flush(); expect($(el).scope().$select.selected.length).toBe(5); });