PDA

View Full Version : How do I load files into multiple DIV layers using AJAX?



CiaNZ
05-17-2008, 01:18 PM
I want the page to load multiple external PHP files into multiple DIV layers, however no matter what I try I can only get one DIV layer to load when the page is first loaded. If you refresh however, both DIVs will load. Very weird!

All the JavaScript is in the source -- any help is very much appreciated!!

http://www.getbweb.com/vidsite/

jscheuer1
05-17-2008, 03:44 PM
Your main problem looks to be that you are running two requests at once, and that you are using the same global variables and functions to do so. Since a request and its fulfilment are rarely instantaneous, variables and/or functions are conflicting.

Just as an example:


function openInMain(file) {

Parent = document.getElementById("main");

xmlHttp=GetXmlHttpObject();
if (xmlHttp==null)
{
alert ("Your browser does not support AJAX!");
return;
}
var url="http://www.getbweb.com/vidsite/" + file;
xmlHttp.onreadystatechange=stateChanged;

xmlHttp.open("GET",url,true);
xmlHttp.send(null);
}


function openInSide(file) {

Parent = document.getElementById("side");

xmlHttp=GetXmlHttpObject();
if (xmlHttp==null)
{
alert ("Your browser does not support AJAX!");
return;
}
var url="http://www.getbweb.com/vidsite/" + file;
xmlHttp.onreadystatechange=stateChanged;

xmlHttp.open("GET",url,true);
xmlHttp.send(null);
}

The two pairs of colored variables in the above functions (one set red, the other green) are undeclared and in the global scope. Whichever function runs first will generally get its values overwritten by the second function before the first one has completed fetching its content. The reason why they may sometimes work together after a refresh (they wouldn't for me) is that once the browser has cached one of the requests from the server, it will load much faster, minimizing the chance that there will be a conflict.

The fact that they both:

xmlHttp.onreadystatechange=stateChanged;

means that data will further be subject to collision in that function (stateChanged).

One thing you could do is wait until one is finished and then call the other. So, in the body tag have:


<body onLoad="openInMain('mainshowcase.php');">

And at the end of stateChanged() have something like:


function stateChanged() {
if (xmlHttp.readyState==4)
{
tid=xmlHttp.responseText;
Parent.innerHTML = tid;
if(Parent.id=='main'&&document.getElementById('side').innerHTML.replace(/\s/g,'')=='')
openInSide('showcase.php');
}
}


However, there are probably better ways to overcome these issues.

jscheuer1
05-17-2008, 04:17 PM
Please see also my previous post in this thread. This approach (untested) if it were to work at all should be able to accommodate multiple requests at the same time:


function openInMain(file) {
var url="http://www.getbweb.com/vidsite/" + file;
var id='main';
new GetXmlHttpObject(url, id);
}


function openInSide(file) {
var url="http://www.getbweb.com/vidsite/" + file;
var id='side';
new GetXmlHttpObject(url, id);
}

function GetXmlHttpObject(url, id) {
this.xmlHttp=null;
try
{
// Firefox, Opera 8.0+, Safari
this.xmlHttp=new XMLHttpRequest();
}
catch (e)
{
// Internet Explorer
try
{
this.xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e)
{
try{
this.xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
}catch(e){this.xmlHttp=null;}
}
}
if(this.xmlHttp!=null){
var c=this;
this.el=document.getElementById(id);
this.xmlHttp.open("GET",url,true);
this.xmlHttp.onreadystatechange=function(){c.stateChanged();};
this.xmlHttp.send(null);
}
else alert('Your browser does not support AJAX!');
}


GetXmlHttpObject.prototype.stateChanged=function () {
if (this.xmlHttp.readyState==4)
{
var tid=this.xmlHttp.responseText;
this.el.innerHTML = tid;
}
}


Then:


<body onload="openInMain('mainshowcase.php'); openInSide('showcase.php');">

should be successful the first time, as long as the files are available, etc. Even if it does work, the code could use refinement. However, I left it in this form to show as clearly as possible the transformation from your original code.

See also:

http://www.dynamicdrive.com/forums/showpost.php?p=143849&postcount=16

for a refined method.

CiaNZ
05-17-2008, 10:46 PM
Thanks for taking the time to help me John, the code youve written is working perfectly.

If I understand correctly, adding 'this.' to the front of a variable is sort of like saying 'only for this call of the of the subroutine'?

Im going to try using the more advanced/refined method youve linked to.

CiaNZ
05-17-2008, 11:51 PM
Ive switched to the refined method code but am having some trouble with links. I get some sort of error from using what I though would work:


<a href='#' onClick='new loadXmlHttp('video.php?id=1', 'main');return false;'>

I cant see anything wrong with it?

jscheuer1
05-18-2008, 12:35 AM
Thanks for taking the time to help me John, the code youve written is working perfectly.

If I understand correctly, adding 'this.' to the front of a variable is sort of like saying 'only for this call of the of the subroutine'?

Im going to try using the more advanced/refined method youve linked to.

The this keyword is very useful, but tricky. Sometimes it is the window, sometimes it is the element, as in:


<span onmouseover="this.style.color='red'">Hi</span>

When a function is called as an instance (new function_name(arguments)), this used inside that function usually refers to that particular instance of the function, with some limitations. When that's what you are doing, this.something is not a variable, it's a property of that instance of the function.


Ive switched to the refined method code but am having some trouble with links. I get some sort of error from using what I though would work:


<a href='#' onClick='new loadXmlHttp('video.php?id=1', 'main');return false;'>

I cant see anything wrong with it?

It looks OK, but I can't see all that's going on. For example, is the proper path getting resolved? It might need to be:


<a href='#' onClick='new loadXmlHttp('vidsite/video.php?id=1', 'main');return false;'>

or:


<a href='#' onClick='new loadXmlHttp('/vidsite/video.php?id=1', 'main');return false;'>

or even:


<a href='#' onClick='new loadXmlHttp('http://www.getbweb.com/vidsite/video.php?id=1', 'main');return false;'>

There could be other issues, I looked at your demo page, but it isn't using the refined code at the moment. xmlHTTP requests need to be on the same domain. The code might not work with unencoded query strings. It really could be anything, the loadXmlHttp function itself may have a flaw. If I had a link to the problem page, I should be able to figure it out.

CiaNZ
05-18-2008, 01:22 AM
Found the problem! any insight into why it was so picky? I should note that the code below was inside an echo string inside a PHP file.

This would cause a JavaScript error:


<a href='#' onClick='new loadXmlHttp('http://www.getbweb.com/vidsite/video.php?id=1', 'main');return false;'>

When changed to this, everything works fine:


<a href='#' onClick='new loadXmlHttp(\"http://www.getbweb.com/vidsite/video.php?id=1\", \"main\");return false;'>

jscheuer1
05-18-2008, 01:36 AM
Yes, you cannot have unescaped (\ is the escape symbol in this type of situation) single or double quotes inside a string that is delimited by that same type of quote without making the script parser think that the string has ended before you intended it to.

This (though perhaps harder to echo using PHP) would also work:


<a href="#" onClick="new loadXmlHttp('http://www.getbweb.com/vidsite/video.php?id=1', 'main');return false;">

because now there are no unescaped same type quotes inside of a string already delimited by that type of quote.

Mixing javascript and PHP can often be confusing because the meaning of the ' and " vary slightly between the two, but both are escaped in the same way when necessary in one or the other. To the parsers (on the server and on the client side) it is all just a matter of valid or invalid. But to the human eye it often all looks bad even when it is written correctly, or good even when written incorrectly.

In fact I missed the mixing of unescaped ' symbols in your example when you first mentioned this issue.