Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Arg! Trying to find a working example of Javascript On Demand, help!

Status
Not open for further replies.

stompeers

Programmer
Jul 17, 2007
6
US
Hello there,

I'm trying to find a practical example of something that uses this pattern, which dynamically loads javascript into a page that has already been loaded:


I have found numerous examples of this, however what I'm really looking for is an example that shows how to dynamically load a javascript file with functions, and then check to see if the page or function is loaded, and then execute the function. If you just execute the function after loading the javascript, it won't be fully loaded yet and the function won't fire.

I've been searching through the web for several hours trying to find a solution, but have not found a good one yet. Any help would be much appreciated!!!

Thank you,
Chris
 
I would have thought that Google determine server-side what script files to include, and so none of this magic processing of which you speak would be done client-side.

Thus, the waiting-for-load issue isn't, because the script will be classed as part of the page content.

Hope this helps,
Dan



Coedit Limited - Delivering standards compliant, accessible web solutions

[tt]Dan's Page [blue]@[/blue] Code Couch
[/tt]
 
Hello Dan,

I know that this kind of thing is possible, but I haven't found any code examples yet.

I'm not sure you quite understand my question, since Google doesn't have anything to do with the process. The way it would work is this:

1. On the original page, there is a function that will append the DOM with the new external javascript file.
2. When a user completes an action (say, clicking on a button), the function is called to grab the external javascript file and add it in.

So far, so good. I've played with some examples that do this already. However, the tricky part is then calling a function in the newly-included file right after running the function to include it, like this, where init() is the function that grabs the external file where the somethingNew() function resides:

<input type="button" value="Insert new.js file" onclick="init();somethingNew();">

So, given that, do you or anyone else have any suggestions?

Thanks!
Chris
 
Here is a quick example I wrote up that shows what you want. It uploads upload.js when you click on the button and calls a function from upload.js.

MAIN FILE
Code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "[URL unfurl="true"]http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">[/URL]
<html>
<head>
<script type="text/javascript">
function uploadScript() {
   if (document.getElementById("uploadScript")) { // Already exists
     alert("JS file already loaded");
     return false;
   }
   var headObj = document.getElementsByTagName("head")[0];
   var scriptObj = document.createElement("script");
   scriptObj.id = 'uploadScript';
   scriptObj.type = 'text/javascript';
   scriptObj.src = "upload.js";
   headObj.appendChild(scriptObj)
 }
</script>
</head>
<body>
<input type="button" value="Upload Script and Run Function" onclick="uploadScript(); doAlert()" />
</body>
</html>

upload.js file
Code:
function doAlert() {
   alert("Hello I was uploaded");
}

[monkey][snake] <.
 
Hi Monksnake,

I've tried that method before, and I just tried your code to double-check, and it doesn't work. The first time you click, it will give you an error because it doesn't load the external file in time to run the function inside it. By the second time you click, it has been loaded and you're good to go. To demonstrate this, you need to clear your cache to make sure the external file isn't already saved.

So, what would be the best way to work around this?

Thanks!
Chris
 
Strange, I guess since this crap computer I use is so slow, the external file did load before it tried to run the function, so I didn't get any errors, even on the load, I'll take a look into this.

[monkey][snake] <.
 
What about using the setTimeout function to wait to call the uploaded JS file's function.
Code:
<input type="button" value="Upload Script and Run Function" onclick="uploadScript(); setTimeout(doAlert, 1000)" />

Of course you will want the timeout as low as possible.

[monkey][snake] <.
 
Thanks, I appreciate it. In the article I posted that describes this pattern, it says:

START QUOTE

The callback function just needs to treat the response as plain-text and pass it to eval(). A warning: here again, asynchronicity rears its ugly head. You can't assume the new function will be available immediately. So don't do this:

if (!self.changePassword) {
requestPasswordModuleFromServer();
}
changePassword(old, new) // Won't work the first time because
// changePassword's not loaded yet.

