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

Commit 6be81d5

Browse files
author
Brian Feister
committed
Catch up with upstream master
Conflicts: src/select.js test/select.spec.js
2 parents c306275 + 3991091 commit 6be81d5

File tree

10 files changed

+136
-21
lines changed

10 files changed

+136
-21
lines changed

src/bootstrap/choices.tpl.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
ng-show="$select.items.length > 0">
44
<li class="ui-select-choices-group">
55
<div class="divider" ng-show="$select.isGrouped && $index > 0"></div>
6-
<div ng-show="$select.isGrouped" class="ui-select-choices-group-label dropdown-header">{{$group.name}}</div>
6+
<div ng-show="$select.isGrouped" class="ui-select-choices-group-label dropdown-header" ng-bind-html="$group.name"></div>
77
<div class="ui-select-choices-row" ng-class="{active: $select.isActive(this), disabled: $select.isDisabled(this)}">
88
<a href="javascript:void(0)" class="ui-select-choices-row-inner"></a>
99
</div>

src/bootstrap/match.tpl.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
ng-disabled="$select.disabled"
44
ng-class="{'btn-default-focus':$select.focus}";
55
ng-click="$select.activate()">
6-
<span ng-show="$select.searchEnabled && $select.isEmpty()" class="text-muted">{{$select.placeholder}}</span>
6+
<span ng-show="$select.isEmpty()" class="text-muted">{{$select.placeholder}}</span>
77
<span ng-hide="$select.isEmpty()" ng-transclude></span>
88
<span class="caret ui-select-toggle" ng-click="$select.toggle($event)"></span>
99
</button>

src/select.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@
2828
padding-left: 0;
2929
}
3030

31+
.select2-locked > .select2-search-choice-close{
32+
display:none;
33+
}
34+
3135
/* Selectize theme */
3236

3337
/* Helper class to show styles when focus */

src/select.js

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@
165165
ctrl.disableChoiceExpression = undefined; // Initialized inside uiSelect directive link function
166166
ctrl.$filter = $filter;
167167
ctrl.taggingTokens = {isActivated: false, tokens: undefined};
168+
ctrl.lockChoiceExpression = undefined; // Initialized inside uiSelect directive link function
168169

169170
ctrl.isEmpty = function() {
170171
return angular.isUndefined(ctrl.selected) || ctrl.selected === null || ctrl.selected === '';
@@ -413,9 +414,24 @@
413414
e.stopPropagation();
414415
};
415416

