diff options
-rwxr-xr-x | include/classes/BigPipe/BigPipe.php | 42 | ||||
-rwxr-xr-x | include/classes/BigPipe/DemoPagelet.php | 17 | ||||
-rwxr-xr-x | include/classes/BigPipe/Pagelet.php | 69 | ||||
-rwxr-xr-x | include/functions.php | 2 | ||||
-rwxr-xr-x | index.php | 47 | ||||
-rwxr-xr-x | output-flushing-test.php | 12 | ||||
-rwxr-xr-x | static/bigpipe-callbacks.js | 27 | ||||
-rwxr-xr-x | static/bigpipe.js | 155 | ||||
-rwxr-xr-x | static/blue.php | 6 | ||||
-rwxr-xr-x | static/delayJS.php | 10 | ||||
-rwxr-xr-x | static/green.php | 6 | ||||
-rwxr-xr-x | static/red.php | 6 |
12 files changed, 230 insertions, 169 deletions
diff --git a/include/classes/BigPipe/BigPipe.php b/include/classes/BigPipe/BigPipe.php index b69f1d8..740d047 100755 --- a/include/classes/BigPipe/BigPipe.php +++ b/include/classes/BigPipe/BigPipe.php @@ -2,53 +2,65 @@ namespace BigPipe; class BigPipe { - public static $enabled = TRUE; + private static $enabled = TRUE; + private static $debug = TRUE; private static $pagelets = []; private static $count = 0; #==================================================================================================== - # Gibt TRUE zurück wenn BigPipe eingeschaltet ist + # Return TRUE if the pipeline is enabled #==================================================================================================== public static function isEnabled() { - return self::$enabled ? TRUE : FALSE; + return self::$enabled; } #==================================================================================================== - # Neues Pagelet zur Pipeline hinzufügen + # Enable or disable the pipeline mode + #==================================================================================================== + public static function enablePipeline($enabled = TRUE) { + return self::$enabled = (bool) $enabled; + } + + #==================================================================================================== + # Add a new pagelet to pipeline #==================================================================================================== public static function addPagelet(Pagelet $Pagelet, $priority) { self::$pagelets[$priority][] = $Pagelet; - self::$count++; + return ++self::$count; } #==================================================================================================== - # Gibt einen einzelnen Pagelet-Response aus + # Prints a single pagelet response #==================================================================================================== - private static function pageletResponse(Pagelet $Pagelet, $async = FALSE, $last = FALSE) { + private static function singleResponse(Pagelet $Pagelet, $last = FALSE) { $data = [ 'ID' => $Pagelet->getID(), - 'RESOURCES' => ['CSS' => $Pagelet->getCSSFiles(), 'JS' => $Pagelet->getJSFiles(), 'JS_CODE' => removeLineBreaksAndTabs($Pagelet->getJSCode())] + 'RESOURCES' => ['CSS' => $Pagelet->getCSSFiles(), 'JS' => $Pagelet->getJSFiles(), 'JS_CODE' => removeLineBreaksAndTabs($Pagelet->getJSCode())], + 'PHASES' => (object) $Pagelet->getPhaseDoneJS(), ]; if($last) { $data['IS_LAST'] = true; } - echo '<code class="hidden" id="_'.$data['ID'].'"><!-- '.str_replace('--', '--', removeLineBreaksAndTabs($Pagelet->getHTML())).' --></code>'."\n"; - echo '<script>BigPipe.onPageletArrive('.json_encode($data).($async ? ', document.getElementById("_'.$Pagelet->getID().'").innerHTML' : NULL).');</script>'."\n\n"; + $pageletHTML = str_replace('--', '--', removeLineBreaksAndTabs($Pagelet->getHTML())); + $pageletJSON = json_encode($data, (self::$debug ? JSON_PRETTY_PRINT : FALSE)); + + echo "<code class=\"hidden\" id=\"_{$Pagelet->getID()}\"><!-- {$pageletHTML} --></code>\n"; + echo "<script>BigPipe.onPageletArrive({$pageletJSON});</script>\n\n"; } #==================================================================================================== - # Sendet den Output-Buffer so weit wie möglich in Richtung User + # Sends output buffer so far as possible towards user #==================================================================================================== public static function flushOutputBuffer() { ob_flush(); flush(); } #==================================================================================================== - # Alle Pagelets an Client schicken + # Render the pagelets #==================================================================================================== - public static function render($async = FALSE) { + public static function render() { self::flushOutputBuffer(); $i = 0; @@ -72,8 +84,10 @@ class BigPipe { } else { - self::pageletResponse($Pagelet, $async, (self::$count === ++$i)); + self::singleResponse($Pagelet, (self::$count === ++$i)); self::flushOutputBuffer(); + + self::$debug AND usleep((rand(250, 1000) * 1000)); } } } diff --git a/include/classes/BigPipe/DemoPagelet.php b/include/classes/BigPipe/DemoPagelet.php new file mode 100755 index 0000000..a6c61e1 --- /dev/null +++ b/include/classes/BigPipe/DemoPagelet.php @@ -0,0 +1,17 @@ +<?php +namespace BigPipe; + +class DemoPagelet extends Pagelet { + + public function __construct($priority = Pagelet::PRIORITY_NORMAL) { + parent::__construct($priority); + + $message = '%s: PhaseDoneJS for phase %s'; + + $this->addPhaseDoneJS(self::PHASE_ARRIVE, 'console.log("'.sprintf($message, $this->getID(), 'ARRIVE').'")'); + $this->addPhaseDoneJS(self::PHASE_LOADCSS, 'console.log("'.sprintf($message, $this->getID(), 'LOADCSS').'")'); + $this->addPhaseDoneJS(self::PHASE_PUTHTML, 'console.log("'.sprintf($message, $this->getID(), 'PUTHTML').'")'); + $this->addPhaseDoneJS(self::PHASE_LOADJS, 'console.log("'.sprintf($message, $this->getID(), 'LOADJS').'")'); + $this->addPhaseDoneJS(self::PHASE_EXECJS, 'console.log("'.sprintf($message, $this->getID(), 'EXECJS').'")'); + } +}
\ No newline at end of file diff --git a/include/classes/BigPipe/Pagelet.php b/include/classes/BigPipe/Pagelet.php index 6fe0032..d1c335f 100755 --- a/include/classes/BigPipe/Pagelet.php +++ b/include/classes/BigPipe/Pagelet.php @@ -3,82 +3,117 @@ namespace BigPipe; class Pagelet { private $ID = NULL; - private $HTML = NULL; + private $HTML = ""; private $JSCode = ""; - private $CSSFiles = []; private $JSFiles = []; + private $CSSFiles = []; + private $phaseDoneJS = []; private static $count = 0; - public function __construct($priority = 50) { + #==================================================================================================== + # Priorities for sorting the pagelets + #==================================================================================================== + const PRIORITY_HIGHEST = 100; + const PRIORITY_HIGH = 75; + const PRIORITY_NORMAL = 50; + const PRIORITY_LOW = 25; + const PRIORITY_LOWEST = 0; + + #==================================================================================================== + # Callback phase numbers for PhaseDoneJS + #==================================================================================================== + const PHASE_ARRIVE = 0; # After the pagelet reached BigPipe + const PHASE_LOADCSS = 1; # After all the CSS resources have been loaded + const PHASE_PUTHTML = 2; # After the HTML content has been injected into the placeholders + const PHASE_LOADJS = 3; # After all the JS resources have been loaded + const PHASE_EXECJS = 4; # After the static JS code has been executed + + public function __construct($priority = self::PRIORITY_NORMAL) { + $this->phaseDoneJS = array_pad([], 5, []); $this->ID = 'P'.++self::$count; + BigPipe::addPagelet($this, $priority); } #==================================================================================================== - # ID zurückgeben + # Return the unique ID #==================================================================================================== public function getID() { return $this->ID; } #==================================================================================================== - # HTML-Code zurückgeben + # Return the HTML content #==================================================================================================== public function getHTML() { return $this->HTML; } #==================================================================================================== - # CSS-Ressourcen zurückgeben + # Return the CSS resources #==================================================================================================== public function getCSSFiles() { return $this->CSSFiles; } #==================================================================================================== - # JS-Ressourcen zurückgeben + # Return the JS resources #==================================================================================================== public function getJSFiles() { return $this->JSFiles; } #==================================================================================================== - # JS-Code zurückgeben + # Return the main JS code #==================================================================================================== public function getJSCode() { return $this->JSCode; } #==================================================================================================== - # HTML-Code hinzufügen + # Add HTML or attach more #==================================================================================================== public function addHTML($HTML) { - $this->HTML .= $HTML; + return $this->HTML .= $HTML; } #==================================================================================================== - # CSS-Ressource hinzufügen + # Attach a CSS resource #==================================================================================================== public function addCSS($file) { - $this->CSSFiles[] = $file; + return $this->CSSFiles[] = $file; } #==================================================================================================== - # JS-Ressource hinzufügen + # Attach a JS resource #==================================================================================================== public function addJS($file) { - $this->JSFiles[] = $file; + return $this->JSFiles[] = $file; } #==================================================================================================== - # JS-Code hinzufügen + # Add JS code or attach more #==================================================================================================== public function addJSCode($code) { - $this->JSCode .= $code; + return $this->JSCode .= $code; + } + + #==================================================================================================== + # Attach a PhaseDoneJS callback + #==================================================================================================== + public function addPhaseDoneJS($phase, $callback) { + return $this->phaseDoneJS[$phase][] = removeLineBreaksAndTabs($callback); + } + + #==================================================================================================== + # Return all registered PhaseDoneJS callbacks + #==================================================================================================== + public function getPhaseDoneJS() { + return $this->phaseDoneJS; } #==================================================================================================== - # Magische Methode: __toString() + # Magic method: __toString() #==================================================================================================== public function __toString() { return '<div id="'.$this->getID().'">'.((!BigPipe::isEnabled()) ? $this->getHTML() : NULL).'</div>'; diff --git a/include/functions.php b/include/functions.php index 443d594..21eb3f0 100755 --- a/include/functions.php +++ b/include/functions.php @@ -1,6 +1,6 @@ <?php #==================================================================================================== -# FUNCTION: Entfernt alle Zeilenumbrüche und Tabulatoren aus einem String +# FUNCTION: Removes all line breaks and tabs from a string or an array with strings #==================================================================================================== function removeLineBreaksAndTabs($mixed, $replace = NULL) { if(is_array($mixed)) { @@ -1,39 +1,48 @@ <?php #==================================================================================================== -# Cache deaktivieren +# Deactivate caching #==================================================================================================== header('Cache-Control: no-cache, no-store, must-revalidate'); #==================================================================================================== -# Klassen und Funktionen einbinden +# Include classes and functions #==================================================================================================== require_once 'include/classes/BigPipe/BigPipe.php'; require_once 'include/classes/BigPipe/Pagelet.php'; +require_once 'include/classes/BigPipe/DemoPagelet.php'; require_once 'include/functions.php'; #==================================================================================================== -# Pagelet mit rotem Hintergrund +# Check if BigPipe should be disabled #==================================================================================================== -$PageletRed = new BigPipe\Pagelet(); -$PageletRed->addHTML('<section id="red" class="text">I AM JUST A PAGELET WITH RED BACKGROUND</section>'); +if(isset($_GET['bigpipe']) AND (int) $_GET['bigpipe'] === 0) { + // You can also check for search spiders and disable the pipeline + BigPipe\BigPipe::enablePipeline(FALSE); +} + +#==================================================================================================== +# Pagelet with red background color +#==================================================================================================== +$PageletRed = new BigPipe\DemoPagelet(); +$PageletRed->addHTML('<section id="red" class="text">I AM A PAGELET WITH RED BACKGROUND</section>'); $PageletRed->addCSS('static/red.php'); $PageletRed->addJS('static/delayJS.php'); $PageletRed->addJSCode("document.getElementById('red').innerHTML += ' [JS executed]';document.getElementById('red').style.borderRadius = '30px';"); #==================================================================================================== -# Pagelet mit blauem Hintergrund +# Pagelet with blue background color #==================================================================================================== -$PageletBlue = new BigPipe\Pagelet(60); -$PageletBlue->addHTML('<section id="blue" class="text">I AM JUST A PAGELET WITH BLUE BACKGROUND</section>'); +$PageletBlue = new BigPipe\DemoPagelet(BigPipe\Pagelet::PRIORITY_HIGH); +$PageletBlue->addHTML('<section id="blue" class="text">I AM A PAGELET WITH BLUE BACKGROUND</section>'); $PageletBlue->addCSS('static/blue.php'); $PageletBlue->addJS('static/delayJS.php'); $PageletBlue->addJSCode("document.getElementById('blue').innerHTML += ' [JS executed]';document.getElementById('blue').style.borderRadius = '30px';"); #==================================================================================================== -# Pagelet mit grünem Hintergrund +# Pagelet with green background color #==================================================================================================== -$PageletGreen = new BigPipe\Pagelet(); -$PageletGreen->addHTML('<section id="green" class="text">I AM JUST A PAGELET WITH GREEN BACKGROUND</section>'); +$PageletGreen = new BigPipe\DemoPagelet(); +$PageletGreen->addHTML('<section id="green" class="text">I AM A PAGELET WITH GREEN BACKGROUND</section>'); $PageletGreen->addCSS('static/green.php'); $PageletGreen->addJS('static/delayJS.php'); $PageletGreen->addJSCode("document.getElementById('green').innerHTML += ' [JS executed]';document.getElementById('green').style.borderRadius = '30px';"); @@ -47,6 +56,7 @@ $PageletGreen->addJSCode("document.getElementById('green').innerHTML += ' [JS ex html{margin:0;padding:0;background:#B9C3D2;font-family:Calibri,Sans-Serif;} body{max-width:1200px;margin:0 auto;} .text{color:white;margin-bottom:30px;padding:40px;border-radius:4px;font-weight:600;text-align:center;border:4px solid black;} + .hidden{display:none;} </style> <script> var globalExecution = function globalExecution(code) { @@ -54,17 +64,16 @@ $PageletGreen->addJSCode("document.getElementById('green').innerHTML += ' [JS ex }; </script> <script src="static/bigpipe.js"></script> - <script src="static/bigpipe-callbacks.js"></script> - <title>BigPipe Example</title> + <title>BigPipe Demo</title> </head> <body> -<h1>BigPipe Example</h1> -<p>Auf dieser Beispielseite werden insgesamt 3 Pagelets gerendert von denen alle jeweils eine CSS- und eine JS-Ressource haben. Wobei jede der CSS-Ressourcen die Hintergrundfarbe des zugehörigen Pagelets ändert. -BigPipe wird hingehen und diese Pagelets der Reihe nach rendern. Dabei werden zuerst die zugehörigen CSS-Ressourcen geladen und dann der HTML-Code injiziert. Wenn dann von allen Pagelets die CSS-Ressourcen geladen -und der HTML-Code injiziert ist, dann wird BigPipe die JS-Ressourcen der Pagelets einbinden und den statischen Javascript-Code (falls vorhanden) ausführen. Damit man den Pipeline-Effekt auf dieser Beispielseite auch -sieht werden die CSS- und JS-Ressourcen über ein Delayscript geleitet. Debuginformationen findest du in der Javascript-Konsole.</p> +<h1>BigPipe Demo</h1> +<p>You see on this page 3 pagelets are getting rendered. Each pagelet has his own CSS and JS resources. The CSS resources change the background color of the pagelet (so you can see the effect when the CSS is loaded). The next step is to load the JS resources and they change the border-radius of the pagelet. After the loading of CSS and JS resources the static JS callback get executed. Additionally, the PhaseDoneJS callbacks performed for each pagelet phase. See the javascript console for more debug informations.</p> +<p>PhaseDoneJS is a new feature of BigPipe which can execute JS callbacks for each pagelet phase. Each pagelet can have multiple PhaseDoneJS callbacks for each phase. The difference between a PhaseDoneJS callback and a static JS callback ("JS_CODE") is the following: The static JS callback always get executed (regardless of whether the pipeline is enabled or disabled) and can be a main part of the JS from the pagelet. But the PhaseDoneJS callbacks are only executed if the pipeline is enabled. They are suitable for application-specific stuff.</p> + +<p><b>More information [at this time only in german; sorry]:</b><br /><a href="https://blackphantom.de/artikel/bigpipe-website-pipelining-und-schnellerer-aufbau-durch-einzelne-pagelets/" target="_blank">https://blackphantom.de/artikel/bigpipe-website-pipelining-und-schnellerer-aufbau-durch-einzelne-pagelets/</a></p> -<p><b>Weitere Informationen:</b> <a href="https://blackphantom.de/artikel/bigpipe-website-pipelining-und-schnellerer-aufbau-durch-einzelne-pagelets/" target="_blank">https://blackphantom.de/artikel/bigpipe-website-pipelining-und-schnellerer-aufbau-durch-einzelne-pagelets/</a></p> +<p><b>Check if output flushing works on your server:</b><br /><a href="output-flushing-test.php">output-flushing-test.php</a></p> <?php echo $PageletRed; diff --git a/output-flushing-test.php b/output-flushing-test.php new file mode 100755 index 0000000..410208f --- /dev/null +++ b/output-flushing-test.php @@ -0,0 +1,12 @@ +<?php +header('Content-Type: text/plain; charset=UTF-8'); + +echo "[INFO: If you see the single blocks successively, then the output flushing on your server works. If not, and you see it all at once, your server need to be configured to use output flushing.]\n\n"; + +for($i = 1; $i <= 8; $i++) { + echo '[BLOCK: '.$i.']'."\n".str_repeat('[0]', 1500)."\n\n\n"; + flush(); usleep(750000); +} + +echo '[ALL BLOCKS LOADED]'; +?>
\ No newline at end of file diff --git a/static/bigpipe-callbacks.js b/static/bigpipe-callbacks.js deleted file mode 100755 index a9f48f1..0000000 --- a/static/bigpipe-callbacks.js +++ /dev/null @@ -1,27 +0,0 @@ -// Folgende Phasen stehen zur Auswahl: PAGELET_STARTED, RESOURCE_DONE, PAGELET_HTML_RENDERED, PAGELET_JS_EXECUTED und BIGPIPE_PAGELETS_RENDERED - -var debugLine = "------------------------------------------------------------------------------------------------------------------------"; - -BigPipe.registerPhaseDoneCallback('PAGELET_STARTED', function(Pagelet) { - console.log(debugLine); - console.log(Pagelet.pageletID + ":\t" + "Die Ausführung des Pagelets wurde gestartet."); -}); - -BigPipe.registerPhaseDoneCallback('RESOURCE_DONE', function(Resource) { - console.log(Resource.pageletID + ":\t" + 'Die Ressource ' + Resource.file + ' wurde geladen.'); -}); - -BigPipe.registerPhaseDoneCallback('PAGELET_HTML_RENDERED', function(Pagelet) { - console.log(Pagelet.pageletID + ":\t" + 'Die Platzhalter wurden mit HTML-Code befüllt.'); -}); - -BigPipe.registerPhaseDoneCallback('BIGPIPE_PAGELETS_RENDERED', function() { - console.log(debugLine); - console.log('BP' + ":\t" + 'Die Platzhalter von allen Pagelets wurden mit ihrem HTML-Code befüllt.'); - console.log(debugLine); -}); - -BigPipe.registerPhaseDoneCallback('PAGELET_JS_EXECUTED', function(Pagelet) { - console.log(Pagelet.pageletID + ":\t" + 'Der zugehörige Javascript-Code des Pagelets wurde ausgeführt.'); - console.log(debugLine); -});
\ No newline at end of file diff --git a/static/bigpipe.js b/static/bigpipe.js index d3289b6..0fcf68f 100755 --- a/static/bigpipe.js +++ b/static/bigpipe.js @@ -1,58 +1,55 @@ //=================================================================================================== -// REVEALING MODLUE PATTERN: BigPipe +// Revealing Module Pattern //=================================================================================================== var BigPipe = (function() { //=================================================================================================== - // PROTOTYPE: PageletResource-Konstruktor + // Resource: Represents a single CSS or JS resource //=================================================================================================== - function PageletResource(file, type, pageletID) { - this.pageletID = pageletID; + function Resource(resourceURL, type) { + this.resourceURL = resourceURL; this.callbacks = []; this.done = false; - this.file = file; this.type = type; } //=================================================================================================== - // PROTOTYPE: Startet den Ladevorgang der Ressource + // Resource: Loading the resource //=================================================================================================== - PageletResource.prototype.start = function() { + Resource.prototype.start = function() { if(this.type === 0) { var element = document.createElement('link'); element.setAttribute('rel', 'stylesheet'); - element.setAttribute('href', this.file); + element.setAttribute('href', this.resourceURL); } else { var element = document.createElement('script'); - element.setAttribute('src', this.file); + element.setAttribute('src', this.resourceURL); element.async = true; } document.head.appendChild(element); element.onload = function() { - BigPipe.executePhaseDoneCallbacks('RESOURCE_DONE', this); this.executeCallbacks(); }.bind(this); element.onerror = function() { - BigPipe.executePhaseDoneCallbacks('RESOURCE_DONE', this); this.executeCallbacks(); }.bind(this); }; //=================================================================================================== - // PROTOTYPE: Registriert eine Callback-Funktion + // Resource: Register a new callback //=================================================================================================== - PageletResource.prototype.registerCallback = function(callback) { + Resource.prototype.registerCallback = function(callback) { return this.callbacks.push(callback); }; //=================================================================================================== - // PROTOTYPE: Führt alle registrierten Callback-Funktionen aus + // Resource: Executes all registered callbacks //=================================================================================================== - PageletResource.prototype.executeCallbacks = function() { + Resource.prototype.executeCallbacks = function() { if(!this.done) { this.done = true; @@ -63,7 +60,7 @@ var BigPipe = (function() { }; //=================================================================================================== - // PROTOTYPE: Pagelet-Konstruktor + // Pagelet: Represents a single pagelet //=================================================================================================== function Pagelet(data) { this.pageletID = data.ID; @@ -72,36 +69,62 @@ var BigPipe = (function() { this.JSFiles = data.RESOURCES.JS; this.JSCode = data.RESOURCES.JS_CODE; - this.phase = 0; // 1 => Laden von CSS-Ressourcen, 2 => CSS-Ressourcen geladen, 3 => HTML wurde injiziert, 4 => JS-Ressourcen geladen und JS-Code ausgeführt + this.phase = 0; this.CSSResources = []; this.JSResources = []; + + this.phaseDoneJS = data.PHASES; } //=================================================================================================== - // PROTOTYPE: Startet die Initialisierung des Pagelets und startet die Pagelet-Ressourcen + // 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() { - BigPipe.executePhaseDoneCallbacks('PAGELET_STARTED', this); - this.CSSFiles.forEach(function(file) { - this.attachCSSResource(new PageletResource(file, 0, this.pageletID)); + var isStarted = false; + + this.CSSFiles.forEach(function(resourceURL) { + this.attachCSSResource(new Resource(resourceURL, 0)); }.bind(this)); - this.JSFiles.forEach(function(file) { - this.attachJSResource(new PageletResource(file, 1, this.pageletID)); + this.JSFiles.forEach(function(resourceURL) { + this.attachJSResource(new Resource(resourceURL, 1)); }.bind(this)); this.CSSResources.forEach(function(resource) { - this.phase = 1; + isStarted = true; resource.start(); }.bind(this)); - if(this.phase === 0) { - this.injectHTML(); - } + // If no CSS resource was started (= no external CSS resources exists), then begin to inject the HTML + !isStarted && this.injectHTML(); }; //=================================================================================================== - // PROTOTYPE: Fügt eine CSS-Ressource hinzu + // Pagelet: Attach a new CSS resource to the pagelet //=================================================================================================== Pagelet.prototype.attachCSSResource = function(resource) { resource.registerCallback(this.onloadCSS.bind(this)); @@ -109,7 +132,7 @@ var BigPipe = (function() { }; //=================================================================================================== - // PROTOTYPE: Fügt eine JS-Ressource hinzu + // Pagelet: Attach a new JS resource to the pagelet //=================================================================================================== Pagelet.prototype.attachJSResource = function(resource) { resource.registerCallback(this.onloadJS.bind(this)); @@ -117,76 +140,69 @@ var BigPipe = (function() { }; //=================================================================================================== - // PROTOTYPE: Führt den statischen JS-Code des Pagelets aus + // Pagelet: Executes the main JS code of the pagelet //=================================================================================================== Pagelet.prototype.executeJSCode = function() { try { globalExecution(this.JSCode); - BigPipe.executePhaseDoneCallbacks('PAGELET_JS_EXECUTED', this); } catch(e) { - console.error(this.pageletID + ":\t" + e); + console.error(this.pageletID + ": " + e); } }; //=================================================================================================== - // PROTOTYPE: Pagelet-Methode + // 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; - })) { + return resource.done; + })) { + this.phaseDoneHandler(3); this.executeJSCode(); - this.phase = 4; + this.phaseDoneHandler(4); } }; //=================================================================================================== - // PROTOTYPE: Pagelet-Methode + // 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; - })) { + return resource.done; + })) { this.injectHTML(); } }; //=================================================================================================== - // PROTOTYPE: Injiziert den HTML-Code des Pagelets in den DOM + // Pagelet: Injects the HTML content into the DOM //=================================================================================================== Pagelet.prototype.injectHTML = function() { - this.phase = 2; - if(placeholder = document.getElementById(this.pageletID)) { - if(this.HTML) { - placeholder.innerHTML = this.HTML; - } + this.phaseDoneHandler(1); - else { - var content = document.getElementById('_' + this.pageletID); - placeholder.innerHTML = content.innerHTML.substring(5, content.innerHTML.length - 4); - document.body.removeChild(content); - } + 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.phase = 3; + this.phaseDoneHandler(2); - BigPipe.executePhaseDoneCallbacks('PAGELET_HTML_RENDERED', this); 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.executePhaseDoneCallbacks('BIGPIPE_PAGELETS_RENDERED'); BigPipe.loadJSResources(); } }; //=================================================================================================== - // BigPipe-Hauptobjekt + // BigPipe //=================================================================================================== var BigPipe = { pagelets: [], - phase: 0, // 1 => Erstes Pagelet gestartet, 2 => Alle Pagelets angekommen, 3 => JS-Ressourcen geladen + JS-Code ausgeführt + phase: 0, offset: 0, - phaseDoneCallbacks: {}, executeNextPagelet: function() { if(this.pagelets[this.offset]) { @@ -194,27 +210,15 @@ var BigPipe = (function() { } else if(this.phase < 2) { - setTimeout(this.executeNextPagelet.bind(this), 30); - } - }, - - registerPhaseDoneCallback: function(phase, callback) { - if(!this.phaseDoneCallbacks[phase]) { - this.phaseDoneCallbacks[phase] = []; - } - return this.phaseDoneCallbacks[phase].push(callback); - }, - - executePhaseDoneCallbacks: function(phase, param) { - if(this.phaseDoneCallbacks[phase]) { - this.phaseDoneCallbacks[phase].forEach(function(callback) { - callback(param); - }); + setTimeout(this.executeNextPagelet.bind(this), 20); } }, onPageletArrive: function(data) { - if(this.pagelets.push(new Pagelet(data)) && this.phase === 0 && !data.IS_LAST) { + var pagelet = new Pagelet(data); + pagelet.phaseDoneHandler(0); + + if(this.pagelets.push(pagelet) && this.phase === 0 && !data.IS_LAST) { this.phase = 1; this.executeNextPagelet(); } @@ -260,12 +264,7 @@ var BigPipe = (function() { BigPipe.onPageletArrive(data); }, - registerPhaseDoneCallback: function(phase, callback) { - BigPipe.registerPhaseDoneCallback(phase, callback); - }, - reset: function() { - BigPipe.phaseDoneCallbacks = {}; BigPipe.pagelets = []; BigPipe.offset = 0; BigPipe.phase = 0; diff --git a/static/blue.php b/static/blue.php index ddffcf6..e715d83 100755 --- a/static/blue.php +++ b/static/blue.php @@ -1,16 +1,16 @@ <?php #==================================================================================================== -# Cache deaktivieren +# Disable cache #==================================================================================================== header('Cache-Control: no-cache, no-store, must-revalidate'); #==================================================================================================== -# Content-Type setzen +# Set Content-Type #==================================================================================================== header('Content-Type: text/css'); #==================================================================================================== -# Lange Ladezeit simulieren +# Simulate long loading time #==================================================================================================== usleep(intval(rand(60, 100).'0000')); ?> diff --git a/static/delayJS.php b/static/delayJS.php index 1307ca0..96e46c5 100755 --- a/static/delayJS.php +++ b/static/delayJS.php @@ -1,16 +1,18 @@ <?php #==================================================================================================== -# Cache deaktivieren +# Disable cache #==================================================================================================== header('Cache-Control: no-cache, no-store, must-revalidate'); #==================================================================================================== -# Content-Type setzen +# Set Content-Type #==================================================================================================== header('Content-Type: text/javascript'); #==================================================================================================== -# Lange Ladezeit simulieren +# Simulate long loading time #==================================================================================================== usleep(intval(rand(10, 40).'0000')); -?>
\ No newline at end of file +?> + +console.log("EXTERNAL: Delayed javascript resource loaded"); diff --git a/static/green.php b/static/green.php index 3e45fc6..65ded6f 100755 --- a/static/green.php +++ b/static/green.php @@ -1,16 +1,16 @@ <?php #==================================================================================================== -# Cache deaktivieren +# Disable cache #==================================================================================================== header('Cache-Control: no-cache, no-store, must-revalidate'); #==================================================================================================== -# Content-Type setzen +# Set Content-Type #==================================================================================================== header('Content-Type: text/css'); #==================================================================================================== -# Lange Ladezeit simulieren +# Simulate long loading time #==================================================================================================== usleep(intval(rand(60, 100).'0000')); ?> diff --git a/static/red.php b/static/red.php index 9ad993e..e6936e8 100755 --- a/static/red.php +++ b/static/red.php @@ -1,16 +1,16 @@ <?php #==================================================================================================== -# Cache deaktivieren +# Disable cache #==================================================================================================== header('Cache-Control: no-cache, no-store, must-revalidate'); #==================================================================================================== -# Content-Type setzen +# Set Content-Type #==================================================================================================== header('Content-Type: text/css'); #==================================================================================================== -# Lange Ladezeit simulieren +# Simulate long loading time #==================================================================================================== usleep(intval(rand(60, 100).'0000')); ?> |