Question

Please note that, I'm not telling about conditionally enqueue/dequeue scripts, I'm referring to conditionally dequeue certain dependencies from an existing enqueued scripts in front end. And please note the question is not plugin-specific. I want to be enlightened about the general rules.

I used Elementor (page builder) for front end. But it's not used in all my pages. So the default lightbox feature enabled in Elementor doesn't work in those pages. That's why I added my own lightbox throughout the site, using a regex $pattern ="/<a(.*?)href=('|\")(.*?).(bmp|gif|jpeg|jpg|png)('|\")(.*?)>/i"; hooked to the the_content filter. Thing's working fine, but-

Where there the Elementor gallery or lightbox is triggered, both the scripts are messing up. Two lightbox are being called, sometimes the gallery lightbox are conflicting and not working etc.

Solution 1:

I know I can conditionally filter the_content with the regex like:

if( ! is_singular('cpt') ) {
    return $content = preg_replace($pattern, $replacement, $content);
}

But I actually want to keep this feature everywhere. Just want to remove the elementor lightbox where I want 'em to. So, I's trying the solution#2.

Solution 2:

What Elementor did, is something, like:

wp_enqueue_script('elementor-frontend', 'link/to/frontend.js', array('elementor-dialog', 'elementor-waypoints', 'jquery-swiper'), '1.9.7', true);

Now I want not to load the lightbox feature from Elementor, so I tried to dequeue the 'elementor-dialog':

if( is_singular('cpt') ) {
    wp_dequeue_script( 'elementor-dialog' );
}

But it's not working, as the dependencies are set in 'elementor-frontend'. So I tried deregistering dialog:

if( is_singular('cpt') ) {
    wp_dequeue_script( 'elementor-dialog' );
    wp_deregister_script( 'elementor-dialog' );
}

It's devastating, because it dequeued the frontend.js.

How can I change the dependencies of frontend.js (handle: 'elementor-frontend') on the fly, so that I can change the dependencies to array('elementor-waypoints', 'jquery-swiper')?

Was it helpful?

Solution

Solution 1:

Here we will dequeue and deregister elementor-dialog and elementor-frontend, then we will re-register elementor-frontend without the elementor-dialog dependency:

// This needs to fire after priority 5 which is where Elementor
// handles enqueueing scripts. We're ok since the default is 10.
add_action( 'wp_enqueue_scripts', 'wpse_elementor_frontend_scripts' );
function wpse_elementor_frontend_scripts() {
    // Optionally add guard clauses such as checking if( ! is_singular('cpt') )...

    // Bail if Elementor is not available.
    if ( ! defined( 'ELEMENTOR_VERSION' ) ) {
        return;
    }

    // Dequeue and deregister elementor-dialog
    wp_dequeue_script( 'elementor-dialog' );
    wp_deregister_script( 'elementor-dialog' );

    // Dequeue and deregister elementor-frontend
    wp_dequeue_script( 'elementor-frontend' );
    wp_deregister_script( 'elementor-frontend' );

    // Re-register elementor-frontend without the elementor-dialog dependency.
    $suffix = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
    wp_register_script(
            'elementor-frontend',
            ELEMENTOR_ASSETS_URL . 'js/frontend' . $suffix . '.js',
            [
                //'elementor-dialog', // <-- We removed this
                'elementor-waypoints',
                'jquery-swiper',
            ],
            ELEMENTOR_VERSION,
            true
        );

    // debugging... 
    //$scripts = wp_scripts();
    //exit ( print_r( $scripts ) );
}

Solution 2:

In this solution, we will use wp_scripts() to modify the $wp_scripts global and then safely deregister elementor-dialog.

We will remove the elementor-dialog dependency from the elementor-frontend handle, then dequeue the elementor-dialog script which is enqueued separately by the Elementor\Frontend class.

/**
 * The Elementor\Frontend class runs its register_scripts() method on
 * wp_enqueue_scripts at priority 5, so we want to hook in after this has taken place.
 */
