Select all table rows between headers using JQuery - javascript

Having the following automatically generated table layout (I have nearly no influence over it)
<table>
<tr>
<th>First Header</th>
<th>
show/hide
</th>
</tr>
<tr>
<td>A question?</td>
<td><input value="User's answer" /></td>
</tr>
<!-- Some more rows -->
<tr>
<th>Second Header</th>
</tr>
<!-- Some more question blocks -->
</table>
... I'd like to select all the <tr>-elements between two headers using Javascript/jQuery
in order to provide such features like:
Hiding all the questions belonging to a certain header.
Automatically edit the <input>s (eg. check/uncheck all or restore default)
The links causing the desired actions are already in the correct headers.
What would be the best way to approach this issue?

You can use nextUntil() to solve this problem.
function getRows(start){
return start.nextUntil(function(i, v){
return $('th', v).length > 0;
});
}
Demo: Fiddle
Implementation of Show/Hide
$('table').on('click', '.used-for-some-action', function(){
getRows($(this).closest('tr')).toggle();
return false;
});
Demo: Fiddle
Update:
Based on comments by #BLSully
$('table').on('click', '.used-for-some-action', function(){
$(this).closest('tr').nextUntil('tr:has(th)').toggle();
return false;
});
Demo: Fiddle

I like Arun P Johny's answer. Here's what I originally thought (this code implements the hide/show functionality)
$(".used-for-some-action").click(function(e) {
e.preventDefault()
$(this).parents("tr").next().is(":visible") ? $(this).parents("tr").next().hide() : $(this).parents("tr").next().show();
});
Fiddle: http://jsfiddle.net/DQMht/1/

I would keep it real simple. You're using JavaScript, so when the page loads, just add a class to rows with a <th>, then use the class.
$(function() {
$("th").parent().addClass("hasTH");
});
Then you can simply target rows that have the hasTH class.
Another option would be to still do it when the page loads, but instead of adding a class, group the rows into new <tbody> elements. This would give you the most pure DOM representation.

Try this:
$("tr:has(th)").each(function(){
if ($(this).find('th').length==2) {
// here you have this: that represent the row which have two td
}
})

Related

How to filter vertical html table with javascript

