I'm trying to trigger my own custom events as global events, so that anything on my page can listen to them and react, however, for dynamically added content it's not working. See my fiddle at: http://jsfiddle.net/6TMkG/8/
As far as I understand, the event is triggered for any element in the page that jQuery knows has a handler for it, and it seems it doesn't trigger the event for the li's even though they do have a handler.
Anyone know how to get around this behaviour?
try this
$("#b2").click(function() {
//$.event.trigger("randomEvent");
$('li').trigger('randomEvent');
});
If you want global event, then you could bind the event handler on document, and trigger it on any element in the document.
$(document).on('randomEvent', callback);
$('ul').click(function() {
$(this).trigger("randomEvent");
});
Sorry I completely missed that.. I did not see the first part of your question.. Custom events.. Looks like you are associating the randomEvent but you are not triggering that event when that is associated with it..
Make sure you add the trigger Event in the Document.Ready function so that the evnet handler is associated with as and when the element is available.
Related
I have a button being created after the DOM is created. That button has an action. What I'm having trouble is binding that action to the button. I have researched and people said to us the .on() function but it doesn't seem to be working. What am I missing?
http://jsfiddle.net/e7a4X/
HTML
<button id="firstClick">Click me to create another button</button>
<div id="container"></div>
Javascript
$('#firstClick').click(function() {
$('#container').append('<button class="second-button">Button after DOM</button>');
});
$('.second-button').on('click', function () {
alert("Success");
})
Working demoL http://jsfiddle.net/Metsx/ or http://jsfiddle.net/ZB2Ns/
API : .on http://api.jquery.com/on/
Now to make your event know about the click event you need .on at document or at #container level, which attaches event handlers to the currently selected set of elements in the jQuery object.
Rest should fit your need :)
Code
$('#firstClick').click(function() {
$('#container').append('<button class="second-button">Button after DOM</button>');
});
$(document).on('click', '.second-button', function () {
alert("Success");
})
You will need to tell the DOM, parent to listen to its child.
The issue is that Your new .second-button is a new element, and you have defined your .click function before the DOM actually exists.
But all DOM interactions will trigger a event propagations(bubbling), therefore you can tell #container to listen for click events coming from .second-button
Or use $(document).on to listen, since the bubbling will go all the way to the document root.
If you are a performance minimalist than you would just do #container .on, and stop the propagation from that point, since theres no need to travel to every parent node, but you might eventually need to listen it from the parent of the #container, who knows
I have a jQuery that, whenever the document is ready, binds a hover event with a handler to an element with the class="widget-box". The issue is that once the document is ready, the hover event handler gets binded, but when the user clicks a button on the page, ajax is used so that part of the page is reloaded and then document ready causes the hover event to be binded again to the same element. I don't want this behavior to occur and only want the hover event to be binded once. I've tried to unbind hover() whenever document ready gets called again with unbind('mouseenter') and unbind('mouseleave') but somehow, that doesn't work to remove the hover that is already binded. Does anyone have any ideas as to how to fix this?
Thanks!
You may have done something wrong. Do it this way:
$(".widget-box").unbind('mouseenter mouseleave').bind('hover', ...);
Hope this helps. Cheers
try using the .live() method:)
to qualify:
why are you loading the same javascript twice? if you only load it once, and use .live rather than .hover you can still attach your events to pertinent elements without having to run the js again.
EDIT:
have you considered just wrapping your code in something like:
if(document.myScriptIsLoaded!=true){
document.myScriptIsLoaded=true;
//put your document ready here
}
Good morning peoples.
I have a bit of a slight jQuery question/problem that I am not sure how to tackle.
I have a click handler bound to varying classes on some anchor tags (which works great). I have now come to a page that needs an extra handler on the same anchor tags so I decided to use some namespacing to get the desired result. The trouble with the namespacing is that it is called before the original click handler and creates problems with the first handler. The error is raised due to the first handler requiring an element to exist to continue in the function but the namespaced click handler removes the element before so it errors out.
Does anyone know if one can tell namespaced handlers to execute After the original handler or would I have to completely re-write the script and perhaps extend it on this one (and only) page to have the funcitonality work as I would like.
Thanks in advance.
Alex
It's easier to add a classname to the anchors on the page that events are bound on and check that in my function..
Sorry for any time wasted
If you bring the handler out into a separate function, you can call the original handler from the other handler.
function handler() {
// original event handler code
};
$('#originalTarget').click(handler);
$('#otherTarget').click(function() {
// code to do anything specific to this handler
handler();
}
You can assign more than one handler:
// general handler
$('a.linkclass').click( function(){
doThis();
});
// specific handler on the page in question
$('#specificlink').click( function(){
doSomethingExtra();
});
I have HTML similar to the following in my page
<div id="someDiv">
<img src="foo.gif" class="someImg" />
</div>
The wrapper div is set up such that when it is clicked, it's background-color changes using the following jQuery code.
$("div").click(function(event){
$(this).css("background-color", "blue");
});
I also have some jQuery associated with my img that will do some other function (for the sake of argument I am going to display and alert box) like so:
$("img[class=someImg]").click(function(event){
alert("Image clicked");
});
The issue I have come across is that when I click on the img, the event associated with the div is also triggered. I'm pretty sure that this is due to the way that jQuery (or indeed JavaScript) is handling the two DOM elements - clicking the img would require you to also technically click the div, thus triggering both events.
Two questions then really:
Is my understanding of the
DOM/JavaScript flawed in some way or
is this actually how things are
occurring?
Are there any jQuery methods that
would allow me to perform actions on
a child element without invoking
those associated with its parent?
That is known as event bubbling, you can prevent it with stopPropagation():
$("img[class=someImg]").click(function(event){
alert("Image clicked");
event.stopPropagation();
});
.
Is my understanding of the DOM/JavaScript flawed in some way or
is this actually how things are
occurring?
That is because of what is known event bubbling.
Are there any jQuery methods that would allow me to perform actions
on a child element without invoking
those associated with its parent?
Yes, you need stopPropagation()
No, this is by design. Events bubble up through the entire dom, if you put another handler on body, it would fire too
Yes :) JQuery normalizes the event object, so adding event.stopPropagation() in your img click handler will give you the behavior you expect on all browsers
The problem you just facing is called "event bubbling". That means, if you click on a nested
element, that click event will "bubble up" the DOM tree.
If other elements also are bound to an click event, their listeners will fire aswell.
Solution to prevent this is called:
stopPropagation()
which is used within your event handler
$("img[class=someImg]").click(function(event){
event.stopPropagation();
alert("Image clicked");
});
This is what's called event bubbling, and you can stop it to get the behavior you want with .stopPropagation() (or return false; if you want to stop the event completely, including handlers on the same level), like this:
$("img[class=someImg]").click(function(event){
alert("Image clicked");
event.stopPropagation();
});
You can view a demo here, comment it out and click run again to see the difference.
The short version is that when most event types happen, they happen on the immediate element, then bubble up the DOM, occurring on each parent as they go. This is not jQuery specific at all, native JavaScript does this. If you're more curious, I'd read the linked article, it has a great explanation of what's going on.
So, you have a page:
<html><head>
<script type="text/javascript" src="jquery.1.3.2.js"></script>
<script type="text/javascript">
$(function() {
var onajax = function(e) { alert($(e.target).text()); };
var onclick = function(e) { $(e.target).load('foobar'); };
$('#a,#b').ajaxStart(onajax).click(onclick);
});
</script></head><body>
<div id="a">foo</div>
<div id="b">bar</div>
</body></html>
Would you expect one alert or two when you clicked on 'foo'? I would expect just one, but i get two. Why does one event have multiple targets? This sure seems to violate the principle of least surprise. Am i missing something? Is there a way to distinguish, via the event object which div the load() call was made upon? That would sure be helpful...
EDIT: to clarify, the click stuff is just for the demo. having a non-generic ajaxStart handler is my goal. i want div#a to do one thing when it is the subject of an ajax event and div#b to do something different. so, fundamentally, i want to be able to tell which div the load() was called upon when i catch an ajax event. i'm beginning to think it's not possible. perhaps i should take this up with jquery-dev...
Ok, i went ahead and looked at the jQuery ajax and event code. jQuery only ever triggers ajax events globally (without a target element):
jQuery.event.trigger("ajaxStart");
No other information goes along. :(
So, when the trigger method gets such call, it looks through jQuery.cache and finds all elements that have a handler bound for that event type and jQuery.event.trigger again, but this time with that element as the target.
So, it's exactly as it appears in the demo. When one actual ajax event occurs, jQuery triggers a non-bubbling event for every element to which a handler for that event is bound.
So, i suppose i have to lobby them to send more info along with that "ajaxStart" trigger when a load() call happens.
Update: Ariel committed support for this recently. It should be in jQuery 1.4 (or whatever they decide to call the next version).
when you set ajaxStart, it's going to go off for both divs. so when you set each div to react to the ajaxStart event, every time ajax starts, they will both go off...
you should do something separate for each click handler and something generic for your ajaxStart event...
Because you have a selector with two elements, you're creating two ajaxStart handlers. ajaxStart is a global event, so as soon as you fire any ajax event, the onajax function is going to be called twice. So yes, you'd get two popups.