PDA

View Full Version : Loading external content together with (external) scripts



molendijk
05-18-2011, 11:06 PM
1) CODE TITLE: Loading external content together with (external) scripts

2) AUTHOR NAME: Arie Molendijk

3) DESCRIPTION:
We can use Ajax to dynamically update our page without page-reload. Unfortunately, Ajax does not bring in (by itself) the scripts belonging to the external content we want to include. I propose a script that does exactly that.

4) URL TO CODE:
http://www.let.rug.nl/molendyk/include_external_together_with_scripts/include_external_together_with_scripts

EDIT:
I modified the script for easier usage. New URL TO CODE:
http://www.let.rug.nl/molendyk/include_external_together_with_scripts2/include_external_together_with_scripts
All we have to do now is putting this in the head of the main page:

<script type="text/javascript">
var str = '';

/*Creating an (invisible) iframe for importing external content and a div for importing external scripts. The script as a whole won't work in IE7 if we do it the standard DOM way. So I use document.write*/
document.write('<iframe style="position:absolute; left: -10000px; width: 30px; height: 30px; display: none" name="ifr"><\/iframe>')
document.write('<div id="script_container"><\/div>')


/* Specifying the url of the external page that we want to put in the iframe and, subsequently, extract from the iframe */
function get_url(url)
{
frames['ifr'].location.replace(url)
}

/* Representing the source of the iframe (used to extract external content) as a string */
function create_string()
{
str=frames['ifr'].document.documentElement.innerHTML
}

/* Inserting the string into a div of our choice, and interpreting the code that may be contained in the string. */
function include(content,div)
{
document.getElementById(div).innerHTML=content;

var html_doc = window.frames.ifr.document;
var js = html_doc.createElement('script');
js.type="text/javascript";
js.text='function bring_code_to_main(){var el = document.getElementsByTagName("script");var search_limit = el.length-1;for(var x=0; x < search_limit; x++){newScript = top.document.createElement("script");newScript.type = "text/javascript";if(el[x].src != "") {newScript.src=el[x].src;newScript.text=""} else {newScript.text = el[x].text;}top.document.getElementById("script_container").innerHTML="";top.document.getElementById("script_container").appendChild(newScript);}};setTimeout("bring_code_to_main()",0)'; html_doc.getElementsByTagName('body').item(0).appendChild(js);

}

/* Making it work*/
function iframe_include(url,div)
{where=div
get_url(url);setTimeout("create_string();include(str,where)",200)
}

</script>


Usage:

<a href="javascript: void(0)" onclick="iframe_include('external.html','some_div')">include external.html</a>
(Of course, there should be a div having id='some_div' on the page!).

molendijk
06-06-2011, 05:28 PM
I noticed that the (modified) script even works if we want to include menus having complicated js and css, provided we put the css of the external file in the head of the main document. There should be a way to do this automatically, but I don't know yet how to achieve that.
So what I said in the demo, under 'Including whole menus', turns out to be too pessimistic. I'll change the info in the demo as soon I can use a decent computer. (The place where I am now is rather primitive from a technical point of view).
===
Arie.

jscheuer1
06-07-2011, 01:41 PM
Does this work repeatedly? Like could you keep switching the content with various and/or the same script with the same and/or different content, essentially importing multiple times without there being some collisions? What about default content - content that's already in the div on page load? What happens to that if you want to get it back later after replacing it and have no external page for it?

Anyways, I'm finding I have to click on the link twice or three times to get it to work. That's in Firefox, Chrome and IE the first time I view the page or if I clear the cache between attempts. In Opera - always.

molendijk
06-07-2011, 04:49 PM
Does this work repeatedly? Like could you keep switching the content with various and/or the same script with the same and/or different content, essentially importing multiple times without there being some collisions?
Yes, it's supposed to work repeatedly, with the same or different content.


What about default content - content that's already in the div on page load? What happens to that if you want to get it back later after replacing it and have no external page for it?
There should not be static default content. Dynamically inserted default content can be imported via 'onload'.


