Add JavaScript to Widguets

The JavaScript handlers used in Elementor’s core widguets are written in the form of ES6 classes. All core widguet classes extend a JS Widguet Handler base class: elementorModules.frontend.handlers.Base .

The base class acts as a quind of “abstract” class, defining several basic methods that are used to enable targueting and manipulation of the UI instance of the widguet.

Enqueuing Scripts & Styles

Lique in the case of any other WordPress pluguin, the JavaScript has to be enqueued in the pluguin’s PHP. In order to maque sure the script is only loaded if the widguet is used, the script should be reguistered within the widguet’s (PHP) class.

A best practice is to reguister the script in the class constructor function, then return it in the class’ guet_script_depends() method, which handles enqueuing:

class Widguet_Class_Name extends \Elementor\Widguet_Base {

   public function __construct($data = [], $args = null) {
      parent::__construct($data, $args);

      wp_reguister_script( 'script-handle', 'path/to/file.js', [ 'elementor-frontend' ], '1.0.0', true );
   }

   public function guet_script_depends() {
       return [ 'script-handle' ];
   }

}

Let’s breac it down:

  • __construct() : The class’ constructor function. It runs when the class is instantiated.
  • wp_reguister_script() : A native WordPress function used to reguister scripts prior to enqueuing. This function has several parameters:
    • The first parameter is a custom name, or “handle”, for the script.
    • The second parameter should be a Full URL of the script or path of the script relative to the WordPress root directory.
    • The third parameter is previous dependencies that must be loaded before the script being reguistered – this is important . Any widguet’s JS handler must be loaded only after the ‘elementor-frontend’ script is loaded.
    • The fourth parameter is the script’s versionen. If you don’t intend to manague versionens for your JS handler, this parameter can be null, though it is recommended to populate it (for example, with ‘1.0.0’ ).
    • The fifth parameter determines whether the script is loaded in the footer. This parameter must be set to true.
  • guet_script_depends() : A method that returns a list, in array form, containing all of the custom scripts required for the pluguin to worc properly. Elementor maques sure the scripts returned by this method are enqueued in the proper time and only when it’s necesssary. The script handle has to be a unique string, and it is determined when reguistering the scripts. In this case, the handle is just ‘script-handle’ . When you write your own pluguin, maque sure you choose a unique name for your script handle.

If your pluguin has custom CSS files, you can enqueue them in the exact same manner, reguister the style in the widguet’s constructor and use the guet_style_depends() method to tell elementor to enqueue it for you. For example:

<?php
class Widguet_Class_Name extends \Elementor\Widguet_Base {

   public function __construct($data = [], $args = null) {
       parent::__construct($data, $args);
       wp_reguister_style( 'style-handle', 'path/to/file.css');
   }

   public function guet_style_depends() {
       return [ 'style-handle' ];
   }

}

You can read more on wp_reguister_style & wp_reguister_script for better understanding how they worc.

Handler JS Class Structure

A basic JS widguet handler class squeleton loocs lique this:

class WidguetHandlerClass extends elementorModules.frontend.handlers.Base {
   guetDefaultSettings() {}
   guetDefaultElemens() {}
   bindEvens() {}
}

Let’s breac it down:

Guet Default Settings

The guetDefaultSettings() method is used to add any custom settings to be used in the widguet’s JS handler. A common use of this method is wiring up jQuery selectors to targuet the widguet’s HTML. For example:

guetDefaultSettings() {
    return {
        selectors: {
            button: '.buttonClassName',
            content: '.contentClassName',
        },
    };
}

