diff options
-rwxr-xr-x | async.php | 144 | ||||
-rwxr-xr-x | include/classes/BigPipe/BigPipe.php | 26 | ||||
-rwxr-xr-x | include/classes/BigPipe/Pagelet.php | 56 | ||||
-rwxr-xr-x | include/functions.php | 22 | ||||
-rwxr-xr-x | index.php | 176 | ||||
-rwxr-xr-x | output-flushing-test.php | 22 | ||||
-rwxr-xr-x | static/bigpipe.js | 544 | ||||
-rwxr-xr-x | static/blue.php | 32 | ||||
-rwxr-xr-x | static/delayJS.php | 36 | ||||
-rwxr-xr-x | static/green.php | 32 | ||||
-rwxr-xr-x | static/red.php | 32 |
11 files changed, 634 insertions, 488 deletions
diff --git a/async.php b/async.php new file mode 100755 index 0000000..9093c87 --- /dev/null +++ b/async.php @@ -0,0 +1,144 @@ +<?php
+# >>> [Additional code for the async function]
+
+#===============================================================================
+# FUNCTION: Return TRUE if the request awaiting a async response
+#===============================================================================
+function isAsyncRequest() {
+ return isset($_GET['response']) AND $_GET['response'] === 'async';
+}
+
+# <<<
+
+#===============================================================================
+# Deactivate caching
+#===============================================================================
+header('Cache-Control: no-cache, no-store, must-revalidate');
+
+#===============================================================================
+# 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';
+
+#===============================================================================
+# Check if BigPipe should be disabled
+#===============================================================================
+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">['.time().'] 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 with blue background color
+#===============================================================================
+$PageletBlue = new BigPipe\DemoPagelet('customPageletID', BigPipe\Pagelet::PRIORITY_HIGH);
+$PageletBlue->addHTML('<section id="blue" class="text">['.time().'] 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 with green background color
+#===============================================================================
+$PageletGreen = new BigPipe\DemoPagelet();
+$PageletGreen->addHTML('<section id="green" class="text">['.time().'] 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';");
+?>
+<!DOCTYPE html>
+<html lang="de">
+<?php if(!isAsyncRequest()): ?>
+<head>
+ <meta charset="UTF-8" />
+ <meta name="robots" content="noindex, nofollow" />
+ <style>
+ 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) {
+ window.execScript ? window.execScript(code) : window.eval.call(window, code);
+ };
+ </script>
+ <script src="static/bigpipe.js"></script>
+ <title>BigPipe Demo</title>
+ <!-- >>> [Additional code for the async function] -->
+ <script>
+ var Application = {
+ placeholderHTML: function(HTML) {
+ document.getElementById('placeholder_container').innerHTML = HTML;
+ }
+ };
+
+ function fireAsyncRequest(href) {
+ console.info('ASYNC REQUEST FIRED!');
+ Application.placeholderHTML("");
+ BigPipe.reset();
+ var transport_frame;
+
+ if(transport_frame = document.getElementById('transport_frame')) {
+ document.body.removeChild(transport_frame);
+ }
+
+ var iframe = document.createElement('iframe');
+ iframe.setAttribute('id', 'transport_frame');
+ iframe.setAttribute('class', 'hidden');
+ iframe.setAttribute('src', href + '?response=async');
+
+ document.body.appendChild(iframe);
+
+ iframe.onload = function() {
+ document.body.removeChild(iframe);
+ }.bind(this);
+
+ return false;
+ }
+ </script>
+ <!-- <<< -->
+</head>
+<?php endif; ?>
+<body>
+<?php if(!isAsyncRequest()): ?>
+<h1>BigPipe Async Demo</h1>
+
+<p><a href="async.php" onclick="return fireAsyncRequest(this)">LOAD CONTENT VIA TRANSPORT FRAME</a> [Current Time: <?=time();?> – So you can see, that the page does not get completely reloaded]</p>
+<p><em>Look at the developer console of your browser to see the debug messages and how the async response from server looks.</em></p>
+
+<section id="placeholder_container">
+ <?php else: ob_start(); endif; ?>
+ <?php
+ echo $PageletRed;
+ echo $PageletBlue;
+ echo $PageletGreen;
+ ?>
+ <?php if(!isAsyncRequest()):?>
+</section>
+<footer><strong>The footer of the page.</strong></footer>
+
+<?php endif;
+if(isAsyncRequest()) {
+ $BUFFER = removeLineBreaksAndTabs(ob_get_clean());
+ echo '<script>["Application","BigPipe"].forEach(function(name){window[name] = parent[name];});</script>'."\n";
+ echo '<script>["BigPipe", "Application"].forEach(function(name){window[name] = parent[name];});</script>'."\n";
+ echo '<script>Application.placeholderHTML('.json_encode($BUFFER).');</script>'."\n\n";
+}
+
+BigPipe\BigPipe::render();
+?>
+</body>
+</html>
\ No newline at end of file diff --git a/include/classes/BigPipe/BigPipe.php b/include/classes/BigPipe/BigPipe.php index 740d047..63cb711 100755 --- a/include/classes/BigPipe/BigPipe.php +++ b/include/classes/BigPipe/BigPipe.php @@ -7,31 +7,31 @@ class BigPipe { private static $pagelets = []; private static $count = 0; - #==================================================================================================== + #=============================================================================== # Return TRUE if the pipeline is enabled - #==================================================================================================== + #=============================================================================== public static function isEnabled() { return self::$enabled; } - #==================================================================================================== + #=============================================================================== # 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; return ++self::$count; } - #==================================================================================================== + #=============================================================================== # Prints a single pagelet response - #==================================================================================================== + #=============================================================================== private static function singleResponse(Pagelet $Pagelet, $last = FALSE) { $data = [ 'ID' => $Pagelet->getID(), @@ -47,19 +47,19 @@ class BigPipe { $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"; + echo "<script>BigPipe.onPageletArrive({$pageletJSON}, (document.getElementById(\"_{$Pagelet->getID()}\")));</script>\n\n"; } - #==================================================================================================== + #=============================================================================== # Sends output buffer so far as possible towards user - #==================================================================================================== + #=============================================================================== public static function flushOutputBuffer() { ob_flush(); flush(); } - #==================================================================================================== + #=============================================================================== # Render the pagelets - #==================================================================================================== + #=============================================================================== public static function render() { self::flushOutputBuffer(); diff --git a/include/classes/BigPipe/Pagelet.php b/include/classes/BigPipe/Pagelet.php index 3b5530c..3a6c64e 100755 --- a/include/classes/BigPipe/Pagelet.php +++ b/include/classes/BigPipe/Pagelet.php @@ -10,18 +10,18 @@ class Pagelet { private $phaseDoneJS = []; private static $count = 0; - #==================================================================================================== + #=============================================================================== # 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 @@ -35,86 +35,86 @@ class Pagelet { BigPipe::addPagelet($this, $priority); } - #==================================================================================================== + #=============================================================================== # Return the unique ID - #==================================================================================================== + #=============================================================================== public function getID() { return $this->ID; } - #==================================================================================================== + #=============================================================================== # Return the HTML content - #==================================================================================================== + #=============================================================================== public function getHTML() { return $this->HTML; } - #==================================================================================================== + #=============================================================================== # Return the CSS resources - #==================================================================================================== + #=============================================================================== public function getCSSFiles() { return $this->CSSFiles; } - #==================================================================================================== + #=============================================================================== # Return the JS resources - #==================================================================================================== + #=============================================================================== public function getJSFiles() { return $this->JSFiles; } - #==================================================================================================== + #=============================================================================== # Return the main JS code - #==================================================================================================== + #=============================================================================== public function getJSCode() { return $this->JSCode; } - #==================================================================================================== + #=============================================================================== # Add HTML or attach more - #==================================================================================================== + #=============================================================================== public function addHTML($HTML) { return $this->HTML .= $HTML; } - #==================================================================================================== + #=============================================================================== # Attach a CSS resource - #==================================================================================================== + #=============================================================================== public function addCSS($file) { return $this->CSSFiles[] = $file; } - #==================================================================================================== + #=============================================================================== # Attach a JS resource - #==================================================================================================== + #=============================================================================== public function addJS($file) { return $this->JSFiles[] = $file; } - #==================================================================================================== + #=============================================================================== # Add JS code or attach more - #==================================================================================================== + #=============================================================================== public function addJSCode($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; } - #==================================================================================================== + #=============================================================================== # 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 21eb3f0..d06823d 100755 --- a/include/functions.php +++ b/include/functions.php @@ -1,12 +1,12 @@ -<?php -#==================================================================================================== -# FUNCTION: Removes all line breaks and tabs from a string or an array with strings -#==================================================================================================== -function removeLineBreaksAndTabs($mixed, $replace = NULL) { - if(is_array($mixed)) { - return array_map(__FUNCTION__, $mixed); - } - - return is_string($mixed) ? str_replace(["\r\n", "\r", "\n", "\t"], $replace, $mixed) : $mixed; -} +<?php
+#===============================================================================
+# FUNCTION: Removes all line breaks and tabs from a string or an array with strings
+#===============================================================================
+function removeLineBreaksAndTabs($mixed, $replace = NULL) {
+ if(is_array($mixed)) {
+ return array_map(__FUNCTION__, $mixed);
+ }
+
+ return is_string($mixed) ? str_replace(["\r\n", "\r", "\n", "\t"], $replace, $mixed) : $mixed;
+}
?>
\ No newline at end of file @@ -1,88 +1,90 @@ -<?php -#==================================================================================================== -# Deactivate caching -#==================================================================================================== -header('Cache-Control: no-cache, no-store, must-revalidate'); - -#==================================================================================================== -# 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'; - -#==================================================================================================== -# Check if BigPipe should be disabled -#==================================================================================================== -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 with blue background color -#==================================================================================================== -$PageletBlue = new BigPipe\DemoPagelet('customPageletID', 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 with green background color -#==================================================================================================== -$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';"); -?> -<!DOCTYPE html> -<html lang="de"> -<head> - <meta charset="UTF-8" /> - <meta name="robots" content="noindex, nofollow" /> - <style> - 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) { - window.execScript ? window.execScript(code) : window.eval.call(window, code); - }; - </script> - <script src="static/bigpipe.js"></script> - <title>BigPipe Demo</title> -</head> -<body> -<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>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; -echo $PageletBlue; -echo $PageletGreen; -?> - -<?php -BigPipe\BigPipe::render(); -?> -</body> +<?php
+#===============================================================================
+# Deactivate caching
+#===============================================================================
+header('Cache-Control: no-cache, no-store, must-revalidate');
+
+#===============================================================================
+# 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';
+
+#===============================================================================
+# Check if BigPipe should be disabled
+#===============================================================================
+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 with blue background color
+#===============================================================================
+$PageletBlue = new BigPipe\DemoPagelet('customPageletID', 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 with green background color
+#===============================================================================
+$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';");
+?>
+<!DOCTYPE html>
+<html lang="de">
+<head>
+ <meta charset="UTF-8" />
+ <meta name="robots" content="noindex, nofollow" />
+ <style>
+ 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) {
+ window.execScript ? window.execScript(code) : window.eval.call(window, code);
+ };
+ </script>
+ <script src="static/bigpipe.js"></script>
+ <title>BigPipe Demo</title>
+</head>
+<body>
+<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><strong>Notice:</strong> BigPipe may support the features of the new <em>PHP 7</em> in the future and you may also benefit from the performance boost with <em>PHP 7</em>.</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;
+echo $PageletBlue;
+echo $PageletGreen;
+?>
+
+<footer><strong>The footer of the page.</strong></footer>
+
+<?php
+BigPipe\BigPipe::render();
+?>
+</body>
</html>
\ No newline at end of file diff --git a/output-flushing-test.php b/output-flushing-test.php index 410208f..faaf9bc 100755 --- a/output-flushing-test.php +++ b/output-flushing-test.php @@ -1,12 +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]'; +<?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.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 @@ -<?php -#==================================================================================================== -# Disable cache -#==================================================================================================== -header('Cache-Control: no-cache, no-store, must-revalidate'); - -#==================================================================================================== -# Set Content-Type -#==================================================================================================== -header('Content-Type: text/css'); - -#==================================================================================================== -# Simulate long loading time -#==================================================================================================== -usleep(intval(rand(60, 100).'0000')); -?> +<?php
+#===============================================================================
+# Disable cache
+#===============================================================================
+header('Cache-Control: no-cache, no-store, must-revalidate');
+
+#===============================================================================
+# Set Content-Type
+#===============================================================================
+header('Content-Type: text/css');
+
+#===============================================================================
+# Simulate long loading time
+#===============================================================================
+usleep(intval(rand(60, 100).'0000'));
+?>
#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 @@ -<?php -#==================================================================================================== -# Disable cache -#==================================================================================================== -header('Cache-Control: no-cache, no-store, must-revalidate'); - -#==================================================================================================== -# Set Content-Type -#==================================================================================================== -header('Content-Type: text/javascript'); - -#==================================================================================================== -# Simulate long loading time -#==================================================================================================== -usleep(intval(rand(10, 40).'0000')); -?> - -console.log("EXTERNAL: Delayed javascript resource loaded"); +<?php
+#===============================================================================
+# Disable cache
+#===============================================================================
+header('Cache-Control: no-cache, no-store, must-revalidate');
+
+#===============================================================================
+# Set Content-Type
+#===============================================================================
+header('Content-Type: text/javascript');
+
+#===============================================================================
+# Simulate long loading time
+#===============================================================================
+usleep(intval(rand(10, 40).'0000'));
+?>
+
+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 @@ -<?php -#==================================================================================================== -# Disable cache -#==================================================================================================== -header('Cache-Control: no-cache, no-store, must-revalidate'); - -#==================================================================================================== -# Set Content-Type -#==================================================================================================== -header('Content-Type: text/css'); - -#==================================================================================================== -# Simulate long loading time -#==================================================================================================== -usleep(intval(rand(60, 100).'0000')); -?> +<?php
+#===============================================================================
+# Disable cache
+#===============================================================================
+header('Cache-Control: no-cache, no-store, must-revalidate');
+
+#===============================================================================
+# Set Content-Type
+#===============================================================================
+header('Content-Type: text/css');
+
+#===============================================================================
+# Simulate long loading time
+#===============================================================================
+usleep(intval(rand(60, 100).'0000'));
+?>
#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 @@ -<?php -#==================================================================================================== -# Disable cache -#==================================================================================================== -header('Cache-Control: no-cache, no-store, must-revalidate'); - -#==================================================================================================== -# Set Content-Type -#==================================================================================================== -header('Content-Type: text/css'); - -#==================================================================================================== -# Simulate long loading time -#==================================================================================================== -usleep(intval(rand(60, 100).'0000')); -?> +<?php
+#===============================================================================
+# Disable cache
+#===============================================================================
+header('Cache-Control: no-cache, no-store, must-revalidate');
+
+#===============================================================================
+# Set Content-Type
+#===============================================================================
+header('Content-Type: text/css');
+
+#===============================================================================
+# Simulate long loading time
+#===============================================================================
+usleep(intval(rand(60, 100).'0000'));
+?>
#red{background:red;}
\ No newline at end of file |