jQuery Children selector question - javascript

I have the following code:
$("#Table1 tbody").children().each(function(e){
$(this).bind('click',
function(){
// Do something here
},
false)
});
The Table1 html table has 2 columns; one for Names and one for a <button> element.
When I click on a table row, it works fine. When I click on the button, the button code fires; however, so does the row code.
How can I filter the selector so the button doesn't trigger the parent element's click event?

This is what you want.
It's stopPropogation that will stop the parents.
<table>
<tr>
<td>The TD: <input type="button" id="anotherThing" value="dothis"></td>
</tr>
</table>
<div id="results">
Results:
</div>
<script>
$(function() {
$('#anotherThing').click(function(event) {
$('#results').append('button clicked<br>');
event.stopPropagation();
});
$('td').click(function() {
$('#results').append('td clicked<br>');
});
});
</script>
Here's a link to an example of it working as well:
http://jsbin.com/uyuwi
You can tinker with it at: http://jsbin.com/uyuwi/edit

You could also do something like this:
$('#Table1 tr').bind('click', function(ev) {
return rowClick($(this), ev);
}); //Bind the tr click
$('#Table1 input').bind('click', function(ev) {
return buttonClick($(this), ev);
}) //Bind the button clicks
function rowClick(item, ev) {
alert(item.attr('id'));
return true;
}
function buttonClick(item, ev) {
alert(item.attr('id'));
ev.stopPropagation();
return true;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="Table1">
<tbody>
<tr id="tr1">
<td>
The TD: <input type="button" id="button1" value="dothis" />
</td>
</tr>
<tr id="tr2">
<td>
The TD: <input type="button" id="Button2" value="dothis" />
</td>
</tr>
</tbody>
</table>

Is it possible to remove the button code and just run the row code, therefore kind of using event bubbling.
Another couple options:
can you add a class to the TD that has the button in it and in the selector, do '[class!="className"]'
maybe try event.preventDefault(). You can see it being used here. this way you can prevent the default action that is triggered when the button is clicked, although I'm not sure if it will completely prevent the bubbling.

Related

Changing attribute not working as expected

I made the following example to describe my problem:
$("tr > td > #arm").on("click", function() {
$(this).parent().children("#arm").prop("disabled", true);
$(this).parent().children("#disarm").prop("disabled", false);
});
$("tr > td > #disarm").on("click", function() {
$(this).parent().children("#arm").prop("disabled", false);
$(this).parent().children("#disarm").prop("disabled", true);;
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<table>
<tr>
<td>
<button id="arm" disabled>Arm</button>
</td>
<td>
<button id="disarm">Disarm</button>
</td>
</tr>
</table>
<script>
</script>
I have the above table with one row that contains 2 cells and a button in each cell. One of them is disabled so I made a script where when I press the second button it should enable the first one and disable the one which was clicked.
Disabling the button that was clicked work as I expected but I don't know why it doesn't enable the other button.
You're not selecting the right element. Your code is
$(this).parent().children("#disarm")
where $(this) is the #arm element, then parent() is the td cell.
So basically you're searching for a children element (#disarm) of that cell, that's why he can't find it
Try with this instead
$("tr > td > #arm").on("click", function() {
$(this).prop("disabled", true);
$(this).closest("tr").find("#disarm").prop("disabled", false);
});
$("tr > td > #disarm").on("click", function() {
$(this).closest("tr").find("#arm").prop("disabled", false);
$(this).prop("disabled", true);
});
Here it is a WORKING DEMO of your code :)
you need to use prev and next
$("tr > td > #arm").on("click", function() {
$(this).parent().children("#arm").prop("disabled", true);
$(this).parent().next().children("#disarm").prop("disabled", false);
});
$("tr > td > #disarm").on("click", function() {
$(this).parent().prev().children("#arm").prop("disabled", false);
$(this).parent().children("#disarm").prop("disabled", true);;
});
https://jsfiddle.net/hfr33exa/1/
Try to totatlly remove disable attribute from element. As far as I know not all browsers correctly works with disable="false"
you can add a class and then use prop function as below
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
</head>
<body>
<table>
<tr>
<td>
<button id="arm" disabled class="test">Arm</button>
</td>
<td>
<button id="disarm" class="test">Disarm</button>
</td>
</tr>
</table>
<script>
$('.test').click(function(){
$(".test").prop('disabled', function () {
return ! $(this).prop('disabled');
});
});
</script>
</body>
</html>
DEMO
description: I have added a class test to all the buttons and then I used the prop function. So the button on which click event occurs is disabled and rest all are enabled
Here is the solution of your problem. Use removeAttr to remove disabled to the element.
<table>
<tr>
<td>
<button id="arm" disabled>Arm</button>
</td>
<td>
<button id="disarm">Disarm</button>
</td>
</tr>
</table>
<script>
$("tr > td > #arm").on("click", function() {
$("#arm").prop("disabled", true);
$("#disarm").removeAttr("disabled");
});
$("tr > td > #disarm").on("click", function() {
$("#arm").removeAttr("disabled");
$("#disarm").prop("disabled", true);;
});
</script>
here is a jsfiddle of a working example
There is no reason to select the parent when you click on the button.
$(this).parent().children("#arm").prop("disabled", true);
should just be
$(this).prop("disabled", false);
Now when you are trying to pick the other element you do this.
You pick the parent of the button
You look for the other button inside of that element.
The problem is the button is in a sibling of the parent. But there is no need to select the parents when you have the id. Just select it by its id to start, it will be faster.
$("table tbody").on("click", "button", function() {
var btn = $(this).prop("disabled", true);
var opposite = btn.attr("id") === "disarm" ? "#arm" : "#disarm";
$(opposite).prop("disabled", false);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<table>
<tr>
<td>
<button id="arm" disabled>Arm</button>
</td>
<td>
<button id="disarm">Disarm</button>
</td>
</tr>
</table>

Disable click anywhere except one cell (in the selected row) when a cell enters the edit mode

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.

delegate checkbox within my table row

<tbody>
<tr>
<td><input type="checkbox"/></td>
<td>453</td>
<td>Nick James</td>
<td>12/9/2016</td>
</tr>
</tbody>
JS
$('body').on('click','#myTable tbody',function(e){
alert('do something');
});
I have checkbox within my table row, how do I delegate it form above's click event? I do not want the event to be occur when I click on the checkbox.
To perform the functionality only when target type is not checkbox
$(document).ready(function(){
$('body').on('click','#myTable tbody',function(e){
if(e.target.type!='checkbox')
alert('do something');
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id='myTable'>
<tbody>
<tr>
<td><input type="checkbox"/></td>
<td>453</td>
<td>Nick James</td>
<td>12/9/2016</td>
</tr>
</tbody>
</table>
You can check if the target is checkbox and prevent further execution:
$(document).ready(function(){
$('body').on('click','#myTable tbody',function(e){
if($(e.target).is(':checkbox'))
{
return;
}
alert('do something');
});
})
Check this Fiddle
Use stop event.stopPropagation() to prevent the click on inner element to bubble across the parents.
$('body').on('click','#myTable tbody input[type="checkbox"]',function(event){
event.stopPropagation();
});
$('body').on('click','#myTable tbody',function(e){
alert('do something');
});
Now the alert will come only when you click on anywhere inside the table, which is not a input[type="checkbox"].
try this
You can use Jquery not and has selectors to achieve this
$('body').on('click','#myTable tbody td:not("td:has(input[type=checkbox])")',function(event){
alert('do something');
});
Working FIDDLE

Can I exclude a button click inside a TR click event?

I am currently highlighting a table row when selected but in one of the cells I have a button. When I click the button I am triggering the table row click event. Is it possible to seperate the two?
My two calls currently look like this:
$('table.table-striped tbody tr').on('click', function () {
$(this).find('td').toggleClass('row_highlight_css');
});
$(".email-user").click(function(e) {
e.preventDefault();
alert("Button Clicked");
});
My HTML looks like this:
<table class="table table-bordered table-condensed table-striped">
<thead>
<tr>
<th>col-1</th>
<th>col-2</th>
</tr>
</thead>
<tbody>
<tr>
<td>Some Data</td>
<td><button class="btn btn-mini btn-success email-user" id="email_123" type="button">Email User</button></td>
</tr>
</tbody>
</table>
Any idea how I might stop the button click event from triggering the row click event?
You have to use stopPropagation:
$(".email-user").click(function(e) {
e.preventDefault();
e.stopPropagation();
alert("Button Clicked");
});
(See also : What's the difference between event.stopPropagation and event.preventDefault?)
I believe this is caused by event bubbling, try using e.stopPropagation(); just after e.preventDefault();
Try this:
$('.table-striped').find('tr').on('click', function() {
$(this).find('td').toggleClass('row_highlight_css');
});
$(".email-user").on('click', function(e) {
e.preventDefault();
e.stopPropagation();
});​

jQuery Table Row Click Event also firing when i click a link

Here is what i have so far, getting the row number is working great but i need to make it so that when i click on the link in the table, it doesnt fire the code inside the function.
<table>
<tr class="row">
<td>A</td>
<td><a class="link" href="foo.html">Foo</a></td>
</tr>
<tr class="row">
<td>B</td>
<td><a class="link" href="Bar.html">Bar</a></td>
</tr>
</table>
<script>
$(function(){
$('.row:not(.link)').click(function(){
var $row = $(this).index();
});
});
</script>
The selector .row:not(.link) will select all elements that have a class "row" and don't have the class "link", which is not what you are looking for.
You need to use event.stopPropagation within the click event of the a.link elements so that the click event is not propagated to the parents, which includes row.
Try this:
<table>
<tr class="row">
<td>A</td>
<td><a class="link" href="foo.html">Foo</a></td>
</tr>
<tr class="row">
<td>B</td>
<td><a class="link" href="Bar.html">Bar</a></td>
</tr>
</table>
<script>
$(function(){
$('.row').click(function(){
var $row = $(this).index();
});
$('.row .link').click(function(e){
e.stopPropagation();
});
});
</script>
Just a bit late, but this is first link in Google I opened in search for solution to relative topic. So, it may become useful for someone:
$(".clickableRow").click(function(e) {
if (e.target.nodeName != "A") {
window.document.location = $(this).attr("href");
}
});
Links in a row, I mean standart , will work as usual, and this example markup will have three independent link activations:
<tr class="clickablerow" href="profile.html">
<td>John Doe, the VP</td>
<td>PrintChat</td>
</tr>
Heres a quick fix in jquery, just use instanceof
$("#news-table tr").click(function(e){
if((e.srcElement instanceof HTMLAnchorElement)!=true )console.log("IIIIIIHA HA!");
});
You need to prevent event propagation in the click event of the links - here's a sample: http://jsfiddle.net/6t8u7/1/
As you can see, clicking on the link just fires one event. Clicking on the row fires the other event.
The reason you're getting the current behaviour is that the click event from the link "bubbles up" to the parent element.
With a data attribute, there's no need for a class:
$(document).on('click', '[data-href]', function(e) {
if($(e.target).hasClass('ignore'))
return;
var ignore = ['input', 'a', 'button', 'textarea', 'label'];
var clicked = e.target.nodeName.toLowerCase();
if($.inArray(clicked, ignore) > -1)
return;
window.location = $(this).data('href');
});
Usage example (tr is just an example - you can use div, etc):
<tr data-href="your_url">
<td class="ignore">Go nowhere</td>
<td>Go to your_url</td>
<td>Go to another_url</td>
<td><input type="text" value="Go nowhere"></td>
</tr>
You can also use this without explicitly selecting the row in the second function.
$(function(){
$('.row').click(function(){
var $row = $(this).index();
});
$('.link').click(function(event){
event.preventDefault();
event.stopPropagation();
});
});
Just add: if (e.target.tagName == 'A') return; to row click and Link element will use its own logic.
Here is more detailed example:
$("#table tr").click(function(e) {
// Skip if clicked on <a> element
if (e.target.tagName == 'A') return;
// Logic for tr click ...
});
Also can be usable (especially if you use href with span or other nested items in href):
$(".row").click(function(e) {
var hasHref = $(e.target).closest('td').find('a').length;
if (! hasHref) {
window.document.location = $(this).data("href");
}
});

Categories