homepage Welcome to WebmasterWorld Guest from 54.204.94.228
register, free tools, login, search, pro membership, help, library, announcements, recent posts, open posts,
Become a Pro Member

Home / Forums Index / Code, Content, and Presentation / JavaScript and AJAX
Forum Library, Charter, Moderator: open

JavaScript and AJAX Forum

    
Dynamic update of web page... help rewriting code.
Help needed on DHTML code rewrite.
HillsCap

10+ Year Member



 
Msg#: 702 posted 6:51 am on Aug 15, 2003 (gmt 0)

Hi, all.
I've got some code that fetches an external HTML file, then injects the contents of that file into a DIV container. We use it on our site so the header, footer, and menu always stay loaded, but the Content DIV is dynamic.

It does this by loading the external HTML file into a hidden iFrame, then setting the DIV contents == iFrame contents.

I have some problems with it:
The existing code works, but isn't DOM2 compatible (i.e.: it uses the MS kludge innerHTML, which I want to get away from because I read on the W3C site that future DOM2 compatible browsers aren't guaranteed to support it).

It only works in IE 5.5+. I want it to also work in NS 6+. I DO NOT want to support older browsers, only DOM2 compatible browsers.

It messes up the browser Back button. I read somewhere this can be fixed by destroying the iFrame after the DIV contents == iFrame contents. I'm not sure if that's true, though. You can see in the updated code I'm trying to destroy the iFrame, but I don't think I've got it quite right.

It uses the readyState attribute to check if the iFrame has fully loaded the external content. readyState is IE specific, so I need some other way to check that the external content is fully loaded into the iFrame so it works with NS, as well. (And, no, I don't want to use the kludge of putting an onload trigger into each external file... that'd take me way too long to do. It needs to be able to check that the iFrame is ready from within the Javascript in question.)

Here's the original code, which we're using right now on our website:
var docgetElement = (document.getElementById!=null) //test for newer browsers
var docAll = (document.all!=null) //test for older browsers

function getElement(id) {
// Return the positioned element with the specified ID
if(docgetElement)
return document.getElementById(id) //newer browsers
else if (docAll)
return document.all[id] //older browsers
else if (!docgetElement &&!docAll) { //error message for really old browsers
upgrdmsg = "Your browser does not support the necessary"
+ "\r\n\r\n"
+ "technology to properly view this website."
+ "\r\n\r\n"
+ "Please upgrade your browser.";
alert(upgrdmsg);
}
}

function checkIFrame(destID) {
if (docAll) {
var iframeID = document.frames[destID+"target"] //get iFrame ID, if it exists
if (iframeID==null) { //if not, create it
document.body.insertAdjacentHTML("beforeEnd","<iframe style='width: 0pt; height: 0pt' name='"+destID+"target' src='' ></iframe>")
iframeID = document.frames[destID+"target"]
}
return iframeID; //send the iFrame ID
}
else if (docgetElement) {
var iframeID = window.frames[destID+"target"] //get iframe ID, if it exists
if (iframeID==null) { //if not, create it
iframeID=document.createElement('iframe');
iframeID.setAttribute('id','"+destID+"target');
iframeID.setAttribute('name','"+destID+"target');
iframeID.setAttribute('src','');
iframeID.style.border='0px';
iframeID.style.width='0px';
iframeID.style.height='0px';
var bodyRef = document.getElementsByTagName("body").item(0);
bodyRef.appendChild(newPara);
if (navigator.userAgent.indexOf('Gecko')!=-1) { // we have to give NS time to recognize the new IFrame
setTimeout('checkIFrame(destID)',500);
return false;
}
}
return iframeID; //send the iframe ID
}
}

function pollIFrame(destID) {
var destFrame = checkIFrame(destID) //get iFrame ID
if (destFrame.document.readyState=='complete') { //wait for iFrame to be ready
var el1 = getElement(destID) //get DIV id
el1.innerHTML = destFrame.document.body.innerHTML //set DIV content equal to iFrame contents
} else
setTimeout("pollIFrame('"+destID+"')",200) //otherwise, try again if iFrame not ready
}

function updateContents(destID, src) {
var el1 = getElement(destID) //get DIV id
destFrame = checkIFrame(destID) //get iFrame id
destFrame.location.href = src //set iFrame src to update content
setTimeout("pollIFrame('"+destID+"')",200) //make sure iFrame is ready and update DIV contents
}

