mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
add async and defer attributes to js requirements, replaces #4555
This commit is contained in:
parent
859acf571e
commit
9fc51dc527
@ -56,7 +56,7 @@ If you're using the CSS method a second argument can be used. This argument defi
|
|||||||
### Javascript Files
|
### Javascript Files
|
||||||
|
|
||||||
:::php
|
:::php
|
||||||
Requirements::javascript($path);
|
Requirements::javascript($path, $options);
|
||||||
|
|
||||||
A variant on the inclusion of custom javascript is the inclusion of *templated* javascript. Here, you keep your
|
A variant on the inclusion of custom javascript is the inclusion of *templated* javascript. Here, you keep your
|
||||||
JavaScript in a separate file and instead load, via search and replace, several PHP-generated variables into that code.
|
JavaScript in a separate file and instead load, via search and replace, several PHP-generated variables into that code.
|
||||||
@ -75,7 +75,6 @@ that your included files provide these scripts. This will ensure that subsequent
|
|||||||
Requirement calls that rely on those included scripts will not double include those
|
Requirement calls that rely on those included scripts will not double include those
|
||||||
files.
|
files.
|
||||||
|
|
||||||
|
|
||||||
:::php
|
:::php
|
||||||
Requirements::javascript('<my-module-dir>/javascript/dist/bundle.js', ['provides' => [
|
Requirements::javascript('<my-module-dir>/javascript/dist/bundle.js', ['provides' => [
|
||||||
'<my-module-dir>/javascript/jquery.js'
|
'<my-module-dir>/javascript/jquery.js'
|
||||||
@ -84,6 +83,16 @@ files.
|
|||||||
]]);
|
]]);
|
||||||
Requirements::javascript('<my-module-dir>/javascript/jquery.js'); // Will will skip this file
|
Requirements::javascript('<my-module-dir>/javascript/jquery.js'); // Will will skip this file
|
||||||
|
|
||||||
|
You can also use the second argumet to add the 'async' and/or 'defer attributes to the script tag generated:
|
||||||
|
|
||||||
|
:::php
|
||||||
|
Requirements::javascript(
|
||||||
|
"<my-module-dir>/javascript/some_file.js",
|
||||||
|
array(
|
||||||
|
"async" => true,
|
||||||
|
"defer" => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
### Custom Inline CSS or Javascript
|
### Custom Inline CSS or Javascript
|
||||||
|
|
||||||
@ -218,6 +227,20 @@ When combining CSS files, take care of relative urls, as these will not be re-wr
|
|||||||
the destination location of the resulting combined CSS.
|
the destination location of the resulting combined CSS.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
### Combined JS Files
|
||||||
|
|
||||||
|
You can also add the 'async' and/or 'defer' attributes to combined Javascript files as you would with the
|
||||||
|
`Requirements::javascript` call - use the third paramter of the `combine_files` function:
|
||||||
|
|
||||||
|
:::php
|
||||||
|
$scripts = array(
|
||||||
|
"$themeDir/javascript/some_script.js",
|
||||||
|
"$themeDir/javascript/some_other_script.js",
|
||||||
|
);
|
||||||
|
|
||||||
|
Requirements::combine_files('scripts.js', $scripts, array('async' => true, 'defer' => true));
|
||||||
|
|
||||||
|
|
||||||
## Clearing assets
|
## Clearing assets
|
||||||
|
|
||||||
:::php
|
:::php
|
||||||
|
@ -118,6 +118,29 @@ class RequirementsTest extends SapphireTest {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function setupCombinedRequirementsJavascriptAsyncDefer($backend, $async, $defer) {
|
||||||
|
$basePath = $this->getCurrentRelativePath();
|
||||||
|
$this->setupRequirements($backend);
|
||||||
|
|
||||||
|
// require files normally (e.g. called from a FormField instance)
|
||||||
|
$backend->javascript($basePath . '/RequirementsTest_a.js');
|
||||||
|
$backend->javascript($basePath . '/RequirementsTest_b.js');
|
||||||
|
$backend->javascript($basePath . '/RequirementsTest_c.js');
|
||||||
|
|
||||||
|
// require two of those files as combined includes
|
||||||
|
$backend->combineFiles(
|
||||||
|
'RequirementsTest_bc.js',
|
||||||
|
array(
|
||||||
|
$basePath . '/RequirementsTest_b.js',
|
||||||
|
$basePath . '/RequirementsTest_c.js'
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'async' => $async,
|
||||||
|
'defer' => $defer,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public function testCombinedJavascript() {
|
public function testCombinedJavascript() {
|
||||||
/** @var Requirements_Backend $backend */
|
/** @var Requirements_Backend $backend */
|
||||||
$backend = Injector::inst()->create('Requirements_Backend');
|
$backend = Injector::inst()->create('Requirements_Backend');
|
||||||
@ -205,6 +228,152 @@ class RequirementsTest extends SapphireTest {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testCombinedJavascriptAsyncDefer() {
|
||||||
|
/** @var Requirements_Backend $backend */
|
||||||
|
$backend = Injector::inst()->create('Requirements_Backend');
|
||||||
|
|
||||||
|
$this->setupCombinedRequirementsJavascriptAsyncDefer($backend, true, false);
|
||||||
|
|
||||||
|
$combinedFileName = '/_combinedfiles/RequirementsTest_bc-2a55d56.js';
|
||||||
|
$combinedFilePath = AssetStoreTest_SpyStore::base_path() . $combinedFileName;
|
||||||
|
|
||||||
|
$html = $backend->includeInHTML(false, self::$html_template);
|
||||||
|
|
||||||
|
/* ASYNC IS INCLUDED IN SCRIPT TAG */
|
||||||
|
$this->assertRegExp(
|
||||||
|
'/src=".*' . preg_quote($combinedFileName, '/') . '" async/',
|
||||||
|
$html,
|
||||||
|
'async is included in script tag'
|
||||||
|
);
|
||||||
|
|
||||||
|
/* DEFER IS NOT INCLUDED IN SCRIPT TAG */
|
||||||
|
$this->assertNotContains('defer', $html, 'defer is not included');
|
||||||
|
|
||||||
|
/* COMBINED JAVASCRIPT FILE EXISTS */
|
||||||
|
clearstatcache(); // needed to get accurate file_exists() results
|
||||||
|
$this->assertFileExists($combinedFilePath,
|
||||||
|
'combined javascript file exists');
|
||||||
|
|
||||||
|
/* COMBINED JAVASCRIPT HAS CORRECT CONTENT */
|
||||||
|
$this->assertTrue((strpos(file_get_contents($combinedFilePath), "alert('b')") !== false),
|
||||||
|
'combined javascript has correct content');
|
||||||
|
$this->assertTrue((strpos(file_get_contents($combinedFilePath), "alert('c')") !== false),
|
||||||
|
'combined javascript has correct content');
|
||||||
|
|
||||||
|
/* COMBINED FILES ARE NOT INCLUDED TWICE */
|
||||||
|
$this->assertNotRegExp('/src=".*\/RequirementsTest_b\.js/', $html,
|
||||||
|
'combined files are not included twice');
|
||||||
|
$this->assertNotRegExp('/src=".*\/RequirementsTest_c\.js/', $html,
|
||||||
|
'combined files are not included twice');
|
||||||
|
|
||||||
|
/* NORMAL REQUIREMENTS ARE STILL INCLUDED */
|
||||||
|
$this->assertRegExp('/src=".*\/RequirementsTest_a\.js/', $html,
|
||||||
|
'normal requirements are still included');
|
||||||
|
|
||||||
|
/* NORMAL REQUIREMENTS DON'T HAVE ASYNC/DEFER */
|
||||||
|
$this->assertNotRegExp('/src=".*\/RequirementsTest_a\.js\?m=\d+" async/', $html,
|
||||||
|
'normal requirements don\'t have async');
|
||||||
|
$this->assertNotRegExp('/src=".*\/RequirementsTest_a\.js\?m=\d+" defer/', $html,
|
||||||
|
'normal requirements don\'t have defer');
|
||||||
|
$this->assertNotRegExp('/src=".*\/RequirementsTest_a\.js\?m=\d+" async defer/', $html,
|
||||||
|
'normal requirements don\'t have async/defer');
|
||||||
|
|
||||||
|
// setup again for testing defer
|
||||||
|
unlink($combinedFilePath);
|
||||||
|
/** @var Requirements_Backend $backend */
|
||||||
|
$backend = Injector::inst()->create('Requirements_Backend');
|
||||||
|
|
||||||
|
$this->setupCombinedRequirementsJavascriptAsyncDefer($backend, false, true);
|
||||||
|
|
||||||
|
$html = $backend->includeInHTML(self::$html_template);
|
||||||
|
|
||||||
|
/* DEFER IS INCLUDED IN SCRIPT TAG */
|
||||||
|
$this->assertRegExp(
|
||||||
|
'/src=".*' . preg_quote($combinedFileName, '/') . '" defer/',
|
||||||
|
$html,
|
||||||
|
'defer is included in script tag'
|
||||||
|
);
|
||||||
|
|
||||||
|
/* ASYNC IS NOT INCLUDED IN SCRIPT TAG */
|
||||||
|
$this->assertNotContains('async', $html, 'async is not included');
|
||||||
|
|
||||||
|
/* COMBINED JAVASCRIPT FILE EXISTS */
|
||||||
|
clearstatcache(); // needed to get accurate file_exists() results
|
||||||
|
$this->assertFileExists($combinedFilePath,
|
||||||
|
'combined javascript file exists');
|
||||||
|
|
||||||
|
/* COMBINED JAVASCRIPT HAS CORRECT CONTENT */
|
||||||
|
$this->assertTrue((strpos(file_get_contents($combinedFilePath), "alert('b')") !== false),
|
||||||
|
'combined javascript has correct content');
|
||||||
|
$this->assertTrue((strpos(file_get_contents($combinedFilePath), "alert('c')") !== false),
|
||||||
|
'combined javascript has correct content');
|
||||||
|
|
||||||
|
/* COMBINED FILES ARE NOT INCLUDED TWICE */
|
||||||
|
$this->assertNotRegExp('/src=".*\/RequirementsTest_b\.js/', $html,
|
||||||
|
'combined files are not included twice');
|
||||||
|
$this->assertNotRegExp('/src=".*\/RequirementsTest_c\.js/', $html,
|
||||||
|
'combined files are not included twice');
|
||||||
|
|
||||||
|
/* NORMAL REQUIREMENTS ARE STILL INCLUDED */
|
||||||
|
$this->assertRegExp('/src=".*\/RequirementsTest_a\.js/', $html,
|
||||||
|
'normal requirements are still included');
|
||||||
|
|
||||||
|
/* NORMAL REQUIREMENTS DON'T HAVE ASYNC/DEFER */
|
||||||
|
$this->assertNotRegExp('/src=".*\/RequirementsTest_a\.js\?m=\d+" async/', $html,
|
||||||
|
'normal requirements don\'t have async');
|
||||||
|
$this->assertNotRegExp('/src=".*\/RequirementsTest_a\.js\?m=\d+" defer/', $html,
|
||||||
|
'normal requirements don\'t have defer');
|
||||||
|
$this->assertNotRegExp('/src=".*\/RequirementsTest_a\.js\?m=\d+" async defer/', $html,
|
||||||
|
'normal requirements don\'t have async/defer');
|
||||||
|
|
||||||
|
// setup again for testing async and defer
|
||||||
|
unlink($combinedFilePath);
|
||||||
|
/** @var Requirements_Backend $backend */
|
||||||
|
$backend = Injector::inst()->create('Requirements_Backend');
|
||||||
|
|
||||||
|
$this->setupCombinedRequirementsJavascriptAsyncDefer($backend, true, true);
|
||||||
|
|
||||||
|
$html = $backend->includeInHTML(self::$html_template);
|
||||||
|
|
||||||
|
/* ASYNC/DEFER IS INCLUDED IN SCRIPT TAG */
|
||||||
|
$this->assertRegExp(
|
||||||
|
'/src=".*' . preg_quote($combinedFileName, '/') . '" async defer/',
|
||||||
|
$html,
|
||||||
|
'async and defer are included in script tag'
|
||||||
|
);
|
||||||
|
|
||||||
|
/* COMBINED JAVASCRIPT FILE EXISTS */
|
||||||
|
clearstatcache(); // needed to get accurate file_exists() results
|
||||||
|
$this->assertFileExists($combinedFilePath,
|
||||||
|
'combined javascript file exists');
|
||||||
|
|
||||||
|
/* COMBINED JAVASCRIPT HAS CORRECT CONTENT */
|
||||||
|
$this->assertTrue((strpos(file_get_contents($combinedFilePath), "alert('b')") !== false),
|
||||||
|
'combined javascript has correct content');
|
||||||
|
$this->assertTrue((strpos(file_get_contents($combinedFilePath), "alert('c')") !== false),
|
||||||
|
'combined javascript has correct content');
|
||||||
|
|
||||||
|
/* COMBINED FILES ARE NOT INCLUDED TWICE */
|
||||||
|
$this->assertNotRegExp('/src=".*\/RequirementsTest_b\.js/', $html,
|
||||||
|
'combined files are not included twice');
|
||||||
|
$this->assertNotRegExp('/src=".*\/RequirementsTest_c\.js/', $html,
|
||||||
|
'combined files are not included twice');
|
||||||
|
|
||||||
|
/* NORMAL REQUIREMENTS ARE STILL INCLUDED */
|
||||||
|
$this->assertRegExp('/src=".*\/RequirementsTest_a\.js/', $html,
|
||||||
|
'normal requirements are still included');
|
||||||
|
|
||||||
|
/* NORMAL REQUIREMENTS DON'T HAVE ASYNC/DEFER */
|
||||||
|
$this->assertNotRegExp('/src=".*\/RequirementsTest_a\.js\?m=\d+" async/', $html,
|
||||||
|
'normal requirements don\'t have async');
|
||||||
|
$this->assertNotRegExp('/src=".*\/RequirementsTest_a\.js\?m=\d+" defer/', $html,
|
||||||
|
'normal requirements don\'t have defer');
|
||||||
|
$this->assertNotRegExp('/src=".*\/RequirementsTest_a\.js\?m=\d+" async defer/', $html,
|
||||||
|
'normal requirements don\'t have async/defer');
|
||||||
|
|
||||||
|
unlink($combinedFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
public function testCombinedCss() {
|
public function testCombinedCss() {
|
||||||
$basePath = $this->getCurrentRelativePath();
|
$basePath = $this->getCurrentRelativePath();
|
||||||
/** @var Requirements_Backend $backend */
|
/** @var Requirements_Backend $backend */
|
||||||
@ -217,7 +386,9 @@ class RequirementsTest extends SapphireTest {
|
|||||||
$basePath . '/RequirementsTest_print_a.css',
|
$basePath . '/RequirementsTest_print_a.css',
|
||||||
$basePath . '/RequirementsTest_print_b.css'
|
$basePath . '/RequirementsTest_print_b.css'
|
||||||
),
|
),
|
||||||
'print'
|
array(
|
||||||
|
'media' => 'print'
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
$html = $backend->includeInHTML(self::$html_template);
|
$html = $backend->includeInHTML(self::$html_template);
|
||||||
@ -284,7 +455,7 @@ class RequirementsTest extends SapphireTest {
|
|||||||
/* BLOCKED UNCOMBINED FILES ARE NOT INCLUDED */
|
/* BLOCKED UNCOMBINED FILES ARE NOT INCLUDED */
|
||||||
$this->setupCombinedRequirements($backend);
|
$this->setupCombinedRequirements($backend);
|
||||||
$backend->block($basePath .'/RequirementsTest_b.js');
|
$backend->block($basePath .'/RequirementsTest_b.js');
|
||||||
$combinedFileName2 = '/_combinedfiles/RequirementsTest_bc-3748f67.js'; // SHA1 without file c included
|
$combinedFileName2 = '/_combinedfiles/RequirementsTest_bc-3748f67.js'; // SHA1 without file b included
|
||||||
$combinedFilePath2 = AssetStoreTest_SpyStore::base_path() . $combinedFileName2;
|
$combinedFilePath2 = AssetStoreTest_SpyStore::base_path() . $combinedFileName2;
|
||||||
clearstatcache(); // needed to get accurate file_exists() results
|
clearstatcache(); // needed to get accurate file_exists() results
|
||||||
$html = $backend->includeInHTML(self::$html_template);
|
$html = $backend->includeInHTML(self::$html_template);
|
||||||
@ -353,7 +524,7 @@ class RequirementsTest extends SapphireTest {
|
|||||||
|
|
||||||
$this->assertTrue(count($backend->getJavascript()) == 1,
|
$this->assertTrue(count($backend->getJavascript()) == 1,
|
||||||
"There should be only 1 file included in required javascript.");
|
"There should be only 1 file included in required javascript.");
|
||||||
$this->assertTrue(in_array($basePath . '/a.js', $backend->getJavascript()),
|
$this->assertArrayHasKey($basePath . '/a.js', $backend->getJavascript(),
|
||||||
"a.js should be included in required javascript.");
|
"a.js should be included in required javascript.");
|
||||||
|
|
||||||
$backend->javascript($basePath . '/b.js');
|
$backend->javascript($basePath . '/b.js');
|
||||||
@ -363,9 +534,9 @@ class RequirementsTest extends SapphireTest {
|
|||||||
$backend->block($basePath . '/a.js');
|
$backend->block($basePath . '/a.js');
|
||||||
$this->assertTrue(count($backend->getJavascript()) == 1,
|
$this->assertTrue(count($backend->getJavascript()) == 1,
|
||||||
"There should be only 1 file included in required javascript.");
|
"There should be only 1 file included in required javascript.");
|
||||||
$this->assertFalse(in_array($basePath . '/a.js', $backend->getJavascript()),
|
$this->assertArrayNotHasKey($basePath . '/a.js', $backend->getJavascript(),
|
||||||
"a.js should not be included in required javascript after it has been blocked.");
|
"a.js should not be included in required javascript after it has been blocked.");
|
||||||
$this->assertTrue(in_array($basePath . '/b.js', $backend->getJavascript()),
|
$this->assertArrayHasKey($basePath . '/b.js', $backend->getJavascript(),
|
||||||
"b.js should be included in required javascript.");
|
"b.js should be included in required javascript.");
|
||||||
|
|
||||||
$backend->css($basePath . '/a.css');
|
$backend->css($basePath . '/a.css');
|
||||||
@ -675,8 +846,7 @@ EOS
|
|||||||
case 'js':
|
case 'js':
|
||||||
case 'javascript':
|
case 'javascript':
|
||||||
case 'script':
|
case 'script':
|
||||||
$scripts = $backend->getJavascript();
|
return $backend->getJavascript();
|
||||||
return array_combine(array_values($scripts), array_values($scripts));
|
|
||||||
}
|
}
|
||||||
return array();
|
return array();
|
||||||
}
|
}
|
||||||
|
@ -183,7 +183,7 @@ class SSViewerTest extends SapphireTest {
|
|||||||
|
|
||||||
// secondly, make sure that requirements is generated, even though minification failed
|
// secondly, make sure that requirements is generated, even though minification failed
|
||||||
$testBackend->processCombinedFiles();
|
$testBackend->processCombinedFiles();
|
||||||
$js = $testBackend->getJavascript();
|
$js = array_keys($testBackend->getJavascript());
|
||||||
$combinedTestFilePath = BASE_PATH . reset($js);
|
$combinedTestFilePath = BASE_PATH . reset($js);
|
||||||
$this->assertContains('_combinedfiles/testRequirementsCombine-4c0e97a.js', $combinedTestFilePath);
|
$this->assertContains('_combinedfiles/testRequirementsCombine-4c0e97a.js', $combinedTestFilePath);
|
||||||
|
|
||||||
|
@ -112,6 +112,8 @@ class Requirements implements Flushable {
|
|||||||
* @param string $file Relative to docroot
|
* @param string $file Relative to docroot
|
||||||
* @param array $options List of options. Available options include:
|
* @param array $options List of options. Available options include:
|
||||||
* - 'provides' : List of scripts files included in this file
|
* - 'provides' : List of scripts files included in this file
|
||||||
|
* - 'async' : Boolean value to set async attribute to script tag
|
||||||
|
* - 'defer' : Boolean value to set defer attribute to script tag
|
||||||
*/
|
*/
|
||||||
public static function javascript($file, $options = array()) {
|
public static function javascript($file, $options = array()) {
|
||||||
self::backend()->javascript($file, $options);
|
self::backend()->javascript($file, $options);
|
||||||
@ -337,12 +339,19 @@ class Requirements implements Flushable {
|
|||||||
*
|
*
|
||||||
* @param string $combinedFileName Filename of the combined file relative to docroot
|
* @param string $combinedFileName Filename of the combined file relative to docroot
|
||||||
* @param array $files Array of filenames relative to docroot
|
* @param array $files Array of filenames relative to docroot
|
||||||
* @param string $media
|
* @param array $options Array of options for combining files. Available options are:
|
||||||
|
* - 'media' : If including CSS Files, you can specify a media type
|
||||||
|
* - 'async' : If including JavaScript Files, boolean value to set async attribute to script tag
|
||||||
|
* - 'defer' : If including JavaScript Files, boolean value to set defer attribute to script tag
|
||||||
*
|
*
|
||||||
* @return bool|void
|
* @return bool|void
|
||||||
*/
|
*/
|
||||||
public static function combine_files($combinedFileName, $files, $media = null) {
|
public static function combine_files($combinedFileName, $files, $options = array()) {
|
||||||
self::backend()->combineFiles($combinedFileName, $files, $media);
|
if(is_string($options)) {
|
||||||
|
Deprecation::notice('4.0', 'Parameter media is deprecated. Use options array instead.');
|
||||||
|
$options = array('media' => $options);
|
||||||
|
}
|
||||||
|
self::backend()->combineFiles($combinedFileName, $files, $options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -803,14 +812,37 @@ class Requirements_Backend
|
|||||||
* @param string $file Relative to docroot
|
* @param string $file Relative to docroot
|
||||||
* @param array $options List of options. Available options include:
|
* @param array $options List of options. Available options include:
|
||||||
* - 'provides' : List of scripts files included in this file
|
* - 'provides' : List of scripts files included in this file
|
||||||
|
* - 'async' : Boolean value to set async attribute to script tag
|
||||||
|
* - 'defer' : Boolean value to set defer attribute to script tag
|
||||||
*/
|
*/
|
||||||
public function javascript($file, $options = array()) {
|
public function javascript($file, $options = array()) {
|
||||||
$this->javascript[$file] = true;
|
// make sure that async/defer is set if it is set once even if file is included multiple times
|
||||||
|
$async = (
|
||||||
|
isset($options['async']) && isset($options['async']) == true
|
||||||
|
|| (
|
||||||
|
isset($this->javascript[$file])
|
||||||
|
&& isset($this->javascript[$file]['async'])
|
||||||
|
&& $this->javascript[$file]['async'] == true
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$defer = (
|
||||||
|
isset($options['defer']) && isset($options['defer']) == true
|
||||||
|
|| (
|
||||||
|
isset($this->javascript[$file])
|
||||||
|
&& isset($this->javascript[$file]['defer'])
|
||||||
|
&& $this->javascript[$file]['defer'] == true
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$this->javascript[$file] = array(
|
||||||
|
'async' => $async,
|
||||||
|
'defer' => $defer,
|
||||||
|
);
|
||||||
|
|
||||||
// Record scripts included in this file
|
// Record scripts included in this file
|
||||||
if(isset($options['provides'])) {
|
if(isset($options['provides'])) {
|
||||||
$this->providedJavascript[$file] = array_values($options['provides']);
|
$this->providedJavascript[$file] = array_values($options['provides']);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -841,7 +873,7 @@ class Requirements_Backend
|
|||||||
public function getProvidedScripts() {
|
public function getProvidedScripts() {
|
||||||
$providedScripts = array();
|
$providedScripts = array();
|
||||||
$includedScripts = array();
|
$includedScripts = array();
|
||||||
foreach($this->javascript as $script => $flag) {
|
foreach($this->javascript as $script => $options) {
|
||||||
// Ignore scripts that are explicitly blocked
|
// Ignore scripts that are explicitly blocked
|
||||||
if(isset($this->blocked[$script])) {
|
if(isset($this->blocked[$script])) {
|
||||||
continue;
|
continue;
|
||||||
@ -869,11 +901,11 @@ class Requirements_Backend
|
|||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getJavascript() {
|
public function getJavascript() {
|
||||||
return array_keys(array_diff_key(
|
return array_diff_key(
|
||||||
$this->javascript,
|
$this->javascript,
|
||||||
$this->getBlocked(),
|
$this->getBlocked(),
|
||||||
$this->getProvidedScripts()
|
$this->getProvidedScripts()
|
||||||
));
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -882,7 +914,7 @@ class Requirements_Backend
|
|||||||
* @return array Indexed array of javascript files
|
* @return array Indexed array of javascript files
|
||||||
*/
|
*/
|
||||||
protected function getAllJavascript() {
|
protected function getAllJavascript() {
|
||||||
return array_keys($this->javascript);
|
return $this->javascript;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1130,10 +1162,12 @@ class Requirements_Backend
|
|||||||
// Combine files - updates $this->javascript and $this->css
|
// Combine files - updates $this->javascript and $this->css
|
||||||
$this->processCombinedFiles();
|
$this->processCombinedFiles();
|
||||||
|
|
||||||
foreach($this->getJavascript() as $file) {
|
foreach($this->getJavascript() as $file => $attributes) {
|
||||||
|
$async = (isset($attributes['async']) && $attributes['async'] == true) ? " async" : "";
|
||||||
|
$defer = (isset($attributes['defer']) && $attributes['defer'] == true) ? " defer" : "";
|
||||||
$path = Convert::raw2att($this->pathForFile($file));
|
$path = Convert::raw2att($this->pathForFile($file));
|
||||||
if($path) {
|
if($path) {
|
||||||
$jsRequirements .= "<script type=\"application/javascript\" src=\"$path\"></script>";
|
$jsRequirements .= "<script type=\"application/javascript\" src=\"$path\"{$async}{$defer}></script>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1267,7 +1301,7 @@ class Requirements_Backend
|
|||||||
$jsRequirements = array();
|
$jsRequirements = array();
|
||||||
$cssRequirements = array();
|
$cssRequirements = array();
|
||||||
|
|
||||||
foreach($this->getJavascript() as $file) {
|
foreach($this->getJavascript() as $file => $attributes) {
|
||||||
$path = $this->pathForFile($file);
|
$path = $this->pathForFile($file);
|
||||||
if($path) {
|
if($path) {
|
||||||
$jsRequirements[] = str_replace(',', '%2C', $path);
|
$jsRequirements[] = str_replace(',', '%2C', $path);
|
||||||
@ -1399,10 +1433,14 @@ class Requirements_Backend
|
|||||||
* Example for combined JavaScript:
|
* Example for combined JavaScript:
|
||||||
* <code>
|
* <code>
|
||||||
* Requirements::combine_files(
|
* Requirements::combine_files(
|
||||||
* 'foobar.js',
|
* 'foobar.js',
|
||||||
* array(
|
* array(
|
||||||
* 'mysite/javascript/foo.js',
|
* 'mysite/javascript/foo.js',
|
||||||
* 'mysite/javascript/bar.js',
|
* 'mysite/javascript/bar.js',
|
||||||
|
* ),
|
||||||
|
* array(
|
||||||
|
* 'async' => true,
|
||||||
|
* 'defer' => true,
|
||||||
* )
|
* )
|
||||||
* );
|
* );
|
||||||
* </code>
|
* </code>
|
||||||
@ -1410,23 +1448,33 @@ class Requirements_Backend
|
|||||||
* Example for combined CSS:
|
* Example for combined CSS:
|
||||||
* <code>
|
* <code>
|
||||||
* Requirements::combine_files(
|
* Requirements::combine_files(
|
||||||
* 'foobar.css',
|
* 'foobar.css',
|
||||||
* array(
|
* array(
|
||||||
* 'mysite/javascript/foo.css',
|
* 'mysite/javascript/foo.css',
|
||||||
* 'mysite/javascript/bar.css',
|
* 'mysite/javascript/bar.css',
|
||||||
|
* ),
|
||||||
|
* array(
|
||||||
|
* 'media' => 'print',
|
||||||
* )
|
* )
|
||||||
* );
|
* );
|
||||||
* </code>
|
* </code>
|
||||||
*
|
*
|
||||||
* @param string $combinedFileName Filename of the combined file relative to docroot
|
* @param string $combinedFileName Filename of the combined file relative to docroot
|
||||||
* @param array $files Array of filenames relative to docroot
|
* @param array $files Array of filenames relative to docroot
|
||||||
* @param string $media If including CSS Files, you can specify a media type
|
* @param array $options Array of options for combining files. Available options are:
|
||||||
|
* - 'media' : If including CSS Files, you can specify a media type
|
||||||
|
* - 'async' : If including JavaScript Files, boolean value to set async attribute to script tag
|
||||||
|
* - 'defer' : If including JavaScript Files, boolean value to set defer attribute to script tag
|
||||||
*/
|
*/
|
||||||
public function combineFiles($combinedFileName, $files, $media = null) {
|
public function combineFiles($combinedFileName, $files, $options = array()) {
|
||||||
|
if(is_string($options)) {
|
||||||
|
Deprecation::notice('4.0', 'Parameter media is deprecated. Use options array instead.');
|
||||||
|
$options = array('media' => $options);
|
||||||
|
}
|
||||||
// Skip this combined files if already included
|
// Skip this combined files if already included
|
||||||
if(isset($this->combinedFiles[$combinedFileName])) {
|
if(isset($this->combinedFiles[$combinedFileName])) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add all files to necessary type list
|
// Add all files to necessary type list
|
||||||
$paths = array();
|
$paths = array();
|
||||||
@ -1436,25 +1484,25 @@ class Requirements_Backend
|
|||||||
list($path, $type) = $this->parseCombinedFile($file);
|
list($path, $type) = $this->parseCombinedFile($file);
|
||||||
if($type === 'javascript') {
|
if($type === 'javascript') {
|
||||||
$type = 'js';
|
$type = 'js';
|
||||||
}
|
}
|
||||||
if($combinedType && $type && $combinedType !== $type) {
|
if($combinedType && $type && $combinedType !== $type) {
|
||||||
throw new InvalidArgumentException(
|
throw new InvalidArgumentException(
|
||||||
"Cannot mix js and css files in same combined file {$combinedFileName}"
|
"Cannot mix js and css files in same combined file {$combinedFileName}"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
switch($type) {
|
switch($type) {
|
||||||
case 'css':
|
case 'css':
|
||||||
$this->css($path, $media);
|
$this->css($path, (isset($options['media']) ? $options['media'] : null));
|
||||||
break;
|
break;
|
||||||
case 'js':
|
case 'js':
|
||||||
$this->javascript($path);
|
$this->javascript($path, $options);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new InvalidArgumentException("Invalid combined file type: {$type}");
|
throw new InvalidArgumentException("Invalid combined file type: {$type}");
|
||||||
}
|
}
|
||||||
$combinedType = $type;
|
$combinedType = $type;
|
||||||
$paths[] = $path;
|
$paths[] = $path;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Duplicate check
|
// Duplicate check
|
||||||
foreach($this->combinedFiles as $existingCombinedFilename => $combinedItem) {
|
foreach($this->combinedFiles as $existingCombinedFilename => $combinedItem) {
|
||||||
@ -1466,15 +1514,15 @@ class Requirements_Backend
|
|||||||
implode(',', $duplicates),
|
implode(',', $duplicates),
|
||||||
$existingCombinedFilename
|
$existingCombinedFilename
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->combinedFiles[$combinedFileName] = array(
|
$this->combinedFiles[$combinedFileName] = array(
|
||||||
'files' => $paths,
|
'files' => $paths,
|
||||||
'type' => $combinedType,
|
'type' => $combinedType,
|
||||||
'media' => $media
|
'options' => $options,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return path and type of given combined file
|
* Return path and type of given combined file
|
||||||
@ -1559,7 +1607,7 @@ class Requirements_Backend
|
|||||||
foreach($this->getAllCombinedFiles() as $combinedFile => $combinedItem) {
|
foreach($this->getAllCombinedFiles() as $combinedFile => $combinedItem) {
|
||||||
$fileList = $combinedItem['files'];
|
$fileList = $combinedItem['files'];
|
||||||
$type = $combinedItem['type'];
|
$type = $combinedItem['type'];
|
||||||
$media = $combinedItem['media'];
|
$options = $combinedItem['options'];
|
||||||
|
|
||||||
// Generate this file, unless blocked
|
// Generate this file, unless blocked
|
||||||
$combinedURL = null;
|
$combinedURL = null;
|
||||||
@ -1585,7 +1633,7 @@ class Requirements_Backend
|
|||||||
if(!in_array($css, $fileList)) {
|
if(!in_array($css, $fileList)) {
|
||||||
$newCSS[$css] = $spec;
|
$newCSS[$css] = $spec;
|
||||||
} elseif(!$included && $combinedURL) {
|
} elseif(!$included && $combinedURL) {
|
||||||
$newCSS[$combinedURL] = array('media' => $media);
|
$newCSS[$combinedURL] = array('media' => (isset($options['media']) ? $options['media'] : null));
|
||||||
$included = true;
|
$included = true;
|
||||||
}
|
}
|
||||||
// If already included, or otherwise blocked, then don't add into CSS
|
// If already included, or otherwise blocked, then don't add into CSS
|
||||||
@ -1594,13 +1642,13 @@ class Requirements_Backend
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'js': {
|
case 'js': {
|
||||||
// Assoc array of file => true
|
// Assoc array of file => attributes
|
||||||
$newJS = array();
|
$newJS = array();
|
||||||
foreach($this->getAllJavascript() as $script) {
|
foreach($this->getAllJavascript() as $script => $attributes) {
|
||||||
if(!in_array($script, $fileList)) {
|
if(!in_array($script, $fileList)) {
|
||||||
$newJS[$script] = true;
|
$newJS[$script] = $attributes;
|
||||||
} elseif(!$included && $combinedURL) {
|
} elseif(!$included && $combinedURL) {
|
||||||
$newJS[$combinedURL] = true;
|
$newJS[$combinedURL] = $options;
|
||||||
$included = true;
|
$included = true;
|
||||||
}
|
}
|
||||||
// If already included, or otherwise blocked, then don't add into scripts
|
// If already included, or otherwise blocked, then don't add into scripts
|
||||||
|
Loading…
Reference in New Issue
Block a user