Наиболее эффективный способ решить проблему смежных элементов в vanilla js + html? - PullRequest
0 голосов
/ 19 января 2019

Это проблема:

Создание сетки 10x10 с использованием html, vanilla javascript и css.

Если щелкнуть квадрат на этой сетке, измените цвет фона соседних квадратов (один сверху, слева и т. Д.) На желтый.

Мне удалось решить эту проблему, но я не думаю, что она эффективна - мой html - только одна строка:

<table id="grid"></table>

И я использовал javascript, чтобы вручную заполнить таблицу кучей ячеек / квадратов. Я дал каждой ячейке два атрибута data-row и data-col для хранения места расположения ячейки. Затем на клике я делаю что-то вроде этого:

  var row = this.getAttribute('data-row');
  var col = this.getAttribute('data-col');

  ...

  //if not on the top most row, retrieve square above
  if(row>0){
      let sel = "td[data-row='"+(row-1)+"'][data-col='"+col+"']";
      let elem = document.querySelector(sel);
      elem.classList.toggle('yellow');
  }

  ...

  //3 more if blocks like the one above to find the bottom, left and right squares

Есть ли более эффективный или лаконичный способ сделать это? Спасибо за ваши ответы заранее! Это ценится:)

Ответы [ 2 ]

0 голосов
/ 19 января 2019

То, как указывается желаемый результат, заставляет меня думать, что нажатие на ячейку должно , а не стать желтым, и вопрос состоит в том, чтобы обработать окрестность Мура ячейки.

Один из подходов к достижению этой цели, который я использовал в игре в прошлом, заключается в том, чтобы хранить массив элементов DOM ячеек сетки (небольшой «теневой DOM», если хотите) в JavaScript и выполнять итерации вокруг щелкнул ячейку в массиве, чтобы найти соседей.

Если интересует рабочий пример:

"use strict";

// iterate through the Moore neighbors of a cell
// ( in a 2D rectangular array)

function iter8( r, c, cellArray, callback) {
    r=+r; // convert row and column string arguments to number
    c=+c;

    const 
        maxRow = cellArray.length -1,
        maxCol = cellArray[0].length -1,
        r0 = r ? r-1 : 0,
        r1 = r < maxRow ? r+1 : maxRow,
        c0 = c ? c-1 : 0,
        c1 = c < maxCol? c+1 : maxCol
    ;
    for( var row = r0; row <= r1; ++ row) {
        for( var col = c0; col <= c1; ++ col) {
            if( ! (row == r && col == c)) {
                callback( cellArray[row][col], row, col, cellArray);
            }
        }
    }
}

//  *******   Test Code Follows  *********

const div = document.getElementById("board");
const array = [];
for( var r = 0; r < 10; ++r) {
    array.push([]);
    for( var c = 0; c < 10; ++c) {
        var cell = document.createElement( "SPAN");
        cell.className = "cell";
        cell.dataset["row"] = r;
        cell.dataset["col"] = c;
        cell.textContent = "(" + r + "," + c + ")";
        array[ r].push( cell);
        div.appendChild( cell);
    }
    div.appendChild( document.createElement("BR"));
}
div.addEventListener("click", event => {
    let cell = event.target;
    if( cell.classList.contains("cell")) {
         iter8( cell.dataset.row, cell.dataset.col, array, 
             neighbor => neighbor.classList.contains("yellow") || neighbor.classList.add("yellow")
         );
    }
}, false);
    
    
.div {
    white-space: nowrap;
}
.cell {
    display: inline-block;
    width: 2.5em;
    text-align: center;
    background-color: green;
    cursor: default;
}
.cell.yellow {
    background-color: yellow;
}
<div id="board">
0 голосов
/ 19 января 2019

Вы могли бы рассмотреть возможность вызова querySelector независимо, а затем проверить, был ли выбран элемент, вместо того, чтобы иметь различные блоки if (row > 0) ... ранее. Например:

tryChange(-1, 0);
tryChange(1, 0);
tryChange(0, -1);
tryChange(0, 1);
function tryChange(xDiff, yDiff) {
  const sel = "td[data-row='"+(row + xDiff)+"'][data-col='"+(col + yDiff)+"']";
  const elem = document.querySelector(sel);
  if (elem) {
    elem.classList.toggle('yellow');
  }
}

Тест if (elem) не пройден, если ни один элемент не был выбран.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...