6.5. Демонстрация - Красим списки
Шаг 1
Перед тем, как перейти непосредственно к окраске, немного подготовимся: возьмём ноду с корнем списка из DOM и перенесём список цветов.
const root = document.getElementById('root');
const colors = ['#DCD6F7', '#A6B1E1', '#B4869F'];
Шаг 2
Для начала напишем обычный обход дерева в ширину и попробуем окрасить список в случайные цвета, чтобы убедиться, что все ноды действительно обходятся. Теперь список выглядит слишком пёстро и несуразно, возможно, из технологов плохие дизайнеры...
const root = document.getElementById('root');
const colors = ['#DCD6F7', '#A6B1E1', '#B4869F'];
function color(node) {
// та же очередь для просмотра нод
const queue = [];
queue.push(node);
// обходим все ноды из списка
while(queue.length) {
// получаем ноду из списка
const currentNode = queue.shift();
// красим её
const randomColorIndex = Math.floor(Math.random() * colors.length);
currentNode.style.backgroundColor = colors[randomColorIndex];
// и кладем в очередь всех потомков
queue.push(...currentNode.children);
}
}
color(root);
Шаг 3
Нетрудно заметить, что мы красим не только li, как нам надо по условию задания, но и вообще все элементы! Исправим это.
const root = document.getElementById('root');
const colors = ['#DCD6F7', '#A6B1E1', '#B4869F'];
const elementToStyle = 'LI';
function color(node) {
// та же очередь для просмотра нод
const queue = [];
queue.push(node);
// обходим все ноды из списка
while(queue.length) {
// получаем ноду из списка
const currentNode = queue.shift();
// если это нода, которую нам нужно красить ...
if (currentNode.tagName === elementToStyle) {
// ... красим её
const randomColorIndex = Math.floor(Math.random() * colors.length);
currentNode.style.backgroundColor = colors[randomColorIndex];
}
// и кладем в очередь всех потомков
queue.push(...currentNode.children);
}
}
color(root);
Шаг 4
А теперь надо как-то понять, на каком уровне вложенности мы находимся. Самый простой способ это сделать — просто присвоить эту информацию прямо в элемент очереди! Тогда во время добавления новых элементов в очередь, если мы дошли до новой вложенности (встретили li), будем ставить им вложенность в текущая + 1.
const root = document.getElementById('root');
const colors = ['#DCD6F7', '#A6B1E1', '#B4869F'];
const elementToStyle = 'LI';
function color(node) {
// та же очередь для просмотра нод
const queue = [];
queue.push({
node,
depth: 0,
});
// обходим все ноды из списка
while(queue.length) {
// получаем ноду из списка
const {node: currentNode, depth: currentDepth} = queue.shift();
const isStylable = currentNode.tagName === elementToStyle
// если это нода, которую нам нужно красить ...
if (isStylable) {
// ... красим её
const randomColorIndex = Math.floor(Math.random() * colors.length);
currentNode.style.backgroundColor = colors[randomColorIndex];
}
// и кладем в очередь всех потомков с обновленной глубиной
for (const node of currentNode.children) {
queue.push({
node,
depth: isStylable ? currentDepth + 1 : currentDepth,
})
}
}
}
color(root);
Шаг 5
Теперь осталось только красить в цвет подстать глубине.
const root = document.getElementById('root');
const colors = ['#DCD6F7', '#A6B1E1', '#B4869F'];
const elementToStyle = 'LI';
function color(node) {
// та же очередь для просмотра нод
const queue = [];
queue.push({
node,
depth: 0,
});
// обходим все ноды из списка
while(queue.length) {
// получаем ноду из списка
const {node: currentNode, depth: currentDepth} = queue.shift();
const isStylable = currentNode.tagName === elementToStyle
// если это нода, которую нам нужно красить ...
if (isStylable) {
// ... красим её
currentNode.style.backgroundColor = colors[currentDepth];
}
// и кладем в очередь всех потомков с обновленной глубиной
for (const node of currentNode.children) {
queue.push({
node,
depth: isStylable ? currentDepth + 1 : currentDepth,
})
}
}
}
color(root);
Шаг 6
И конечно, не забыть обработать случай вложенности больше трёх!
const root = document.getElementById('root');
const colors = ['#DCD6F7', '#A6B1E1', '#B4869F'];
const elementToStyle = 'LI';
function color(node) {
// та же очередь для просмотра нод
const queue = [];
queue.push({
node,
depth: 0,
});
// обходим все ноды из списка
while(queue.length) {
// получаем ноду из списка
const {node: currentNode, depth: currentDepth} = queue.shift();
const isStylable = currentNode.tagName === elementToStyle
// если это нода, которую нам нужно красить ...
if (isStylable) {
// ... красим её
currentNode.style.backgroundColor = colors[currentDepth % 3];
}
// и кладем в очередь всех потомков с обновленной глубиной
for (const node of currentNode.children) {
queue.push({
node,
depth: isStylable ? currentDepth + 1 : currentDepth,
})
}
}
}
color(root);