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

Viewed 69

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>

1 Answers

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>

Related