javascript - 有没有办法用子列表迭代无序列表 - 没有 jQuery?

标签 javascript html dom

我想突出显示无序列表“g1”中的每个列表项。 该列表有几个子列表。我想按“向下箭头”和“向上箭头”突出显示下一个项目。我能够迭代外部列表,但是对于子列表,我的解决方案变得非常困惑。有没有比我的纯 JavaScript 更好的方法?

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <title>Family Tree</title>
</head>

<body id='main'>
    <nav>
        <h1 id=pos></h1>
    </nav>
    <ul id='g1' class="special">
        <ul id='generation2'>
            <li>John Williams</li>
            <li>Filippa Williams</li>
            <ul id='generation3'>
                <li>Juan James</li>
                <li>Catarina James</li>
                <li>Aoifa James</li>
            </ul>
            <li>Juan Williams</li>
        </ul>
        <li>Mark Williams</li>
        <li>Christina Johnson</li>
        <li>Christina Johnson</li>
        <li>Christina Johnson</li>
        <li>Juan Williams</li>
        <li>Juan Williams</li>
        <ul id='generation2'>
            <li>John Williams</li>
            <li>Filippa Williams</li>
        </ul>
    </ul>

</body>


</html>



document.onkeydown = function (e) {
    switch (e.keyCode) {
        case 37:
            alert('left');
            break;
        case 38:
            up()
            break;
        case 39:
            alert('right');
            break;
        case 40:
            down();
            break;
    }
};

var pos = -1;
var posSub = -1;
var posSubSub = 0;
var pointer;


function down() {
    var childrensChildren;
    var childrensGrandchildren;
    var gen1 = document.getElementById('g1');
    var gen1children = gen1.children;
    if (pos === -1) {
        gen1children[0].style.backgroundColor = 'yellow';
        pos++;
        document.getElementById('pos').innerHTML = pos;
        return null;
    }
    if (pos == gen1children.length - 1) {
        gen1children[gen1children.length - 1].style.backgroundColor = 'white';
        gen1children[0].style.backgroundColor = 'yellow';
        pos = 0;
        document.getElementById('pos').innerHTML = pos;
        return null;
    }
    if (gen1children[pos].firstElementChild) {
        var childrensChildren = gen1children[pos].children;
        if (childrensChildren.firstChild) {
            childrensGrandchildren = childrensChildren[posSub].children;
            childrensGrandchildren[posSubSub].style.backgroundColor = 'yellow';
            childrensGrandchildren[childrensGrandchildren.length - 1].style.backgroundColor = 'white';
            posSubSub++;
        } else {
            if (posSub === -1) {
                childrensChildren[0].style.backgroundColor = 'yellow';
                posSub++;
                return null;
            }
            if (posSub == childrensChildren.length - 1) {
                childrensChildren[childrensChildren.length - 1].style.backgroundColor = 'white';
                childrensChildren[0].style.backgroundColor = 'yellow';
                return null;
            } else {
                posSub += 1;
                childrensChildren[posSub - 1].style.backgroundColor = 'white';
                childrensChildren[posSub].style.backgroundColor = 'yellow';
                return null;
            }

        }
    }
    gen1children[pos].style.backgroundColor = 'white';
    gen1children[pos + 1].style.backgroundColor = 'yellow';
    pos += 1;
    document.getElementById('pos').innerHTML = pos;
    return null;
}

function up() {
    var gen1 = document.getElementById('g1');
    var gen1children = gen1.children;
    if (pos === -1) {
        gen1children[0].style.backgroundColor = 'yellow';
        pos++;
        document.getElementById('pos').innerHTML = pos;
        return null;
    }
    if (pos == 0) {
        gen1children[gen1children.length - 1].style.backgroundColor = 'yellow';
        gen1children[0].style.backgroundColor = 'white';
        pos = gen1children.length - 1;
        document.getElementById('pos').innerHTML = pos;
        return null;
    }
    gen1children[pos].style.backgroundColor = 'white';
    gen1children[pos - 1].style.backgroundColor = 'yellow';
    pos -= 1;
    document.getElementById('pos').innerHTML = pos;
    return null;
}

最佳答案

您可以快速创建分层 DOM 树中所有 li 项的平面列表,并使用箭头键直观地遍历此列表:

// Flat list of all `li` elements (in expected order)
let allLiElems = Array.from(document.getElementById('g1').getElementsByTagName('li'));

let liInd = null;
let highlightAtInd = ind => {
  // Remove highlight from previous node
  if (liInd !== null) allLiElems[liInd].classList.remove('highlight');
  
  // Apply highlight to next node
  liInd = ind;
  allLiElems[liInd].classList.add('highlight');
};

window.addEventListener('keydown', evt => {
  if (![ 38, 40 ].includes(evt.keyCode)) return;
  
  // Get the new index; ensure it doesn't over/underflow
  let newInd = liInd + ((evt.keyCode === 38) ? -1 : +1);
  if (newInd < 0) newInd = allLiElems.length - 1;
  if (newInd >= allLiElems.length) newInd = 0;
  
  highlightAtInd(newInd);
  
  evt.preventDefault();
});

// Initially highlight the 1st node
highlightAtInd(0);
* { overflow: hidden !important; }
#g1 { font-size: 11px; /* I want this to fit in the preview box */ }
.highlight {
  background-color: rgba(255, 0, 0, 0.3);
}
<ul id='g1' class="special">
  <ul id='generation2'>
    <li>John Williams</li>
    <li>Filippa Williams</li>
    <ul id='generation3'>
      <li>Juan James</li>
      <li>Catarina James</li>
      <li>Aoifa James</li>
    </ul>
    <li>Juan Williams</li>
  </ul>
  <li>Mark Williams</li>
  <li>Christina Johnson</li>
  <li>Christina Johnson</li>
  <li>Christina Johnson</li>
  <li>Juan Williams</li>
  <li>Juan Williams</li>
  <ul id='generation2'>
    <li>John Williams</li>
    <li>Filippa Williams</li>
  </ul>
</ul>

在尝试执行关键事件之前,请确保您已将窗口聚焦!

关于javascript - 有没有办法用子列表迭代无序列表 - 没有 jQuery?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54697866/

相关文章:

javascript - 如何在 reactJS 中使用 AngularJS 指令

javascript - 三.js拖动查看

javascript - 滑动到底部背景图像被压缩时的垂直 slider

jquery 将绝对子项的高度设置为父项

iphone - 如何从 objective-c 中的html页面检索特定数据

javascript - 如何使用 JS/jQuery 处理两个按钮单击(同时向左+向右)?

html - 如何在无需刷新页面的情况下更改不同媒体的 css

javascript - 在 ReactJS 中操作 DOM 是好习惯吗?

javascript - Dom 加载事件跨浏览器原生 javascript 代码

javascript - 为什么jQuery或诸如getElementById之类的DOM方法找不到元素?