如何在div之间实现箭头键导航

时间:2015-04-11 18:50:20

标签: html css

我有以下div列表

<div id="multi-picker">
  <div id="opt1">
     <input type="checkbox">  Option 1
  </div>
  <div id="opt2">
     <input type="checkbox">  Option 2
  </div>
  etc...
</div>

一切正常,但我对键盘导航不满意。要从opt1导航到opt2,我需要按Tab键。理想情况下,我想将选项视为选择,并使用向上/向下箭头导航。可以这样做吗?

...可替换地 是否有任何方法可以使用带有复选框样式的选项进行多选,以反映每个选项的选择状态?

4 个答案:

答案 0 :(得分:7)

我认为您需要使用javascript并使用插件是完成任务维护跨浏览器功能的更简单方法。但是,这里有一个fiddle,我认为,只需使用javascript即可。它定义了select元素的附加属性,并使用onkeydown函数来处理元素之间的导航。

function keyPressed(e) {
    var srcElement = e.target;    // get the element that fired the onkeydown function
    var dataset = false;
    var selectList = false;
    var next = "";
    var prev = "";
    if (srcElement.dataset) {        // can we use HTML5 dataset?
        dataset = true;              // remember for later
        // is this an element for which we care
        if (srcElement.dataset.selectlist == 'true') {
            selectList = true;
        }
    } else {    // can't use HTML5 dataset, use getAttribute
        if (srcElement.getAttribute('data-selectlist') == 'true') {
            selectList = true;
        }
    }
    // is it a select element and the user pressed either up arrow or down arrow
    if (selectList && (e.keyCode == '38' || e.keyCode == '40')) {
        // get the next and prev navigation options for this element
        if (dataset) {
            next = srcElement.dataset.next;
            prev = srcElement.dataset.prev;
        } else {
            next = srcElement.getAttribute('data-next');
            prev = srcElement.getAttribute('data-prev');
        }
        // up arrow was pressed and a prev element is defined
        if (e.keyCode == '38' && prev != '') {
            document.getElementById(prev).focus();
        }
        // down arrow was pressed and a next element is defined
        if (e.keyCode == '40' && next != '') {
            document.getElementById(next).focus();
        }
        // don't do native processing of the up or down arrow (page scrolling)
        e.preventDefault;
    }
}
document.onkeydown = keyPressed;

以下是包含其他元素的新html:

<div id="multi-picker">
    <div id="opt1">
        <input id="select1" type="checkbox" data-selectlist="true" data-prev="" data-next="select2">  Option 1
    </div>
    <div id="opt2">
        <input id="select2" type="checkbox" data-selectlist="true" data-prev="select1" data-next="">  Option 2
    </div>
</div>

此代码非常特定于所提出的问题,虽然它可以解决问题,但使用通用插件可能会更好,这样可以在整个环境中实现更广泛的应用。您可能还会遇到与用户期望向下和向上箭头键相关的问题,以及通过拦截它们所做的事情。

根据我的经验,我遇到了不同浏览器甚至不同的最终用户平台对应用程序呈现不同行为的问题,这使得实现一致性变得不稳定。许多插件旨在消除这种不一致性,并提供更清晰,更直观的界面。

答案 1 :(得分:2)

  

或者......是否有任何方法可以使用带有复选框的选项进行多选,以反映每个选项的选择状态?

是否有multi-browser支持?并不是的。但是,如果你是&#34; 它适用于Chrome,则会发货!&#34;键入dev,然后你可以完全伪造multi select似乎有一个复选框,反映每个选项的选择状态与良好的ol&#39; CSS

首先我们的HTML:

<select multiple="multiple">
    <option>Hello</option>
    <option>World</option>
    <option>Hello</option>
    <option>World</option>
</select>

A simple select...

接下来,dat CSS:

select {
    border: none;
}
select:focus {
    outline: none;
}
select option:before {
    display: inline-block;
    content: '';
    width: 13px;
    height: 13px;
    position: relative;
    margin-right: 3px;
    background-image: url('http://i.imgur.com/5xszy3H.png');
    background-position: -40px 0px;
    top: 2px;
}

