JSFiddle - React, Tailwind, and code Playground

by slphd

HTML

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <title>JS Bin</title>
</head>
<body>
<button id="play-button" type="button">play</button>
<button id="stop-button" type="button">stop</button>
<div id="board" class="board">
    <div class="row js-row">
        <div class="js-cell cell"></div>
        <div class="js-cell cell"></div>
        <div class="js-cell cell"></div>
        <div class="js-cell cell"></div>
        <div class="js-cell cell"></div>
    </div>
    <div class="row js-row">
        <div class="js-cell cell"></div>
        <div class="js-cell cell"></div>
        <div class="js-cell cell"></div>
        <div class="js-cell cell"></div>
        <div class="js-cell cell"></div>
    </div>
    <div class="row js-row">
        <div class="js-cell cell"></div>
        <div class="js-cell cell"></div>
        <div class="js-cell cell"></div>
        <div class="js-cell cell"></div>
        <div class="js-cell cell"></div>
    </div>
    <div class="row js-row">
        <div class="js-cell cell"></div>
        <div class="js-cell cell"></div>
        <div class="js-cell cell"></div>
        <div class="js-cell cell"></div>
        <div class="js-cell cell"></div>
    </div>
</div>
</body>
</html>

CSS

.board{
            padding: 10px 0;
        }
        .cell{
            width:20px;
            height:20px;
            background-color:grey;
            border:1px solid black;
            float:left;
        }

        .row{
            overflow:hidden;
        }

        .cell.is-active{
            background-color:tomato;
        }

JavaScript

function Board(boardElement, playButtonElement, stopButtonElement, initX, initY) {
    this.boardElement = boardElement;
    this.playButtonElement = playButtonElement;
    this.stopButtonElement = stopButtonElement;

    this.x = typeof initX !== 'undefined' ? initX : 0;
    this.y = typeof initY !== 'undefined' ? initY : 0;

    this.xMax = 0;
    this.yMax = 0;
    this.activeCell = null;
    this.interval = null;
    this.rows = [];

    this.init();
}

Board.prototype.init = function () {
    var rowsElements = [].slice.call(this.boardElement.querySelectorAll('.js-row'));
    for (var i in rowsElements) {
        var row = rowsElements[i];
        var cells = [].slice.call(row.querySelectorAll('.js-cell'));
        for (var j in cells) {
            var cell = cells[j];
            cell.setAttribute('data-x', i);
            cell.setAttribute('data-y', j);
        }
        this.rows.push(cells);
    }

    this.xMax = this.rows.length - 1;
    this.yMax = this.rows[0].length - 1;

    this.playButtonElement.addEventListener('click', this.play.bind(this));
    this.stopButtonElement.addEventListener('click', this.stop.bind(this));
    this.boardElement.addEventListener('click', this.onBoardClick.bind(this));

    this.activateCoords(this.x, this.y);
};

Board.prototype.getCellByCoords = function (x, y) {
    return this.rows[x][y];
};
Board.prototype.step = function () {
    var nextX = this.x === this.xMax ? 0 : this.x + 1;
    var nextY = this.y;
    if (nextX === 0) {
        nextY = this.y === this.yMax ? 0 : this.y + 1;
    }

    this.activateCoords(nextX, nextY);
};
Board.prototype.play = function () {
    if (this.interval === null) {
        this.step();
        this.interval = setInterval(this.step.bind(this), 1000);
    }
};
Board.prototype.stop = function () {
    if (this.interval !== null) {
        clearInterval(this.interval);
        this.interval = null;
    }
};

Board.prototype.onBoardClick = function (e) {
    var target = e.target;
   ...