Does .replace not work in a for loop? - javascript

So I'm trying to just make a ".replace" loop, but something mysterious is happening.
var cell = "r1c1";
for (i = 0; i <= 4; i++){
cell = cell.replace(cell[3],i+1);
My expected output:
cell = "r1c1"
cell = "r1c2"
cell = "r1c3"
cell = "r1c4"
cell = "r1c5"
The actual output:
cell = "r1c2"
cell = "r2c1"
cell = "r2c3"
cell = "r2c4"
cell = "r2c5"
As you can see, it runs normal EXCEPT for the second iteration.
What in the world am I doing so wrong?

cell.replace(cell[3], i+1) is going to replace the first instance of the '1' character it finds in the string 'r1c1'. In this case it is the '1' at position 1 that gets replaced instead of the '1' at position 3.
To get the results you want, try
var cell = "r1c1";
for (i = 0; i <= 4; i++){
cell = cell.substring(0, cell.length-1)+(i+1);
}

You can use a regular expression: /^r(\d+)c(\d+)/:
var row_col = 'r1c1';
var match = /^r(\d+)c(\d+)/.exec(row_col); // match string
var row = +match[1]; // extract row
var col = +match[2]; // extract column
// edit row and col as needed
row_col = 'r' + row + 'c' + col; // "reassemble" string
This will take care of bigger row/column numbers than 9. If that is not to be expected, then read about String.prototype.substring():
var row_col = 'r1c1';
var row = +row_col.substring(1,2);
var col = +row_col.substring(3,4)

I don't like this, but the fix I ended up using looks like this:
cell = "r"+(j)+cell.substr(2,2);
Since I'm inevitably answering my own question, here, I still want to ask for comments:
How elegant would you say a solution like this is in the long run?

Related

How to remove all children from an element using jQuery?

I have a script that creates a table with specifications given by the user.
The issue is that when the table is printed more than once, it prints below the other table. Turning a 10x10 table into a 10x20 table. (if that makes sense)
In previous assignments I used:
//Clean grid
while(grid.firstChild)
grid.removeChild(grid.firstChild);
to clear the grid, but this assignment is using jQuery and I am not sure how to do it. I've tried:
var divBlock = document.getElementById('my_table');
while (divBlock.firstChild) {
divBlock.removeChild(divBlock.firstChild);
and
$("#my_table").empty();
and
$("#my_table").remove();
and
$('#my_table').remove('table');
but neither seem to work, here is the full code:
// TODO: clear table
var $rows = $("#rows");
var $cols = $("#cols");
var $print_button = $("#print");
var $my_table = $("#my_table");
var $stats = $("#stats");
var arr = [];
var $table_obj = $('<table>'); //Create an element
var $row_obj;
var $col_obj;
var counter = 0;
$print_button.on('click', function() {print_pattern();});
function print_pattern()
{
// Clear table
// var divBlock = document.getElementById('my_table');
// while (divBlock.firstChild) {
// divBlock.removeChild(divBlock.firstChild);
// }
// $("#my_table").empty();
$('#my_table').remove('table');
// Get row and column values
var r = $rows.val(); //Get value of rows
element
var c = $cols.val(); //Get value of cols element
// Create 2-D Array
for (var i = 0; i < r; i++) {
arr[i] = [];
}
// Double for-loop to create table
for (var i = 0; i < r; i++) {
$row_obj = $('<tr>'); // Create row
for (var j = 0; j < c; j++) {
$col_obj = $('<td>'); // Create table cell
var n = Math.floor(Math.random()*10000)%100; //Math methods:
floor and random
$($col_obj).append(n); // Append random number to table cell
$($row_obj).append($col_obj); // Append column to row
$($table_obj).append($row_obj); // Append row to table object
// if random number > 90 -> make background color yellow
if (n > 90) {
$col_obj.css('background-color', 'yellow'); //Change css
counter++; // counter for stats
}
}
$($table_obj).append($row_obj); // Append row to table object
}
$($my_table).append($table_obj); // Append table to div container
// Stats calculation
$stats.html("<b>" + (counter/(r*c)*100).toFixed(2) + "%<b>");
//Change html content
counter = 0; // reset counter
// event function for removing a row when its clicked on
$('tr').on('click', function(){ $(this).fadeOut(500); });
}
So I've tried a number of things, I am not sure if I am just getting the syntax wrong or if I am using the wrong function to clear the div tag.
If anyone can point me in the right direction that would help a lot!
Thank you.
EDIT: I figured out the issue. My original while() block worked fine when I put all the variables inside the function.
First of all, you have to distinguish variables.
A. There is a variable that has to define 1 time, and any changes will
be stored on that.
B. And there is a variable that needs to be reset every function
called.
variable on condition b you need put inside your function so it won't keep last value and make it has double value (last value + new value)
in this case i could say this variable is on condition b:
$table_obj, $row_obj, $col_obj, arr, ...

Object created is empty

I'm trying to get a function to loop through data in two tables and put them into an object. The first for-loop that goes through the first table does this fine, but the second for-loop that goes through the second table spits out an empty object when there's only 1 row to go through.
However, when there is more than 1 row, then all of the objects have the values as the second row.
I really don't understand what I'm doing wrong here:
function foo(){
var rows = $('#table1').find('tr');
var array1 = [];
for(var i = 1; i < rows.length-1; i++){
var row = $(rows[i]).find('input');
var o = {
name : $(row[0]).val(),
bday : $(row[1]).val(),
parent : $(row[2]).val(),
parentBDay : $(row[3]).val(),
parentNumber : $(row[4]).val()
};
array1.push(o);
}
var array2 = [];
rows = $('#table2').find('tr');
for(var j = 1; j < rows.length-1; j++){
var row = $(rows[i]).find('input');
var o = {
name : $(row[0]).val(),
bday : $(row[1]).val(),
phoneNumber : $(row[2]).val()
};
console.log('wtf: ' + JSON.stringify(o));
array2.push(o);
}
}
Your problem is that your indexes in the for cycle are not looping well. You start the for cycle from 1, which, in case you want to use the very first element, then it is wrong. Note, that indexing begins from 0. If you miss the very first element on purpose, because it is a header row or something, then this is not a problem. However, the end sign, like
< rows.length - 1
is clearly wrong. Let's suppose, the number of rows is 50. Then its last index is 50 - 1 = 49. If you loop from one until you reach the number below 50 - 1, then your last index will be 48 and you will miss the very last element. Your condition should be either < rows.length or <= rows.length - 1.

Uncaught IndexSizeError: Failed to execute 'insertCell' on 'HTMLTableRowElement': The value provided (1) is outside the range [-1, 0]

Why pictures don't appear on my page? Uncaught IndexSizeError: Failed to execute 'insertCell' on 'HTMLTableRowElement': The value provided (1) is outside the range [-1, 0] - this error call on this string.
[JS]var cell = row.insertCell(i);[/JS]
function createPreview() {
var f = document.createElement("table");
var row = f.insertRow();
var cell = row.insertCell(i);
for(var j = 0; j < count ; j++) {
var img = new Image();
img.src = "image/" + j + ".jpg";
img.id = "i" + j;
cell.appendChild(img);
}
document.body.appendChild(f);
}
</script>[/JS]
This is old, but for anyone reaching here, and having the same problem, the first cell you have to put in a row is the cell 0, then, you can put the cell 1, for example:
You cant put the cell 0, and after that the cell 2, because you need a cell 1.
The way to do it is insert cell 0,1,2,3...
Just to add to Gaunts answer, cause this one came up for me too.
I was creating a new tbody, and within this tbody I was dynamically creating new rows by looping through an array.
Initially, I had the code loop using the typical for loop which was working fine.
var tableBody = tableBody || document.createElement('tbody')
for (var i = 0, rowCtr = rowOrder.length; i < rowCtr; i++) {
var newRow = tableBody.insertRow(i);
}
But then I went ahead and refactored to use a reverse for loop to reduce the verbosity of that for statement and for the performance advantages at no extra cost to readability and future maintenance.
var tableBody = tableBody || document.createElement('tbody')
for (var i = rowOrder.length; i--;) {
var newRow = tableBody.insertRow(i);
}
Both for loops have the same expected result, with the reverse for loop being more readable. So if rowOrder is an array of 4 elements, using the reverse for loop will yield this:
start loop
i = 3
i = 2
i = 1
i = 0
end loop
In this loop, the first run through will attempt var newRow = tableBody.insertRow(3) so you will get an index error because a row at position 0, 1, 2 have not been previously created.
This happened to me on Google Chrome 46.0.2490.80 m - not sure why they thought to throw exceptions on creating a sparse array of rows in the tbody, they can just restructure their code to allow for sparse arrays and then prior to updating the DOM, just re-sort the index keys. Even that is unnecessary, just push the rows out.
Just bumped into this, so I guessing the error is trying to tell you that you can only add to the front; (0) or at the back; (-1)
found this link , Hope it helps
for(i=0;i<names.length;i++){
if(i===0){
var cell=column.insertCell(0);;
cell.outerHTML = "<th>Heading</th>";
}else{
var cell=column.insertCell(-1);
cell.outerHTML = "<input>";
}
}

Trouble with JavaScript arithmetic and NaN values from the DOM

The problem I'm having is with my function calculate(). The purpose of the program is creating a dynamic spreadsheet with JavaScript and html, with a CSS for decoration purposes.
So far I have it insert the values into the spreadsheet, however when attempting to run a simple addition calculation on it the values that I'm grabbing from the cells are not properly being grabbed.
Here's the function in specific that's giving me the problem. My apologies for the sloppy code. Any help would be appreciated, I'm sure it's something simple that I'm missing.
EDIT:: Corrected the issue, for those of you wondering, I had to call not innerHTML.text, or value. It had to be simply the .innerHTML on the cell in question.
function calculate() {
//create two variables to get the values in the row and columns
var row1, row2, col1, col2, total, totalInsert;
var row = document.getElementById("row");
var col = document.getElementById("col");
var value = document.getElementById(row + "_" + col);
var formula = document.getElementById("inputText");
formula = formula.value; //=SUM(1,2,2,1)
formula1 = formula;
//get the raw values to ints
row = row.value;
col = col.value;
//get JUST the formula in questions part
formula = formula.substr(0,4);
//Parsing the the selected cells from =sum(1,1,2,1) into Cell ID's
col1 = parseInt(formula1.substr(5, 1));//row 1
row1 = parseInt(formula1.substr(7, 1));
col2 = parseInt(formula1.substr(9, 1));
row2 = parseInt(formula1.substr(11, 1)); // column2
//this gives us the proper cell's address. id=1_1
var td1 = col1 + "_" + row1;
var td2 = col2 + "_" + row2;
//problem starts around here
var sum = document.getElementById(td1);
var sum2 = document.getElementById(td2);
//this returns a undefined value
sum = sum.value;
sum2 = sum2.value;
//this restults in a NaN
sum = parseInt(sum);
sum2 = parseInt(sum2);
//creating the total value
total = sum + sum2;
//returning values
totalInsert = document.getElementById(td1).innerHTML = total;
}
This part seems odd to me, you are selecting two elements and then combining them as a string to find another element?
var row = document.getElementById("row");
var col = document.getElementById("col");
var value = document.getElementById(row + "_" + col);
I'm not sure that would do what you are expecting... In my experience you'd get something like this:
document.getElementById('[object Object]_[object Object]');
or:
document.getElementById('[object HTMLDivElement]_[object HTMLDivElement]');
... depending on the browser. Now obviously you could have an element with that kind of id, but that would be a little bit bonkers ;)
It looks to me like the row and col elements are inputs, so maybe you actually mean:
var row = document.getElementById("row");
var col = document.getElementById("col");
var value = document.getElementById(row.value + "_" + col.value);

Adding text to InnerHTML in TDs with Javascript

I am trying to add text to each cell in particular column via Javascript. Like every 8th TD would be processed for adding text.
Tell me what I have done wrong here/why it doesn't appear in my table:
<script type="text/javascript">
window.onload = function inventorytable() {
var tableRows = document.getElementById
("inventorytable").getElementsByTagName("tbody")[0].getElementsByTagName("tr");
for(var i = 0, l = tableRows.length; i < l; i++) {
tds = tableRows.getElementsByTagName("td");
var processor = tds[8].innerHTML += " Ghz"
var ram = tds[9].innerHTML += " GB"
var rspeed = tds[11].innerHTML += " Mhz"
}}
</script>
You've forgotten to refer to the i-th row:
tds = tableRows[i].getElementsByTagName("td");
I recommend to use:
window.onload = function inventorytable() {
var tableRows = document.getElementById("inventorytable").rows;
//or .tBodies[0].rows
for(var i=0, l=tableRows.length; i < l; i++) {
var tds = tableRows[i].cells;
/*processor*/ tds[8].innerHTML += " Ghz"
/*ram */ tds[9].innerHTML += " GB"
/* rspeed */ tds[11].innerHTML += " Mhz"
}
}
Do not define unused variables. If you want to clarify their use, use comments.
Also, I have replaced .getElementsByTagName by .rows and .cells.
Update
JavaScript sets are zero-based. So, if you want to refer to the 4th cell, use .cells[3].
At your previous answer, you've showed a fiddle. see http://jsfiddle.net/ndfh2/.
As you can see, the first row is also getting postfixes. To not add postfixes to these cells in the first row, initiate the counter at one: for( var i=1; .. ; .. )
Your current code does probably not work, because your rows don't have twelve (12) rows. Remember, the number at tds[ number ] equals the index of a cell within a row, starting at zero.

Categories