使用箭头键浏览列表? (JavaScript/JQ)
Posted
技术标签:
【中文标题】使用箭头键浏览列表? (JavaScript/JQ)【英文标题】:Navigate through list using arrow keys? (JavaScript/JQ) 【发布时间】:2012-02-12 17:43:42 【问题描述】:我似乎无法找到如何完成此任务的答案,但这是我多次看到的功能。本质上,我正在呼应一个列表,我想创建使用箭头键/输入突出显示和选择这些项目的能力。有人可以帮助我了解如何做到这一点吗?我知道如何使用键码(当然),只是不知道如何将其变成功能代码以选择列表中的项目...
我在想也许我必须有某种隐藏的单选按钮来将其标记为选中或未选中...但即便如此我也不知道如何从一个单选按钮跳到另一个单选按钮在列表中。因此,如果有人可以帮我解决这个问题,我将不胜感激。谢谢。
【问题讨论】:
【参考方案1】:由于您没有真正解释您遇到的问题,我只是创建了一个通用解决方案。希望这会有所帮助:
var li = $('li');
var liSelected;
$(window).keydown(function(e)
if(e.which === 40)
if(liSelected)
liSelected.removeClass('selected');
next = liSelected.next();
if(next.length > 0)
liSelected = next.addClass('selected');
else
liSelected = li.eq(0).addClass('selected');
else
liSelected = li.eq(0).addClass('selected');
else if(e.which === 38)
if(liSelected)
liSelected.removeClass('selected');
next = liSelected.prev();
if(next.length > 0)
liSelected = next.addClass('selected');
else
liSelected = li.last().addClass('selected');
else
liSelected = li.last().addClass('selected');
);
JSFiddle:http://jsfiddle.net/Vtn5Y/
【讨论】:
这正是我遇到的麻烦,所以谢谢。 如果元素不是链接,你将如何使用键盘的“Enter”键来选择元素? if(e.which === 13) $(".selected").click(); 我会添加 preventDefault() 以防止窗口向下滚动\向上 - 在 "if (e.which ===40) e.preventDefault();.... else if ( e.which ===38) e.preventDefault(); 或【参考方案2】:我的原生 javascript 示例
var ul = document.getElementById('list');
var liSelected;
var index = -1;
document.addEventListener('keydown', function(event)
var len = ul.getElementsByTagName('li').length-1;
// DOWN ARROW
if(event.which === 40)
index++;
if (liSelected)
removeClass(liSelected, 'selected');
next = ul.getElementsByTagName('li')[index];
if(typeof next !== undefined && index <= len)
liSelected = next;
else
index = 0;
liSelected = ul.getElementsByTagName('li')[0];
addClass(liSelected, 'selected');
console.log(index);
else
index = 0;
liSelected = ul.getElementsByTagName('li')[0];
addClass(liSelected, 'selected');
// UP ARROW
else if (event.which === 38)
if (liSelected)
removeClass(liSelected, 'selected');
index--;
next = ul.getElementsByTagName('li')[index];
if(typeof next !== undefined && index >= 0)
liSelected = next;
else
index = len;
liSelected = ul.getElementsByTagName('li')[len];
addClass(liSelected, 'selected');
else
index = 0;
liSelected = ul.getElementsByTagName('li')[len];
addClass(liSelected, 'selected');
, false);
function removeClass(el, className)
if(el.classList)
el.classList.remove(className);
else
el.className = el.className.replace(new RegExp('(^|\\b)' + className.split(' ').join('|') + '(\\b|$)', 'gi'), ' ');
;
function addClass(el, className)
if(el.classList)
el.classList.add(className);
else
el.className += ' ' + className;
;
li.selected background:yellow
<ul id="list">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
https://jsfiddle.net/m6watqpe/
【讨论】:
【参考方案3】:2020 年更新
如果有人想在 Vue.js 中执行此操作,我已在必要时使用 cmets 添加了下面的代码,其余部分是不言自明的
HTML
<script type="text/x-template" id="list">
<div id="list-container" ref="root">
<div v-for="item in items" :key="item.id" class="list-item" :class="item.id === selectedId ? 'selected': ''" @click="select(item.id)">
item.value
</div>
</div>
</script>
<div id="app">
<list></list>
</div>
CSS
*
padding: 0;
margin: 0;
box-sizing: border-box;
html
height: 100%;
body
height: 100%;
min-height: 100%;
padding: 1rem;
font-family: 'Tahoma', sans-serif;
.list-item
padding: 1rem 0.25rem;
.selected
background: lightyellow;
JS
const items = new Array(100).fill(null).map((item, index) =>
return id: index, value: "Item " + index ;
);
// https://***.com/questions/5685589/scroll-to-element-only-if-not-in-view-jquery
function scrollIntoViewIfNeeded(target)
var rect = target.getBoundingClientRect();
if (rect.bottom > window.innerHeight)
target.scrollIntoView(false);
if (rect.top < 0)
target.scrollIntoView();
Vue.component("list",
template: "#list",
data()
return
items,
selectedId: 0
;
,
methods:
select(itemId)
this.selectedId = itemId;
scrollIntoViewIfNeeded(this.$refs.root.children[itemId])
// this.$refs.root.children[item.id].scrollIntoView( behavior: "smooth" );
,
handleKeyDown(event)
switch (event.keyCode)
// In case of left arrow key move to the last item
case 37:
if (this.selectedId > 0)
this.select(this.selectedId - 1);
// Prevent the default scroll event from firing
event.preventDefault();
break;
// In case of up arrow key, move to the last item
case 38:
if (this.selectedId > 0)
this.select(this.selectedId - 1);
event.preventDefault();
break;
// In case of right arrow key, move to the next item
case 39:
if (this.selectedId < this.items.length - 1)
this.select(this.selectedId + 1);
event.preventDefault();
break;
// In case of down arrow key, move to the next item
case 40:
if (this.selectedId < this.items.length - 1)
this.select(this.selectedId + 1);
event.preventDefault();
break;
,
mounted()
window.addEventListener("keydown", this.handleKeyDown);
,
destroyed()
window.removeEventListener("keydown", this.handleKeyDown);
);
new Vue(
el: "#app"
);
【讨论】:
【参考方案4】:这可能取决于浏览器。 它似乎只有在无线电输入彼此相邻时才有效(标签也可以)。
<input type="radio" ... />
<input type="radio" ... />
<input type="radio" ... />
但这会破坏 Firefox 和其他浏览器中的无线电导航:
<div><input type="radio" ... /> ... </div>
<div><input type="radio" ... /> ... </div>
如果您想制作比简单列表(类别...)更复杂一点的东西,这很烦人。
【讨论】:
以上是关于使用箭头键浏览列表? (JavaScript/JQ)的主要内容,如果未能解决你的问题,请参考以下文章
到达下拉列表时单击iphone移动箭头键,应显示下拉列表内容