function update(destID, src) {
if (src=="none" src=="") {
var el1 = getElement(destID) //get target DIV
var el1Len=el1.childNodes.length; //count number of Nodes in target DIV
for (i=0;i<el1Len;i++){
el1.removeChild(el1.childNodes[0]); //remove all the Nodes in target DIV
}
}
else {
updateContents(destID, src)
}
}

----------
And here's the code, as I've reworked it... but can't get it to work:
var docgetElement = (document.getElementById!=null) //test for newer browsers

function getElement(id) {
// Return the positioned element with the specified ID
if(docgetElement)
return document.getElementById(id) //newer browsers
else if (!docgetElement) { //error message for old browsers
upgrdmsg = "Your browser does not support the necessary"
+ "\r\n\r\n"
+ "technology to properly view this website."
+ "\r\n\r\n"
+ "Please upgrade your browser.";
alert(upgrdmsg);
}
}

function checkIFrame(destID, source) {
var iframeID = document.getElementByID(destID+"target"); //get iframe ID, if it exists
if (iframeID==null) { //if not, create it
iframeID=document.createElement('IFRAME');
iframeID.setAttribute('id','"+destID+"target');
iframeID.setAttribute('name','"+destID+"target');
iframeID.setAttribute('style','border : 0px;');
iframeID.setAttribute('style','width : 0px;');
iframeID.setAttribute('style','height : 0px;');
document.body.appendChild(iframeID);
}
iframeID.setAttribute('src',source);
return iframeID; //send the iframe ID
}

function pollIFrame(destID) {
var destFrame = checkIFrame(destID); //get iFrame ID
var fr = document.getElementById('"+destID+"target');
document.getElement(destID).appendChild(fr) //get DIV id and set content equal to iFrame content
var fr = document.getElementById('"+destID+"target');
fr.parentNode.removeChild(fr);

}

function updateContents(destID, source) {
var el1 = getElement(destID) //get DIV id
destFrame = checkIFrame(destID, source) //get iFrame id
setTimeout("pollIFrame('"+destID+"')",200) //make sure iFrame is ready and update DIV contents
}

function update(destID, source) {
if (source=="none" source=="") {
var el1 = getElement(destID) //get target DIV
var el1Len=el1.childNodes.length; //count number of Nodes in target DIV
for (i=0;i<el1Len;i++){
el1.removeChild(el1.childNodes[0]); //remove all the Nodes in target DIV
}
}
else {
updateContents(destID, source)
}
}

I've removed all references to document.all and to Frames technology (which was in the original (very old) version). Remember, I only want to support DOM2-compatible browsers by using DOM2 specific code.

It's called like this... say you have a link in the web page:
<a href="somepage.htm" onclick="update('content','somepage.htm');return false;">Go to some page.</a>

You'll notice that the traditional 'a href=' portion remains, so search engines / text readers / text-only browsers can follow that to the actual external HTML file.

update = the function that is called.
content = the target DIV with ID of 'content'
somepage.htm = the external HTML file

Thanks for any help you can provide.

 

MonkeeSage

WebmasterWorld Senior Member 10+ Year Member



 
Msg#: 702 posted 10:17 am on Aug 15, 2003 (gmt 0)

Welcome to WebmasterWorld, HillsCap!

I only see a couple possible points that might be problematic, the rest looks really well laid out:

--------

In checkIFrame():
document.body.appendChild(iframeID);

I don't think you can insert objects at this level of the DOM...you need a known child lower in the DOM to insert from, e.g.,
document.getElementById("some-elemenet").parentNode.appendChild(iframeID);

--------