found many javascript scripts to filter html tables but they all seem to only work with horizontal tables. need to be able to filter whole records of vertical layout html table. any pointers?
Alternatively, is there a way to write a html vertical table without repeating field headers and thus make the structure more repeated record like? That should make it more amenable to filtering
Technically this is off-topic, as you're not supposed to ask for reviews or suggestions of external libraries - as it's bound to open more discussion than just a simple answer. "Product or service recommendations or comparisons" is listed under "Don't ask about" on the Tour page (https://stackoverflow.com/tour).
Seeing, however, as I've just written some code that could help you with this 'issue', I will post it here for you. Please remember for next time that SO is for assistance with scripts - where you've posted a minimal copy of your code so that the issue can be replicated by us. You should specify the issue you're having and what you've tried so far.
In any case; here's a small vertical table with some filters:
<div>
First Name:<input class='filter' row='1'>
Last Name:<input class='filter' row='2'>
</div>
<table border='1'>
<tr>
<th>First Name</th>
<td>Bill</td>
<td>Mark</td>
<td>Steve</td>
</tr>
<tr>
<th>Last Name</th>
<td>Gates</td>
<td>Zuckerberg</td>
<td>Wozniak</td>
</tr>
</table>
Here's a script to make it filter-able:
var filterTable = $('table');
$('.filter').keyup(function(){
var hide = [];
$('.filter').each(function(){
var val = $(this).val().toLowerCase();
var row = $(this).attr('row');
$('table tr:nth-child(' + row + ') td').each(function(){
if($.inArray($(this).index(), hide) == -1 && $(this).text().toLowerCase().indexOf(val) == -1)
hide.push($(this).index());
});
});
filterTable.find('tr td').each(function(){
if($.inArray($(this).index(), hide) != -1)
$(this).hide();
else
$(this).show();
});
});
And here's a link to a fiddle: https://jsfiddle.net/aacden58/

This will only delete the first row in my table. I would like it to delete whichever row I click on using jQuery & html

I would like to know how to delete whichever table row I click the delete link in. Right now it is only deleting one row.
<script type="text/javascript">
$(function() {
$("#deleteEvent").click(function(e) {
$("#drow").remove();
return false;
});
</script>
The html is here
<div id="students">
<table>
<caption>Students</caption>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Student ID</th>
<th>Email</th>
<th>Action</th>
</tr>
<tr id="drow"><td>John</td><td>Doe</td><td>1234</td><td>john.doe#gmail.com</td><td>Delete</td></tr>
<tr id="drow"><td>Amy</td><td>Adams</td><td>234234</td><td>amy.adams#hotmail.com</td> <td>Delete</td></tr>
<tr id="drow"><td>Megan</td><td>Huffman</td><td>12255</td><td>amy.adams#hotmail.com</td><td>Delete</td></tr>
</table>
Add Record
</div>
You're re-using id values in your HTML, which is invalid. Given that, the behavior of anything selecting those ids is undefined. This, for example:
$("#drow").remove();
It might delete the first #drow, it might delete all of them, it might delete none of them, it might throw an error, etc. Since the markup is invalid, the behavior is undefined.
So the first thing you'll want to do is not re-use id values in the HTML. The HTML you show could use class values instead:
<tr class="drow">
Or, you might not need the id or class at all...
If the delete button is inside the row then you can reference the row relative to the button that was clicked with this:
$(this).closest('tr').remove();
This will start at the element which invoked the event and traverse the DOM upwards until it finds the first tr element, then remove that element.
Edit: You also are using duplicate ids on your a tags:
<a href="#" id="deleteEvent">
You can replace them with a class:
<a href="#" class="deleteEvent">
And change your selector to:
$(".deleteEvent").click(function(e) {
// code
});
Or you can probably remove the id or class entirely since you can still identify the elements without it:
$("#students a").click(function(e) {
// code
});
USE THIS
<script type="text/javascript">
$(function() {
$("#deleteEvent").click(function(e) {
$(this).parent('tr').remove();
});
</script>
please replace your function with function given below. its working. I have checked it.
$(function() {
$("table a").click(function(e) {
$(this).parent().parent().remove();
return false;
});
});

How to pass parameters from dynamic table to the event handler without inline javascript hanlder

As I heard, I should avoid using inline javascript handler on html. e.g. onclick = "FUNCTION_NAME".
If I have a table that is generated dynamically, Each row has a button for its own.
If I don't use incline Javascript function, how can I pass some parameters from the table to the event handler?
Maybe passing the data from the table cell is not very hard. What if some data is not shown on the table cell (for security reason), for example, a secret ID number that is used internally within the application and is not supposed to exposure on the html (Setting it in the invisible cell in the table is not safe because people who knows html can still inspect it). How can we pass those data that is not shown on the table from dynamic table to event handler in this case?
If we use inline click attribute, i.e. onclick="javascript_function(parameter_1, parameter_2)" on each row, that's fairly easy to pass any data I want, and I do not need to show those kinds of secure data on the html in order to pass it.
If you use jQuery, I would recommand
<table class="with-val">
<td data-val="17">17 points</td>
</table>
and
$('.with-val').on('click', 'td', function() {
var val = $(this).data('val');
console.log(val) //17
});
This way (with the on(eventType, selector, handler) signature), you don't have to reset the events if rows are deleted or added,
and the markup is much lighter (and it is considred best practice, as you add only one event handler for the whole table).
Giving markup
<td class="val" data-val="17">17 points</td>
you can get value from binding like this:
$('.val').on('click', function() {
var val = $(this).data('val');
console.log(val) //17
});
For this:
Setting it in the invisible cell in the table is not safe because
people who knows html can still inspect it
You must not send secure data in any way to frontend. User can stop your code with breakpoints, debug or anything else, and get this data even when it is not visible in html. In addition this data will be visible in responses for the requests that browser send
You can use click event to call a function, that does the task of getting the value of any paramater you wish.
Hope this helps.
<td><button id="btn">Click me</button></td>
<td><input type="hidden" id="secret_id"></td>
$("#btn").click(function(){
var id = $("#secret_id").val();
alert(id);
});
This is a possible solution:
HTML:
<table border="1">
<thead>
<tr>
<th>HEAD1</th>
<th>HEAD2</th>
<th>HEAD3</th>
</tr>
</thead>
<tr>
<td class="hiddenField">row1 col1</td>
<td>row1 col2</td>
<td><button class="seeHidden">btn1</button></td>
</tr>
<tr>
<td class="hiddenField">row2 col1</td>
<td>row2 col2</td>
<td><button class="seeHidden">btn2</button></td>
</tr>
</table>
CSS:
th:nth-child(1), td:nth-child(1){
display: none;
}
jQuery:
$(".seeHidden").click(function(){
var hiddenField = $(this).parent()
.siblings("td.hiddenField")
.html();
alert(hiddenField);
});
Check this link jsfiddle to see a working example.
Hope it's useful!

How to select first td element and its text with Jquery

I want to change the "Yes! Pick me" into "Picked" with Jquery in the following HTML structure, I used $('#myDiv>table>tr>td>table>tr').eq(1).text("Picked"); But it was not working. Could someone shed some light on this please? Thanks!
FYI, the first td of the the first table itself contains another table...
<div id="myDiv">
<table>
<tr>
<td>
<table>
<tr>
<td>Yes! Pick me!</td>
<td>Not me..</td>
</tr>
<tr>
<td>Not me..</td>
</tr>
</table>
</td>
<td>Not me..</td>
</tr>
<tr>
<td>Not me..</td>
</tr>
</table>
</div>
The section $('#myDiv>table>tr>td>table>tr>td').eq(1).text("Picked"); does the trick, I forgot the last td part. Thanks to Rocket and everyone's help.
Try this:
$("#myDiv table table td:first").text("Picked")
$('#myDiv').find('table table td').eq(0).text(...);
Start your selection at the #myDiv element ($('#myDiv')), then find all the TD element that are inside a table that is inside another table (.find('table table td')), then only alter the first one (.eq(0)).
Documentation:
.find(): http://api.jquery.com/find
.eq(): http://api.jquery.com/eq
The main problem is that you want .eq(0) not .eq(1) as .eq() is 0-based, and you are not selecting the td, only the tr.
Other than that using > direct descendant selectors makes your selection not very robust at all.
Try $('#myDiv table table td').eq(0).text('Picked');
You can try:
$("td:contains('Yes! Pick me!')").text("Picked"); ​
You can use the :contains(text) selector
$('#myDiv td table td:contains(Yes! Pick me!)').text('Picked');
Be careful with nested tables however because if you were to use just
$('#myDiv td:contains(Yes! Pick me!)').text('Picked');
You would get both the cell your after plus the cell it is nested within.
Your child selector query won't work because HTML5 requires the parser to insert <tbody> elements inside your <table> elements, since you've forgotten to put them in yourself. Perhaps you should consider validating your HTML?

Looping through table rows with Javascript/Jquery

So what I'm trying to do is get the last row of an HTML table. If this row then has a certain class I will ignore this row and select the previous one. This would then be cycled through from the end of the table until a row was found without this certain class.
I figured it's probably involving a for loop, a check for the row class and then JQuery's row.prev method, but still not quite sure how to approach this.
Thanks in advance!
To get the last table row that doesn't have a certain class, say targetClass, you can do this:
$("tr:not(.targetClass):last");
I'm not sure what you want to do with this table row, but if you were to add targetClass to the last row that didn't have it, it would look like this
$("tr:not(.targetClass):last").addClass("targetClass");
Check out this fiddle to see it in action
This example shows you how to get the last of each table on the current page: http://jsfiddle.net/JBnzK/
$('table').find('tr:last').each(function(){
if ($(this).hasClass('stupid')) {
$(this).css('color', 'red');
} else {
$(this).css('color', 'green');
}
});
Assuming you've got the following HTML:
<table id="mytable">
<tbody>
<tr>
<td>1</td>
</tr>
<tr id="YouFoundMe">
<td>1</td>
</tr>
<tr class="certainclass">
<td>1</td>
</tr>
<tr class="certainclass">
<td>1</td>
</tr>
<tr class="certainclass">
<td>1</td>
</tr>
</tbody>
</table>
You can do this:
var elWithoutClass = $('#mytable tr:not(.certainclass):last');
if (elWithoutClass.length) {
alert(elWithoutClass.get(0).id);
// alerts "YouFoundMe"
}
:not(.certainclass) will eliminate <tr> without class 'certainclass'
:last will get you the last one
I invite you to check the Selectors documentation page of jquery to learn more about them.

Categories

Resources