Chaining :not selector in jquery.on - javascript

I have a table of rows that are dynamically managed via listjs. I have made these rows clickable to open a Bootstrap Modal based on a data attribute (data-modal). This all works fine except for when a link appears in the columns of the rows. Both the anchor is firing and the modal is opening.
To prevent this, I used the following code, which worked on initially loaded elements:
$("[data-modal]").on("click", "a:not(.open-disabled)", function(e) {//open modal code}
But as expected, this doesn't bind to dynamically injected rows or divs.
So I changed my code to try binding to $(document) instead, but I can't get the :not selector to chain properly -- the selectors aren't being properly identified and the modal does not open.
Here is what I changed my code to:
$(document).on("click", "[data-modal], a:not(.open-disabled)", function(e) {}
Questions:
A. How do I chain selectors in the above to prevent the modal from opening if there is an anchor child element that is being clicked.
B. Is there a better method of preventing the modal from opening?

Try this,
$(document).on("click", "[data-modal] > a:not(.open-disabled)", function(e) {}
//-----------^ use child selector here

I found a solution by implementing the method described here: https://stackoverflow.com/a/8696420/2659318
Here is the resulting code:
$(document).on("click", "[data-modal]", function() {
$(this).modal();
});
$(document).on("click", "a.open-disabled", function(e) {
if (!e.stopPropagation) {
e.cancelBubble = true;
return;
}
e.stopPropagation();
})

Related

jQuery tablesorter child elements th disable sorting

I have child elements in th that are popup windows. When i click .show_history div to display the popup div .show_history_ctn, sorting for that column is triggered. I have increased the z-index for .show_history to 9999 and still sorting is triggered. I've also added stopPropagation to .show_history click event and still sorting occurs.
jQuery
$(".show_history").on("click",function(event) {
$(this).siblings(".show_history_ctn").find("tr").show();
event.stopPropagation();
if($(this).hasClass("active")) {
$(this).siblings(".show_history_ctn").slideUp();
$(this).removeClass("active");
} else {
$(".show_history_ctn").hide();
$(".show_history").removeClass("active");
$(this).siblings(".show_history_ctn").slideDown();
$(this).addClass("active");
}
});
$(".tablesorter").tablesorter();
html
<table class='tablesorter'><thead><tr><th><div class='show_history'>Show History</div><div class='show_history_ctn' style='display:none'>**content**</div></th><th></th></tr></thead></table>
How do i solve? I need sorting on the column otherwise i'd just add sorter:'false'.
The problem is that the click binding is removed by tablesorter since it rebuilds the table header. You can solve this using either of the following methods:
Set the headerTemplate option to an empty string ("") - this prevents altering the header content and therefore doesn't break any bindings. Internally, it is using an innerHTML (this will likely be changed soon) to wrap the content because jQuery's wrap was extremely slow in older versions of IE.
Bind the popup links inside the initialized callback (demo)
$(function() {
function bindLink() {
$('.link').click(function(e) {
e.preventDefault();
e.stopPropagation();
});
}
$('table').tablesorter({
theme: 'blue',
initialized: bindLink
});
});
Update: Oops, I forgot to include the cssNoSort class name of "tablesorter-noSort" which needs to be added to the element you're clicking on. Demo link updated above.
<th>AlphaNumeric <a class="link tablesorter-noSort" href="https://google.com">test</a>

Can't get dynamically created modal to close on click | opens with .parents()

I have a module that was built using a Handlebars.js template, I orignally had it opening and closing perfectly, but the information wasn't updated, this can be seen here.
Now I have it so it updates the info, but the toggleClass won't fire when clicking either the 'x' or .overlay. This can be seen here.
Here is my jQuery functions to activate the modal.
$(document).on('click', "a.btn", function (e) {
$(e.target).parents('.image-container').prev('.modal').toggleClass('modal--show');
});
$(document).on('click', '.overlay', function (e) {
$(e.target).prev('.modal').toggleClass('modal--show');
});
$(document).on('click', '.modal__close', function () {
$('.modal').toggleClass('modal--show');
});
How can I make it so this modal will both Open and Close, as well as display the correct information?
Some things I've tried...
replacing: $(e.target) with $(this)
The problem with your code is that you are trying to toggle class of all .modal divs. But you need to toggle the class of only .modal.modal--show.
Also in case of overlay, you need to find the parent div not the sibling div. So use .closest() in place of .prev()
So if you modify your code as
$(document).on('click', '.overlay', function (e) {
$(e.target).closest('.modal.modal--show').toggleClass('modal--show');
});
$(document).on('click', '.modal__close', function () {
$('.modal.modal--show').toggleClass('modal--show');
});

Adding event listener on a replaced HTML DOM

I am using the tooltipster jquery plugin to show title in a nicer way. In my site there is a link with two classes .fav tooltip
<div class="actsave">
Save
</div>
The .tooltip is use to take the above anchor title and display it according to the tooltipster plugin.
$('.tooltip').tooltipster();
This works just fine, but when a user will click on this link the entire DOM will be replace with a new DOM.
$("div.actsave").on("click", "a.fav", function(e){
e.preventDefault();
$(this).replaceWith('Delete');
});
At this point no events are occurring with the new anchor with .del class.
My question is how i can add a event listener to this newly created dom in jquery?
After doing some research i fix it this way:
$("div.actsave").on("mouseover mouseout", "a.del", function(e){
$(e.target).tooltipster();
});
but it seems that we are adding same event again and again without any reason to the dom when we hover the link, so here is the question can we add an event listener to this newly created dom just for once?
$("div.actsave").on("click", "a.fav", function(e){
e.preventDefault();
var newElement = $('Delete');
$(this).replaceWith(newElement);
newElement.tooltipster();
});
Create a flag to keep track using data()
$("div.actsave").on("mouseover mouseout", "a.del", function (e) {
if (!$(this).data('triggered')) {
$(e.target).tooltipster();
$(e.target).data('triggered', true);
}
});

jQuery .on('click') firing multiple times when used with :not() selector

Good morning,
I have a set of boxes on a page that are presented as a list, and within these boxes there might be some links that can be clicked. I want the links within the boxes to work as normal (i.e. bubble up and either perform the default action or then be handled by event handlers further up the DOM), but if the box is clicked anywhere else then it should be caught by a particular event handler attached to the "list" containing all the boxes.
Simple html representation
<div class="boxlist">
<div class="box" data-boxid="1">
Some text, and possibly a link and another link, and perhaps even a third link.
</div>
<div class="box" data-boxid="2">
Some more text, this time without a link.
</div>
</div>
The javascript that I thought should work.
$(function () {
$('.boxlist').on('click', '.box :not(a)', function (e) {
var boxid= $(this).closest('.box').data('boxid');
console.log('open: ' + boxid);
});
});
My expectation was that the above javascript should handle all clicks that did not originate from tags. However, for some reason when the box is clicked (either the box itself, or an tag, doesn't matter), it fires this event X times, where X is the total number of tags within the list of boxes.
So I have two questions:
1. What am I doing wrong with the :not() selector.
2. Is there a better way to handle this scenario?
Thank you for helping!
linkUsing jQuery :not selector actually is very slow ex:http://jsperf.com/not-vs-notdasdsad/4 and it's way better to just use event delegation. So in this case you want to keep track of every click on the .boxlist but check the node type to see if its an anchor or not. This is an example.
$(function () {
$('.boxlist').on('click', function(ev){
if(ev.target.tagName != "A"){
// handle box click code
console.log('box click');
return false;
}
// Otherwise allow event to bubble through.
});
});
and here is a jsfiddle example
http://jsfiddle.net/drXmA/
Also their are a few reasons your code doesn't work
.box :not(a)
should be
.box:not(a)
and the reason this also does not work is because .box is not an anchor tag it has children elements that are anchor tags it will never find an anchor tag named .box if their is one the callback would not execute. Changing the .box to an anchor tag will make it so the code doesn't execute because .box is an anchor and it is only running when .box:not(a)
I guess you want something like this:
$('.boxlist').on('click', '.box:not(a)', function (e) {
var boxid = $(this).closest('.box').data('boxid');
console.log('open: ' + boxid);
}).on('click', '.box a', function (e) {
e.preventDefault().stopPropagation();
});
DEMO FIDDLE
I think better to stop the default behavior and stop the event bubbling to its parent. .on() chain to the .box items excluding <a> from it and stop the default behavior and event bubble with e.preventDefault().stopPropagation();

using preventDefault() with on() in jQuery AJAX tabs

I have a set of jQuery UI AJAX tabs that load individual .php pages when they are clicked. All of my styling, etc. conveys, because the pages that hold the tabs widget provide the already linked CSS, and scripts. When it comes to the actual pages that load when clicking on the tabs however, I can't seen to get preventDefault() to work with .on() on these newly created DOM elements.
I'm using jQuery BBQ with my tabs so I can't have "#"s being appended to the URL. This is caused when links within the tab panels are clicked.
I've been able to successfully use preventDefault() on DOM elements that are initially loaded, but not ones that are being fetched into the tabs widget via AJAX.
My function for a content toggler is...
$(function(){
$(".showMoreOrLess").on('click', (function() {
if (this.className.indexOf('clicked') != -1 ) {
$(this).removeClass('clicked');
$(this).prev().slideUp(500);
$(this).html("Read More" + "<span class='moreUiIcon'></span>");
}
else {
$(this).addClass('clicked');
$(this).prev().slideDown(500);
$(this).html("See Less" + "<span class='lessUiIcon'></span>");
}
}));
});
I'd like to combine the preventDefault() from this function into it.
// prevents default link behavior on BBQ history stated tab panels with "showMoreOrLess" links
$(".showMoreOrLess").click(function (event)
{
event.preventDefault();
//here you can also do all sort of things
});
// /prevents default behavior on "showMoreOrLess" links
I've tried several ways using .on("click", function(work)), etc. I've used .on() in a separate function and also tried to combine it in the first function above. Does anyone know what I'm doing wrong? The code works on tab content that is static, just not content loaded via AJAX. Any help would be greatly appreciated. Can't seem to figure this out. Thanks in advance.
the part $(".showMoreOrLess").click just applies to already accessable links on your page
try to use event delegation (here the clicks are captured on an every time existing element and you just pass the selector it is watching for... as a nice side effect you save listeners
$(document).on("click", ".showMoreOrLess", function(event) {
event.preventDefault();
//here you can also do all sort of things
});
rather than document use a certain id from your page $("#myContainerId") (EDIT: of course the elements you are clicking on need to be inside of the element with the id)
$("body").on('click', ".showMoreOrLess", function(event) {
event.preventDefault();
var self = $(this);
if (self.hasClass('clicked')) {
self.html("Read More" + "<span class='moreUiIcon'></span>").removeClass('clicked').prev().slideUp(500);
}else {
self.html("See Less" + "<span class='lessUiIcon'></span>").addClass('clicked').prev().slideDown(500);
}
});

Categories

Resources