function advagg_mod_js_async_defer in Advanced CSS/JS Aggregation 7.2
Same name and namespace in other branches
- 8.2 advagg_mod/advagg_mod.module \advagg_mod_js_async_defer()
Add the defer and or the async tag to js.
Parameters
array $js: JS array.
Return value
bool TRUE if jQuery is deferred.
1 call to advagg_mod_js_async_defer()
- advagg_mod_js_post_alter in advagg_mod/
advagg_mod.module - Alter the js array.
File
- advagg_mod/
advagg_mod.module, line 2349 - Advanced aggregation modifier module.
Code
function advagg_mod_js_async_defer(array &$js) {
$jquery_deferred = FALSE;
$jquery_rev = strrev('/jquery.js');
$jquery_min_rev = strrev('/jquery.min.js');
$jquery_ui_rev = strrev('/jquery-ui.js');
$jquery_ui_min_rev = strrev('jquery-ui.min.js');
// Return early if this is disabled.
list(, , $no_async_defer_list, $inline_wrapper_list, , , , , $defer_setting, $async_setting) = advagg_mod_get_lists($js);
if (!$defer_setting && !$async_setting) {
// Special handling if using loadcss to defer css loading.
if (!empty($GLOBALS['advagg_mod_loadcss_jquery_holdready'])) {
foreach ($js as $name => &$values) {
// Special handling for jQuery.
if (stripos(strrev($name), $jquery_rev) === 0 || stripos(strrev($name), $jquery_min_rev) === 0) {
// Do not fire jQuery.ready until Drupal.settings has been defined.
$values['onload'] = "if(jQuery.isFunction(jQuery.holdReady)){jQuery.holdReady(true);}";
break;
}
}
}
return $jquery_deferred;
}
// Disable this section of code for now; the on error attribute only works
// with async safe JS.
$use_on_error = FALSE;
if (variable_get('advagg_mod_js_defer_jquery', ADVAGG_MOD_JS_DEFER_JQUERY) !== FALSE && variable_get('advagg_mod_js_defer_inline_alter', ADVAGG_MOD_JS_DEFER_INLINE_ALTER) && variable_get('jquery_update_jquery_cdn', 'none') !== 'none') {
$use_on_error = TRUE;
}
// If everything is async safe then we can use on error.
// Only needed if the jquery_update javascript is loaded via async/defer.
if ($use_on_error) {
$jquery_update_fallback = '';
$jquery_update_ui_fallback = '';
$jquery_migrate_fallback = '';
$inline_array = array();
if (module_exists('jquery_update') && (variable_get('jquery_update_jquery_cdn', 'none') !== 'none' || variable_get('jquery_update_jquery_migrate_cdn', 'none') !== 'none')) {
$min = variable_get('jquery_update_compression_type', 'min') == 'none' ? '' : '.min';
$path = drupal_get_path('module', 'jquery_update');
foreach ($js as $name => &$values) {
// Skip if not inline.
if ($values['type'] !== 'inline') {
continue;
}
// JQuery UI.
if (stripos($values['data'], 'window.jQuery.ui') !== FALSE && stripos($values['data'], 'document.write("<script') !== FALSE && variable_get('jquery_update_jquery_cdn', 'none') !== 'none') {
$js_path = $min == '.min' ? '/replace/ui/ui/minified/jquery-ui.min.js' : '/replace/ui/ui/jquery-ui.js';
$jquery_update_ui_fallback = "{$GLOBALS['base_path']}{$path}{$js_path}";
if (empty($inline_array)) {
$inline_array = $values;
}
unset($js[$name]);
continue;
}
// JQuery Migrate.
if (stripos($values['data'], 'window.jQuery.migrateWarnings') !== FALSE && stripos($values['data'], 'document.write("<script') !== FALSE && variable_get('jquery_update_jquery_migrate_cdn', 'none') !== 'none') {
$version = '1.2.1';
$jquery_migrate_fallback = "{$GLOBALS['base_path']}{$path}/replace/jquery-migrate/{$version}/jquery-migrate{$min}.js";
$inline_array = $values;
unset($js[$name]);
continue;
}
// JQuery.
// This should always be last.
if (stripos($values['data'], 'window.jQuery') !== FALSE && stripos($values['data'], 'document.write("<script') !== FALSE && variable_get('jquery_update_jquery_cdn', 'none') !== 'none') {
$version = variable_get('jquery_update_jquery_version', '1.10');
$jquery_update_fallback = "{$GLOBALS['base_path']}{$path}/replace/jquery/{$version}/jquery{$min}.js";
$inline_array = $values;
unset($js[$name]);
continue;
}
}
unset($values);
}
if (!empty($jquery_update_fallback) || !empty($jquery_update_ui_fallback) || !empty($jquery_migrate_fallback)) {
// Add in the advagg_fallback() function so it's available inline.
$inline_array['group'] = '-150';
$inline_array['weight'] += -10;
$inline_array['data'] = 'function advagg_fallback(file){var head = document.getElementsByTagName("head")[0];var script = document.createElement("script");script.src = file;script.type = "text/javascript";head.appendChild(script);};';
$inline_array['scope_lock'] = TRUE;
$inline_array['movable'] = FALSE;
$inline_array['no_defer'] = TRUE;
$inline_array['scope'] = 'header';
$js['advagg_fallback'] = $inline_array;
}
}
// Make all scripts defer and/or async.
$hold_ready = FALSE;
foreach ($js as $name => &$values) {
// Skip if not a file or external.
if ($values['type'] !== 'file' && $values['type'] !== 'external') {
continue;
}
// Everything is defer.
if (variable_get('advagg_mod_js_defer', ADVAGG_MOD_JS_DEFER) && empty($values['nodefer'])) {
$values['defer'] = TRUE;
}
// Everything is async.
if (variable_get('advagg_mod_js_async', ADVAGG_MOD_JS_ASYNC) && empty($values['noasync'])) {
$values['async'] = TRUE;
}
// Special handling for jQuery.
if (stripos(strrev($name), $jquery_rev) === 0 || stripos(strrev($name), $jquery_min_rev) === 0) {
$jquery_deferred = TRUE;
// Do not fire jQuery.ready until Drupal.settings has been defined.
if (empty($hold_ready)) {
if (!empty($GLOBALS['advagg_mod_loadcss_jquery_holdready'])) {
$values['onload'] = "if(jQuery.isFunction(jQuery.holdReady)){jQuery.holdReady(true);jQuery.holdReady(true);}";
}
else {
$values['onload'] = "if(jQuery.isFunction(jQuery.holdReady)){jQuery.holdReady(true);}";
}
$hold_ready = TRUE;
}
// jquery_update fallback.
if (module_exists('jquery_update') && variable_get('jquery_update_jquery_cdn', 'none') !== 'none') {
if ($use_on_error && !empty($jquery_update_fallback)) {
if (!isset($values['onerror'])) {
$values['onerror'] = '';
}
$values['onerror'] .= "advagg_fallback('{$jquery_update_fallback}');";
}
// Do not defer/async the loading of jquery.js.
if (!variable_get('advagg_mod_js_defer_jquery', ADVAGG_MOD_JS_DEFER_JQUERY) !== FALSE && variable_get('advagg_mod_js_defer_inline_alter', ADVAGG_MOD_JS_DEFER_INLINE_ALTER) && variable_get('jquery_update_jquery_cdn', 'none') !== 'none') {
if (variable_get('advagg_mod_js_defer', ADVAGG_MOD_JS_DEFER)) {
$values['defer'] = FALSE;
$jquery_deferred = FALSE;
}
}
if (variable_get('advagg_mod_js_async', ADVAGG_MOD_JS_ASYNC)) {
$values['async'] = FALSE;
}
// Defer/async is off; done with loop.
continue;
}
}
// Special handling for jQuery migrate.
if (stripos($name, '/jquery-migrate') !== FALSE) {
// jquery_update ui fallback.
if (module_exists('jquery_update') && variable_get('jquery_update_jquery_migrate_cdn', 'none') !== 'none') {
if ($use_on_error) {
if (!isset($values['onerror'])) {
$values['onerror'] = '';
}
$values['onerror'] .= "advagg_fallback('{$jquery_migrate_fallback}');";
}
// Do not defer/async the loading of jquery-migrate.
if (!variable_get('advagg_mod_js_defer_jquery', ADVAGG_MOD_JS_DEFER_JQUERY) !== FALSE && variable_get('advagg_mod_js_defer_inline_alter', ADVAGG_MOD_JS_DEFER_INLINE_ALTER) && variable_get('jquery_update_jquery_cdn', 'none') !== 'none') {
if (variable_get('advagg_mod_js_defer', ADVAGG_MOD_JS_DEFER)) {
$values['defer'] = FALSE;
}
}
if (variable_get('advagg_mod_js_async', ADVAGG_MOD_JS_ASYNC)) {
$values['async'] = FALSE;
}
// Defer/async is off; done with loop.
continue;
}
}
// Special handling for jQuery UI.
if (stripos(strrev($name), $jquery_ui_rev) === 0 || stripos(strrev($name), $jquery_ui_min_rev) === 0) {
// jquery_update ui fallback.
if (module_exists('jquery_update') && variable_get('jquery_update_jquery_cdn', 'none') !== 'none') {
if ($use_on_error) {
if (!isset($values['onerror'])) {
$values['onerror'] = '';
}
$values['onerror'] .= "advagg_fallback('{$jquery_update_ui_fallback}');";
}
// Do not defer/async the loading of jquery-ui.js.
if (!variable_get('advagg_mod_js_defer_jquery', ADVAGG_MOD_JS_DEFER_JQUERY) !== FALSE && variable_get('advagg_mod_js_defer_inline_alter', ADVAGG_MOD_JS_DEFER_INLINE_ALTER) && variable_get('jquery_update_jquery_cdn', 'none') !== 'none') {
if (variable_get('advagg_mod_js_defer', ADVAGG_MOD_JS_DEFER)) {
$values['defer'] = FALSE;
}
}
if (variable_get('advagg_mod_js_async', ADVAGG_MOD_JS_ASYNC)) {
$values['async'] = FALSE;
}
// Defer/async is off; done with loop.
continue;
}
}
// Drupal settings; don't run until misc/drupal.js has ran.
if ($name === 'misc/drupal.js') {
// Initialize the Drupal.settings JavaScript object after this has
// loaded.
if (!isset($values['onload'])) {
$values['onload'] = '';
}
$matches[0] = $matches[2] = 'init_drupal_core_settings();';
$values['onload'] .= advagg_mod_wrap_inline_js($matches, "window.init_drupal_core_settings && window.jQuery && window.Drupal", 1);
}
// No async defer list.
foreach ($no_async_defer_list as $search_string) {
if (strpos($name, $search_string) !== FALSE) {
// Do not defer/async the loading this script.
if (variable_get('advagg_mod_js_defer', ADVAGG_MOD_JS_DEFER)) {
$values['defer'] = FALSE;
}
if (variable_get('advagg_mod_js_async', ADVAGG_MOD_JS_ASYNC)) {
$values['async'] = FALSE;
}
}
}
// Do not defer external scripts setting.
if ($defer_setting == 2 && $values['type'] === 'external') {
$values['defer'] = FALSE;
}
}
unset($values);
// Inline script special handling.
foreach ($js as &$values) {
if ($values['type'] !== 'inline') {
continue;
}
foreach ($inline_wrapper_list as $search_string => $js_condition) {
if (strpos($values['data'], $search_string) !== FALSE) {
$matches[0] = $matches[2] = $values['data'];
$values['data'] = advagg_mod_wrap_inline_js($matches, $js_condition);
}
}
}
unset($values);
return $jquery_deferred;
}