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.
Related
I have two scripts.
The first script holds a prototype class of a game. This class is with use strict and isn't surrounded by document ready. The trigger:
$("#trigger").trigger("noPossibilities");
In the second script, which also has use strict, I try to catch the trigger:
$(document).ready(function() {
$("#trigger").on("noPossibilities", function() {
console.log("noPossibilities trigger");
});
});
The problem is that I can't catch the trigger. This has probaly something to do with use strict/scope but I can't seem to find a way around this.
Really hope someone can help me
UPDATE
The first script has a prototype class.
This class is getting instantiated in the second script. After the handler. Then it still doesn't work because the first script is loaded before the second script?
Also when I execute this line from the console:
$("#trigger").trigger("noPossibilities");
It doesn't get triggered. Shouldn't it work this way?
UPDATE 2
I found the problem. The first script adds the element with id trigger to the document when it is instantiated. I have a popup at the beginning of the game. Now the handler is getting attached on the click of that button.
The document probaly didn't have the element on which the handler should have gotten attached to. Now it is being attached later on and now it's working.
The issue is not with the scope, you are triggering the event before the handler is attaching to the element. The code inside document ready handler executes only after the DOM elements are loaded. In case you are triggering immediately after the script then it won't work since the elements are still loading.
You can check the working of triggering within a different context by moving it to another document ready handler(to execute only after handler attached).
$(document).ready(function() {
$("#trigger").on("noPossibilities", function() {
console.log("noPossibilities trigger");
});
});
$(document).ready(function() {
$("#trigger").trigger("noPossibilities");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="trigger"></div>
I have a slider button created using a JavaScript plugin, which automatically generates an element with class name .flex-next. However, when I run the following code, nothing is logged in my console:
$(window).load(function() {
$( ".flex-next" ).on( "click", function() {
console.log("youclick");
})
});
Since the button is added dynamically after the dom is loaded, you need to use event delegation so the click event can be used on this button:
$(document).on('click','.flex-nex',function() {
console.log("youclick");
})
Your setting your call to fire when the window loads by using $(window).load(...);. A flexsider is initiated on $(document).ready(...) which happens after the window loads and all of the content is loaded into the DOM. So when your script fires, it looks for an element that isnt there yet.
Get around this by firing your script on $(document).ready(), and use event delegation. The best practice way is to declare your function like so:
$(document).ready(
$(document).on('click', ".flex-next", function() {
console.log("youclick");
});
});
this way your click listener will wait until the page is ready and will put a click event on to any .flex-next event, even those created dynamically. That way if your using large imagery that is loaded asynchronously the code will still work.
You are probably calling your $(".flex-next").on call before the slider button has been executed. So, basically, your .flex-next class doesn't exist in the DOM yet when you call the .on
You should call the .on call after plugin has been initialized.
I have a simple link:
Test Link
I want to get an alert whenever this link is pressed, so I add:
<script>
$('#test').click(function() { alert('clicked!'); } );
</script>
and it works fine, but when i move this code to a remote javascript file, it doesn't work..
any idea why?
I've also tried this code:
$(document).ready(function() {
$('#test').click(function() { alert('clicked!'); });
});
Your second example, using the ready function, should be working. Your first example should also work provided you include the script below the element with the ID "test" (the element has to already exist when your script runs, since you're not waiting for DOM ready). In both cases, your script must be included below (after) the jQuery script.
Example when you don't use ready
Example when you do use ready
I'd check that your external file is actually getting loaded (look for 404 errors in the browser console).
Update: From your comment below, the problem is that the "test" element doesn't exist when you're trying to hook up the handler. click only sets up the handler on the element if it already exists. If you're creating the element later, you have three options (two of which are really the same):
Use the code you already have, but run it after you've created the element (e.g., in the success callback of the ajax call you're making).
Use live, which basically hooks the click event document-wide and then checks to see if the element you tell it ("#test", in this case) was clicked.
Use delegate on the appropriate container (the element within which you're adding "test"). delegate is a more targeted version of live.
live and delegate are both examples of a technique called event delegation, which jQuery makes easy for you by providing those methods.
See the links for further information and examples, but for example, suppose you're going to be adding the "test" element to an element with the ID "target". You'd use delegate like this:
$("#target").delegate("#test", "click", function() {
alert("Clicked");
});
That hooks the click event on "target", but acts a lot like you've just magically hooked it on "test" as soon as "test" was added. Within your handler, this refers to the "test" element just as with click.
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
}
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.