Losing click event after recreating elements - javascript

I'm removing table tbody set and inserting new ones but I'm loosing click event on chekcbox. How can I solve this issue?
I went through append(), clone() but failed to apply to my code so for that reason I created a JSFIDDLE which has everything.
Please tell me what I need to do.
Thanks in advance.
JSFIDDLE - CODE IS HERE
JQUERY:
$(window).load(function(){
$('.add-selected').on("click",function() {
alert('hello');
});
$('#removeAndAdd').click(function(event) {
event.preventDefault();
var output = '';
output += '<tbody class="filter-rows">';
output += '<tr class="filter">';
output += '<td><input type="checkbox" id="c-1" class="add-selected" /></td>';
output += '<td>1</td>';
output += '</tr>';
output += '</tbody>';
output += '<tbody class="filter-rows">';
output += '<tr class="filter">';
output += '<td><input type="checkbox" id="c-2" class="add-selected" /></td>';
output += '<td>2</td>';
output += '</tr>';
output += '</tbody>';
$('.filter-rows').empty();
$('#add-new-table tbody:last').after(output);
});
});
HTML:
<table id="add-new-table" border="1px">
<thead>
<th>ID</th>
<th>SKU</th>
</thead>
<tbody>
<tr>
<td>Lbel</td>
<td>011</td>
</tr>
</tbody>
<tbody class="filter-rows">
<tr class="filter">
<td><input type="checkbox" id="c-1" class="add-selected" /></td>
<td>1</td>
</tr>
</tbody>
<tbody class="filter-rows">
<tr class="filter">
<td><input type="checkbox" id="c-2" class="add-selected" /></td>
<td>2</td>
</tr>
</tbody>
<tbody class="filter-rows">
<tr class="filter">
<td><input type="checkbox" id="c-3" class="add-selected" /></td>
<td>3</td>
</tr>
</tbody>
</table>
<br />
<span id='removeAndAdd'>Click me to Remove all first and Add new rows</span>

There some bad practices here. Firstly the fixed version:
http://jsfiddle.net/678CP/5/
$('#add-new-table').on('change', 'input', function() {
alert('hello');
});
$('#removeAndAdd').click(function(event) {
event.preventDefault();
var rows = $('#add-new-table .filter-rows');
rows.first().add(rows.last()).remove();
});
I am going to assume you need to make a new tbody for every row - otherwise remove it.
Why re-create the whole table? I am assuming you don't need to, if you do the code needs some changes.
Why wait for domLoad? I have change it to onDomReady (fiddle settings)
A clickable element should be an anchor <a> with an href
I know this is just a demo but I am hoping you don't mix double and single quotes in your html and javascript and that you don't use IDs everywhere
How it works:
By using the second parameter of jQuery's on we have created an event delegate. This means that the event is placed on the table itself #add-new-table and it is listening for changes to any inputs inside the table. So it is one single event and it doesn't care if stuff inside is updated/removed etc. It is also more efficient.
And a small explanation of var rows = $('#add-new-table .filter-rows'); rows.first().add(rows.last()).remove();:
"Get all the filter rows and store that. Then select the first row and add the last row to that selection, finally remove them"

Related

Find the sum of a column in html table using Jquery or JS

