Someone recommended here that window.onpaint be used to run some javascript before page load. I've never actually seen this before, could someone explain its usage/usefulness?
From the MDN :
onpaint doesn't work currently, and it is questionable whether this
event is going to work at all, see bug 239074.
So the usefulness is zero.
It might depend on your exact use case but if you want to run a script "before page load", the simplest solution is probably to put it in the head.
Related
I thought I should see how much I really need jQuery now. So I started by replacing
jQuery(document).on("keydown.", function(e){...})
with
document.addEventListener("keydown", function(e){...})
I believed that one was easy, but to my surprise the event was no longer fired. To investigate this a bit I entered the second version in the console. Now it worked. ;-)
That is a bit impractical, of course. I would prefer that I did not have to enter it in the console...
In the code the event listener is added right after some changes to the DOM, i e some additions. I guess the trouble might be related to this, but I have no idea what to do.
Any suggestions?
EDIT: Thanks everyone for the comments. In this particular case it would be good to get rid of jQuery (but otherwise it is no problem using jQuery of course).
I should have said that some DOM elements are added long after the page is loaded so window.onload etc is not useful here.
I should maybe also have said that I am testing this in the latest version of Chrome and for this I am not interested in backward compatibility (it is too complicated anyway in this case so I have just dropped that... ;-) ).
UPDATE: Someone asked for code. Here is an example I just tested:
document.addEventListener("keydown.test", function(e){
console.log("doc.addEL test keydown, e=", e)
});
Looking in Chrome Dev Tools at the properties of the HTML element I can see the event listener there (with the code above). It is just not fired. Seems like it is just time to write yet another bug report then. ;-)
My bad. I misread the news that event handlers now can be removed using standard syntax. They can, but the syntax is that you give the event+handler function to removeEventListener.
The syntax I used above for the event, "keydown.test", is not a valid syntax (if you are not using jQuery).
Sorry for wasting your time. Hope someone can use the answer.
Explanation
For reasons which I appreciate, as of jQuery 1.8, the load event has been deprecated, however, it was still possible to detect whether an image was loaded (even if it was in the cache) just by using certain workarounds. Therefore, the deprecation of the event is actually quite irritating as it posed as a starting point at the very least for detecting when an image has finished loading onto the page.
Nevertheless, it has been deprecated, and I am therefore asking this question with the hope that I will find an answer, thus, help me and potentially others that may soon be running into the same issue.
An Example (before jQuery 1.8)
Without using a plugin (as this should be able to be done in very little code, so a plugin is unnecessary), I would like to call a function when each image on my page is loaded.
Something like this (this will not work due to the deprecation):
$('#mn_content .column').on('load','img',function(){
console.log('loaded');
})
My Question
Is anybody aware of how to achieve this now that the load event does not exist?
Please note: If the only way to achieve this (now), is to use the Javascript new Image objects, then please do not waste your time helping me as others need your help more than I do. I am able to write this code, it just seems a bit long winded for something so basic.
I have simply asked this question to ensure there is not a way of achieving this without the use of the Javascript image objects
I will of course be very grateful for any help, I just don't want you spending much time on me when there are others that need your help more. :-)
The load event still exists, you just can't bind to it using .load anymore. Your event delegation example should continue to work on into 1.9 and 2.0 (if the browser you're testing in supports bubbling of the load event)
I personally would still use the new Image method because i don't trust that all browsers will always bubble the load event properly.
Edit: Sorry if i wasn't clear, the point i was making is that the load event is still there, you just have to properly bind to it. Since the load event doesn't bubble in all browsers (if in any browser?), you must bind the event directly to the image. I'd suggest using the method that you asked us not to provide you an example of.
This is not a real coding question, more of a real-world statement.
I have previously noted that DOMReady events are slow, very slow. So, I noticed while browsing the jQuery source that the jQuery domeready event can be trigger using $.ready(). Then I thought, placing this simple execution script just before closing the body should trigger all the "onDomReady" listeners that where previoulsy attached. And yes, it works as expected:
<script>$.ready()</script>
</body>
Here are two examples, this one measures the ms spent while waiting for DOMReady:
http://jsbin.com/aqifon/10
As you can see, the DOMReady trigger is very natively slow, the user has to wait for a whole 200-300 milliseconds before the domready script kick in.
Anyway, if we place $.ready() just before closing the BODY tag we get this:
http://jsbin.com/aqifon/16
See the difference? By triggering domready manually, we can cut off 100-300 ms of execution delay. This is a major deal, because we can rely on jQuery to take care of DOM manipulations before we see them.
Now, to a question, I have never seen this being recommended or discussed before, but still it seems like a major performance issue. Everything is about optimizing the code itself, which is good of course, but it is in vain if the execution is delayed for such a long time that the user sees a "flash of "unjQueryedContent".
Any ideas why this is not discussed/recommended more frequently?
By triggering the event yourself, you are stating to your ready() handlers that your dom has been loaded BUT it may not have been! There is no short cutting the DOM ready event. If there is indeed a long wait time, then employ the amazing debugging tools of firebug, chrome, etc.... check your resources and their timing ques. It's all there in black and white and will indicate what is taking so long (the requests, the rendering, how many resources, etc.. )
Any ideas why this is not discussed/recommended more frequently?
Placing JavaScript just before </body> has been discussed a lot, and as you know it's recommended if you're looking for faster page loads. Manually triggering the jQuery ready handlers is in fact poorly discussed. Why? Well, I don't think there is one single objective answer to that, but I'll try to outline some possibilities here:
Performance is not the main goal of jQuery (anthough it's definitely a concern), and performance freaks will usually look for lighter libraries for cross-browser DOM manipulation and event handling, or roll their own.
It's an extra step, and it doesn't look clean. jQuery tries to be clean and elegant, and recommending an extra step to initialize scripts doesn't sound like something that's gonna happen. They recommend binding to ready, so recommending to force .ready() and ignoring the actual browser event looks "wrong". Whoever is concerned about that probably knows that initializing scripts right before </body> is faster.
Optimizing DOMContentLoaded sounds like a task for browser vendors. I'm not sure why it's slower, though, and maybe there's not much room for optimization – in my understanding, calling init scripts before </body> should always be the fastest way to initialize stuff (as it's executed immediately when parsing the container <script> tag, while browsers must finish parsing the whole file before triggering DOMContentLoaded).
You probably remember that not so long ago it was common practice to have <script> blocks scattered everywhere on the HTML. Then the Web Standards movement came, and recommended more sane and maintanable ways to do things. That included bootstraping scripts from a single place – initially, window.onload, which was then considered problematic for being slow, then DOMContentLoaded and its emulations for IE8 and below. However, we still see spaghetti-HTML with scripts everywhere on a daily basis here on StackOverflow. So I'm not sure if recommending placing scripts before the end of the body is a good call today, because it may be interpreted as a license to add scripts anywhere within the body.
Finally, if you're really concerned about loading your script fast, and your code does not manipulate the DOM, the fastest way to load it is to put it in the <head> before any stylesheets. And I'm stating that just to say that there's no silver bullet, no optimal way to init scripts that is the fastest and most elegant in every scenario. I think that's why the community sticks with recommending something that looks sane and tends to create more maintainable code, instead of other better performing alternatives.
Actually, placing a function call before </body> tag makes it pointless to use jQuery's ready(). Just put native JS-wrapper function call that contains calls of all other functions that should be called on document ready.
In general, it's a working (though somewhat littering HTML code and therefore unacceptable for perfectionists) alternative for situations when author does not need/want to use jQuery at all. In such situations though, I would prefer to use native DOMContentLoaded event handler that is supported by most of browsers including IE9+ (for IE8- we can use window.load() as an acceptable fallback).
My application contains a bug, which makes script run infinitelly long. When I force script to stop, all jQuery UI elements don't answer to my actions, nor application answers to keypresses.
If I choose to open Firebug, it requires reloading page and all current application state is lost.
The thing is I can't reproduce this bug and it's kinda driving me crazy. How to find and fix such slick bug?
UPDATE. Thanks all of you for the advice. But the problem is that I can't figure out when bug happens and, hence, can't reproduce it. That's why standard procedures won't work in my case.
I have examined every while loop and recursive function calls, but haven't figured out the problem yet.
Publishing the code isn't a good idea — code listing is huge and rather complicated (a game).
POSSIBLE SOLUTION. I'll follow one of the published hints and will try to consolelog all functions that might be causing the problem. Hope it helps.
There are two main approaches for dealing with this:
Set break points and step through your code
Start commenting out certain sections of code. Once you comment out a section that eliminates the bug, start commenting out smaller pieces of that section until you arrive at the line of code that is causing the issue.
It might also help to know what you are looking for. An infinitely running script will generally result from one of two things:
A loop that never terminates.
A function that calls itself
Keeping an eye out for these things might help the debugging process go a bit more quickly. Good luck!
break your code into chunks and determine which one causes failure. like for example, if you have a form with several fields that have date-pickers and auto-completes, take them apart one by one. zero-in on who causes it.
use the debugger timeline. cruise around your site with the timeline recording your page performance. you will see in the timeline which task it taking too long. the browser may crash when you find the bug, but you will at least see a glimpse of what happened when.
try to recreate your actions. do some step-by-step checklist on how you navigate through. this way, you can trace in the code the possible path your script took when you did your move. if only JS had a back-trace like PHP, this would be easier.
try to review your code. things like loops, recursions or even two functions calling each other can cause this never-ending loop.
if you could, use a VCS tool like SVN or GIT. you can easily build n' break your code without the worry of losing a working version. you can revert easily if you use VCS.
Infinite long time, means,
I think some function is getting called recursively or some event is getting fired recursively. To track it down,
Try to put console.log in all the functions, which are getting called from window.onload or document.ready (if you are using jquery).
Use Firebug's profile, which will tell you every function call that is happening.
I always look for functions that might be being called too often or loops that never stop looping. Then, keep track of how many times your suspected functions/loops execute. Example:
var runCount = 0;
function guiltyLookingFunction(params)
{
runCount++; //increase by 1 every time this function runs
if (runCount>1000) //if this has run some insane number of times
alert("this function is the that's running wild!");
//the rest of your function's code
//same thing with loops within functions:
var loopCount = 0;
while (0!=1) //this will always be true, so the loop won't stop!
{
loopCount++;
if (loopCount>1000)
alert("this loop is to blame!");
//the rest of your loop
}
}
(replace "this function/loop" with some specific identifier if you're monitoring multiple suspects)
A) Use WebKit's (Safari, Chrome, Chromium) inspector instead of firebug - No more reload, yay!
B) Set some debug output along the way that will help narrow your problem down to the perpetrator.
Firebug. Reloading? Didn't you try to open Firebug before page loading?
I'm am doing a JS location.replace in Opera. There is a known bug that the location does not get replaced but updated when only the location.hash changes (see http://my.opera.com/community/forums/topic.dml?id=568931).
I was trying to do the following workaround:
var url = location.href.split("#")[0];
if (window.opera) {
window.history.back();
}
location.replace(url + '#' + newhash);
Unfortunately that does not seem work. Before I start experimenting with setTimeout, I wanted to check if maybe someone has a better idea.
I think the best workaround for this is to not work around it at all.
Reasoning: firstly, the script running in this page should be terminated if I use the back button, or history.back() is called. Hence, in your workaround above the script will (or should) actually stop running before the location.replace() call. We can not remember that you wanted to call location.replace() and do it on the page you've gone back to, because that would be a script injection security issue.
Secondly, even if this workaround worked I would very much recommend not using it. The reason is that Opera will eventually fix its bug. If an end user used a fixed Opera version and a page running your script, each click on one of your links would remove one entry from that user's browsing history..
For a proper solution, you could investigate history.replaceState() - a new method specified in HTML5: http://www.whatwg.org/specs/web-apps/current-work/multipage/history.html#dom-history-replacestate
Can you clarify a bit? I took the example from the forum link you posted and uploaded it here: http://people.opera.com/miket/tmp/replace.html. In Opera 11.61/Mac, it appears to work as expected.
Are you seeing something different? Can you explain your problem in more detail?