Bug Tracker

Opened 6 years ago

Closed 5 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 6 years ago by dmethvin

Owner: set to mccaskey
Status: newpending

Hmm, that would be odd since our .ready() processing uses window.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?

comment:2 Changed 6 years ago by mccaskey

Status: pendingnew

That's an appealing theory. The "document" is the unprocessed XML. Once it's loaded a DOMContentLoaded fires . . . and then the XST 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?

Version 0, edited 6 years ago by mccaskey (next)

comment:3 Changed 6 years ago by dmethvin

Status: newpending

You could use console.log maybe? One for the window.load bare handler and then one inside your jQueryBug file.

comment:4 Changed 6 years ago by mccaskey

Status: pendingnew

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 6 years ago by dmethvin

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 6 years ago by mccaskey

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:7 Changed 6 years ago by dmethvin

Okay, that's good info right there. I'll dig a bit more later.

comment:8 Changed 6 years ago by dmethvin

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.

Last edited 6 years ago by dmethvin (previous) (diff)

comment:9 Changed 6 years ago by mccaskey

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 6 years ago by dmethvin

Status: newopen

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 6 years ago by mccaskey

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 6 years ago by dmethvin

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 6 years ago by visitsb@…

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 6 years ago by visitsb@…

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 6 years ago by timmywil

Component: unfiledcore
Priority: undecidedlow
Version: git1.9.1

comment:16 Changed 6 years ago by schmunzeldrache

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 6 years ago by dmethvin

Related issue, and perhaps the root cause: https://bugzilla.mozilla.org/show_bug.cgi?id=325891

comment:18 Changed 5 years ago by dmethvin

Resolution: patchwelcome
Status: openclosed

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.

Note: See TracTickets for help on using tickets.