option with generated content

使用generated content,我们现在已经应用了pseudo checkboxes。让我们添加CSS的最后一位,以便为我们提供正确的selected状态!

select option:checked:before {
    background-position: -40px -40px;
}

:checked state applied

WOOP。

这里有一个小提琴:http://jsfiddle.net/9tLz6ugz/

在(有限)测试中,这似乎仅适用于Chrome和FireFox(两者都是最新的OSX)。 Safari,IE和Opera一起忽略了生成的内容。所以,虽然不实用(至少不是今天),但它有点可行!

(这里是另一个没有background-image的小提琴 - 需要更多的工作来使浏览器的外观/感觉保持一致:http://jsfiddle.net/wpch98tg/但是确实使用了unicode来实现假a&#34;复选框&#34;在多选...中

答案 2 :(得分:1)

我不相信你会找到一种简单的HTML&amp; amp; CSS - 这对于定制核心功能来说太过分了,所以一些JavaScript应该可以解决这个问题(我也使用jQuery来使它更容易)。

对于我的测试,我使用<label>而不是<div>来包装复选框,但同样的想法适用于div。我只是喜欢标签,所以如果JavaScript没有加载,复选框仍然是可点击的。

<div class="fake-select">
    <label for="fs1"><input type="checkbox" id="fs1" name="fs1" />Fake 1</label>
    <label for="fs2"><input type="checkbox" id="fs2" name="fs2" />Fake 2</label>
    [ ... ]
</div>

基本上,您需要跟踪用户的按键和&#34;活动&#34;输入。查找向上/向下箭头键按下并根据该按钮更改活动输入(滚动到它,为样式添加类名)。我还允许空格键选中/取消选中当前活动的框。

var fs = $(".fake-select"),
    items = fs.find('input'),
    divs = fs.find('label'),
    active = 0;

// Hook keypresses
fs.keydown( function(e){
    reCalculate(e);
    rePosition();
    return false;
});

// Click event for manual changes
items.unbind('click').click(function(e){
    var thisInput = $(this),
        thisLabel = $(this).parent();
    window.active = thisLabel.index();

    thisLabel.removeClass("checked");
    if (thisInput.is(":checked"))
        thisLabel.addClass("checked");

    rePosition();
});

// Set new active element based on keypress
//    Trigger click event if user hits space bar
function reCalculate(e){
    var max = items.length -1,
        cur = window.active,
        charCode = (typeof e.which == "number" && e.which) ? e.which : e.keyCode;

    if (charCode == 38) { // move up
        cur--;
        cur = (cur <= 0) ? 0 : cur;
    }
    if (charCode == 40) { // move down
        cur++;
        cur = (cur >= max) ? max : cur;
    }
    if (charCode == 32) { // space bar
        items.eq(cur).focus().trigger('click');
    }
    window.active = cur;
}

// Add active class, call scroll function
function rePosition(){
    divs.removeClass('active').eq(window.active).addClass('active');
    scrollInView();
}

// Scroll the list so the active element is in view
function scrollInView(){
    var target = divs.eq(window.active);
    if (target.length) {
        var top = fs.scrollTop() + target.position().top - fs.height()/2 + target.height()/2

        fs.stop().animate({scrollTop: top}, 400);
    }
    return false;
}

jsFiddle示例:http://jsfiddle.net/daCrosby/kqecngv0/13/

答案 3 :(得分:0)

你能用jQuery吗?这将通过向上/向下箭头

激活对焦功能
function focusOnCheckboxes(locator){

var checkboxes = jQuery(locator).find(':checkbox');
var index = 0;

jQuery(locator).on('keydown', function(e){
    if(  e.keyCode == 38 ){
        if(index > 0){
            index = index - 1;
        }
        checkboxes[index].focus();
    }
    else if(e.keyCode == 40){
        if(index < checkboxes.length - 1){
           index = index + 1;     
        }
        else{
             index = checkboxes.length - 1;   
        }
        checkboxes[index].focus();
    }
    else{
        //console.log(e.keyCode);
    }
});
}

// set the locator
focusOnCheckboxes('body');