I'm making a small javascript framework, for a variety of reasons, including learning.
Hence, I wanted to implement "document ready" functionality, and so I went to check how jQuery fakes DOMContentLoaded on IE < 9.
Problem is, it doesn't seem to be working the way it should. Check this fiddle in IE8 and a good browser.
The logic is: apply css to make a div start red, then on "ready" make it blue, and on load make it green. Additionally, there are three img tags with fake URLs just so there is a synthetic lag between ready and load.
What should happen:
The div shouldn't be shown red for more than a split second, if at all. Ideally, the first thing seen should be blue. Then, when the browser times out on the invalid images, green.
What happens on IE8:
The div remains red until all images "load" (in this synthetic example, timeout), then goes green.
Again, I'm not exactly asking for a fix, I'm asking if it is the right thing for a framework to behave like this on IE8 (I don't care about IE 6-7 anymore), or if this is happening due to me misusing jQuery in some way.
P.S.: I know how to bind an event manually, I'm asking more about if this is expected/acceptable/a bug/my mistake.
I'm going to go with working as intended.
jQuery is using the document.readyState for browsers that don't support DOMContentLoaded. document.readyState only equals complete when the page's resources are done loading.
https://developer.mozilla.org/en-US/docs/DOM/document.readyState
There's probably a good reason why they aren't doing it on "interactive", but I'm not positive on that.
Edit: Here's your updated fiddle with a event on document.readyState == interactive
http://jsfiddle.net/PFWmS/7/
It works in both IE7 and IE8
Edit
The reason that jQuery doesn't use "interactive" is because that fires too early in IE9.
http://bugs.jquery.com/ticket/12282#comment:25
I'm thinking there may be a better way of handling that which results in IE7 and 8 proper ready timing while still working properly in IE9
Related
I made a nice website that does a lot of DOM manipulation. Works very nicely in chrome and firefox. Though the client has requested now that it also works in Internet Explorer. The latest version is good enough to start with (that would be 10.0.9200.16721 in my case).
So the adventure starts, i press F12 and see a set of pretty familiar developer tools (coming from chrome and firebug). As i'm tracking the JS code i notice that the HTML tab (with the DOM) doesn't actually update.
According to the manual here http://msdn.microsoft.com/en-us/library/ie/gg589512(v=vs.85).aspx it's "a good idea to refresh the HTML tab to get the current DOM, especially when you use dynamic elements." (d0h ??) problem is .. i can't find a button to enable automatic update of the HTML tab. So i would have to click the refresh button everytime i step into a new line of JS (never mind of real-time DOM view).
But that's not all ... every time i click the refresh button the whole DOM tree view collapses. And i have to click a bunch of pluses to view the node i'm interested in.
Does anyone have a solution for this? Because what would take days will take weeks this way...
Duplicate of How to inspect elements on dynamically created DOM by using IE developers tools
From doing a little digging aroung, it seems like this is an issue other people have reported too. This thread might be of some interest to you.
The most relevant part of it:
The problem is when you modify the dom (with or without jquery) from a callback which is called by a timeout, which is in a callback bound to an event, IE freaks out and doesn't update the dom tree in the development tool. Subsequent modifications to the changed tag in the dev tool won't have any effect.
According to my tests, it's the combination of that sequence of calls that make this happen. If the dom is modified from a settimeout callback but without being inside of an event callback, it works. If instead of settimeout you directly call a function that modifies the dom, it works.
Here's a working example of what you're saying to compound the issue.
Basically, this is an issue with IE. There is no fix available at the moment. The accepted answer on the other thread seems like a very poor workaround.
I've been trying to improve our front-end webpage performance and trying go use webpagetest for some insights. Our current page load time is 8 secs.
Here is a waterfall view of our site - http://i.imgur.com/D4sPLfs.png
The blue line indicates the load event fired which decides the load time.
And here is a waterfall of another site which has a page load time of 4secs - http://i.imgur.com/NuO1Mao.png
The waterfalls of both the sites look similar apart from one glaring difference - The blue line (load event fired) of the second one is way earlier even though a lot of content is loaded after the onLoad firing event.
Am I right in thinking that if somehow I can make the onLoad firing earlier on my site, I will see improved perceived performance for the user? If yes, how do I go about it?
We're already using lazyload.js for lazy loading images
Most of our third part js files (Google Ads / Analytics) are being called near the bottom of the body element
Thanks a lot!
There is the alternative "domready" event, which is also what jQuery uses. It is triggered when the DOM tree was built and does not wait for external resources (mostly images) to load, what the onload event does.
With that loading time it's pretty likely you are using a JS framework that is supporting the domready event already, which you should consider using, then.
You will likely have to rewrite a good portion of your scripts, mostly if you are expecting image width/height to be correctly set.
If you have access to jQuery, you can use something like that:
$().ready(function() {
loadHandler();
});
If jQuery is no solution, you should propably take a look at this extraction of jQueries domready function, because there are a lot of quirks to look out for.
I'm working on a Google Chrome extension that manipulates a webpage, but after it is either partially loaded (the DOM) or fully loaded (with images).
It seems that many sites nowadays use the
<!DOCTYPE html>
declaration, or some variation of it, but many others do not. The question is mainly about HTML doctypes...I'm not sure about the others.
Is it safe to assume that if a webpage does not have the DOCTYPE declaration, then $(window).load(); will not be fired?
In the beginning I was using $(document).ready(); (for when the DOM is loaded), but later switched to $(window).load(); (to let the images load too).
The thing is, now $(window).load(); does not seem to work if there is no DOCTYPE. $(document).ready(); seems to work on all pages, regardless of whether a DOCTYPE is declared or not.
Maybe this can be useful for others with this same issue. I searched a bit and didn't find a decisive answer. It seems that I will end up using something like this:
if (window.document.doctype != null) {$(window).load(checkEntries);}
if (window.document.doctype == null) {$(document).ready(checkEntries);}
I guess my question is... Is this normal to have to check for the DOCTYPE to know which event to use? Or am I missing something here?
Basically, why does $(window).load(); seem not to fire if there's no DOCTYPE declaration?
Basically, you shouldn't be using $(window).load(), since it's not fully supported. If you really need it, then your solution above is the best you can do. The jQuery page sums up the caveats nicely:
Caveats of the load event when used with images
A common challenge developers attempt to solve using the .load()
shortcut is to execute a function when an image (or collection of
images) have completely loaded. There are several known caveats with
this that should be noted. These are:
It doesn't work consistently nor reliably cross-browser
It doesn't fire correctly in WebKit if the image src is set to the same src as before
It doesn't correctly bubble up the DOM tree
Can cease to fire for images that already live in the browser's cache
URL: http://api.jquery.com/load-event/
The .ready() method is generally incompatible with the <body onload=""> attribute. If load must be used, either do not use .ready() or use jQuery's .load() method to attach load event handlers to the window or to more specific items, like images.
EDIT by Phrogz: This appears to be a problem with the framerate of jQuery animation when this particular complex CSS is applied. See the video at the bottom for an example of the problem.
I think is hard to copy and paste the whole code here. So I've create a fiddle for this.
To be honest, CSS is not so important on this (I putted it for have a decent grid). I also removed many functions from my original version, in fact they aren't so important.
The only one that works is by clicking on the buttons + Tracks (which call addTrack()) that adds a new track/line in the grid. Tested on Chrome, IE, and Firefox < 4 version. There isn't much problem. It's really rapid and fluid.
The problem is on Firefox 4 or 5. It's really slow to add the new track/line. It's fast like a turtle.
What the function done is to clone (copy with handler) an element trackOn, which is already written in a hidden field (tracklistOff) and add it (insertAfter) applying a fade effect. (thats means a new line in the grid).
Why this behaviour on Firefox? Too many elements to browse on the DOM I suppose. I need to get rid about this slow attitude... so what can I do?
EDIT
You can hear the difference about Chrome and Firefox (5, last version) on this video. Try to hear/see the difference between clicking on mouse and add new line (with the effect). It's too frozen (also when I try to add more tracks quicly).
Still a problem for me, any suggestion will be appreciate :)
This is not very slow for me. On my computer running Firefox 5 I can add many tracks in less than a second. What performance are you seeing? ("Fast like a turtle" is not a very quantitative measurement. :)
When you have trouble with JavaScript speed, profile it, using the Developer tools for Chrome/Safari/IE or Firebug for Firefox. Here's what I see when I run the profiler on your JSFiddle and click on the +Track button twice:
From this we can see that most of the time is spent in some set function from a mootools library. Since I don't see this library included in your code, I'm assuming the profile is tainted by JSFiddle.
So, we create a standalone test case without the unnecessary CSS and profile that. Now we see this (for several presses of the +Track button):
Almost all of your time is spent in the clone() function.
So what can you do about it? You could try pre-creating the HTML string (in JS) for a template row, and instead of using 'clone' try creating that with:
$(templateString).hide().insertAfter(...).fadeIn(600);
would it be ok if you get just the last element?
something like:
$('.tracklistOff div:last-of-type')
.clone()
.hide()
.insertAfter(($(param).parents('.trackOn')))
.fadeIn(600);
or you could addClass(last) to the last element to get only one
I just tested your fiddle on the following browsers and they all worked well: FireFox 5, Opera, Google Chrome, Safari & IE9.
There were no speed issues but each browser handled the fade slightly differently however everything else seemed to work fine. Not sure what the problem is here. It could be your computer speed but as you're on this site I presume it's decent.
I have a list of items on a page with a set of controls to MoveUp, MoveDown and Delete.
The controls sit at the top of list hidden by default. As you mouseover an item row, I select the controls with jquery
//doc ready function:
..
var tools = $('#tools');
$('#moveup').click(MoveUp);
$('#movedn').click(MoveDn);
$('#delete').click(Delete);
..
$('li.item').mouseover(function(){
$(this).prepend(tools);
});
This works great in Firefox .. the tools move into the current row, and the click events call the ajax functions. However, in IE6 and IE7 .. no click occurs. I tried unbinding on mouseout and rebinding on each mouseover .. to no avail.
I also looked into various reasons outside of javascript (e.g. transparent png conflicts, z-index, position:absolute) .. also no solution found.
I eventually needed to add a tools row to each item and show/hide on mouse over/out. Works just as well -- the only downer is that I have much more 'tools' markup on my page.
Does anyone know why IE ignores/drops/kills the mouse events once the objects are moved (using prepend)? And why rebinding the event afterwards also has no effect? Kept me annoyed for almost 2 hours before I gave up.
IE will lose events depending on how you are adding things to the DOM.
var ele = $("#itemtocopy");
$("#someotheritem").append( ele ); // Will not work and will lose events
$("#someotheritem").append( ele.clone(true) );
I would also recommend using .live() on the click events to simplify your code a little. Mouseover/out is not supported by live yet. http://docs.jquery.com/Events/live
I just spent the whole day troubleshooting events not triggering on items appended to the DOM, (IE7, jQuery 1.4.1) and it wasn't because I needed to use live() (though, good to know, Chad), nor was it because I needed to clone the items.
It was because I was selecting anchor tags that had a "#" in them like so:
var myitem = $('a[href=#top]');
My solution was to use the "Attribute Contains Selector" like so:
var myitem = $('a[href*=top]');
Fortunately I have enough control over everything that it won't likely break in the future. This isn't technically related to appended objects, but hopefully it saves someone some time.
i had a similar problem. trying to use .ready to load a div on the initial page load.
works well in FF , but not ie7.
i have found a hack that seems to get around this.
I have load call a callback, divLoaded().
In divLoaded i check the $('#targetdiv').innerText.length < 50 or whatever you think will indicate that it didnt load. If I detect that case, i simply call the function taht loads that div again.
Oddly enough, i also add a '.' to the innerText before i recall the ajax function. It seems taht sometimes we go through 3 or 4 loops before the ajax load finally takes.
This leads me to think that document.ready works pretty flawlessly in IE7, which seems to dispel a bit of a myth that it is unreliable. What really 'seems' to be happening is that .load is a little bit flakey and doesnt work well when the page is just loaded.
I am still a bit green w/ all the jQuery stuff, so take this w/ a grain of salt. Interested to hear anyone's take on my little hypothesis.
cheers
greg