This is the element which I want to remove:
<div id="tobeRemoved">
<div class="eventAttached"></div>
<div>
<div class="eventAttached"></div>
</div>
</div>
And its child may be have event attached.
And now I want to remove it from the DOM tree; I know I can use this:
var ele=document.getElementById("tobeRemoved");
ele.parentNode.removeChild(ele);
But how about the events? Are they cleared at the same time auto?
BTW, I prefer to a cross-browser solution.
You could try this if you know the event type:
function removeEventHandler(elem,eventType,handler) {
if (elem.removeEventListener)
elem.removeEventListener (eventType,handler,false);
if (elem.detachEvent)
elem.detachEvent ('on'+eventType,handler);
}
or jQuery's .unbind() function.
If the events are added with jQuery it will remove the events when the elements are removed.
Related
I have some elements that I add to the DOM after the page has been loaded. And I'd like to perform some actions when I click on them. I'm using the delegation with jQuery but I don't know how to get the clicked element when I'm in the fonction ($(this) refers in this case to the parent)
<div id="parent">
<div class="child">
<div class="hidden"></div>
</div>
<div class="child">
<div class="hidden"></div>
</div>
</div>
<script>
$('#parent').click('.child', function(){
$(this).find('.child').toggleClass("hidden displayed")
});
</script>
Let's say I want to toggle the inner div from "hidden" to "displayed" when I click on the "child" div. Currently when I click on the first "child" div, the two "hidden" div will be toggled, and I want to be toggled only the one in the div I clicked.
Use e.target to find out which element the event originated on.
$('#parent').on('click', '.child', function(e){
$(e.target).toggleClass("hidden displayed")
});
I also fixed the code a bit - you need to use .on for delegated events. (Mentioned by Barmar.)
You need to use .on() to delegate events. As the documentation says:
When jQuery calls a handler, the this keyword is a reference to the element where the event is being delivered; for directly bound events this is the element where the event was attached and for delegated events this is an element matching selector.
So it should be:
$('#parent').on('click', '.child', function() {
$(this).toggleClass("hidden displayed");
};
Your use of .click('.child', function...) does not do delegation. It matches the function signature:
.click(eventData, handler)
described here. So it's just binding to the parent, not delegating to the child, that's why you get the wrong value in this.
i'm trying to catch a change() on a select which is added after the dom generation but i can't success. Here is a sample code:
HTML:
<div class="test" id="divTest"></div>
jQuery:
$('#divTest').click(function(){ $(this).parent().append("<select id='testSel'><option value='f'>F</option><option value='F'>D</option></select>");});
$('#testSel').change(function(){
alert('change');
});
I want to see the alert when i change the value in the select..
And here is a fiddle.
http://jsfiddle.net/T8J8p/3/
Two problems:
Your select element's ID is #testS not #testSel.1
You need to use event delegation for this, through jQuery's on() method:
$('body').on('change', '#testS', function(){
alert('change');
});
JSFiddle demo.
Event delegation allows us to attach a single event listener, to a parent element, that will fire for all descendants matching a selector, whether those descendants exist now or are added in the future.
1. This related to original JSFiddle featured in the question (available here). The question has since been edited.
You need event delegation dynamically added DOM::
Event delegation allows us to attach a single event listener, to a parent element, that will fire for all descendants matching a selector, whether those descendants exist now or are added in the future.
$(document).on('change','#testS',function(){
alert('change');
});
Demo
Try this,
$('body').on("change", "#testSel", function(){
alert('change');
})
You have to bind event using event delegation as the element is added to the DOM after the DOM loaded:
$(document).on('change','#testSel',function(){
alert('change');
});
See Details HERE
$('#divTest').click(function(){
$(this).parent().append("<select id='testS'><option value='f'>F</option><option value='F'>D</option></select>");
$('#testS').change(function(){alert('change');});
});
You can't bid to something that does not exist yet, so bind it after the click, inside the function.
And there was a typo in the selector #testS vs #testSel
http://jsfiddle.net/q98G6/
HTML
<p>[QUESTION]</p>
<div class="answer-notdone">
<p>[CONTENT_1]</p>
</div
<div class="answer-notdone">
<p>[CONTENT_2]</p>
</div
<div class="answer-notdone">
<p>[CONTENT_3]</p>
</div
JavaScript
$(".answer-notdone").click(function(){
markQuestion(this); //external function
$(".answer-notdone").addClass('answer-complete').removeClass('answer-notdone');
)};
The example above is for a multiple choice question in a quiz - the user should only be able to click the answer once, and then it should be 'unlinked' from that jQuery function.
But the problem is even after the class has been removed successfully, the jQuery function is still called when clicked. Why?
Here is a fiddle I made of a demo, if the code above was not clear: http://jsfiddle.net/q98G6/
The selector is only used to find the elements, once the element is found and the event handler is attached to it, the selector does not have any relevance because the handlers are attached to the element not to the selector.
One way to solve the problem is to make use event delegation. In event delegation the handlers are attached to an ancestor element and we pass a selector as a target element. In this method the target selector is evaluated lazily.
$(document).on('click', ".answer-notdone", function(){
markQuestion(this); //external function
$(".answer-notdone").addClass('answer-complete').removeClass('answer-notdone');
)};
The selector returns all the elements that match it at the time you bind the handler, and then it attaches the handler to all those elements. Changing an element's class later does not remove the event handlers that were already bound.
If you want your handler to be bound to dynamically changing elements, you should use delegation:
$(document).on('click', '.answer-notdone', function() {
...
});
Try this
$(document).on('click',".answer-notdone",function () {
//markQuestion(this);
$(".answer-notdone").addClass('answer-complete').removeClass('answer-notdone');
});
FIDDLE DEMO
The below code is not binding the event to an appended element (using .insertBefore()).
From my understanding, .on() is supposed to work like .live(). Is this not the case?
<div class="todoColumn">
<div class="projectHeader">
<div class="title">Example</div>Subtitle
</div>
<div class="todo">
<div class="checkbox"><span class="check pictos">3</span></div>
<div class="text">another test</div>
<div class="floatfix"></div>
</div>
<div class="todo">
<div class="checkbox"><span class="check pictos">3</span></div>
<div class="text">another test</div>
<div class="floatfix"></div>
</div>
</div>
$('.todoColumn .todo .checkbox').on('mouseenter', function() {
$(this).find('.check').css('visibility','visible');
});
It depends upon where you put the selector. Putting it in the first jQuery object does not have any .live() behavior. It binds static event handlers.
Specifying a comment parent object in the jQuery object and putting the selector in the arguments to .on() gives you live behavior:
$(document.body).on('mouseenter', '.todoColumn .todo .checkbox', function() {
$(this).find('.check').css('visibility','visible');
});
It will work even more efficiently (and better than .live()) if you pick a common parent that is closer to the actual objects than document.body. A problem with .live() was too many event handlers (all with selectors to check) on the document object. .on() works more like .delegate() and allows you to put the event handler on a common parent that is closer to the actual objects.
EDIT: Now that you've included your HTML, more efficient code would be this with a common parent selector in the jQuery object and the simplest possible selector in the .on() arguments:
$('.todoColumn').on('mouseenter', '.checkbox', function() {
$(this).find('.check').css('visibility','visible');
});
To use it the way you want, you need to place the selector in the function and bind the event to the document:
$(document).on("mouseenter", ".column .todo .checkbox", function(){
// do stuff
});
And, like jfriend00 suggested, it's more efficient to bind the event to the closest parent:
$(".column .todo").on("mouseenter", ".checkbox", function(){
// do stuff
});
Is it possible to get anywhere a pure Javascript function for event handler with similar functionality as jQuery's live() ? I need to have the ability to attach events to objects not yet created but both jquery-livequery as well as jquery-events sources are not useful due to dependencies on jQuery core.
Event delegation is quite simple. Take this example:
Markup:
<div id="container">
<p>Test</p>
<p>Test</p>
<p>Test</p>
</div>
<button id="add">Add new paragraph</button>
Script:
document.getElementById("container").onclick = function(e) {
// e.target is the target of the event or "source element"
alert(e.target.innerHTML);
};
// dynamically adds new paragraph on button click
document.getElementById("add").onclick = function() {
var p = document.createElement("p");
p.innerHTML = "a new paragraph";
document.getElementById("container").appendChild(p);
};
Since the event handler is attached to the parent, it will work for any future elements inserted.
You can try it here.
Useful reference:
http://www.quirksmode.org/js/events_properties.html#target
http://www.sitepoint.com/javascript-event-delegation-is-easier-than-you-think/
Yes, it's called event delegation and has been around longer than jQuery and "live".
"live" works by listening for events on the body or document, then when when an event occurs looks at the event.target to see if it's selector matches one of those stored in a cache. It is quite inefficient, but works OK for some.
A more efficient approach is to add elements you want listeners on to an array, then listen for bubbling events on the lowest common ancestor of the elements you want to delegate events for. The body element is the fallback, but it's the least efficient. When the listener gets an event it's waiting for, check if the event.target is one of the elements in the array and if so, call the related function with the element as this.
You can also just store the element id as a property of an object so looking it up is faster if you have lots of elements, or you can register events based on class.
There are a few limitations and foibles (some events bubble in some browsers but not others, and some don't bubble at all), and it can be very inefficient, so use with care.
I know little of Jquery and your functions.
You are looking how works with events in javascript?
You can make this:
element.addEventListener('onclick',
function() {
//do something
});
or
element.onclick =
function() {
//do something
});
the element var is an reference of dom document.
check https://developer.mozilla.org/en/DOM for more details.
JQuery is pure JavaScript and OpenSource, so just have a look into the sources, then copy what you need and adapt it.