[Proto-Scripty] Re: Building a lazy Loader
...you'll get far more benefit from ensuring your code is concise, then budling it into as few source files as reasonable (say one or two) and using the same script files throughout your site so the browser can use cached stuff where possible...zip your source files and let the browser deal with downloading them efficiently. +1 to all of that soapbox In terms of concise script files, make sure your source code is clear and well-commented -- and then use a minifier[1]/packer[2]/etc. to strip all of that stuff out for distribution and pack things in a small space. NEVER sacrifice source clarity for released brevity. /soapbox [1] http://www.crockford.com/javascript/jsmin.html [2] http://dean.edwards.name/packer/ - But use JDD's modified version[3] if you use the $super feature of Prototype; otherwise Packer will obfuscate it. [3] http://code.google.com/p/protosafe/downloads/list - Seems to be locked for some reason, I'll drop JDD a note about it. -- T.J. ;-) On Nov 7, 3:14 am, RobG [EMAIL PROTECTED] wrote: On Nov 7, 12:52 am, Alex Mcauley [EMAIL PROTECTED] wrote: i want it to be transparent hence the syncronous request Blocking the UI is hardly transparent. The lazy loading of scripts is a flawed strategy - it seems a good idea but if you think about the issues, you should realise that you'll get far more benefit from ensuring your code is concise, then budling it into as few source files as reasonable (say one or two) and using the same script files throughout your site so the browser can use cached stuff where possible. Use server-side technologies to bundle required scripts together, that's an order of magnitude more efficient than client-side with AJAX. Loading files as required means waiting for the request, downloading the file, waiting for it to initialise, then calling stuff in it. Way too complex and very prone to errors - zip your source files and let the browser deal with downloading them efficiently. -- Rob --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Prototype script.aculo.us group. To post to this group, send email to prototype-scriptaculous@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/prototype-scriptaculous?hl=en -~--~~~~--~~--~--~---
[Proto-Scripty] Re: Building a lazy Loader
i want it to be transparent hence the syncronous request ... so the function that calls the dependencies waits to continue untill the scripts that it requires are loaded I have it inserting a script into the dom properly but if i try to call the function in the test script it doesnt work -- Code loadDependency : function(e) { var req=new Ajax.Request(e, { evalScripts: true, method: 'post', asynchronous:false, onComplete : function(res) { var scriptTag = document.createElement(script); scriptTag.setAttribute(type, text/javascript); scriptTag.setAttribute(src, e); document.getElementsByTagName(head)[0].appendChild(scriptTag); $(scriptTag).update(res.responseText); } }); }, lazyLoader : function(type,files) { var url=new String(document.location); if (url.charAt(url.length - 1) == /) //remove trailing slash { url = url.substring(0, url.length - 1); } // url now holds the domain name // this is all because IE and ff differ on echoing sources var loaded= new Array(); var toLoad= new Array(); var dependenciesArray = new Array(); var f=files.length; for(i=0;if;i++) { toLoad.push(url+files[i]); } $$('script').each(function(e) { if($(e).readAttribute('src')) { if($(e).readAttribute('src').indexOf(http) 0) { //alert($(e).readAttribute('src')); loaded.push(url+$(e).readAttribute('src')); } else { loaded.push($(e).readAttribute('src')); // now the shit has the fuckin URL in it } } }); var needsLoading=array_diff(toLoad,loaded); // array diff works fine alert(needsLoading.length); for(m=0;mneedsLoading.length;m++) { alert(needsLoading[m]); loadDependency(needsLoading[m]); } helpMe(); // this is in the loaded script (which has 3 lines in it!!) and doesn't work }, Above is the 2 parts to the script ... As you can see the 1st one gathers all the scripts in the DOM and appends them with the current URL (because Firefox and Inernet Explorer get the sources differently - Firefox adds the domain to the start of some of the scripts even though i havent put that as the source, only the relative path ... this fixes everything to add with a domain path) It takes the things that need to be loaded as an array -- Here var files = [ '/resources/includes/client/effects.js','/resources/includes/client/scriptaculous.js','/resources/includes/client/f2.js']; lazyLoader('script',files); and adds domain to the path preceeding so i can match whats what in the 2 arrays and not potentially load something thats already there... array_diff then returns me an array of what is missing from what is loaded and a loop on the array carries out supposedly `syncronous` ajax requests to load them into the head of the document ... It loads them fine and i can see the script source get added in firebug but when i goto call the function from f2.js (which is loaded properly) it returns helpMe() is not defined as a firebug error even though i can see it exists in the DOM So my theory is that if the request is synchronous then helpMe cannot be executed untill it is placed in the DOM... perhaps synchronous requests are removed from the latest prototype build Thanks Alex - Original Message - From: T.J. Crowder [EMAIL PROTECTED] To: Prototype script.aculo.us prototype-scriptaculous@googlegroups.com Sent: Thursday, November 06, 2008 2:41 PM Subject: [Proto-Scripty] Re: Building a lazy Loader Hi Alex, Can you post the offending code? Ideally, though, it makes for a more responsive UI if you allow the request to be asynchronous and handle the remainder of your logic in the onSuccess callback. Synchronous requests basically lock up the UI of the browser. -- T.J. Crowder tj / crowder software / com On Nov 6, 2:33 pm, Jeztah [EMAIL PROTECTED] wrote: Hi guys and gals ... today i am building a lazyLoader based on prototype Its already working except i assumed i could do a synchronous request so nothing further in the javascript function is executed untill the request has finished ... it seems that asynchronous : false; is not wokring as i expected in the Ajax options .. am i expecting to much from the response to hijack my function untill it has finished its XHR then let my script continue what it was doing ? I asumed this was a good idea as it would workout into a nice dependency module for certain scripts ... Any ideas ? ta Alex --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Prototype script.aculo.us group. To post to this group, send email to prototype-scriptaculous@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/prototype
[Proto-Scripty] Re: Building a lazy Loader
, url.length - 1); } // url now holds the domain name // this is all because IE and ff differ on echoing sources var loaded = new Array(); var toLoad = new Array(); var dependenciesArray = new Array(); var f=files.length; for(i=0;if;i++) { toLoad.push(url+files[i]); } $$('script').each(function(e) { if($(e).readAttribute('src')) { if($(e).readAttribute('src').indexOf(http) 0) { //alert($(e).readAttribute('src')); loaded.push(url+$(e).readAttribute('src')); } else { loaded.push($(e).readAttribute('src')); // now the shit has the fuckin URL in it } } }); var needsLoading=array_diff(toLoad,loaded); // array diff works fine alert(needsLoading.length); for(m=0;mneedsLoading.length;m++) { alert(needsLoading[m]); loadDependency(needsLoading[m]); } helpMe(); // this is in the loaded script (which has 3 lines in it!!) and doesn't work }, Above is the 2 parts to the script ... As you can see the 1st one gathers all the scripts in the DOM and appends them with the current URL (because Firefox and Inernet Explorer get the sources differently - Firefox adds the domain to the start of some of the scripts even though i havent put that as the source, only the relative path ... this fixes everything to add with a domain path) It takes the things that need to be loaded as an array -- Here var files = [ '/resources/includes/client/effects.js','/resources/includes/client/scriptaculous.js','/resources/includes/client/f2.js']; lazyLoader('script',files); and adds domain to the path preceeding so i can match whats what in the 2 arrays and not potentially load something thats already there... array_diff then returns me an array of what is missing from what is loaded and a loop on the array carries out supposedly `syncronous` ajax requests to load them into the head of the document ... It loads them fine and i can see the script source get added in firebug but when i goto call the function from f2.js (which is loaded properly) it returns helpMe() is not defined as a firebug error even though i can see it exists in the DOM So my theory is that if the request is synchronous then helpMe cannot be executed untill it is placed in the DOM... perhaps synchronous requests are removed from the latest prototype build Thanks Alex - Original Message - From: T.J. Crowder [EMAIL PROTECTED] To: Prototype script.aculo.us prototype-scriptaculous@googlegroups.com Sent: Thursday, November 06, 2008 2:41 PM Subject: [Proto-Scripty] Re: Building a lazy Loader Hi Alex, Can you post the offending code? Ideally, though, it makes for a more responsive UI if you allow the request to be asynchronous and handle the remainder of your logic in the onSuccess callback. Synchronous requests basically lock up the UI of the browser. -- T.J. Crowder tj / crowder software / com On Nov 6, 2:33 pm, Jeztah [EMAIL PROTECTED] wrote: Hi guys and gals ... today i am building a lazyLoader based on prototype Its already working except i assumed i could do a synchronous request so nothing further in the javascript function is executed untill the request has finished ... it seems that asynchronous : false; is not wokring as i expected in the Ajax options .. am i expecting to much from the response to hijack my function untill it has finished its XHR then let my script continue what it was doing ? I asumed this was a good idea as it would workout into a nice dependency module for certain scripts ... Any ideas ? ta Alex --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Prototype script.aculo.us group. To post to this group, send email to prototype-scriptaculous@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/prototype-scriptaculous?hl=en -~--~~~~--~~--~--~---
[Proto-Scripty] Re: Building a lazy Loader
yes thanks for the reply, i have removed evalScripts, i only put it in for a second to test i am going to put in a timeout to pause the script before it continues to return back to the function that calls it and see if that akes a difference ... if not i will go the async way and put a scope callback handler into the function ... i wante to make it transparent so i didnt have to put in a funciton all the time ... i.e i could just run the lazyLoader function to get all the dependencies needed , then continue as normal once downloaded to the browser ,..!! i guess someone has already thought of this though and couldnt manage it and is why the available ones use a callback function ... i will however continue to work on it as the starting progress is better than any i have come accross in terms of speed of script/lib detection... Thanks again Alex - Original Message - From: T.J. Crowder [EMAIL PROTECTED] To: Prototype script.aculo.us prototype-scriptaculous@googlegroups.com Sent: Thursday, November 06, 2008 4:24 PM Subject: [Proto-Scripty] Re: Building a lazy Loader Hi Alex, I could be completely misreading that code, and if I am, apologies in advance. It *looks* like you're trying to create a queue where you'll only load one script file at a time, and that you're first downloading each script via Ajax.Request and then separately appending a script tag to the page header to tell the browser to download it. I'm guessing you're thinking at that point it'll be in cache. I wouldn't take that bet. :-) The browser will maintain a queue of requests anyway (typically processing two at a time, although I *think* browsers only process one script download at a time because script order can be important -- can't find a reference for that, though, so I may be wrong), you don't have to do it yourself. But again, doing it this way -- synchronously -- will completely lock up the browser's UI during the process, which from the name lazy loader doesn't sound like what you're trying to achieve. I don't think your problem is with the Ajax.Requests not being synchronous. They probably are. But that doesn't mean that your DOM additions are handled synchronously by the browser. The browser may need a moment when script isn't running before it actually processes things like script tags. Then of course, there's also the download of the script itself (by the browser, as it may not be in cache), which is definitely not synchronous to your DOM manipulation. Also: In your Ajax.Request, you're setting evalScripts to true, but you're using it to load a JavaScript file rather than an HTML file. That setting is to tell Prototype to evaluate any script within script tags in the loaded content. The JavaScript files won't have any script tags. If you want to eval the content, just do that directly by eval'ing the response text. But if you do *that*, there's no need to add the script tags to the document's head and you may well end up with errors if you do, as you'll effectively load the script twice. These articles on the unofficial wiki may help: http://proto-scripty.wikidot.com/prototype:tip-scripting-dynamically-loaded-elements http://proto-scripty.wikidot.com/prototype:how-to-load-scripts-dynamically And this one on Ajaxian: http://ajaxian.com/archives/a-technique-for-lazy-script-loading If you really want to create a one-script-at-a-time queue, you can do that without locking things up. For instance, you can build a list of scripts to download (as you are) and then download them via Ajax.Request *asynchronously*, where the completion handler eval's the one it got and then triggers the load of the next one. For example: function loadScripts(ary) { processScriptQueue(ary.reverse()); } function processScriptQueue(queue) { var url; url = queue.pop(); new Ajax.Request(url, { onSuccess: function(transport) { eval(transport.responseText); }, onComplete: function() { if (queue.length 0) { processScriptQueue(queue); } } }); } (See how each completion chains to the next, without being synchronous.) There's a gotcha with using eval() to load scripts, however: Functions declared in the boring old fashioned way (function foo() { ... }) don't end up as properties of the global object, so you can't later call those functions. (You can write them as foo = function() { ... } and they will get added to the global object because of the Horror of Implicit Globals[1], but that only works if you're in control of the script you're loading.) There are clever ways to make them get added, but they get browser-specific[2]. But all in all, I'd stick with letting the browser do it, just add the script tags to the header. [1] http://blog.niftysnippets.org/2008/03/horror-of-implicit-globals.html [2] http://ajaxian.com/archives/evaling-with-ies-windowexecscript FWIW HTH, -- T.J. Crowder tj
[Proto-Scripty] Re: Building a lazy Loader
What are the drawbacks of requestings the JS file via Ajax.Request and stuffing the responseText inside the innerHTML property of a generated script element? Does it have the global scope restriction like eval? Does it cause a processing bottle neck for the client? Is it supported by all browsers? Just a thought as I had seen people using script tags but pointing the src to a destination, which caused issues because then the request for the contents of the file became dependent on the script tag and not the JS execution. On Nov 6, 11:50 am, Alex Mcauley [EMAIL PROTECTED] wrote: yes thanks for the reply, i have removed evalScripts, i only put it in for a second to test i am going to put in a timeout to pause the script before it continues to return back to the function that calls it and see if that akes a difference ... if not i will go the async way and put a scope callback handler into the function ... i wante to make it transparent so i didnt have to put in a funciton all the time ... i.e i could just run the lazyLoader function to get all the dependencies needed , then continue as normal once downloaded to the browser ,..!! i guess someone has already thought of this though and couldnt manage it and is why the available ones use a callback function ... i will however continue to work on it as the starting progress is better than any i have come accross in terms of speed of script/lib detection... Thanks again Alex - Original Message - From: T.J. Crowder [EMAIL PROTECTED] To: Prototype script.aculo.us prototype-scriptaculous@googlegroups.com Sent: Thursday, November 06, 2008 4:24 PM Subject: [Proto-Scripty] Re: Building a lazy Loader Hi Alex, I could be completely misreading that code, and if I am, apologies in advance. It *looks* like you're trying to create a queue where you'll only load one script file at a time, and that you're first downloading each script via Ajax.Request and then separately appending a script tag to the page header to tell the browser to download it. I'm guessing you're thinking at that point it'll be in cache. I wouldn't take that bet. :-) The browser will maintain a queue of requests anyway (typically processing two at a time, although I *think* browsers only process one script download at a time because script order can be important -- can't find a reference for that, though, so I may be wrong), you don't have to do it yourself. But again, doing it this way -- synchronously -- will completely lock up the browser's UI during the process, which from the name lazy loader doesn't sound like what you're trying to achieve. I don't think your problem is with the Ajax.Requests not being synchronous. They probably are. But that doesn't mean that your DOM additions are handled synchronously by the browser. The browser may need a moment when script isn't running before it actually processes things like script tags. Then of course, there's also the download of the script itself (by the browser, as it may not be in cache), which is definitely not synchronous to your DOM manipulation. Also: In your Ajax.Request, you're setting evalScripts to true, but you're using it to load a JavaScript file rather than an HTML file. That setting is to tell Prototype to evaluate any script within script tags in the loaded content. The JavaScript files won't have any script tags. If you want to eval the content, just do that directly by eval'ing the response text. But if you do *that*, there's no need to add the script tags to the document's head and you may well end up with errors if you do, as you'll effectively load the script twice. These articles on the unofficial wiki may help: http://proto-scripty.wikidot.com/prototype:tip-scripting-dynamically-...http://proto-scripty.wikidot.com/prototype:how-to-load-scripts-dynami... And this one on Ajaxian: http://ajaxian.com/archives/a-technique-for-lazy-script-loading If you really want to create a one-script-at-a-time queue, you can do that without locking things up. For instance, you can build a list of scripts to download (as you are) and then download them via Ajax.Request *asynchronously*, where the completion handler eval's the one it got and then triggers the load of the next one. For example: function loadScripts(ary) { processScriptQueue(ary.reverse()); } function processScriptQueue(queue) { var url; url = queue.pop(); new Ajax.Request(url, { onSuccess: function(transport) { eval(transport.responseText); }, onComplete: function() { if (queue.length 0) { processScriptQueue(queue); } } }); } (See how each completion chains to the next, without being synchronous.) There's a gotcha with using eval() to load scripts, however: Functions declared in the boring old fashioned way (function foo() { ... }) don't
[Proto-Scripty] Re: Building a lazy Loader
i wanted to build my own for POC and because i dont want it bloated ... - Original Message - From: buda [EMAIL PROTECTED] To: Prototype script.aculo.us prototype-scriptaculous@googlegroups.com Sent: Thursday, November 06, 2008 7:17 PM Subject: [Proto-Scripty] Re: Building a lazy Loader There is a nice library Ensure.js :) On 6 нояб, 16:33, Jeztah [EMAIL PROTECTED] wrote: Hi guys and gals ... today i am building a lazyLoader based on prototype Its already working except i assumed i could do a synchronous request so nothing further in the javascript function is executed untill the request has finished ... it seems that asynchronous : false; is not wokring as i expected in the Ajax options .. am i expecting to much from the response to hijack my function untill it has finished its XHR then let my script continue what it was doing ? I asumed this was a good idea as it would workout into a nice dependency module for certain scripts ... Any ideas ? ta Alex --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Prototype script.aculo.us group. To post to this group, send email to prototype-scriptaculous@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/prototype-scriptaculous?hl=en -~--~~~~--~~--~--~---
[Proto-Scripty] Re: Building a lazy Loader
not sure on the drawbacks but i have had a good idea ... i am going to write a function to the bottom of the file and test it for calling.. once its callable then the file is ready in the dom and can be used - Original Message - From: Matt Foster [EMAIL PROTECTED] To: Prototype script.aculo.us prototype-scriptaculous@googlegroups.com Sent: Thursday, November 06, 2008 7:45 PM Subject: [Proto-Scripty] Re: Building a lazy Loader What are the drawbacks of requestings the JS file via Ajax.Request and stuffing the responseText inside the innerHTML property of a generated script element? Does it have the global scope restriction like eval? Does it cause a processing bottle neck for the client? Is it supported by all browsers? Just a thought as I had seen people using script tags but pointing the src to a destination, which caused issues because then the request for the contents of the file became dependent on the script tag and not the JS execution. On Nov 6, 11:50 am, Alex Mcauley [EMAIL PROTECTED] wrote: yes thanks for the reply, i have removed evalScripts, i only put it in for a second to test i am going to put in a timeout to pause the script before it continues to return back to the function that calls it and see if that akes a difference ... if not i will go the async way and put a scope callback handler into the function ... i wante to make it transparent so i didnt have to put in a funciton all the time ... i.e i could just run the lazyLoader function to get all the dependencies needed , then continue as normal once downloaded to the browser ,..!! i guess someone has already thought of this though and couldnt manage it and is why the available ones use a callback function ... i will however continue to work on it as the starting progress is better than any i have come accross in terms of speed of script/lib detection... Thanks again Alex - Original Message - From: T.J. Crowder [EMAIL PROTECTED] To: Prototype script.aculo.us prototype-scriptaculous@googlegroups.com Sent: Thursday, November 06, 2008 4:24 PM Subject: [Proto-Scripty] Re: Building a lazy Loader Hi Alex, I could be completely misreading that code, and if I am, apologies in advance. It *looks* like you're trying to create a queue where you'll only load one script file at a time, and that you're first downloading each script via Ajax.Request and then separately appending a script tag to the page header to tell the browser to download it. I'm guessing you're thinking at that point it'll be in cache. I wouldn't take that bet. :-) The browser will maintain a queue of requests anyway (typically processing two at a time, although I *think* browsers only process one script download at a time because script order can be important -- can't find a reference for that, though, so I may be wrong), you don't have to do it yourself. But again, doing it this way -- synchronously -- will completely lock up the browser's UI during the process, which from the name lazy loader doesn't sound like what you're trying to achieve. I don't think your problem is with the Ajax.Requests not being synchronous. They probably are. But that doesn't mean that your DOM additions are handled synchronously by the browser. The browser may need a moment when script isn't running before it actually processes things like script tags. Then of course, there's also the download of the script itself (by the browser, as it may not be in cache), which is definitely not synchronous to your DOM manipulation. Also: In your Ajax.Request, you're setting evalScripts to true, but you're using it to load a JavaScript file rather than an HTML file. That setting is to tell Prototype to evaluate any script within script tags in the loaded content. The JavaScript files won't have any script tags. If you want to eval the content, just do that directly by eval'ing the response text. But if you do *that*, there's no need to add the script tags to the document's head and you may well end up with errors if you do, as you'll effectively load the script twice. These articles on the unofficial wiki may help: http://proto-scripty.wikidot.com/prototype:tip-scripting-dynamically-...http://proto-scripty.wikidot.com/prototype:how-to-load-scripts-dynami... And this one on Ajaxian: http://ajaxian.com/archives/a-technique-for-lazy-script-loading If you really want to create a one-script-at-a-time queue, you can do that without locking things up. For instance, you can build a list of scripts to download (as you are) and then download them via Ajax.Request *asynchronously*, where the completion handler eval's the one it got and then triggers the load of the next one. For example: function loadScripts(ary) { processScriptQueue(ary.reverse()); } function processScriptQueue(queue) { var url; url = queue.pop(); new Ajax.Request(url, { onSuccess: function(transport) { eval(transport.responseText
[Proto-Scripty] Re: Building a lazy Loader
On Nov 7, 12:52 am, Alex Mcauley [EMAIL PROTECTED] wrote: i want it to be transparent hence the syncronous request Blocking the UI is hardly transparent. The lazy loading of scripts is a flawed strategy - it seems a good idea but if you think about the issues, you should realise that you'll get far more benefit from ensuring your code is concise, then budling it into as few source files as reasonable (say one or two) and using the same script files throughout your site so the browser can use cached stuff where possible. Use server-side technologies to bundle required scripts together, that's an order of magnitude more efficient than client-side with AJAX. Loading files as required means waiting for the request, downloading the file, waiting for it to initialise, then calling stuff in it. Way too complex and very prone to errors - zip your source files and let the browser deal with downloading them efficiently. -- Rob --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Prototype script.aculo.us group. To post to this group, send email to prototype-scriptaculous@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/prototype-scriptaculous?hl=en -~--~~~~--~~--~--~---
[Proto-Scripty] Re: Building a lazy Loader
On Nov 7, 5:45 am, Matt Foster [EMAIL PROTECTED] wrote: What are the drawbacks of requestings the JS file via Ajax.Request and stuffing the responseText inside the innerHTML property of a generated script element? It is not reliable across browsers, nor is assigning the source as a string to the text attribute, nor adding a text node with a value of the source. Using a script element with a src attribute is the most reliable. -- Rob --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Prototype script.aculo.us group. To post to this group, send email to prototype-scriptaculous@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/prototype-scriptaculous?hl=en -~--~~~~--~~--~--~---