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

fix(typeahead): fixed dropdown menu positioning #276

Closed
wants to merge 1 commit into from
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
44 changes: 39 additions & 5 deletions src/typeahead/typeahead.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ angular.module('ui.bootstrap.typeahead', [])
}])

//options - min length
.directive('typeahead', ['$compile', '$q', '$document', 'typeaheadParser', function ($compile, $q, $document, typeaheadParser) {
.directive('typeahead', ['$compile', '$q', '$document', '$window', 'typeaheadParser', function ($compile, $q, $document, $window, typeaheadParser) {

var HOT_KEYS = [9, 13, 27, 38, 40];

Expand Down Expand Up @@ -165,9 +165,28 @@ angular.module('ui.bootstrap.typeahead', [])
resetMatches();
scope.$digest();
});


// Calculate the current position and size of the directive element.
function getPosition( element ) {
var boundingClientRect = element[0].getBoundingClientRect();
return {
width: element.prop( 'offsetWidth' ),
height: element.prop( 'offsetHeight' ),
top: boundingClientRect.top + $window.pageYOffset,
left: boundingClientRect.left + $window.pageXOffset
};
}

scope.elemPos = getPosition(element);
// I need to watch the position because it changes while
// the page is being $parsed and $compiled by angular
scope.$watch(function() { return getPosition(element); }, function(newVal) {
scope.elemPos = newVal;
}, true);

var tplElCompiled = $compile("<typeahead-popup matches='matches' active='activeIdx' select='select(activeIdx)' "+
"query='query'></typeahead-popup>")(scope);
"query='query' position='elemPos'></typeahead-popup>")(scope);

element.after(tplElCompiled);
}
};
Expand All @@ -181,15 +200,21 @@ angular.module('ui.bootstrap.typeahead', [])
matches:'=',
query:'=',
active:'=',
select:'&'
select:'&',
position: '='
},
replace:true,
templateUrl:'template/typeahead/typeahead.html',
link:function (scope, element, attrs) {
link:function (scope, element, attrs, typeaheadCtrl) {

scope.isOpen = function () {
return scope.matches.length > 0;
};

// I need this because ng-show="isOpen()" doesn't do the trick :(
scope.displayStyle = function() {
return scope.isOpen() ? 'block' : 'none';
};

scope.isActive = function (matchIdx) {
return scope.active == matchIdx;
Expand All @@ -202,6 +227,15 @@ angular.module('ui.bootstrap.typeahead', [])
scope.selectMatch = function (activeIdx) {
scope.select({activeIdx:activeIdx});
};

scope.$watch('position', function(newVal) {
var popupPosition = {
left: newVal.left,
top: newVal.top + newVal.height
};

element.css(popupPosition);
});
}
};
})
Expand Down
12 changes: 5 additions & 7 deletions template/typeahead/typeahead.html
Original file line number Diff line number Diff line change
@@ -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: displayStyle() }">
<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>