Every JavaScript developer sooner or later faced with case when page elements unavailable in document.onready event. It's happens because onready fired to soon, especially when most of the page parts loaded dynamically (with AJAX). I work with Drupal 7 now. Drupal does not provide Ajax callback, it's seems to be you need to write custom callbacks.
And my question is: what is the most appropriate solution for that case?
Usually I apply
jQuery(document).ready(function(){
setTimeout(function tmr(){
//Wait for any or task specific element will be available
if (jQuery('.bxslider').length) {
//Code here
do_code();
} else
setTimeout(tmr, 1000);
}, 10);
Or better write a callback? Or no different at all?
Attach your js behaviors like this:
Drupal.behaviors.nameOfYourModule= {
attach: function (context, settings) {
// your code here
}
};
This way your code will be executed on every request including AJAX requests.
For more information see this blog post on the subject.
Related
We have started using jquery load in our site to load contents into a div rather than re-loading whole page. However in the complete function we have a method that re-applies various bindings. Is it possible to provide load method with a default complete function? So developers don't have to specify it in the jquery load complete function.
As we currently are providing a lot of duplicate complete functions
E.g.
$('#Target').load(callBackRedirect, function () {
ApplyBindings('#Target');
});
These bindings can't be applied using on and need to be re-applied on page loads. We also do some other work that we want to do on every page load.
The answer is no.
You need the callback because that's what the method calls when the request is done.
This works with on method to, you might be doing something wrong out there in the code.
You could create a helper function for this.
function loadSomething(targetElement, uri,callback) {
targetElement.load(uri, callback);
}
loadSomething(
$('myElement'),
'mylink.com/content',
function() {
applyBindings($(this));
}
)
Yes. Check out the list of Global AJAX Event Handlers.
e.g.
$(document).ajaxComplete(function() {
alert('Triggered ajaxComplete handler.');
});
That said, you shouldn't need to reapply your bindings after an AJAX call. If you need to do this, you're probably doing something wrong. Check out jQuery.on, which explains how to bind to content which is added dynamically.
Try $.ajaxSetup:
$.ajaxSetup({
complete: function() {
ApplyBindings('#target');
}
});
EDIT
You could also make a named function like:
var ajaxApplyBindings = function() {
ApplyBindings('#Target');
// anything else...
};
And then pass it to load:
$('#Target').load(callBackRedirect, ajaxApplyBindings);
I'm optimizing a page, but I can't tell the difference in results between these (the first one is obviously faster, but I'm not sure if it slows the rendering of the page a little or something):
This one will start the request ASAP, and modify the DOM on document ready:
<script>
$.ajax({
url: '/some-url',
success: function() {
$(document).ready(function() {
// do something
});
}
});
</script>
</body>
This one will start the request on document ready:
<script>
$(document).ready(function() {
$.ajax({
url: '/some-url',
success: function() {
// do something
}
});
});
</script>
</body>
Which one is recommended?
Best practice here is to start the Ajax request as soon as possible, but start modifying the DOM only when the document is ready (DOMContentLoaded). To do that, you might use jQuerys Deferred objects which are wired up with jQuerys extended jXHR objects.
<script>
var req = $.ajax({}),
docReady = jQuery.Deferred();
$(function() {
docReady.resolve();
});
$.when( req, docReady ).done(function( data ) {
// read the returned data and modify the DOM
});
</script>
It would be a waste of time to wait for starting the request until the DOM is ready. The XHR request has no business and interest in whats going on with the DOM.
It just makes more sense to decouple those two things entirely. If for some reason the DOM needs a very long time before its ready, you didn't waste the time to let the HTTP request run and collect its data. The other way around, if the request is very slow, you would waste time aswell. So your current snippets are like
DOM ready
-> XHR request
-> Do something useful
Whereas my example is like
DOM ready
XHR request
-> Do something useful as soon as the DOM and request are ready
Since $.ajax doesn't depend on the DOM in any way, there's no reason why you can't call it as soon as possible. In that case, I would put it in the <head> section and call it as soon as its dependent script/script files are done (meaning at least jQuery library). Firing the AJAX request sooner means the response has the ability to come back sooner - it may not be the case that it actually happens, but that's not important.
Checking to sure the DOM is ready inside of success is necessary for you, and it's the quickest way for your code to execute. Using $.when( req ).done(function () {}) creates 2 more jQuery method calls that may or may not significantly delay the execution of your success code - it will delay it, but it will probably be insignificant.
Also, your example where you use document.ready in your success method creates the possibility that the DOM is ready and can execute immediately (in the case that the AJAX request completes before the DOM is fully loaded, which I wouldn't expect). In jAndy's example where document.ready runs immediately after $.ajax, it guarantees that it will bind an event handler for the document being ready...which means it has to be stored (causing the DOM to be ready later) and then looked up later when the event occurs, and executed. Again, the difference is possibility vs. guarantee...and all is probably insignificant (as long as you don't use your second example).
In this simple example, both versions should do. Which one is better depends on your page and other scripts.
If your script is a little more complex, and you need to pass data to the ajax-request which has to be fetched from the page, and your page is not ready at that moment - you will have an error.
Another thing is, that any script on your page will block the browser while it is processed, so a more complex code without doc-ready around it may lead to a short stop in the page-render-process.
In most cases I prefer to let the browser to load all HTML, CSS and the JS - and after that start my progressive enhancement and loading of additional content.
But again - in this simple case - I don't see much of a difference.
I tried looking for the answer, and this is my first post, so bear with me if I mess up in some way.
Basically my problem is this: I'm writing an extension for Chrome that uses jQuery. I have another extension that makes a timed $.ajax() request every 10 seconds. I need to find a way to run my code every time that timed ajax request and its callback function completes. Setting a timer for my own script can be done, although that's rather half-assed and doesn't work as well.
The problem can be illustrated thus:
//extension 1
function timedFunc() {
setTimeout(doStuff, 10000);
};
timedFunc();
//extension 2
//code to be run every time doStuff completes
I feel like there may be a very elementary solution to this problem but I appreciate the help.
There is (was) an event called DOMSubtreeModified.
But it has been deprecated so at tho moment there are really only workarounds available.
Why is the DOMSubtreeModified event deprecated in DOM level 3?
I can't advise on using this event as it hasn't even been implemented in all browsers.
But what you can do (easily) is just trigger you own event with all your ajax call!
Example:
fire your event when (any) ajax call completes:
$(document).ajaxComplete(function() {
$(document).trigger('domChanged');
}
and listen to it:
$(document).on('domChanged',function() {
alert("i changed the DOM tree!");
});
btw:
taken that you just want to react to ajax calls compleing... just use the .ajaxComplete() event:
http://api.jquery.com/ajaxComplete/
i didn't really understand what you are trying to say but i did understand your question in the title so here is my modest answer:
// a global variable for the documents content
var content=document.documentElement.innerHTML;
// return true if the document content has changed
function documentChanged(){
return content==document.documentElement.innerHTML;
}
I have code like this:
$(document).ready(function () {
$('.accessLink')
.bind('click', accessLinkClick);
$('#logoutLink')
.click(function (e) {
window.location = $(this).attr('data-href')
});
});
Functionality for each part of my site is divided into a number of small files and when the site is deployed these are mimified and joined up.
Each of these small files which number up to ten wait on $(document).ready. Can anyone tell me if there is much overhead in doing this. Splitting my code into functional areas has meant the code looks easy to maintain but I am just wondering about overhead now that I am using jQuery 1.8.1
Update:
Based on the answers I started to code like this:
$(document).ready(function () {
accessButtons(); // login, register, logout
layoutButtons();
themeButtons(); // theme switcher, sidebar, print page
});
with each function then coded as:
function accessButtons() {
$('.accessLink')
.bind('click', accessLinkClick);
$('#logoutLink')
.click(function (e) {
window.location = $(this).attr('data-href')
});
};
Here's the difference between 10 $(document).ready() calls versus one that then calls 10 initialization functions.
With the 10 calls, you get:
10 calls to $(document).
10 calls to the .ready() method.
One event listener for the DOM ready event
When the DOM ready event fires, it then cycles through an array of callbacks and calls each callback passed to .ready().
If you have one $(document).ready() that then called all 10 of your initialization functions, you would have this:
1 call to $(document).
1 call to the .ready() method.
One event listener for the DOM ready event
When the DOM ready event fires, it then calls your one ready handler.
Your ready handler then calls the 10 initialization function calls.
So, the difference is approximately the time it takes to construct 9 extra jQuery objects and make 9 extra .ready() method calls. In extreme cases this could be noticeable, but it is unlikely that you would see a difference in practice.
If the code needs to be executed in order, then they should in the same dom ready callback function, otherwise, you could divide them into different dom ready callback.
Only use the .ready() function to wrap all code that needs to be run once ALL other code is loaded and once the page is ready. If you have any libraries that can run on their own and do not need to do anything with the DOM then you shouldn't need to put them into a ready call.
Performance goes down when using many $(document).ready() calls, but it doesn't seem to be too bad, and on some browsers it doesn't seem to affect performance very much at all. The linked page has test results for several popular browsers when using $() to modify a large DOM.
Due to the performance issue, I personally create separate functions for each page. So instead of having $(document).ready() run multiple times, you just fire a function on each page. This way, i tend to generally have $(document).ready() only run twice, once for globals, then once for the particular page.
function ContactForm() {
$(function () {
// Contact form page specific stuff.
});
}
In my View (by the sounds of your question, im assuming you're using MVC), what i do is add the following:
#section scripts {
#Scripts.Render("~/bundles/ContactForm")
<script type="text/javascript">ContactForm();</script>
}
This is my main question for ages and i never got a 100% answer (in some of the cases i managed to do what i want) and now i realize that i need a proper 100% answer to proceed.
I'm running Prototype-UI (Draggable windows and stuff) and i need to know how can i run jQuery scripts inside of these windows while fetching the content with Ajax.
Here is an example of what worked out for me:
window.show_confirm = function(id) {
var r = confirm("huhuhu");
if (r == true) {
jQuery.post('huhuhu.php', {'id':id}, function(data){});
jQuery('#_'+id).animate({
height: "0px",
opacity: 0.0,
}, 1500 );
} else {
alert("Item ["+id+"] was not deleted.");
}
}
Here is an example of something that doesn't work:
jQuery(function() {
jQuery(".line").peity("line");
});
Now the working example needs a click to run the function (this way users can only run it AFTER they opened the window).
In the second case this function needs to run from the moment the document is ready (basically when its executed there is still no DOM with .line class.)
Any help?
I'm a little confused as to what you're asking, but from the last part I'm assuming it's how to call a jQuery function on is created that don't exist yet.
jQuery is an imperative library, not a declarative one – as a rule it only operates on currently existing elements (with the exception of "live" event handlers but that's not your use case). You need to make the call after the matching element is created somehow – either by doing the call after an AJAX request, or by using something like livequery to intercept DOM element creation.