In update():
if (source=="none" source=="") {

Needs to have extra parentheticals, i.e.,
if ((source=="none") (source=="")) {

el1.removeChild(el1.childNodes[0]);

Needs a parenNode in there to make sure type of object is node, i.e.,
el1.parentNode.removeChild(el1.childNodes[0]);

--------

If that doesn't help, you can sticky me the URL and I can dynamically debug it to try to pin-point the problem.

HTH
Jordan

HillsCap

10+ Year Member



 
Msg#: 702 posted 1:51 pm on Aug 15, 2003 (gmt 0)

I KNEW I'd read somewhere that document.body can't do appendChild! But another so-called Javascript 'guru' told me that would work.

What if I put a blank DIV at the end of my index.shtml file, specifically for the iFrame to be created in?

i.e.:
<div id="forIFrame"></div>

Then reference that DIV in the code to create the iFrame? Would that work?

Let me make the changes you specify, and I'll be back in a bit.

Oh, the website URL is www.hillscapital.com. You'll need IE 5.5 or higher to access it, and right now the quotes ticker will force-download Java 1.4.2 if you don't already have it (I tried to convert the APPLETs to OBJECTs, but I don't think I've got them quite right yet... they load dreadfully slowly.)

HillsCap

10+ Year Member



 
Msg#: 702 posted 2:44 pm on Aug 15, 2003 (gmt 0)

Ok, I changed the

if ((source=="none") (source=="")) {

part, and the

el1.parentNode.removeChild(el1.childNodes[0]);

part, and I put a DIV with ID = "foriFrame" into my index.shtml, then changed the code to

document.getElementById("forIFrame").parentNode.appendChild(iframeID);

At least now, when using this script, I don't get an error as the page loads, but as soon as I click a link, I get:
Line: 19
Char: 5
Error: Object doesn't support this property or method
Code: 0
URL: [hillscapital.com...]

HillsCap

10+ Year Member



 
Msg#: 702 posted 2:53 pm on Aug 15, 2003 (gmt 0)

Perhaps we should be doing a cloneNode of the iFrame contents:

function pollIFrame(destID) {
var destFrame = checkIFrame(destID); //get iFrame ID
var fr = document.getElementById('"+destID+"target').cloneNode(true); //? Not sure if this is correct, trying to clone the iFrame contents
document.getElement(destID).appendChild(fr) //get DIV id and set content equal to iFrame content
var fr = document.getElementById('"+destID+"target');
fr.parentNode.removeChild(fr);
}

MonkeeSage

WebmasterWorld Senior Member 10+ Year Member



 
Msg#: 702 posted 3:04 pm on Aug 15, 2003 (gmt 0)

HillsCap:

You got fat fingers like I do. ;)

Make sure that "foriFrame" and "forIFrame" match, and in checkIFrame() make sure this:

var iframeID = document.getElementByID(destID+"target"); //get iframe ID, if it exists

is

var iframeID = document.getElementById(destID+"target"); //get iframe ID, if it exists

The little things that gets ya. :)

Jordan

HillsCap

10+ Year Member



 
Msg#: 702 posted 4:57 pm on Aug 15, 2003 (gmt 0)

Thanks, I never would have caught that.

I consolidated the code... here's what I've got so far:

var docgetElement = (document.getElementById!=null) //test for newer browsers

function getElement(id) {
// Return the positioned element with the specified ID
if(docgetElement)
return document.getElementById(id) //newer browsers
else if (!docgetElement) { //error message for old browsers
upgrdmsg = "Your browser does not support the necessary"
+ "\r\n\r\n"
+ "technology to properly view this website."
+ "\r\n\r\n"
+ "Please upgrade your browser.";
alert(upgrdmsg);
}
}

function checkIFrame(destID, source) {
var iframeID = document.getElementById(destID+"target"); //get iframe ID, if it exists
if (iframeID==null) { //if not, create it
iframeID=document.createElement('IFRAME');
iframeID.setAttribute('id','"+destID+"target');
iframeID.setAttribute('name','"+destID+"target');
iframeID.setAttribute('style','border : 0px;');
iframeID.setAttribute('style','width : 0px;');
iframeID.setAttribute('style','height : 0px;');
document.getElementById("forIFrame").parentNode.appendChild(iframeID);
// document.body.appendChild(iframeID);
}
iframeID.setAttribute('src',source);
return iframeID; //send the iframe ID
}

function pollIFrame(destID, source) {
var destFrame = checkIFrame(destID, source); //get iFrame ID
var fr = document.getElementById('"+destID+"target');
document.getElement(destID).appendChild(fr) //get DIV id and set content equal to iFrame content
var fr = document.getElementById('"+destID+"target');
fr.parentNode.removeChild(fr);
}

function update(destID, source) {
if ((source=="none") (source=="")) {
var el1 = getElement(destID) //get target DIV
var el1Len=el1.childNodes.length; //count number of Nodes in target DIV
for (i=0;i<el1Len;i++){
el1.parentNode.removeChild(el1.childNodes[0]);
// el1.removeChild(el1.childNodes[0]); //remove all the Nodes in target DIV
}
}
else {
setTimeout("pollIFrame('"+destID+", source')",200) //make sure iFrame is ready and update DIV contents
}
}

I got rid of the UpdateContents function and consolidated it into the Update function.

We need some way to determine if the iFrame is done loading the external HTML file... I was thinking of doing something like [this is going to be pretty rough, so brace yourself]:

Do While (iFrameID.onload=='null') {
set Timeout("do nothing", 200);
}

I know, I know... totally wrong. But there's got to be a way to check if the iFrame's onload event has been triggered, and wait for that to occur before we copy the iFrame contents to the DIV.

Have any ideas for this?

With the new code, I'm getting:
Line: 37
Char: 5
Error: Object doesn't support this property or method
Code: 0
URL:

I think it has to do with the code that destroys the iFrame... I'm pretty sure I hosed that up bad.

[edited by: korkus2000 at 1:55 pm (utc) on Oct. 18, 2003]

HillsCap

10+ Year Member



 
Msg#: 702 posted 5:08 pm on Aug 15, 2003 (gmt 0)

It created an iFrame! Yeah! :)