You either need to make a synchronous call to the server, explicitly make the call in the response handler, or use a closure callback - either manually or using a continuation transformer such as Narrative JavaScript or djax. Note that you can't just add a loop to keep checking for the new function, due to the single-threaded nature of Javascript.


END QUOTE


A few options are mentioned here:
- Make a synchronous call: I tried looking this up, but I'm not sure how to do this
- Explicitly make the call in the response handler: I'm not sure what this means in this case
- Use a continuation transformer: I looked into the two options mentioned above (Narrative Javascript and DJAX), but I would much rather work with Javascript that alternate languages.

In regards to your second post, a timeout could probably be used, but that would be a last resort solution since: 1) you don't know how long it will take to fetch the file, and 2) you're wasting a user's time during the timeout. If you use this dynamic javascript menthod often, the timeouts could really add up and have a high cost to the user interface.

So, do you happen to have any other tricks up your sleve? ;)

Thanks!
Chris
 
Not sure what this will do to your CPU, but you can put an empty loop that loops until the new script is loaded, it'll only use that loop code one time, will exit the loop the instant the file is uploaded, and won't be used again.

Code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "[URL unfurl="true"]http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">[/URL]
<html>
<head>
<script type="text/javascript">
function uploadScript() {
   if (document.getElementById("uploadScript")) { // Already exists
     return false;
   }
   var headObj = document.getElementsByTagName("head")[0];
   var scriptObj = document.createElement("script");
   scriptObj.id = 'uploadScript';
   scriptObj.type = 'text/javascript';
   scriptObj.src = "upload.js";
   headObj.appendChild(scriptObj)
   [!]while (!document.getElementById("uploadScript")) {
   }[/!]
 }
</script>
</head>
<body>
<input type="button" value="Upload Script and Run Function" onclick="uploadScript(); doAlert()" />
</body>
</html>



[monkey][snake] <.
 
Hello Monsnake,

I gave that a shot and the same thing happens. :(

These are some good ideas, I appreciate you sticking with this. Any other ideas?

Thanks!
Chris
 
I'm not sure you quite understand my question

You're right - I completely mis-understood what you were asking.

I thought you were asking how Google insetred its code on top of the page you linked to (you didn't make it clear the article in question had any relevance - I thought you were asking how it did what it did).

Dan

Coedit Limited - Delivering standards compliant, accessible web solutions

[tt]Dan's Page [blue]@[/blue] Code Couch
[/tt]
 
Sortty, I'm all out of ideas, it's hard to test because I'm not getting the problem (function call before script is loaded) cause of my slow computer.



[monkey][snake] <.
 
I reckon the timeout is the way to go... maybe have a unique variable in the JS file, something like:

Code:
var uniqueVar01 = true;

and then you could test for it continually using a timeout:

Code:
var scriptLoaded = false;

var timerHandle = setInterval('checkForScript();', 500);

function checkForScript() {
   if (typeof(window['uniqueVar01']) != 'undefined') {
      clearInterval(timerHandle);
      scriptLoaded = true;
   }
}

Not tested... just hacked away quickly.. but it should giveyou the idea.

Hope this helps,
Dan

Coedit Limited - Delivering standards compliant, accessible web solutions

[tt]Dan's Page [blue]@[/blue] Code Couch
[/tt]
 
Chris said:
In regards to your second post, a timeout could probably be used, but that would be a last resort solution since: 1) you don't know how long it will take to fetch the file, and 2) you're wasting a user's time during the timeout. If you use this dynamic javascript menthod often, the timeouts could really add up and have a high cost to the user interface.

Just FYI, timers in JS do not sit and wait - they fire off in the background, so no "user time" is wasted... it's just the user cannot user functions in the external file until it has been loaded.

Dan

Coedit Limited - Delivering standards compliant, accessible web solutions

[tt]Dan's Page [blue]@[/blue] Code Couch
[/tt]
 
Hello,

Just to complete the thread, I'm not sure if I did find a solution that I like to the problem, but it seems like a timeout might be the answer. I will be doing some experimenting with jQuery soon and it's possible that it provides something within the framework to accomplish what I'm looking for.

Thank you!
Chris
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top