jquery click event for buttons having same id - javascript

I am having a table structure like this
<table>
<c forEach var="item" items="${manyItems}">
<tr>
<td id="item1"> ${item.data1} </td>
<td id="item2"> ${item.data2} </td>
<td> <button id="deleteButton"/> </td>
</tr>
</c:forEach>
</table>
Now I want to add a click event to the deleteButton
In my jquery is like this:
$(function() {
$('#deleteButton').click(function() {
var ele = $(this).parent();
/* fetch the other <td> siblings of the #deleteButton */
/* delete code goes here having an ajax query*/
});
});
This code is only deleting the 1st row of the table, but does not work on any other row.
I believe this is because we need to have distinct id's?
Kindly guide me to a good solution.

You are creating duplicate IDs, Identifiers in HTML must be unique and this is the expected behavior.
Use class, Here In example below I have converted deleteButton in to a CSS class so that we can use Class Selector (".class")
<button class="deleteButton"/>
Script
$('.deleteButton').click(function() {
var ele = $(this).parent();
});

Issue is the same ids for multiple elements in a single page. When this happens browser only looks for first instance of it and never goes ahead to look for another one, This is the reason one should understand that IDs should be unique per element.
change to class name instead:
<table>
<c forEach var="item" items="${manyItems}">
<tr>
<td class="item1"> ${item.data1} </td>
<td class="item2"> ${item.data2} </td>
<td> <button class="deleteButton"/> </td>
</tr>
</c:forEach>
</table>
and jquery:
$(function() {
$('.deleteButton').click(function() {
var ele = $(this).parent();
/* fetch the other <td> siblings of the .deleteButton */
/* delete code goes here having an ajax query*/
});
});

First think that, id is known unique, if u need to have click event for two button, u can use class for selecting the button, so try to follow the standards, id is unique selector and class is multiple selector.

Related

Show/Hide more than one <table> with a checkbox

I want to show and hide several tables on one page with one button. Unfortunately my script can only show and hide one table at a time.
I have a page with a lot of queries. There are also text fields in a table. For a better overview, the tables with the text fields should only be displayed when the checkbox is ticked. The checkbox should not be clicked at the beginning.
function Displayer(n)
{
var check = document.getElementById('Section'+n);
if (check.style.display == 'none')
{
check.style.display='inline';
}
else
{
check.style.display='none';
}
}
<p><input type="checkbox" class="btnstylega" onClick="Displayer(99)" />Show Tables</p>
<table id="Section99" style="display:none;"> <td>
AAAAAAAAAAAAAA
</td></table>
<table id="Section99" style="display:none;"> <td>
BBBBBBBBBBBBBBB
</td></table><br>
I want to show and hide many tables without adjusting the tables by clicking on the checkbox.
An ID must be unique in a document. The tool to mark multiple elements as part of a group is a class.
Replace your id attributes with class attributes.
Then replace getElementById with getElementsByClassName (or querySelectorAll).
These methods return lists of nodes and not single elements, so loop over the result like an array and access the style property on each one in turn.
The attribute id must be unique in a document, you can use class instead. You can use querySelectorAll() to target all the elements having the class, then loop through them to set the style. You can toggle the class using classList.toggle() like the following way:
function Displayer()
{
var check = document.querySelectorAll('.Section99');
check.forEach(function(table){
table.classList.toggle('show');
});
}
.Section99{
display: none;
}
.show{
display: block;
}
<p><input type="checkbox" class="btnstylega" onClick="Displayer()" />Show Tables</p>
<table class="Section99" class="hide"> <td>
AAAAAAAAAAAAAA
</td></table>
<table class="Section99" class="hide"> <td>
BBBBBBBBBBBBBBB
</td></table><br>
Improvement: It will add the event handler and trigger the change on load where needed
Note the data-attribute on the checkbox
var chg = new Event('change');
document.querySelectorAll(".btnstylega").forEach(function(but) {
but.addEventListener("change", function() {
var checked = this.checked,
section = this.getAttribute("data-tables");
document.querySelectorAll('.Section' + section).forEach(function(sect) {
sect.classList.toggle("hide",!checked);
});
})
but.dispatchEvent(chg);
});
.hide {
display: none;
}
<p><input type="checkbox" class="btnstylega" data-tables="88" checked />Show Tables 88 </p>
<p><input type="checkbox" class="btnstylega" data-tables="99" />Show Tables 99</p>
<table class="Section88">
<tr>
<td>
AAAAAAAAAAAAAA
</td>
</tr>
</table>
<table class="Section88">
<tr>
<td>
BBBBBBBBBBBBBBB
</td>
</tr>
</table><hr>
<table class="Section99">
<tr>
<td>
CCCCCCCCCCCCCCCC
</td>
</tr>
</table>
<table class="Section99">
<tr>
<td>
DDDDDDDDDDDDDDDDDDDD
</td>
</tr>
</table>

Select elements in each child tables one by one

