Skip to content
This repository was archived by the owner on Sep 5, 2024. It is now read-only.
Closed
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
32 changes: 29 additions & 3 deletions src/components/autocomplete/autocomplete.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ describe('<md-autocomplete>', function() {

scope.asyncMatch = function(term) {
return $timeout(function() {
return scope.match(term)
return scope.match(term);
}, 1000);
};

Expand Down Expand Up @@ -702,7 +702,7 @@ describe('<md-autocomplete>', function() {
return {display: item};
});
var scope = createScope(myItems);

var template = '\
<md-autocomplete\
md-selected-item="selectedItem"\
Expand Down Expand Up @@ -740,7 +740,7 @@ describe('<md-autocomplete>', function() {

expect(scope.searchText).toBe('foo ');
expect(scope.selectedItem).toBe(scope.match(scope.searchText)[0]);

ctrl.clear();
$timeout.flush();

Expand Down Expand Up @@ -1125,6 +1125,32 @@ describe('<md-autocomplete>', function() {
element.remove();
}));

it('should log a warning if the display text does not evaluate to a string',
inject(function($log) {
spyOn($log, 'warn');

var scope = createScope();

var template =
'<md-autocomplete ' +
'md-selected-item="selectedItem" ' +
'md-search-text="searchText"' +
'md-items="item in match(searchText)"> ' +
'</md-autocomplete>';

var element = compile(template, scope);

scope.$apply(function() {
scope.selectedItem = { display: 'foo' };
});

expect($log.warn).toHaveBeenCalled();
expect($log.warn.calls.mostRecent().args[0]).toMatch(/md-item-text/);

element.remove();
})
);

});

describe('xss prevention', function() {
Expand Down
21 changes: 14 additions & 7 deletions src/components/autocomplete/js/autocompleteController.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ var ITEM_HEIGHT = 41,
INPUT_PADDING = 2; // Padding provided by `md-input-container`

function MdAutocompleteCtrl ($scope, $element, $mdUtil, $mdConstant, $mdTheming, $window,
$animate, $rootElement, $attrs, $q) {
$animate, $rootElement, $attrs, $q, $log) {

// Internal Variables.
var ctrl = this,
Expand Down Expand Up @@ -194,7 +194,7 @@ function MdAutocompleteCtrl ($scope, $element, $mdUtil, $mdConstant, $mdTheming,

angular.element($window).off('resize', positionDropdown);
if ( elements ){
var items = 'ul scroller scrollContainer input'.split(' ');
var items = ['ul', 'scroller', 'scrollContainer', 'input'];
angular.forEach(items, function(key){
elements.$[key].remove();
});
Expand All @@ -207,8 +207,8 @@ function MdAutocompleteCtrl ($scope, $element, $mdUtil, $mdConstant, $mdTheming,
function gatherElements () {
elements = {
main: $element[0],
scrollContainer: $element[0].getElementsByClassName('md-virtual-repeat-container')[0],
scroller: $element[0].getElementsByClassName('md-virtual-repeat-scroller')[0],
scrollContainer: $element[0].querySelector('.md-virtual-repeat-container'),
scroller: $element[0].querySelector('.md-virtual-repeat-scroller'),
ul: $element.find('ul')[0],
input: $element.find('input')[0],
wrap: $element.find('md-autocomplete-wrap')[0],
Expand Down Expand Up @@ -290,7 +290,7 @@ function MdAutocompleteCtrl ($scope, $element, $mdUtil, $mdConstant, $mdTheming,
return function() {
element.off('wheel', preventDefault);
element.off('touchmove', preventDefault);
}
};
}

/**
Expand Down Expand Up @@ -335,7 +335,7 @@ function MdAutocompleteCtrl ($scope, $element, $mdUtil, $mdConstant, $mdTheming,
// Clear the searchText, when the selectedItem is set to null.
// Do not clear the searchText, when the searchText isn't matching with the previous
// selected item.
if (displayValue.toLowerCase() === $scope.searchText.toLowerCase()) {
if (displayValue.toString().toLowerCase() === $scope.searchText.toLowerCase()) {
$scope.searchText = '';
}
});
Expand Down Expand Up @@ -531,7 +531,14 @@ function MdAutocompleteCtrl ($scope, $element, $mdUtil, $mdConstant, $mdTheming,
* @returns {*}
*/
function getDisplayValue (item) {
return $q.when(getItemText(item) || item);
return $q.when(getItemText(item) || item).then(function(itemText) {
if (itemText && !angular.isString(itemText)) {
$log.warn('md-autocomplete: Could not resolve display value to a string. ' +
'Please check the `md-item-text` attribute.');
}

return itemText;
});

/**
* Getter function to invoke user-defined expression (in the directive)
Expand Down
4 changes: 2 additions & 2 deletions src/components/autocomplete/js/highlightController.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ function MdHighlightCtrl ($scope, $element, $attrs) {
};
}, function (state, prevState) {
if (text === null || state.unsafeText !== prevState.unsafeText) {
text = angular.element('<div>').text(state.unsafeText).html()
text = angular.element('<div>').text(state.unsafeText).html();
}
if (regex === null || state.term !== prevState.term) {
regex = getRegExp(state.term, flags);
Expand All @@ -28,7 +28,7 @@ function MdHighlightCtrl ($scope, $element, $attrs) {
}

function sanitize (term) {
return term && term.replace(/[\\\^\$\*\+\?\.\(\)\|\{}\[\]]/g, '\\$&');
return term && term.toString().replace(/[\\\^\$\*\+\?\.\(\)\|\{}\[\]]/g, '\\$&');
}

function getRegExp (text, flags) {
Expand Down