add_action( 'wp_enqueue_scripts', 'wpse_elementor_frontend_scripts_modifier', 6 );
function wpse_elementor_frontend_scripts_modifier() {

    // Customize guard clauses to bail if we don't want to run this code.
    /*if ( ! is_singular( 'cpt' ) ) {
        return;
    }*/

    // Get all scripts.
    $scripts = wp_scripts();

    // Bail if something went wrong.
    if ( ! ( $scripts instanceof WP_Scripts ) ) {
        return;
    }

    // Array of handles to remove.
    $handles_to_remove = [
        'elementor-dialog',
    ];

    // Flag indicating if we have removed the handles.
    $handles_updated = false;

    // Remove desired handles from the elementor-frontend script. 
    foreach ( $scripts->registered as $dependency_object_id => $dependency_object ) {

        if ( 'elementor-frontend' === $dependency_object_id ) {

            // Bail if something went wrong.
            if ( ! ( $dependency_object instanceof _WP_Dependency ) ) {
                return;
            }

            // Bail if there are no dependencies for some reason.
            if ( empty( $dependency_object->deps ) ) {
                return;
            }

            // Do the handle removal.
            foreach ( $dependency_object->deps as $dep_key => $handle ) {
                if ( in_array( $handle, $handles_to_remove ) ) {
                    unset( $dependency_object->deps[ $dep_key ] );
                    $dependency_object->deps = array_values( $dependency_object->deps );  // "reindex" array
                    $handles_updated = true;
                }
            }
        }
    }

    // If we have updated the handles, dequeue the relevant dependencies which
    // were enqueued separately Elementor\Frontend.
    if ( $handles_updated ) {
        wp_dequeue_script( 'elementor-dialog' );
        wp_deregister_script( 'elementor-dialog' );
    }
}

By modifying elementor-frontend before dequeueing elementor-dialog, we will not unintentionally dequeue elementor-frontend when we dequeue elementor-dialog.

When testing this code, I inspected the $wp_scripts global (via wp_scripts()) to ensure that the desired results took effect. E.g.

$scripts = wp_scripts();
print_r( $scripts ); 

Relevant part of $scripts before modification:

...

[elementor-dialog] => _WP_Dependency Object
(
    [handle] => elementor-dialog
    [src] => http://example.com/wp-content/plugins/elementor/assets/lib/dialog/dialog.js
    [deps] => Array
            (
                    [0] => jquery-ui-position
            )

    [ver] => 4.1.0
    [args] => 
    [extra] => Array
            (
                    [group] => 1
            )

)

[elementor-frontend] => _WP_Dependency Object
(
    [handle] => elementor-frontend
    [src] => http://example.com/wp-content/plugins/elementor/assets/js/frontend.js
    [deps] => Array
            (
                    [0] => elementor-dialog
                    [1] => elementor-waypoints
                    [2] => jquery-swiper
            )

    [ver] => 1.9.7
    [args] => 
    [extra] => Array
            (
                    [group] => 1
            )

)

...

Relevant part of $scripts after modification:

(Note that the elementor-dialog node has now been removed.)

...
[elementor-frontend] => _WP_Dependency Object
(
    [handle] => elementor-frontend
    [src] => http://example.com/wp-content/plugins/elementor/assets/js/frontend.js
    [deps] => Array
            (
                    [0] => elementor-waypoints
                    [1] => jquery-swiper
            )

    [ver] => 1.9.7
    [args] => 
    [extra] => Array
            (
                    [group] => 1
            )

)
...

OTHER TIPS

why not simple use the elementor hooks to unset an asset? like this:

function remove_elementor_swiper() {
    wp_dequeue_script( 'swiper' );
    wp_deregister_script( 'swiper' );
    
}
add_action( 'elementor/frontend/after_register_scripts', 'remove_elementor_swiper' );
Licensed under: CC-BY-SA with attribution
Not affiliated with wordpress.stackexchange
scroll top