I have the html like below:
<table class="table" id="subscriptions">
<tbody id="subscriptions-tbody">
<tr>
<td>Item 1</td>
<td>delete</td>
</tr>
<tr>
<td>Item 2</td>
<td>delete</td>
</tr>
<tr>
<td>Item 3</td>
<td>delete</td>
</tr>
</tbody>
</table>
Items can be added dynamically there.
Now, I should create the function, which will help me to delete the element from the list, if user clicks delete.
Looks like I should:
assign some unique id for each item in the list (I have such ids) - where should I keep them? part as href?;
once user clicks on the link, I should prevent default action and pass control to my function (it will hide the element from the list and will sent POST request to the server) with item id as parameter.
How to do it?
This is the perfect case for event delegation. Hook the event on the table or tbody, but ask jQuery to trigger it only if it happens on your delete link, like this:
$("#subscriptions-tbody").delegate("a", "click", function(event) {
var row = $(this).closest('tr');
// ...delete the row
return false; // Don't try to follow the link
});
Live Example | Source
Because the event is hooked on the table or tbody, adding and removing rows doesn't matter, because the event is handled at the table or tbody level.
In the above, I'm using delegate because I like how explicit is is. With jQuery 1.7 or higher, you can use the way-too-overloaded-on function instead:
$("#subscriptions-tbody").on("click", "a", function(event) {
var row = $(this).closest('tr');
// ...delete the row
return false; // Don't try to follow the link
});
Live Example | Source
Note that the order of arguments is slightly different.
You should keep the information required for the server side (like the id) on the tr with data- attributes, and use .on() to handle the events from the table..
html
<table class="table" id="subscriptions">
<tbody id="subscriptions-tbody">
<tr data-id="3">
<td>Item 1</td>
<td>delete</td>
</tr>
<tr data-id="5">
<td>Item 2</td>
<td>delete</td>
</tr>
<tr data-id="6">
<td>Item 3</td>
<td>delete</td>
</tr>
</tbody>
</table>
script
$("#subscriptions").on("click", "a.delete", function(e) {
e.preventDefault();
var row = $(this).closest('tr'),
relatedId = row.data('id');
$.post(...); // use relatedId here
row.fadeOut(500, function(){
row.remove();
})
});
Try this:
<table class="table" id="subscriptions">
<tbody id="subscriptions-tbody">
<tr data-id="1">
<td>Item 1</td>
<td>delete</td>
</tr>
<tr data-id="2">
<td>Item 2</td>
<td>delete</td>
</tr>
<tr data-id="3">
<td>Item 3</td>
<td>delete</td>
</tr>
</tbody>
</table>
You will name a class for your delete anchors, let's say class="delete", and you will place data-id attribute to the table row in order to unique identify each item and know what id to send to the server.
Now your js might look like this:
$("#subscriptions-tbody").on('click', 'a.delete', function(e){
var tr = $(e.currentTarget).closest('tr');
//get the id
var id = tr.attr("data-id");
//make ajax request
$.ajax({
url: 'script.php',
data: id,
success: function(data) {
//hide the item or remove
tr.remove(); // tr.hide();
// ajax callback
}
});
});
You can store the ID as a data- attribute on either the control or the row. Delegate the click handler to the table itleslf to account for dynamically added elements that don't exist when code is run using on() method.
HTML:
<!-- class added to element -->
delete
JS
$('#subscriptions').on('click', '.delete-btn',function(evt){
evt.preventDefault();
var id=$(this).data('id'), $row=$(this).closest('tr');
/* send data to server and remove row on success*/
$.post('serverUrl.php', { rowID: id, action :'delete'}, function(){
$row.remove();
})
})
Related
Is there a way to check for the last double clicked element with jQuery. I've made
a table and I want to know how to identify the most recent double clicked <td></td> in my code. I tired something like this:
var clickedTD = $("td").dblclick;
But It didn't work.
element.dblclick() should work provided the DOM is loaded... See the example below...
$(document).ready(function() {
//set up dblclick event on the table data elements
$("td").dblclick(function(){
//$(this) use key word this for the element clicked
$("#display").text(`You double clicked: ${$(this).text()}`)
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr>
<td>Click 1</td>
<td>Click 2</td>
<td>Click 3</td>
<td>Click 4</td>
</tr>
</table>
<div id="display"></div>
I don't really think jQuery is necessary for this:
<td>onclick="checkClick(this)"></td>
function checkClick(clickedElement) {
var clickCount= clickCount + 1;
if(clickCount === 2){
console.log(clickedElement);//Last clickedclicked
}
}
I have many tables each one with an ID, (table1,2,3,...), and in each one I have many TD's <td><a href
example :
<table id="myTable1" class="someclass">
<tbody>
<tr>
<td>blablabla</td>
<td>random text</td>
<td>randomtext</td>
</tr>
</tbody>
</table>
</td>
<table id="myTable2" class="someclasse">
<tbody>
<tr>
<td>blablabla</td>
<td>random text</td>
<td>randomtext</td>
</tr>
</tbody>
</table>
</td>
(don't look at the HTML code it's not important for now )
My goal is to open all hrefs within the table "table X" then open them in new tab. I do that with
var els = document.getElementById("myTable1").querySelectorAll("a[href^='https://domaine.']");
for (var i = 0, l = els.length; i < l; i++) {
var el = els[i];
alert(el)
window.open (el,"_blank");
}
It works like a charm. Now I want to add a checkbox to each table, and if checked to open the href on "the" table I checked (I did some innerHTML to "insert" checkbox). Now my question, how can I get the table ID when I'll check the checkbox?
For example I check the table that have "table6" and then every link in that table gets opened.
table id=1 (checkbox)
table id=2 (checkbox)
etc
if i check the checkbox it will get the table with id 2
You can use closest to get the closest table, then you can get the id from that.
// List of checkboxes
let inputs = Array.from(document.querySelectorAll('input[type=checkbox]'))
// Add a click event to each
inputs.forEach(input => {
input.addEventListener('click', e => {
let target = e.currentTarget
// If the checkbox isn't checked end the event
if (!target.checked) return
// Get the table and id
let table = target.closest('table')
let id = table.id
console.log(id)
})
})
<table id="abc">
<tr>
<td><input type="checkbox"></td>
</tr>
</table>
<table id="def">
<tr>
<td><input type="checkbox"></td>
</tr>
</table>
<table id="ghi">
<tr>
<td><input type="checkbox"></td>
</tr>
</table>
<table id="jkl">
<tr>
<td><input type="checkbox"></td>
</tr>
</table>
You say that you are adding the checkbox dynamically, so you won't want to do a querySelectorAll like I did above. You will want to add it when it is created like this:
// List of tables
let tables = Array.from(document.querySelectorAll('table'))
// insert the checkbox dynamically
tables.forEach(table => {
table.innerHTML = '<tr><td><input type="checkbox"></td></tr>'
// Get the checkbox
let checkbox = table.querySelector('input[type=checkbox]')
// Add an eventlistener to the checkbox
checkbox.addEventListener('click', click)
})
function click(e) {
let target = e.currentTarget
// If the checkbox isn't checked end the event
if (!target.checked) return
// Get the table and id
let table = target.closest('table')
let id = table.id
console.log(id)
}
<table id="abc">
</table>
<table id="def">
</table>
<table id="ghi">
</table>
<table id="jkl">
</table>
…I want to add a checkbox to each table, and if [it's] checked…open the href [in] "the" table I checked…how can I get the table ID when I'll check the checkbox?
Given that you want to find the id of the <table> within which the check-box <input> is contained in order to select the <table> via its id property you don't need the id; you simply need to find the correct <table>.
To that end I'd suggest placing an event-listener on each of those <table> elements, and opening the relevant links found within. For example (bearing in mind that there are restrictions on opening new windows/tabs on Stack Overflow, I'll simply style the relevant <a> elements rather than opening them):
function highlight(e) {
// here we find the Static NodeList of <a> elements
// contained within the <table> element (the 'this'
// passed from EventTarget.addEventListener()) and
// convert that Array-like collection to an Array
// with Array.from():
Array.from(this.querySelectorAll('a'))
// iterating over the Array of <a> elements using
// Array.prototype.forEach() along with an Arrow
// function:
.forEach(
// here we toggle the 'ifCheckboxChecked' class-name
// via the Element.classList API, adding the class-name
// if the Event.target (the changed check-box, derived
// from the event Object passed to the function from the
// EventTarget.addEventListener function) is checked:
link => link.classList.toggle('ifCheckboxChecked', e.target.checked)
);
}
// converting the Array-like Static NodeList returned
// from document.querySelectorAll() into an Array:
Array.from(document.querySelectorAll('table'))
// iterating over the Array of <table> elements:
.forEach(
// using an Arrow function to pass a reference to the
// current <table> element (from the Array of <table>
// elements to the anonymous function, in which we
// add an event-listener for the 'change' event and
// bind the named highlight() function as the event-
// handler for that event:
table => table.addEventListener('change', highlight)
);
function highlight(e) {
Array.from(this.querySelectorAll('a'))
.forEach(
link => link.classList.toggle('ifCheckboxChecked', e.target.checked)
);
}
Array.from(document.querySelectorAll('table')).forEach(
table => table.addEventListener('change', highlight)
);
body {
counter-reset: tableCount;
}
table {
width: 80%;
margin: 0 auto 1em auto;
border: 1px solid limegreen;
}
table::before {
counter-increment: tableCount;
content: 'table' counter(tableCount);
}
a.ifCheckboxChecked {
background-color: #f90;
}
<table>
<tbody>
<tr>
<td><input type="checkbox"></td>
<td>cell 1</td>
<td>cell 2</td>
<td>cell 3</td>
</tr>
</tbody>
</table>
<table>
<tbody>
<tr>
<td><input type="checkbox"></td>
<td>cell 1</td>
<td>cell 2</td>
<td>cell 3</td>
</tr>
</tbody>
</table>
<table>
<tbody>
<tr>
<td><input type="checkbox"></td>
<td>cell 1</td>
<td>cell 2</td>
<td>cell 3</td>
</tr>
</tbody>
</table>
<table>
<tbody>
<tr>
<td><input type="checkbox"></td>
<td>cell 1</td>
<td>cell 2</td>
<td>cell 3</td>
</tr>
</tbody>
</table>
JS Fiddle demo.
References:
CSS:
::before pseudo-element
Using CSS Counters.
JavaScript:
Array.from().
Array.prototype.forEach().
Arrow Functions.
Element.querySelectorAll().
Event.
EventTarget.addEventListener().
I have a table with 4 columns . 4th column is a button (not shown in below code). When I click on the button in a row, I want to get row elements.
I have done it using closest selector. Is there any way to find table row element "Without using closest". This is the requirement for some reason.
Please assume there is a button at end of each row
<table id="food">
<thead>
<tr>
<th>Number</th>
<th>Name</th>
<th>Type</th>
</tr>
</thead>
<tbody>
<tr class='details'>
<td>1</td>
<td>Apple</td>
<td>Fruit</td>
</tr>
<tr class='details'>
<td>2</td>
<td>Mango</td>
<td>Fruit</td>
</tr>
<tr class='details'>
<td>3</td>
<td>Grape</td>
<td>Fruit</td>
</tr>
</tbody>
</table>
Here is the existing code, I need to replace closest. It will be awesome if I can use class names like $(this).somethin('.details');
$('#button1').click(function(){
var row = $(this).closest('tr');
//Do some stuff
})
Thanks
Use parents() and pass a class selector like
$('#button1').click(function(){
var row = $(this).parents('.details');
//Do some stuff
})
Note, you could also use closest in this case and pass the class selector
var row = $(this).closest('.details');
this is a simple demonstration of what i have, this is a table with a single row in it,
<table id="test_table">
<tr>
<td>name</td>
<td>age</td>
<td>action</td>
</tr>
<tr>
<td>test name</td>
<td>20</td>
<td class="delete">delete</td>
</tr>
</table>
and if i click on the delete td this row would be hidden
$('.delete').click(function(){
$(this).parent().parent().hide();
});
and i have a simple form of name and age, when i click on the add button it appends it to the table
$('#test_input').click(function(){
var name = $('#name').val();
var age = $('#age').val();
$('#text_table').append('<tr><td>'+name+'</td><td>'+age+'</td><td class="delete">delete</td></tr>');
});
the problem is i if i click on the new appended row it would hide like its not even there, what ever i try to do using the appended row, it wouldn't take it, is there something wrong that im doing ?
$('#test_table') should be $('#test-table').
And you should bind the on-click on the added row.
Another solution is to create a delegated event.
$('body').on('click', '.delete', function() {
$(this).parent().parent().hide();
});
I have a table like this:
<table>
<tr>
<td>foo</td>
<td><button>delete</delete></td>
</tr>
<tr>
<td>foo</td>
<td><button>delete</delete></td>
</tr>
</table>
I want to use JQuery to install a click handler on the delete buttons such that it deletes the current row when clicked
Give a class of, for example, "delete" to the delete buttons, then use this:
$("button.delete").click(function() {
$(this).closest("tr").remove();
});
Alternatively, if you can't add the class, you can use the :contains selector:
$("button:contains('delete')").click(function() {
$(this).closest("tr").remove();
});
Update (now that the code in the question has completely changed)
Now that you have changed the code in the question to contain only one button instead of two, you don't need to bother adding the class, or using the :contains selector, you can just use the plain old button selector:
$("button").click(function() {
$(this).closest("tr").remove();
});
Try this. As a side not you should not have same id to any dom element on the page.
$("button").click(function() {
$(this).closest("tr").remove();
});
In your markup the tags are not closed properly. E.g the button tag is not closed properly so the selector will not work. Give a unique id or a class name to select the required buttons.
Something like this
<tr>
<td>foo</td>
<td>Some content</td>
<td><input type="button" class="delete" value="Delete" /></td>
</tr>
Using delegate to attach event handler only to table for better performance. This way the click event will be attached only to the table element no matter how many rows it has.
$("table").delegate("input.delete", "click", function() {
$(this).closest("tr").remove();
});
You can try soemthing like this:
<table>
<tr>
<td>row 1, cell 1</td>
<td><img class="delete" src="del.gif" /></td>
</tr>
<tr>
<td>row 2, cell 1</td>
<td><img class="delete" src="del.gif" /></td>
</tr>
</table>
And your jQuery:
$('table td img.delete').click(function(){
$(this).parent().parent().remove();
});
First off, there's a syntax error in your HTML, and you should a class identifier for easier access to those buttons:
<table>
<tr>
<td>foo</td>
<td><button class="delete">delete</button></td>
</tr>
<tr>
<td>foo</td>
<td><button class="delete">delete</button></td>
</tr>
</table>
Next, here's the jQuery code you need:
$(function() {
$('button.delete').click(function(event) {
event.preventDefault();
$(this).closest('tr').remove();
});
});