Skip to content
This repository has been archived by the owner on Oct 2, 2019. It is now read-only.

Commit

Permalink
Merge branch 'master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
DarkIsDude authored Sep 6, 2017
2 parents fb1bc85 + 2b0b17b commit e166672
Show file tree
Hide file tree
Showing 8 changed files with 147 additions and 31 deletions.
4 changes: 2 additions & 2 deletions src/bootstrap/select-multiple.tpl.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@
autocapitalize="off"
spellcheck="false"
class="ui-select-search input-xs"
placeholder="{{$selectMultiple.getPlaceholder()}}"
placeholder="{{$select.getPlaceholder()}}"
ng-disabled="$select.disabled"
ng-click="$select.activate()"
ng-model="$select.search"
role="combobox"
aria-expanded="{{$select.open}}"
aria-label="{{$select.baseTitle}}"
ng-class="{'spinner': $select.refreshing}"
ondrop="return false;">
data-disallow-drop=data-disallow-drop>
</div>
<div class="ui-select-choices"></div>
<div class="ui-select-no-choice"></div>
Expand Down
4 changes: 2 additions & 2 deletions src/select2/select-multiple.tpl.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@
aria-label="{{ $select.baseTitle }}"
aria-activedescendant="ui-select-choices-row-{{ $select.generatedId }}-{{ $select.activeIndex }}"
class="select2-input ui-select-search"
placeholder="{{$selectMultiple.getPlaceholder()}}"
placeholder="{{$select.getPlaceholder()}}"
ng-disabled="$select.disabled"
ng-hide="$select.disabled"
ng-model="$select.search"
ng-click="$select.activate()"
style="width: 34px;"
ondrop="return false;">
data-disallow-drop=data-disallow-drop>
</li>
</ul>
<div class="ui-select-dropdown select2-drop select2-with-searchbox select2-drop-active"
Expand Down
6 changes: 3 additions & 3 deletions src/selectize/select-multiple.tpl.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
<input type="search" autocomplete="off" tabindex="-1"
class="ui-select-search"
ng-class="{'ui-select-search-hidden':!$select.searchEnabled}"
placeholder="{{$selectMultiple.getPlaceholder()}}"
placeholder="{{$select.getPlaceholder()}}"
ng-model="$select.search"
ng-disabled="$select.disabled"
aria-expanded="{{$select.open}}"
aria-label="{{ $select.baseTitle }}"
ondrop="return false;">
data-disallow-drop=data-disallow-drop>
</div>
<div class="ui-select-choices"></div>
<div class="ui-select-no-choice"></div>
</div>
</div>
21 changes: 15 additions & 6 deletions src/uiSelectController.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ uis.controller('uiSelectCtrl',
return isNil(ctrl.selected) || ctrl.selected === '' || (ctrl.multiple && ctrl.selected.length === 0);
};

ctrl.getPlaceholder = function(){
if(ctrl.selected && ctrl.selected.length) return;
return ctrl.placeholder;
};

