I'm new to JQuery but have some experience with HTML and CSS.
I'm trying to make a list of checkboxes on a form more interactive, I though I could put them inside a table, clicking anywhere inside each row would check the corresponding checkbox and change the row color so the user would know the selection had been made. For some of the rows I would need a toggle effect to reveal a new row where more information could be entered. I have had some success in doing these things on their own but cannot get them to work together. Please Help!
My toggle effect was simple enough
$(document).ready(function(){
$("#top1").click(function(){$("#bottom1").toggle();});
$("#top2").click(function(){$("#bottom2").toggle();});
});
For the click selection I used
$(document).ready(function() {
$('#row5 tr').click(function(event) {
$(this).toggleClass('selected');
if (event.target.type !== 'checkbox') {
$(':checkbox', this).trigger('click');
}
});
});
Each click would add/remove the 'selected' class which I would use to change the row color. However I'm finding that the selected class only take effect if I use an anonymous function for the click event and adding the code for the extra row, breaks the function.
What am I missing, or am I doing this all wrong? Would love some guidance.
This is the HTML structure I am using
<table class="rowclick" id="rowclick5">
<tbody>
<tr>
<td class="cb"><input type="checkbox" value="yes" /></td>
<td>row 1</td>
</tr>
<tr>
<td class="cb" id="bottom2"><input type="checkbox" value="yes" /></td>
<td>row 2</td>
</tr>
<tr>
<td class="cb"><input type="checkbox" value="yes" /></td>
<td>row 3</td>
</tr>
</tbody>
</table>
Here is what I would do:
$(function() {
$(document).on('click', '#row5 tr', function (event) {
var newState = !$(this).is('.selected');
$(this)
.toggleClass('selected', newState)
.find(':checkbox').prop('checked', newState);
});
});
This uses event delegation (via $(document).on()) and prevents that the state of the checkbox (checked/not checked) and the state of the row (selected/not selected) ever become inconsistent.
Note that I would probably use tr.selectable instead of #row5 tr, as the latter is a bit too specific and therefore hinders re-usability.
You could simply check /uncheck it using:
$(document).ready(function() {
$('#row5 tr').click(function(event) {
$(this).toggleClass('selected');
if ($(event.target).is(':not(:checkbox)')) {
$(':checkbox', this).prop('checked', $(this).hasClass('selected'));
// if you want to trigger click handler bound to checkbox
// without making it bubbles, use:
/*$(':checkbox', this).triggerHandler('click');*/
}
});
});
-jsFiddle-
Related
How do I disable click on all grid cells except one cell in a row? I am trying to disable clicks on any cell in the grid, when a cell enters the edit mode. So I tried:
$('#QCStatus tr td').bind('click',function() {
return false;
});
//QCStatus is the id of the grid
To enable click on a cell, in the same row that is being edited, I tried:
$('#QCStatus tr.selected-row td[aria-describedby="QCStatus_ActionIcons"]').bind('click',function() {
return true;
});
But this doesn't have any effect as click is disabled by the first snippet. What is the correct way to achieve this?
You can exclude the selected row it with :not() here:
$('#QCStatus tr:not(.selected) td').on('click', function(e) {
$('pre').prepend('event :::: '+e.type+'\n');
return false;
});
.selected{background:yellow;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<table id='QCStatus'>
<tr><td>click</td></tr>
<tr class='selected'><td>click</td></tr>
<tr><td>click</td></tr>
<tr><td>click</td></tr>
</table>
<pre></pre>
This will bind the click on all the tds which are not the children of tr.selected.
As per your comment you can add more:
How could I just exclude the td in the selected row td[aria-describedby="QCStatus_ActionIcons"]?
$('#QCStatus tr:not(.selected) td:not([aria-describedby="QCStatus_ActionIcons"])').on('click', function(e) {
$('pre').prepend('event :::: '+e.type+'\n');
return false;
});
Use event.stoppropagation() for element to be eliminated for click event. It prevents further propagation of the current event.
$('tr').on('click', function() {
console.log('clicked!');
});
$('.disabled').on('click', function(e) {
e.stopPropagation();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<table border="1">
<tr>
<td>Hello</td>
<td class="disabled">Disabled</td>
</tr>
<tr>
<td>Hello</td>
<td class="disabled">Disabled</td>
</tr>
<tr>
<td>Hello</td>
<td class="disabled">Disabled</td>
</tr>
</table>
Fiddle here
add a "disabled" attribute to those buttons where you want to disable the click.
for a div disabled attribute doesn't work.
in those cases use "pointer-events:none;" in your css of that particular divs.
I have a dynamically generated table that contains a checkbox for each row, some data, and a text input field.
I want to automatically check the checkbox for a selected row once text is entered in that row's textbox. Finally, when the 'Finish' button is pressed, I want any unselected rows to be hidden from printing. Final output will be the table containing only the selected rows (i.e. those with a check in the checkbox) and their values.
Here's the css print class to hide the unselected rows:
<style type="text/css" media="print">
.grid .hidden tr {
display:none;
}
</style>
Here's the HTML:
<table id="data" class="grid">
<thead>
<tr>
<th> </th>
<th>Part Number</th>
<th>Description</th>
<th>Qty to Order</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="checkbox" class="check"></td>
<td>1234</td>
<td>Description data goes here</td>
<td><input type="text" class="inputData"></td>
</tr>
<tr>
<td><input type="checkbox" class="check"></td>
<td>3454</td>
<td>Description data goes here</td>
<td><input type="text" class="inputData"></td>
</tr>
<tr>
<td><input type="checkbox" class="check"></td>
<td>6787</td>
<td>Description data goes here</td>
<td><input type="text" class="inputData"></td>
</tr>
</tbody>
</table>
<button id="clicker">Finish</button>
Finally, here's the jQuery. This is selecting all the checkboxes when text is entered in a text field, not just the one for that row (which I don't understand), and not assigning the "hidden" class to the rows without a checkbox - the class is not being assigned at all.
$(document).ready(function() {
//Check for input in text field
$('#data > tbody > tr').each(function() {
$(".inputData").change(function() {
if ($(this).val().length > 0) {
$(".check").prop("checked",true);
} else {
$("tr").addClass("hidden");
}
});
});
$("#clicker").click(function() {
window.print();
return false;
});
});
</script>
My logic in constructing this was to make sure we're only selecting rows in the table with an id of data. The first function will iterate over each row looking at the text field, and if the length of that field is greater than 0, check the box. Otherwise, assign the class of "hidden", which will prevent it from printing. Finally, simply assign a click event to the button.
Any help is greatly appreciated.
Here's a jsFiddle
This checks or unchecks the appropriate box based on whether the input has a value:
$(".inputData").on('input', function () {
var checkbox= $(this).closest('tr').find('[type="checkbox"]');
checkbox.prop('checked', $(this).val());
});
It doesn't need to be within an each() method.
This hides all rows in which the checkboxes are not checked:
$('[type="checkbox"]:not(:checked)').closest('tr').hide();
It makes sense to put that within the $("#clicker").click() function.
Updated Fiddle
I have two tables:
<table class="highlight_row" id="table1">
<tr id="first_row">
<td><input type="checkbox" id="first">first thing</td>
<td><input type="checkbox" id="second">second thing</td>
<td><input type="checkbox" id="third">third thing</td>
</tr>
</table>
<table class="highlight_td" id="table2">
<tr id="second_row">
<td><input type="checkbox" id="fourth">fourth thing</td>
<td><input type="checkbox" id="fifth">fifth thing</td>
<td><input type="checkbox" id="sixth">sixth thing</td>
</tr>
</table>
and I am trying to differenciate them -- when I check any box in the first table, I want that whole row to be highlighted, and when I check a box in the second table, I want just that td to be highlighted.
I am able to get rows highlighted (using addClass() to a 'selected' color), but when I specify the table class, I still get the whole row for the second table, when I just want the td (I figure identifying by class instead of id will be better in the long run as I add more tables).
jquery code:
$(".highlight_row").click(function(){
$(":checkbox").change(function() {
$(this).closest("tr").toggleClass("selected", this.checked)
})
});
Something like this fiddle, perhaps?
Your HTML.
CSS:
.highlight { background: #ff0; }
JS:
$("#table1 input[type=checkbox]").on('click', function ()
{
$(this).parent().parent().toggleClass('highlight');
});
$("#table2 input[type=checkbox]").on('click', function ()
{
$(this).parent().toggleClass('highlight');
});
For the first table, you'll want to eval all of the checkboxes so it doesn't get un-highlighted. The second table is much easier.
Fiddle: http://jsfiddle.net/24vm61dk/
$(function () {
// Highlight Row
$('#table1 input[type="checkbox"]').on('change', function () {
var anyChecked = false;
$(this).closest('tr').find('input[type="checkbox"]').each(function () {
if ($(this).prop('checked')) {
anyChecked = true;
}
});
if (anyChecked) {
$(this).closest('tr').addClass('highlight');
} else {
$(this).closest('tr').removeClass('highlight');
}
});
// Highlight Cell
$('#table2 input[type="checkbox"]').on('change', function () {
var checked = $(this).prop('checked');
if (checked) {
$(this).closest('td').addClass('highlight');
} else {
$(this).closest('td').removeClass('highlight');
}
});
});
Code shown is adding change handler within a click handler on the whole table.
This will lead to compounding events and can lead to serious browser performance problems if user clicks a lot in table.
Simply put, click on table 4 times and every time a checkbox gets changed it will trigger 4 change handlers
A simple way for the row highlighting would be to use the count of checked checkboxes in the row to determine the class state
$('table.highlight_row input:checkbox').change(function(){
var $row = $(this).closest('tr'),
hasChecked = $row.find(':checkbox:checked').length;
$row.toggleClass('selected', hasChecked);
});
The cell highlighting is even easier...just toggle the class on the parent cell based on the checked state
$('table.highlight_td input:checkbox').change(function(){
$(this).parent().toggleClass('selected', this.checked);
});
For rows use:
.highlight_row .selected {
background: yellow;
}
for the cell use:
.highlight_td .selected td:nth-child(1) {
background: yellow;
}
I have a Datatables Table with some random values in it. I would like to create a popup when the client clicks on the TR itself, but NOT on the first and the last TD of the table.
<table class="table href="#popup">
<tr id="tr1">
<td><input type="checkbox"></td>
<td>Test1</td>
<td>Test1</td>
<td><input type="checkbox"></td>
</tr>
<tr id="tr2">
<td><input type="checkbox"></td>
<td>Test1</td>
<td>Test1</td>
<td><input type="checkbox"></td>
</tr>
<tr id="tr3">
<td><input type="checkbox"></td>
<td>Test1</td>
<td>Test1</td>
<td><input type="checkbox"></td>
</tr>
<tr id="tr4">
<td><input type="checkbox"></td>
<td>Test1</td>
<td>Test1</td>
<td><input type="checkbox"></td>
</tr>
</table>
My popup plugin works like, if an href link is called and the popup div's id equals to that href value, it automatically pops up.
However if someone clicks on the first or the last TD do NOT want the popup to activate. Is it actually possible to achieve this somehow?
(The following solution should not be mentioned, because it would make the code look like a mess literally: if I select all the TD fields without the first and last, and add a href attribute to all of the selected TD elements.)
Any other suggestions are welcomed!
When you click, the event is propagated from the child nodes to the parent nodes (learn more here).
You can disable event propagation in both td:first-child and td:last-child elements inside your table in order to prevent your tr event handler from being reached.
I'd also suggest you to use event delegation to keep better performance.
$('.table').on('click', 'tr', function() {
alert('show popup');
});
$('.table').on('click', 'td:first-child, td:last-child', function(e) {
e.stopPropagation();
});
FIDDLE: http://jsfiddle.net/6QTrL/1/
Just use this:
Using :first-child and :last-child with not()
$('table tbody tr td').not(":first-child").not(":last-child").click(function(
//This will only be triggered on the td that are not the first or the last on a tr
))
Here's a fiddle to accomplish that - First and Last row now clickable
I have the first and last row throwing an alert but that's just to give you an idea of how to target them.
$(function(){
var tableRows = $('table').find('tr');
$('table').on('click', 'tr', function(){
if (this == tableRows[0])
alert('first row');
else if (this == tableRows[tableRows.length - 1])
alert('last row');
else
alert('somewhere in the middle');
});
});
The code below is probably more along the lines of what you're looking for. I made the code above in the fiddle so I just pasted that as well.
$(function(){
var tableRows = $('table').find('tr');
$('table').on('click', 'tr', function(){
if (this != tableRows[0] && this == tableRows[tableRows.length - 1])
alert('somewhere in the middle');
});
});
I've got a jQuery/AJAX solution set up to update and delete items that are displayed in a table. The AJAX part works fine but once an item is deleted I need to be able to remove it from view and I can't figure out how to identify the selected item(s) based on their value after the submit button is clicked.
Here's my jQuery:
$('#button').click(function(event){
var order = $("#sortable tbody").sortable("serialize");
order += "&" + $("form[name=favorites]").serialize().replace(/%5B%5D/g, '[]');
order += "&crudtype=update_favorites";
$('#savemessage').html('<p>Saving changes...</p>');
$.post("/crud",order,function(theResponse){
$('#savemessage').html(theResponse);
});
});
});
My HTML is generated from PHP so the quantities and IDs are variable but the format is as follows:
<tr class="odd" id="field_37">
<td class="handle">Item #1 Name</td>
<td><input type="checkbox" name="fid[]" id="fid" value="37" class="box check-child"></td>
</tr>
<tr class="even" id="field_29">
<td class="handle">Item #2 Name</td>
<td><input type="checkbox" name="fid[]" id="fid" value="29" class="box check-child"></td>
</tr>
So effectively what (I think) I need is to add to my .click function something like "foreach checked fid, remove the corresponding row ID" if that makes any sense.
A basic selector to get a checked checkbox is
'input[type="checkbox"]:checked'
or
'input:checkbox:checked'
Now you can either use has() or loop through and use closest to get the trs
$('input[type="checkbox"]:checked').closest("tr").remove();
or
$('tr:has(input[type="checkbox"]:checked)').remove();
You can do it like this: http://jsfiddle.net/dSANw/
When user clicks on checked box add class to the parent tr
$(".box").click(function() {
if($(this).is(':checked')) {
$(this).parents('tr').addClass('checkedtd');
} else {
$(this).parents('tr').removeClass('checkedtd');
}
});
When clicked on delete, get all tables tr's classed 'checkedtd' and delete
$("#delt").click(function() {
alert($('.checkedtd').length);
$('.checkedtd').remove();
});