Anyways, I'm finding I have to click on the link twice or three times to get it to work. That's in Firefox, Chrome and IE the first time I view the page or if I clear the cache between attempts. In Opera - always.
That's strange. It worked here with all the major modern browsers (and even with IE6). I cannot check it now, because I don't have access to a decent browser right now. Did you (1) try the 'second' script and (2) put the css of the files_to_be_included in the head of the main page?
Could you try this:


<!-- Valid doctype here -->
<html>

<head>
<link rel="stylesheet" type="text/css" href="flexdropdown.css" />

<link rel="stylesheet" type="text/css" href="anylinkcssmenu.css" />

<script type="text/javascript">
var str = '';

/*Creating an (invisible) iframe for importing external content and a div for importing external scripts. The script as a whole won't work in IE7 if we do it the standard DOM way. So I use document.write*/
document.write('<iframe style="position:absolute; left: -10000px; width: 30px; height: 30px; display: none" name="ifr"><\/iframe>')
document.write('<div id="script_container" style="display:inline"><\/div>')

/* Specifying the url of the external page that we want to put in the iframe and, subsequently, extract from the iframe */
function get_url(url)
{
frames['ifr'].location.replace(url)
}

/* Representing the source of the iframe (used to extract external content) as a string */
function create_string()
{
str=frames['ifr'].document.documentElement.innerHTML;

}

/* Inserting the string into a div of our choice, and interpreting the code that may be contained in the string. */
function include(content,div)
{
document.getElementById(div).innerHTML=content;

var html_doc = window.frames.ifr.document;
var js = html_doc.createElement('script');
js.type="text/javascript";
js.text='function bring_code_to_main(){var el = document.getElementsByTagName("script");var search_limit = el.length-1;for(var x=0; x < search_limit; x++){newScript = top.document.createElement("script");newScript.type = "text/javascript";if(el[x].src != "") {newScript.src=el[x].src;newScript.text=""} else {newScript.text = el[x].text;}top.document.getElementById("script_container").innerHTML="";top.document.getElementById("script_container").appendChild(newScript);}};setTimeout("bring_code_to_main()",0)'; html_doc.getElementsByTagName('body').item(0).appendChild(js);

}

/* Making it work*/
function iframe_include(url,div)
{where=div
get_url(url);setTimeout("create_string();include(str,where)",200)

}

</script>

</head>

<body >

<a href="javascript: void(0)" onclick="iframe_include('flexmenu.html','some_div');">include flex</a><br>
<a href="javascript: void(0)" onclick="iframe_include('anylinkmenu.html','some_div');">include anylink</a><br>
<div id="some_div"></div>
It works with me, provided we have a standalone anylink menu and a standalone flex menu.
===
Arie.

molendijk
06-07-2011, 05:07 PM
John, if it still refuses to work with you, does it work with a timeout, like:
<a href="javascript: void(0)" onclick="setTimeout('iframe_include(\'flexmenu.html\',\'some_div\')',0)">include flex</a><br>
<a href="javascript: void(0)" onclick="setTimeout('iframe_include(\'anylinkmenu.html\',\'some_div\')',0)">include anylink</a><br><div id="some_div"></div>?
Arie.

jscheuer1
06-07-2011, 05:15 PM
I was using your live demo page.

