Как переключить стрелками подсветку только верхнего элемента списка?
Нужно чтобы при переключении стрелками вверх-вниз менялся цвет фона элемента списка Local Disk(C:), (D:0), (E:). у меня есть отдельно функция ligth, которая меняет цвет подсветки нужного только родительского элемента. FirstChild для li не сработал. Не смогла придумать, как соединить эту функцию с нажатием стрелок. Написала переключение, но оно работает неправильно, подсвечивает и дочерние элементы тоже. Ну и привязано к свойству CSS, чего хотелось бы избежать.
В общем, как привязать функцию ligth, чтобы она работала вместо CSS свойства (li.selected), и как избежать подсветки дочерних элементов.
for (let li of list.querySelectorAll("li")) {
let span = document.createElement("span"); //создает пространство для клика
span.classList.add("show");
li.prepend(span);
span.append(span.nextSibling);
}
list.onclick = function(event) {
if (event.target.tagName != "SPAN") return;
let childrenList = event.target.parentNode.querySelector("ul");
if (!childrenList) return;
childrenList.hidden = !childrenList.hidden;
if (childrenList.hidden) {
event.target.classList.add("hide");
event.target.classList.remove("show");
} else {
event.target.classList.add("show");
event.target.classList.remove("hide");
}
};
//подсветка
const parentLi = list.getElementsByClassName('parent');
for (var i = 0; i < parentLi.length; i++) {
light(parentLi[i].firstChild)
}
function light(parentLi) {
parentLi.addEventListener('mouseover', function() {
this.style.color = 'pink';
this.style.backgroundColor = 'grey';
})
parentLi.addEventListener('mouseout', function() {
this.style.color = 'black';
this.style.backgroundColor = 'white';
})
}
var liSelected;
var index = -1;
document.addEventListener('keydown', function(event) {
var len = parentLi.length - 1;
if (event.which === 40) {
index++;
//down
if (liSelected) {
removeClass(liSelected, 'selected');
next = parentLi[index];
if (typeof next !== undefined && index <= len) {
liSelected = next;
} else {
index = 0;
liSelected = parentLi[0];
}
addClass(liSelected, 'selected');
} else {
index = 0;
liSelected = parentLi[0];
addClass(liSelected, 'selected');
}
} else if (event.which === 38) {
//up
if (liSelected) {
removeClass(liSelected, 'selected');
index--;
next = parentLi[index];
if (typeof next !== undefined && index >= 0) {
liSelected = next;
} else {
index = len;
liSelected = parentLi[len];
}
addClass(liSelected, 'selected');
} else {
index = 0;
liSelected = parentLi[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;
}
};
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
.list span {
cursor: pointer;
}
li.selected {
background-color: aqua;
}
<div>This PC
<ul class="list" id="list">
<li class="parent">Local Dick(C:)
<ul>
<li>Programm Files</li>
<li>Users</li>
<li>Windows</li>
</ul>
</li>
<li class="parent">Local Dick(D:)
<ul>
<li>New Folder 1</li>
<li>New Folder 2</li>
<li>New Folder 3</li>
</ul>
</li>
<li class="parent">Local Dick(E:)
<ul>
<li>Games
<ul>
<li>GTA</li>
<li>Assasin's creed</li>
<li>Skyrim</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
Ответы (1 шт):
Не понял про "привязку", но думаю этот код должен покрывать ваши задачи. Пишите, если нужно пояснить.
const ARROW_UP_CODE = 38
const ARROW_DOWN_CODE = 40
const ENTER_KEY_CODE = 13
const disks = document.querySelectorAll('.disk')
// collapse on click
const getTargetTreeId = (disk) => disk.dataset.collapseTarget
const toggleTreeCollapse = (targetId) => {
const collapseTarget = document.getElementById(targetId)
collapseTarget.classList.toggle('hidden')
}
const diskClickHandler = (ev) => {
const collapseTargetId = getTargetTreeId(ev.target)
toggleTreeCollapse(collapseTargetId)
}
disks.forEach((el) => el.addEventListener('click', diskClickHandler))
// collapse on enter + arrow nav
let selectedDisk = null
const selectDisk = (direction) => {
disks.forEach((el) => el.classList.remove('selected'))
if (selectedDisk === null) {
selectedDisk = 0
} else {
const lastDiskIdx = disks.length - 1
if (direction === 'down') {
if (selectedDisk < lastDiskIdx) {
selectedDisk += 1
} else {
selectedDisk = 0
}
}
if (direction === 'up') {
if (selectedDisk > 0) {
selectedDisk -= 1
} else {
selectedDisk = lastDiskIdx
}
}
}
const selectedDiskEl = disks[selectedDisk]
selectedDiskEl.classList.add('selected')
}
const getPressedBtn = (ev) => {
switch (ev.keyCode) {
case ARROW_UP_CODE:
return 'up';
case ARROW_DOWN_CODE:
return 'down';
case ENTER_KEY_CODE:
return 'enter';
default:
return 'invalid-btn'
}
}
document.addEventListener('keydown', (ev) => {
const pressedBtn = getPressedBtn(ev)
if (pressedBtn === 'enter') {
const isSelected = selectedDisk !== null
if (isSelected) {
const collapseTreeId = disks[selectedDisk].dataset.collapseTarget
toggleTreeCollapse(collapseTreeId)
}
}
if (pressedBtn !== 'invalid-btn') {
selectDisk(pressedBtn)
}
}, false);
h1, h2, h3 {
margin: 0;
font-weight: normal;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
.disk {
cursor: pointer;
transition: background-color 0.25s, color 0.25s;
}
.disk:hover {
color: pink;
background-color: grey !important;
}
.disk.selected {
background-color: aqua;
}
.disk-tree.hidden {
display: none;
}
<div>
<h2>This PC</h2>
<ul class="list" id="list">
<li class="disk-item">
<h3 class="disk" data-collapse-target="disk-c">Local Dick(C:)</h3>
<ul class="disk-tree" id="disk-c">
<li>Programm Files</li>
<li>Users</li>
<li>Windows</li>
</ul>
</li>
<li class="disk-item">
<h3 class="disk" data-collapse-target="disk-d">Local Dick(D:)</h3>
<ul class="disk-tree" id="disk-d">
<li>New Folder 1</li>
<li>New Folder 2</li>
<li>New Folder 3</li>
</ul>
</li>
<li class="disk-item">
<h3 class="disk" data-collapse-target="disk-e">Local Dick(E:)</h3>
<ul class="disk-tree" id="disk-e">
<li>Games
<ul>
<li>GTA</li>
<li>Assasin's creed</li>
<li>Skyrim</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>