fix(typeahead): fix matches pop-up positioning issues

Closes #262, #282
This commit is contained in:
Pawel Kozlowski
2013-04-15 21:09:51 +02:00
parent 77d9fa7e13
commit 74beecdb8f
3 changed files with 29 additions and 20 deletions
+4 -5
View File
@@ -200,7 +200,7 @@ describe('typeahead tests', function () {
};
var findDropDown = function(element) {
return element.find('div.dropdown');
return element.find('ul.typeahead');
};
var findMatches = function(element) {
@@ -222,7 +222,7 @@ describe('typeahead tests', function () {
this.message = function() {
return "Expected '" + angular.mock.dump(this.actual) + "' to be closed.";
};
return !typeaheadEl.hasClass('open') && findMatches(this.actual).length === 0;
return typeaheadEl.css('display')==='none' && findMatches(this.actual).length === 0;
}, toBeOpenWithActive: function(noOfMatches, activeIdx) {
@@ -232,7 +232,7 @@ describe('typeahead tests', function () {
this.message = function() {
return "Expected '" + angular.mock.dump(this.actual) + "' to be opened.";
};
return typeaheadEl.hasClass('open') && liEls.length === noOfMatches && $(liEls[activeIdx]).hasClass('active');
return typeaheadEl.css('display')==='block' && liEls.length === noOfMatches && $(liEls[activeIdx]).hasClass('active');
}
});
});
@@ -391,12 +391,11 @@ describe('typeahead tests', function () {
var inputEl = findInput(element);
changeInputValueTo(element, 'b');
var dropdown = findDropDown(element);
$document.find('body').click();
$scope.$digest();
expect(dropdown).not.toHaveClass('open');
expect(element).toBeClosed();
});
});
+20 -8
View File
@@ -1,4 +1,4 @@
angular.module('ui.bootstrap.typeahead', [])
angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position'])
/**
* A helper service that can parse typeahead's syntax (string provided by users)
@@ -29,8 +29,7 @@ angular.module('ui.bootstrap.typeahead', [])
};
}])
//options - min length
.directive('typeahead', ['$compile', '$parse', '$q', '$document', 'typeaheadParser', function ($compile, $parse, $q, $document, typeaheadParser) {
.directive('typeahead', ['$compile', '$parse', '$q', '$document', '$position', 'typeaheadParser', function ($compile, $parse, $q, $document, $position, typeaheadParser) {
var HOT_KEYS = [9, 13, 27, 38, 40];
@@ -51,6 +50,16 @@ angular.module('ui.bootstrap.typeahead', [])
var isLoadingSetter = $parse(attrs.typeaheadLoading).assign || angular.noop;
//pop-up element used to display matches
var popUpEl = angular.element(
"<typeahead-popup " +
"matches='matches' " +
"active='activeIdx' " +
"select='select(activeIdx)' "+
"query='query' "+
"position='position'>"+
"</typeahead-popup>");
//create a child scope for the typeahead directive so we are not polluting original scope
//with typeahead-specific data (matches, query etc.)
var scope = originalScope.$new();
@@ -87,6 +96,11 @@ angular.module('ui.bootstrap.typeahead', [])
}
scope.query = inputValue;
//position pop-up with matches - we need to re-calculate its position each time we are opening a window
//with matches as a pop-up might be absolute-positioned and position of an input might have changed on a page
//due to other elements being rendered
scope.position = $position.position(element);
scope.position.top = scope.position.top + element.prop('offsetHeight');
} else {
resetMatches();
@@ -167,15 +181,12 @@ angular.module('ui.bootstrap.typeahead', [])
}
});
$document.find('body').bind('click', function(){
$document.bind('click', function(){
resetMatches();
scope.$digest();
});
var tplElCompiled = $compile("<typeahead-popup matches='matches' active='activeIdx' select='select(activeIdx)' "+
"query='query'></typeahead-popup>")(scope);
element.after(tplElCompiled);
element.after($compile(popUpEl)(scope));
}
};
@@ -188,6 +199,7 @@ angular.module('ui.bootstrap.typeahead', [])
matches:'=',
query:'=',
active:'=',
position:'=',
select:'&'
},
replace:true,
+5 -7
View File
@@ -1,7 +1,5 @@
<div class="dropdown clearfix" ng-class="{open: isOpen()}">
<ul class="typeahead dropdown-menu">
<li ng-repeat="match in matches" ng-class="{active: isActive($index) }" ng-mouseenter="selectActive($index)">
<a tabindex="-1" ng-click="selectMatch($index)" ng-bind-html-unsafe="match.label | typeaheadHighlight:query"></a>
</li>
</ul>
</div>
<ul class="typeahead dropdown-menu" ng-style="{display: isOpen()&&'block' || 'none', top: position.top+'px', left: position.left+'px'}">
<li ng-repeat="match in matches" ng-class="{active: isActive($index) }" ng-mouseenter="selectActive($index)">
<a tabindex="-1" ng-click="selectMatch($index)" ng-bind-html-unsafe="match.label | typeaheadHighlight:query"></a>
</li>
</ul>