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

Commit cea08ca

Browse files
author
Stefan Zollinger
committed
fix(uiSelectCtrl): properly calculate container width
- Account for paddings on input container in case box-sizing: border-box is set. - Added some tests for this case Closes #1980.
1 parent 2b0b17b commit cea08ca

File tree

3 files changed

+75
-4
lines changed

3 files changed

+75
-4
lines changed

src/common.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,4 +172,24 @@ var uis = angular.module('ui.select', [])
172172
left: boundingClientRect.left + ($window.pageXOffset || $document[0].documentElement.scrollLeft)
173173
};
174174
};
175+
}])
176+
177+
/**
178+
* Gets an elements inner width (width minus padding)
179+
*/
180+
.factory('uisElementInnerWidth',
181+
['$window',
182+
function ($window) {
183+
return $window.jQuery ? getInnerWidthJQuery : getInnerWidth;
184+
185+
function getInnerWidthJQuery(element) {
186+
return element.width();
187+
}
188+
189+
function getInnerWidth(element) {
190+
var style = $window.getComputedStyle(element[0]);
191+
var paddingLeft = parseFloat(style.getPropertyValue('padding-left'));
192+
var paddingRight = parseFloat(style.getPropertyValue('padding-right'));
193+
return element[0].clientWidth - paddingLeft - paddingRight;
194+
}
175195
}]);

src/uiSelectController.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
* put as much logic in the controller (instead of the link functions) as possible so it can be easily tested.
66
*/
77
uis.controller('uiSelectCtrl',
8-
['$scope', '$element', '$timeout', '$filter', '$$uisDebounce', 'uisRepeatParser', 'uiSelectMinErr', 'uiSelectConfig', '$parse', '$injector', '$window',
9-
function($scope, $element, $timeout, $filter, $$uisDebounce, RepeatParser, uiSelectMinErr, uiSelectConfig, $parse, $injector, $window) {
8+
['$scope', '$element', '$timeout', '$filter', '$$uisDebounce', 'uisRepeatParser', 'uiSelectMinErr', 'uiSelectConfig', '$parse', '$injector', '$window', 'uisElementInnerWidth',
9+
function($scope, $element, $timeout, $filter, $$uisDebounce, RepeatParser, uiSelectMinErr, uiSelectConfig, $parse, $injector, $window, uisElementInnerWidth) {
1010

1111
var ctrl = this;
1212

@@ -534,10 +534,9 @@ uis.controller('uiSelectCtrl',
534534
ctrl.sizeSearchInput = function() {
535535

536536
var input = ctrl.searchInput[0],
537-
container = ctrl.$element[0],
538537
calculateContainerWidth = function() {
539538
// Return the container width only if the search input is visible
540-
return container.clientWidth * !!input.offsetParent;
539+
return uisElementInnerWidth(ctrl.$element) * !!input.offsetParent;
541540
},
542541
updateIfVisible = function(containerWidth) {
543542
if (containerWidth === 0) {

test/select.spec.js

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2060,6 +2060,58 @@ describe('ui-select tests', function () {
20602060

20612061
});
20622062

2063+
it('input size should properly account for container paddings if box-sizing is set to border-box', function () {
2064+
var el = createUiSelectMultiple({
2065+
tagging: '',
2066+
taggingLabel: 'false'
2067+
});
2068+
2069+
angular.element(document.body).append(el);
2070+
// Set fixed match item width for easier testing
2071+
var style = $(
2072+
'<style> \
2073+
* { box-sizing: border-box; } \
2074+
.ui-select-container { position: relative; } \
2075+
.ui-select-search { border: 0; } \
2076+
.ui-select-match-item { display: inline-block; overflow: hidden; width: 260px; white-space: nowrap; } \
2077+
</style>'
2078+
);
2079+
$('head').append(style);
2080+
2081+
var searchInput = el.find('.ui-select-search');
2082+
2083+
el.css({
2084+
paddingLeft: '6px',
2085+
paddingRight: '6px'
2086+
});
2087+
2088+
$timeout.flush();
2089+
2090+
var fullWidth = searchInput.outerWidth();
2091+
var matchItemWidth = 260;
2092+
var textNodeWidth = 4;
2093+
2094+
expect(searchInput.outerWidth()).toBe(el.width() - 6); // Full width minus padding
2095+
2096+
clickItem(el, 'Wladimir');
2097+
$timeout.flush();
2098+
// 1 items selected, input should be less than full width minus the invisible text node and one item with
2099+
expect(searchInput.outerWidth()).toBe(fullWidth - textNodeWidth - matchItemWidth ); // remaining width of the row
2100+
2101+
clickItem(el, 'Samantha');
2102+
$timeout.flush();
2103+
// Input should be smaller than before
2104+
expect(searchInput.outerWidth()).toBe(fullWidth - textNodeWidth - (2 * matchItemWidth));
2105+
2106+
clickItem(el, 'Adrian');
2107+
$timeout.flush();
2108+
// Minimum input width is 50px, we should be on a new line now
2109+
expect(searchInput.outerWidth()).toBe(fullWidth);
2110+
2111+
el.remove();
2112+
style.remove();
2113+
});
2114+
20632115
it('should update size of search input use container width', function () {
20642116
scope.selection.selectedMultiple = [scope.people[4], scope.people[5]]; //Wladimir & Samantha
20652117
var el = createUiSelectMultiple({

0 commit comments

Comments
 (0)