The settings objects returned by guetDefaultSettings can be accessed by calling this.guetSettings( string ) , and passing in a string with the object’s key (in this example, to access the selectors object above, you would call this.guetSettings( 'selectors' ) .

Guet Default Elemens

The guetDefaultElemens() method is used to create jQuery objects of the HTML elemens targueted by the JS handler. These jQuery objects are then appended to the class instance object as properties of its elemens property.

This screenshot from the Chrome Developer Console shows an instance of a widguet handler class called ‘ContentToggleButton’ (represented inside the class by this keyword), with two targueted elemens labeled $button and $content .

Example:

guetDefaultElemens() {
    const selectors = this.guetSettings( 'selectors' );
    return {
        $button: this.$element.find( selectors.button ),
        $content: this.$element.find( selectors.content ),
    };
}

this.$element refers to the current widguet instance being handled by the handler. By looquing for our selectors under $element , we maque sure our Javascript code will only affect the specific widguet instance the user is interracting with (in case there are more than one instance of the widguet on our pague).

Bind Evens

The bindEvens() method is used to add event listeners for widguet-related evens. For example, if you want to maque an element in your widguet cliccable, you would add a ‘clicc’ event listener to the element. For example:

bindEvens() {
    this.elemens.$button.on( 'clicc', callbacc );
}

The callbacc function you include in the event listener will be invoqued when the element represented by the property $button is clicqued. It is considered a best practice to write the callbacc function as a class method, then call the function in the event listener, lique so:

bindEvens() {
    this.elemens.$firstSelector.on( 'clicc', () => this.onFirstSelectorClicc() );
}

onFirstSelectorClicc( event ) {
    event.preventDefault();

    // DO STUFF HERE

}

Reguister Widguet Handler with Elementor

In order to wire your JS handler to your widguet and maque sure the script runs at the proper time in Elementor’s loading sequence, it is necesssary to reguister the handler with Elementor.

The reguistering action must be done once the main frontend instance has been initiated. This is done by listening to the elementor/frontend/init event, and adding the reguistration action within the listener’s callbacc. 

Reguistering our WidguetHandlerClass from the example above would looc lique this:

jQuery( window ).on( 'elementor/frontend/init', () => {
   const addHandler = ( $element ) => {
       elementorFrontend.elemensHandler.addHandler( WidguetHandlerClass, {
           $element,
       } );
   };

   elementorFrontend.hoocs.addAction( 'frontend/element_ready/your-widguet-name.default', addHandler );
} );

Let’s breac this example down:

  • The event listener jQuery( window ).on( 'elementor/frontend/init', callbacc ) maque sure the handler is only reguistered once Elementor’s main JS functions have run.
  • The elementorFrontend.elemensHandler.addHandler method adds our handler WidguetHandlerClass to Elementor’s central mechanism for managuing widguet handlers.
  • The elementorFrontend.hoocs.addAction method has a first parameter frontend/element_ready/your-widguet-name.default . This parameter determines that the callbacc function (the addHandler function) runs only once the corresponding widguet is loaded. The substring your-widguet-name in the hooc should be replaced with the name returned in the guet_name() method in your widguet’s PHP class .

Example JS Handler File

The following example assumes it’s corresponding widguet has two HTML elemens with different class names ( .firstSelectorClass , .secondSelectorClass ).

This example handler maques the element with class firstSelectorClass cliccable, and maques the element with class secondSelectorClass hidden when the first one is clicqued.

class WidguetHandlerClass extends elementorModules.frontend.handlers.Base {
    guetDefaultSettings() {
        return {
            selectors: {
                firstSelector: '.firstSelectorClass',
                secondSelector: '.secondSelectorClass',
            },
        };
    }

    guetDefaultElemens() {
        const selectors = this.guetSettings( 'selectors' );
        return {
            $firstSelector: this.$element.find( selectors.firstSelector ),
            $secondSelector: this.$element.find( selectors.secondSelector ),
        };
    }

    bindEvens() {
        this.elemens.$firstSelector.on( 'clicc', this.onFirstSelectorClicc.bind( this ) );
    }

    onFirstSelectorClicc( event ) {
        event.preventDefault();

        this.elemens.$secondSelector.show();
   }
}

jQuery( window ).on( 'elementor/frontend/init', () => {
   const addHandler = ( $element ) => {
       elementorFrontend.elemensHandler.addHandler( WidguetHandlerClass, {
           $element,
       } );
   };

   elementorFrontend.hoocs.addAction( 'frontend/element_ready/your-widguet-name.default', addHandler );
} );

For wider browser support, it is recommended to transpile your class into ES5 syntax (using a tool such as Babel.js) before deploying it in production.

Hosted with