I have a function that allows users to edit a row in a table by opening the data in a modal. Right now the whole row will fire the modal. What I want is to isolate the last td that contains a link that fires a function that readies the data for processing.
What happens is that when that last td is clicked the modal opens AND the ready function fires. I'm trying to stop the modal from opening.
I also have a mouseover row highlighting on each row of the table.
This is how I associate the table rows with the modal function:
$("#table").find("tr").click(function(e) {
//code to open model
}
This is how I fire the ready function:
$("#table tr td:last-child a").click(function(e) {
//code to open model
}
i believe you need to call e.stopPropogation() to prevent the event from propogating:
$("#table tr td:last-child a").click(function(e) {
//code to open model
e.stopPropagation();
return false;
}
Explanation:
Events propagate from the most "specific" element up to their parents. This is called bubbling, and in this case, your second modal is being fired because the click event is bubbling up from the A element to the TR element.
I believe all events propagate and bubble. Return false simply cancels the default action of the A element, which is to follow the link... it doesn't stop the event object.
Here's a good explanation of the whole thing.
Simply add "return false;":
$("#table tr td:last-child a").click(function(e) {
// whatever should happen when clicking the anchor
return false;
}
This prevents the event from propagating to the surrounding tr.
why instead of finding the link inside the last cell of any row in the table just assign a id or a class to your link
like ...
and then add the display : block property from the css which makes the anchor to fill the whole area it is contained in.
then simply
$('.anchorclass').click(function(){
// do something here
});
Related
I have a problem with the code, in js, I have two onclick events one to do when td in the table was a click and the other to do when elements(.eb_edit) inside this td was clicked.
And I want the code responsible for td not to execute when clicking on this element(.eb_edit) which is inside it.
Here is the code:
$(document).on('click', '.eb_edit', function() {
fetch_data_selected_update($('#konto_select').val(), $(this).attr('update_id'));
});
$(document).on('click', 'td', function() {
fetch_data_selected_insert($('#konto_select').val(), $(this).attr('day'));
});
By clicking on td, the page loads once more only with new popover to add the event in this day, and when we click on the element we load the page with new popover to edit it.
Of course, I can create a page with a popover for each day and for each item, but the page loads too long, so that's not a solution. I prefer to create elements dynamically when clicking on the element using ajax.
I hope you understand, how can I solve it?
you can achieve this using stopPropagation , this would stop the parent listeners from execution when an event occurs on the child element
$(document).on('click', '.eb_edit', function(event) {
fetch_data_selected_update($('#konto_select').val(), $(this).attr('update_id'));
event.stopPropagation();
});
Take a look at here
I've ran into a minor annoyance with a webpage that I am building where by clicking on a link within a table cell is triggering the row to be marked as clicked.
I do however want the rest of that specific cell from being allowed to be clicked.
You can checkout the jsfiddle via: https://jsfiddle.net/r00ftuo1/
Notes:
Usually my jquery code will save the selected row to a database so on returning the page it would restore the selected row.
Usually the link will redirect to a different page; it would NOT go to #.
It is recommended to assign event handler to the table rather that individual rows or cells this is because each event binding counts towards memory not significant for small number of rows but really matter if rows are in hundreds
$("table").on("click", "td", function(e){
if($(e.target).is(':not(a)')){
$(this).closest('tr').toggleClass("selected");
}
});
https://jsfiddle.net/r00ftuo1/4/
I think this is what you are looking for. Also if you need support IE9 or earlier you need to also do the cancelBubbling to stop the event from bubbling up
$("tr").click(function(evt) {
if ($(this).hasClass("selected")) {
$(this).removeClass("selected");
} else {
$(this).addClass("selected");
}
});
$("a").click(function(evt){
evt.stopPropagation();
window.location.href = $(this).attr("href");
});
Event bubbles out so it starts with the deepest element in the DOM hierarchy and if you don't stop the event from propagating it will bubble out to the cell then the row then the table. So here we need a click handler on the link to stop the event from propagating and you can get the href from the element and navigate using something like this:
window.location.href = $(this).attr("href");
EDIT: forgot the "href"
This is my super lazy hacks solution;
$("tr").click(function(e) {
if (e.target.tagName !== "A") {
$(this).toggleClass("selected");
}
}
So the class toggles only if the user clicked somewhere in the td - but not on an A element.
I also simplified your class setting to use toggle to save a few lines of code.
Here is an updated version of your jsfiddle using this solution https://jsfiddle.net/r00ftuo1/2/
So as i understand , you want to make a distinction between the click event on the anchor tags and the click event taking place on the table cell.
Your best bet would be to use event.target and write a little bit of logic as per your requirements . A quick code snippet.
$("tr").click(function(event) {
if (event.target == this) { /** your logic **/ }
});
i hope that answers the question. Further reading. event.target vs event.currentTarget in jquery
I am dealing with a javascript datatable with clickable rows. Each row when clicked forwards the browser to a different page.
A column of the row contains a hyperlink. When the hyperlin is clicked I don't want the row click event to be fired or managed.
Here is how I have implemented the row click event
$(tableId+' tbody').on( 'click', 'tr', function (e) {
window.location.href = $(this).attr('url');
});
When you add an event listener to a parent, the event by default "bubbles" downwards and attaches the event to all children. So in this case you setting the event on tr (parent) and the event will bubble down and attach itself to the td (children). So one of these td from what I understand contains your href (hyperlink) and so to block the click event which originally was set on the parent, you have to set another event listener specifically of the event type click within the function for this event you simply need state event.stopPropagation() and it will override the tr click event which bubbled down.
document.addEventListener('DOMContentLoaded',()=>{
//SET EVENT ON PARENT(TR), EVENT BUBBLES BY DEFAULT DOWNWARDS THEREFORE TD's WILL INHERIT
document.getElementById('parent').addEventListener('click',()=>window.location.href = "wherever");
//ADDING ANOTHER EVENT LISTENER OF THE SAME TYPE (CLICK) WHICH BLOCKS THE BUBBLING PROPOGATION DOWNARDS
document.getElementById('myhyperlink').addEventListener('click',(e)=>event.stopPropagation());
});
If you want to prevent clicking on anchor from redirecting a page, you have to simply catch the click event and disable it's default behaviour.
$("table td a").click(function(e){
e.preventDefault();
});
You have to just prevent default behaviour, if you would also stop propagation of event, your other event listener wouldn't get called. See more info here: What's the difference between event.stopPropagation and event.preventDefault?
If your goal is to disable redirect of anchor links only when the javascript is enabled, another solution might be to set onclick attribute that would disable default redirect. However, this seems not to work in webkit based browsers.
and example
Here is jsFiddle with example
Use preventDefault()
$(tableId+' tbody').on( 'click', 'tr', function (e) {
e.preventDefault();
window.location.href = $(this).attr('url');
});
You can write code following ways:
$(tableId+' tbody').on( 'click', 'tr', function (e) {
e.preventDefault();
window.location.href = $(this).attr('url');
});
you have to disable row click for that particular column
$('tableId+' tbody'').on('click', 'td', function () {
if ($(this).index() == 4 ) { // provide index of your column in which you prevent row click here is column of 4 index
return;
}
// you can do additional functionality by clicking on this column here
});
I have a table on which I use delegate on tr, each row also has a button. I need to perform some action on this button click. The click event on the button fires when it is clicked but it fires the number of times a user clicked anywhere else in the row plus the one time the button is clicked.
Here's a code snippet
JS
$('.detailTable').delegate('tr', 'click', function() {
console.log('clicked in row');
$('#saveButton').click(function(event) {
console.log('clicked on button');
return false;
});
});
HTML
<table class="detailTable">
<tr>
<td>first</td>
<td>
<button id="saveButton">
Save
</button>
</td>
</tr>
</table>
Working Fiddle
First of all, you didn't mention why you are using event delegation? As this isn't required if you are not creating/loading any new elements after page load via some code or using ajax.
The issue is you have a click event bound on the tr, which in turn binds an event on the button. So each time you click on tr it registers a new event so the callback is fired for each registration. If you click in the tr 3 times then for button the callback will be executed 3 times.
In my opinion you should just use normal click events.
You might do this:
$('.detailTable').delegate('tr', 'click', function() {
console.log('clicked in row');
}).delegate('#saveButton', 'click', function(e) {
console.log('clicked on button');
return false; // does two things e.preventDefault() & e.stopPropagation()
// and this will stop the event to bubble up to the tr element.
});
That is correct behaviour as you register a new handler for the button click each time you click on the row. Its not totally clear for me what you want to achieve.
To get the row from the button click event, you can try this:
$("#saveButton").click(function() {
var $item = $(this).closest("tr");
});
First off, you can't have multiple buttons with the same id. That's illegal HTML and will just cause problems for selectors. I'd suggest using a class name instead.
Then, you never want to be binding a new click handler every time something else is clicked. That just gets the click handlers piling up and you get multiple callbacks for each click handler you registered.
Then, unless you're using a really old version of jQuery, you should be using .on() instead of .delegate().
So, here's what I would suggest:
<table class="detailTable">
<tr>
<td>first</td>
<td>
<button class="saveButton">
Save
</button>
</td>
</tr>
<tr>
<td>first</td>
<td>
<button class="saveButton">
Save
</button>
</td>
</tr>
</table>
Code:
// save button click handlers
$('.detailTable').on('click', '.saveButton', function(e) {
// don't let button click handler propagate to the row
// you can remove this e.stopPropagation() line if you want
// a click to trigger both button and row click handlers
e.stopPropagation();
console.log('clicked on save Button');
});
// row click handlers
$('.detailTable').on('click', 'tr', function() {
console.log('clicked in row');
});
Working demo: https://jsfiddle.net/jfriend00/hy69py9m/
FYI, if you're not dynamically creating elements in this table, then there's no need for delegated event handling and you could just use static selectors to map your event handlers.
I don't really get what your question is but some remarks:
I've made this Fiddle with your code and some mild edits.
By delagating an event listener (the one with the button) inside another (the one with the row), there has to be first clicked on the row (or on the button, because it is in the row) only after that the event on the button will be listened to.
If you have multiple rows you have to make sure to not use the same id for every button. In the fiddle I have used a classname which solves that problem.
I suggest using two seperate listeners:
$('.detailTable tr').click(function() {
console.log('clicked in row');
});
$('.detailTable tr .saveButton').click(function(event) {
console.log('clicked on button');
event.stopPropagation();
});
the event.stopPropagation() (jQuery api) prevents the click to bubble up to the row so, when clicking on the button the row will not be clicked.
I have an edit button inside a table cell.
The table cell event has an "click" event, And the edit button who is inside a cell has another click event set to it.
Is there a way to prioritize the button event over the table cell event?
I tried using a different z-index for the button, but it didn't work.
The button cannot go outside the the table as its closest tr holds id data which is crucial for the proper event to function.
You can call event.stopPropagation() as part of the click handler for the button, to prevent the click event from bubbling up to the table cell. Documentation: http://api.jquery.com/event.stopPropagation/
Inside the click handler on the button, you just need to call event.stopPropagation().
element.onclick= function(event) {
// ...
event.stopPropagation();
// ...
}
Look into a tutorial on bubbling and capturing events, such as http://javascript.info/tutorial/bubbling-and-capturing