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

Commit 3ab865a

Browse files
committed
Merge pull request #1213 from angular-ui/fix-setting-dropdown-pos
feat(choices): allow to set default dropdown position
2 parents f6b6d81 + a159525 commit 3ab865a

5 files changed

+224
-18
lines changed

examples/demo-dropdown-position.html

+168
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
<!DOCTYPE html>
2+
<html lang="en" ng-app="demo">
3+
<head>
4+
<meta charset="utf-8">
5+
<title>AngularJS ui-select</title>
6+
7+
<!--
8+
IE8 support, see AngularJS Internet Explorer Compatibility http://docs.angularjs.org/guide/ie
9+
For Firefox 3.6, you will also need to include jQuery and ECMAScript 5 shim
10+
-->
11+
<!--[if lt IE 9]>
12+
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.js"></script>
13+
<script src="http://cdnjs.cloudflare.com/ajax/libs/es5-shim/2.2.0/es5-shim.js"></script>
14+
<script>
15+
document.createElement('ui-select');
16+
document.createElement('ui-select-match');
17+
document.createElement('ui-select-choices');
18+
</script>
19+
<![endif]-->
20+
21+
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.18/angular.js"></script>
22+
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.18/angular-sanitize.js"></script>
23+
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.css">
24+
25+
<!-- ui-select files -->
26+
<script src="../dist/select.js"></script>
27+
<link rel="stylesheet" href="../dist/select.css">
28+
29+
<script src="demo.js"></script>
30+
31+
<!-- Select2 theme -->
32+
<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/select2/3.4.5/select2.css">
33+
34+
<!--
35+
Selectize theme
36+
Less versions are available at https://github.com/brianreavis/selectize.js/tree/master/dist/less
37+
-->
38+
<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/selectize.js/0.8.5/css/selectize.default.css">
39+
<!-- <link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/selectize.js/0.8.5/css/selectize.bootstrap2.css"> -->
40+
<!-- <link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/selectize.js/0.8.5/css/selectize.bootstrap3.css"> -->
41+
42+
<style>
43+
body {
44+
padding: 15px;
45+
}
46+
47+
.select2 > .select2-choice.ui-select-match {
48+
/* Because of the inclusion of Bootstrap */
49+
height: 29px;
50+
}
51+
52+
.selectize-control > .selectize-dropdown {
53+
top: 36px;
54+
}
55+
</style>
56+
</head>
57+
58+
<body ng-controller="DemoCtrl">
59+
60+
<h3>Dropdown Position</h3>
61+
62+
<br>
63+
<br>
64+
<br>
65+
66+
<pre>default value can be changed at <strong class="text-warning">uiSelectConfig</strong></pre>
67+
68+
<br>
69+
<br>
70+
<br>
71+
<br>
72+
<br>
73+
<br>
74+
<br>
75+
<br>
76+
<br>
77+
<br>
78+
<br>
79+
<br>
80+
<br>
81+
<br>
82+
<br>
83+
<br>
84+
85+
86+
<p>Always UP</p>
87+
<ui-select ng-model="person.selected" theme="select2" ng-disabled="disabled" style="min-width: 300px;" title="Choose a person">
88+
<ui-select-match placeholder="Select a person in the list or search his name/age...">{{$select.selected.name}}</ui-select-match>
89+
<ui-select-choices repeat="person in people | propsFilter: {name: $select.search, age: $select.search}" position='up'>
90+
<div ng-bind-html="person.name | highlight: $select.search"></div>
91+
<small>
92+
email: {{person.email}}
93+
age: <span ng-bind-html="''+person.age | highlight: $select.search"></span>
94+
</small>
95+
</ui-select-choices>
96+
</ui-select>
97+
98+
<br>
99+
<br>
100+
<br>
101+
<br>
102+
<br>
103+
<br>
104+
<br>
105+
<br>
106+
<br>
107+
<br>
108+
<br>
109+
<br>
110+
111+
112+
<p>Always DOWN</p>
113+
<ui-select ng-model="person.selected" theme="select2" ng-disabled="disabled" style="min-width: 300px;" title="Choose a person">
114+
<ui-select-match placeholder="Select a person in the list or search his name/age...">{{$select.selected.name}}</ui-select-match>
115+
<ui-select-choices repeat="person in people | propsFilter: {name: $select.search, age: $select.search}" position='down'>
116+
<div ng-bind-html="person.name | highlight: $select.search"></div>
117+
<small>
118+
email: {{person.email}}
119+
age: <span ng-bind-html="''+person.age | highlight: $select.search"></span>
120+
</small>
121+
</ui-select-choices>
122+
</ui-select>
123+
124+
<br>
125+
<br>
126+
<br>
127+
<br>
128+
<br>
129+
<br>
130+
<br>
131+
<br>
132+
133+
134+
<p>AUTO depending on available space (default)</p>
135+
<ui-select ng-model="person.selected" theme="select2" ng-disabled="disabled" style="min-width: 300px;" title="Choose a person">
136+
<ui-select-match placeholder="Select a person in the list or search his name/age...">{{$select.selected.name}}</ui-select-match>
137+
<ui-select-choices repeat="person in people | propsFilter: {name: $select.search, age: $select.search}" position='auto'>
138+
<div ng-bind-html="person.name | highlight: $select.search"></div>
139+
<small>
140+
email: {{person.email}}
141+
age: <span ng-bind-html="''+person.age | highlight: $select.search"></span>
142+
</small>
143+
</ui-select-choices>
144+
</ui-select>
145+
146+
<br>
147+
<br>
148+
<br>
149+
<br>
150+
<br>
151+
<br>
152+
<br>
153+
<br>
154+
<br>
155+
<br>
156+
<br>
157+
<br>
158+
<br>
159+
<br>
160+
<br>
161+
<br>
162+
<br>
163+
<br>
164+
<br>
165+
<br>
166+
167+
</body>
168+
</html>