The only problem... it's visible, not hidden, so there's obviously something wrong in the code that creates it.

I think it might have to do with the following:
iframeID.setAttribute('style','border : 0px;');
iframeID.setAttribute('style','width : 0px;');
iframeID.setAttribute('style','height : 0px;');

I think I'll have to do iframeID.style.border, iframeID.style.width, and iframeID.style.height.

Actually, making it visible might make it easier to troubleshoot.

HillsCap

10+ Year Member



 
Msg#: 702 posted 5:11 pm on Aug 15, 2003 (gmt 0)

OK, I'm getting a 404 error in the iFrame... so we're obviously not passing the correct SRC to it.

HillsCap

10+ Year Member



 
Msg#: 702 posted 7:14 pm on Aug 15, 2003 (gmt 0)

OK, here's the code as it stands now. I get an error saying that the iFrame source is undefined.

var docgetElement = (document.getElementById!=null) //test for newer browsers

function getElement(id) {
// Return the positioned element with the specified ID
if(docgetElement)
return document.getElementById(id) //newer browsers
else if (!docgetElement) { //error message for old browsers
upgrdmsg = "Your browser does not support the necessary"
+ "\r\n\r\n"
+ "technology to properly view this website."
+ "\r\n\r\n"
+ "Please upgrade your browser.";
alert(upgrdmsg);
}
}

function checkIFrame(destID, source) {
var iframeID = document.getElementById(destID+"target"); //get iframe ID, if it exists
if (iframeID==null) { //if not, create it
iframeID=document.createElement('iframe');
iframeID.setAttribute('id','"+destID+"target');
iframeID.setAttribute('name','"+destID+"target');
// iframeID.setAttribute('border','0px');
iframeID.style.width = '225px';
iframeID.style.height = '225px';
document.getElementById("forIFrame").appendChild(iframeID);
}
iframeID.location.replace(source);
return iframeID; //send the iframe ID
}

function pollIFrame(destID, source) {
var destFrame = checkIFrame(destID, source); //get iFrame ID
var fr = document.getElementById('"+destID+"target');
document.getElement(destID).appendChild(fr) //get DIV id and set content equal to iFrame content
var fr = document.getElementById('"+destID+"target');
fr.parentNode.removeChild(fr);
}

function update(destID, source) {
var source='intro.shtml';
if ((source=="none") ¦¦ (source=="")) {
var el1 = getElement(destID) //get target DIV
var el1Len=el1.childNodes.length; //count number of Nodes in target DIV
for (i=0;i<el1Len;i++){
// el1.parentNode.removeChild(el1.childNodes[0]);
el1.removeChild(el1.childNodes[0]); //remove all the Nodes in target DIV
}
}
else {
pollIFrame(destID, source); //make sure iFrame is ready and update DIV contents
}
}

I have to take a break before my head implodes.

Global Options:
 top home search open messages active posts  
 

Home / Forums Index / Code, Content, and Presentation / JavaScript and AJAX
rss feed

All trademarks and copyrights held by respective owners. Member comments are owned by the poster.
Home ¦ Free Tools ¦ Terms of Service ¦ Privacy Policy ¦ Report Problem ¦ About ¦ Library ¦ Newsletter
WebmasterWorld is a Developer Shed Community owned by Jim Boykin.
© Webmaster World 1996-2014 all rights reserved