From 7a49346f8069d814c51af2e0cefcc6e66fe9826e Mon Sep 17 00:00:00 2001 From: Thomas Lange Date: Fri, 22 Apr 2016 21:17:53 +0200 Subject: Multiple updates with async demo. --- static/bigpipe.js | 544 ++++++++++++++++++++++++++--------------------------- static/blue.php | 32 ++-- static/delayJS.php | 36 ++-- static/green.php | 32 ++-- static/red.php | 32 ++-- 5 files changed, 338 insertions(+), 338 deletions(-) (limited to 'static') diff --git a/static/bigpipe.js b/static/bigpipe.js index 0fcf68f..fed6e39 100755 --- a/static/bigpipe.js +++ b/static/bigpipe.js @@ -1,273 +1,273 @@ -//=================================================================================================== -// Revealing Module Pattern -//=================================================================================================== -var BigPipe = (function() { - //=================================================================================================== - // Resource: Represents a single CSS or JS resource - //=================================================================================================== - function Resource(resourceURL, type) { - this.resourceURL = resourceURL; - this.callbacks = []; - this.done = false; - this.type = type; - } - - //=================================================================================================== - // Resource: Loading the resource - //=================================================================================================== - Resource.prototype.start = function() { - if(this.type === 0) { - var element = document.createElement('link'); - element.setAttribute('rel', 'stylesheet'); - element.setAttribute('href', this.resourceURL); - } - - else { - var element = document.createElement('script'); - element.setAttribute('src', this.resourceURL); - element.async = true; - } - - document.head.appendChild(element); - - element.onload = function() { - this.executeCallbacks(); - }.bind(this); - - element.onerror = function() { - this.executeCallbacks(); - }.bind(this); - }; - - //=================================================================================================== - // Resource: Register a new callback - //=================================================================================================== - Resource.prototype.registerCallback = function(callback) { - return this.callbacks.push(callback); - }; - - //=================================================================================================== - // Resource: Executes all registered callbacks - //=================================================================================================== - Resource.prototype.executeCallbacks = function() { - if(!this.done) { - this.done = true; - - this.callbacks.forEach(function(callback) { - callback(); - }); - } - }; - - //=================================================================================================== - // Pagelet: Represents a single pagelet - //=================================================================================================== - function Pagelet(data) { - this.pageletID = data.ID; - this.HTML = data.HTML || ""; - this.CSSFiles = data.RESOURCES.CSS; - this.JSFiles = data.RESOURCES.JS; - this.JSCode = data.RESOURCES.JS_CODE; - - this.phase = 0; - this.CSSResources = []; - this.JSResources = []; - - this.phaseDoneJS = data.PHASES; - } - - //=================================================================================================== - // Pagelet: Increases phase and executes PhaseDoneJS - //=================================================================================================== - Pagelet.prototype.phaseDoneHandler = function(phase) { - for(var currentPhase = this.phase; currentPhase <= phase; ++currentPhase) { - this.executePhaseDoneJS(currentPhase); - } - - return (this.phase = ++phase); - }; - - //=================================================================================================== - // Pagelet: Executes the callbacks of the specific phase - //=================================================================================================== - Pagelet.prototype.executePhaseDoneJS = function(phase) { - this.phaseDoneJS[phase].forEach(function(code) { - try { - globalExecution(code); - } catch(e) { - console.error("PhaseDoneJS: " + e); - } - }); - }; - - //=================================================================================================== - // Pagelet: Initialize and start the CSS resources - //=================================================================================================== - Pagelet.prototype.start = function() { - var isStarted = false; - - this.CSSFiles.forEach(function(resourceURL) { - this.attachCSSResource(new Resource(resourceURL, 0)); - }.bind(this)); - - this.JSFiles.forEach(function(resourceURL) { - this.attachJSResource(new Resource(resourceURL, 1)); - }.bind(this)); - - this.CSSResources.forEach(function(resource) { - isStarted = true; - resource.start(); - }.bind(this)); - - // If no CSS resource was started (= no external CSS resources exists), then begin to inject the HTML - !isStarted && this.injectHTML(); - }; - - //=================================================================================================== - // Pagelet: Attach a new CSS resource to the pagelet - //=================================================================================================== - Pagelet.prototype.attachCSSResource = function(resource) { - resource.registerCallback(this.onloadCSS.bind(this)); - return this.CSSResources.push(resource); - }; - - //=================================================================================================== - // Pagelet: Attach a new JS resource to the pagelet - //=================================================================================================== - Pagelet.prototype.attachJSResource = function(resource) { - resource.registerCallback(this.onloadJS.bind(this)); - return this.JSResources.push(resource); - }; - - //=================================================================================================== - // Pagelet: Executes the main JS code of the pagelet - //=================================================================================================== - Pagelet.prototype.executeJSCode = function() { - try { - globalExecution(this.JSCode); - } catch(e) { - console.error(this.pageletID + ": " + e); - } - }; - - //=================================================================================================== - // Pagelet: Get each time called if a single JS resource has been loaded - //=================================================================================================== - Pagelet.prototype.onloadJS = function() { - if(this.phase === 3 && this.JSResources.every(function(resource){ - return resource.done; - })) { - this.phaseDoneHandler(3); - this.executeJSCode(); - this.phaseDoneHandler(4); - } - }; - - //=================================================================================================== - // Pagelet: Get each time called if a single CSS resource has been loaded - //=================================================================================================== - Pagelet.prototype.onloadCSS = function() { - if(this.CSSResources.every(function(resource){ - return resource.done; - })) { - this.injectHTML(); - } - }; - - //=================================================================================================== - // Pagelet: Injects the HTML content into the DOM - //=================================================================================================== - Pagelet.prototype.injectHTML = function() { - this.phaseDoneHandler(1); - - if(placeholder = document.getElementById(this.pageletID)) { - var pageletHTML = document.getElementById('_' + this.pageletID); - placeholder.innerHTML = pageletHTML.innerHTML.substring(5, pageletHTML.innerHTML.length - 4); - document.body.removeChild(pageletHTML); - } - - this.phaseDoneHandler(2); - - BigPipe.executeNextPagelet(); - - // Check if this was the last pagelet and then start loading of the external JS resources - if(BigPipe.phase === 2 && BigPipe.pagelets[BigPipe.pagelets.length - 1].pageletID === this.pageletID) { - BigPipe.loadJSResources(); - } - }; - - //=================================================================================================== - // BigPipe - //=================================================================================================== - var BigPipe = { - pagelets: [], - phase: 0, - offset: 0, - - executeNextPagelet: function() { - if(this.pagelets[this.offset]) { - this.pagelets[this.offset++].start(); - } - - else if(this.phase < 2) { - setTimeout(this.executeNextPagelet.bind(this), 20); - } - }, - - onPageletArrive: function(data) { - var pagelet = new Pagelet(data); - pagelet.phaseDoneHandler(0); - - if(this.pagelets.push(pagelet) && this.phase === 0 && !data.IS_LAST) { - this.phase = 1; - this.executeNextPagelet(); - } - - else if(data.IS_LAST) { - this.phase = 2; - if(this.pagelets.length === 1) { - this.executeNextPagelet(); - } - } - }, - - loadJSResources: function() { - this.phase = 3; - var isLoading = false; - - this.pagelets.forEach(function(Pagelet) { - if(Pagelet.JSResources.length === 0) { - Pagelet.onloadJS(); - } - }); - - this.pagelets.forEach(function(Pagelet) { - Pagelet.JSResources.forEach(function(Resource) { - Resource.start(); - isLoading = true; - }); - }); - - if(!isLoading) { - this.pagelets.forEach(function(Pagelet) { - Pagelet.onloadJS(); - }); - } - } - }; - - //=================================================================================================== - // Public-Access - //=================================================================================================== - return { - onPageletArrive: function(data) { - BigPipe.onPageletArrive(data); - }, - - reset: function() { - BigPipe.pagelets = []; - BigPipe.offset = 0; - BigPipe.phase = 0; - } - }; +//============================================================================== +// Revealing Module Pattern +//============================================================================== +var BigPipe = (function() { + //============================================================================== + // Resource: Represents a single CSS or JS resource + //============================================================================== + function Resource(resourceURL, type) { + this.resourceURL = resourceURL; + this.callbacks = []; + this.done = false; + this.type = type; + } + + //============================================================================== + // Resource: Loading the resource + //============================================================================== + Resource.prototype.start = function() { + if(this.type === 0) { + var element = document.createElement('link'); + element.setAttribute('rel', 'stylesheet'); + element.setAttribute('href', this.resourceURL); + } + + else { + var element = document.createElement('script'); + element.setAttribute('src', this.resourceURL); + element.async = true; + } + + document.head.appendChild(element); + + element.onload = function() { + this.executeCallbacks(); + }.bind(this); + + element.onerror = function() { + this.executeCallbacks(); + }.bind(this); + }; + + //============================================================================== + // Resource: Register a new callback + //============================================================================== + Resource.prototype.registerCallback = function(callback) { + return this.callbacks.push(callback); + }; + + //============================================================================== + // Resource: Executes all registered callbacks + //============================================================================== + Resource.prototype.executeCallbacks = function() { + if(!this.done) { + this.done = true; + + this.callbacks.forEach(function(callback) { + callback(); + }); + } + }; + + //============================================================================== + // Pagelet: Represents a single pagelet + //============================================================================== + function Pagelet(data, HTML) { + this.pageletID = data.ID; + this.HTML = HTML || ""; + this.CSSFiles = data.RESOURCES.CSS; + this.JSFiles = data.RESOURCES.JS; + this.JSCode = data.RESOURCES.JS_CODE; + + this.phase = 0; + this.CSSResources = []; + this.JSResources = []; + + this.phaseDoneJS = data.PHASES; + } + + //============================================================================== + // Pagelet: Increases phase and executes PhaseDoneJS + //============================================================================== + Pagelet.prototype.phaseDoneHandler = function(phase) { + for(var currentPhase = this.phase; currentPhase <= phase; ++currentPhase) { + this.executePhaseDoneJS(currentPhase); + } + + return (this.phase = ++phase); + }; + + //============================================================================== + // Pagelet: Executes the callbacks of the specific phase + //============================================================================== + Pagelet.prototype.executePhaseDoneJS = function(phase) { + this.phaseDoneJS[phase].forEach(function(code) { + try { + globalExecution(code); + } catch(e) { + console.error("PhaseDoneJS: " + e); + } + }); + }; + + //============================================================================== + // Pagelet: Initialize and start the CSS resources + //============================================================================== + Pagelet.prototype.start = function() { + var isStarted = false; + + this.CSSFiles.forEach(function(resourceURL) { + this.attachCSSResource(new Resource(resourceURL, 0)); + }.bind(this)); + + this.JSFiles.forEach(function(resourceURL) { + this.attachJSResource(new Resource(resourceURL, 1)); + }.bind(this)); + + this.CSSResources.forEach(function(resource) { + isStarted = true; + resource.start(); + }.bind(this)); + + // If no CSS resource was started (= no external CSS resources exists), then begin to inject the HTML + !isStarted && this.injectHTML(); + }; + + //============================================================================== + // Pagelet: Attach a new CSS resource to the pagelet + //============================================================================== + Pagelet.prototype.attachCSSResource = function(resource) { + resource.registerCallback(this.onloadCSS.bind(this)); + return this.CSSResources.push(resource); + }; + + //============================================================================== + // Pagelet: Attach a new JS resource to the pagelet + //============================================================================== + Pagelet.prototype.attachJSResource = function(resource) { + resource.registerCallback(this.onloadJS.bind(this)); + return this.JSResources.push(resource); + }; + + //============================================================================== + // Pagelet: Executes the main JS code of the pagelet + //============================================================================== + Pagelet.prototype.executeJSCode = function() { + try { + globalExecution(this.JSCode); + } catch(e) { + console.error(this.pageletID + ": " + e); + } + }; + + //============================================================================== + // Pagelet: Get each time called if a single JS resource has been loaded + //============================================================================== + Pagelet.prototype.onloadJS = function() { + if(this.phase === 3 && this.JSResources.every(function(resource){ + return resource.done; + })) { + this.phaseDoneHandler(3); + this.executeJSCode(); + this.phaseDoneHandler(4); + } + }; + + //============================================================================== + // Pagelet: Get each time called if a single CSS resource has been loaded + //============================================================================== + Pagelet.prototype.onloadCSS = function() { + if(this.CSSResources.every(function(resource){ + return resource.done; + })) { + this.injectHTML(); + } + }; + + //============================================================================== + // Pagelet: Injects the HTML content into the DOM + //============================================================================== + Pagelet.prototype.injectHTML = function() { + this.phaseDoneHandler(1); + + document.getElementById(this.pageletID).innerHTML = this.HTML; + + this.phaseDoneHandler(2); + + BigPipe.executeNextPagelet(); + + // Check if this was the last pagelet and then start loading of the external JS resources + if(BigPipe.phase === 2 && BigPipe.pagelets[BigPipe.pagelets.length - 1].pageletID === this.pageletID) { + BigPipe.loadJSResources(); + } + }; + + //============================================================================== + // BigPipe + //============================================================================== + var BigPipe = { + pagelets: [], + phase: 0, + offset: 0, + + executeNextPagelet: function() { + if(this.pagelets[this.offset]) { + this.pagelets[this.offset++].start(); + } + + else if(this.phase < 2) { + setTimeout(this.executeNextPagelet.bind(this), 20); + } + }, + + onPageletArrive: function(data, codeContainer) { + var pageletHTML = codeContainer.innerHTML; + pageletHTML = pageletHTML.substring(5, pageletHTML.length - 4); + codeContainer.parentNode.removeChild(codeContainer); + + var pagelet = new Pagelet(data, pageletHTML); + pagelet.phaseDoneHandler(0); + + if(this.pagelets.push(pagelet) && this.phase === 0 && !data.IS_LAST) { + this.phase = 1; + this.executeNextPagelet(); + } + + else if(data.IS_LAST) { + this.phase = 2; + if(this.pagelets.length === 1) { + this.executeNextPagelet(); + } + } + }, + + loadJSResources: function() { + this.phase = 3; + var isLoading = false; + + this.pagelets.forEach(function(Pagelet) { + if(Pagelet.JSResources.length === 0) { + Pagelet.onloadJS(); + } + }); + + this.pagelets.forEach(function(Pagelet) { + Pagelet.JSResources.forEach(function(Resource) { + Resource.start(); + isLoading = true; + }); + }); + + if(!isLoading) { + this.pagelets.forEach(function(Pagelet) { + Pagelet.onloadJS(); + }); + } + } + }; + + //============================================================================== + // Public-Access + //============================================================================== + return { + onPageletArrive: function(data, codeContainer) { + BigPipe.onPageletArrive(data, codeContainer); + }, + + reset: function() { + BigPipe.pagelets = []; + BigPipe.offset = 0; + BigPipe.phase = 0; + } + }; })(); \ No newline at end of file diff --git a/static/blue.php b/static/blue.php index e715d83..5f9bacb 100755 --- a/static/blue.php +++ b/static/blue.php @@ -1,17 +1,17 @@ - + #blue{background:blue;} \ No newline at end of file diff --git a/static/delayJS.php b/static/delayJS.php index 96e46c5..b4af48d 100755 --- a/static/delayJS.php +++ b/static/delayJS.php @@ -1,18 +1,18 @@ - - -console.log("EXTERNAL: Delayed javascript resource loaded"); + + +console.log("EXTERNAL: Delayed javascript resource loaded"); diff --git a/static/green.php b/static/green.php index 65ded6f..f1c5f1b 100755 --- a/static/green.php +++ b/static/green.php @@ -1,17 +1,17 @@ - + #green{background:green;} \ No newline at end of file diff --git a/static/red.php b/static/red.php index e6936e8..b54abb3 100755 --- a/static/red.php +++ b/static/red.php @@ -1,17 +1,17 @@ - + #red{background:red;} \ No newline at end of file -- cgit v1.2.3