I'm loading html content via ajax onto a div (using mootools 1.11 and squeezebox, if it matters).
In the content that I load I have some JS that manipulates some of the loaded HTML objects.
Everything works fine in FF, but when I load it in IE (tested on IE7 for now) the code fails with "'null' is null or not an object.
A quick test shows that the new elements loaded by AJAX are not in the IE DOM. Loaded a div with id 'test' and when I ran document.getElementById('test') I got null. Needless to say running getElementById on original elements works fine.
Does anyone know how to solve / work around this problem?
Some more information:
I put my code inside the window 'domready'. Tried using 'load' event, but then IE never called it.
UPDATE
as advised, I checked the same script on IE8 with it's better debugging abilities.
It seems that the problem is indeed in the timing. I run my code at the windows's domReady, and it seems to run instantly, without really waiting for the DOM to be ready (in the popup window). Running the same script using the debugger, once the whole page has loaded, locates the elements with no problem.
So I guess the question now is how to make the script run at the proper time.
domready event seems to fire well before the dom is ready
load event seems not to fire at all
putting the script at the end of the file, after the HTML objects, doesn't help as well
In the Mootools AJAX options, I indicate 'evalScripts' as true, otherwise the script doesn't run at all
any ideas?
there is nothing that prevents IE from loading elements into the dom. there is also no such thing as 'domready' after updating an innerHTML property. consider this:
new Ajax("someurl", {
method: "get",
evalScripts: true,
onComplete: function() {
$("someid").setHTML(this.response.text); // load content.
}
}).request();
now, the question here is, does evalScripts run BEFORE the onComplete or after. i take it the script that you send back is relevant to the markup that you use to update?
the source code for 1.11 goes:
onComplete: function(){
if (this.options.update) $(this.options.update).empty().setHTML(this.response.text);
if (this.options.evalScripts || this.options.evalResponse) this.evalScripts();
this.fireEvent('onComplete', [this.response.text, this.response.xml], 20);
},
which indicates that scripts are evaluated after the update: and before the onComplete, so using:
update: $('somediv'),
evalScripts: true
ought to work. if it does not, then i would suggest trying:
new Ajax("someurl", {
method: "get",
onComplete: function() {
$("someid").setHTML(this.response.text); // load content.
this.evalScripts();
// or if it fails still, delay it:
/*
if (window.ie)
(function() {
this.evalScripts();
}).delay(100, this);
*/
}
}).request();
You may want to test on IE8 and use the IE Web developer tools to see what is really happening, to see if there was an error somewhere.
You can also get this plugin for IE7, though I remember it being improved for IE8.
This way you can get a better idea what is going wrong, and then update your question and we can help with less guessing.
Some test ideas:
- Did you try to use old fassion xmlHttpRequest methods to see if it works without frameworks?
- Check your document DOCTYPE, maybe you have an html/xml content type issues that affect only IE
- Are you sure the object you are trying manipulate already exist when you access it? IE is way slower than FF.
- Did you try to use some other AJAX methods or DOM manipulations to see maybe the problem is less specific?
- Did you check your HTML validity? maybe you have some malformed HTML that FF is able to parse but IE doesn't.
For what it's worth, here's a Prototype version of Dimitar Christoffs answer:
new Ajax.Request('someurl', {
parameters: param,
onComplete: function(transport) {
/* eval scripts first */
transport.responseText.evalScripts();
/* rest of onComplete code */
/* ... */
}
});
This ensures that the embedded scripts are evaluated before executing the rest of the onComplete callback (which is, as of Prototype 1.7.1, NOT the default behaviour).
There may be some version skew issues -- current squeezebox requires mootools 1.2 (and doesn't use setHTML any more, cfr here for issues another tool had with it); you sure your squeezebox and mootools are in compatible releases (and fully support IE)? Maybe just upgrading both to the latest release would fix your problem (worth trying!).
Related
I have an application which contains dijit dialog and we are loading that dialog using .show method in all browsers like mozilla ,chrome,safari but when we do same with IE7,it says zoomChart is undefined .
Note : data-dojo-id="zoomChart"
Maybe it's the Problem, that the widget wasn't ready loaded at this time.
IE handles many things in other ways the Firefox, etc. What other browsers ignore, disturbs the Ie.
UPDATE1
Possible Solution:
This one is setup at the beginning of your Html-Page right afterwards the declaration for the Scripts. In the Init-Function you can load all Modules the you later want to use. dojo/ready and dojo/domReady guarants you, that all nessessary Scripts and Nodes are loaded BEFORE it starts.
<script type="text/javascript">
require(["dojo/ready"],function(ready){
ready(function(){
init();
});
});
function init(){
require(["dojo/domReady!"],function(){
zoomChart.show();
});
}
By the way - even with this minimum of code you paste in the comments its nearly impossible to say where the error lies. Please, if the Example above wont work fot you, post all of the code is related to the problem.
Here's a link to dojo/domReady which could be helpful for you:
http://dojotoolkit.org/reference-guide/1.8/dojo/domReady.html#dojo-domready
Regards
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.
I have a webpage which loads properly formatted html forms using AJAX calls. This HTML also loads javascript code along with it and it is not working. As I am using jQuery I tried to add live() but it didn't help me. Now I need to debug this. How can I set breakpoints or watch on this code using firebug? I am using jQuery1.3 and can not deviate from it.
TIA
I'm uncertain from reading your question as to whether or not you have access to and can modify the dynamically loaded script, but if you do, add this statement:
debugger;
where you want your breakpoint.
Also note that although Firebug is perfectly capable of displaying dynamically loaded scripts, I think it hides them by default.
Also, if you have the option of using Chrome or Safari, you can just throw an exception from the point where you want to break, then set the Chrome or Safari debugger option to break on any exception. For example:
try {
throw new Error("");
}
catch () {}
I want to call some JS after the page-load, this may involve a delay and as such I want the page loaded first so content is shown... but it seems that the code in onLoad handler is called before the rendering is complete. Is there a better event I can use, which is triggered when the page is 'finished'?
To clarify, I want to run some JS after the page is rendered on-screen, so a 'post-everything event' really.
There are several points of interest along the time sequence. This generic sequence is a good overview, even though different browsers and versions implement the details a little differently. (This assumes you're using raw Javascript and need to minimize cross-browser issues; with it's comprehensive internal handling of cross-browser issues JQuery is a little different):
T0] page-begun-- The browser has started working on the page, but otherwise the environment is in flux. Your JS operations may occur in the wrong context, and simply be flushed away when the right context stabilizes. You probably don't want to try to execute any JS at all.
T1] "onLoad" event-- [however you get events: addEventListener("Load"..., window.onload=..., etc.] All parts of the page have been identified and downloaded from the server and are in the local system's memory. In order for all parts to be identified, some parsing has already occurred. (Note that "load" is a cognate of "download", not "parse" nor "render".)
You now have the right environment and can begin to execute JS code without fear of losing anything. HOWEVER, operations that try to read or manipulate the HTML [getElementById(..., appendChild(..., etc.] may fail in strange ways, or may appear to work but then disappear, or may do something different than you expected.
T2] DOM-almost-ready-- This hack is very simple and fully cross browser. Just put your JS <script>...</script> at the very end of your HTML, just before the </body> tag. Most things will work right, although attempts to append to or modify the DOM at the very end of the <body> may produce surprising results. This isn't fully correct, but it works 99% of the time. Given its simplicity and the very high probability of correct operation, this may be the way to go (at least if you don't use JQuery).
T3] DOM-ready-- [however you get events: addEventListener("DOMContentLoaded"..., window.ondomcontentloaded=..., etc.] At this point the HTML has been completely parsed and JS is 100% available, including all functions that read or manipulate the HTML [getElementById(..., appendChild(..., etc.].
T4] Render-done-- The browser is finished displaying the content on the screen. There is NOT any such event or any reasonable cross-browser version-agnostic way to detect this situation. That's just as well, as you probably don't really want this anyway. If the browser has already displayed the page on the screen and then you manipulate the DOM, you'll get a "flash", where both the before and the after are visible on the screen at least briefly. What you probably really want is the point where you can execute arbitrary JS code; that's the previous (T3] DOM-ready) point in time.
Either attach a callback to window.onload
window.onload = function(){
// your code here
};
this will fire when all resources are loaded (which might be not what you want).
Or put all of your code at the bottom the page (before the closing body tag). The code will be run when the HTML is parsed.
FWIW, here is the jQuery code. You see, the use custom event handlers for IE and the other browsers, but use window.onload as fallback:
// Mozilla, Opera and webkit nightlies currently support this event
if ( document.addEventListener ) {
// Use the handy event callback
document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
// A fallback to window.onload, that will always work
window.addEventListener( "load", jQuery.ready, false );
// If IE event model is used
} else if ( document.attachEvent ) {
// ensure firing before onload,
// maybe late but safe also for iframes
document.attachEvent("onreadystatechange", DOMContentLoaded);
// A fallback to window.onload, that will always work
window.attachEvent( "onload", jQuery.ready );
// If IE and not a frame
// continually check to see if the document is ready
var toplevel = false;
try {
toplevel = window.frameElement == null;
} catch(e) {}
if ( document.documentElement.doScroll && toplevel ) {
doScrollCheck();
}
}
As with a lot of JavaScript this will depend on which browser you are using.
As #Avitus' answer, have you looked at the execution point of JQuery's document ready event? This has been generalised across all browsers.
If you plan on using a javascript library (like jQuery) I would rather go with the $(document).ready() statement which is called once the DOM is ready to be manipulated.
The other option I see would be to include your function call at the end of your HTML page so that all the HTML content would be loaded so you can afterward execute your code safely
"The onload event waits for all binary content to download before firing. No kitty-tickilng until then."
As this post says, it is called after all binary content is downloaded, you need to listen for a ready event either using jQuery's ready, or your own function. This project looks interesting.
There are many cross browser implementations so use either jQuery or that project I linked to.
I have written my own function for my library, it uses internal methods so will not work on its own but might give you a feel for what you have to do. You can find that function here.
I'm looking for a way to debug a dynamically loaded jQuery document.ready function.
Obviously I can't just bring up the script panel and add a breakpoint with the mouse since the function does not exist there.
I've also tried adding "debugger;" to the function (without the quotes), but that did not do anything. I have ensured that the function is actually executed while I tried this.
Thanks for your help,
Adrian
Edit: I just noticed that Firebug actually breaks on debug. However, when it does so on a dynamically loaded script, it does not bring up the source code of that script as usual. Plus, the call stack ends right below my own code. I can bring up the implementation for document.ready via the call stack, but that does not really help. Is this a Firebug bug or have I missed something?
I just worked on this similar question. The solution involves adding the word debugger twice; once at the top of the external file and one more time at the top of the function that needs to be debugged.
I noticed that if the debugger word was used only once, it did not work. Example:
//myExternal.js
debugger;
function myExternalFunction(){
debugger;
/* do something here */
}
You might try placing a break point where the event is called, and then instead of click "Play", choose "Step Into" (F11). I don't have a test case in front of me, but I think this may work.
I don't know if you ever got this figured out, but in case someone else needs it...
I got around this by moving the code I wanted to debug to an external file that was linked from the main page.
In my case, I had default.aspx loading services.aspx into a content div using jQuery AJAX. Services.aspx in turn, was loading jQuery UI tab elements using AJAX from a webservice that was providing it data. The webservice code was in a file called data.js which was linked from default.aspx. I needed to debug the code that was in the header of services.aspx (that loaded the tabs with data), but couldn't ever see it in any of the available inspectors. I just moved the code I needed to a new function in data.js and called it from the header in services.aspx.
I hope that makes sense to someone who needs it!
Just encountered same behavior (Firebug ignoring debugger; statement in dynamically loaded code) in Firefox 5.0/Firebug 1.7.3.
Worked around by detaching Firebug window ("Open Firebug in New Window").
There's also a 'debugger' keyword that's supported by the IE JScript debugger, and Safari's Web Inspector, so i would be surprised ifit wasn't supported in firebug.
Basically:
// mydynamicallyloadedfile.js
... // do stuff
debugger; // triggers debugger
... // more stuff
And i would expect firebug to break at the debugger keyword