Event bubbling in jQuery - event.stopPropogation not working - javascript

I am trying to prevent a click form bubbling to the parent <a> HTML tag. Here is my code:
var $result = $("<a href='" + result["link"] + "' class='list-group-item'></a>");
var $title = $("<h4 class='list-group-item-heading'>" + result['title'] + "</h4>");
var $snippet = $("<p class='list-group-item-text'>" + result['htmlSnippet'] + "</p>");
// some code omitted for brevity
var $expandBooksbutton = $("<button type='button' id='btn-showMoreBooks' class='btn btn-default btn-xs'><span class='glyphicon glyphicon-resize-full'></span> expand</div></button>");
$expandBooksbutton.on('click', function(event){
event.stopPropagation();
var height = $('#book-container').height();
if(height != 200){
$('#book-container').height(200);
}
else{
$('#book-container').height(100);
}
});
I am wrapping the whole thing in the anchor tag <a> because I am crafting a search result item.
Regardless of adding event.stopPropogation(); the click event on the <a> still fires.

You can try this
$(<a tag selector>).on('click',function(e){
e.preventDefault();
});

There is a difference between preventing bubbling and cancelling out the default browser behaviour. Try adding
return false;
in the end of your handler function, like this
$expandBooksbutton.on('click', function(event){
var height = $('#book-container').height();
if(height != 200){
$('#book-container').height(200);
}
else{
$('#book-container').height(100);
}
return false;
});
This should be the solution if I understood the question correctly.
UPDATE
Sorry, I should have mentioned that there's also an alternative for this (which actually I should have given as an advice primarily) and this is:
event.preventDefault();
This function actually prevents the default behaviour, whereas
return false;
does both (stops bubbling & prevents default behaviour)
There's more info on this here:
event.preventDefault() vs. return false

Without knowing your full DOM structure, this will be slightly abstract. However event handlers bound to an element before it is added to the DOM aren't actually triggered.
From the jQuery docs:
Event handlers are bound only to the currently selected elements; they
must exist on the page at the time your code makes the call to .on().
To ensure the elements are present and can be selected, perform event
binding inside a document ready handler for elements that are in the
HTML markup on the page. If new HTML is being injected into the page...attach event handlers after the new HTML is placed into the page. Or, use delegated events....
So basically you have two options:
Create a handler for a delegated event and bind that to the parent element after the parent is added to the DOM. Note that this approach requires that the parent be nested inside the <a> as well.
$(parent-elem).on('click', '#btn-showMoreBooks', function(e) {
// your handler logic
});
Of course, you can always keep your logic as-is, but bind the handler to the element only after it's added to the DOM. This is reasonable as long as you won't be re-creating that element dynamically more than once after the initial page load.

Related

EventListener not working with anchor tel:XXXXXXXXX

