I am trying to have a button that, when clicked, will have some jQuery code linked to it. See the general layout below. However, there will be a variable number of rows on the table. All the buttons should have the same action but applied to its parent element. How can I achieve this?
Thanks
td {
border: 1px solid black;
padding: 10px;
}
<table>
<tr>
<td>Info</td>
<td><button class="remove">Remove row</button></td>
</tr>
<tr>
<td>Info</td>
<td><button class="remove">Remove row</button></td>
</tr>
<tr>
<td>Info</td>
<td><button class="remove">Remove row</button></td>
</tr>
</table>
You can do that in several ways, question is tagged with jQuery so the easiest way using jQuery is :
$("button").on("click", function(ev) {
$(this).parents("tr").remove()
});
This will remove tr element when clicked on it's button, you can do what you want inside that anonymous function
The example below does what you need, it will check any click within a table element to see if it matches the required pattern (in this case a button with class .remove), before then actioning the code.
I've added a dynamically added row so you can test it.
If you aren't having dynamically added rows (i.e. they are all there before this code is run) then you can simply use:
$("table button.remove").click( function() {
$(this).closest("tr").remove();
});
// Add click event linked to the table
// Will trigger whenever a button with class .remove is clicked within the table
$( "table" ).on( "click", "button.remove", function() {
// Move up DOM tree to nearest 'tr' and remove it
$(this).closest("tr").remove();
});
// Add click event to add row button
$("#add-row").click( function() {
// Add dynamic row for testing
$("table").append('<tr><td>Info</td><td><button class="remove">Remove row</button></td></tr>');
});
td {
border: 1px solid black;
padding: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr>
<td>Info</td>
<td><button class="remove">Remove row</button></td>
</tr>
</table>
<button id="add-row">Add Row</button>
Try this
let btns = $("button.remove"); // you will select only buttons with remove class
in your case you want something like this :
btns.each(function(){
let btn = $(this);
btn.on('click',()=>{
// your stuff
})
})
i hope it was useful !
Related
I have a table with rows. In each row there is a "copy to clipboard" button implemented using Clipboard.js
Now I want the table row to be clickable and I want it to redirect to "google.com", if the user clicks anywhere on the row BUT the button.
When the user clicks the button, I want to copy the text to the clipboard, but NOT redirect.
I have tried using the solution suggested in this answer here, but using event.stopPropagation() also disables the Clipboard.js functionality.
Is there an elegant solution for this problem? Here's some code:
<table>
<tr>
<th>Name</th>
<th></th>
</tr>
<tr class='valign-middle' data-href='www.google.com'>
<td>Text</td>
<td>
<button data-clipboard-text='www.facebook.com' id='clipboard-btn'>
<i class="fa fa-clipboard"></i>
</button>
</td>
</tr>
</table>
<script>
// activate Clipboard buttons
var clipboard = new Clipboard('button#clipboard-btn');
// make table rows clickable
$(function(){
$('.table tr[data-href]').each(function(){
$(this).css('cursor','pointer').hover(
function(){
$(this).addClass('active');
},
function(){
$(this).removeClass('active');
}).click( function(event){
document.location = $(this).attr('data-href');
}
);
});
});
</script>
You can have a class for td in tr except for the last one in which your copy button is present, then instead of applying click event on row you can have this click event on each td and then check in click event whether td has that specified class or not, if it has redirect it to google.com else do nothing.
Below is the sample implementation :
<table>
<tr>
<th>Name</th>
<th></th>
</tr>
<tr class='valign-middle' data-href='www.google.com'>
<td class='normalText'>Text</td>
<td>
<button data-clipboard-text='www.facebook.com' id='clipboard-btn'>Copy
<i class="fa fa-clipboard"></i>
</button>
</td>
</tr>
</table>
<script>
var clipboard = new Clipboard('button#clipboard-btn');
// make table rows clickable
(function(){
$('table tr[data-href] td').each(function(){
$(this).css('cursor','pointer').hover(
function(){
$(this).addClass('active');
},
function(){
$(this).removeClass('active');
});
$(this).click( function(event){
if($(this).hasClass("normalText"))
document.location = $(this).parent().attr('data-href');
}
);
});
});
</script>
[Not exactly the same as the question "how to disable knockout click...". My question involves specific usage of an HTML table and contains valuable approaches on solving such case.]
I have the following table and button below it:
<table>
<tbody data-bind="foreach: my-array">
<tr data-bind="click: $ShowDetails()">
...
<button>Add New Record</button>
The table rows are clickable (and would load some details data in another table).
On click of the button I need to disable all table rows and add one new <tr> on top.
I know how to add the new record on top:
$('<tr><td contenteditable="true">New Record Here</td></tr>').prependTo('table > tbody');
But how to disable all rows of the table so they won't be clickable and look disabled (grayed out)?
Just add disabled class to your <tr>'s using $("tr").addClass("disabled").
The grayed out backgroung can be added by using $('tr').css('background-color','grey') or by describing .disabled class in your css-file:
tr.disabled {
background-color: grey;
}
Then in your ShowDetails() method just check if calling element has the .disabled class by using $(this).hasClass("disabled") method. Show details if it doesn't and do nothing if it does.
Instead of checking the disabled class you can also add a new bool observable named AddMode() and set it to true on Add New button click, and on ShowDetails() put a first line if(AddMode() === true) return; (by #st_stefanov)
I used this CSS code to disable HTML row
.row-disabled {
background-color: rgba(236, 240, 241, 0.5);
pointer-events: none;
width: 100%;
}
$(function (){
var myDisableBtn = $('#btn');
myDisableBtn.on('click',function (){
$('tr').css({'pointer-events':'none',
'background-color':'grey'});
});
});
$(document).ready(function () {
$('#btn').click(function () {
$('#test_table tr').prop('disabled', 'disabled').css('background-color', 'grey');
$('#test_table tbody').prepend('<tr><td contenteditable="true">New Record Here</td></tr>')
});
});
<input type="button" id="btn" value="Add New Record"/>
<table style="width:100%" id="test_table">
<tbody>
<tr>
<td>Jill</td>
</tr>
<tr>
<td>Eve</td>
</tr>
</tbody>
</table>
I have two tables. From the top table you select data items by clicking on a add button which would add that row to the bottom table. In reverse if you select the remove button from the bottom table the row would go back to the top table. Now I am not even sure if it is possible with jQuery to accomplish this without using unique class names...hence me looking for help here.
Here is a Fiddle that is only half working, since I haven't figured out yet if it is possible to do what I am asking.
HTML
<table class="aside-table">
<thead>
<tr>
<th>Data Options
<button type="button" class="btn add-all-selection pull-right" onclick="location.href='#'"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Add All Data Options</button></th>
</tr>
</thead>
<tbody>
<tr>
<td>Item 3
<button type="button" class="btn add-selection pull-right"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span></button></td>
</tr>
<tr>
<td>Item 4
<button type="button" class="btn add-selection pull-right"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span></button></td>
</tr>
</tbody>
</table>
<table class="data-selection-table">
<thead>
<tr>
<th>Data Selection Summary
<button type="button" class="btn remove-all-selection pull-right" onclick="location.href='#'"><span class="glyphicon glyphicon-minus" aria-hidden="true"></span> Remove All Data Options</button></th>
</tr>
</thead>
<tr>
<td>Item 1
<button type="button" class="btn pull-right remove-selection"><span class="glyphicon glyphicon-minus" aria-hidden="true"></span></button></td>
</tr>
<tr>
<td>Item 2
<button type="button" class="btn pull-right remove-selection"><span class="glyphicon glyphicon-minus" aria-hidden="true"></span></button></td>
</tr>
</table>
jQuery
$(document).ready(function(e) {
$('.add-selection').click(function(){
$(this).closest('tr').find('td').fadeOut("fast");
});
$('.remove-selection').click(function(){
$(this).closest('tr').find('td').fadeOut("fast");
});
});
Here's a full solution that works in both directions and includes changing the classes for the icons.
I added a common class to each table.
HTML Change:
<table class="aside-table items-table">
This single event handler works for both sets of buttons
/* delegate a click handler for both button classes */
$('table.items-table').on('click', '.add-selection, .remove-selection', function(){
/* "this" is the button element instance */
var $btn = $(this).toggleClass('add-selection remove-selection'),
/* define row to be moved by looking up DOM tree*/
$item = $btn.closest('tr'),
/* define other table */
$otherTable = $('.items-table').not( $btn.closest('table'));
/* fade and move to other table */
$item.fadeOut(function(){
/* fade out has finished, can move now */
$otherTable.append($item);
/* switch button icon classes */
$btn.find('span').toggleClass('glyphicon-plus glyphicon-minus')
/* is in new table, can fade in */
$item.fadeIn()
});
});
Note that the clcik event has to be delegated to the table elements since removing an element removes event listeners also
References:
closest() Docs
toggleClass() Docs
DEMO
This is what I did. Updated fiddle here
First I added tbody to the html table element so we can target the data areas.
Then added click events to the table elements instead of buttons so we can use event delegation.
$(document).ready(function() {
$('.aside-table').on('click', '.add-selection', function(){
var $item = $(this).closest('tr');
$item.fadeOut("fast");
var $new = $item.clone();
$new.find('.add-selection').removeClass('add-selection').addClass('remove-selection');
$new.find('.glyphicon').removeClass('glyphicon-plus').addClass('glyphicon-minus');
$('.data-selection-table').find('tbody').append($new);
});
$('.data-selection-table').on('click', '.remove-selection', function(){
var $item = $(this).closest('tr');
$item.fadeOut("fast");
var $new = $item.clone();
$new.find('.remove-selection').removeClass('remove-selection').addClass('add-selection');
$new.find('.glyphicon').removeClass('glyphicon-minus').addClass('glyphicon-plus');
$('.aside-table').find('tbody').append($new);
});
});
If you're not wanting to keep them in order, then basically you can just remove the row, not the cell, and append it to the last row on the other table. You'll need to add another "tbody" tag to the 2nd table so we don't put the rows in the "thead" if there's no rows in the table.
$('.add-selection').on('click', function(){
var $row = $(this)
.closest('tr')
.fadeOut("fast");
$row.detach()
.appendTo($('.aside-table').find('tbody tr:last'))
.find('button')
.removeClass('add-selection')
.addClass('remove-selection')
.find('span')
.removeClass('glyphicon-plus')
.addClass('glyphicon-minus');
});
For the remove function, it'd be the same code w/ the exception of the table class selector, and switch out the classes for the button as well.
I am using jQuery.
I want to select a cell from a table.
So I tried the following codes.
// First line works fine for me. I can get a list of columns at the correct target row.
var targetColumns = $(elemClicked).closest("tr").find("td");
// I want to get the cell with the class named "draftstatus". This line has problem. I cannot get what I want.
var targetCell = columnsAtTargetRow.$(".draftstatus");
The targetColumns inspected from browser looks like the following:
The 5th td above is my target cell.
I also try to use find() function. It won't work either because find() will start from next children level.
columnsAtTargetRow.find(".draftstatus"); // this does not work.
What functions should I used to get that cell within that "list of td".
Thanks in advance.
You just need to figure out which selectors to use.
var targetColumns = $(elemClicked).closest("tr").find("td");
this goes up the DOM to the "tr" and selects the tds. If the elemClicked is inside a td you can select the tds with closest("td"), and then use siblings(".draftstatus");
If the elemClicked is a td, then you can just use siblings(".draftstatus");
Here is some example code to help demonstrate some selectors. Hope this helps some and not confused you more.
$(function(){
//reference all cells with myclass class using filter
$("#table1 tbody td").filter(".myclass").addClass("red");
// click events for all tds reference the .target class cell using siblings
$("#table1 tbody td").on("click",function(e){
$(this).siblings(".target").toggleClass("red");
});
//items inside a table cell click event
$("#table1 tbody td a").on("click",function(e){
//toggle bold class
$(this).closest("td").siblings(".target").toggleClass("bold");
//prevent event from bubbling up
e.stopPropagation();
});
})
.red {
background-color:red;
}
.bold { font-weight:bold; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<table border="1" id="table1">
<tbody>
<tr>
<td>foo</td>
<td>bar</td>
<td class="myclass target">value2</td>
<td>Two link</td>
</tr>
<tr>
<td>foo</td>
<td>bar</td>
<td class="myclass target">value2</td>
<td>Two link</td>
</tr>
</tbody>
</table>
This is incorrect:
columnsAtTargetRow.$(".myclass");
This should be:
columnsAtTargetRow.find(".myclass");
I have to change the table row color based on some business logic. I have limited access.
I have PHP code which decide TD content...from that TD I have to change the current TR background color.
jQuery can help, as it is having lot of traverser and accesser.
code I am writing is
<script type="text/javascript">$(this).closest("td").css("border", "1px solid red");</script>
But not able to access the current TD or TR
Instead of using this, give the element an id and get it using jQuery. In your code, this points to nothing. like:
<table><tr><td> <input id="myInput" type="text" /> </td></tr></table>
//If you want to access the td
$('#myInput').closest("td").css("border", "1px solid red");
//If you want to access the tr
$('#myInput').closest("tr").css("background", "red");
here you can use parents() funciton.
if your element is $('#el') then following will give you nearest td and tr
$('#el').parents('td').first();
$('#el').parents('tr').first();
then you can apply operation like below
$('#el').parents('td').first().css("border", "1px solid red");
$('#el').parents('tr').first().css("border", "1px solid red");
Assuming the worst case, where you have nested tables and you cannot change current TD attributes, than print an empty span within it this way:
<table>
<tr>
<td>Content 1
<table>
<tr>
<td>Content 2<span data-class="very_important" /></td>
</tr>
</table>
</td>
</tr>
</table>
Than add class to (first or last) parent TR like this:
$(function() {
$('span[data-class]').each(function(n) {
var highlightClass = $(this).attr('data-class');
$(this).parents('tr:first').addClass( highlightClass );
$(this).remove(); /* Optional */
});
});
Now your TR has class and you can style it (and its children) the way you like. Result code:
<table>
<tr>
<td>Content 1
<table>
<tr class="very_important">
<td>Content 2</td>
</tr>
</table>
</td>
</tr>
</table>
You need some way to target the TD content or the TD itself. If the content was unique you could search for a keyword or phrase. Either way, you need a selector - $(this) is just a reference to the jquery object once inside a handler.
EDIT
I thought about it a bit more and here's something you could try. Since you only have access to the content, could you add something to it like UPDATED? If so, then you could add that keyword and with jQuery we can add in the border, background and remove the keyword like this:
<table cellpadding="5px" cellspacing="5px" border="1px">
<tr><td>*UPDATED*Apple</td><td>Pie</td></tr>
<tr><td>Orange</td><td>Crush</td></tr>
</table>
-
var $updatedContent = $('td:contains("*UPDATED*")');
$updatedContent.closest('td').css('border', '1px solid red').closest('tr').css('background','green');
$updatedContent.text($updatedContent.text().replace('*UPDATED*', ''));