src/common.js

+1
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ var uis = angular.module('ui.select', [])
9393
placeholder: '', // Empty by default, like HTML tag <select>
9494
refreshDelay: 1000, // In milliseconds
9595
closeOnSelect: true,
96+
dropdownPosition: 'auto',
9697
generateId: function() {
9798
return latestId++;
9899
},

src/uiSelectChoicesDirective.js

+2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ uis.directive('uiSelectChoices',
2828
$select.disableChoiceExpression = attrs.uiDisableChoice;
2929
$select.onHighlightCallback = attrs.onHighlight;
3030

31+
$select.dropdownPosition = attrs.position ? attrs.position.toLowerCase() : uiSelectConfig.dropdownPosition;
32+
3133
if(groupByExp) {
3234
var groups = element.querySelectorAll('.ui-select-choices-group');
3335
if (groups.length !== 1) throw uiSelectMinErr('rows', "Expected 1 .ui-select-choices-group but got '{0}'.", groups.length);

src/uiSelectController.js

+2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ uis.controller('uiSelectCtrl',
2929
ctrl.disabled = false;
3030
ctrl.selected = undefined;
3131

32+
ctrl.dropdownPosition = 'auto';
33+
3234
ctrl.focusser = undefined; //Reference to input element used to handle focus events
3335
ctrl.resetSearchInput = true;
3436
ctrl.multiple = undefined; // Initialized inside uiSelect directive link function

src/uiSelectDirective.js

+51-18
Original file line numberDiff line numberDiff line change
@@ -258,10 +258,38 @@ uis.directive('uiSelect',
258258

259259
// Support changing the direction of the dropdown if there isn't enough space to render it.
260260
scope.$watch('$select.open', function() {
261-
scope.calculateDropdownPos();
261+
262+
if ($select.dropdownPosition === 'auto' || $select.dropdownPosition === 'up'){
263+
scope.calculateDropdownPos();
264+
}
265+
262266
});
263267

268+
var setDropdownPosUp = function(offset, offsetDropdown){
269+
270+
offset = offset || uisOffset(element);
271+
offsetDropdown = offsetDropdown || uisOffset(dropdown);
272+
273+
dropdown[0].style.position = 'absolute';
274+
dropdown[0].style.top = (offsetDropdown.height * -1) + 'px';
275+
element.addClass(directionUpClassName);
276+
277+
};
278+
279+
var setDropdownPosDown = function(offset, offsetDropdown){
280+
281+
element.removeClass(directionUpClassName);
282+
283+
offset = offset || uisOffset(element);
284+
offsetDropdown = offsetDropdown || uisOffset(dropdown);
285+
286+
dropdown[0].style.position = '';
287+
dropdown[0].style.top = '';
288+
289+
};
290+
264291
scope.calculateDropdownPos = function(){
292+
265293
if ($select.open) {
266294
dropdown = angular.element(element).querySelectorAll('.ui-select-dropdown');
267295
if (dropdown.length === 0) {
@@ -274,24 +302,29 @@ uis.directive('uiSelect',
274302
// Delay positioning the dropdown until all choices have been added so its height is correct.
275303
$timeout(function(){
276304

277-
element.removeClass(directionUpClassName);
305+
if ($select.dropdownPosition === 'up'){
306+
//Go UP
307+
setDropdownPosUp(offset, offsetDropdown);
308+
309+
}else{ //AUTO
310+
311+
element.removeClass(directionUpClassName);
312+
313+
var offset = uisOffset(element);
314+
var offsetDropdown = uisOffset(dropdown);
315+
316+
//https://code.google.com/p/chromium/issues/detail?id=342307#c4
317+
var scrollTop = $document[0].documentElement.scrollTop || $document[0].body.scrollTop; //To make it cross browser (blink, webkit, IE, Firefox).
318+
319+
// Determine if the direction of the dropdown needs to be changed.
320+
if (offset.top + offset.height + offsetDropdown.height > scrollTop + $document[0].documentElement.clientHeight) {
321+
//Go UP
322+
setDropdownPosUp(offset, offsetDropdown);
323+
}else{
324+
//Go DOWN
325+
setDropdownPosDown(offset, offsetDropdown);
326+
}
278327

279-
var offset = uisOffset(element);
280-
var offsetDropdown = uisOffset(dropdown);
281-
282-
//https://code.google.com/p/chromium/issues/detail?id=342307#c4
283-
var scrollTop = $document[0].documentElement.scrollTop || $document[0].body.scrollTop; //To make it cross browser (blink, webkit, IE, Firefox).
284-
285-
// Determine if the direction of the dropdown needs to be changed.
286-
if (offset.top + offset.height + offsetDropdown.height > scrollTop + $document[0].documentElement.clientHeight) {
287-
//Go UP
288-
dropdown[0].style.position = 'absolute';
289-
dropdown[0].style.top = (offsetDropdown.height * -1) + 'px';
290-
element.addClass(directionUpClassName);
291-
}else{
292-
//Go DOWN
293-
dropdown[0].style.position = '';
294-
dropdown[0].style.top = '';
295328
}
296329

297330
// Display the dropdown once it has been positioned.

0 commit comments

Comments
 (0)