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
}
Related
What is the difference between
$(function()
{
$(".some").click(function()
{
...
});
});
and
$(".some").click(function()
{
...
});
I know from here that $(function() is shorthand for $(document).ready(function(). But why are we waiting for the document to be ready? Will the function not be only called when some is clicked anyway?
Note: #2 does not work in my case.
The difference is that #1 waits for the DOM to fully load before running the JavaScript.
The second code runs the JavaScript when it receives it which means it looks for .class elements before they have finished loading. This is why it doesn't work.
You need the document to be ready, i.e. all elements of the document to be available, before you can add an event listener to an element.
The reason is: consider a button, and you want an event listener (listening for the click event, for example.
When your sript runs but the button is not yet present, the attempt to attach the listener will fail. As a result, the associated function cannot be called once the button is actually clicked.
Does that answer your question?
You use the $(function()) simply because you need the DOM to fully load.
For example you have a button and you want to add some action on click. You click the button, but nothing happened, because the button was handled prior to the DOM loading.
If you won't check that the DOM is fully loaded, some unexpected behavior might occur.
Please do not confuse between onload() to ready(), as on load executes once the page is loaded and ready() executes only when the DOCUMENT is fully ready.
$(function(){...}) triggers the function when the DOM is load, it's similar to window.onload but part of jquery lib.
you can also use $(NAMEOFFUNCTION);
It's there to be sure the event has a element to listen to.
I've come across an issue where jQuery events fire twice after $.load() is called. The event handler is placed in the load() callback function, and this seems to be the only place where events fire twice on the script.
I've tried adding event.stopPropogation() and event.preventDefault(), as these seem to be common suggestions with jQuery events firing more than one. I'm not sure if my code is bubbling improperly or what. Any feedback would be helpful.
Here's an extract of some of the code where you see the behavior.
$("div.questions").load("question_source.php #simplified_a", function(){
...
// Line 1
$("#some_id").change(function(){
cantBeNegative(this);
adjusted_gross_income = $(this).val();
console.log(adjusted_gross_income);
// event.stopPropagation();
// event.preventDefault();
});
You can clearly see the event firing twice with the console.log bit I've got in there. Any advice would be appreciated!
EDIT
OK, I checked through everything on the live page based on some of the suggestions, and there's definitely only one <div id="questions"> in existence when the problem is occurring. So, it doesn't appear to be an HTML problem.
I also checked to see if the event was actually being called twice, and as far as I can tell, the event is only being called once.
Now, I added a .on() event attached to the document which is called on the dynamically created elements, and that only fires once. .on() is not called within the .load() callback. Here's an example used on one of the other input boxes on the page which works without any problems:
$(document).on('change', "#SWA_mothers_income", function(){
console.log("mothers income changes from on()");
});
So, that works properly, but when tested on the same input within the .load() callback function, it fires twice, regardless of how it's called. So, it seems to me that it's almost certainly an issue with .load(). I wouldn't exactly call myself an expert in this, so if someone can figure out the issue, I'd love to know the answer. As it stands, I'm going to rewrite this code using .on().
SECOND EDIT
Adding $("#some_id").unbind('change');
before the 'change(function()) bit did the trick!
add this line
$("#some_id").unbind('change');
before
$("#some_id").change(function(){});
I'm not saying this will solve your problems but you need to pass in the event to reference it.
$("#some_id").change(function(event){
cantBeNegative(this);
adjusted_gross_income = $(this).val();
console.log(adjusted_gross_income);
event.stopPropagation();
event.preventDefault();
});
It's possible that you have two divs with a class of 'questions', so you could be binding the change function twice.
If you update your change function to the below, this will unbind the change event before re-adding it. This will make sure you only have the function bound once;
$("#some_id").unbind('change').change(function(event) {
event.preventDefault();
cantBeNegative(this);
adjusted_gross_income = $(this).val();
console.log(adjusted_gross_income);
});
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.
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.
Heres my link:
http://tinyurl.com/6j727e
If you click on the link in test.php, it opens in a modal box which is using the jquery 'facebox' script.
I'm trying to act upon a click event in this box, and if you view source of test.php you'll see where I'm trying to loacte the link within the modal box.
$('#facebox .hero-link').click(alert('click!'));
However, it doesn't detect a click and oddly enough the click event runs when the page loads.
The close button DOES however have a click event built in that closes the box, and I suspect my home-grown click event is being prevented somehow, but I can't figure it out.
Can anyone help? Typically its the very last part of a project and its holding me up, as is always the way ;)
First, the reason you're getting the alert on document load is because the #click method takes a function as an argument. Instead, you passed it the return value of alert, which immediately shows the alert dialog and returns null.
The reason the event binding isn't working is because at the time of document load, #facebox .hero-link does not yet exist. I think you have two options that will help you fix this.
Option 1) Bind the click event only after the facebox is revealed. Something like:
$(document).bind('reveal.facebox', function() {
$('#facebox .hero-link').click(function() { alert('click!'); });
});
Option 2) Look into using the jQuery Live Query Plugin
Live Query utilizes the power of jQuery selectors by binding events or firing callbacks for matched elements auto-magically, even after the page has been loaded and the DOM updated.
jQuery Live Query will automatically bind the click event when it recognizes that Facebox modified the DOM. You should then only need to write this:
$('#facebox .hero-link').click(function() { alert('click!'); });
Alternatively use event delegation
This basically hooks events to containers rather than every element and queries the event.target in the container event.
It has multiple benefits in that you reduce the code noise (no need to rebind) it also is easier on browser memory (less events bound in the dom)
Quick example here
jQuery plugin for easy event delegation
P.S event delegation is pencilled to be in the next release (1.3) coming very soon.