I have a table where one td gets 1 if a checkbox is checked and I would like to multiple this td with another and display it in a third one.
See the html here:
<div>
<input type="checkbox" id="fut1">check</input>
</div>
<table border="1" cellpadding="10" id="countit">
<tr>
<td id="td1"></td>
<td id="td2">5000</td>
<td id="td3"></td>
</tr>
</table>
And here is the js:
$('#fut1').change(function () {
if ($(this).is(":checked")) {
$('#td1').text('1');
} else {
$('#td1').text('0');
}
});
$('#td1').change(function () {
var me = $('#td1').value;
var ar = $('#td2').value;
var sum = me * ar;
$('#td3').text(sum);
});
$('#td1').change(function () { // <--- td elements don't have a change event listener/handler
var me = $('#td1').value; // <--- td elements don't have a value
var ar = $('#td2').value; // <--- td elements don't have a value
var sum = me * ar;
$('#td3').text(sum);
});
If you want to do it this way:
$('#fut1').change(function () {
if ($(this).is(":checked")) {
$('#td1').text('1');
} else {
$('#td1').text('0');
}
callTdChange();
});
function callTdChange() {
var me = parseInt($('#td1').text());
var ar = parseInt($('#td2').text());
var sum = me * ar;
$('#td3').text(sum);
}
Of course, the better way should be to use form elements (inputs) in the case you want to save your data to a server, or use change behaviors.
#td1 doesn't support the change event, because that's only meant for interactive elements (like input, select, or textarea).
You can either do the calculation in your first event listener in #fut1, or declare an input element inside #td1.
Related
I have this function (it works) to create a number of dynamic inputs:
<script type='text/javascript'>
var arr = [];
function espacioArreglos() {
// Number of inputs to create
var number = document.getElementById("cantidadArreglos").value;
// Container <div> where dynamic content will be placed
var container = document.getElementById("container");
// Clear previous contents of the container
while (container.hasChildNodes()) {
container.removeChild(container.lastChild);
}
for (i=0;i<number;i++){
// Append a node with a random text
container.appendChild(document.createTextNode("Arreglo #" + (i+1)));
// Create an <input> element, set its type and name attributes
var input = document.createElement("input");
input.type = "number";
input.name = "arreglo" + i;
//set ID to each input to calculate summatory
var inputId = 'input-' + i;
input.setAttribute('id', inputId);
arr.push(inputId);
input.setAttribute('onchange', function() {
var sum = 0;
arr.forEach(function(val) {
var inputVal = document.getElementById(val).value;
if (inputVal) sum += inputVal;
});
document.getElementById('totalPlacas').value = sum;
});
container.appendChild(input);
// Append a line break
container.appendChild(document.createElement("br"));
}
}
</script>
And now I want to display the sum of the input values. Here is the HTML:
<tr>
<td align="center" bgcolor="#D4D4D4">Cantidad de arreglos:</td>
<td align="center" bgcolor="#D4D4D4"><input type="number" id="cantidadArreglos" onchange="espacioArreglos();" size="1"></td>
</tr>
<tr>
<td align="center" bgcolor="#D4D4D4">Cantidad de placas:</td>
<td bgcolor="#FFFF00"><div id="container"/></td>
</tr>
<tr>
<td align="center" bgcolor="#D4D4D4">Total de placas:</td>
<td align="center" bgcolor="#D4D4D4"><div id="totalPlacas"></div></td>
</tr>
So, you enter a number in "Cantidad de arreglos", it calls the function "espacioArreglos" and then I want to use the values that I will enter on the generated inputs to calculate its summatory, which should be displayed at the div "totalPlacas". However, nothing appears... Whats the problem with my code?
There are some changes that need to be done:
First, change the
<div id="container"/> to <div id="container"></div> as the shortcut on a div breaks the HTML causing that totalPlacas doesn't exists.
Second, add the onchange event using
input.onchange = function() {...}
Now the result should be added to the 'totalPlacas' div using .innerText = sum instead using the .value = sum.
Now you can check that the result displayed is a concatenation of strings instead adding the numbers, this can be solved replacing
if (inputVal) sum += inputVal;
with
if (inputVal) sum += parseInt(inputVal);
You should add some kind of validation to avoid an error when the user types a letter or symbol instead a number.
Hope it works!
You will need to assign a unique ID to the input elements, so you can reference them using document.getElementById().
Something like:
input.setAttribute("id", 'input' + i);
How about assigning id's to the dynamic inputs and storing them in an array. First, outside of the function (global scope) define an empty array:
var arr = [];
In your for loop:
var inputId = 'input-' + i;
input.setAttribute('id', inputId);
arr.push(inputId);
input.setAttribute('onchange', function() {
var sum = 0;
arr.forEach(function(val) {
var inputVal = document.getElementById(val).value;
if (inputVal) sum += inputVal;
});
// do something with the sum
console.log(sum)
});
I have a monthly calendar which displays days with events happening in this day. This is how generated HTML looks like:
<table class="event-cal">
<tbody>
<tr class="eventcont event-93">
<td class="eventtime">19:00</td>
<td><a class="calendar-title" href="#>Event title</a><br></td></tr>
<tr class="eventcont event-237">
<td class="eventtime">13:00</td>
<td><a class="calendar-title" href="#">Event 2 title</a><br></td></tr>
</tbody>
</table>
What I want to do is to order tr.eventcont elements based on contents of .eventtime child element. Ordering has to be done within .event-cal element which contains these particular .eventcont elements because I will have several .event-cal elements in the page.
Here is the code I have so far but what it does it takes all tr.eventcont elements from page and pastes them all into each .event-cal table.
$( document ).ready(function() {
var list = $(".event-cal").find(".eventcont");
list.sort(sortDesc);
$(".event-cal").html("");
$(".event-cal").append(list);
});
function sortDesc(a, b){
var test1 = jQuery(a);
var test2 = jQuery(b);
return test1.find(".eventtime").text() > test2.find(".eventtime").text();
}
You need to run your function for each table using jquery.fn.each
$('.event-cal').each(function() {
var table = $(this),
list = table.find('.eventcont').sort(sortDesc);
table.empty().append(list);
});
Check this fiddle
$(".event-cal").each(function(){
var events=$('tr',this);
events.sort(function (a, b) {
a = parseInt($('.eventtime',a).text().replace(':',''));
b = parseInt($('.eventtime',b).text().replace(':',''));
if(a > b) {
return 1;
} else if(a < b) {
return -1;
} else {
return 0;
}
});
$(this).html(events);
});
Hi I am struck with this problem.
I need to create a table with Onclicklisteners dynamically. so i prefered this way.
function create_weekmenu(json)
{
var column_list=json.week_list;
var menu_table=document.getElementById("weekmenu");
var row=document.createElement('tr');
for(var i=0;i<column_list.length;i++)
{
var cell=document.createElement('th');
var span_ele=document.createElement('span');
if(span_ele.addEventListener)
{
span_ele.addEventListener('click', toggletable(column_list[i]),true);
}
else if(span_ele.attachEvent)
{ // IE < 9 :(
span_ele.attachEvent('onclick', toggletable(column_list[i]));
}
span_ele.appendChild(document.createTextNode(column_list[i]))
cell.appendChild(span_ele);
row.appendChild(cell);
}
menu_table.appendChild(row);
}
The Resultant element Structure I am getting is
<table id="weekmenu">
<tr>
<th>
<span>week_one</span>
</th>
<th>
<span>week_two</span>
</th>
</tr>
</table>
But i need a Element Structure like this,
<table id="weekmenu">
<tr>
<th>
<span onclick="toggle(week_one)'>week_one</span>
</th>
<th>
<span onclick="toggle(week_two)'>week_two</span>
</th>
</tr>
</table>
Further to notice: I could see that the onclick listener is triggering while creating the element. but its not binding with the element permanently.
What would be the solution.
I prefered to construct DOM structure using appendChild() than by .innerHTML or document.write().
The problem is that you're calling the toggleTable function when you attach it. That's why it's being triggered when you create the element.
span_ele.addEventListener('click', toggletable(column_list[i]),true);
To avoid that it should be:
span_ele.addEventListener('click', toggletable, true);
But obviously that doesn't pass in the column to toggle so it's not ideal.
I would use something like:
function create_weekmenu(json)
{
var column_list=json.week_list;
var menu_table=document.getElementById("weekmenu");
var row=document.createElement('tr');
for(var i=0;i<column_list.length;i++)
{
var cell=document.createElement('th');
var span_ele=document.createElement('span');
if(span_ele.addEventListener)
{
span_ele.addEventListener('click', function(col) {
return function() {
toggletable(col);
}
}(column_list[i]),true);
}
else if(span_ele.attachEvent)
{ // IE < 9 :(
span_ele.attachEvent('onclick', function(col) {
return function() {
toggletable(col);
}
}(column_list[i]));
}
span_ele.appendChild(document.createTextNode(column_list[i]))
cell.appendChild(span_ele);
row.appendChild(cell);
}
menu_table.appendChild(row);
}
You need to make sure you attach a function to the event handler, not the result of a function.
function create_weekmenu(json) {
var column_list = json.week_list;
var menu_table = document.getElementById("weekmenu");
var row = document.createElement('tr');
for (var i = 0; i < column_list.length; i++) {
var cell = document.createElement('th');
var span_ele = document.createElement('span');
span_ele.setAttribute('onclick', 'toggletable(column_list[' + i + '])');
span_ele.appendChild(document.createTextNode(column_list[i]))
cell.appendChild(span_ele);
row.appendChild(cell);
}
menu_table.appendChild(row);
};
I have a table with two different columns that I would like to add up to their respective sums. Right now I just add up one of the columns, I could add up the second column by just making the same JS again but with different names for the values but that is not so pretty.
How would I do to change it so it counts the ue column as well as the egen and spit out two results, sum and sum2.
<table>
<tr>
<td><asp:TextBox ID="TextBox1" runat="server">Number</asp:TextBox></td>
<td class="egen"><asp:TextBox ID="TextBox56" runat="server" Columns="1">56</asp:TextBox></td>
<td class="ue"><asp:TextBox ID="TextBox57" runat="server" Columns="1">57</asp:TextBox></td>
</tr>
<tr>
<td><asp:TextBox ID="TextBox2" runat="server">Worker</asp:TextBox></td>
<td class="egen"><asp:TextBox ID="TextBox58" runat="server" Columns="1">58</asp:TextBox></td>
<td class="ue"><asp:TextBox ID="TextBox59" runat="server" Columns="1">59</asp:TextBox></td>
</tr>
<tr>
<td align="right">Sum:</td>
<td align="center"><span id="sum"></span></td>
<td align="center"><span id="sum2"></span></td
</tr>
</table>
This is my javascript that I use to add up the values in the column egen.
$(document).ready(function () {
//iterate through each td based on class / input and add keyup
//handler to trigger sum event
$(".egen :input").each(function () {
$(this).keyup(function () {
calculateSum();
});
});
});
function calculateSum() {
var sum = 0;
// iterate through each td based on class and add the values from the input
$(".egen :input").each(function () {
var value = $(this).val();
// add only if the value is number
if (!isNaN(value) && value.length != 0) {
sum += parseFloat(value);
}
});
$('#sum').text(sum);
};
You can target all elements in .egen or .ue by the following selector:
$('.egen :input, .ue :input')
Or if you prefer:
$('.egen, .ue').find(':input')
By the way you don't need to iterate over the collection of elements to bind keyup listeners to them, you can bind to the entire collection immediately:
$('.egen :input, .ue :input').keyup(calculateSum);
EDIT
I note from the presence of #sum and #sum2 that you may want to sum up the columns separately. You could do something like this:
$('.egen :input').keyup(function() { calculateSum('.egen'); });
$('.ue :input').keyup(function() { calculateSum('.ue'); });
function calculateSum(container) {
var sum = 0;
$(container).find(':input').each(function() {
...
});
}
And then of course set the value of #sum or #sum2, respectively. That could be acheived in a number of ways. Either you pass the id, just as we're passing the class above, or you use a class named sum, and have the respective td's reuse the egen and ue classes. That way you could access the correct sum with $(container+'.sum').val(). Another solution would be to just return the sum, and setting it in your keyup listener:
$('.ue :input').keyup(function() {
$('#sum2').val( calculateSum('.ue') );
});
Note also that your parsing could be simplified. parseFloat will yield NaN for a lot of invalid values, including empty strings and null, so you do not need to check your values closely before calling it. NaN will evaluate to false, so you could always sum by (parsedResult || 0), as the result would be 0, leaving the sum unaffected, if parsedResult is NaN.
Thus:
var sum = 0;
$(container).find(':input').each(function() {
sum += (parseFloat( $(this).val() ) || 0);
});
changed your sum <span> id to its respective class_sum like
<span id="egen_sum"></span>
<span id="ui_sum"></span>
...
so that we can get this working with one function
try this
$('.egen :input, .ue :input').keyup(function(){
var keyupClass= $(this).parent().hasClass('egen') ? 'egen' : 'ue';
calculateSum(keyupClass);
});
function calculateSum(keyupClass) {
var sum = 0;
$("."+ keyupClass+" :input").each(function () {
var value = $(this).val();
// add only if the value is number
if (!isNaN(value) && value.length != 0) {
sum += parseFloat(value);
}
});
$('#'+keyupClass+"_sum").text(sum);
};
this will work for any number of input ... just need to make sure the corresponding sum span is given the right id...
I have a table which will output the id of the parent cell when it is clicked. How could I change this so it outputs more than one clicked cell. For example, right now if I click cell id '1' it will output 1. If I click cell '2' it will output 2 and so on. How can I make it so that it outputs '1,2,3' given that I've clicked on cell 1, 2 and 3.
HTML:
<table>
<tr>
<td class='test' id='1'><img src='images/Dog.gif'/></td>
<td class='test' id='2'><img src='images/Cat.gif'/></td>
<td class='test' id='3'><img src='images/Mouse.gif'/></td>
<td class='test' id='4'><img src='images/Human.gif'/></td>
</tr>
</table>
<div id='output'></div>
JS:
$(document).ready(function() {
$('td.test').click(function() {
$('#output').text(this.id);
});
});
Also, is there a way that if I clicked back on say, cell 2. it would remove '2' from the list.
Use an array to keep track of clicked items:
$(document).ready(function() {
var clicked = [];
$('td.test').click(function() {
var found = clicked.indexOf(this.id);
// Remove
if(found !== -1) {
clicked.splice(found, 1);
// Add
} else {
clicked.push(this.id);
}
$('#output').text(clicked.join(','));
});
});
http://jsfiddle.net/mx2kj/
var ids = "";
$(".test").on("click", function () {
$(this).data("selected", !$(this).data("selected"));
var ids = $(".test").filter(function () {
return $(this).data("selected") === true;
}).map(function () {
return this.id;
}).get().join(",");
alert(ids);
});
Demo: http://jsfiddle.net/fY5tj/1
You can append your clicked item id in your output div like this :
$('td.test').click(function() {
var currentText = $("#output").text();
$("#output").text(currentText+this.id);
});