molendijk
06-07-2011, 05:25 PM
Your findings are in accordance with my own observations in so far as they relate to the first demo (first script).
But the script here (http://www.let.rug.nl/molendyk/include_external_together_with_scripts2/include_external_together_with_scripts) (second version) should work.
===
Arie

jscheuer1
06-07-2011, 07:12 PM
Nope.

djr33
06-07-2011, 07:38 PM
There should not be static default content. Dynamically inserted default content can be imported via 'onload'.My personal opinion is that Javascript should never be used unless there is default content. There should be something there if Javascript doesn't work, or if the other page doesn't load for some reason. Is it possible then to have a fallback? Maybe you're just saying you can't revert to the default (static) content after loading something else. That would be ok.

molendijk
06-07-2011, 08:43 PM
Nope.
But here it works. Strange! As soon as I'm home again (Sunday), I'll examine everything in detail.

Maybe you're just saying you can't revert to the default (static) content after loading something else. That would be ok.
Yes, that's what I'm saying.
---
DJR, doesn't this (http://www.let.rug.nl/molendyk/include_external_together_with_scripts2/include_external_together_with_scripts) work with you either?
Thanks,
Arie.
===

djr33
06-07-2011, 08:45 PM
Same caching situation in Firefox as John explained. It worked after 2 clicks. Now that it's cached, it works immediately.

molendijk
06-07-2011, 08:50 PM
Thanks David.
===
Arie.

jscheuer1
06-07-2011, 09:16 PM
Sorry if I was a bit terse. But it works like I said. It's just fine after the pages are cached. If I empty the cache in IE or in Firefox it takes 2 clicks to get it to come up. In Opera, even with it cached it sometimes takes 2 or more clicks to work, other times it happens right away. In Opera it seems to make a difference if I navigate to the page as opposed to refreshing it. Refreshing is better. With a fresh navigation to the page, even with it cached, it often takes 2 or more clicks.

I only bothered to check any of this because it appeared balky at first, then fine. So I immediately wondered what would happen if I cleared the cache.

BTW, I just checked in Chrome. It's the same as in IE and the Fox.

molendijk
06-07-2011, 10:35 PM
Well John, at least I know now where the problem is.
The reason I want to further develop this is that the script seems to be able to repeatedly load external files like the flex menu and the anylink menu without affecting their functionality, despite the lines (in the js for flex and anylink) that seem to block repeated initializations. (I checked this at home and on the primitive computer I'm using here). The script's behavior for non-cached vs cached files may very well be related to its capacity to unblock the said restrictions with respect to repeated inits.
I cannot wait to be home again and test the whole lot on my own computer. I'll keep you informed.
Thanks for now,
Arie.

djr33
06-08-2011, 02:35 AM
You both know more about Javascript than I do, but here's my common sense response to the loading problems: it seems to me like it must be loading only after it's cached. The first time you click the link, it requests the data and caches it, but it doesn't display because it was too late responding. The second time, it has loaded. And other times after refreshing the page (but not clearing the cache) it is still there so it can be loaded immediately.

The solution then seems to be to add some sort of delay to the script. But of course that will vary by server response time / connection speed.

I don't know if that helps at all, but it seems logical to me.


This reminds me of a recent project using Flash. It was using Flash Media Server to record audio-- record a clip, send it to the remote server and after that refresh the page. The problem is that if it refreshed too early the file then didn't get saved. So the more-or-less solution was to just add a long pause, longer than required, with a "loading" message.

Not sure if that's applicable here. One option that would be easier is simply adding a one-time loop: 100ms after the first click, refresh the content. Right?

molendijk
06-08-2011, 10:54 AM
Yes, I was thinking about that too.
To test it, I need to have access to my own computer. Thanks anyway for your suggestion.
===
Arie.

molendijk
06-18-2011, 11:06 PM
Well, I'm home again, and I can see now (on my own computer, finally) that John and David were right: the external files don't always load 'on first click'. But they did on that old computer I was using in that foreign region, with IE6, very strange. And on that old far-away computer, the scripts contained in complicated external files also worked fine after inclusion. I tested that thoroughly under the palm trees, using IE6. But back home again here in wet and flat Holland, using my modern computer and modern browsers, my script doesn't always work as expected!
Anyhow, it seems that dynamically including the contents of an external document with the help of Ajax or a similar technique (hidden iframe) does not always yield the desired results (on modern computers using modern browsers). The scripts used in the external document may not function anymore after inclusion, even if we hard-code them in the main page. If that situation occurs, we could try another script I made for faking dynamic inclusion of external content. It uses the old static 'show & hide' technique for making divs visible or invisible. Demo HERE (http://www.let.rug.nl/molendyk/include_external_together_with_scripts3/main.html).
===
Arie.