From fedddfd60edb9cfe5bb5a90745ad7d8b963661ac Mon Sep 17 00:00:00 2001 From: "ctrlaltca@gmail.com" <> Date: Sat, 16 Jul 2011 09:28:55 +0000 Subject: applied prado-lazyload-in-callbacks-patch (ticket #348) --- .../source/prado/activecontrols/ajax3.js | 433 ++++++++++++++++++++- 1 file changed, 416 insertions(+), 17 deletions(-) (limited to 'framework/Web/Javascripts') diff --git a/framework/Web/Javascripts/source/prado/activecontrols/ajax3.js b/framework/Web/Javascripts/source/prado/activecontrols/ajax3.js index d9b5bdfa..b0e4e31e 100644 --- a/framework/Web/Javascripts/source/prado/activecontrols/ajax3.js +++ b/framework/Web/Javascripts/source/prado/activecontrols/ajax3.js @@ -26,32 +26,53 @@ Object.extend(Prado.AjaxRequest.prototype, if (event == 'Complete') { - var redirectUrl = this.getBodyContentPart(Prado.CallbackRequest.REDIRECT_HEADER); - if(redirectUrl) + var redirectUrl = this.getBodyContentPart(Prado.CallbackRequest.REDIRECT_HEADER); + if (redirectUrl) document.location.href = redirectUrl; - if ((this.getHeader('Content-type') || '').match(/^text\/javascript/i)) - { - try + if ((this.getHeader('Content-type') || '').match(/^text\/javascript/i)) + { + try { - json = eval('(' + transport.responseText + ')'); - }catch (e) + json = eval('(' + transport.responseText + ')'); + } + catch (e) { if(typeof(json) == "string") json = Prado.CallbackRequest.decode(result); } - } + } - try - { - Prado.CallbackRequest.updatePageState(this,transport); - Ajax.Responders.dispatch('on' + transport.status, this, transport, json); - Prado.CallbackRequest.dispatchActions(transport,this.getBodyDataPart(Prado.CallbackRequest.ACTION_HEADER)); + try + { + Prado.CallbackRequest.updatePageState(this,transport); + Prado.CallbackRequest.checkHiddenFields(this,transport); + var obj = this; + Prado.CallbackRequest.loadAssets(this,transport, function() - (this.options['on' + this.transport.status] - || this.options['on' + (this.success() ? 'Success' : 'Failure')] - || Prototype.emptyFunction)(this, json); - } catch (e) { + { + try + { + Ajax.Responders.dispatch('on' + transport.status, obj, transport, json); + Prado.CallbackRequest.dispatchActions(transport,obj.getBodyDataPart(Prado.CallbackRequest.ACTION_HEADER)); + + ( + obj.options['on' + obj.transport.status] + || + obj.options['on' + (obj.success() ? 'Success' : 'Failure')] + || + Prototype.emptyFunction + ) (obj, json); + } + catch (e) + { + obj.dispatchException(e); + } + } + ); + } + catch (e) + { this.dispatchException(e); } } @@ -150,6 +171,18 @@ Object.extend(Prado.CallbackRequest, * Page state header name. */ PAGESTATE_HEADER : 'X-PRADO-PAGESTATE', + /** + * Script list header name. + */ + SCRIPTLIST_HEADER : 'X-PRADO-SCRIPTLIST', + /** + * Stylesheet list header name. + */ + STYLESHEETLIST_HEADER : 'X-PRADO-STYLESHEETLIST', + /** + * Hidden field list header name. + */ + HIDDENFIELDLIST_HEADER : 'X-PRADO-HIDDENFIELDLIST', REDIRECT_HEADER : 'X-PRADO-REDIRECT', @@ -344,6 +377,181 @@ Object.extend(Prado.CallbackRequest, //Logger.warn('current request ' + self.currentRequest.id); }, + /* + * Checks which scripts are used by the response and ensures they're loaded + */ + loadScripts : function(request, transport, callback) + { + var self = Prado.CallbackRequest; + var data = request.getBodyContentPart(self.SCRIPTLIST_HEADER); + if (!this.ScriptsToLoad) this.ScriptsToLoad = new Array(); + this.ScriptLoadFinishedCallback = callback; + if (typeof(data) == "string" && data.length > 0) + { + json = Prado.CallbackRequest.decode(data); + if(typeof(json) != "object") + Logger.warn("Invalid script list:"+data); + else + for(var key in json) + if (/^\d+$/.test(key)) + { + var url = json[key]; + if (!Prado.ScriptManager.isAssetLoaded(url)) + this.ScriptsToLoad.push(url); + } + } + this.loadNextScript(); + }, + + loadNextScript: function() + { + var done = (!this.ScriptsToLoad || (this.ScriptsToLoad.length==0)); + if (!done) + { + var url = this.ScriptsToLoad.shift(); var obj = this; + if ( + Prado.ScriptManager.ensureAssetIsLoaded(url, + function() { + obj.loadNextScript(); + } + ) + ) + this.loadNextScript(); + } + else + { + if (this.ScriptLoadFinishedCallback) + { + var cb = this.ScriptLoadFinishedCallback; + this.ScriptLoadFinishedCallback = null; + cb(); + } + } + }, + + loadStyleSheetsAsync : function(request, transport) + { + var self = Prado.CallbackRequest; + var data = request.getBodyContentPart(self.STYLESHEETLIST_HEADER); + if (typeof(data) == "string" && data.length > 0) + { + json = Prado.CallbackRequest.decode(data); + if(typeof(json) != "object") + Logger.warn("Invalid stylesheet list:"+data); + else + for(var key in json) + if (/^\d+$/.test(key)) + Prado.StyleSheetManager.ensureAssetIsLoaded(json[key],null); + } + }, + + loadStyleSheets : function(request, transport, callback) + { + var self = Prado.CallbackRequest; + var data = request.getBodyContentPart(self.STYLESHEETLIST_HEADER); + if (!this.StyleSheetsToLoad) this.StyleSheetsToLoad = new Array(); + this.StyleSheetLoadFinishedCallback = callback; + if (typeof(data) == "string" && data.length > 0) + { + json = Prado.CallbackRequest.decode(data); + if(typeof(json) != "object") + Logger.warn("Invalid stylesheet list:"+data); + else + for(var key in json) + if (/^\d+$/.test(key)) + { + var url = json[key]; + if (!Prado.StyleSheetManager.isAssetLoaded(url)) + this.StyleSheetsToLoad.push(url); + } + } + this.loadNextStyleSheet(); + }, + + loadNextStyleSheet: function() + { + var done = (!this.StyleSheetsToLoad || (this.StyleSheetsToLoad.length==0)); + if (!done) + { + var url = this.StyleSheetsToLoad.shift(); var obj = this; + if ( + Prado.StyleSheetManager.ensureAssetIsLoaded(url, + function() { + obj.loadNextStyleSheet(); + } + ) + ) + this.loadNextStyleSheet(); + } + else + { + if (this.StyleSheetLoadFinishedCallback) + { + var cb = this.StyleSheetLoadFinishedCallback; + this.StyleSheetLoadFinishedCallback = null; + cb(); + } + } + }, + + /* + * Checks which assets are used by the response and ensures they're loaded + */ + loadAssets : function(request, transport, callback) + { + /* + + ! This is the callback-based loader for stylesheets, which loads them one-by-one, and + ! waits for all of them to be loaded before loading scripts and processing the rest of + ! the callback. + ! + ! That however is not neccessary, as stylesheets can be loaded asynchronously too. + ! + ! I leave this code here for the case that this turns out to be a compatibility issue + ! (for ex. I can imagine some scripts trying to access stylesheet properties and such) + ! so if need can be reactivated. If you do so, comment out the async stylesheet loader below! + + var obj = this; + this.loadStyleSheets(request,transport, function() { + obj.loadScripts(request,transport,callback); + }); + + */ + + this.loadStyleSheetsAsync(request,transport); + + this.loadScripts(request,transport,callback); + }, + + checkHiddenField: function(name, value) + { + var id = name.replace(':','_'); + if (!document.getElementById(id)) + { + var field = document.createElement('input'); + field.setAttribute('type','hidden'); + field.id = id; + field.name = name; + field.value = value; + document.body.appendChild(field); + } + }, + + checkHiddenFields : function(request, transport) + { + var self = Prado.CallbackRequest; + var data = request.getBodyContentPart(self.HIDDENFIELDLIST_HEADER); + if (typeof(data) == "string" && data.length > 0) + { + json = Prado.CallbackRequest.decode(data); + if(typeof(json) != "object") + Logger.warn("Invalid hidden field list:"+data); + else + for(var key in json) + this.checkHiddenField(key,json[key]); + } + }, + /** * Updates the page state. It will update only if EnablePageStateUpdate and * HasPriority options are both true. @@ -722,3 +930,194 @@ Prado.Callback = function(UniqueID, parameter, onSuccess, options) request.dispatch(); return false; }; + + + +/** + * Asset manager classes for lazy loading of scripts and stylesheets + * @author Gabor Berczi (gabor.berczi@devworx.hu) + */ + +if (typeof(Prado.AssetManagerClass)=="undefined") { + + Prado.AssetManagerClass = Class.create(); + Prado.AssetManagerClass.prototype = { + + initialize: function() { + this.loadedAssets = new Array(); + this.discoverLoadedAssets(); + }, + + + /** + * Detect which assets are already loaded by page markup. + * This is done by looking up all elements and registering the values of their src attributes. + */ + discoverLoadedAssets: function() { + + // wait until document has finished loading to avoid javascript errors + if (!document.body) return; + + var assets = this.findAssetUrlsInMarkup(); + for(var i=0;i element in page header + var asset = this.createAssetElement(url); + + if (callback) + { + asset.onreadystatechange = this.createAssetReadyStateChangeFunction(url, asset, callback, false); + asset.onload = this.createAssetReadyStateChangeFunction(url, asset, callback, true); + } + + var head = document.getElementsByTagName('head')[0]; + head.appendChild(asset); + + // mark this asset as loaded + this.markAssetAsLoaded(url); + + return (callback!=false); + }, + + /** + * Check whether a asset is loaded into the page, and if itsn't, load it now + * @param string url of the asset to check/load + * @return boolean returns true if asset is already loaded, or false, if loading has just started. callback will be called when loading has finished. + */ + ensureAssetIsLoaded: function(url, callback) { + url = this.makeFullUrl(url); + if (this.loadedAssets.indexOf(url)==-1) + { + this.startAssetLoad(url,callback); + return false; + } + else + return true; + } + + } + +}; + + Prado.ScriptManagerClass = Class.extend(Prado.AssetManagerClass, { + + findAssetUrlsInMarkup: function() { + var urls = new Array(); + var scripts = document.getElementsByTagName('script'); + for(var i=0;i0)) + urls.push(href); + } + return urls; + }, + + createAssetElement: function(url) { + var asset = document.createElement('link'); + asset.rel = 'stylesheet'; + asset.media = 'screen'; + asset.setAttribute('type', 'text/css'); + asset.href = url; +// asset.async = false; // HTML5 only + return asset; + } + + }); + + if (typeof(Prado.ScriptManager)=="undefined") Prado.ScriptManager = new Prado.ScriptManagerClass(); + if (typeof(Prado.StyleSheetManager)=="undefined") Prado.StyleSheetManager = new Prado.StyleSheetManagerClass(); + + // make sure we scan for loaded scripts again when the page has been loaded + var discover = function() { + Prado.ScriptManager.discoverLoadedAssets(); + Prado.StyleSheetManager.discoverLoadedAssets(); + } + if (window.attachEvent) window.attachEvent('onload', discover); + else if (window.addEventListener) window.addEventListener('load', discover, false); + -- cgit v1.2.3