Hello!

Task: Add columns to the table. If the number of columns == 10, then stop adding and perform certain actions. Here is what I invented:

var addCol = document.body; addCol.onclick = function() { var table = document.querySelectorAll('table')[0]; var rows = table.querySelectorAll('tr'); var col = table.querySelectorAll('td'); for (var i = 0; i < table.rows.length; i++) { var newCol = col[i].cloneNode(true); rows[i].appendChild(newCol); if(rows[i].col.length == 10) { console.log(rows[i].col.length); } } } 
 body, html { width: 100%; height: 100%; padding: 0; margin: 0; font-size: 14px; font-family: "Segoe UI"; } * { box-sizing: border-box; } section { padding: 15px 30px 15px 372px; min-height: 100%; } .b-matrix { position: relative; margin: 0 30px 25px 0; padding: 3px; border-left: 2px solid #444; border-right: 2px solid #444; position: relative; display: inline-block; /*float: left;*/ } /*------- [ ] -------*/ .b-matrix_border:before, .b-matrix_border:after, .b-matrix__table_border:before, .b-matrix__table_border:after { position: absolute; display: block; width: 8px; height: 2px; background: #444; content: ''; } .b-matrix_border:before { top: 0; left: 0; } .b-matrix_border:after { top: 0; right: 0; } .b-matrix__table_border:before { bottom: 0; left: 0; } .b-matrix__table_border:after { bottom: 0; right: 0; } /*----- // [ ] // -----*/ .matrix-name-A, .matrix-name-B { position: absolute; font-size: 25px; } .matrix-name-A { top: 50%; right: -30px; margin-top: -13px; } .matrix-name-B { bottom: -30px; left: 50%; margin-top: 0; margin-left: -6px; } .matrix-cell { display: block; width: 40px; height: 40px; margin: 5px; border: 1px solid #ddd; text-align: center; } .matrix-cell:hover { /*добавить стили*/ } .matrix-cell:focus { border-color: #09d; outline: 2px solid #09d; } .matrix-cell[disabled] { background: #eee; } .matrix-cell[disabled]:hover { border-color: #ddd; outline: none; } 
 <section> <div class="b-matrix b-matrix_border" data-name="a"> <table class="b-matrix__table b-matrix__table_border"> <tr> <td> <input class="matrix-cell" type="text" value="" /> </td> <td> <input class="matrix-cell" type="text" value="" /> </td> </tr> <tr> <td> <input class="matrix-cell" type="text" value="" /> </td> <td> <input class="matrix-cell" type="text" value="" /> </td> </tr> <tr> <td> <input class="matrix-cell" type="text" value="" /> </td> <td> <input class="matrix-cell" type="text" value="" /> </td> </tr> <tr> <td> <input class="matrix-cell" type="text" value="" /> </td> <td> <input class="matrix-cell" type="text" value="" /> </td> </tr> <tr> <td> <input class="matrix-cell" type="text" value="" /> </td> <td> <input class="matrix-cell" type="text" value="" /> </td> </tr> </table> </div> <br /> </section> 

As a result, the columns are added, but if I prescribe a condition below, some nonsense occurs, namely, the columns are added only to the first row of the table, and the condition does not work.

One more thing: the console displays the message "Cannot read property 'appendChild' of undefined". Why?

Please tell me where I crap. Maybe there are some subtleties that I do not consider / do not know ...?

  • Cannot read property 'appendChild' of undefined - this means that an attempt is being made to access the appendChild property of a variable, while the value of the variable undefined is Grundy
  • @Grundy, I don’t quite understand what variable I’m talking about, if it’s about newCol, then it’s defined, isn't it? - Astor
  • In the console, next to the error, the specific line on which the error occurred is indicated, moreover, you can click on it and go to the location of the error - Grundy
  • And why, when adding a condition, or, say, console.log (), are the columns added only to the first row of the table? - Astor
  • rows[i] - will be undefined if in the markup there are less than 10 elements tr - Grundy

3 answers 3

To add a cell to the end of the row, just select the last cells in the rows, and after each insert a new cell.

In this case, the cells have a cellIndex property showing the cell number in the row (counting from 0), that is, you can immediately find out how many cells are already in the row and whether you need to add new ones.

 var addCol = document.body; addCol.onclick = function() { var lastCells = document.querySelectorAll('[data-name="a"] td:last-child'); // если в строке уже 10 ячеек - ничего не делаем if(lastCells.length && lastCells[0].cellIndex==9) return; [].forEach.call(lastCells,function(cell){ cell.parentNode.insertBefore(cell.cloneNode(true),null); }) if(lastCells[0].parentNode.childElementCount==10){ // в таблице теперь 10 ячеек в строке console.log('10 cells'); } } 
 body, html { width: 100%; height: 100%; padding: 0; margin: 0; font-size: 14px; font-family: "Segoe UI"; } * { box-sizing: border-box; } section { padding: 15px 30px 15px 30px; min-height: 100%; } .b-matrix { position: relative; margin: 0 30px 25px 0; padding: 3px; border-left: 2px solid #444; border-right: 2px solid #444; position: relative; display: inline-block; /*float: left;*/ } /*------- [ ] -------*/ .b-matrix_border:before, .b-matrix_border:after, .b-matrix__table_border:before, .b-matrix__table_border:after { position: absolute; display: block; width: 8px; height: 2px; background: #444; content: ''; } .b-matrix_border:before { top: 0; left: 0; } .b-matrix_border:after { top: 0; right: 0; } .b-matrix__table_border:before { bottom: 0; left: 0; } .b-matrix__table_border:after { bottom: 0; right: 0; } /*----- // [ ] // -----*/ .matrix-name-A, .matrix-name-B { position: absolute; font-size: 25px; } .matrix-name-A { top: 50%; right: -30px; margin-top: -13px; } .matrix-name-B { bottom: -30px; left: 50%; margin-top: 0; margin-left: -6px; } .matrix-cell { display: block; width: 40px; height: 40px; margin: 5px; border: 1px solid #ddd; text-align: center; } .matrix-cell:hover { /*добавить стили*/ } .matrix-cell:focus { border-color: #09d; outline: 2px solid #09d; } .matrix-cell[disabled] { background: #eee; } .matrix-cell[disabled]:hover { border-color: #ddd; outline: none; } 
 <section> <div class="b-matrix b-matrix_border" data-name="a"> <table class="b-matrix__table b-matrix__table_border"> <tr> <td> <input class="matrix-cell" type="text" value="" /> </td> <td> <input class="matrix-cell" type="text" value="" /> </td> </tr> <tr> <td> <input class="matrix-cell" type="text" value="" /> </td> <td> <input class="matrix-cell" type="text" value="" /> </td> </tr> <tr> <td> <input class="matrix-cell" type="text" value="" /> </td> <td> <input class="matrix-cell" type="text" value="" /> </td> </tr> <tr> <td> <input class="matrix-cell" type="text" value="" /> </td> <td> <input class="matrix-cell" type="text" value="" /> </td> </tr> <tr> <td> <input class="matrix-cell" type="text" value="" /> </td> <td> <input class="matrix-cell" type="text" value="" /> </td> </tr> </table> </div> <br /> </section> 

  • @Grandy, and thanks again. - Astor
  • Here only the childElementCount property is not supported by IE under version 9. Maybe there is an alternative? - Astor
  • @Astor, eat, childElements.length - Grundy
  • Grandy, please explain this line of code - if (lastCells.length && lastCells [0] .cellIndex == 9) return; I do not understand how lastCells with a zero index can be equal to nine, because it is at the zero position. - Astor
  • @Astor, answered in the chat, it’s better to ask additional questions on the answer there - Grundy

And you have tr elements only 5, and you go in a cycle up to 10, and it turns out that rows [i] when i> 10 == undefined. Here is the code without error:

 var addCol = document.body; addCol.onclick = function() { var table = document.querySelectorAll('table')[0]; var rows = table.querySelectorAll('tr'); var col = table.querySelectorAll('td'); for (var i = 0; i < rows.length; i++) { var newCol = col[i].cloneNode(true); rows[i].appendChild(newCol); } } 
  body, html { width: 100%; height: 100%; padding: 0; margin: 0; font-size: 14px; font-family: "Segoe UI"; } * { box-sizing: border-box; } section { padding: 15px 30px 15px 372px; min-height: 100%; } .b-matrix { position: relative; margin: 0 30px 25px 0; padding: 3px; border-left: 2px solid #444; border-right: 2px solid #444; position: relative; display: inline-block; /*float: left;*/ } /*------- [ ] -------*/ .b-matrix_border:before, .b-matrix_border:after, .b-matrix__table_border:before, .b-matrix__table_border:after { position: absolute; display: block; width: 8px; height: 2px; background: #444; content: ''; } .b-matrix_border:before { top: 0; left: 0; } .b-matrix_border:after { top: 0; right: 0; } .b-matrix__table_border:before { bottom: 0; left: 0; } .b-matrix__table_border:after { bottom: 0; right: 0; } /*----- // [ ] // -----*/ .matrix-name-A, .matrix-name-B { position: absolute; font-size: 25px; } .matrix-name-A { top: 50%; right: -30px; margin-top: -13px; } .matrix-name-B { bottom: -30px; left: 50%; margin-top: 0; margin-left: -6px; } .matrix-cell { display: block; width: 40px; height: 40px; margin: 5px; border: 1px solid #ddd; text-align: center; } .matrix-cell:hover { /*добавить стили*/ } .matrix-cell:focus { border-color: #09d; outline: 2px solid #09d; } .matrix-cell[disabled] { background: #eee; } .matrix-cell[disabled]:hover { border-color: #ddd; outline: none; } 
 <!DOCTYPE html> <html> <head> <script src="/scripts/snippet-javascript-console.min.js"></script> </head> <body> <section> <div class="b-matrix b-matrix_border" data-name="a"> <table class="b-matrix__table b-matrix__table_border"> <tr> <td> <input class="matrix-cell" type="text" value="" /> </td> <td> <input class="matrix-cell" type="text" value="" /> </td> </tr> <tr> <td> <input class="matrix-cell" type="text" value="" /> </td> <td> <input class="matrix-cell" type="text" value="" /> </td> </tr> <tr> <td> <input class="matrix-cell" type="text" value="" /> </td> <td> <input class="matrix-cell" type="text" value="" /> </td> </tr> <tr> <td> <input class="matrix-cell" type="text" value="" /> </td> <td> <input class="matrix-cell" type="text" value="" /> </td> </tr> <tr> <td> <input class="matrix-cell" type="text" value="" /> </td> <td> <input class="matrix-cell" type="text" value="" /> </td> </tr> </table> </div> <br /> </section> </body> </html> 

    Rewrote your script a little

     document.body.onclick = function() { var table = document.querySelectorAll('table')[0]; var rows = table.querySelectorAll('tr'); var allCols = table.querySelectorAll('td'); var columnsCount = allCols.length / rows.length; if (columnsCount < 10) { for (var i = 0; i < rows.length; i++) { var newCol = allCols[i * columnsCount].cloneNode(true); rows[i].appendChild(newCol); } } else { console.log("Делаем что-то другое") } } 

    He is just doing what you asked. When you click on the page, it copies the first column from the table.

    • You just copied my answer and added meaningless lines that do not affect the result of the script. - ikerya
    • @ikerya, uh ... actually this is based on the code from the question. And scribbling is not even meaningless. And here not only adding lines. Have you watched how this code works? - mymedia