Why does this Javascript only run once per page? - javascript

I have this Try-it-Yourself section to my website but for some reason when I am wanting to have more than one Try-it-Yourself section it will only work for the one at the top of the page. So if I had three of them on a page the top one would work in the way I want but the next two would do nothing.
I have the following HTML:
<div class="tryit">
<table>
<tr>
<td>Try It Yourself</td>
</tr>
<tr>
<td><textarea id="input" rows="10" cols="47"></textarea></td>
</tr>
<tr>
<td><input onclick="update();" type="button" value="Update"></td>
</tr>
<tr>
<td><iframe id="output" name="output" width="600" height="300" ></iframe></td>
</tr>
</table>
</div>
And the following Javascript:
function update()
{
var tryitoutput = document.getElementById('input').value;
window.frames['output'].document.documentElement.innerHTML = tryitoutput;
}
Thank you.

As others mentioned, this is happening because there can't be more than one HTML element with same value of ID attribute. In your case javascript only finds the first element, that's why it doesn't work on later Update buttons. The simplest approach would be to set different ID attribute values for different "Try it yourself" boxes:
Slightly modify your JS, see following jsFiddle example
function update(tryItIndex) {
var tryItOutput = document.getElementById('input-' + tryItIndex).value;
window.frames['output-' + tryItIndex].document.documentElement.innerHTML = tryItOutput;
}

That's because you are referring to the textarea and the output by id which means it will always just retrieve the first one. A quick fix would be having unique id's for these fields and send the names as parameters to the update function like update(inputId, outputId)

Related

How to create html id attributes dynamically?

Im trying to display multiple charts.
Right now, I have <canvas id="pie-chart"> inside a loop and document.getElementById("pie-chart") will only return the first element with that id. How do I create a dynamically html attribute?
<table class="table">
<tr>
<th>
Questions
</th>
</tr>
#foreach (var question in (List<Testv3.Models.MyViewModel>)ViewData["questionlist"])
{
<tr>
<td>
#question.Question
<br />
<div class="chart">
<canvas id="pie-chart"></canvas>
</div>
</td>
</tr>
}
</table>
A part of my script section:
var ctx1 = document.getElementById("pie-chart").getContext("2d");
I'm not totally sure what you are using to render your HTML since your code doesn't look like pure HTML to me. However, the answer stays the same, you can use the index of the loop as a part of your id to make it unique. Something like this:
<canvas id="pie-char-#id></canvas>
with #id is your index of the loop.
If your current renderer doesn't support that, you may want to add a counter outside of the loop, use that counter as part of your id. Then increase the counter at the end of the loop.
See Does ID have to be unique in the whole page?
The HTML Id needs to be unique in your whole HTML-Instance. Use "class" instead of "id".
Id is and was never designed to be used multiple times. Id is designed to be a unique identifier.

.each() function on affect current object

having some issues with my code below, first here is the HTML:
<table class="finance-table">
<tbody><tr>
<th></th>
<th>Deposit</th>
<th>Balance</th>
<th>Fees</th>
<th>Total Payable</th>
<th>Term</th>
<th>Fixed Rate</th>
<th>Representative APR</th>
<th>Monthly Pmt</th>
</tr>
<tr class="hp">
<td><strong>HP</strong></td>
<td id="td_finance_deposit">£11700.00</td>
<td id="td_finance_balance">£105300.00</td>
<td id="td_finance_fees">£298.00</td>
<td id="td_finance_total_inc_deposit">£146255.50</td>
<td id="td_finance_term">60 mths</td>
<td id="td_finance_rate">5.50%</td>
<td id="td_finance_apr">10.1%</td>
<td id="td_finance_monthly_payments">£2242.59 p/m* x 60 mths</td>
</tr>
</tbody></table>
There is about 10 of these tables [within the same document], all with the same id's and class's. I'm using an each loop to execute some code against each table found, however it only seems to be working on the first table and disregards the others.
Below is the jQuery, like I said works find on the first table, but ignores the rest!
<!-- Remove First and Final Payment from Showroom Finance Examples -->
<script>
$(".finance-table").each(function(key, value) {
// Display loading
var html = $(this);
// Remove the First Payment and Final Payment Column
$(this).find("#td_finance_first_payment, #td_finance_final_payment").remove();
$(this).find("th:contains('1st Pmt')").remove(); $(this).find("th:contains('Final Pmt')").remove();
// Get the Term and update the monthly payment
var term = $(this).find("#td_finance_term").html(); // .replace(/\D/g,'')
var payments = ($(this).find("#td_finance_monthly_payments").html()).split('x')[0];
($(this).find("#td_finance_monthly_payments")).html(payments + " x " + term);
})
</script>
Edit:
Please note, I can't change the HTML at all
You should first give a unique ID to each <td>, perhaps with your DB identifier for that record. You don't need it now but this will allow you to do other thing later if you need it.
Then change all the <td> ids to classes:
<td class="td_finance_fees">£298.00</td>
Finally change all your javascript accordingly to use class instead of IDs:
$(this).find(".td_finance_first_payment, .td_finance_final_payment").remove();
Using Attribute Equals Selector
Change your code from:
$(this).find("#td_finance_first_payment, #td_finance_final_payment").remove();
to:
$(this).find('td[id="td_finance_first_payment"], td[id="td_finance_final_payment"]').remove();
Do this type of change for all areas of #xxx to id="xxx"
What this does is find all tds with attribute id="xxx", rather than using #id identifier, this is forces jQuery to do a tree search.
Also your HTML does not match your code, (theres no td_finance_first_payment in your html, I assume you removed it?)
Edit: This solution is useful if you 100% cannot edit the html (comes from a source you have no control over, such as an API or internal software). Best solution would be to fix the ids!

