Same name and namespace in other branches
  1. 8.x-2.x advagg_mod/advagg_mod.module \advagg_mod_js_async_defer() 1 commentaire

Add the defer and or the async tag to js.

Paramètres

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 dans advagg_mod/advagg_mod.module
Alter the js array.

Fichier

advagg_mod/advagg_mod.module, line 2349

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;
}