I want to add numbers in <td></td> below via JavaScript. For example using the following description:
<td id='last'> + formatNumber(data.tickers[key].last) + </td>
<td id='high'> + formatNumber(data.tickers[key].high) + </td>
<td id='low'> + formatNumber(data.tickers[key].low) + </td>
How do I change the text of table data elements via JavaScript?
<td id='new1'> = + <td id='last'> + <td id='high'> + </td>
<td id='new2'> = + <td id='high'> + <td id='loww'> + </td>
Try this:
// these target the cell elements
let last = document.getElementById("last");
let high = document.getElementById("high");
let low = document.getElementById("low");
let new1 = document.getElementById("new1");
let new2 = document.getElementById("new2");
// now we convert cell content to numbers, add them and make them 2 decimal places.
new1.textContent = (parseFloat(last.textContent) + parseFloat(high.textContent)).toFixed(2);
new2.textContent = (parseFloat(high.textContent) + parseFloat(low.textContent)).toFixed(2);
td {
border: solid 1px;
}
<table>
<tr>
<th>last</th>
<th>high</th>
<th>low</th>
<th>new1</th>
<th>new2</th>
</tr>
<tr>
<td id='last'> 23.40 </td>
<td id='high'> 28.20 </td>
<td id='low'> 22.10 </td>
<td id='new1'></td>
<td id='new2'></td>
</tr>
</table>
First I'm going to make your life a bit easier. Instead of using document.getElementsByTagName('tr')[3].getElementsByTagName('td')[2] to get the fourth tr element's third td element ([0] = first, [2] = third, etc) this will help make your code much much easier to read. You don't need id attributes on every element if you know how reliable code and order are by default.
function tag_(t)
{//Example: tag_('body')[0];
return (document.getElementsByTagName(t)) ? document.getElementsByTagName(t) : false;
}
Object.prototype.tag_ = function(t)
{//Example: id_('unique_id').tag_('td')[0];
return (this.getElementsByTagName && this.getElementsByTagName(t) && this.getElementsByTagName(t).length > 0) ? this.getElementsByTagName(t) : false;
}
Secondly the easiest way to both read and write data to any element is to use textContent.
Read the fourth td on the third tr:
//Read an element's text node:
console.log(tag_('tr')[2].tag_('td')[5].textContent);
//Write to an element's text node:
tag_('table')[0].tag_('tr')[2].tag_('td')[5].textContent = '1,234');
JavaScript is a bit strict when it comes to types. So if you need to do some math with text content that you just read you need to convert it:
Number(tag_('tr')[1].tag_('td')[5].textContent);//'123' becomes `123`
Number(tag_('tr')[2].tag_('td')[2].textContent);//'a123' becomes `NaN` (Not a Number)
If I recall correctly I recently used the following to strip non-numeric text from a string:
var my_number = Number('String or replace with object reference'.replace(/\D/g,''));
Now that you're getting the read/write aspects and overcoming some of the more oddities associated with it I'll iterate over...iteration! You may already know this though I'm presuming a full answer is more desirable than a partial answer for not just you though also others reading this in the future.
var table = tag_('table');
for (var i = 0; i < table.length; i++)
{
console.log(table[i]);
var tr = table[i].tag_('tr');//Whatever table[i] is and it's table rows.
for (var j = 0; j < tr[i].length; j++)
{
console.log(tr[j]);
var td = table[i].tag_('tr')[j].tag_('td');//All the table data elements.
for (var k = 0; k < td.length; k++)
{
//apply read/write conditions here.
//potentially call a second global function to keep your code reusable.
}
}
}
That should help you get far enough with specific and iteral targeting of table data elements to help you learn and achieve your goals.
Related
i have a site where i paste my entire source code into a box and update all the td tags with a background color if there isnt currently a "bgcolor" attribute.
I've been messing with this for some time but i can't get my ogSource to update. I've tried many ways such as assigning new variables, returns etc etc. No luck.
the below code properly scans for the appropriate td and adds the background color, it just doesnt apply it to the ogSource. I've removed all my other code to make this as basic as possible.
Can anyone assist with this?
Thanks in advance.
var ogSource = '<table id="test1"> <tr> <td> <table id="test2"> <tr> <td> </td> </tr> </table></td> </tr> </table>'
ogSource.replace(/\<td(.*?)\>/g, function(matches) {
if (!matches.includes('bgcolor')) {
var idx = matches.lastIndexOf(">");
if (idx > -1) {
matches = matches.substr(0, idx) + " bgcolor='pink'" + matches.substr(idx);
}
}
});
console.log(ogSource);
EDIT/UPDATE
After a lot of messing around- this was a solution that was able to capture all the source code pasted and make the modification needed.
ogSource = ogSource.replace(/\<td(.*?)\>/g, function( matches , i ) {
var idx = matches.lastIndexOf(">");
if (idx > -1) {
if (!matches.includes('bgcolor')) {
ogSource = matches.substr(0, idx) + " bgcolor='pink'" + matches.substr(idx);
} else {
ogSource = matches;
}
} return ogSource;
});
console.log(ogSource);
My initial answer was off the mark but quite a bit, however, I think regex in general may not be the best solution due to the amount of edge cases present and the DOMParser might be a better solution for this.
Essentially, you pass the html string into the DOMParser method parseFromString and store that in a variable, then select all td elements and check if they have a bgColor attribute, if they don't, give them one, then output the new DOM string.
Here's an example:
const domParser = new DOMParser();
const DOM = domParser.parseFromString(`<table id="test1"> <tr> <td> <table id="test2"> <tr> <td> </td> </tr> </table></td> </tr> </table>`, "text/html");
// Find all tds
const tds = DOM.querySelectorAll("td");
for(let i = 0; i < tds.length; i++) {
let currentTD = tds[i];
if(!currentTD.hasAttribute("bgColor")) {
currentTD.setAttribute("bgColor", "someValue");
}
}
console.log(DOM.body.innerHTML); // If you only want to return the table content
console.log(DOM.querySelector("html").innerHTML); // If you want all of the html code that was added
I have this table that has a column in which the cell may or may not contain a value, but when it does, it is in a JSON format; otherwise it will be empty (null).
<table>
<tbody>
<tr>
<td>Barley</td>
<td>AK, AZ</td>
<td class="fpdCell">[{"date":"06/01/2016","error":"Double/Triple cropping","id":2},{"date":"06/07/2016","error":"Lack of Planting Dates Established","id":2}]</td>
<td>null</td>
</tr>
<tr>
<td>Barley</td>
<td>AK, AZ, AR</td>
<td class="fpdCell">[{"date":"06/04/2016","error":"No Error Found","id":3},{"date":"06/27/2016","error":"Lack of Planting Dates Established","id":3},{"date":"06/28/2016","error":"Weather Patterns","id":3}]</td>
<td>null</td>
</tr>
<tr>
<td>Burley Tobacco</td>
<td>null</td>
<td class="fpdCell">null</td>
<td>null</td>
</tr>
<tr>
<td>Fire Cured Tobbacco</td>
<td>null</td>
<td class="fpdCell">null</td>
<td>null</td>
</tr>
<tr>
<td>Flue Cured Tobacco</td>
<td>null</td>
<td class="fpdCell">null</td>
<td>null</td>
</tr>
<tr>
<td>Oats</td>
<td>null</td>
<td class="fpdCell">null</td>
<td>null</td>
</tr>
What I need to do is to loop through each of the cells with the fpdCell class, loop the object inside of each of those cell, create a list and add them as list element.
This is as far as I was able to get. I really don't know how to move forward from here.
var theCells = $('.fpdCell');
$.each(theCells, function(index, value) {
var cellValues = $.parseJSON(value.textContent);
if (cellValues != 'null') {
console.log(cellValues);
value.textContent = '';
$(value).append('<ul class="list-group ul'+index+'"></ul>')
//then add <li class="list-group-item">Test</li>
//Not working------------------
/*
for (var u = 0; u < cellValues. length; u++) {
$('ul' + index).append('<li class="list-group-item">'+cellValues[u].date+'</li>');
console.log(cellValues[u].date);
}
*/
}
});
Thanks in advance.
To achieve this you just need two loops, one to go through the .fpdCell elements, the other to go through the parsed JSON and build the HTML of the ul. Try this:
$('.fpdCell').each(function() {
var $el = $(this), html = '';
$.each(JSON.parse($el.text()), function(i, obj) {
html += '<li class="list-group-item">' + obj.date + '</li>';
})
$el.append('<ul>' + html + '</ul>');
});
Working example
var theCells = $('.fpdCell');
$.each(theCells, function() {
var cellValues = $.parseJSON($(this).text());
if (cellValues != 'null') {
console.log(cellValues);
$(this).html("");
var list = '<ul class="list-group ul'+index+'">';
for (var u = 0; u < cellValues.length; u++) {
list+='<li class="list-group-item">'+cellValues[u].date+'</li>';
console.log(cellValues[u].date);
}
if(cellValues.length>0)
list+="</ul>";
$(this).append(list);
}
The objects in the fpdcell columns are array objects which you may have missed in your logic.
One more thing, may be a typo, but, you missed the . in the commented code to append list items to the ul :)
Here is a solution which loops through the array and then loops through the individual elements in each array element to create a linear list.
var theCells = $('.fpdCell');
$.each(theCells, function(index, value) {
var cellValues = JSON.parse(value.textContent);
if (cellValues != 'null') {
$(value).html('<ul class="list-group ul'+index+'"></ul>');
$.each(cellValues, function(cellValueIndex, cellValue){
for (var prop in cellValue) {
$('.ul'+index).append('<li class="list-group-item">'+ cellValue[prop] +'</li>');
}
});
} else {
$(value).html('');
}
});
This may not be the exact solution to what you are looking for but, should help you along the line you would want to go. Happy coding.
Here is a fiddle with the solution JSFiddle
Here is the following table code and I want to store all TD values into an Array.
<tr class="item-row">
<td class="item-name"><textarea>Item</textarea></td>
<td class="description"><textarea>Item</textarea></td>
<td><textarea class="cost">$0.00</textarea></td>
<td><textarea class="qty">0</textarea></td>
<td><span class="price">$0.00</span></td>
</tr>
<tr class="item-row">
<td class="item-name"><textarea>Item</textarea></td>
<td class="description"><textarea>Item</textarea></td>
<td><textarea class="cost">$0.00</textarea></td>
<td><textarea class="qty">0</textarea></td>
<td><span class="price">$0.00</span></td>
</tr>
For this I have written this following code:
function checkForm() {
var table = document.getElementsByClassName("item-row");
var arr = new Array();
for (var i = 0, row; row = table.rows[i]; i++) {
for (var j = 0, col; col = row.cells[j]; j++) {
arr.push(row.cells[j].val);
}
}
}
But this gives me no output...I am new to javascript so may be am missing something in big time.
Your code is almost right, the thing is that rows property work for tables not for trs so you have to take a table instead of the tr directly.
The other thing is that getElementsByClassName returns an array of your elements so you have to use [index] to get your element.
The last thing is that to get the value for the cell you can't use val, so use firstChild to get the child and value to get the value as in the code, or better as #pawel suggest directly cell.textarea :)
Try with this code:
function checkForm() {
var table = document.getElementsByClassName("yourTable")[0];
var arr = new Array();
for (var i = 0, row; row = table.rows[i]; i++) {
for (var j = 0, col; col = row.cells[j]; j++) {
arr.push(row.cells[j].firstChild.value);
}
}
console.log(arr);
}
<table class="yourTable">
<tr class="item-row">
<td class="item-name"><textarea>Item</textarea></td>
<td class="description"><textarea>Item</textarea></td>
<td><textarea class="cost">$0.00</textarea></td>
<td><textarea class="qty">0</textarea></td>
<td><span class="price">$0.00</span></td>
</tr>
<tr class="item-row">
<td class="item-name"><textarea>Item</textarea></td>
<td class="description"><textarea>Item</textarea></td>
<td><textarea class="cost">$0.00</textarea></td>
<td><textarea class="qty">0</textarea></td>
<td><span class="price">$0.00</span></td>
</tr>
</table>
<input type="button" onclick="checkForm();" value="check form"/>
Hope this helps,
What you have is a good first effort for being new to JavaScript, but, yes, there are quite a few items that need updating. :)
Here is what you would need to do what you are trying to do:
function checkForm() {
var rows = document.getElementsByClassName("item-row");
var arr = new Array();
for (i = 0; i < rows.length; i++) {
var cols = rows[i].getElementsByTagName("td");
for (j = 0; j < cols.length; j++) {
arr.push(cols[j].textContent);
}
}
}
You need to cycle through each row . . . the easiest way to do this by going from i = 0 to i < rows.length in your for loop.
Once you have a row, you need to gather all of the columns in the row, by finding all of the <td> elements (var cols = rows[i].getElementsByTagName("td"););
Then, you loop through each of those, just like you did with the rows (j = 0 to j < cols.length
Finally, to get the text contained in each td, you use the textContent property . . . values (i.e., the value property) are used only for <input> elements
There were a couple of syntax errors in there, too (you used , instead of ;, when building your for loop and you used val instead of value, when attempting to get the td content), but that was all that I saw.
Edit: I'm also assuming that you just did not paste your <table> tags in when you added your HTML, but, if you didn't your <tr> tags must be inside a <table.
Edit 2: My solution also skips the looking at the tags inside the <td> elements, since they are not standard (4 contain <textarea> inputs and the 5th a <span>). If you want to go down one more level of detail, you could use .value on the textareas and (again) .textContent on the <span>. By using .textContent one level up, you are ignoring all HTML tags insid the <td> tags and returning only the text.
I am trying to get to the logic of the Tic Tac Toe game which I almost have made a logic, but I am stuck while pushing the Data to the array. Here is a fiddle that I have created.
http://jsfiddle.net/afzaal_ahmad_zeeshan/6bgjp/1/
Let me explain the whole thing to you!
I am trying to use the 9 td of the table as the 8 rows of the possible win. For that I have given some of the tds a className depending on their location in the table.
The HTML is simple
<div class="vicvacvoe">
<table>
<tr>
<td class="line1 line4 line7"></td>
<td class="line1 line5"></td>
<td class="line1 line6 line8"></td>
</tr>
<tr>
<td class="line2 line4"></td>
<td class="line2 line5 line7 line8"></td>
<td class="line2 line6"></td>
</tr>
<tr>
<td class="line3 line4 line8"></td>
<td class="line3 line5"></td>
<td class="line3 line6 line7"></td>
</tr>
</table>
</div>
Just a simple table with 9 tds, the CSS is not relative to this so leave it I guess.
jQuery for this also simple one. But I am not able to push the data to the Array.
var vic = $('.vicvacvoe table tr td');
var player = 1;
var tick = '✓';
var cross = 'X';
var user1 = [];
var user2 = [];
vic.click(function () {
var className = $(this).attr('class');
if (className != 'dead') {
// A new board place to write on...
// Now do the processes here...
if (player == 1) {
// First player!
var cArray = className.split(' ');
for (i = 0; i < cArray.length; i++) {
for (j = 0; j < user1.length; j++) {
// check for each class
if (user1[j] != cArray[i]) {
user1.push(cArray[i]);
}
}
}
} else {
/* code for second player, the same */
}
$(this).text('Works!');
$(this).attr('class', 'dead');
}
});
This is the entire jQuery script. Actually when I run the code, it really does go to the end of the stack (to the class attribute change script) and it locks the td for further process and it write Works! in the td too. But I am not able to get the classNames inside the Array for that user. I want to save the line number for each user and then check whether he has 3 spots filled or not. I need help with the Array part.
Thanks!
I prefer simplicity so you could use indexOf to check whether the class is already in the users' array like so:
if (player == 1) {
// First player!
var cArray = className.split(' ');
for (i = 0; i < cArray.length; i++) {
if(user1.indexOf(cArray[i]) == -1) {
user1.push(cArray[i]);
} else {
// css class is already in the array
}
}
}
Your issue is here:
for (j = 0; j < user1.length; j++) {
The only place you add to the user1 array is within this loop. Now the array is initially empty, so clearly this loop will never iterate as user1.length is always 0.
I think your intent with this bit of code was to check if the value was already in the array in which case I suggest using $.inArray.
Im trying to achieve the following: Add the numbers from two table columns, perform the following operation on them ($price2 - $price1)/$price1 * 100 and then add the result to the top of the table in a special div.
<div id="mydiv">Percentage Gain/Loss</div>
<table id="mytable">
<tbody>
<tr>
<th>price1</th><th>price2</th>
</tr>
<tr>
<td>10</td><td>30</td>
</tr>
<tr>
<td>5</td><td>10</td>
</tr>
<tr>
<td>15</td><td>5</td>
</tr>
</tbody>
</table>
So the desired operation would populate #mydiv with the results of ((30+10+5) - (10+5+15))/(10+5+15)*100 What would be the best way to achieve this? Also, if price2 should happen to be lower than price1 the output should be negative (I guess something like -Math.abs would work).
You can use getElementsByTagName to get the html elements that contain your prices and then do the computations.
var sum1 = 0, sum2 = 0;
var table = document.getElementById('mytable');
var rows = table.getElementsByTagName('tr'); // restrict the search to one table
for (var i=0, length = rows.length; i<length; i++) {
var tds = rows[i].getElementsByTagName('td');
if (tds.length >= 1) {
var val1 = +tds[0].innerHTML; // unary plus converts the value to Number
var val2 = +tds[1].innerHTML;
sum1 += val1;
sum2 += val2;
}
}
document.getElementById('mydiv').innerHTML = (sum2 - sum1) / sum1 * 100 + '';
Working JsFiddle: http://jsbin.com/IqARONE/1/edit
I would just put classes to each td, something like:
<tr>
<th>price1</th><th>price2</th>
</tr>
<tr>
<td class="price1">10</td><td class="price2">30</td>
</tr>
<tr>
<td class="price1">5</td><td class="price2">10</td>
</tr>
<tr>
<td class="price1">15</td><td class="price2">5</td>
</tr>
Then, in your JavaScript, use the getElementsByClassName method to get an array of price1 tags and a second array of price2 tags, then use the parseInt method to get the actual value inside each tag and compute the wanted value. You then put this value using something like $('#mydiv').html(total). Hope this helps.