417+
ctrl.isLocked = function(itemScope, itemIndex) {
418+
var isLocked, item = ctrl.selected[itemIndex];
419+
420+
if (item && !angular.isUndefined(ctrl.lockChoiceExpression)) {
421+
isLocked = !!(itemScope.$eval(ctrl.lockChoiceExpression)); // force the boolean value
422+
item._uiSelectChoiceLocked = isLocked; // store this for later reference
423+
}
424+
425+
return isLocked;
426+
};
427+
416428
// Remove item from multiple select
417429
ctrl.removeChoice = function(index){
418430
var removedChoice = ctrl.selected[index];
431+
432+
// if the choice is locked, can't remove it
433+
if(removedChoice._uiSelectChoiceLocked) return;
434+
419435
var locals = {};
420436
locals[ctrl.parserResult.itemName] = removedChoice;
421437

@@ -937,7 +953,7 @@
937953

938954
scope.$watch('searchEnabled', function() {
939955
var searchEnabled = scope.$eval(attrs.searchEnabled);
940-
$select.searchEnabled = searchEnabled !== undefined ? searchEnabled : true;
956+
$select.searchEnabled = searchEnabled !== undefined ? searchEnabled : uiSelectConfig.searchEnabled;
941957
});
942958

943959
attrs.$observe('disabled', function() {
@@ -1096,6 +1112,7 @@
10961112
$select.parseRepeatAttr(attrs.repeat, groupByExp); //Result ready at $select.parserResult
10971113

10981114
$select.disableChoiceExpression = attrs.uiDisableChoice;
1115+
$select.onHighlightCallback = attrs.onHighlight;
10991116

11001117
if(groupByExp) {
11011118
var groups = element.querySelectorAll('.ui-select-choices-group');
@@ -1109,6 +1126,7 @@
11091126
}
11101127

11111128
choices.attr('ng-repeat', RepeatParser.getNgRepeatExpression($select.parserResult.itemName, '$select.items', $select.parserResult.trackByExp, groupByExp))
1129+
.attr('ng-if', '$select.open') //Prevent unnecessary watches when dropdown is closed
11121130
.attr('ng-mouseenter', '$select.setActiveItem('+$select.parserResult.itemName +')')
11131131
.attr('ng-click', '$select.select(' + $select.parserResult.itemName + ')');
11141132

@@ -1156,6 +1174,7 @@
11561174
return theme + (multi ? '/match-multiple.tpl.html' : '/match.tpl.html');
11571175
},
11581176
link: function(scope, element, attrs, $select) {
1177+
$select.lockChoiceExpression = attrs.uiLockChoice;
11591178
attrs.$observe('placeholder', function(placeholder) {
11601179
$select.placeholder = placeholder !== undefined ? placeholder : uiSelectConfig.placeholder;
11611180
});

src/select2/choices.tpl.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<ul class="ui-select-choices ui-select-choices-content select2-results">
22
<li class="ui-select-choices-group" ng-class="{'select2-result-with-children': $select.isGrouped}">
3-
<div ng-show="$select.isGrouped" class="ui-select-choices-group-label select2-result-label">{{$group.name}}</div>
3+
<div ng-show="$select.isGrouped" class="ui-select-choices-group-label select2-result-label" ng-bind-html="$group.name"></div>
44
<ul ng-class="{'select2-result-sub': $select.isGrouped, 'select2-result-single': !$select.isGrouped}">
55
<li class="ui-select-choices-row" ng-class="{'select2-highlighted': $select.isActive(this), 'select2-disabled': $select.isDisabled(this)}">
66
<div class="select2-result-label ui-select-choices-row-inner"></div>

src/select2/match-multiple.tpl.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
-->
66
<span class="ui-select-match">
77
<li class="ui-select-match-item select2-search-choice" ng-repeat="$item in $select.selected"
8-
ng-class="{'select2-search-choice-focus':$select.activeMatchIndex === $index}">
8+
ng-class="{'select2-search-choice-focus':$select.activeMatchIndex === $index, 'select2-locked':$select.isLocked(this, $index)}">
99
<span uis-transclude-append></span>
1010
<a href="javascript:;" class="ui-select-match-close select2-search-choice-close" ng-click="$select.removeChoice($index)" tabindex="-1"></a>
1111
</li>

src/select2/match.tpl.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<a class="select2-choice ui-select-match"
77
ng-class="{'select2-default': $select.isEmpty()}"
88
ng-click="$select.activate()">
9-
<span ng-show="$select.searchEnabled && $select.isEmpty()" class="select2-chosen">{{$select.placeholder}}</span>
9+
<span ng-show="$select.isEmpty()" class="select2-chosen">{{$select.placeholder}}</span>
1010
<span ng-hide="$select.isEmpty()" class="select2-chosen" ng-transclude></span>
1111
<span class="select2-arrow ui-select-toggle" ng-click="$select.toggle($event)"><b></b></span>
1212
</a>

src/selectize/choices.tpl.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<div ng-show="$select.open" class="ui-select-choices selectize-dropdown single">
22
<div class="ui-select-choices-content selectize-dropdown-content">
33
<div class="ui-select-choices-group optgroup">
4-
<div ng-show="$select.isGrouped" class="ui-select-choices-group-label optgroup-header">{{$group.name}}</div>
4+
<div ng-show="$select.isGrouped" class="ui-select-choices-group-label optgroup-header" ng-bind-html="$group.name"></div>
55
<div class="ui-select-choices-row" ng-class="{active: $select.isActive(this), disabled: $select.isDisabled(this)}">
66
<div class="option ui-select-choices-row-inner" data-selectable></div>
77
</div>

src/selectize/match.tpl.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
<div ng-hide="$select.searchEnabled && ($select.open || $select.isEmpty())" class="ui-select-match" ng-transclude></div>
1+
<div ng-hide="($select.open || $select.isEmpty())" class="ui-select-match" ng-transclude></div>

test/select.spec.js

Lines changed: 105 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use strict';
22

33
describe('ui-select tests', function() {
4-
var scope, $rootScope, $compile, $timeout;
4+
var scope, $rootScope, $compile, $timeout, $injector;
55

66
var Key = {
77
Enter: 13,
@@ -16,11 +16,12 @@ describe('ui-select tests', function() {
1616
};
1717

1818
beforeEach(module('ngSanitize', 'ui.select'));
19-
beforeEach(inject(function(_$rootScope_, _$compile_, _$timeout_) {
19+
beforeEach(inject(function(_$rootScope_, _$compile_, _$timeout_, _$injector_) {
2020
$rootScope = _$rootScope_;
2121
scope = $rootScope.$new();
2222
$compile = _$compile_;
2323
$timeout = _$timeout_;
24+
$injector = _$injector_;
2425
scope.selection = {};
2526

2627
scope.getGroupLabel = function(person) {
@@ -144,6 +145,7 @@ describe('ui-select tests', function() {
144145
var choicesContainerEl = $(el).find('.ui-select-choices');
145146
expect(choicesContainerEl.length).toEqual(1);
146147

148+
openDropdown(el);
147149
var choicesEls = $(el).find('.ui-select-choices-row');
148150
expect(choicesEls.length).toEqual(8);
149151
});
@@ -254,7 +256,7 @@ describe('ui-select tests', function() {
254256
expect(isDropdownOpened(el2)).toEqual(true);
255257

256258
var el3 = createUiSelect();
257-
expect(el3.scope().$select.disabled).toEqual(false);
259+
expect(el3.scope().$select.disabled).toEqual(false || undefined);
258260
clickMatch(el3);
259261
expect(isDropdownOpened(el3)).toEqual(true);
260262
});
@@ -401,12 +403,14 @@ describe('ui-select tests', function() {
401403
});
402404

403405
it('should set a disabled class on the option', function() {
404-
var option = $(this.el).find('.ui-select-choices-row div:contains("Wladimir")');
405-
var container = option.closest('.ui-select-choices-row');
406406

407407
openDropdown(this.el);
408408

409+
var option = $(this.el).find('.ui-select-choices-row div:contains("Wladimir")');
410+
var container = option.closest('.ui-select-choices-row');
411+
409412
expect(container.hasClass('disabled')).toBeTruthy();
413+
410414
});
411415
});
412416

@@ -432,11 +436,11 @@ describe('ui-select tests', function() {
432436
});
433437

434438
it('should set a disabled class on the option', function() {
439+
openDropdown(this.el);
440+
435441
var option = $(this.el).find('.ui-select-choices-row div:contains("Wladimir")');
436442
var container = option.closest('.ui-select-choices-row');
437443

438-
openDropdown(this.el);
439-
440444
expect(container.hasClass('disabled')).toBeTruthy();
441445
});
442446
});
@@ -463,11 +467,11 @@ describe('ui-select tests', function() {
463467
});
464468

465469
it('should set a disabled class on the option', function() {
470+
openDropdown(this.el);
471+
466472
var option = $(this.el).find('.ui-select-choices-row div:contains("Wladimir")');
467473
var container = option.closest('.ui-select-choices-row');
468474

469-
openDropdown(this.el);
470-
471475
expect(container.hasClass('disabled')).toBeTruthy();
472476
});
473477
});
@@ -519,9 +523,8 @@ describe('ui-select tests', function() {
519523
var el = createUiSelect();
520524
el.scope().$select.search = 't';
521525
scope.$digest();
522-
var choices = el.find('.ui-select-choices-row');
523-
524526
openDropdown(el);
527+
var choices = el.find('.ui-select-choices-row');
525528

526529
expect(choices.eq(0)).toHaveClass('active');
527530
expect(getGroupLabel(choices.eq(0)).text()).toBe('Foo');
@@ -759,6 +762,35 @@ describe('ui-select tests', function() {
759762

760763
});
761764

765+
it('should invoke hover callback', function(){
766+
767+
var highlighted;
768+
scope.onHighlightFn = function ($item) {
769+
highlighted = $item;
770+
};
771+
772+
var el = compileTemplate(
773+
'<ui-select on-select="onSelectFn($item, $model)" ng-model="selection.selected"> \
774+
<ui-select-match placeholder="Pick one...">{{$select.selected.name}}</ui-select-match> \
775+
<ui-select-choices on-highlight="onHighlightFn(person)" repeat="person.name as person in people | filter: $select.search"> \
776+
<div ng-bind-html="person.name | highlight: $select.search"></div> \
777+
<div ng-bind-html="person.email | highlight: $select.search"></div> \
778+
</ui-select-choices> \
779+
</ui-select>'
780+
);
781+
782+
expect(highlighted).toBeFalsy();
783+
784+
if (!isDropdownOpened(el)){
785+
openDropdown(el);
786+
}
787+
788+
$(el).find('.ui-select-choices-row div:contains("Samantha")').trigger('mouseover');
789+
scope.$digest();
790+
791+
expect(highlighted).toBe(scope.people[5]);
792+
})
793+
762794
it('should set $item & $model correctly when invoking callback on select and no single prop. binding', function () {
763795

764796
scope.onSelectFn = function ($item, $model, $label) {
@@ -878,6 +910,7 @@ describe('ui-select tests', function() {
878910
</ui-select>'
879911
);
880912

913+
openDropdown(el);
881914
expect($(el).find('.only-once').length).toEqual(1);
882915

883916

@@ -993,12 +1026,12 @@ describe('ui-select tests', function() {
9931026
describe('selectize theme', function() {
9941027

9951028
it('should show search input when true', function() {
996-
setupSelectComponent('true', 'selectize');
1029+
setupSelectComponent(true, 'selectize');
9971030
expect($(el).find('.ui-select-search')).not.toHaveClass('ng-hide');
9981031
});
9991032

10001033
it('should hide search input when false', function() {
1001-
setupSelectComponent('false', 'selectize');
1034+
setupSelectComponent(false, 'selectize');
10021035
expect($(el).find('.ui-select-search')).toHaveClass('ng-hide');
10031036
});
10041037

@@ -1507,5 +1540,64 @@ describe('ui-select tests', function() {
15071540
});
15081541
});
15091542

1543+
describe('default configuration via uiSelectConfig', function() {
1544+
1545+
describe('searchEnabled option', function() {
1546+
1547+
function setupWithoutAttr(){
1548+
return compileTemplate(
1549+
'<ui-select ng-model="selection.selected"> \
1550+
<ui-select-match placeholder="Pick one...">{{$select.selected.name}}</ui-select-match> \
1551+
<ui-select-choices repeat="person in people | filter: $select.search"> \
1552+
<div ng-bind-html="person.name | highlight: $select.search"></div> \
1553+
<div ng-bind-html="person.email | highlight: $select.search"></div> \
1554+
</ui-select-choices> \
1555+
</ui-select>'
1556+
);
1557+
}
15101558

1559+
function setupWithAttr(searchEnabled){
1560+
return compileTemplate(
1561+
'<ui-select ng-model="selection.selected" search-enabled="'+searchEnabled+'"> \
1562+
<ui-select-match placeholder="Pick one...">{{$select.selected.name}}</ui-select-match> \
1563+
<ui-select-choices repeat="person in people | filter: $select.search"> \
1564+
<div ng-bind-html="person.name | highlight: $select.search"></div> \
1565+
<div ng-bind-html="person.email | highlight: $select.search"></div> \
1566+
</ui-select-choices> \
1567+
</ui-select>'
1568+
);
1569+
}
1570+
1571+
it('should be true by default', function(){
1572+
var el = setupWithoutAttr();
1573+
expect(el.scope().$select.searchEnabled).toBe(true);
1574+
});
1575+
1576+
it('should disable search if default set to false', function(){
1577+
var uiSelectConfig = $injector.get('uiSelectConfig');
1578+
uiSelectConfig.searchEnabled = false;
1579+
1580+
var el = setupWithoutAttr();
1581+
expect(el.scope().$select.searchEnabled).not.toBe(true);
1582+
});
1583+
1584+
it('should be overridden by inline option search-enabled=true', function(){
1585+
var uiSelectConfig = $injector.get('uiSelectConfig');
1586+
uiSelectConfig.searchEnabled = false;
1587+
1588+
var el = setupWithAttr(true);
1589+
expect(el.scope().$select.searchEnabled).toBe(true);
1590+
});
1591+
1592+
it('should be overridden by inline option search-enabled=false', function(){
1593+
var uiSelectConfig = $injector.get('uiSelectConfig');
1594+
uiSelectConfig.searchEnabled = true;
1595+
1596+
var el = setupWithAttr(false);
1597+
expect(el.scope().$select.searchEnabled).not.toBe(true);
1598+
});
1599+
1600+
});
1601+
1602+
});
15111603
});

0 commit comments

Comments
 (0)