I have the following html which is basically a parent table with some child tables inside it,
<table id="roottable" class="tablemain" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td></td>
<td>
<table class="intable" align="center" border="0">
<tbody>
<tr>
<td class="chn" colspan="2" align="center">
<div>
<div class="mparent">
<div class="checkbox">
<input type="checkbox" id="ch243" name="ch243" value="243">
<label for="ch243"></label>
</div>
<div class="chtext">Category</div>
</div>
</div>
</td>
</tr>
<tr>
<td>Param two</td>
<td>
<div class="checkbox">
<input type="checkbox" id="ch244" name="ch244" value="244">
<label for="ch244"></label>
</div>
</td>
</tr>
</tbody>
</table>
......
......
<table class="intable" align="center" border="0">
......
......
What I need to do is access all checkboxes of the nested table, for each table. That is get the checkboxes inside the first nested table, perform some operations with it, move to the next nested table do the same with the checkboxes inside it.
I can access individual tables like below with their id,
$('#tableid').find('input[type="checkbox"]').each(function () {
});
This works, but the tables are auto generated from db and the id is not known beforehand, also, the number of tables may vary, so I have no option other than selecting the parent table and then look for every child tables inside it one by one ... I have tried this ...
$('table').each(function(){
$(this).find('input[type="checkbox"]').each(function () {
// DO STUFFS WITH CHECKBOXES
});
But it doesn't work... How do I go about this? Thanks.
$('table tr td').each(function(){ // this line is for main outer table
$(this).children('table').each(function () { //this will iterate all the child table
$(this).find('input:checkbox').each(function(){ //this will find checkbox inside each table
//Your Stuff
});
});
});
NOTE :- I m not using id selector here because questioner mentioned that he doesn't know id's beforehand.
Working Demo
Working Demo
Your final code block looks acceptable, except that you haven't prevented the table selector from also selecting the outer table. As written, this would cause each set of checkboxes to be considered twice - once as part of its own table and again (actually first) as descendants of the outer table.
Try a more specific selector:
$('#roottable .intable').each(...)
I would do something like this:
$('#roottable').find('.intable').each(function(index, elt) {
// operate now on each "child table"
var $childTable = $(elt);
$childTable.find('input[type="checkbox"]').each(function(i, cb){
// Do your stuff with the checkoxes of the current ".intable" table
});
});
Just use:
var tableInputs = {};
$('#roottable input[type="checkbox"]').each(function () {
var id = $(this).closest('table').attr('id');
var name = $(this).attr('name');
tableInputs[id] = {};
tableInputs[id][name] = $(this).val();
});
This will select all checkboxes that are a child of a table.
EDIT if you need to group just find the id of the closest parent table and use that as an index for an object. You end up with one large object with all the id's as properties, while using only one each loop.

Adding event handlers to each table row that will affect only that table row?

This isn't actually something I'm currently attempting to do; it just occurred to me while working with another table that I have no idea how I'd go about doing it, and the entire time on the train ride home I was puzzling over different solutions, none of which I could imagine working.
Imagine this situation: there is a table of 50 rows. On each row is a button. When clicked, this button should do something to the row it's on -- say, make all its text strikethrough, or make an AJAX call with the first cell's value, or something.
How would you go about binding those event handlers?
My initial thought was something like
buttons = document.getElementsByTagName("input");
rows = document.getElementsByTagName("tr");
for (i=0;i<buttons.length;i++) {
buttons[i].addEventListener('click',function() {
makeAjaxCall(rows[i]);
});
};
That is,
For each button in the document,
Add an event handler to that button,
Which will makeAjaxCall with the data of the row whose number corresponds to the button.
The problem, of course, being that makeAjaxCall will check the value of i when it's invoked, by which time, i is equal to buttons.length, and so the function will only ever work on the final row of the table.
So I suppose you'd need to find some way to actually hard-code the current value of i within the function handler... and that's something I don't even think is possible. Is it? How would you actually do something like this?
You can refer to the button object you are adding the event listener to using 'this'
Given the table in this format
<table>
<tr>
<td> <input type='button'> </td>
<td> 1st <td>
</tr>
<tr>
<td> <input type='button'> </td>
<td> 2nd <td>
</tr>
<tr>
<td> <input type='button'> </td>
<td> 3rd <td>
</tr>
</table>
The following code will allow you to access the data in the next cell, shown using console.log() rather than any ajax calls of course.
buttons = document.getElementsByTagName("input");
for (i=0;i<buttons.length;i++) {
buttons[i].addEventListener('click',function() {
makeAjaxCall(this);
});
};
function makeAjaxCall(btn) {
var sib=btn.parentNode.nextSibling;
while (sib.nodeName !='TD') {
sib=sib.nextSibling;
}
console.log(sib.innerHTML);
}
This can be extended to find any data in the row.
This section
while (sib.nodeName !='TD') {
sib=sib.nextSibling;
}
skips any extraneous characters (white space etc) between cells.
Fiddle Here
Interesting problem. I would go about doing it the way #kennebec suggests in the comment above.
Here is the fiddle: http://jsfiddle.net/u988D/
First, a slight change in markup to add data attributes
HTML
<table>
<tr>
<td data-to-json="id">1</td>
<td data-to-json="text">Lorem ipsum dolor.</td>
<td><button type="button">Click Me</button></td>
</tr>
<tr>
<td data-to-json="id">2</td>
<td data-to-json="text">Lorem ipsum dolor.</td>
<td><button type="button">Click Me</button></td>
</tr>
<tr>
<td data-to-json="id">3</td>
<td data-to-json="text">Lorem ipsum dolor.</td>
<td><button type="button">Click Me</button></td>
</tr>
</table>
Then the javascript. Probably can be optimized a bit more.
JS
var table = document.querySelector("table")
table.addEventListener("click", function(e) {
var element = e.target,
parent
//If the element is a button
if ( element && element.nodeName == "BUTTON" ) {
parent = element.parentNode
//Find the closest parent that is a TR
while ( parent.nodeName !== "TR" ) {
parent = parent.parentNode
}
//Convert Row to JSON
var json = {},
child
for ( var i = 0, _len = parent.children.length; i < _len; i++ ) {
child = parent.children[i]
if ( child.hasAttribute("data-to-json") ) json[child.getAttribute("data-to-json")] = child.innerText
}
// Do your AJAX stuff here
console.log(json)
}
})

How to disable tbody

I have a tbody inside which there are href/input type text/ etc
I have a code to get all elements of tbody but how to disable it.
My tbody
<tbody id="FamilyHistory_3">
<tr>
<td class="tablecell">
<a id="FamilyHistory_3" name="316098" value="316098" onclick="javascript:save('FamilyHistory_3','test');" href="#">
<img style="border-style: none" src="../images/v10/arrow_doc.png">
</a> test
</td>
</tr>
<tr>
<td>
<table>
<tbody>
<tr>
<td></td>
<td class="tablecell">
<input type="checkbox" value="Yes" name="10627_316098">Yes
<input type="checkbox" checked="" value="No" name="10627_316098">No
</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td height="2px"></td>
</tr>
</tbody>
Below is my code to get the content of tbody
function save(inputID,category){
var content= document.querySelectorAll('#tbodyID');
for(var i=0; i<content.length; i++){
// how to disable all the elements inside it
}
}
JSFiddle
document.querySelector('#tbodyID input').disabled = true;
You don't need jQuery for this.
For more than one:
JSFiddle
var l = document.querySelectorAll('#tbodyID input');
for (i = 0;i<l.length;i++)
{
l[i].disabled = true;
}
There's no need to loop, jquery can deal with groups of elements just using selectors.
Use the Jquery selectors and the prop function to add disabled="disabled" to each one.
You can also select multiple items using a comma separated list
$('#tbodyID input, #tbodyID select, ....').prop('disabled', true);
disabling an a tag will not prevent it from being clicked though. May be better to hide() these.
$('#tbodyID a').hide();
You might need to specify the types of all elements you want to disable. If you have jQuery, you can do that with something like this:
$('#tbodyID').find('a, input').prop('disabled', true);
Explanation
$('#tbodyID') : Select the element with id tbodyID
find('a, input') : Find all the a and input elements inside it
prop('disabled', true) : Set the disabled property of each element returned by the previous command
Based on your answer finally I accomplished my task using below code. I know you people have already answer but then also I am posting my answer with few addition.
Disable input
$('[id='+inputID+']').find('input').attr('disabled', true);
id of tbody
Disable click but clickable hand will be there but no request will be submitted to server
$('[id='+inputID+']').attr('onclick','').unbind('click');
id of anchor tag
Thanks,Pise

Loop through all checkboxes that are inside a div tag

I need to loop through all checkboxes that are inside a div tag with id #abc123
How can I do this?
$("#abc123").foreach( ???? )
Update
my html row looks like:
<tr>
<td><input .../> </td>
<td>234</td>
</tr>
I need to add the value of the <td> into the ID of the checkbox.
Would I just get the parent, then ancestor it somehow?
$("#abc123 input[type=checkbox]").each(function()
{
});
UPDATE:
Ok, Let'd see if I got this straight. Given:
<tr>
<td><input .../> </td>
<td>234</td>
</tr>
You want the result to be (effectively)
<tr>
<td><input id="abc234" .../> </td>
<td>234</td>
</tr>
$("td input[type=checkbox]").each(function()
{
var id = $(this).next("td").text();
$(this).attr("id", "abc"+ id);
});
$("#abc123 input[type=checkbox]").each(function() {
$(this).dosomething();
});
Use a onkeydown event... I recommend the tab key which is keycode "9"
$(document).keydown(function(e){
if(event.keyCode == '9'){
...
}
Inside the if statement you'll need a nested if statement that checks which element is in focus and then assigns focus to the next element like this :
document.div.id.focus();
You didn't label where #abc123 is in your code. Also, do the <td> tags have any identification? The following may work.
$("#abc123 input:checkbox").each(function(i) {
id = $(this).closest('td').next('td').text();
$(this).attr('id', id);
});
I am not sure how deep your <div id="abc123"> is in the <td> so I used the closest() method to get to the cell wrapper. If it is only 1 deep, i.e. there is no <div> as it appears in your code, then you can just use parent(). Good luck.

Categories

Resources