Skip to content
This repository was archived by the owner on Sep 5, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions src/components/autocomplete/autocomplete.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
$autocomplete-option-height: 48px !default;
// The default item height is also specified in the JavaScript.
$md-autocomplete-item-height: 48px !default;

@keyframes md-autocomplete-list-out {
0% {
Expand Down Expand Up @@ -201,25 +202,24 @@ md-autocomplete {
.md-virtual-repeat-container.md-autocomplete-suggestions-container {
position: absolute;
box-shadow: 0 2px 5px rgba(black, 0.25);
height: 41px * 5.5;
max-height: 41px * 5.5;
z-index: $z-index-tooltip;
}

.md-virtual-repeat-container.md-not-found {
height: 48px;
height: $md-autocomplete-item-height;
}

.md-autocomplete-suggestions {
margin: 0;
list-style: none;
padding: 0;

li {
font-size: 14px;
overflow: hidden;
padding: 0 15px;
line-height: $autocomplete-option-height;
height: $autocomplete-option-height;
line-height: $md-autocomplete-item-height;
height: $md-autocomplete-item-height;
transition: background 0.15s linear;
margin: 0;
white-space: nowrap;
Expand Down
118 changes: 118 additions & 0 deletions src/components/autocomplete/autocomplete.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1736,6 +1736,26 @@ describe('<md-autocomplete>', function() {

describe('dropdown position', function() {

var DEFAULT_MAX_ITEMS = 5;
var DEFAULT_ITEM_HEIGHT = 48;

var dropdownItems = DEFAULT_MAX_ITEMS;

/**
* Function to create fake matches with the given dropdown items.
* Useful when running tests against the dropdown max items calculations.
* @returns {Array} Fake matches.
*/
function fakeItemMatch() {
var matches = [];

for (var i = 0; i < dropdownItems; i++) {
matches.push('Item ' + i);
}

return matches;
}

it('should adjust the width when the window resizes', inject(function($timeout, $window) {
var scope = createScope();

Expand Down Expand Up @@ -1936,6 +1956,104 @@ describe('<md-autocomplete>', function() {
document.body.removeChild(parent[0]);
}));

it('should calculate the height from the default max items', inject(function($timeout) {
var scope = createScope();

scope.match = fakeItemMatch;

var template =
'<div>' +
'<md-autocomplete ' +
'md-search-text="searchText" ' +
'md-items="item in match(searchText)" ' +
'md-item-text="item" ' +
'md-min-length="0" ' +
'placeholder="placeholder">' +
'<span md-highlight-text="searchText">{{item}}</span>' +
'</md-autocomplete>' +
'</div>';

var parent = compile(template, scope);
var element = parent.find('md-autocomplete');
var ctrl = element.controller('mdAutocomplete');

// Add container to the DOM to be able to test the rect calculations.
document.body.appendChild(parent[0]);

$timeout.flush();

// Focus the autocomplete and trigger a query to be able to open the dropdown.
ctrl.focus();
scope.$apply('searchText = "Query 1"');
waitForVirtualRepeat(element);

var scrollContainer = document.body.querySelector('.md-virtual-repeat-container');

expect(scrollContainer).toBeTruthy();
expect(scrollContainer.style.maxHeight).toBe(DEFAULT_MAX_ITEMS * DEFAULT_ITEM_HEIGHT + 'px');

dropdownItems = 6;

// Trigger a new query to request an update of the items and dropdown.
scope.$apply('searchText = "Query 2"');

// The dropdown should not increase its height because of the new extra item.
expect(scrollContainer.style.maxHeight).toBe(DEFAULT_MAX_ITEMS * DEFAULT_ITEM_HEIGHT + 'px');

document.body.removeChild(parent[0]);
}));

it('should calculate its height from the specified max items', inject(function($timeout) {
var scope = createScope();
var maxDropdownItems = 2;

// Set the current dropdown items to the new maximum.
dropdownItems = maxDropdownItems;
scope.match = fakeItemMatch;

var template =
'<div>' +
'<md-autocomplete ' +
'md-search-text="searchText" ' +
'md-items="item in match(searchText)" ' +
'md-item-text="item" ' +
'md-min-length="0" ' +
'md-dropdown-items="' + maxDropdownItems +'"' +
'placeholder="placeholder">' +
'<span md-highlight-text="searchText">{{item}}</span>' +
'</md-autocomplete>' +
'</div>';

var parent = compile(template, scope);
var element = parent.find('md-autocomplete');
var ctrl = element.controller('mdAutocomplete');

// Add container to the DOM to be able to test the rect calculations.
document.body.appendChild(parent[0]);

$timeout.flush();

// Focus the autocomplete and trigger a query to be able to open the dropdown.
ctrl.focus();
scope.$apply('searchText = "Query 1"');
waitForVirtualRepeat(element);

var scrollContainer = document.body.querySelector('.md-virtual-repeat-container');

expect(scrollContainer).toBeTruthy();
expect(scrollContainer.style.maxHeight).toBe(maxDropdownItems * DEFAULT_ITEM_HEIGHT + 'px');

dropdownItems = 6;

// Trigger a new query to request an update of the items and dropdown.
scope.$apply('searchText = "Query 2"');

// The dropdown should not increase its height because of the new extra item.
expect(scrollContainer.style.maxHeight).toBe(maxDropdownItems * DEFAULT_ITEM_HEIGHT + 'px');

document.body.removeChild(parent[0]);
}));

});

describe('md-highlight-text', function() {
Expand Down
17 changes: 11 additions & 6 deletions src/components/autocomplete/js/autocompleteController.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ angular
.module('material.components.autocomplete')
.controller('MdAutocompleteCtrl', MdAutocompleteCtrl);

var ITEM_HEIGHT = 41,
MAX_HEIGHT = 5.5 * ITEM_HEIGHT,
var ITEM_HEIGHT = 48,
MAX_ITEMS = 5,
MENU_PADDING = 8,
INPUT_PADDING = 2; // Padding provided by `md-input-container`

Expand Down Expand Up @@ -92,7 +92,12 @@ function MdAutocompleteCtrl ($scope, $element, $mdUtil, $mdConstant, $mdTheming,
* @returns {*}
*/
function positionDropdown () {
if (!elements) return $mdUtil.nextTick(positionDropdown, false, $scope);
if (!elements) {
return $mdUtil.nextTick(positionDropdown, false, $scope);
}

var dropdownHeight = ($scope.dropdownItems || MAX_ITEMS) * ITEM_HEIGHT;

var hrect = elements.wrap.getBoundingClientRect(),
vrect = elements.snap.getBoundingClientRect(),
root = elements.root.getBoundingClientRect(),
Expand All @@ -112,14 +117,14 @@ function MdAutocompleteCtrl ($scope, $element, $mdUtil, $mdConstant, $mdTheming,
minWidth: width + 'px',
maxWidth: Math.max(hrect.right - root.left, root.right - hrect.left) - MENU_PADDING + 'px'
};
if (top > bot && root.height - hrect.bottom - MENU_PADDING < MAX_HEIGHT) {
if (top > bot && root.height - hrect.bottom - MENU_PADDING < dropdownHeight) {
styles.top = 'auto';
styles.bottom = bot + 'px';
styles.maxHeight = Math.min(MAX_HEIGHT, hrect.top - root.top - MENU_PADDING) + 'px';
styles.maxHeight = Math.min(dropdownHeight, hrect.top - root.top - MENU_PADDING) + 'px';
} else {
styles.top = (top - offset) + 'px';
styles.bottom = 'auto';
styles.maxHeight = Math.min(MAX_HEIGHT, root.bottom + $mdUtil.scrollTop() - hrect.bottom - MENU_PADDING) + 'px';
styles.maxHeight = Math.min(dropdownHeight, root.bottom + $mdUtil.scrollTop() - hrect.bottom - MENU_PADDING) + 'px';
}

elements.$.scrollContainer.css(styles);
Expand Down
7 changes: 6 additions & 1 deletion src/components/autocomplete/js/autocompleteDirective.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ angular
* will select on case-insensitive match
* @param {string=} md-escape-options Override escape key logic. Default is `blur clear`.<br/>
* Options: `blur | clear`, `none`
* @param {string=} md-dropdown-items Specifies the maximum amount of items to be shown in
* the dropdown.<br/><br/>
* When the dropdown doesn't fit into the viewport, the dropdown will shrink
* as less as possible.
*
* @usage
* ### Basic Example
Expand Down Expand Up @@ -165,7 +169,8 @@ function MdAutocomplete ($$mdSvgRegistry) {
autoselect: '=?mdAutoselect',
menuClass: '@?mdMenuClass',
inputId: '@?mdInputId',
escapeOptions: '@?mdEscapeOptions'
escapeOptions: '@?mdEscapeOptions',
dropdownItems: '=?mdDropdownItems'
},
link: function(scope, element, attrs, controller) {
// Retrieve the state of using a md-not-found template by using our attribute, which will
Expand Down