Search code examples
javascripthtmlsudoku

How do I make empty cells editable in a Sudoku table in javascript?


I wrote a function that generates random numbers to an 2d array. With this function I could fill the cells of a sudoku table (built in HTML) with random numbers. But for some reason when I fill the random numbers to my HTML table (using .innerHTML) I cannot edit the empty cells. The empty cells are locked although I used inputs to build the table. Please Help me so I can make the empty cells editable. I tried to use the attribute contenteditable:"true" in the the td but the problem is that it also allows to delete the cells filled with the random numbers and doesn't restrict the text area to numbers only from 1-9.

Here is the JS part:

let sudoku = [
  [null, null, null, null, null, null, null, null, null],
  [null, null, null, null, null, null, null, null, null],
  [null, null, null, null, null, null, null, null, null],
  [null, null, null, null, null, null, null, null, null],
  [null, null, null, null, null, null, null, null, null],
  [null, null, null, null, null, null, null, null, null],
  [null, null, null, null, null, null, null, null, null],
  [null, null, null, null, null, null, null, null, null],
  [null, null, null, null, null, null, null, null, null],
];
window.onload = function () {
  generateSudoku(61);
  fillEmptySudoku();
};
function generateSudoku(displayedNumbers) {
  let numAdded = 0;

  while (numAdded < displayedNumbers) {
    let row = Math.floor(Math.random() * 9);
    let col = Math.floor(Math.random() * 9);
    let number = Math.floor(Math.random() * 9) + 1;

    if (sudoku[row][col] === null) {
      sudoku[row][col] = number;
    
    } else {
      numAdded++;
    }
  }
  return sudoku;
}

let table = document.getElementById("table");

//enter the matrix value into the html table
function fillEmptySudoku() {
  for (let i = 0; i < table.rows.length; i++) {
    for (let j = 0; j < table.rows[i].cells.length; j++) {
      table.rows[i].cells[j].innerHTML = sudoku[i][j];
    }
  }
}
Here is the HTML part:


<table id="table">
          <tr class="tr" id="row1">
            <td class="td" id="cell1">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell2">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell3">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell4">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell5">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell6">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell7">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell8">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell9">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
          </tr>

          <tr class="tr" id="row2">
            <td class="td" id="cell10">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell11">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell12">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell13">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell14">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell15">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell16">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell17">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell18">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
          </tr>

          <tr class="tr" id="row3">
            <td class="td" id="cell19">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell20">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell21">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell22">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell23">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell24">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell25">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell26">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell27">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
          </tr>

          <tr class="tr" id="row4">
            <td class="td" id="cell28">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell29">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell30">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell31">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell32">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell33">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell34">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell35">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell36">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
          </tr>

          <tr class="tr" id="row5">
            <td class="td" id="cell37">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell38">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell39">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell40">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell41">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell42">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell43">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell44">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell45">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
          </tr>

          <tr class="tr" id="row6">
            <td class="td" id="cell46">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell47">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell48">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell49">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell50">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell51">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell52">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell53">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell54">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
          </tr>

          <tr class="tr" id="row7">
            <td class="td" id="cell55">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell56">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell57">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell58">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell59">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell60">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell61">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell62">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell63">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
          </tr>

          <tr class="tr" id="row8">
            <td class="td" id="cell64">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell65">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell66">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell67">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell68">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell69">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell70">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell71">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell72">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
          </tr>

          <tr class="tr" id="row9">
            <td class="td" id="cell73">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell74">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell75">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell76">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell77">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell78">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell79">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell80">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
            <td class="td" id="cell81">
              <input type="number" min="1" max="9" step="1" class="inp" />
            </td>
          </tr>
      </table>