I have a html table created using jQuery:
success: function(data, textStatus, errorThrown) {
var rows ="";
function formatItem(data) {
return '<td>'+data.name + '</td> <td> ' + data.price + ' </td><td>' + "<input></input>" +'</td>';
}
$.each(data, function (key, item) {
$('<tr>', { html: formatItem(item) }).appendTo($("#foodnames"));
});
}
This is what the interface looks like:
The table is working fine with all the data showing.
The problem is finding the sum of the third column. Where I can enter a number and display it using an id.
Is there anyway to do it?
What you want to do is to use jQuery to select the table, and all of the third td's for each row, then sum it. The basic pseudocode is:
Clear the output box.
ForEach TR
Select the third TD
Add that value to the output box.
End ForEach
To do that in jQuery, you just need to know how to select the right values. Assigning relevant class/id names is helpful.
I put together a basic example that you can run. It will tabulate the total of the third column dynamically, as you change the value. I hard coded the price column, but you could easily put some other values or input there.
I put it in an onChange event handler, but if you are loading the data from a server or something, you could do document onLoad or whenever your ajax is complete.
//trigger an event when the input receives a change
$("#exampleTableContainer table td input").off("change").on("change", function(ele) {
//clear the out put box
$("#totalOut").val("0");
//for the table container, select all tr's within the table's tbody.
//Excluding tbody will also select the thead.
$("#exampleTableContainer table tbody tr").each(function(index, rowElement) {
//tablulate the cost of the current row
var rowCost = parseInt($(rowElement).find(".cost").text()) * parseInt($(rowElement).find(".amount input").val());
//if the rowCost is a valid number, add it to whatever is in the output box
if (rowCost) $("#totalOut").val(parseInt($("#totalOut").val()) + rowCost)
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="exampleTableContainer">
<table>
<thead>
<tr>
<th class="item">Item</th>
<th class="cost">Cost</th>
<th class="amount">Amount</th>
</tr>
</thead>
<tbody>
<tr>
<td class="item">Item 1</td>
<td class="cost">123</td>
<td class="amount">
<input type="number">
</td>
</tr>
<tr>
<td class="item">Item 2</td>
<td class="cost">1</td>
<td class="amount">
<input type="number">
</td>
</tr>
<tr>
<td class="item">Item 3</td>
<td class="cost">2</td>
<td class="amount">
<input type="number">
</td>
</tr>
<tr>
<td class="item">Item 4</td>
<td class="cost">4</td>
<td class="amount">
<input type="number">
</td>
</tr>
</tbody>
</table>
<br>
<div>
Total:
<input id="totalOut" readonly value="0">
</div>
</div>
I'm not sure if you plan to use this in a production environment or not, so maybe this is overkill for what you're trying to accomplish, but I would recommend using an underlying data model bound to the table. Then you can get your sum from your data:
const data = [
{food: "Veggie burger", price: 200, qty:1},
// ...Add as many food items as you like
]
You would be able to use the data to build your table:
// Get a reference to the table and create a document fragment
const table = document.getElementById("table-body");
const body = document.createDocumentFragment();
// Fill the fragment with your data:
data.map((value, key) => {
// Row-building logic goes here
// this probably isn't what you actually do here:
const row = document.createElement("tr");
row.className = key;
for (let x in value) {
const dataCell = document.createElement("td");
dataCell.className = x;
dataCell.innerHTML = value[x];
row.appendChild(dataCell);
}
body.appendChild(row);
});
table.innerHTML = "";
table.appendChild(body);
Then you can calculate your sum based on the data, not the UI:
const subTotal = data
.map((value) => value.price * value.qty)
.reduce((a, b) => a + b);
document.getElementById("total").textContent = subTotal;
You would set an event listener on the table(parent node) and use event.target to find the row and column (.qty in this case) and update the corresponding field (qty) in the data object when the input is changed.
$("#my-table").on("input", (e) => {
// You would probably be better off using a custom attribute than a class since there can be multiple classes, but we'll use class to keep it simple:
const column = $(e.target).parent("td").attr("class");
const row = $(e.target).parent("td").parent('tr').attr("class");
data[row][column] = e.target.value;
console.log(data);
});
This pattern also makes it easy to send the updated data back to the REST API to update your database later.
https://jsfiddle.net/79et1gkc/
I know you said you're using jQuery, but ES6 is much nicer in my opinion.
Try this:
$(document).ready(function(){
var total = 0;
$("#submit").click(function(){
$(".user_input").each(function(){
var value = parseInt($(this).val());
total += value;
});
$("#output").text(total);
});
});
HTML
<input type="text" name="value1" class="user_input"/>
<input type="text" name="value2" class="user_input"/>
<input type="text" name="value3" class="user_input"/>
<button name="submit" id="submit" value="calculate">
Calculate
</button>
<div>
<span>Total:</span><div id="output">
</div>

Show the responce of ajax is not working

Hi I am trying to replace the table->tr->td with new td I have tried like this but it is not working.
<table id="job1">
<tr><td></td></tr>
<tr id="Jobstatus1">
<td>Accept</td>
<td>Reject</td>
<tr>
</table>
<table id="job2">
<tr><td></td></tr>
<tr id="Jobstatus2">
<td>Accept</td>
<td>Reject</td>
<tr>
</table>
I am showing a response like this:
$response['jobStatus'] =
'<td class="textcenter" colspan="2" style="color:green;" > Accepted The Above Job </td>';
This is what I am trying in ajax response:
if (response["success"] == true){
$("#Jobstatus"+jobId).remove(); //in here jobId will come as 1,2....
$("#Jobstatus"+jobId).append($response['jobStatus']);
The .remove() method will remove the element so append() can't find it, you should use .htmt('') or .empty() instead of remove.
Replace :
$("#Jobstatus"+jobId).remove();
By :
$("#Jobstatus"+jobId).html('');
//Or
$("#Jobstatus"+jobId).empty();
Hope this helps.
You can use the html() method to inject the response value straight into the target tr element, replacing whatever it contained:
$("#Jobstatus" + jobId).html($response['jobStatus']);

Access textContent of hidden table cell

I'm working with an html form that displays rows of data only for data elements that are found with a submitted value in the database. For example, the following table row will be toggled off ( style="display:none" ) if there is no value found in the database for 'Seizures_Type', and WILL be displayed if there is a value found in the database.
The javascript works to concatenate values from several similar fields on the form and store in a single field, id="medalert".
When the script runs, it fails if it tries to access a field that is in the display:none state.
What would be a good way to allow the script to run fully, even if it encounters these hidden elements?
Build
<tr style="display:none">
<td title="seizures type">Seizures Type</td>
<td></td>
<td id="par_med_seizures_type"></td>
<td><input type="checkbox" id="chk_med_seizures_type"></td>
</tr>
<tr style="display:none">
<td title="seizures type">Seizures Medication</td>
<td></td>
<td id="par_med_seizures_medication"></td>
<td><input type="checkbox" id="chk_med_seizures_medication"></td>
</tr>
function buildMedAlert(){
var retval = "";
if (document.getElementById('par_med_seizures_type').textContent.length>0) {
retval += "Type: " + document.getElementById('par_med_seizures_type').textContent;
}
if (document.getElementById('par_med_seizures_medication').textContent.length>0) {
retval += "Medication: " + document.getElementById('par_med_seizures_medication').textContent;
}
document.getElementById('medalert').value=retval;
}
You should make a condition to check if the row is visible, give it an ID (since I don't believe you want to work on every element in the code) and then, make sure to check if the element is visible, like this:
var element = document.getElementById('element');
if(element.style.display != 'none'){
}
The thing is that you cannot access the contents of a hidden element since it is hidden and so, the javascript doesn't recognize it. You have to make sure the element is not hidden.
If I add the missing field medalert, it does not fail in neither Chrome nor IE10
function buildMedAlert() {
var retval = "";
if (document.getElementById('par_med_seizures_type').textContent.length > 0) {
retval += "Type: " + document.getElementById('par_med_seizures_type').textContent;
}
if (document.getElementById('par_med_seizures_medication').textContent.length > 0) {
retval += "Medication: " + document.getElementById('par_med_seizures_medication').textContent;
}
document.getElementById('medalert').value = retval;
}
Build
<table>
<tr style="display:none">
<td title="seizures type">Seizures Type</td>
<td></td>
<td id="par_med_seizures_type">Some type</td>
<td>
<input type="checkbox" id="chk_med_seizures_type">
</td>
</tr>
<tr style="display:none">
<td title="seizures type">Seizures Medication</td>
<td></td>
<td id="par_med_seizures_medication">Some med</td>
<td>
<input type="checkbox" id="chk_med_seizures_medication">
</td>
</tr>
</table>
<input type="text" id="medalert">

how to add jquery toggle between smarty loop or foreach items

For the jquery Guru's out there, I am trying. I am trying to add a jquery toggle between smarty template { foreach item list } my code works great just that it works on the first list item, it does not toggle when I click on the 2nd, 3rd etc items in the list. any suggestions?
jquery code
<script>
$(function(){
$("#itm_add").each(function(){
$(this).click(function(e){
e.preventDefault();
$("#itm_add_box").parent("tr").empty();
href=$(this).attr("href");
$(this).closest("tr").next("tr").empty().append('<td colspan="6"><div
id="itm_add_box" data-href="'+href+'">
<input type="text" id="itm_serial" class="input" placeholder="Serial
Number..." />
<input type="text" id="itm_qty" class="input"
placeholder="Quantity..." />
<button class="green" id="itm_submit">Submit</button></div><td>');
$("#itm_add_box button").click(function(e){
e.preventDefault();
href2=$(this).parent("#itm_add_box").attr("data-href");
serial=$(this).parent().find("#itm_serial").val();
qty=$(this).parent().find("#itm_qty").val();
href2=href2+"&item_serial="+serial+"&item_quantity="+qty;
window.location=href2;
});
});
});
});
</script>
Smarty template:
<table>
<tr>
<td class="olohead" align="center" width="80">ID</td>
<td class="olohead" align="center">Type</td>
<td class="olohead" align="center">Name</td>
<td class="olohead" align="center">No</td>
<td class="olohead" align="center">Features</td>
</tr>
{foreach from=$customer item=customer}
<td class="olotd4" nowrap align="center">{$customer.ID}</td>
<td class="olotd4" nowrap align="center">{$customer.TYPE}</td>
<td class="olotd4" nowrap > {$customer.NAME} </td>
<td class="olotd4" nowrap > {$customer.NO} </td>
<td class="olotd4" nowrap align="center">
<a id="itm_add">Add</a>
</td>
</tr>
{/foreach}
</table>
Again: This works, just that the toggle only works on the first listed item. Any suggestions?
The suggestion to remove the id from the loop and make it into a class was already made in the comments. With that in mind, I tried to clean up your js a bit:
$(function() {
$(".itm_add").click(function(e) {
e.preventDefault();
$(this).parent("tr").empty();
$(this).closest("tr").next("tr").empty().append(getTemplate($(this).attr("href")));
$(this).find("button").click(function(e) {
e.preventDefault();
var href = $(this).parent("#itm_add_box").attr("data-href");
var serial = $(this).parent().find("#itm_serial").val();
var qty = $(this).parent().find("#itm_qty").val();
href += "&item_serial=" + serial + "&item_quantity=" + qty;
window.location = href;
});
});
});
function getTemplate(href) {
return '<td colspan="6">'
+ '<div id="itm_add_box" data-href="' + href + '" >'
+ '<input type="text" id="itm_serial" class="input" placeholder="Serial Number..." /> '
+ '<input type="text" id="itm_qty" class="input" placeholder="Quantity..." /> '
+ '<button class="green" id="itm_submit">Submit</button>'+
+'</div>'
+ '<td>';
}
Note that this code is not tested, so there could be bugs in there...
What I changed:
Removed the .eachas it is not required. jQuery will automatically
add the event handler on all elements that the selector applies to.
Used $(this) inside the handler, to make the code only apply to the item that has triggered the event, in stead of all the matched items.
Moved the html to a separate function, just to keep things a bit more readable.
Made all the variables function scope in stead of global, by adding the varkeyword in front of their declaration.
Let me know if there are any bugs that I missed, or if this is anything that needs further explanation.

Get values of one column and pass it to another

I have a table and if I click a button i want to take the value from charge_outstanding_NUM and set charge_receipt_NUM to it. I need a reusable script because I will not know how many rows will get posted through.
<table>
<thead>
<tr>
<th>ID</th>
<th>Value</th>
<th>Outstanding</th>
<th>Reciept</th>
</tr>
</thead>
<tbody>
<tr>
<td>001</td>
<td>150.00</td>
<td id="charge_outstanding_1">150.00</td>
<td><input type="text" name="charge_receipt_1" id="charge_receipt_1" value=""></td>
</tr>
<tr>
<td>002</td>
<td>10.00</td>
<td id="charge_outstanding_2">10.00</td>
<td><input type="text" name="charge_receipt_2" id="charge_receipt_2" value=""></td>
</tr>
<tr>
<td>003</td>
<td>250.00</td>
<td id="charge_outstanding_3">250.00</td>
<td><input type="text" name="charge_receipt_3" id="charge_receipt_3" value=""></td>
</tr>
</tbody>
</table>
My jquery isn't working and I am not sure why. I click the button then loop through each col that starts with 'charge_outstanding_' then take the value and assign it to the closest input which is within the same row.
$('#pay_in_full').click(function(){
$("[id^=charge_outstanding_]").each(function(){
charge = $(this).val();
$(this).closest('input').val(charge);
});
});
working JSfiddle: http://jsfiddle.net/F5NvW/2/
Issue with your code: charge = $(this).val(); you are finding td which has no value, you need .html() for this
$(document).on("click", "#pay_in_full", function() {
$("[id^=charge_outstanding_]").each(function(){
var charge = $(this).html();
$(this).next().find('input').val(charge);
});
});
Suggestion: use class name with each <td> like this
Jsfiddle: http://jsfiddle.net/F5NvW/
Note: less error prone..
$(document).on("click", "#pay_in_full", function() {
$(".outstanding").each(function(){
var charge = $(this).html();
$(this).next().find('.paidAmount').val(charge);
});
});
.Closest will search for the ancestor elements, In your case the target input is the children of the next sibling of the selected element. So you have to use .find() or .children() to select that.
Try,
$('#pay_in_full').click(function(){
$("[id^='charge_outstanding_']").each(function(){
charge = parseInt($(this).text());
$(this).next().find('input').val(charge);
});
});
Additionally, You are selecting a td element, so you have to use .text() to get its text not .val()
DEMO

Categories

Resources