I have wondered/worried about this for a while now, so I thought I'd ask someone who knows for sure. Can a page have more than one document.ready function? Will they both be executed?
document.ready isn't as standard DOM handler but you're probably referring to the jQuery utility that you're calling as $(document).ready(...
It adds the function to a queue so that you may call this function many times with different callbacks.
Yes, they will both be executed. You can assign multiple .ready() event handlers to a document. When the DOM is ready, jQuery will trigger any bound ready events. From the source:
// Handle when the DOM is ready
ready: function( wait ) {
...
// Trigger any bound ready events
if ( jQuery.fn.trigger ) {
jQuery( document ).trigger("ready").off("ready");
}
}
DEMO.
Yes, you can have multiple document.ready function on a page.They run in sequential order one after the another based on their occurrence in the code.
$(document).ready(function() {
alert("hello 1");
});
$(document).ready(function() {
alert("hello 2");
})
;
Related
Is there a way to control execution order of JS scripts bound to element click? For example, we have two separate scripts, that are fired on the same action and for the same element.
First script (fired by script on website - which I have no permission to change):
$('body').on('click', '#button', function1);
And the second script (which is fired by browser plugin, which I can change, and would run after everything else was fired):
$('body').on('click', '#button', function2);
Those two scripts are separated (in two different files) and cannot be merged into one like this, because I can change only the second one:
$('body').on('click', '#button', function() {
function1();
function2();
});
Can I set the order of execution? Can I force one script to be executed last?
In your second script you can read which function was bound to the click event by the first script. Then you can detach that handler and add your own, where you can (if you want) add the execution of the original function in the last step:
// script 1 ///////////////////////////////////////////////////////////
function f1() {
console.log('f1: function bound by script 1');
}
$('body').on('click', '#button', f1);
// script 2 ///////////////////////////////////////////////////////////
function f2() {
console.log('f2: my own function that should run first');
}
var original_f = $._data(document.body, 'events').click[0].handler;
$('body').off('click', '#button').on('click', '#button', function () {
f2();
original_f();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="button">Trigger handlers</button>
This makes use of $._data, which is not part of the public API of jQuery. See this answer.
Remarks
The above solution assumes that
the site's script (the first script) uses jQuery event delegation on the body element for the element #button; as follows:
$('body').on('click', '#button', function1);
Note that there are other ways to attach event handlers, but this answer assumes that the first script does it like this (as you provided in the question). Of course, function1 can be any function, or even an anonymous, in-line function.
You have full control over the second script and can redefine the click handler you have defined in it.
You write in comments that you cannot access the function of the first script (function1). But please realise that if JavaScript is able to execute it, there is no reason why you could not have access to it via JavaScript.
Furthermore, since you informed that the first script uses jQuery to attach their handler, also jQuery knows which function it is and can access it (how else could it execute it when a click event happens?).
The solution I provide above actually asks jQuery to provide you the reference to that function. And then you can execute it just like jQuery would do when a click event occurs.
Testing the presence of the handler
In order to verify that indeed the first script has set a handler in this way:
$('body').on('click', '#button', function1);
... and that is still there, you can use the following script for debugging:
// script 1 -- you don't need to enter this, it is for this snippet to work with.
function f1() {
console.log('f1: function bound by script 1');
}
$('body').on('click', '#button', f1);
// script 2 -- your code ///////////////////////////////////////////////////////////
var click_handlers = $._data(document.body, 'events').click;
console.log('Info on BODY click handlers that have been set via jQuery:\n',
JSON.stringify(click_handlers, null, 2));
console.log('First click handler is this function:\n', click_handlers[0].handler);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
So i have the same piece of code that runs for both Ready and Click events, but when I try to combine them it doesn't work
$("input[name='reimburse']").on("ready click", function() {
//some code
});
I think it has to do it the Ready function because even this doesn't work
$("input[name='reimburse']").on("ready", function() {
//some code
});
Instead I have to do this for Ready functionality
$("input[name='reimburse']").ready(function() {
//some code
});
Other than creating another JS function and calling that method from 2 different declared events, how can I achieve my initial code? Why doesn't calling on("ready") work?
EDIT:
Its been brought to my attention that ready event is not applicable for individual DOM's and that load should be used instead. I have tried this but still doesn't work. Only the click event works. I have also tried replacing on with bind and same thing happens.
The ready event applies to the document, not to individual DOM elements. So, there is no specific ready event that applies to the "input[name='reimburse']" DOM elements.
If what you're trying to do is to have the same function fire both when the page is first loaded and when a specific click event is fired, then you can put your common event handling code into a named function and then refer to that function from two separate event handlers:
function myHandler(e) {
// code here
}
$(document).ready(myHandler);
$("input[name='reimburse']").on("click", myHandler);
Though, the last line of code above will only work IF those DOM elements are already loaded. As such, you may need to put that line of code inside a .ready() handler (depending upon where the code is being run from).
$(document).ready(function() {
$("input[name='reimburse']").on("click", myHandler);
myHandler();
});
Here's another related answer: jQuery.ready() equivalent event listener on elements?
Why doesn't calling on("ready") work?
Because jQuery decided not to support that structure. jQuery used to support $(document).on( "ready", handler ), but as of jQuery v1.8, that support has been deprecated (e.g. you shouldn't use it because it will be removed). Per the jQuery documentation, these three forms can be used for .ready().
$( document ).ready( handler )
$().ready( handler ) // works, but not recommended
$( handler )
If it is bothering you to have to both specify an event handler and call your function at initiatialization time, then you could create your own plug-in that would do that for you:
$.fn.initOn = function(events, handler) {
this.on(events, handler);
handler();
}
Then, instead of this:
$(document).ready(function() {
$("input[name='reimburse']").on("click", myHandler);
myHandler();
});
You could just do this:
$(document).ready(function() {
$("input[name='reimburse']").initOn("click", myHandler);
});
You can just imitate the click on ready:
jQuery(document).ready(function () {
$("input[name='reimburse']").click(function() {
//some code
});
$("input[name='reimburse']").click();
});
Try using bind()
$("input[name='reimburse']").bind("ready click", function() {
//some code
});
According to the documentation
Multiple event types can be bound at once by including each one
separated by a space
Note, ready is valid for document and shouldn't be used for elements. To get similar functionality, use load
$("input[name='reimburse']").bind("load click", function() {
//some code
});
From the jQuery docs here: https://api.jquery.com/ready/
There is also $(document).on( "ready", handler ), deprecated as of jQuery 1.8. This behaves similarly to the ready method but if the ready event has already fired and you try to .on( "ready" ) the bound handler will not be executed. Ready handlers bound this way are executed after any bound by the other three methods above.
While you shouldn't be using deprecated methods whenever possible, I'm curious, where are you setting your event listeners?
In this example someone shows a jQuery onclick event.
My shows this:
$(function() {
$('.post').on('click', function() {
SOME STUFF
});
});
But what are the first and last line doing?
if i remove the lines, it's not working:
$('.post').on('click', function() {
SOME STUFF
});
But why? In the linked example is a second commenter. He shows this way (without first/last line).
Can someone explain this?
It is a shortcut for $( document ).ready(...)
See http://api.jquery.com/ready/
Quoting the doc :
While JavaScript provides the load event for executing code when a page is rendered, this event does not get triggered until all assets such as images have been completely received. In most cases, the script can be run as soon as the DOM hierarchy has been fully constructed. The handler passed to .ready() is guaranteed to be executed after the DOM is ready, so this is usually the best place to attach all other event handlers and run other jQuery code. [...]
All three of the following syntaxes are equivalent:
* $( document ).ready( handler )
* $().ready( handler ) (this is not recommended)
* $( handler )
That is short for document.ready. It waits until the entire document is loaded and the element with class .post can be found and bound to.
If you omit that part, the jQuery function will not find the element and your event will not work.
The first and last lines create an anonymous function. In computer programming, an anonymous function is a function defined, and possibly called, without being bound to an identifier.
In the example here it is used to set the event listener that is loaded onload of the page.
$(function() {
$('.something').on('click', function() {
alert('hello');
$(this).addClass('classOne');
});
});
$(function(){});
is jQuery short hand for
$(document).ready(function() {});
which ensures your document is ready for manipulation before executing anything within it. In many ways its similar to the browser window.onready event. See jQuery docs..
The risk if you don't wrap your jQuery code in either of these forms of the functions is that you will try and manipulate elements before they have been created by the browser. Your code is not guaranteed to fail, but you could, at the very least, get inconsistent behaviour.
This works for running the same code on both ready and resize:
$(document).ready(function() {
$(window).resize(function() {
// Stuff in here happens on ready and resize.
}).resize(); // Trigger resize handlers.
});//ready
How would you accomplish the same result using jQuery.on() ?
on can be used to wire up the resize and ready events just like any other event.
So for your case, you could create a function that has the code you want to happen for resize and ready, and then pass it to both calls to on.
If you want to keep your enclosing scope clean, you could do all this in an immediately executing function:
(function() {
function stuffForResizeAndReady(){
// Stuff in here happens on ready and resize.
}
$(window).on("resize", stuffForResizeAndReady);
$(document).on("ready", stuffForResizeAndReady);
})();
2012-07-25: There are 2 differences to be aware of when using .on() to attach ready handlers:
Ready handlers added via $(fn) and $(document).ready(fn) are "retro-fired" while ones added by .on() are not. Using those, if you add a handler after the DOM is already loaded, the fn will be fired immediately. If you add a handler via .on('ready', fn) after the DOM is loaded, it will not be fired by jQuery, but you can manually .trigger('ready') it.
When you use $(fn) or $(document).ready(fn) to add a ready handler, the fn receives jQuery as its 1st arg, allowing the familar jQuery(function($){ }) usage. If you use $(document).on('ready', fn), the 1st arg that the fn receives is an event object. In both cases this inside the fn is the document. If you were to do something abnormal like $('#foo').on('ready', fn) for the purpose of triggering, this would be the #foo element.
.ready(), .resize(), and others like .mouseover() are all just short-cuts for using the .bind() function (or .on() in jQuery 1.7+). .resize(function () {}) maps to .bind('resize', function () {}). Here is how your code would look using .on() wherever possible:
$(document).on('ready', function() {
$(window).on('resize', function() {
// Stuff in here happens on ready and resize.
}).trigger('resize'); // Trigger resize handlers.
});//ready
Here is a demo: http://jsfiddle.net/qMBtP/
Bind it both the load and resize event as below:
$(window).on('load resize', function () {
// your code
});
Much simpler - hope this helps.
In one section of code I have this:
$("#searchbar").trigger("onOptionsApplied");
In another section of code, I have this:
$("#searchbar").bind("onOptionsApplied", function () {
alert("fdafds");
});
The bind() is executed before the trigger(), but when I view the page, I never get an alert().
Why not? What am I doing wrong with events?
Perhaps your #searchbar is not part of the DOM when you execute:
// This will not work if #searchbar is not part of the DOM
// or if the DOM is not ready yet.
$("#searchbar").bind("onOptionsApplied", function () {
alert("fdafds");
});
This type of stuff often happens if .bind() is outside the document ready or because #searchbar is added dynamically.
To make sure onOptionsApplied is bound correctly even under these conditions, use .live() or .delegate():
// This can be outside document ready.
// It binds all now and future #searchbars
$("#searchbar").live("onOptionsApplied", function () {
alert("fdafds");
});
// Document ready
$(function() {
// Whatever you do....
// Make sure #searchbar is now part of the DOM
// Trigger onOptionsApplied
$("#searchbar").trigger("onOptionsApplied");
});
});
jsFiddle example
I also tried it and works fine.
put the bind function in the ready handler and then trigger the event ...it should go smooth