Solution

  • To make the empty cells editable, you can mix the contenteditable attribute and input together in the table cells:

    if(sudoku[i][j] === null){
      table.rows[i].cells[j].setAttribute("contenteditable", "true");                   
    } else {
      table.rows[i].cells[j].textContent = sudoku[i][j];
    }
    

    To restrict the input to 1 to 9 and to only one number, you can use some event listeners:

    table.addEventListener("keypress", function(e){
       if (e.which < 49 || e.which > 57) e.preventDefault();
    });
    
    table.addEventListener("input", function(e){
      e.target.value = e.data;
    });
    

    I also added some CSS to make the table print out a bit nicer.

    let sudoku = [
      [null, null, null, null, null, null, null, null, null],
      [null, null, null, null, null, null, null, null, null],
      [null, null, null, null, null, null, null, null, null],
      [null, null, null, null, null, null, null, null, null],
      [null, null, null, null, null, null, null, null, null],
      [null, null, null, null, null, null, null, null, null],
      [null, null, null, null, null, null, null, null, null],
      [null, null, null, null, null, null, null, null, null],
      [null, null, null, null, null, null, null, null, null],
    ];
    window.onload = function () {
      generateSudoku(61);
      fillEmptySudoku();
    };
    function generateSudoku(displayedNumbers) {
      let numAdded = 0;
    
      while (numAdded < displayedNumbers) {
        let row = Math.floor(Math.random() * 9);
        let col = Math.floor(Math.random() * 9);
        let number = Math.floor(Math.random() * 9) + 1;
    
        if (sudoku[row][col] === null) {
          sudoku[row][col] = number;
        
        } else {
          numAdded++;
        }
      }
      return sudoku;
    }
    
    let table = document.getElementById("table");
    
    //enter the matrix value into the html table
    function fillEmptySudoku() {
      for (let i = 0; i < table.rows.length; i++) {
        for (let j = 0; j < table.rows[i].cells.length; j++) {
          if(sudoku[i][j] === null){
            table.rows[i].cells[j].setAttribute("contenteditable", "true");                   
          } else {
            table.rows[i].cells[j].textContent = sudoku[i][j];
          }
        }
      }
    }
    
    //only allow 1 to 9 in cells
    table.addEventListener("keypress", function(e){
       if (e.which < 49 || e.which > 57) e.preventDefault();
    });
    
    //restrict inputs to one number only
    table.addEventListener("input", function(e){
       e.target.value = e.data;
    });
    table {
      border-collapse: collapse;
      width: 180px;
      text-align: center;
    }
    
    td {
      border: 1px solid black;
      min-width: 25px;  
    }
    
    td:nth-of-type(3) {
      border-right: 3px solid black;
    }
    
    td:nth-of-type(6) {
      border-right: 3px solid black;
    }
    
    tr:nth-of-type(3) {
      border-bottom: 3px solid black;
    }
    
    tr:nth-of-type(6) {
      border-bottom: 3px solid black;
    }
    
    input {
      width: 20px;
      text-align: center;
    }
    
    /* Chrome, Safari, Edge, Opera */
    input::-webkit-outer-spin-button,
    input::-webkit-inner-spin-button {
      -webkit-appearance: none;
      margin: 0;
    }
    
    /* Firefox */
    input[type=number] {
      -moz-appearance: textfield;
    }
    <table id="table">
      <tr class="tr" id="row1">
        <td class="td" id="cell1">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell2">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell3">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell4">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell5">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell6">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell7">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell8">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell9">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
      </tr>
    
      <tr class="tr" id="row2">
        <td class="td" id="cell10">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell11">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell12">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell13">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell14">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell15">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell16">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell17">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell18">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
      </tr>
    
      <tr class="tr" id="row3">
        <td class="td" id="cell19">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell20">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell21">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell22">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell23">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell24">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell25">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell26">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell27">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
      </tr>
    
      <tr class="tr" id="row4">
        <td class="td" id="cell28">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell29">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell30">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell31">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell32">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell33">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell34">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell35">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell36">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
      </tr>
    
      <tr class="tr" id="row5">
        <td class="td" id="cell37">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell38">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell39">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell40">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell41">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell42">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell43">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell44">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell45">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
      </tr>
    
      <tr class="tr" id="row6">
        <td class="td" id="cell46">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell47">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell48">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell49">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell50">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell51">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell52">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell53">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell54">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
      </tr>
    
      <tr class="tr" id="row7">
        <td class="td" id="cell55">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell56">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell57">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell58">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell59">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell60">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell61">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell62">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell63">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
      </tr>
    
      <tr class="tr" id="row8">
        <td class="td" id="cell64">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell65">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell66">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell67">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell68">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell69">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell70">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell71">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell72">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
      </tr>
    
      <tr class="tr" id="row9">
        <td class="td" id="cell73">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell74">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell75">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell76">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell77">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell78">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell79">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell80">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
        <td class="td" id="cell81">
          <input type="number" min="1" max="9" step="1" class="inp" />
        </td>
      </tr>
    </table>