Loop through multiple TD, grab multiple values, fill array

I have two tables on the page.
Inside of my second table I am dynamically adding html from JS.
I am checking to see if the <tr> inside of the tbody are empty using:
var rowCount = $('#dynatable >tbody >tr').length;
If the row count is 0 I continue on with my javascript, if 1 or more <tr> exists I need to go through each <tr> and grab the two input values inside the <td>; for every <tr> available. Then need to collect the data into an array for server-side processing.
<table id="dynatable">
<thead>
<tr>
<th>Time</th>
<th>Description</th>
</tr>
</thead>
<tbody id="p_scents">
<tr><td class="ts_td"><input type="text" name="ts_value[]" class="timestamp_input"/></td><td><TEXTAREA NAME="ts_description[]" class="ts_desc" rows="3" cols="30" style="resize:none;" ></TEXTAREA></td></tr>
<tr><td class="ts_td"><input type="text" name="ts_value[]" class="timestamp_input"/></td><td><TEXTAREA NAME="ts_description[]" class="ts_desc" rows="3" cols="30" style="resize:none;" ></TEXTAREA></td></tr>
</tbody>
I have browsed similar questions but I cannot figure out a solution for my situation. I had a previous solution using simpleHTMLDOM + PHP but it's way too slow performance wise.
I was told to use JS or jquery and I am quite unfamiliar with both, any help is greatly appreciated.
How do I grab the values of multiple inputs from multiple <tr>'s inside a specific table and store the values in an array?
If your classes will be the same, you could do something like this with jQuery.
It put the values into arrays.
var values = $("input[class='timestamp_input']").map(function(){return $(this).val();}).get();
var textAreaValues = $("textarea[class='ts_desc']").map(function(){return $(this).val();}).get();
console.log(values);
console.log(textAreaValues);
JSFiddle demo here.

display or read colspan value

I created a table contain the colspan and rowspan. Then I would like to get or read these colspan and rowspan value. I'm doing this because I want to use it for xml generation. I need this value. I play around with this code to test:
<!DOCTYPE html>
<html>
<head>
<script>
function displayResult()
{
document.getElementById("myHeader1").colSpan="2";
}
function displayColSpan()
{
var te;
document.getElementById("myHeader1").colSpan=te;
alert(te);
}
</script>
</head>
<body>
<table border="1">
<tr>
<th id="myHeader1">Month</th>
<th id="myHeader2">Savings</th>
</tr>
<tr>
<td>January</td>
<td>$100.00</td>
</tr>
<tr>
<td>February</td>
<td>$10.00</td>
</tr>
<tr>
<td>March</td>
<td>$80.00</td>
</tr>
</table>
<br>
<button type="button" onclick="displayResult()">Change colSpan for the first cell</button>
<button type="button" onclick="displayColSpan()">test</button>
</body>
</html>
Could you help me? Thanks!
There's a bit of confusion with your code.
This:
document.getElementById("myHeader1").colSpan=te;
Changes the colspan value of myHeader1 to var te, which is undefined. Instead you should do:
te = document.getElementById("myHeader1").colSpan
now te is the colspan value of myHeader1.
If you want to get the value, that is 'month':
te = document.getElementById("myHeader1").innerHTML
Now te has the value of 'month'!
Hope this helps!
The code you're using was copied from this site: http://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_th_colspan Isn't it?
Good, then you must have noticed that what they are doing there? They are simply changing the properties of the columns and their span, what we can say in css might be padding.
You want to get the value of the span? I never tried javascript for this, I have always used CSS.
But still, go through this page: Calculate and set colspan value dynamically
He showed a well developed code, you can also try out getting the values from element such as:
var val=document.getElementById("idofel").style.backgroundColor;
To get the background-color, you can try such other values for this table too. Obviously not background-color, but the necessary ones. And then write them in XML!

Complex jQuery filter() not working

I am trying to dynamically insert links to return to the top of the document at the end of every section of a web page (sad to say, but it's table-based layout). I'm using the jQuery filter() selector, and while I get no error, it's not making any changes in the browser output. When I use alert() with the variable, it says Object object. I understand that the problem is in the line where I define the filter itself, but I was unable to find a similar example, and I don't know how to fix it.
Here's the code:
HTML
<table>
<tr class="head"><td colspan="2">section title 1 </td></tr>
<tr><td>text</td>
<td><img /></td>
</tr>
<tr><td>text</td>
<td>< img /></td>
</tr>
<tr class="head"><td colspan="2">section title 2 </td></tr>
<tr><td>text</td>
<td><img /></td>
</tr>
<tr><td>text</td>
<td>< img /></td>
</tr>
<!-- you get the point -->
JavaScript
$(document).ready(function(){
var lastRow = $('tr').filter(function(){
return $(this).next()==$(".head"); // Here's the problem, IMO
});
var a = '<tr class="toTop"><td class="top" style="text-align:right" colspan="2">go to top ↑</td></tr>';
lastRow.after(a);
});
The script attempts to select each row that precedes a row with class="head" and insert a row with a top link.
That's because you are comparing 2 different objects that is always false, you should use is method or length property:
var lastRow = $('tr').filter(function(){
return $(this).next(".head").length;
// return $(this).next().is(".head");
});
However, I'd suggest using .prev() method:
$('tr.head').prev(); // selects the previous sibling tr element

Categories