How do I pass (or reference) "$(this)" from html event? - javascript

Let's say I have a button in a table which adds a new row to a table:
<td><a onclick="addRow()"></a></td></tr>...
and I want to reference $(this) or $(this).closest('tr') from the function at the bottom of the page.
function addRow(){
$(this) // contains all information from the row which pressed the button
}
Simply passing a javascript variable from the HTML will result in null (as expected). Is there a way to reference the row that pressed the button?

The RECOMMENDED way of doing this is unobtrusive and delegated - give the link a class:
var $tb = $("#someTable");
$tb.on("click", ".addRow", function(e) { // delegation to allow new rows' links to work
e.preventDefault(); // stop any click side effects
var $row = $(this).closest("tr");
$tb.append($row.clone())
});
a { text-decoration:none }
td,th { padding:3px }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<thead>
<tr>
<th>A</th>
<th>B</th>
<th>Add</th>
</tr>
</thead>
<tbody id="someTable">
<tr>
<td>1st</td>
<td>2nd</td>
<td><a class="addRow" href="#">+</a></td>
</tr>
<tr>
<td>3rd</td>
<td>4th</td>
<td><a class="addRow" href="#">+</a></td>
</tr>
</tbody>
</table>

Use this
<td><a onclick="addRow(this)"></a></td></tr>
and then:
function addRow(e){
console.log($(e)) // contains all information from the row which pressed the button
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<a onclick="addRow(this)">Clickme</a>

You can reference the row that you clicked using an event.
<td>Add</td>
and in javascript you can check the event
<script>
function addRow(event) {
console.log(event);
}
</script>

Related

Checking for last double clicked element with jQuery

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
}
}

Get ID of Table that contains a checkbox

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().

when i append something using the append function i dont have control over it using jquery

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();
});

why the button inside a table cell which is clicked is undefined

I can't explain why ehn i click a button inside a table cell and try to get rowID - i see that its undefined
Here is my code
#model Onion.Web.ViewModels.CategoryViewModel
<script>
function btnEdit_Click()
{
var par = this.parentNode.parentNode;
alert(par.id);
}
</script>
<table>
<tr>
<td>ID</td>
<td>Title</td>
<td>Button</td>
</tr>
#foreach (var item in Model.lstCategoryLanguages)
{
<tr id='#item.CategoryLanguagesID'>
<td>#item.Title</td>
<td>#item.ShortDescription</td>
<td><input type="button" value="Edit" onclick='btnEdit_Click()' /></td>
</tr>
}
</table>
You need to pass the function the element you want to refer to, and then in the function use that.
This works for me:
<script>
function btnEdit_Click(elem)
{
var par = elem.parentNode.parentNode;
alert(par.id);
}
</script>
<table>
<tr>
<td>ID</td>
<td>Title</td>
<td>Button</td>
</tr>
#foreach (var item in Model.lstCategoryLanguages)
{
<tr id='#item.CategoryLanguagesID'>
<td>#item.Title</td>
<td>#item.ShortDescription</td>
<td><input type="button" value="Edit" onclick='btnEdit_Click(this)' /></td>
</tr>
}
</table>
I think this returns the wrong context there.
Try passing this in the onclick event and use the parameter instead in your function:
onclick='btnEdit_Click(this)'
I think it would be even better to bind #item.CategoryLanguagesID a second time and pass that the function to get rid of the static parentNode.parentNode reference. What if your structure changes over time? You'd always have to modify the function too.

delete table row

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();
});
});

Categories