Firing click event on li at the time of prepending - javascript

<ul>
<li>Hello..</li>
</ul>
$('input').click(function(){
$('ul').prepend($('<li>Another Hello...</li>').click()); // not working [1]
$('ul').prepend('<li>This is hello appending...</li>').children(':first').click(); // this is working [2]
});
$('ul li').live('click', function(){
console.log('New li clicked...');
});
Why the [1] code snippet working? Is there any other ways to resolve this the same task? I want to fire the click event at the time of prepend().
N.B: here prependTo() can be used, but is it possible do the same job using prepend().

Because the new element, $('<li>Another Hello...</li>'), is not part of the DOM tree (the document) yet, so the event cannot bubble up to fire the event handler bound with .live().
.live() binds the event handler to the document root and works because events are bubbling up the DOM tree. That means, first the event handler of the element where the event originated is called, then the event handler of its parent and so on, for every ancestor, until it reaches the document root.
But if the element is not added to the document, it has not parent node, so the event cannot bubble up.
You could use .prependTo() [docs] instead:
$('<li>Another Hello...</li>').prependTo('ul').click();

Related

Single click on dynamically added element

Most people know how to bind "click' event to dynamically added element with
$('#main').on('click','.link',function(){ //some code here });
Where .link is a dynamically added element. But how the code above should look like when i want to fire function only on first click? Yes, i know about .one(), but the question is to merge .one() with .on().
jQuery docs for show .one() and .on() are the same as of 1.7:
.one( events [, selector ] [, data ], handler )
.on( events [, selector ] [, data ], handler )
If you just want it to fire on the first click, you can unbind the listener after the execution.
$('#main').on('click', '.link', function() {
$('#main').off('click', '.link');
// do whatever you need here
});
.one()
Description: Attach a handler to an event for the elements. The handler is executed at most once per element per event type.
$('#main').one('click','.link',function(){
//some code here
});
I dont think it is possible straight-away to create delegated on() which will be fired at most once( i.e one()) because of the way delegated handler is wired up.
on(): 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.
Thus the event will always be fired on descendent, even you detach the handler for the current element .link using .off() method inside the handler body.
However you can still achieve this by maintaining a list of DOM elements as a closure and match the list before doing actual code work.
var elements = [];//list of elements which is responded to events at once
$('#main').on('click', '.link', function() {
if(matched){//match $(this)/ uniqueIdentifier in 'elements' array
// prevent default and stopPropagation
return;
}
elements.push($(this));//or push something like 'id' to uniquely identify current element
//..codes
});

Need to get info from any element, which was clicked, but not from parent elements

Need to get info from any element, which was clicked.
Example:
<div>text1<section>text2</section></div>
and JS
$(function(){
$('body *').click(function(){
alert($(this).get(0).tagName.toLowerCase());
});
});
If I click text2, parent element throw alert too. I need only first alert from section. How I can block next alerts from all parent elements of section.
Use event.stopPropagation() to prevent the event from firing on the containing elements.
$(function(){
$('body *').click(function(e){
e.stopPropagation();
alert($(this).get(0).tagName.toLowerCase());
});
});
Just wanted to expand on Kooilnc answer - Using on with event delegation is another option.
Event delegation would be nice if you have an event listener bound before or after on a node that needs to listen to a click handler that has bubbled up. If you stopPropagation, this obviously would be an issue.
Here's a fiddle with a demo:
http://jsfiddle.net/ahgtLjbn/
Let's say a buddy of yours has bound an event listener to a node higher up in the DOM tree. He expects any events that bubble up to it, to be handled by his script.
Using event delegation, the event still bubbles up (so your buddies code will still fire), but it will only alert once (since we called e.stopPropagation).
Calling on without event delegation, or binding the event directly using click (which, under the hood, is just calling on) will prevent the event from bubbling, so your buddies code will never run.

Click event not triggered of dynamically added div

I have added a div dynamically into HTML,
When i have tried to trigger the click event of same element
what i have tried till yet is below ::
$(function(){
$("#id").bind("click",function(){
alert("hi");
})
});
i have also tried to use "on" instead of "bind" but it doesn't work.
but when i have write simple , it works fine
<div onclick="javascript:testFunction();"></div>
Delegate event using on(), you can give the static parent of element that is supposed to be added after execution of binding code.
$(function(){
$(document).on("click", "#id",function(){
alert("hi");
});
});
Delegated events
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, reference.

The added class doesn't trigger its jQuery function

It's an audio player: the idea is that the play button turns into a pause button (and viceversa) when clicked.
Thing is that the .pause event doesn't trigger the following function:
$('.pause').click(function(){
player.pause();
$(this).addClass('play');
$(this).removeClass('pause');
});
The css shows that the pause class is set, but the function doesn't work. Is there a way to make it work? (would be great to know why it didn't work)
jsFiddle
Use a delegated event binding to bind a handler that will be selector-aware without requiring rebinding on events.
For the purposes of your demo, the selector would be along the lines of:
$('.player_controls').on('click', '.pause', function () {...});
Delegate event bindings attach the listener to a parent element that checks to see if the event fired was fired on an element that matches the provided selector.
jQuery docs
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.
You can use event delegation for this. The issue is that binding directly (without delegation) binds to whichever elements exist at the time click is called.
$(".player_controls").on("click", ".pause", function(){
/* ... */
});
Instead of using $('.pause').click(function(){...}) you would need to start using the $.on method to start listening for objects which are still not in the DOM.
e.g
$(".pause").parent().on("click",".pause", function(event){
player.pause();
$(this).addClass('play');
$(this).removeClass('pause');
});

jQuery on() event only working with $(document)

I'm using jQuery's .on() event handler and it's only working when I use $(document).
This works:
$(function() {
$(document).on("click", ".search .remove", function(e) {
console.log("clicked");
});
});
This does not work:
$(function() {
$(".search .remove").on("click", function(e) {
console.log("clicked");
});
});
Nothing happens on that second one...no errors or anything. It just doesn't fire.
You are using two different syntaxes of .on which have two very different outcomes.
Your first is:
$(context).on("event","targetselector",handler)
This binds the event to context, and any events of type event that gets to the context that has an e.target that can be selected with targetselector will trigger the handler with e.target as the context. this is commonly known as event delegation.
Your second syntax is
$(targetselector).on("event",handler)
In this case, the event is bound directly to the elements currently on the page that match targetselector, not future elements. This is essentially the same as the old .bind.
Your second example doesn't work because your elements are created dynamically. When using .on() with dynamically inserted elements, you have to bind it via an element that isn't inserted dynamically, i.e. one that exists on the page at load time.
You can continue to use document as an ancestor element but in terms of performance you might want to find an element closer in the DOM to ".search .remove".
From the jQuery docs on .on():
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.
Your first method is the on() equivalent for the deprecated method live(). Probably your elements get inserted dynamically after the page loading has finished.
You could rewrite your code like following and it should work:
$(function() {
$(".search").on("click", ".remove", function(e) {
console.log("clicked");
});
});

Categories