twitter-bootstrap typeahead 控件的向上/向下箭头键问题(角度引导 UI)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27705490/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
up/down arrow key issue with typeahead control (angular bootstrap UI)
提问by ankitd
Check this PLNKR, i have implemented typeaheadcontrol, By default in type ahead control they are not setting any max-height or height to list, but as per requirement i have to fix height of list to 110px. So, when we have longer list at a time only 4 data will be shown and rest can be seen by scrolling down. Scrolling is working while user click on scroll up/down arrows, but it's not working with keyboard up/down keys.
检查这个PLNKR,我已经实现了预先输入控制,默认情况下,在预先输入控制中,他们没有设置任何最大高度或高度到列表,但根据要求,我必须将列表的高度固定为 110px。因此,当我们一次有更长的列表时,只会显示 4 个数据,向下滚动可以看到其余的数据。当用户单击向上/向下滚动箭头时滚动正在工作,但它不适用于键盘向上/向下键。
The problem is explained in steps:-
问题分步骤解释:-
- Type something i.e "a" to get data in typeahead (list will be populated)
- Press down-arrow key (focus will be on list item)
- Press down-arrow key 4-5 time to go further down (When we traverse down to list, scroll is not getting moved.)
- It always show top 4 items in list. Ideal behavior is it should shift.
- 输入一些东西,即“a”以在预先输入中获取数据(列表将被填充)
- 按向下箭头键(焦点将在列表项上)
- 按向下箭头键 4-5 次进一步向下(当我们向下遍历列表时,滚动条不会移动。)
- 它总是显示列表中的前 4 项。理想的行为是它应该转变。
User is able to scroll by clicking on scroll manually but with arrow key it's not scrolling.
用户可以通过手动单击滚动来滚动,但使用箭头键不会滚动。


