使用箭头键浏览列表?(JavaScript/JQ)

使用箭头键浏览列表?(JavaScript/JQ),javascript,jquery,navigation,arrow-keys,Javascript,Jquery,Navigation,Arrow Keys,我似乎找不到如何实现这一点的答案,但这是一个我见过好几次的特性。本质上,我是在回显一个列表,我想创建一个功能,可以使用箭头键/enter突出显示和选择这些项目。有人能给我一个想法,我如何才能做到这一点?我知道如何使用键码(当然),只是不知道如何将其转换为功能代码来选择列表中的项目 我在想也许我必须有某种隐藏的单选按钮来标记它是否被选中。。。但即使这样,我也不知道如何在列表中从一个单选按钮跳到另一个单选按钮。如果有人能帮我,我会非常感激。谢谢。由于您没有真正解释您遇到的问题,我只是创建了一个通用解

我似乎找不到如何实现这一点的答案,但这是一个我见过好几次的特性。本质上,我是在回显一个列表,我想创建一个功能,可以使用箭头键/enter突出显示和选择这些项目。有人能给我一个想法,我如何才能做到这一点?我知道如何使用键码(当然),只是不知道如何将其转换为功能代码来选择列表中的项目


我在想也许我必须有某种隐藏的单选按钮来标记它是否被选中。。。但即使这样,我也不知道如何在列表中从一个单选按钮跳到另一个单选按钮。如果有人能帮我,我会非常感激。谢谢。

由于您没有真正解释您遇到的问题,我只是创建了一个通用解决方案。希望这有助于:

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');
        }
    }
});

jsIDLE:

这可能取决于浏览器。 只有当收音机输入彼此相邻(标签也正常)时,它才起作用


但这将破坏Firefox和其他浏览器中的无线电导航:

<div><input type="radio" ... /> ... </div>
<div><input type="radio" ... /> ... </div>
。。。
... 

当您想要使某个内容比简单的列表(类别…)更复杂时,这很烦人。

我的本机JavaScript示例

var ul=document.getElementById('list');
他当选了;
var指数=-1;
document.addEventListener('keydown',函数(事件){
var len=ul.getElementsByTagName('li')。长度为1;
//向下箭头
如果(event.which==40){
索引++;
如果(当选){
removeClass(liSelected,“selected”);
next=ul.getElementsByTagName('li')[index];
if(typeof next!==undefined&&index=0){
liSelected=next;
}
否则{
指数=len;
liSelected=ul.getElementsByTagName('li')[len];
}
addClass(LisSelected,“selected”);
}
否则{
指数=0;
liSelected=ul.getElementsByTagName('li')[len];
addClass(LisSelected,“selected”);
}
}
},假);
函数removeClass(el,类名){
if(el.classList){
el.classList.remove(className);
}否则{
el.className=el.className.replace(新的RegExp(“(^ |\\b)”+className.split(“”).join(“|”)+”(\\b |$),“gi”),“”);
}
};
函数addClass(el,类名){
if(el.classList){
el.classList.add(className);
}否则{
el.className+=''类名称;
}
};
li.selected{背景:黄色}
  • 项目1
  • 项目2
  • 项目3
  • 项目4

2020年更新

如果有人想在Vue.js中执行此操作,我已经在下面添加了代码,并在必要时添加了注释,其余的都是不言自明的

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>
JS

* {
  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;
}
const items = new Array(100).fill(null).map((item, index) => {
  return { id: index, value: "Item " + index };
});

// https://stackoverflow.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"
});
const items=新数组(100).fill(null).map((项目,索引)=>{
返回{id:index,值:“Item”+index};
});
// https://stackoverflow.com/questions/5685589/scroll-to-element-only-if-not-in-view-jquery
功能ScrollIntoViewIfRequired(目标){
var rect=target.getBoundingClientRect();
if(rect.bottom>window.innerHeight){
target.scrollIntoView(false);
}
如果(矩形顶部<0){
target.scrollIntoView();
} 
}
Vue.component(“列表”{
模板:“#列表”,
数据(){
返回{
项目,
已选择的ID:0
};
},
方法:{
选择(项目ID){
this.selectedId=itemId;
ScrollIntoViewIfRequired(此.$refs.root.children[itemId])
//this.$refs.root.children[item.id].scrollIntoView({behavior:“smooth”});
},
handleKeyDown(事件){
开关(event.keyCode){
//如果是左箭头键,则移动到最后一项
案例37:
如果(此选项已选择EDID>0){
this.select(this.selectedId-1);
}
//防止触发默认滚动事件
event.preventDefault();
打破
//如果使用向上箭头键,则移动到最后一项
案例38:
如果(此选项已选择EDID>0){
this.select(this.selectedId-1);
}
event.preventDefault();
打破
//如果是右箭头键,则移动到下一项
案例39:
if(this.selectedId
这正是我遇到的问题,谢谢。如果元素不是链接,你会如何使用键盘的“回车”键来选择元素?如果(e.which==13){$(.selected”)。单击();}。我会添加preventDefault()以防止窗口在“If(e.which==40){e.preventDefault();…}之后向下/向上滚动如果(e.which==38){e.preventDefault();}或
const items = new Array(100).fill(null).map((item, index) => {
  return { id: index, value: "Item " + index };
});

// https://stackoverflow.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"
});