I think there's some kind of non-fatal bug in my script that's not allowing me to a/ debug the script with Firebug and b/ causes Firefox to constantly display a Connecting... (with the swirly) while I'm on the page. The script seems to run fine though.
Any ideas what could cause that?
<script type="text/javascript">
var xmlHttp;
var xmlDoc;
loadXMLFile();
function loadXMLFile()
{
xmlHttp = new window.XMLHttpRequest();
xmlHttp.open("GET", "myFile.xml", true);
xmlHttp.onreadystatechange = StateChange;
xmlHttp.send(null);
}
function StateChange()
{
if ( xmlHttp.readyState == 4 )
{
xmlDoc = xmlHttp.responseXML;
processXML();
}
}
function processXML()
{
var firstNames = xmlDoc.querySelectorAll("name");
if (firstNames == null)
{
document.write("Oh poo. Query selector returned null.");
}
else
{
for (var i = 0; i < firstNames.length; i++)
{
document.write(firstNames[i].textContent + "<br>");
}
}
}
</script>
All the code in your page is parsed, but not executed before the page is completed. This happens, since you're calling document.write() from onreadystatechange event handler function rather than parsing time.
In this case document.write() implicitly calls document.open(), which wipes all the code out of the page, and only what is left is the text written by document.write(). Also document is left open, which causes the browser being "busy". This can be avoided by using document.close(), but it won't prevent the original content to vanish.
You need to add an element to the body and then use some "real" DOM manipulation method. Something like this:
<div id="qResult"></div>
Then instead of document.write():
document.getElementById('qResult').innerHTML = WHAT_EVER_NEEDED
Related
I have the following generic Ajax response writer which I recently added some logic to, in order to dynamically parse the results for script objects, and run them when I find them using jQuery.globalEval().
Here is the code:
//Generic Results Writter method for Ajax Calls
function writeAjaxResponse(targetId, response) {
document.getElementById(targetId).innerHTML = response;
try {
var dom = $j(response);
dom.find('script').each( function(){
$j.globalEval(this.text || this.textContent || this.innerHTML || '');
});
} catch (e) {
console.error("Error parsing for script reloads: "+e);
}
}
This solution works very nicely the first time its called. However writeAjaxResponse(targetId, response); is called each time a user loads some dynamic Ajax content. And unfortunately after the first time, the scripts are no longer loaded. To be clear, after the server side generated page is loaded, there are numerous links on the page which the users may click, which invoke this handler for the Ajax response.
No error occurs, and no console.error() is written.. The Ajax data loads as normal, its just that the scripts in the response are no longer loaded.
In debugging, $j.globalEval is still getting called and this.text still has the script content in it, and the data looks correct, but still no joy.
Any light someone could shed on this would be very much appreciated!
Adding main ajax call for GET for reference:
function doAjaxGet(targetId, getUrl, handler) {`
var xmlhttp;
if (window.XMLHttpRequest) {
// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = new XMLHttpRequest();
} else {
// code for IE6, IE5
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
try {
handler(targetId, xmlhttp.response);
}
catch (err) {
alert("Failed calling handler, detail: " + err + " Got responseText: " + xmlhttp.responseText);
}
}
}
xmlhttp.open("GET", getUrl, true);
xmlhttp.send(null);
}
i have a span with the same value..
echo "<span id='msgNotif1' class='badge' style='position:relative;right:5px;bottom:10px;'>".$number."</span>";
where $number have a value..
and my js code is..
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
var val = xmlhttp.responseText;
//alert(val);
document.getElementById("msgNotif1").innerHTML = val;
//document.getElementById("msgNotif2").innerHTML = val;
alert(val);
//document.getElementById("msgNotif3").innerHTML = xmlhttp.responseText;
}
}
xmlhttp.open("GET", "some page", true);
xmlhttp.send();
the problem is the value still remains and do not change,
trying to uncomment the first alert shows an alert with the right value, but when i try to comment it the second alert never executed, giving me an idea that the document.getelementbyid().innerhtml is the one that is not working, been with this for a few hours,
any help will be appreciated.
thanks in advance
Your error message Cannot set property 'innerHTML' of null" means that:
document.getElementById("msgNotif1")
is returning null. That can happen for several possible reasons:
There is no element in your page with id="msgNotif1".
You are calling this code before your document has finished loading and thus the element with id="msgNotif1" has not yet loaded. This can commonly happen if you execute your code in the <head> section of the document rather than at the very end of <body> or in response to the DOMContentLoaded event.
Your content is dynamically loaded (not in the original page HTML) and you are calling document.getElementById("msgNotif1") before your dynamic content has been loaded.
You have some HTML errors which are preventing the proper parsing of your HTML that contains the element with id="msgNotif1".
For a general purpose description of how to run Javascript after the current page has been loaded without using a framework like jQuery, see this answer: pure JavaScript equivalent to jQuery's $.ready() how to call a function when the page/dom is ready for it
You are receiving this error in your console because it doesn't exist at the time your script is running. This can be caused if the element hasn't been loaded when your script is running, if your IDs aren't the same, or if the element doesn't exist in your html. If you are referencing the element before it loads, add a function that executes when your page loads.
You can use JQuery
$(document).ready(function(){
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
var val = xmlhttp.responseText;
//alert(val);
document.getElementById("msgNotif1").innerHTML = val;
//document.getElementById("msgNotif2").innerHTML = val;
alert(val);
//document.getElementById("msgNotif3").innerHTML = xmlhttp.responseText;
}
}
xmlhttp.open("GET", "some page", true);
xmlhttp.send();
});
or with pure Javascript to create the event.
window.onload = function(){
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
var val = xmlhttp.responseText;
//alert(val);
document.getElementById("msgNotif1").innerHTML = val;
//document.getElementById("msgNotif2").innerHTML = val;
alert(val);
//document.getElementById("msgNotif3").innerHTML = xmlhttp.responseText;
}
}
xmlhttp.open("GET", "some page", true);
xmlhttp.send();
};
Valid points have been brought up in that doing Ajax requests with pure Javascript takes much more code than if you were to use JQuery. This is the reason why I (and many others) use JQuery for all the Ajax requests performed. JQuery has many methods for Ajax that will save a lot of time and code and in the long run will reduce your file size by a few bytes since, with JQuery, the code is reused.
I understand that jQuery will not run when the DOM content is being loaded via AJAX. But I'm confused as to the reason why. My understanding was that the DOM elements didn't exist at the time the jQuery was initiated therefore it won't find the correct IDs or classes.
But I have a situation where the jQuery is only called AFTER all the content has been loaded via AJAX. yet it still does not work.
Here is my code. I am trying to get the function decorateGains() to run after AJAX completes.
loadData('7-days'); // Runs the default AJAX for 7 days
function loadData(type){
var xmlhttp;
if (window.XMLHttpRequest){xmlhttp=new XMLHttpRequest();}
else{xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");}
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200){document.getElementById("home-table").innerHTML=xmlhttp.responseText;}
}
xmlhttp.open("GET","actions/get-data-"+type+".php",true);
xmlhttp.send();
decorateGains();
}
You can see that I am including a call to the function decorateGains() right at the end of the loadData() function.
The decorateGains() function does run, as I can see my console message. However it does not do the task that it should.
function decorateGains() {
console.log('here');
$(".gains").each(function() {
var num = +($(this).text());
if (num > 0) {
console.log('here');
$(this).addClass("positive");
}
if (num < 0) {
console.log('here');
$(this).addClass("negative");
}
});
}
(The script searches for all elements with a class of .gains and adds a new class of positive or negative depending on the content of the element. Essentially it decorates the .gains element to be red or green depending on whether the number is negative or positive).
This is because the AJAX call is asynchronous. The request has not been completed (and therefore the new content has not been appended to the DOM) when you call your decorateGains() function. You need to place the call to the function inside the onreadystatechange handler, after setting the innerHTML:
loadData('7-days'); // Runs the default AJAX for 7 days
function loadData(type) {
var xmlhttp;
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest();
} else {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
document.getElementById("home-table").innerHTML = xmlhttp.responseText;
decorateGains(); // <-- move this in here
}
}
xmlhttp.open("GET", "actions/get-data-" + type + ".php", true);
xmlhttp.send();
}
I have a problem with javascript in an ajax call
my script looks like this:
<html>
<body>
<div>contains large files to load</div>
<script type="text/javascript">
window.onload = function() {
alert('content is completely loaded');
}
</script>
</body>
</html>
When I reload the page it is working, but when I am dynamically loading this file with an ajax call.
my code to actually load and execute all scripts from the ajax call:
var tmp;
tmp = document.implementation.createHTMLDocument();
tmp.body.innerHTML = xmlhttp.responseText;
var scripts = tmp.getElementsByTagName('script');
var scripts_length = scripts.length;
for(i = 0; i < scripts_length; ++i) {
var script_tag = document.createElement('script');
script_tag.setAttribute('src', scripts[i].getAttribute('src'));
script_tag.setAttribute('type', 'text/javascript');
script_tag.setAttribute('charset', 'utf-8');
document.body.appendChild(script_tag);
}
how can I let all scripts execute when someone refreshes the page and also when the content is loaded with ajax?
so: my scripts are loading but not executing because window.onload, but window.onload can't be removed because then the page refresh does not work anymore
You're lacking an eval function in your code, cause your described method only adds the scripts from the response to the page. You can try with the following function
// this function create an Array that contains the JS code of every <script> tag in parameter
// then apply the eval() to execute the code in every script collected
function parseScript(strcode) {
var scripts = new Array(); // Array which will store the script's code
// Strip out tags
while(strcode.indexOf("<script") > -1 || strcode.indexOf("</script") > -1) {
var s = strcode.indexOf("<script");
var s_e = strcode.indexOf(">", s);
var e = strcode.indexOf("</script", s);
var e_e = strcode.indexOf(">", e);
// Add to scripts array
scripts.push(strcode.substring(s_e+1, e));
// Strip from strcode
strcode = strcode.substring(0, s) + strcode.substring(e_e+1);
}
// Loop through every script collected and eval it
for(var i=0; i<scripts.length; i++) {
try {
eval(scripts[i]);
}
catch(ex) {
// do what you want here when a script fails
}
}
}
the complete article is available here http://coursesweb.net/ajax/execute-javascript-code-ajax-response_t
attach an onload event handler to the body tag like this or otherwise use an eventListner.and to check if when conetent is loaded by ajax.check for the onreadystatechange. for example
function makerequest(serverPage, objID) {
var obj = document.getElementById(objID);
obj.innerHTML = '<b>Loading....</b>';
xmlhttp.open("GET", serverPage);
xmlhttp.onreadystatechange = function() {
//perform mystunts
}
}
xmlhttp.send(null);
}
You can use the status code to check whatever you want to.
see Ref from w3school.com
The onreadystatechange event
When a request to a server is sent, we want to perform some actions based on the response.
The onreadystatechange event is triggered every time the readyState changes.
The readyState property holds the status of the XMLHttpRequest.
Three important properties of the XMLHttpRequest object:
onreadystatechange Stores a function (or the name of a function) to be called automatically each time the readyState property changes
readyState Holds the status of the XMLHttpRequest. Changes from 0 to 4:
0: request not initialized
1: server connection established
2: request received
3: processing request
4: request finished and response is ready
status 200: "OK"
404: Page not found
I load html & JS code dynamically from webservice. I use prototype update method:
placeholder.update(result.Static.html); // which also include javascript code
Immediately after i loaded code, everything works fine:
ProRegResetForm();
alert('reset done');
however, from control declared as
Reset
I am having error: ProRegResetForm is not defined.
SIMPLIFIED TEST CODE (which is also not working):
<script type="text/javascript">
var defkeyword_ZipCode = 'Zip Code';
</script>
test link
It was correct to write code like:
test link
<script type="text/javascript">
functoin somethingcomplex() {
bla bla bla
}
$('element').onclick = function() { somethingcomplex(); }
</script>
Given that your 'simplified test code' did not execute, you likely have a javascript error elsewhere in your code. Javascript code that follows an exception will not execute.
Have you tried examining the script prior to your snippet (as it appears on the client) using Firebug or IE Developer Toolbar?
I had a similar problem and solved it by delimiting the HTML response from the JavaScript with a '^' and inserting them separately.
//=============================================================================
function injectJavascript(src)
{
var scripts = document.getElementById("scripts");
var javascriptSrc = document.createElement("script");
javascriptSrc.setAttribute("type", "text/javascript");
javascriptSrc.setAttribute("language", "JavaScript1.2");
javascriptSrc.innerHTML = src;
scripts.appendChild(javascriptSrc);
}
//=============================================================================
function insertHtmlAndScript(target)
{
if (req.readyState == 4) // 4 == "loaded"
{
if (req.status == 200) // 200 == "Ok"
{
var resp = req.responseText.split("^");
div = document.getElementById(target);
div.innerHTML = resp[0];
injectJavascript(resp[1]);
}
else
{
alert("Could not retreive URL:\n" + req.statusText);
}
}
}
//======================================================================
The only reason I can think of that this works while your injection does not is that the HTML vs. JavaScript interpretation is threaded such that the JavaScript can not bind properly... but that's just a guess.