NEW Force the javascripts to be put before the closing body tag

This commit is contained in:
Firesphere 2013-12-07 15:38:51 +01:00
parent 14447b167a
commit 41371fea72
2 changed files with 62 additions and 4 deletions

View File

@ -350,6 +350,45 @@ class RequirementsTest extends SapphireTest {
$this->assertContains('</script></body>', $html); $this->assertContains('</script></body>', $html);
} }
public function testForceJsToBottom() {
$backend = new Requirements_Backend();
$backend->javascript('http://www.mydomain.com/test.js');
// Test matching with HTML5 <header> tags as well
$template = '<html><head></head><body><header>My header</header><p>Body<script></script></p></body></html>';
// Test if the script is before the first <script> tag, not before the body.
$backend->set_write_js_to_body(false);
$backend->set_force_js_to_bottom(false);
$html = $backend->includeInHTML(false, $template);
$this->assertNotContains('</script></body>', $html);
$this->assertNotContains('</script><script', $html);
$this->assertContains('<head><script', $html);
// Test if the script is before the first <script> tag, not before the body.
$backend->set_write_js_to_body(true);
$backend->set_force_js_to_bottom(false);
$html = $backend->includeInHTML(false, $template);
$this->assertNotContains('</script></body>', $html);
$this->assertContains('</script><script', $html);
// Test if the script is placed just before the closing bodytag, with write-to-body false.
$backend->set_write_js_to_body(false);
$backend->set_force_js_to_bottom(true);
$html = $backend->includeInHTML(false, $template);
$this->assertNotContains('<head><script', $html);
$this->assertNotContains('</script><script', $html);
$this->assertContains('</script></body>', $html);
// Test if the script is placed just before the closing bodytag, with write-to-body true.
$backend->set_write_js_to_body(true);
$backend->set_force_js_to_bottom(true);
$html = $backend->includeInHTML(false, $template);
$this->assertNotContains('<head><script', $html);
$this->assertNotContains('</script><script', $html);
$this->assertContains('</script></body>', $html);
}
public function testSuffix() { public function testSuffix() {
$template = '<html><head></head><body><header>My header</header><p>Body</p></body></html>'; $template = '<html><head></head><body><header>My header</header><p>Body</p></body></html>';
$basePath = $this->getCurrentRelativePath(); $basePath = $this->getCurrentRelativePath();

View File

@ -316,7 +316,7 @@ class Requirements {
* @param boolean $var If true, force the javascripts to be included at the bottom. * @param boolean $var If true, force the javascripts to be included at the bottom.
*/ */
public static function set_force_js_to_bottom($var) { public static function set_force_js_to_bottom($var) {
self::backend()->force_js_to_bottom = $var; self::backend()->set_force_js_to_bottom($var);
} }
public static function debug() { public static function debug() {
@ -454,7 +454,7 @@ class Requirements_Backend {
* *
* @var boolean * @var boolean
*/ */
public $force_js_to_bottom = false; protected $force_js_to_bottom = false;
public function set_combined_files_enabled($enable) { public function set_combined_files_enabled($enable) {
$this->combined_files_enabled = (bool) $enable; $this->combined_files_enabled = (bool) $enable;
@ -506,6 +506,14 @@ class Requirements_Backend {
public function set_write_js_to_body($var) { public function set_write_js_to_body($var) {
$this->write_js_to_body = $var; $this->write_js_to_body = $var;
} }
/**
* Forces the javascript to the end of the body, just before the closing body-tag.
*
* @param boolean
*/
public function set_force_js_to_bottom($var) {
$this->force_js_to_bottom = $var;
}
/** /**
* Register the given javascript file as required. * Register the given javascript file as required.
* Filenames should be relative to the base, eg, 'framework/javascript/loader.js' * Filenames should be relative to the base, eg, 'framework/javascript/loader.js'
@ -720,7 +728,18 @@ class Requirements_Backend {
$requirements .= "$customHeadTag\n"; $requirements .= "$customHeadTag\n";
} }
if($this->write_js_to_body) { if ($this->force_js_to_bottom) {
// Remove all newlines from code to preserve layout
$jsRequirements = preg_replace('/>\n*/', '>', $jsRequirements);
// We put script tags into the body, for performance.
// If your template already has script tags in the body, then we put our script
// tags just before those. Otherwise, we put it at the bottom.
$content = preg_replace("/(<\/body[^>]*>)/i", $jsRequirements . "\\1", $content);
// Put CSS at the bottom of the head
$content = preg_replace("/(<\/head>)/i", $requirements . "\\1", $content);
} elseif($this->write_js_to_body) {
// Remove all newlines from code to preserve layout // Remove all newlines from code to preserve layout
$jsRequirements = preg_replace('/>\n*/', '>', $jsRequirements); $jsRequirements = preg_replace('/>\n*/', '>', $jsRequirements);
@ -730,7 +749,7 @@ class Requirements_Backend {
$p2 = stripos($content, '<body'); $p2 = stripos($content, '<body');
$p1 = stripos($content, '<script', $p2); $p1 = stripos($content, '<script', $p2);
if($p1 !== false && !$this->force_js_to_bottom) { if($p1 !== false) {
$content = substr($content,0,$p1) . $jsRequirements . substr($content,$p1); $content = substr($content,0,$p1) . $jsRequirements . substr($content,$p1);
} else { } else {
$content = preg_replace("/(<\/body[^>]*>)/i", $jsRequirements . "\\1", $content); $content = preg_replace("/(<\/body[^>]*>)/i", $jsRequirements . "\\1", $content);