HTML
HTML
<!doctype html>
<html ng-app="ui.bootstrap.demo">
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.js"></script>
<script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.12.0.js"></script>
<script src="example.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
<link href="style.css" rel="stylesheet">
</head>
<body>
<div class='container-fluid' ng-controller="TypeaheadCtrl">
<h4>Static arrays</h4>
<pre>Model: {{selected | json}}</pre>
<input type="text" ng-model="selected" typeahead="state for state in states | filter:$viewValue | limitTo:8" class="form-control">
</div>
</body>
</html>
CSS
CSS
.dropdown-menu{
height:110px;
overflow:auto;
}
javascript datalist
javascript 数据列表
$scope.states = ['Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorado', 'Connecticut', 'Delaware', 'Florida', 'Georgia', 'Hawaii', 'Idaho', 'Illinois', 'Indiana', 'Iowa', 'Kansas', 'Kentucky', 'Louisiana', 'Maine', 'Maryland', 'Massachusetts', 'Michigan', 'Minnesota', 'Mississippi', 'Missouri', 'Montana', 'Nebraska', 'Nevada', 'New Hampshire', 'New Jersey', 'New Mexico', 'New York', 'North Dakota', 'North Carolina', 'Ohio', 'Oklahoma', 'Oregon', 'Pennsylvania', 'Rhode Island', 'South Carolina', 'South Dakota', 'Tennessee', 'Texas', 'Utah', 'Vermont', 'Virginia', 'Washington', 'West Virginia', 'Wisconsin', 'Wyoming'];
采纳答案by MKB
In this I have override ui-bootstrap typeahead as suggested in the answer.
在此,我按照答案中的建议覆盖了 ui-bootstrap typeahead 。
Following are the changes I need to make it work:
以下是我需要进行的更改:
Added following line in typeaheadMatchdirective (line - 335 of ui.bootstrap.typeahead.js file in the plunker)
在typeaheadMatch指令中添加了以下行(plunker 中 ui.bootstrap.typeahead.js 文件的第 335 行)
element[0].focus();
Added shouldFocusdirective (line - 314 -350)
添加shouldFocus指令(行 - 314 -350)
.directive('shouldFocus', function(){
return {
restrict: 'A',
link: function(scope,element,attrs){
scope.$watch(attrs.shouldFocus,function(newVal,oldVal){
element[0].scrollIntoView(false);
});
}
};
})
and finally added directive in li(line - 372)
最后在li(line - 372) 中添加指令
should-focus=\"isActive($index)\"
回答by JimmyBob
@user1690588 answer works great. Only problem is that when the last item in the list is active and you press the down key. the scrollToView tothe first item does not work. I added a check to ensure newVal is true which seems to fix this.
@ user1690588 答案很好用。唯一的问题是,当列表中的最后一项处于活动状态并且您按下向下键时。scrollToView 到第一项不起作用。我添加了一个检查以确保 newVal 为真,这似乎解决了这个问题。
if (newVal) {
element[0].scrollIntoView(false);
}
回答by almeidap
I used another approach to solve this problem, as none of the solutions here satisfying. Mainly:
我使用了另一种方法来解决这个问题,因为这里的解决方案都不令人满意。主要是:
- reaching the last item and pressing the DOWN key should bring the first item into view
- hovering items with the cursor should not make the Typeahead popup scroll
- using mouse scroll wheel should not trigger weird behaviors on the Typeahead popup
- fix should avoid modifying AngularUI Bootstrap sources
- 到达最后一个项目并按 DOWN 键应该可以看到第一个项目
- 将光标悬停在项目上不应使 Typeahead 弹出窗口滚动
- 使用鼠标滚轮不应在 Typeahead 弹出窗口中触发奇怪的行为
- 修复应该避免修改 AngularUI Bootstrap 源
Extending AngularUI Bootstrap directives and listening to only specific key events seems to provide a cleaner workaround as you can see here: http://plnkr.co/edit/QuZw7j?p=preview
扩展 AngularUI Bootstrap 指令并只收听特定的关键事件似乎提供了一种更清晰的解决方法,正如您在此处看到的:http://plnkr.co/edit/QuZw7j?p=preview
angular.module('ui.bootstrap.demo')
.directive('typeahead', function () {
return {
restrict: 'A',
priority: 1000, // Let's ensure AngularUI Typeahead directive gets initialized first!
link: function (scope, element, attrs) {
// Bind keyboard events: arrows up(38) / down(40)
element.bind('keydown', function (evt) {
if (evt.which === 38 || evt.which === 40) {
// Broadcast a possible change of the currently active option:
// (Note that we could pass the activeIdx value as event data but AngularUI Typeahead directive
// has its own local scope which makes it hard to retrieve, see:
// https://github.com/angular-ui/bootstrap/blob/7b7039b4d94074987fa405ee1174cfe7f561320e/src/typeahead/typeahead.js#L104)
scope.$broadcast('TypeaheadActiveChanged');
}
});
}
};
}).directive('typeaheadPopup', function () {
return {
restrict: 'EA',
link: function (scope, element, attrs) {
var unregisterFn = scope.$on('TypeaheadActiveChanged', function (event, data) {
if(scope.activeIdx !== -1) {
// Retrieve active Typeahead option:
var option = element.find('#' + attrs.id + '-option-' + scope.activeIdx);
if(option.length) {
// Make sure option is visible:
option[0].scrollIntoView(false);
}
}
});
// Ensure listener is unregistered when $destroy event is fired:
scope.$on('$destroy', unregisterFn);
}
};
});
Tested with AngularJS 1.4.5 & AngularUI Bootstrap 0.13.4, but this should work with other recent versions.
已使用 AngularJS 1.4.5 和 AngularUI Bootstrap 0.13.4 进行测试,但这应该适用于其他最新版本。
[Note that I had to manually include jQuery, as the one preloaded by Plunker (jQuery v1.8.3) will fail retrieving the current active option.]
[请注意,我必须手动包含 jQuery,因为由 Plunker (jQuery v1.8.3) 预加载的 jQuery 将无法检索当前活动选项。]
回答by ewahner
The accepted solution will fail if the main window is already scrolling. @user1690588 was on the right track.
如果主窗口已经在滚动,则接受的解决方案将失败。@ user1690588 走在正确的轨道上。
Edit the ui-bootstrap-tpls-0.13.3.js and drop this in around line 5205 above .filter('typeaheadHighlight')at least until the AngularUI team decides to fix this. As well as applying the other change to the template that the accepted solution references.
编辑 ui-bootstrap-tpls-0.13.3.js 并将其放在.filter('typeaheadHighlight')上方的第 5205 行附近,至少直到 AngularUI 团队决定修复此问题为止。以及对接受的解决方案引用的模板应用其他更改。
.directive('shouldFocus', function () {
return {
restrict: 'A',
link: function (scope, element, attrs) {
scope.$watch(attrs.shouldFocus, function (newVal, oldVal) {
if (newVal && element.prop("class").indexOf("active")) {
var par = element.parent("ul");
var scrollingTo = element.offset().top - par.offset().top + par.scrollTop();
// uncomment below section if you want the selected content to be
// viewed at half the box height
// scrollingTo = scrollingTo - (par.height() / 2);
par.scrollTop(scrollingTo);
}
});
}
}
})
Also if you want to get rid of the mouse artifact where it starts scrolling up until it hits the first entry or down till hits the last entry then remove from the template the ng-mouseenterattribute.
此外,如果您想摆脱鼠标工件,它开始向上滚动直到遇到第一个条目或向下滚动直到遇到最后一个条目,然后从模板中删除ng-mouseenter属性。