I have a tag with href="tel:XXXXXXXXX", and I need catch the click event.
I have tested the following code on chrome: $(document).on('click',console.log). If i click on this tag browser it calls the application, but does not trigger a click event.
$("a[href^='tel']").on('click', console.log);
This is working, but I my have a problem with content load by ajax. My code has loaded a page and after some time application added content by ajax. When i use $(document).on('click', ("a[href^='tel']", console.log), there is a problem.
$("a[href^='tel']").on("click", function(e){
e.preventDefault(); e.stopPropagation();
console.log(this);
alert(this.getAttribute("href"));
})
//or if you want to delegate your function
$(document).on('click', "a[href^='tel']", function(e){
e.preventDefault(); e.stopPropagation();
console.log(this);
alert(this.getAttribute("href"));
});
This will bind an event listener to all click on a tags with a href attribute and prevent the click itself. After click, you'll be able to use your console to see which element was click and what href was used.
Ok, i found resolve.
I use earlier event "mousedown" and change attr "href" to "only number" for disable action click.
Code:
const click2dial_Event = function(e) {
e.preventDefault();
let a = $(this), number;
if (a.attr('href') !== '#') {
number = a.attr('href');
number = number.substr(4);
a.attr('href', '#');
a.attr('data-dial', number)
a.addClass('click-to-dial');
} else {
number = a.attr('data-dial');
}
//...
};
$(document).on('mousedown', "a[href^='tel']", click2dial_Event);
$(document).on('mousedown', '.click-to-dial', click2dial_Event);
This would get the phone number from the a tag starting with a value of tel upon clicking it.
$("a[href^='tel']").on("click", function(e) {
var hrefText = this.getAttribute("href");
var str = hrefText;
var res = str.split(":");
alert(res[1]);
});
On Initial Load
I would first recommend that you wait for the initial DOM to be ready before binding any events to elements.
// DOM ready shorthand
$(function() {
$("a[href^='tel']").on('click', function(e) {
// Do work here
});
});
AJAX Content
If you are adding additional elements after the initial load you will have to bind events to those new elements as well.
You could also do something like adding a data attribute to the elements that you've bound click events to and only add to ones that don't yet have that data attribute - but that's additional unnecessary work.
Full Example Code
// DOM Ready Shorthand
$(function() {
// Click Handler
function clickEvent(e) {
// Do work here
}
// Bind click event to initial tels
$("a[href^='tel']").on('click', clickEvent);
// Arbitrary AJAX request for demonstration (wherever yours may be)
$.ajax('/newContent')
.done(function(html) {
// Adding our response HTML to the page within #someElement
$('#someElement').append(html);
// Bind click event to the new tel elements scoped to the returned html
$("a[href^='tel']", html).on('click', clickEvent);
});
});

Adding Jquery click handler to dynamically-loaded content

My Rails app loads links to a page dynamically. I want to append an onClick action to those links.
The links are appended to the page properly, but the JS for the page is not being applied to those newly added elements.
I've tried rendering new JS tags to the dynamically-added content. I've also tried including this block of code, which should target any link with .select-link added to the #links div.
$("#links").on("click", ".select-link", function() {
my code here...
})
That code works when the links are not dynamically loaded. However, I cannot seem to apply ANY onClick handler to them when dynamically loaded, even in the console.
What could possibly cause this issue?
For more context, the problem I'm trying to solve is here: AJAX-loaded JS not rendering
You should bind your event to document like this
$(document).on("click", "#links .select-link", function() {
my code here...
});
Try following code:
$(document).on("click", "#links .select-link", function() {
/*my code here...*/
})
or
$("#links .select-link").live("click", function() {
/*my code here...*/
})
The thing is, the code which you have in the question does work for dynamically inserted content.
The following snippet has one <div class="select-link"> which is part of the HTML and inserts two <div class="select-link"> elements via JavaScript.
jQuery is used to add two separate click handlers. The first handler is added prior to any of the dynamic content being added to the DOM. The second handler is added after the second <div class="select-link"> is added, but before the third one is inserted. Both handlers are called for all three <div class="select-link">. This demonstrates that the code you have provided in the question does work for dynamically inserted content. That means something else is going on.
$("#links").on("click", ".select-link"
,logEvent.bind(null,'#links on .select-link','jQuery'));
function logEvent(text,type,e){
var curTarget = (e.currentTarget.id)?e.currentTarget.id:e.currentTarget.nodeName;
var target = (e.target.id)?e.target.id:e.target.nodeName;
console.log(text + ' ::' + type + ' ::curTarget=' + curTarget
+ ' ::target=' + target);
}
function appendLink(id,text) {
document.querySelector('#links').insertAdjacentHTML('beforeend'
,'<div class="select-link" id="' + id + '" style="color:blue;">'
+ text + '</div>');
}
appendLink('sel-pre-ready','Selected Link 2 (added prior to document ready)');
$(document).ready(function(){
$("#links").on("click", ".select-link"
,logEvent.bind(null,'#links on .select-link','jQuery at doc ready'));
appendLink('sel-post-ready','Selected Link 3 (added after document ready)');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>Not Link</div>
<div id="links">Links
<div id="not-sel">Not Selected Link</div>
<div class="select-link" id="sel-html" style="color:blue;">Selected Link 1 (HTML)</div>
</div><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
Without more information, spending a lot of time speculating on what might be causing the problem is just wasting time.
One possibility of what is happening is that another event handler is being fired for these events and stopping propagation. One way to (mostly) check for that is to add an event handler to the window on the capture phase (i.e. not using jQuery). You could do so with the following:
//The following will catch the event prior to almost all possible
// interference by other event handlers.
window.addEventListener('click',function(e){
if(!$(e.target).is("#links .select-link")){
return; //Not one of the elements we are interested in
}//else
//e.stopPropagation();
logEvent('on window','Capture',e);
},true);

'.on' click not running function?

I have a function that when it runs new markup is generated on the fly...
$('.search input[type="image"]').on('click', function(){
// Open directions in a map
if($('#TXT_SAddr').val() === ''){
return false;
$('.directions .search').css('background' , '#ff0000');
} else {
var from = $('#TXT_SAddr').val();
var to = $('.postal-code').html();
var directions = 'http://maps.google.com/maps?saddr=' + from + '&daddr=' + to + '&output=embed';
var modal = '<div class="apply-modal modal"><a class="close-apply-now" style="margin-bottom: 20px;"><img src="http://site.co.uk/images/closeModal.png" alt="Close" style="border-width:0px;"></a><div class="holder"><iframe src="'+directions+'" style="border:none; width:100%; height:500px;" border="0"></iframe></div></div>';
$('body').prepend('<div class="modalOverlay"/>' + modal);
$('.modal').animate({
'opacity': 1,
'top': '100px'
}, 700, 'easeOutBack');
}
return false;
});
If you can see, the above generates a div with an anchor under the class name of 'close-apply-now'.
I now want to bind a function to this and I've tried using...
$('a.close-apply-now').on('click', function(){
alert('asdasd');
});
with no luck, can anybody see where I may be going wrong? Not even my alert is working.
Since the close-apply-now div is added dynamically, you need to use event delegation to register the event handler like:
// New way (jQuery 1.7+) - .on(events, selector, handler)
$('body').on('click', 'a.close-apply-now', function(event) {
event.preventDefault();
alert('asdasd');
});
This will attach your click event to any anchors with class close-apply-now within the body element.
The syntax for event delegation is slightly different.
The event need to be bind to an element which is already existing in the dom while the target element selector needs to be passed as the second argument
$(document).on('click', 'a.close-apply-now', function(){
alert('asdasd');
});
The close-apply-now div is added dynamically. You have to add the selector parameter, otherwise the event is directly bound (doesn't work for dynamically loaded content) instead of delegated. See http://api.jquery.com/on/#direct-and-delegated-events
Change your code to
$(document.body).on('click', '.update' ,function(){
The jQuery set receives the event then delegates it to elements matching the selector given as argument. This means that contrary to when using live, the jQuery set elements must exist when you execute the code.
Use jQuery's live() method. Description: Attach an event handler for all elements which match the current selector, now and in the future.
$("a.close-apply-now").live("click", function(){
alert('asdasd');
});
Try Both in Jsfiddle

.click() function being ignored

I'm generating list items that go in an unordered list. I then want to listen for a click on any of these list items. I'm aware I haven't posted the full code, but I'm hoping it isn't necessary for me to. Are elements that are appended like this completely ignored by my jQuery click function? I've tried just about everything and can't find out why! All I want to see is my "lol" alert! :(
$.each(entries, function(i, v) {
s += '<li';
if (favouriteItem(v.title)) s += ' data-theme="e"';
s += '>' + v.title + '</li>';
});
$("#linksList").append(s);
$("#linksList").listview("refresh");
$("li").click(function() {
alert("lol");
selectedEntry = $(this).data("entryid");
});
Although the items do visually appear the source code stays like this:
<div data-role="content">
<ul data-role="listview" id="linksList" data-divider-theme="b" data-inset="false"></ul>
</div>
Suggesting that there are no li elements there. Yet they do show visually? Someone please save me before I jump into a pool of lava.
Change:
$("li").click(function() {
alert("lol");
selectedEntry = $(this).data("entryid");
});
to
$('#linksList').on('click', 'li',function() {
alert("lol");
selectedEntry = $(this).data("entryid");
});
When you add elements dynamically to the document, you need to use .on()'s delegated event syntax.
Event handlers are bound only to the currently selected elements; they
must exist on the page at the time your code makes the call to .on().
To ensure the elements are present and can be selected, perform event
binding inside a document ready handler for elements that are in the
HTML markup on the page. If new HTML is being injected into the page,
select the elements and attach event handlers after the new HTML is
placed into the page.
Use delegation:
$("#linksList").on('click',"li",function() {
alert("lol");
selectedEntry = $(this).data("entryid");
});

Trapping all `a` clicks including ones added dynamcally

I know you can bind to click events with jQuery like so:
$('a').click(function(){});
But what about html elements that are added dynamically? Lets say I have a div with the following contents:
<div>
<a href='location.html'>location</a>
</div>
Now I call:
$('a').click(
function(){
console.log("going to " + $(this).attr('href'));
return true;
});
And that will work fine. But if somewhere along the line I call
$('div').("<a href='location2.html'>location2</a>");
without explicitly binding that event handler to that event then the event handler will pick up on it.
Is it possible to rebind when ever a new a element is added. Or even better, when ever the location.href property is changing so I can add a get parameter to it every time.
For example if I was binding to a click event on an a element the event handler would be:
function(){
var newid = parseInt(Obj.Request('pageid'), 10) + 1;
location.href = $(this).attr('href') + '?pageid=' + newid.toString();
return false;
}
Assuming the Obj.Request is a function that returns a get parameter. (I already have this in place).
Use it in this manner:
$(document).on( 'click', 'a', function() {
console.log("going to " + $(this).attr('href'));
return true;
});
Working on your fiddle link.
You want to use the function .on.
$('a').on('click', function() {
//works on non dynamic elements present at page load
});
$('#some_non_dynamic_parent_ID').on('click', 'a', function() {
//works on dynamic elements added later
});
You want to use .on(), but as a delegation method.
Bind it to the closest static parent - for this example I'll just use body.
$('body').on('click', 'a', function(e){
e.preventDefault();
});
This will wait until the event bubbles up to the body element and check what the original target of the event was - if it was an a element, it'll fire the handler.
You can use .on() or live() functions if you use jquery upper then 1.7 version. About the difference of these functions you can read in this article

Categories