Search code examples
javascripthtmldomtraversaldom-traversal

Javascript select all surrounding elements


Is this possible using only JavaScript?

Essentially I have 25 divs with a class .cell and the very center div contains the text: "O"

I want to loop through all cells and change the background color of any cell that immediately surrounds the cell with innerHTML of "O"

I know I can check the previousSibling and nextSibling

for (var i = 0;i < 25; i++) {
    if (cell[i].innerHTML == "O") {
        cell[i].previousSibling.style.backgroundColor = "#000"
        cell[i].nextSibling.style.backgroundColor = "#000"
    }
}

My question: How would I go about selecting the above sibling, beneath sibling and/or diagonal siblings?

Here's my fiddle http://jsfiddle.net/xamte3fa/2/


Solution

  • If you know the matrix is 5x5 which you seem to know from the code that creates it and the CSS width rules, then you can calculate the index of the surrounding cells based on knowing the size of the matrix.

    For example, the cell immediately above will be the index of the cell with the "O" in it minus the width which is 5.

    var cellAbove = index - 5;
    var cellLeft = index - 1;
    var cellRight = index + 1;
    var cellBelow = index + 5;
    

    You will, of course have to bounds check all these in case the cell with the "O" is on an edge.

    Here's an example of code that highlights the above, below, left and right cells using the notion that you know it's a 5x5 matrix:

    function highlightSurrounding() {
        var cells = document.querySelectorAll(".cell");
        for (var i = 0; i < cells.length; i++) {
            if (cells[i].innerHTML === "O") {
                // found a target
                var results = calcNeighbors(i, 5, 5);
                var bordered = results.bordered;
                var diagonals = results.diagonals;
                for (var dir in bordered) {
                    if (bordered[dir] !== null) {
                        cells[bordered[dir]].style.backgroundColor = "#F00";
                    }
                }
                for (var dir in diagonals) {
                    if (diagonals[dir] !== null) {
                        cells[diagonals[dir]].style.backgroundColor = "#0F0";
                    }
                }
    
            }
        }
    }
    
    // this is where the neighbor indexes are calculated
    // and bounds-checked
    // returns an object with two objects in it where each
    // object has an index number for each direction or null if that neighbor
    // doesn't exist
    function calcNeighbors(index, matrixWidth, matrixHeight) {
        var bordered = {};
        bordered.above = index >= matrixWidth ? index - matrixWidth : null;
        bordered.below = index + matrixWidth < matrixWidth * matrixHeight ? index + matrixWidth : null;
        bordered.left = index % matrixWidth !== 0 ? index - 1 : null;
        bordered.right = (index + 1) % matrixWidth !== 0 ? index + 1 : null;
    
        // now calc diagonals
        var diagonals = {upLeft: null, upRight: null, belowLeft: null, belowRight: null};
        if (bordered.left !== null && bordered.above !== null) {
            diagonals.upLeft = bordered.above - 1;
        }
        if (bordered.left !== null && bordered.below !== null) {
            diagonals.belowLeft = bordered.below - 1;
        }
        if (bordered.right !== null && bordered.above !== null) {
            diagonals.upRight = bordered.above + 1;
        }
        if (bordered.right !== null && bordered.below !== null) {
            diagonals.belowRight = bordered.below + 1;
        }
    
    
        return {bordered: bordered, diagonals: diagonals};
    }
    
    highlightSurrounding();
    

    Working demo: http://jsfiddle.net/jfriend00/zmkq9ejo/


    FYI, if you wanted to do this purely based on layout position on the screen, you would have to calculate the coordinate bounds of each cell and then look for cells that occupy the position in the direction you are interested in. In my opinion, that is much more difficult than just relying on the fact that you know it's a matrix and letting math calculate which cell number will be a given direction.