I created a table in my HTML code. It has 9 columns and 13 rows. It gets filled up pletely by a JavaScript loop that fills it with names of people from a few arrays. However, I want to add a validation step that makes sure that no two cells within a row hold the same value and that the value of a each cell does not repeat in the cell directly beneath it.
Since I am only able to access the values of the cells of the table as a NodeList, I decided to make it into an array to use the IndexOf property to search through the array:
var table1 = document.getElementsByTagName("td");
var table1Array = []; //number of "td" elements on page
for (i = 0; i < 117; i++) {
table1Array[i] = table1[i].innerHTML;
}
I don't know of a more elegant method (sort of a beginner here). So I set up some nested loops to pare each cell to each element in the row array I create (for all 13 rows):
function validateCells() {
for (i = 0; i < 117; i = i + 9) { //increment for going to next column (after 9 cells or elements in array)
for (j = 0; j < 8; j++) {
var curCell = table1Array[i];
var curRow = []; //I'm ignoring the first column which is "date", so it has 8 elements rather than 9
for (k = 0; k < 8; k++) {
curRow[k] = document.getElementById("row" + j).children[k].innerHTML;
}
if (curRow.indexOf(curCell) != -1) {
curCell = "CONFLICT"; //trying to change value in table. Doesn't work.
}
}
}
}
Unfortunately, this won't work. I don't even know if modifying the value of the curCell reference variable will actually change the value of the table1Array at that location, even less if it will change the data in the table.
Am I using the indexOf property correctly? Do I use the != parison operator or !==? Does indexOf return the index as a Is there any other less plicated, more elegant to do this? I just started with jQuery, maybe it can help simplify the code and make it less error-prone.
Sorry for the all the questions, I'm really trying to understand how all of this works. Thanks!
I created a table in my HTML code. It has 9 columns and 13 rows. It gets filled up pletely by a JavaScript loop that fills it with names of people from a few arrays. However, I want to add a validation step that makes sure that no two cells within a row hold the same value and that the value of a each cell does not repeat in the cell directly beneath it.
Since I am only able to access the values of the cells of the table as a NodeList, I decided to make it into an array to use the IndexOf property to search through the array:
var table1 = document.getElementsByTagName("td");
var table1Array = []; //number of "td" elements on page
for (i = 0; i < 117; i++) {
table1Array[i] = table1[i].innerHTML;
}
I don't know of a more elegant method (sort of a beginner here). So I set up some nested loops to pare each cell to each element in the row array I create (for all 13 rows):
function validateCells() {
for (i = 0; i < 117; i = i + 9) { //increment for going to next column (after 9 cells or elements in array)
for (j = 0; j < 8; j++) {
var curCell = table1Array[i];
var curRow = []; //I'm ignoring the first column which is "date", so it has 8 elements rather than 9
for (k = 0; k < 8; k++) {
curRow[k] = document.getElementById("row" + j).children[k].innerHTML;
}
if (curRow.indexOf(curCell) != -1) {
curCell = "CONFLICT"; //trying to change value in table. Doesn't work.
}
}
}
}
Unfortunately, this won't work. I don't even know if modifying the value of the curCell reference variable will actually change the value of the table1Array at that location, even less if it will change the data in the table.
Am I using the indexOf property correctly? Do I use the != parison operator or !==? Does indexOf return the index as a Is there any other less plicated, more elegant to do this? I just started with jQuery, maybe it can help simplify the code and make it less error-prone.
Sorry for the all the questions, I'm really trying to understand how all of this works. Thanks!
Share Improve this question edited Jun 22, 2014 at 4:00 d8k_irf asked Jun 22, 2014 at 2:54 d8k_irfd8k_irf 2611 gold badge4 silver badges11 bronze badges 4-
When you create an array like this
var curRow = [8];
it creates an array with only one element, which value is 8 – axelduch Commented Jun 22, 2014 at 3:10 -
So it would just be
var curRow = [];
to declare the array? And in the first one, too? I would have to change it tovar table1Array = [];
? – d8k_irf Commented Jun 22, 2014 at 3:16 - 1 Tables have a rows collection, and rows have a cells collection. You should be able to access cells in adjacent rows using their index (e.g. pare the content of rows[i].cells[j] to rows[i+1].cells[j]. – RobG Commented Jun 22, 2014 at 3:47
-
@user96872 Yes that would be an improvement, and also, it is generally to use
Array.prototype.push
instead of directly setting the value at an index in an array when the given index does not exist yet. – axelduch Commented Jun 22, 2014 at 3:57
2 Answers
Reset to default 2You should get an array of rows, each row is an array of cells. That way the validation is much easier. I'm not sure about how you want to show the conflict. In this demo I've just highlight the duplicated cells (conflicted) in red (at least I like this kind of showing conflict rather than modifying the conflicted cells' text).
HTML:
<table>
<tr><td>1</td><td>2</td><td>3</td></tr>
<tr><td>1</td><td>5</td><td>6</td></tr>
<tr><td>7</td><td>8</td><td>7</td></tr>
<tr><td>8</td><td>9</td><td>10</td></tr>
</table>
<button>Check constraints</button>
CSS:
td {
width:100px;
height:50px;
border:1px solid black;
}
table {
border:1px solid black;
border-collapse:collapse;
}
td.invalid {
background:red;
}
JS:
$('td').attr('contenteditable',true);
var cell;
function highlight(){
$(arguments).toggleClass('invalid',true);
}
function checkConstraints(e){
//reset style before re-checking
$('td.invalid').toggleClass('invalid');
//get rows as an array of array
var rows = $('tr').map(function(elem,i){
return [$(this).children('td').toArray()];
}).toArray();
//loop through the rows
for(var i = 0; i < rows.length; i++){
cell = {};
for(var j = 0; j < rows[i].length; j++){
var cellText = $(rows[i][j]).text();
if(cell[cellText]) {
highlight(cell[cellText], rows[i][j]);
} else {
cell[cellText] = rows[i][j];
}
if(i < rows.length - 1 &&
cellText == $(rows[i+1][j]).text()){
highlight(rows[i][j],rows[i+1][j]);
}
}
}
}
$('button').click(checkConstraints);
Demo.
Note that, I set contenteditable
for all the cells (td
), you can edit the cells text to what you want and click the button to test the demo.
You can use the table rows and cells collections for the iteration. The following does a literal parison of the text content, you may wish to process the text first to "normalise" it in regard to whitespace.
<table id="t0">
<tr><td>foo<td>bar<td>fum</td>
<tr><td>fum<td>bar<td>foo</td>
<tr><td>foo<td>fum<td>fum</td>
</table>
<script>
pareRows(document.getElementById('t0'));
function pareRows(table) {
var row, rows = table.rows;
var cell, cells;
var rowText;
// For each row in the table
for (var i=0, iLen=rows.length; i<iLen; i++) {
row = rows[i];
cells = row.cells;
// Compare the text in each cell
for (var j=0, jLen=cells.length; j<jLen; j++) {
cell = cells[j];
for (var k=0; k<jLen; k++)
if (k != j && cells[k].textContent == cell.textContent) {
// cell text is repeated in current row
console.log('row ' + i + ' cell ' + j + ' text repeated in cell ' + k);
}
// Compare with the text in the cell immediately below (if there is one)
if (i < iLen-2 && cell.textContent == rows[i+1].cells[j].textContent) {
// cell text is repeated in next row
console.log('row ' + i + ' cell ' + j + ' text repeated in row ' + (i+1));
}
}
}
}
</script>
Note that repeated text in a row will be reported twice.
The above uses the textContent property, which may be supported as innerText in some user agents. It also runs about 10 times faster than the jQuery alternative.
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744756901a4591935.html
评论列表(0条)