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().
Related
I have a table with ajax call to create rows within the tbody element. I have the table created on the html page.
<table id='mytable'>
<thead>
<tr>
<th>First Col</th>
<th>Second Col</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
My javascript code to attach the event to second cell of each row in tbody
$('#mytable tbody').on( 'click', 'tr td:eq(2)', function() {
console.log($(this).html())
});
This code only works for the second cell of the first row of the tbody. Clicking the second cell of all other rows did not trigger the event. I have to work around this by check the cell index
if (this.cellIndex == 2) console.log($(this).html())
I still want to know how to make the correct selection.
To select the specific td of each row use nth-child() instead of eq():
$('#mytable tbody').on( 'click', 'tr td:nth-child(3)', function() {
console.log($(this).html())
});
You can just have an event listener for the entire table and then test what was clicked. Adding the event listener to the table you don't need to assign it again if the content of the table changes.
Adding a class name can both be useful for the usability (styling the cursor) and easier to find elements using JS.
document.getElementById('mytable').addEventListener('click', e => {
let td = e.target.closest('td[class="clickable"]');
if (td) {
console.log(e.target.innerText, 'was clicked');
}
});
td.clickable {
cursor: pointer;
}
<table id='mytable'>
<thead>
<tr>
<th>First Col</th>
<th>Second Col</th>
</tr>
</thead>
<tbody>
<tr>
<td>First</td>
<td class="clickable">Second 1</td>
</tr>
<tr>
<td>First</td>
<td class="clickable">Second 2</td>
</tr>
<tr>
<td>First</td>
<td class="clickable">Second 3</td>
</tr>
<tr>
<td>First</td>
<td class="clickable">Second 4</td>
</tr>
</tbody>
</table>
I have created HTML markup using Javascript now I want to remove that element when clicked, but its not working
if (tBody) {
return (
`<tr class="tr1">
<th class="th1"> Category Name </th>
<th class="th1">Delete </th>
</tr>` +
getdata.data
.map(function (wizard) {
return `<tr class="td1"> <td class=".th1"> ${wizard.categoryName}</td>
<td class="td1"><a class="delClass" onclick="removeCat()" data-remove="${JSON.stringify(wizard._id)}" href="#">Delete</a></td>
</tr>`;
})
.join('')
);
Now I want to remove the above elements when clicked but I use getElementsByClassName and other methods but its not working
Error message and code images
new images**********
enter image description here
the html is rendered dynamically
here is the picture
data-remove image here********
You can use .closest() to find the tr and remove it:
function removeCat(e) {
e.closest('tr').remove()
};
<table>
<tr>
<td>1</td>
<td><button onclick="removeCat(this)">-</button>
</tr>
<tr>
<td>2</td>
<td><button onclick="removeCat(this)">-</button>
</tr>
<tr>
<td>3</td>
<td><button onclick="removeCat(this)">-</button>
</tr>
</table>
Beside, I see your delete buttons has class delClass so you can add event listener to this class and avoid inline script. For example:
var elements = document.getElementsByClassName("delClass");
var removeCat = function() {
console.log(this.dataset.remove)
this.closest('tr').remove();
};
for (var i = 0; i < elements.length; i++) {
elements[i].addEventListener('click', removeCat, false);
}
<table>
<tr>
<td>1</td>
<td><button class="delClass" data-remove="1">-</button>
</tr>
<tr>
<td>2</td>
<td><button class="delClass" data-remove="2">-</button>
</tr>
<tr>
<td>3</td>
<td><button class="delClass" data-remove="3">-</button>
</tr>
</table>
You use a query selector and the remove method:
tBody.querySelectorAll('tr').forEach(tr => tr.remove());
Or if your table has other rows you don't want to delete, then you must have a way of targeting those exactly. Either give them some special class, or maybe you can use the ones you've already given:
tBody.querySelectorAll('.tr1, .td1').forEach(tr => tr.remove());
I'm trying to modify a element using JS however this element does not have any unique properties like ID. Also the table in which this element resides does not have a unique class. Also, the HTML page has multiple tables and td elements.
For example:
Existing HTML :
<table border="1">
<tbody>
<tr>
<td>Id</td>
<td>Name</td>
</tr>
<tr>
<td>12334567</td>
<td>BirthName</td>
</tr>
</tbody>
</table>
I'm trying to modify the cell which contains the value "BirthName" to "BirthName (Sidharth)"
Something Like this:
<table border="1">
<tbody>
<tr>
<td>Id</td>
<td>Name</td>
</tr>
<tr>
<td>12334567</td>
<td>BirthName (Sidharth)</td>
</tr>
</tbody>
</table>
You can find all having BirthName by using bellow colde
const allTds = document.querySelectorAll('td')
// Find the td element that contains the text "BirthName"
const birthDateTd = Array.from(allTds).filter(td=>td.textContent==='BirthName')
After that you can target that <td> as you want.
You can do checking the text for all td and change where matches birthname
let element = document.querySelectorAll('td');
for(let i = 0; i<element.length; i++){
if(element[i].innerText == 'BirthName'){
element[i].innerText += '(Sidharth)';
}
}
If the text is unique then you can use Xpath as shown below and change it.
var td = document.evaluate("//td[contains(text(), 'BirthName')]", document, null, XPathResult.ANY_TYPE, null );
var thisTd = td.iterateNext();
thisTd.innerHTML = "BirthName (Sidharth)";
<table border="1">
<tbody>
<tr>
<td>Id</td>
<td>Name</td>
</tr>
<tr>
<td>12334567</td>
<td>BirthName</td>
</tr>
</tbody>
</table>
Making an food ordering app. There is a first table with all items you can choose. Each item have a button. On this button click it clones the line and put it in a second table containing your chosen items. I would like to change the text content of the button when the element go to the second table. Like "+" in the first table become "-" in the second table (to next delete the item of the second table on "-" click)
HTML
<h1>CHOOSE</h1>
<table id="starters">
<tr>
<th>PRODUCT</th>
<th>PRICE</th>
<th>ADD TO CART</th>
</tr>
<tr>
<td>Cherry</td>
<td>6</td>
<td><button class="item_button">+</button></td>
</tr>
<tr>
<td>Peach</td>
<td>8</td>
<td><button class="item_button">+</button></td>
</tr>
<tr>
<td>Strawberry</td>
<td>12</td>
<td><button class="item_button">+</button></td>
</tr>
</table>
<h1>YOUR CHOICE</h1>
<table id="products_cart">
</table>
JS
let basket = document.getElementById("products_cart")
let buttons = document.querySelectorAll('.item_button');
for (button of buttons) {
button.addEventListener('click', cloneLine);
}
function cloneLine(e) {
let td = e.target.parentNode;
let tr = td.parentNode;
let clone = tr.cloneNode(true);
basket.appendChild(clone);
}
I tried different things like to get (querySelectorAll) the buttons and change their innerHTML (or textContent or innerText) with no success. I also tried to create another button and to replace the former by the newer.
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();
})
})