function _findIndex(collection, predicate, thisArg){
if (collection.findIndex){
return collection.findIndex(predicate, thisArg);
Expand All @@ -88,10 +93,14 @@ uis.controller('uiSelectCtrl',
if (ctrl.resetSearchInput) {
ctrl.search = EMPTY_SEARCH;
//reset activeIndex
if (ctrl.selected && ctrl.items.length && !ctrl.multiple) {
ctrl.activeIndex = _findIndex(ctrl.items, function(item){
return angular.equals(this, item);
}, ctrl.selected);
if (!ctrl.multiple) {
if (ctrl.selected && ctrl.items.length) {
ctrl.activeIndex = _findIndex(ctrl.items, function(item){
return angular.equals(this, item);
}, ctrl.selected);
} else {
ctrl.activeIndex = 0;
}
}
}
}
Expand Down Expand Up @@ -468,11 +477,11 @@ uis.controller('uiSelectCtrl',
ctrl.toggle = function(e) {
if (ctrl.open) {
ctrl.close();
e.preventDefault();
e.stopPropagation();
} else {
ctrl.activate();
}
e.preventDefault();
e.stopPropagation();
};

// Set default function for locked choices - avoids unnecessary
Expand Down
14 changes: 9 additions & 5 deletions src/uiSelectDirective.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
uis.directive('uiSelect',
['$document', 'uiSelectConfig', 'uiSelectMinErr', 'uisOffset', '$compile', '$parse', '$timeout',
function($document, uiSelectConfig, uiSelectMinErr, uisOffset, $compile, $parse, $timeout) {
['$document', 'uiSelectConfig', 'uiSelectMinErr', 'uisOffset', '$compile', '$parse', '$timeout', '$window',
function($document, uiSelectConfig, uiSelectMinErr, uisOffset, $compile, $parse, $timeout, $window) {

return {
restrict: 'EA',
Expand Down Expand Up @@ -206,11 +206,15 @@ uis.directive('uiSelect',
$select.clickTriggeredSelect = false;
}

// See Click everywhere but here event http://stackoverflow.com/questions/12931369
$document.on('click', onDocumentClick);
// See Click everywhere but here. Similar approach to http://stackoverflow.com/questions/12931369
// but using the capture phase instead of bubble phase of the event propagation.
//
// Using the capture phase avoids problems that araise when event.stopPropatagion()
// is called before the event reaches the `document`.
$window.document.addEventListener('click', onDocumentClick, true);

scope.$on('$destroy', function() {
$document.off('click', onDocumentClick);
$window.document.removeEventListener('click', onDocumentClick, true);
});

// Move transcluded elements to their correct position in main template
Expand Down
6 changes: 0 additions & 6 deletions src/uiSelectMultipleDirective.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,6 @@ uis.directive('uiSelectMultiple', ['uiSelectMinErr','$timeout', function(uiSelec
return true;
};

ctrl.getPlaceholder = function(){
//Refactor single?
if($select.selected && $select.selected.length) return;
return $select.placeholder;
};


}],
controllerAs: '$selectMultiple',
Expand Down
4 changes: 4 additions & 0 deletions src/uiSelectSortDirective.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ uis.directive('uiSelectSort', ['$timeout', 'uiSelectConfig', 'uiSelectMinErr', f
}
});

if (element.data('disallowDrop')) {
return;
}

element.on('dragstart', function(event) {
element.addClass(draggingClassName);

Expand Down
119 changes: 112 additions & 7 deletions test/select.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ describe('ui-select tests', function () {
Escape: 27
};

var defaultPlaceholder = 'Pick one...';

function isNil(value) {
return angular.isUndefined(value) || value === null;
}
Expand Down Expand Up @@ -191,6 +193,10 @@ describe('ui-select tests', function () {
return $(el).find('.ui-select-match > span:first > span[ng-transclude]:not(.ng-hide)').text();
}

function getMatchPlaceholder(el) {
return el.find('.ui-select-search').attr('placeholder')
}

function clickItem(el, text) {

if (!isDropdownOpened(el)) {
Expand Down Expand Up @@ -740,6 +746,28 @@ describe('ui-select tests', function () {
el2.remove();
});

it('should close an opened select clicking outside with stopPropagation()', function () {
var el1 = createUiSelect();
var el2 = $('<div></div>');
el1.appendTo(document.body);
el2.appendTo(document.body);

el2.on('click', function (e) {
e.stopPropagation()
});

expect(isDropdownOpened(el1)).toEqual(false);
clickMatch(el1);
expect(isDropdownOpened(el1)).toEqual(true);

// Using a native dom click() to make sure the test fails when it should.
el2[0].click();

expect(isDropdownOpened(el1)).toEqual(false);
el1.remove();
el2.remove();
});

it('should bind model correctly (with object as source)', function () {
var el = compileTemplate(
'<ui-select ng-model="selection.selected"> \
Expand Down Expand Up @@ -846,6 +874,20 @@ describe('ui-select tests', function () {
expect(getMatchLabel(el)).toEqual('-- None Selected --');
});

it('should not have active option when model cleared', function () {
var el = createUiSelect();

clickItem(el, 'Samantha');
expect(el.scope().$select.activeIndex).toBe(5);

scope.selection.selected = null;
scope.$digest();

el.find(".ui-select-toggle").click();

expect(el.scope().$select.activeIndex).toBe(0);
});

describe('backspace reset option', function () {
it('should undefined model when pressing BACKSPACE key if backspaceReset=true', function () {
var el = createUiSelect();
Expand Down Expand Up @@ -1860,7 +1902,9 @@ describe('ui-select tests', function () {
function createUiSelectMultiple(attrs) {
var attrsHtml = '',
choicesAttrsHtml = '',
matchesAttrsHtml = '';
matchesAttrsHtml = '',
matchesPlaceholder = defaultPlaceholder;

if (attrs !== undefined) {
if (attrs.disabled !== undefined) { attrsHtml += ' ng-disabled="' + attrs.disabled + '"'; }
if (attrs.required !== undefined) { attrsHtml += ' ng-required="' + attrs.required + '"'; }
Expand All @@ -1870,24 +1914,26 @@ describe('ui-select tests', function () {
if (attrs.taggingTokens !== undefined) { attrsHtml += ' tagging-tokens="' + attrs.taggingTokens + '"'; }
if (attrs.taggingLabel !== undefined) { attrsHtml += ' tagging-label="' + attrs.taggingLabel + '"'; }
if (attrs.inputId !== undefined) { attrsHtml += ' input-id="' + attrs.inputId + '"'; }
if (attrs.groupBy !== undefined) { choicesAttrsHtml += ' group-by="' + attrs.groupBy + '"'; }
if (attrs.uiDisableChoice !== undefined) { choicesAttrsHtml += ' ui-disable-choice="' + attrs.uiDisableChoice + '"'; }
if (attrs.lockChoice !== undefined) { matchesAttrsHtml += ' ui-lock-choice="' + attrs.lockChoice + '"'; }
if (attrs.removeSelected !== undefined) { attrsHtml += ' remove-selected="' + attrs.removeSelected + '"'; }
if (attrs.resetSearchInput !== undefined) { attrsHtml += ' reset-search-input="' + attrs.resetSearchInput + '"'; }
if (attrs.limit !== undefined) { attrsHtml += ' limit="' + attrs.limit + '"'; }
if (attrs.onSelect !== undefined) { attrsHtml += ' on-select="' + attrs.onSelect + '"'; }
if (attrs.removeSelected !== undefined) { attrsHtml += ' remove-selected="' + attrs.removeSelected + '"'; }
if (attrs.refresh !== undefined) { choicesAttrsHtml += ' refresh="' + attrs.refresh + '"'; }
if (attrs.refreshDelay !== undefined) { choicesAttrsHtml += ' refresh-delay="' + attrs.refreshDelay + '"'; }
if (attrs.spinnerEnabled !== undefined) { attrsHtml += ' spinner-enabled="' + attrs.spinnerEnabled + '"'; }
if (attrs.spinnerClass !== undefined) { attrsHtml += ' spinner-class="' + attrs.spinnerClass + '"'; }
if (attrs.groupBy !== undefined) { choicesAttrsHtml += ' group-by="' + attrs.groupBy + '"'; }
if (attrs.uiDisableChoice !== undefined) { choicesAttrsHtml += ' ui-disable-choice="' + attrs.uiDisableChoice + '"'; }
if (attrs.refresh !== undefined) { choicesAttrsHtml += ' refresh="' + attrs.refresh + '"'; }
if (attrs.refreshDelay !== undefined) { choicesAttrsHtml += ' refresh-delay="' + attrs.refreshDelay + '"'; }
if (attrs.lockChoice !== undefined) { matchesAttrsHtml += ' ui-lock-choice="' + attrs.lockChoice + '"'; }
if (attrs.uiSelectHeaderGroupSelectable !== undefined) { choicesAttrsHtml += ' ui-select-header-group-selectable'; }
}

matchesAttrsHtml += ' placeholder="' + matchesPlaceholder + '"';

return compileTemplate(
'<ui-select multiple ng-model="selection.selectedMultiple"' + attrsHtml + ' theme="bootstrap" style="width: 800px;"> \
<ui-select-match "' + matchesAttrsHtml + ' placeholder="Pick one...">{{$item.name}} &lt;{{$item.email}}&gt;</ui-select-match> \
<ui-select-match ' + matchesAttrsHtml + '>{{$item.name}} &lt;{{$item.email}}&gt;</ui-select-match> \
<ui-select-choices repeat="person in people | filter: $select.search"' + choicesAttrsHtml + '> \
<div ng-bind-html="person.name | highlight: $select.search"></div> \
<div ng-bind-html="person.email | highlight: $select.search"></div> \
Expand Down Expand Up @@ -2958,6 +3004,65 @@ describe('ui-select tests', function () {
triggerKeydown(searchInput, Key.Enter);
expect(el.scope().$select.activeIndex).toBe(2);
});

it('should not display the placeholder when tag is selected (by default)', function () {
var placeholderText = defaultPlaceholder;

var el = createUiSelectMultiple({
tagging: '',
taggingLabel: ''
});

var $select = el.scope().$select; // uiSelectCtrl

expect($select.selected).toEqual([]);
expect($select.getPlaceholder()).toEqual(placeholderText);
expect(getMatchPlaceholder(el)).toEqual(placeholderText); // get placeholder

clickItem(el, scope.people[0].name);
expect($select.selected).toEqual([scope.people[0]]);
expect(getMatchLabel(el)).toEqual(''); // empty text
expect(getMatchPlaceholder(el)).toEqual(''); // empty placeholder

clickItem(el, scope.people[1].name);
expect($select.selected).toEqual([scope.people[0], scope.people[1]]);
expect(getMatchLabel(el)).toEqual('');
expect(getMatchPlaceholder(el)).toEqual('');
});

// Could be needed when e.g. tag is shown below the input
it('should display the placeholder when tag is selected (if user overrides .getPlaceholder())', function () {
var placeholderText = defaultPlaceholder;

var el = createUiSelectMultiple({
tagging: '',
taggingLabel: ''
});
var $select = el.scope().$select;

/**
* In case user wants to show placeholder when the text is empty - they can override $select.getPlaceholder.
* Cannot do this with $selectMultiple, bc <ui-select-multiple is appended inside the library
* This override closes #1796
*/
$select.getPlaceholder = function() {
return $select.placeholder;
};

expect($select.selected).toEqual([]);
expect(getMatchLabel(el)).toEqual('');
expect(getMatchPlaceholder(el)).toEqual(placeholderText);

clickItem(el, scope.people[0].name);
expect($select.selected).toEqual([scope.people[0]]);
expect(getMatchLabel(el)).toEqual(''); // empty text
expect(getMatchPlaceholder(el)).toEqual(placeholderText); // show placeholder

clickItem(el, scope.people[1].name);
expect($select.selected).toEqual([scope.people[0], scope.people[1]]);
expect(getMatchLabel(el)).toEqual('');
expect(getMatchPlaceholder(el)).toEqual(placeholderText);
});
});

describe('resetSearchInput option multiple', function () {
Expand Down

0 comments on commit e166672

Please sign in to comment.