Replace with RegEx does not update source value - javascript

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

Related

How to add and subtract numbers via JavaScript in an HTML table

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.

Repeat script for multiple elements

Hey i have this code:
<body>
<table>
<tr>
<td class="first">100</td>
</tr>
</table>
<h4 class=curs style="display:none">10</h4>
<script>
document.body.onload = function(){
var firstTdVal = document.getElementsByClassName('first')[0].innerHTML;
var secondTdVal = document.getElementsByClassName('curs')[0].innerHTML;
var valueToBeShown = parseInt(firstTdVal)/ parseInt(secondTdVal);
document.getElementsByClassName('first')[0].innerHTML = valueToBeShown ;
}
</script>
</body>
As you see ".first" has a number in it,this number is divied to ".curs" and the result is showed in ".first" too.Now the problem is that for exemple i add 100 more td's with class ".second,.third...,.hundred" in table.How to make script to do the same for all td's as it does for the ".first"(devide to ".curs").How do i do this in my JS by keeping it complex.
Use document.querySelectorAll to get an array of matched elements (matched with CSS selector), then loop through them using forEach, applying you logic one td at a time. Like this:
// querySelector gets the first element matched. textContent get the text of that element
var cursValue = parseInt(document.querySelector(".curs").textContent);
// querySelectorAll get an array of all the matched elements
var tds = document.querySelectorAll("td");
// loop through that array one td at a time
tds.forEach(function(td){
// get the text of the current td
var value = parseInt(td.textContent);
// if the value is not valid (a string for example) return and don't process anymore for this td (go straight to the next one).
if(isNaN(value)) return;
// calculate the new value
value = value / cursValue;
// change the text of this td (update it to the new value)
td.textContent = value;
});
NOTE: querySelector and querySelectorAll match elements using CSS selectors, so to match an element using a class the selector should be ".className", to match it using an ID: "#someID", ... All CSS selectors are accepted (even this one: "#anID>li.some-class a:not([href])").
NOTE2: tds is an array, so if you don't want to use forEach you can use a normal for loop (for(var i = 0; i < tds.length; i++) ...).
This will iterate over your table (be sure to set the table ID) (open dev console to view output but it's pretty straight forward.)
var table = document.getElementById("myTable");
for (var row of table.rows) {
for (var col of row.cells) {
console.log(col.className, col.innerHTML); //Class names and the values of the elements.
}
}
If you need anymore help please ask because I do not fully understand what you're trying to do here.
Here's a way where you put the number to be divided by in the first td, the number to divide by in the second td, and the result will be placed in the third td.
var trs = document.getElementsByTagName('tr');
for (var i = 0; i< trs.length; i++) {
var tds = trs[i].getElementsByTagName('td'),
first = tds[0].textContent,
second = tds[1].textContent,
third = tds[2],
result = (parseInt(first) / parseInt(second));
third.innerHTML = result;
}
<table>
<tr>
<td>10</td>
<td>2</td>
<td></td>
</tr>
<tr>
<td>4</td>
<td>2</td>
<td></td>
</tr>
</table>

Using Javascript replace with getElementsByClassName not working

I posted a question a few days ago which worked great and I thank those who helped but for reasons beyond my control I have to classes instead of id's as per my original post.
Basically what I am trying to do is remove the word "Other" from a string (The content is added dynamically through a form).
Here is the code I am trying to use:
var str = document.getElementsByClassName('gv-field-4-custom').innerHTML;
var text = str.replace("Other", " ");
document.getElementsByClassName('gv-field-4-custom').innerHTML = text;
.gv-field-4-custom {
color: #ff0000;
}
<table>
<tr>
<td class="gv-field-4-custom">Complex interventions, Evidence Synthesis (randomised trials), Studies within a Trial (SWAT), Trial Conduct, Trial Design, Other Core Outcome Sets (COS)</td>
</tr>
</table>
Any advise as to what I am doing wrong?
Your problem here is, that getElementsByClassName returns a set of elements, which in this particular case just contains a single element. If you just have a single element with this className, or just want to change one single element, you can go like this:
var element = document.getElementsByClassName('gv-field-4-custom')[0];
var str = element.innerHTML;
var text = str.replace("Other", " ");
element.innerHTML = text;
.gv-field-4-custom {
color: #ff0000;
}
<table>
<tr>
<td class="gv-field-4-custom">Complex interventions, Evidence Synthesis (randomised trials), Studies within a Trial (SWAT), Trial Conduct, Trial Design, Other Core Outcome Sets (COS)</td>
</tr>
</table>
If you have more elements that need a treatment, go like this:
var elements = document.getElementsByClassName('gv-field-4-custom');
for (var i = 0; i < elements.length; i++) {
var str = elements[i].innerHTML;
var text = str.replace("Other", " ");
elements[i].innerHTML = text;
}
.gv-field-4-custom {
color: #ff0000;
}
<table>
<tr>
<td class="gv-field-4-custom">Complex interventions, Evidence Synthesis (randomised trials), Studies within a Trial (SWAT), Trial Conduct, Trial Design, Other Core Outcome Sets (COS)</td>
</tr>
</table>
document.getElementsByClassName('gv-field-4-custom')
will returns an array.You cannot directly get the innerHtml.
use document.getElementsByClassName('gv-field-4-custom')[0].innerHtml to get the value.Use the below code
var str = document.getElementsByClassName('gv-field-4-custom')[0].innerHTML;
var text = str.replace("Other", " ");
Note the s in getElementsByClassName. It means you need to loop over these.
You can use either the code
var className= document.getElementsByClassName("gv-field-4-custom");
for(i=0;i<className.length;i++)
{
className[i].innerHTML = "text";
}
like #saina suggested, or use document.getElementsByClassName('gv-field-4-custom')[0] like #Imran suggested.
var str = document.getElementsByClassName('gv-field-4-custom')[0];
var oldText = str.innerHTML
var text = oldText.replace("Other", " ");
str.innerHTML = text;
try this:
document.getElementsByClassName('gv-field-4-custom')[0]
instead of
document.getElementsByClassName('gv-field-4-custom')

How can I fix jquery when i change table elements to div style in body section?

<body>
<input type="text" id="search"/>
<table id="boxdata">
<tr>
<td class="namebox1">jQuery</td>
</tr>
<tr>
<td class="namebox2">javascript</td>
</tr>
<tr>
<td class="namebox3">php</td>
</tr>
<tr>
<td class="namebox4">sql</td>
</tr>
<tr>
<td class="namebox5">XML</td>
</tr>
<tr>
<td class="namebox6">ASP</td>
</tr>
</table>
</body>
<script>
$(document).ready(function(){
$('#search').keyup(function(){
searchBox($(this).val());
});
});
function searchBox(inputVal) {
$('#boxdata').find('tr').each(function(index, row){
var names = $(row).find('td');
var found = false;
if(names.length > 0) {
names.each(function(index, td) {
var regExp = new RegExp(inputVal, 'i');
if(regExp.test($(td).text()) & inputVal != ''){
found = true;
return false;
}
});
if(found == true)
$(row).addClass("red");
else
$(row).removeClass("red");
}
});
}
</script>
there's a textfield for searching words and there are 6 words in the each 6 boxes below textfield.(I omitted css codes. but, it wouldnt matter to solve the problem.). if i type a letter 's' then the words that including letter 's' like 'javascript', 'sql', 'ASP' these font-color will be changed black to red. And i made it by using table elements in html but i'd like to change all elements into div style to put some data fluidly later. i have difficulty to fix especially jquery. how can i fix it?
You can simplify this a little bit.
function searchBox(inputVal) {
var regExp = new RegExp(inputVal, 'i');
$('#boxdata').find('tr').removeClass('red').filter(function() {
return $(this).find('td').filter(function() {
return regExp.test( $(this).text() );
}).length && $.trim(inputVal).length;
}).addClass('red');
}
So remove the red class from all <tr>'s first, then filter them, test the text of each <td>, if it matches, return the <tr> and then add the class red again.
Here's a fiddle
As for changing from a table to div, the jQuery would depend on how you structure your markup, but the principle would remain the same.
Here's another fiddle
You can make javascript code HTML agnostic by using css classes instead of element names. Demo.
function searchBox(inputVal) {
var regExp = new RegExp(inputVal = $.trim(inputVal), 'i'),
highlight = 'red';
$('#wrapper').find('.word') //instead of tr/td/div
.removeClass(highlight)
.each(function(){
var $this = $(this);
inputVal && regExp.test($this.text()) &&
$this.addClass(highlight);
});
}

How can I access elements inside a table in Javascript?

I have html that looks like this,
<table id="TableAddresses">
<tbody>
<tr>
<td>
string 1
</td>
<td>
<input type="hidden" id='ADDR_843886'
<div id='FLAG_843886'>Pending...</div>
</td>
</tr>
<tr>
<td>
string 2
</td>
<td>
<input type="hidden" id='ADDR_843886'
<div id='FLAG_843886'>Pending...</div>
</td>
</tr>
How do I get all the strings inside of TableAddresses > tbody >tr > td[0]?
EDIT:
I was mistaken in tagging jquery. This is actually a asp.net project.
An easy way would be to use querySelectorAll
var td = querySelectorAll("#TableAddresses tbody td")[0];
Otherwise you can do
var table = document.getElementById("TableAddresses");
var tbody = table.getElementsByTagName("tbody")[0];
var tr = tbody.getElementsByTagName("tr")[0];
var td = tr.getElementsByTagName("td")[0];
// etc
You can try this:
document.getElementById('TableAddresses').firstChild.firstChild.firstChild.innerHTML
or with less legacy support:
document.querySelector('#TableAddresses td').innerHTML
You can use the map method:
var strings = $('#TableAddresses td:first-child').map(function() {
return $.trim( this.textContent || this.innerText );
}).get(); // ["string 1", "string 2"]
Alternatively you can read the HTMLTableElement's rows property:
var rows = document.getElementById('TableAddresses').rows,
strings = [];
for (var i = 0; i < rows.length; i++) {
if ( rows[i].cells[0] ) {
strings.push( rows[i].cells[0].innerHTML );
}
}
http://jsfiddle.net/kvyUh/
Using jQuery:
var myString = $('#tableAddress td:first').text()
Cheers!
There's an MDN article on this topic. In a nutshell, you need to traverse your table with standard means, mostly getElementsByTagName, see this jsBin (look in the console).
var table = document.getElementById("TableAddresses");
var rows = table.getElementsByTagName("tr");
Array.prototype.forEach.call(rows, function(ele, idx) {
console.log(ele.getElementsByTagName("td")[0].textContent.trim());
});
This snippet traverses each row of your table and outputs the textContent of the first <td> element. Please note that this will most likely not work out of the box on older IE versions iirc, but nothing that can't be shimmed. ;-)

Categories

Resources