You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2010/05/07 19:47:30 UTC
svn commit: r942158 -
/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry.js
Author: hlship
Date: Fri May 7 17:47:30 2010
New Revision: 942158
URL: http://svn.apache.org/viewvc?rev=942158&view=rev
Log:
TAP5-1137: Dynamically adding JavaScript libraries to a page via a partial page update does not seem to work consistently in Safari and Chrome
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry.js
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry.js?rev=942158&r1=942157&r2=942158&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry.js (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry.js Fri May 7 17:47:30 2010
@@ -1772,66 +1772,6 @@ Tapestry.FormInjector = Class.create( {
}
});
-/**
- * Wait for a set of JavaScript libraries to load (in terms of DOM script
- * elements), then invokes a callback function.
- */
-Tapestry.ScriptLoadMonitor = Class
- .create( {
-
- initialize : function(scriptElements, callback) {
- this.callback = callback;
- this.loaded = 0;
- this.toload = scriptElements.length;
-
- var executor = this;
-
- scriptElements
- .each(function(scriptElement) {
- if (Prototype.Browser.IE) {
- var loaded = false;
-
- scriptElement.onreadystatechange = function() {
- /*
- * IE may fire either loaded or complete, or
- * perhaps even both.
- */
- if (!loaded
- && (this.readyState == 'loaded' || this.readyState == 'complete')) {
- loaded = true;
- executor.loadComplete(scriptElement);
- }
- };
- } else {
- /* Much simpler in FF, Safari, etc. */
- scriptElement.onload = executor.loadComplete
- .bindAsEventListener(executor,
- scriptElement);
- }
- });
-
- /*
- * If no scripts to actually load, call the callback
- * immediately.
- */
-
- if (this.toload == 0)
- this.callback.call(this);
- },
-
- loadComplete : function() {
- this.loaded++;
-
- /*
- * Evaluated the dependent script only once all the elements
- * have loaded.
- */
-
- if (this.loaded == this.toload)
- this.callback.call(this);
- }
- });
-
Tapestry.ScriptManager = {
/**
@@ -1846,7 +1786,6 @@ Tapestry.ScriptManager = {
* Check to see if document.scripts is supported; if not (for example,
* FireFox), we can fake it.
*/
-
this.emulated = false;
if (!document.scripts) {
@@ -1860,6 +1799,41 @@ Tapestry.ScriptManager = {
}
},
+ loadScript : function(scriptURL, callback) {
+ /* IE needs the type="text/javascript" as well. */
+ var element = new Element('script', {
+ src : scriptURL,
+ type : 'text/javascript'
+ });
+
+ $$("head").first().insert( {
+ bottom : element
+ });
+
+ if (this.emulated)
+ document.scripts.push(element);
+
+ if (Prototype.Browser.IE) {
+ var loaded = false;
+
+ element.onreadystatechange = function() {
+ /* IE may fire either 'loaded' or 'complete', or possibly both. */
+ if (!loaded && this.readyState == 'loaded'
+ || this.readyState == 'complete') {
+ loaded = true;
+
+ callback.call(this);
+ }
+ };
+
+ return;
+ }
+
+ /* Safari, Firefox, etc. are easier. */
+
+ element.onload = callback.bindAsEventListener(this);
+ },
+
/**
* Checks to see if the given collection (of <script> or <style> elements)
* contains the given asset URL.
@@ -1897,51 +1871,44 @@ Tapestry.ScriptManager = {
* invoked after scripts are loaded
*/
addScripts : function(scripts, callback) {
- var added = new Array();
- if (scripts) {
- var emulated = this.emulated;
- /*
- * Looks like IE really needs the new <script> tag to be in the
- * <head>. FF doesn't seem to care. See
- * http://unixpapa.com/js/dyna.html
- */
- var head = $$("head").first();
+ var scriptsToLoad = [];
- scripts.each(function(s) {
- var assetURL = Tapestry.rebuildURL(s);
+ /* scripts may be null or undefined */
+ (scripts || []).each(function(s) {
+ var assetURL = Tapestry.rebuildURL(s);
- /*
- * Check to see if the script is already loaded, either as a
- * virtual script, or as an individual script src="" element.
- */
-
- if (Tapestry.ScriptManager.virtualScripts.member(assetURL))
- return;
- if (Tapestry.ScriptManager.contains(document.scripts, "src",
- assetURL))
- return;
-
- /* IE needs the type="text/javascript" as well. */
-
- var element = new Element('script', {
- src : assetURL,
- type : 'text/javascript'
- });
+ /*
+ * Check to see if the script is already loaded, either as a virtual
+ * script, or as an individual script src="" element.
+ */
+ if (Tapestry.ScriptManager.virtualScripts.member(assetURL))
+ return;
- head.insert( {
- bottom : element
- });
+ if (Tapestry.ScriptManager.contains(document.scripts, "src",
+ assetURL))
+ return;
- added.push(element);
+ scriptsToLoad.push(assetURL);
+ });
- if (emulated)
- document.scripts.push(element);
- });
+ /*
+ * Set it up last script to first script. The last script's callback is
+ * the main callback (the code to execute after all scripts are loaded).
+ * The 2nd to last script's callback loads the last script. Prototype's
+ * Array.inject() is effectively the same as Clojure's reduce().
+ */
+ scriptsToLoad.reverse();
- }
+ var topCallback = scriptsToLoad.inject(callback, function(nextCallback,
+ scriptURL) {
+ return function() {
+ Tapestry.ScriptManager.loadScript(scriptURL, nextCallback);
+ };
+ });
- new Tapestry.ScriptLoadMonitor(added, callback);
+ /* Kick it off with the callback that loads the first script. */
+ topCallback.call();
},
addStylesheets : function(stylesheets) {
@@ -1967,7 +1934,6 @@ Tapestry.ScriptManager = {
* Careful about media types, some browser will break if it
* ends up as 'null'.
*/
-
if (s.media != undefined)
element.writeAttribute('media', s.media);