I know that for dynamic dom elements I need to use jQuery.fn.on or delegate, but if I 'move' the elements container appending to another elements in the dom, the click doesn't work anymore.
Here is the the jsFiddle to reproduce the issue:
http://jsfiddle.net/j0L7c51f/
Currently I'm using the following bind method:
$('#commoditySelector').on( 'click', 'li.available', function() {
var cmID = $(this).attr('data-cmid');
$('#debug').html('commoditySelected: '+ cmID);
});
If I comment out the code line where I move the ul element using appendTo(), the click event bound works fine.
The issue is caused by your use of mousemove, not the delegated event handler, as the HTML is being re-built every single time the mouse moves. This means that the delegated event handler is correctly fired on a clicked element, but that element is immediately removed from the DOM, so the event is cancelled before it propagates up the DOM to be processed.
To fix this issue, use the mouseenter event on the a instead:
$('#commodityCategories li a').mouseenter(function(e) {
// your code...
});
Updated fiddle
Related
I have an element with properties such as drag and drop and 1 click event handler. I have cloned this element, and find that the cloned element has the event handler working, as long as the original element is still in the DOM. The moment I remove the original from the DOM, however, the event handler is destroyed. My code goes:
el = $(#id).clone(true)
$('#container').packery('addItems', el)
el.appendTo('#container')
$('#container').packery('layout')
$('#lowerContainer > ' + #id).remove()
The event handler on el works as long as the last line is not added. However, adding $('#lowerContainer > ' + #id).remove() kills the handler. Does anyone know how I can keep the handler in cloned element even after removing the original? Thanks in advance!
You should define your click handler on container rather than on individual items:
$('#container').on('click', '.item', function() {...});
In this case it will handle clicks as on existing items as on ones added later.
I have created a dynamic page in which i am loadin 10 element by default. after that if user scroll doun i am apppending more element to this page by js (appending data by ajax).
and on click of a tag i am doing some js work
I am using
$('.atnd_modal').click(function(){
alert("dsfds");
});
not
onclick ="function()" and i dont want to do that onclick.
Problem i am facing that this js is working perfectely for first 10 result but after that it stop working for the block i have appended by js.
how can to do it working for both the cases ??
Try jquery on() for event delegation. It will work on dynamic loaded element on DOM also.
$('body').on('click','.atnd_modal', function(){
alert("dsfds");
});
Delegated events have the advantage that they can process events from
descendant elements that are added to the document at a later time.
Your click event is not working because when you use click() it will attach this handler to all elements having atnd_modal class, but when new element loading in DOM that event is not attached automatically with new element. For previous elements it will work fine but for new element it won't. So here comes Delegated events. We shall attach event to parent element with on() or delegate()
If you want to bind an event to the dynamically added new elements you have to use event delegation :-
Delegated events have the advantage that they can process events from
descendant elements that are added to the document at a later time. By
picking an element that is guaranteed to be present at the time the
delegated event handler is attached, you can use delegated events to
avoid the need to frequently attach and remove event handlers.
Change your code like this, use Jquery On
$('body').on('click','.atnd_modal', function(){
alert("dsfds");
});
The Code:
if($('.info-dropdown').length){
setTimeout(function(){
$('li').has('input[type="checkbox"]').on('click', function(){
$(this).find('.brand-checkbox').parent().toggleClass('active');
});
}, 10);
}
The Problem: This code detects event click on element checkbox. After dynamically changing this ul li the event stops working.
Note: These checkboxes are from bootstrap dropdown menu.
To bind event for dynamic HTML, You can follow below code :
$('containerSelector').on('eventName', 'mainElementSelector' function(e){
});
Realtime example
$("ul").on("click", "li:has(:checkbox)", function(){
});
Event handlers added directly to an object are added only to that specific DOM object. If you then add or replace more DOM objects, those DOM object won't have any of these event handlers on them. You will have to either manually add the event handlers after you create or replace the DOM objects or you will have to switch to using delegated event handling.
Delegated event handling attaches the event handler to a common parent object (that is not replaced) and uses the fact that many events bubble up the parent chain in order to process the event from the common parent. This allows you to freely create or replace child elements, but still have one event handler that works for all child objects.
You can read a lot more about how to do delegated event handling in these other answers:
jQuery .live() vs .on() method for adding a click event after loading dynamic html
Does jQuery.on() work for elements that are added after the event handler is created?
JQuery Event Handlers - What's the "Best" method
As illustrated in those referenced answers, the general idea is like this:
$("#staticParentSelector").on("click", ".selectorForDynamicChildren", function(e) {
// event handler code here
});
I want to do something on all clicks except on a certain element.
I've created a very simple example which demonstrates the issue: http://jsfiddle.net/nhe6wk77/.
My code:
$('body').on('click', ':not(a)', function () {
// do stuff
});
I'd expect all click to on <a> to be ignored, but this is not the case.
Am I doing something wrong or is this a bug on jQuery's side?
There's a lot going on in that code that's not obvious. Most importantly, the click event is actually attached to the body element. Since that element isn't an anchor, you'll always get the alert. (Event delegation works because the click event bubbles up from the a through all its ancestors, including body, until it reaches document.)
What you want to do is check the event.target. That will tell you the element that was actually clicked on, but the actual click event is still bound to the body element:
$('body').on('click', function (e) { // e = event object
if ($(e.target).is(':not(a)')) {
alert('got a click');
}
});
http://jsfiddle.net/y3kx19z7/
No this is not a bug but rather intended behaviour.
The event bubbles all the way up. By clicking the a node, you are still triggering it's parents event from the div node.
Read more about event bubbling in the W3C DOM Specification. Just search for "bubble".
You need to stop the event propagation of the a nodes. i.e.:
$('body').on('click', ':not(a)', function () {
// do something effectively
alert('you should not see me when clicking a link');
});
$("a").click(function( event ) {
// do nothing effectively, but stop event bubbling
event.stopPropagation();
});
JSFiddle: http://jsfiddle.net/nhe6wk77/6/
It's working as intended, here's why!
Use of the :not() selector is honored in delegated events, but it's an uncommon practice because of how events bubble up the DOM tree potentially triggering the handler multiple times along the way.
The jQuery API Documentation states that:
jQuery bubbles the event from the event target up to the element where the handler is attached (i.e., innermost to outermost element) and runs the handler for any elements along that path matching the selector.
Notice the phrase "and runs the handler for any elements along that path matching the selector".
In your example, jQuery is accurately not running the handler on the a element, but as the event bubbles up the tree, it runs the handler for any element that matches :not(a), which is every other element in the path.
Here is a clear example showing how this works: http://jsfiddle.net/gfullam/5mug7p2m/
$('body').on('click', ':not(a)', function (e) {
alert($(this).text());
});
<div class="outer">
<div class="inner">
Click once, trigger twice
</div>
</div>
<div class="outer">
<div class="inner">
<button type="button">Click once, trigger thrice</button>
</div>
</div>
Clicking on the link in the first block of nested divs, will start the event bubbling, but the clicked a element — a.k.a. the event target — doesn't trigger the handler because it doesn't match the :not(a) selector.
But as the event bubbles up through the DOM, each of its parents — a.k.a the event currentTarget — triggers the handler because they do match the :not(a) selector, causing the handler to run twice. Multiple triggering is something to be aware of since it may not be a desired result.
Likewise, clicking on the button in the second block of nested divs, will start the event bubbling, but this time the event target does match the :not(a) selector, so it triggers the handler immediately. Then as the event bubbles up, each of its parents matching the selector triggers the handler, too, causing the handler to run three times.
As others have suggested, you need to either bind an alternate handler that stops propagation on a click events or check the event target against the :not(a) selector inside your handler instead of the delegated selector.
$("body").click(function(e) {
if($(e.target).is('a')){
e.preventDefault();
return;
}
alert("woohoo!");
});
check the target of the click. this way you dont need to bind another event.
updated fiddle
I am using jQuery to attach a function to my click event for an entire class. For example:
$(".clickDiv").click(function(){
$(this).hide();
});
On my client-side javascript, I create more .clickDiv instances dynamically.
Do I need to call the $(".clickDiv).click(function...) again, or will the new instances automatically have that function bound to the click event?
Yes you do, unless you use a delegate event
like this:
$('#container').on('click', '.clickDiv', function() {
$(this).hide();
});
on docs:
If selector is omitted or is null, the event handler is referred to as direct or directly-bound. The handler is called every time an event occurs on the selected elements, whether it occurs directly on the element or bubbles from a descendant (inner) element.
When a selector is provided, the event handler is referred to as delegated. The handler is not called when the event occurs directly on the bound element, but only for descendants (inner elements) that match the selector. jQuery bubbles the event from the event target up to the element where the handler is attached (i.e., innermost to outermost element) and runs the handler for any elements along that path matching the selector.
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. Or, use delegated events to attach an event handler, as described next.
Delegated events have the advantage that they can process events from descendant elements that are added to the document at a later time. By picking an element that is guaranteed to be present at the time the delegated event handler is attached, you can use delegated events to avoid the need to frequently attach and remove event handlers. This element could be the container element of a view in a Model-View-Controller design, for example, or document if the event handler wants to monitor all bubbling events in the document. The document element is available in the head of the document before loading any other HTML, so it is safe to attach events there without waiting for the document to be ready.
Just because too much people here suggested you should use live, live is deprecated since version 1.7 by on and was replaced in version 1.4.3 by delegate
$(selector).live(events, data, handler); // jQuery 1.3+
$(document).delegate(selector, events, data, handler); // jQuery 1.4.3+
$(document).on(events, selector, data, handler); // jQuery 1.7+
I am attaching an event like :
$('body').on('click', 'button[data-tracking], a[data-tracking]',
function(event) { console.log($(event.target));
});
and want to get to the target of element which is set up as :
<pre> <[]a data-tracking="hello" href="hello">
\<\span\>test now\<\/span\>
\<\/a\>
</pre>
it does work perfectly, but event.target gives me "span" element but what i want is "a" element so that I could get to value of data-tracking attribute.
This will bind the event to all new instances
$('.clickDiv').live('click', function() {
$(this).hide();
});
http://api.jquery.com/live/