Opened 10 years ago
Closed 9 years ago
#13193 closed bug (patchwelcome)
document.ready not firing on Firefox, Opera with XSLT and XML
Reported by: | mccaskey | Owned by: | mccaskey |
---|---|---|---|
Priority: | low | Milestone: | None |
Component: | core | Version: | 1.9.1 |
Keywords: | Cc: | ||
Blocked by: | Blocking: |
Description
With this JavaScript, jQueryBug.js,
window.onload=alert('window.load'); $(document).ready(function(){ alert('jQuery(document).ready'); }); $(window).load(function(){ alert('jQuery(window).load'); });
this XML
<?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet type="text/xsl" href="jQueryBug.xsl" ?> <library> <book>My book</book> <book>My other book</book> </library>
and this XSL transformation, jQueryBug.xsl,
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="xml" indent="no" encoding="utf-8" /> <xsl:template match ="/"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>jQuery bug</title> <script type="text/javascript" src="jquery.min.js" ></script> <script type="text/javascript" src="jQueryBug.js" ></script> </head> <body> <xsl:apply-templates /> </body> </html> </xsl:template> </xsl:stylesheet>
load the xml file. $(document).ready fires in IE 9 and Chrome 23, but not in Firefox 18 or Opera 12.
The problem was also noticed here: http://forum.jquery.com/topic/document-ready-with-xslt-in-xhtml
Both window.load's fire, but not the document.ready. It will fire if the XSLT output is changed from xml to html, but it should work for xml as well.
Change History (18)
comment:1 Changed 10 years ago by
Owner: | set to mccaskey |
---|---|
Status: | new → pending |
comment:2 Changed 10 years ago by
Status: | pending → new |
---|
That's an appealing theory. The "document" is the unprocessed XML. Once it's loaded a DOMContentLoaded fires . . . and then the XSLT replaces all of the DOM with results of the transform. Something like that?
I'll need to learn how to monitor events in Firefox using something other than alert(). I never use FF. Can you give me any suggestions? Is there a timeline or console log?
comment:3 Changed 10 years ago by
Status: | new → pending |
---|
You could use console.log
maybe? One for the window.load
bare handler and then one inside your jQueryBug file.
comment:4 Changed 10 years ago by
Status: | pending → new |
---|
I'm a little outside my comfort zone here. . .
I put this in the jQueryBug.js
console.log("beginning of JavaScript"); window.onload=console.log("window.onload"); document.addEventListener('DOMContentLoaded', function() { console.log('DOMContentLoaded'); }); $(document).ready(function(){ //alert('jQuery(document).ready'); console.log('jQuery(document).ready'); }); $(window).load(function(){ //alert('jQuery(window).load'); console.log('jQuery(window).load'); }); console.log('end of javaScript');
When I put that in the <head> of a plain HTML file and load that file, this appears in the console:
beginning of JavaScript window.onload end of javaScript jQuery(document).ready DOMContentLoaded jQuery(window).load
When that jQueryBug.js is loaded through that original XSLT transform, this appears in the console:
beginning of JavaScript window.onload end of javaScript jQuery(window).load
Is that of any value?
comment:5 Changed 10 years ago by
Pretty close!
window.onload=console.log("window.onload");
That line should be:
window.onload=function(){ console.log("window.onload"); };
Otherwise the function will be run immediately. Make that change and give it another try.
comment:6 Changed 10 years ago by
I may not know what I'm doing, but I can follow directions.
After making that change, here are the results for jQueryBug.js in the <head> of an HTML file:
beginning of JavaScript end of javaScript jQuery(document).ready DOMContentLoaded window.onload jQuery(window).load
Here are the results when jQueryBug.js is loaded through that original XSLT transform:
beginning of JavaScript end of javaScript window.onload jQuery(window).load
Awaiting further instructions, sir.
comment:8 Changed 10 years ago by
Oh, but I forgot to ask which version of jQuery you're using.
Also note that the native DOMContentLoaded didn't work, so jQuery is only going to fall back to the load event anyway.
comment:9 Changed 10 years ago by
I found this with 1.7.3 then moved to 1.8.3 but found the same behavior there as well.
Does "only going to fall back to the load event anyway" mean that in a case where DOMContentLoaded isn't available (or isn't seen before window.load unexpectedly appears), jQuery(document).ready will (or should) fire concurrent with jQuery(window).load?
comment:10 Changed 10 years ago by
Status: | new → open |
---|
Marking the ticket open for now, but I don't have the ability to research it now. It seems like the code should be falling back to the load event.
Can you provide links to the files you're using?
comment:11 Changed 10 years ago by
No, sorry, I can't. But it's pretty easy to reproduce, including with the test case I posted in the ticket.
comment:12 Changed 10 years ago by
May be related to this? https://bugzilla.mozilla.org/show_bug.cgi?id=858850#c8
And while parsing an application/xhtml+xml response produces an HTMLDocument, the output of XSLT seems to always be an XMLDocument.
comment:13 Changed 10 years ago by
I have submitted a pull request https://github.com/jquery/jquery/pull/1247 to address this one. Apparently, the ready handler is correctly firing on DOMContentLoaded under these circumstances, so there is no question about window.load fallback.
There appears to be some promise resolution not working, and I haven't figured out why. Hence, I have added patch to core.js to ensure all pending promises are resolved.
comment:14 Changed 10 years ago by
Just to add, since this issue isn't a blocker for majority of users, this fix at best gives some hint at what makes it go away. The issue appears to be inside jQuery.ready.promise().done( fn ), or more specifically core.js, 810: readyList as jQuery.Deferred() instance's done() invocation, which somehow shows readyList.state() as 'pending', yet fn doesn't fire at all.
Some insights into root cause might be needed, actually I think it might be a simpler fix on Deferred() implementation at best.
I'd be happy to create unit tests in meanwhile for that case. I could be wrong, but since currently existing tests pass, that ensures that $(document).ready contract, and overall jQuery behavior passes.
comment:15 Changed 10 years ago by
Component: | unfiled → core |
---|---|
Priority: | undecided → low |
Version: | git → 1.9.1 |
comment:16 Changed 10 years ago by
Problem seems to exist also with jQuery 1.8.1 & 1.10.0:
XSLT generates HTML from XML, but $(document).ready() does not fire on Opera 12.15
Since I see the issue also with 'xsl:output method="html"' I think this is an issue for everyone, whose using XSLT and jQuery (unless you're not willing to ignore Opera)
comment:17 Changed 10 years ago by
Related issue, and perhaps the root cause: https://bugzilla.mozilla.org/show_bug.cgi?id=325891
comment:18 Changed 9 years ago by
Resolution: | → patchwelcome |
---|---|
Status: | open → closed |
Given that XSLT seems to be on its way out in Chrome (according to this) it's unlikely we'll try to chase this down. If someone does and it's fixable with a small amount of code, let us know.
Hmm, that would be odd since our
.ready()
processing useswindow.load
as a fallback. My suspicion is that by the time the browser renders that template with the script tag, the load event has already fired and jQuery never sees it. Could you create some test cases to confirm or deny that?