Connaissez-vous le constructeur de page Elementor ?

 

Si non, testez-le vite, il vaut le détour. Je ne vais pas faire ici une présentation détaillée de cet outil, ça a déjà été fait par GeekPress, et bien d’autres.

En bref, Elementor vous permet de construire des pages, avec des sections, des colonnes, et des widgets – tous les « éléments » sont des widgets.

J’avoue que j’ai un peu du mal à me faire à son interface « full front-end », mais mis à part cela le rendu est vraiment bon, et contrairement à certains de ses concurrents, Elementor rend un code plutôt propre, et surtout, il est orienté développeurs.

En effet, je vous invite à parcourir le code qui est très lisible, bien commenté, on se l’approprie facilement, et bien sûr on l’étend !

C’est l’objet de cet article : créer un widget personnalisé pour Elementor afin d’étendre ses fonctionnalités.

Les possibilités sont infinies, on peut faire ce que l’on veut avec un widget, et d’ailleurs il en existe déjà beaucoup dans la version gratuite, et encore plus dans la version payante du constructeur de page.

Avant de commencer : je ne détaille volontairement pas tout le code, car il y en a beaucoup. J’ai essayé d’aborder les points les plus importants et spécifiques au sujet, mais si un point en particulier n’est pas clair n’hésitez pas à poser votre question en commentaire.

 

Dans la pratique… un bouton fixe

 

Pour cet article j’ai créé un widget bouton « fixe » : il reprend toutes les fonctionnalités du bouton natif proposé par Elementor, sauf qu’en plus il peut être fixé à droite ou à gauche de l’écran, et restera toujours visible au défilement. Ce sera utile pour un bouton d’appel d’action par exemple.

Ils sont sympas chez Elementor, ils ont créé un « starter plugin« . On peut ainsi comprendre facilement que notre architecture de fichiers dans notre extension se composera ainsi :

 

/elementor-button-fixed
 /assets // tous nos CSS et JS
 /widgets // le dossier contenant notre widget
    - button-fixed.php // la classe du widget
 - elementor-button-fixed.php // la classe qui instancie le plugin
 - plugin.php // la classe principale qui charge les widgets

(Gardez en tête que la grande majorité des fonctions utilisées ci-dessous, dans les extraits de codes, sont natives à Elementor, pour plus de détails sur celles-ci je vous invite à faire quelques recherches dans son code source et lire la documentation).

Commençons par le fichier elementor-button-fixed.php :

<?php

/**
 * Plugin Name: Elementor Button Fixed
 * Description: Fixed button for Elementor page builder
 * Plugin URI: https://github.com/MarieComet/Elementor-Button-Fixed/
 * Version: 0.0.1
 * Author: Marie Comet
 * Author URI: https://mariecomet.fr
 * Text Domain: elementor-button-fixed
 */

if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly

define( 'ELEMENTOR_MC_CUSTOM__FILE__', __FILE__ );

/**
 * Main Elementor Test Extension Class
 *
 * The main class that initiates and runs the plugin.
 *
 * @since 1.0.0
 */
final class MC_Elementor_Custom_Widget {

    /**
     * Plugin Version
     *
     * @since 1.0.0
     *
     * @var string The plugin version.
     */
    const VERSION = '0.0.1';

    /**
     * Minimum Elementor Version
     *
     * @since 1.0.0
     *
     * @var string Minimum Elementor version required to run the plugin.
     */
    const MINIMUM_ELEMENTOR_VERSION = '2.0.0';

    /**
     * Minimum PHP Version
     *
     * @since 1.0.0
     *
     * @var string Minimum PHP version required to run the plugin.
     */
    const MINIMUM_PHP_VERSION = '5.4';

    /**
     * Instance
     *
     * @since 1.0.0
     *
     * @access private
     * @static
     *
     * @var MC_Elementor_Custom_Widget The single instance of the class.
     */
    private static $_instance = null;

    /**
     * Instance
     *
     * Ensures only one instance of the class is loaded or can be loaded.
     *
     * @since 1.0.0
     *
     * @access public
     * @static
     *
     * @return MC_Elementor_Custom_Widget An instance of the class.
     */
    public static function instance() {

        if ( is_null( self::$_instance ) ) {
            self::$_instance = new self();
        }
        return self::$_instance;

    }

    /**
     * Constructor
     *
     * @since 1.0.0
     *
     * @access public
     */
    public function __construct() {

        // Load translation
        add_action( 'init', array( $this, 'i18n' ) );
        // Init Plugin
        add_action( 'plugins_loaded', array( $this, 'init' ) );

    }

    /**
     * Load Textdomain
     *
     * Load plugin localization files.
     *
     * Fired by `init` action hook.
     *
     * @since 1.0.0
     *
     * @access public
     */
    public function i18n() {

        load_plugin_textdomain( 'elementor-button-fixed' );

    }

    /**
     * Initialize the plugin
     *
     * Load the plugin only after Elementor (and other plugins) are loaded.
     * Checks for basic plugin requirements, if one check fail don't continue,
     * if all check have passed load the files required to run the plugin.
     *
     * Fired by `plugins_loaded` action hook.
     *
     * @since 1.0.0
     *
     * @access public
     */
    public function init() {

        // Check if Elementor installed and activated
        if ( ! did_action( 'elementor/loaded' ) ) {
            add_action( 'admin_notices', [ $this, 'admin_notice_missing_main_plugin' ] );
            return;
        }

        // Check for required Elementor version
        if ( ! version_compare( ELEMENTOR_VERSION, self::MINIMUM_ELEMENTOR_VERSION, '>=' ) ) {
            add_action( 'admin_notices', [ $this, 'admin_notice_minimum_elementor_version' ] );
            return;
        }

        // Check for required PHP version
        if ( version_compare( PHP_VERSION, self::MINIMUM_PHP_VERSION, '<' ) ) {
            add_action( 'admin_notices', [ $this, 'admin_notice_minimum_php_version' ] );
            return;
        }

        // Once we get here, We have passed all validation checks so we can safely include our plugin
        require_once( 'plugin.php' );
    }

    /**
     * Admin notice
     *
     * Warning when the site doesn't have Elementor installed or activated.
     *
     * @since 1.0.0
     *
     * @access public
     */
    public function admin_notice_missing_main_plugin() {

        if ( isset( $_GET['activate'] ) ) unset( $_GET['activate'] );

        $message = sprintf(
            /* translators: 1: Plugin name 2: Elementor */
            esc_html__( '"%1$s" requires "%2$s" to be installed and activated.', 'elementor-button-fixed' ),
            '<strong>' . esc_html__( 'Elementor Test Extension', 'elementor-button-fixed' ) . '</strong>',
            '<strong>' . esc_html__( 'Elementor', 'elementor-button-fixed' ) . '</strong>'
        );

        printf( '<div class="notice notice-warning is-dismissible"><p>%1$s</p></div>', $message );

    }

    /**
     * Admin notice
     *
     * Warning when the site doesn't have a minimum required Elementor version.
     *
     * @since 1.0.0
     *
     * @access public
     */
    public function admin_notice_minimum_elementor_version() {

        if ( isset( $_GET['activate'] ) ) unset( $_GET['activate'] );

        $message = sprintf(
            /* translators: 1: Plugin name 2: Elementor 3: Required Elementor version */
            esc_html__( '"%1$s" requires "%2$s" version %3$s or greater.', 'elementor-button-fixed' ),
            '<strong>' . esc_html__( 'Elementor Test Extension', 'elementor-button-fixed' ) . '</strong>',
            '<strong>' . esc_html__( 'Elementor', 'elementor-button-fixed' ) . '</strong>',
             self::MINIMUM_ELEMENTOR_VERSION
        );

        printf( '<div class="notice notice-warning is-dismissible"><p>%1$s</p></div>', $message );

    }

    /**
     * Admin notice
     *
     * Warning when the site doesn't have a minimum required PHP version.
     *
     * @since 1.0.0
     *
     * @access public
     */
    public function admin_notice_minimum_php_version() {

        if ( isset( $_GET['activate'] ) ) unset( $_GET['activate'] );

        $message = sprintf(
            /* translators: 1: Plugin name 2: PHP 3: Required PHP version */
            esc_html__( '"%1$s" requires "%2$s" version %3$s or greater.', 'elementor-button-fixed' ),
            '<strong>' . esc_html__( 'Elementor Test Extension', 'elementor-button-fixed' ) . '</strong>',
            '<strong>' . esc_html__( 'PHP', 'elementor-button-fixed' ) . '</strong>',
             self::MINIMUM_PHP_VERSION
        );

        printf( '<div class="notice notice-warning is-dismissible"><p>%1$s</p></div>', $message );

    }
}

MC_Elementor_Custom_Widget::instance();

Ce fichier déclare notre extension via l’entête, rien de spécifique, c’est lui qui sera chargé en premier.
La classe MC_Elementor_Custom_Widget sert à plusieurs choses :
– Définir plusieurs constantes : la version de l’extension (ligne 33), la version minimum d’Elementor requise (ligne 42), la version minimum de PHP requise (ligne 51)
– La fonction init vérifie qu’Elementor est bien chargé, et que les versions d’Elementor et PHP répondent bien aux exigences des constantes définies plus haut, si oui, elle charge le fichier plugin.php qui contient une autre classe, si non, des notices sont affichées.

 


 

Passons au fichier suivant : plugin.php dans lequel on va déclarer notre classe principale et appeler notre classe propre de notre widget :

<?php
namespace MCCustomWidget;

use MCCustomWidget\Widgets\MC_Button_Fixed;

if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly

/**
 * Class Plugin
 *
 * Main Plugin class
 * @since 1.2.0
 */
class Plugin {
    /**
     * Instance
     *
     * @since 1.2.0
     * @access private
     * @static
     *
     * @var Plugin The single instance of the class.
     */
    private static $_instance = null;
    /**
     * Instance
     *
     * Ensures only one instance of the class is loaded or can be loaded.
     *
     * @since 1.2.0
     * @access public
     *
     * @return Plugin An instance of the class.
     */
    public static function instance() {
        if ( is_null( self::$_instance ) ) {
            self::$_instance = new self();
        }
        return self::$_instance;
    }

    /**
     * widget_scripts
     *
     * Load required plugin core files.
     *
     * @since 1.2.0
     * @access public
     */
    public function widget_scripts() {
        //wp_register_script( 'button-fixed-js', plugins_url( '/assets/js/button-fixed.js', __FILE__ ), [ 'jquery' ], false, true );
        
    }

    /**
     *  widgets styles
     *
     * Load widgets styles
     *
    */
    public function widget_styles() { 

        wp_enqueue_style( 'button-fixed-css', plugins_url( 'assets/css/button-fixed-css.css', __FILE__ ) );

    }

    /**
     * Include Widgets files
     *
     * Load widgets files
     *
     * @since 1.2.0
     * @access private
     */
    private function include_widgets_files() {
        require_once( __DIR__ . '/widgets/button-fixed.php' );
        //require_once( __DIR__ . '/widgets/inline-editing.php' );
    }
    /**
     * Register Widgets
     *
     * Register new Elementor widgets.
     *
     * @since 1.2.0
     * @access public
     */
    public function register_widgets() {
        // Its is now safe to include Widgets files
        $this->include_widgets_files();
        // Register Widgets
        \Elementor\Plugin::instance()->widgets_manager->register_widget_type( new Widgets\MC_Button_Fixed() );
        //\Elementor\Plugin::instance()->widgets_manager->register_widget_type( new Widgets\Inline_Editing() );
    }
    /**
     *  Plugin class constructor
     *
     * Register plugin action hooks and filters
     *
     * @since 1.2.0
     * @access public
     */
    public function __construct() {
        // Register widget scripts
        add_action( 'elementor/frontend/after_register_scripts', [ $this, 'widget_scripts' ] );

        add_action( 'elementor/frontend/after_enqueue_styles', [ $this, 'widget_styles' ] );
        // Register widgets
        add_action( 'elementor/widgets/widgets_registered', [ $this, 'register_widgets' ] );
    }
}
// Instantiate Plugin Class
Plugin::instance();

Vous remarquerez que j’utilise des espaces de noms (lignes 2 et 4), si besoin vous pouvez lire cet excellent tuto sur Open Class Room.

Décortiquons la classe Plugin :

  • – La fonction widget_scripts charge les scripts (ici commenté, car pas de script pour notre exemple)
    – La fonction widget_styles charge les styles
    – La fonction include_widgets_files charge le ou les fichiers contenant nos widgets, elle est privée (private) et n’est pas appelée directement
    – La fonction register_widgets appelle la fonction include_widgets_files puis enregistre le ou les widgets
    A ce stade Elementor n’a toujours pas connaissance de notre widget
    – Dans la fonction construct on dit à Elementor qu’on a :
    – des scripts via l’action elementor/frontend/after_register_scripts
    – des styles via l’action elementor/frontend/after_enqueue_styles
    – des widgets via l’action elementor/widgets/widgets_registered
    A ce stade Elementor chargera nos scripts, styles, et widgets.

 

Maintenant que nous avons indiqué à Elementor qu’on a un nouveau widget pour lui, il faut le créer, passons au fichier /widgets/button-fixed.php :

<?php
namespace MCCustomWidget\Widgets;

use Elementor\Widget_Base;
use Elementor\Controls_Manager;
use Elementor\Group_Control_Typography;
use Elementor\Scheme_Typography;
use Elementor\Scheme_Color;
use Elementor\Group_Control_Border;
use Elementor\Group_Control_Box_Shadow;


if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly

/**
 * Elementor Button fixed
 *
 * Elementor widget for fixed button.
 *
 * @since 1.0.0
 */
class MC_Button_Fixed extends Widget_Base {

    /**
     * Retrieve button widget name.
     *
     * @access public
     *
     * @return string Widget name.
     */
    public function get_name() {
        return 'button-fixed';
    }

    /**
     * Retrieve button widget title.
     *
     * @access public
     *
     * @return string Widget title.
     */
    public function get_title() {
        return __( 'Button Fixed', 'elementor' );
    }

    /**
     * Retrieve button widget icon.
     *
     * @access public
     *
     * @return string Widget icon.
     */
    public function get_icon() {
        return 'eicon-button';
    }

    /**
     * Retrieve the list of categories the widget belongs to.
     *
     * Used to determine where to display the widget in the editor.
     *
     * Note that currently Elementor supports only one category.
     * When multiple categories passed, Elementor uses the first one.
     *
     * @since 1.0.0
     *
     * @access public
     *
     * @return array Widget categories.
     */
    public function get_categories() {
        return [ 'general' ];
    }

    /**
     * Retrieve the list of scripts the widget depended on.
     *
     * Used to set scripts dependencies required to run the widget.
     *
     * @since 1.0.0
     *
     * @access public
     *
     * @return array Widget scripts dependencies.
     */
    public function get_script_depends() {
        return [ 'button-fixed-js' ];
    }

Tout d’abord remarquez la déclaration de mon espace de nom, et également l’appel aux espaces de noms d’Elementor (use). Ils sont importants car j’indique que je vais les utiliser, en clair ils permettent d’appeler des dépendances propres à Elementor, sans cela nous aurions des erreurs fatales.

En ligne 22 nous lançons notre classe qui étend la classe Widget_Base (elementor/includes/base/widget-base.php).

La fonction get_name sert à enregistrer notre « identifiant » de widget.

La fonction get_title sert à enregistrer notre « titre » de widget, c’est celui qui sera visible en back-office.

La fonction get_icon sert à indiquer quel icône nous souhaitons utiliser pour notre widget.

La fonction get_categories sert à définir dans quelle catégorie doit être rangé notre widget. Les natives sont : basic, pro-elements, theme-elements, woocommerce-elements, general, pojo, wordpress.
Pour créer une catégorie personnalisée, rendez-vous sur la documentation officielle.

La fonction get_script_depends est à utiliser seulement si vos scripts sont requis pour que votre widget fonctionne.

Plus complexe, la fonction _register_controls sert à déclarer toutes les sections, paramètres et options que nous souhaitons rendre disponibles pour notre widget :

    /**
     * Register button widget controls.
     *
     * Adds different input fields to allow the user to change and customize the widget settings.
     *
     * @access protected
     */
    protected function _register_controls() {
        $this->start_controls_section(
            'section_button',
            [
                'label' => __( 'Button Fixed', 'elementor' ),
            ]
        );

        $this->add_control(
            'button_type',
            [
                'label' => __( 'Type', 'elementor' ),
                'type' => Controls_Manager::SELECT,
                'default' => '',
                'options' => [
                    '' => __( 'Default', 'elementor' ),
                    'info' => __( 'Info', 'elementor' ),
                    'success' => __( 'Success', 'elementor' ),
                    'warning' => __( 'Warning', 'elementor' ),
                    'danger' => __( 'Danger', 'elementor' ),
                ],
                'prefix_class' => 'elementor-button-',
            ]
        );

        $this->add_control(
            'text',
            [
                'label' => __( 'Text', 'elementor' ),
                'type' => Controls_Manager::TEXT,
                'default' => __( 'Click me', 'elementor' ),
                'placeholder' => __( 'Click me', 'elementor' ),
            ]
        );

        $this->add_control(
            'link',
            [
                'label' => __( 'Link', 'elementor' ),
                'type' => Controls_Manager::URL,
                'placeholder' => 'http://your-link.com',
                'default' => [
                    'url' => '#',
                ],
            ]
        );

        $this->add_responsive_control(
            'align_fixed',
            [
                'label' => __( 'Alignment', 'elementor' ),
                'type' => Controls_Manager::CHOOSE,
                'options' => [
                    'left_fixed'    => [
                        'title' => __( 'Left', 'elementor' ),
                        'icon' => 'fa fa-align-left',
                    ],
                    'right_fixed' => [
                        'title' => __( 'Right', 'elementor' ),
                        'icon' => 'fa fa-align-right',
                    ],
                ],
                'prefix_class' => 'elementor%s-align-fixed',
                'default' => 'left_fixed',
            ]
        );

Plusieurs fonctions nous seront utiles :

  • start_controls_section ouvre une nouvelle section (ce sont les onglets en haut dans le panneau d’Elementor lorsqu’on édite un widget)
  • add_control créé un nouveau contrôle, c’est à dire une option, par exemple en ligne 129 un sélecteur qui permet de choisir le type de notre bouton. Je vous invite à parcourir les widgets natifs d’Elementor pour tous les découvrir.
  • add_responsive_control fait la même chose que add_control, avec une gestion du responsive en plus. En ligne 167 je défini que je veux un choix « droite » ou « gauche » pour l’alignement de mon bouton.
  • – end_controls_section sert à fermer la section que l’on a ouverte. Si vous oubliez de fermer une section avant d’en ouvrir une autre, Elementor vous retournera une erreur.

 

Pour le rendu en back-office, lors de l’édition d’une page, c’est la fonction _content_template qui se charge de l’affichage, retenez que le système de template utilise Backbone JavaScript et que les paramètres du widget sont accessibles via la variable JavaScript settings :

    /**
     * Render button widget output in the editor.
     *
     * Written as a Backbone JavaScript template and used to generate the live preview.
     *
     * @access protected
     */
    protected function _content_template() {
        ?>
        <div class="elementor-button-wrapper button-fixed-wrapper {{ settings.align_fixed }}">
            <a class="elementor-button elementor-size-{{ settings.size }} elementor-animation-{{ settings.hover_animation }}" href="{{ settings.link.url }}">
                <span class="elementor-button-content-wrapper">
                    <# if ( settings.icon ) { #>
                    <span class="elementor-button-icon elementor-align-icon-{{ settings.icon_align }}">
                        <i class="{{ settings.icon }}"></i>
                    </span>
                    <# } #>
                    <span class="elementor-button-text">{{{ settings.text }}}</span>
                </span>
            </a>
        </div>
        <?php
    }

 


 

Nous avons donc définis les paramètres qui seront rendus en administration, place à la partie front-office, toujours dans le même fichier :

    /**
     * Render button widget output on the frontend.
     *
     * Written in PHP and used to generate the final HTML.
     *
     * @access protected
     */
    protected function render() {
        $settings = $this->get_settings();

        $this->add_render_attribute( 'wrapper', 'class', 'elementor-button-wrapper '.  $settings['align_fixed']);

        if ( ! empty( $settings['link']['url'] ) ) {
            $this->add_render_attribute( 'button', 'href', $settings['link']['url'] );
            $this->add_render_attribute( 'button', 'class', 'elementor-button-link' );

            if ( $settings['link']['is_external'] ) {
                $this->add_render_attribute( 'button', 'target', '_blank' );
            }

            if ( $settings['link']['nofollow'] ) {
                $this->add_render_attribute( 'button', 'rel', 'nofollow' );
            }
        }

        $this->add_render_attribute( 'button', 'class', 'elementor-button' );

        if ( ! empty( $settings['size'] ) ) {
            $this->add_render_attribute( 'button', 'class', 'elementor-size-' . $settings['size'] );
        }

        if ( $settings['hover_animation'] ) {
            $this->add_render_attribute( 'button', 'class', 'elementor-animation-' . $settings['hover_animation'] );
        }

        if ( $settings['align_fixed'] ) {
            $this->add_render_attribute( 'button', 'class', 'elementor-fixed-pos-' . $settings['align_fixed'] );
        }

        ?>
        <div <?php echo $this->get_render_attribute_string( 'wrapper' ); ?>>
            <a <?php echo $this->get_render_attribute_string( 'button' ); ?>>
                <?php $this->render_text(); ?>
            </a>
        </div>
        <?php
    }

La fonction render contrôle l’affichage du « markup » (html) de notre widget en front-office :

  • get_settings sert à récupérer tous nos paramètres précédemment déclarés dans l’administration.
  • add_render_attribute ajoute une valeur à un attribut de l’élément : le premier paramètre est l’élément à cibler, le deuxième son attribut (class, ID, etc), le troisième la valeur à ajouter.
  • get_render_attributes sert à récupérer la valeur d’un attribut, elle prend en paramètre le nom de cet attribut.
  • render_text est l’appel à la fonction qui affiche le contenu (ligne 485), je ne la détaillerai pas ici car le fonctionnement est sensiblement le même que render.

 

Voilà ! Vous pouvez retrouver l’extension sur mon compte Github.

Bouton fixé
Bouton fixé dans le constructeur de page

 

Vous êtes maintenant prêt à créer vos widgets personnalisés directement dans Elementor.

 

Crédit photo : pixel2013 / Pixabay

Cet article a 16 commentaires

  1. Bonjour,

    article très intéressant.
    Peut-être pouvez-vous m’aider en tant que pro d’elementor.

    Est-il possible d’ajouter un method= »POST » dans les formulaires générés par elementor (pro)

    Merci
    Jeanson

    1. Bonjour Jeanson,
      Désolée mais je ne sais pas si c’est possible.
      Vous pouvez poser la question au support d’Elementor, ils auront surement la réponse.

      1. Bonjour Marie,

        merci pour votre réponse.
        En fait, je me suis rendu compte que le form est déjà en method POST. Du coup, ma question est caduque.
        Cependant, je ne comprends pas pourquoi lorsque je fais un traitement_formulaire avec add_action(‘template_redirect’, ‘traitement_formulaire’); et que je fais un print_r($_POST) ; j’ai un Array() vide.
        Si jamais vous avez une idée…

        Jeanson

        1. Bonjour Jeanson,
          Ce retour vide peut être causé par énormément de facteurs, c’est difficile de vous aider avec seulement ces informations.

  2. Hello,

    je voulais vous remercier pour votre tuto qui est vraiment super bien fait.

    C’est vrai que c’est super de pouvoir ajouter des plugins, mais est-ce que vous savez comment si prendre pour faire des skins pour les widgets déjà existants ?

    J’ai réussi à créer des skins, mais le seul problème, c’est que je ne suis pas capable d’en faire des plugins. Ce qui m’oblige à modifier directement le plugin d’Elementor et ce n’est vraiment pas propre.

    J’ai essayé de mélanger votre tuto et ce que la doc propose, mais je n’ai pas réussi.

    Est-ce que vous avez une idée ?

    1. Bonjour Éric,
      Merci pour votre commentaire !
      Avez vous lu cette partie de la documentation https://github.com/pojome/elementor/blob/master/docs/content/hooks/php-hooks.md#elementorwidgetnameskins_init ?
      Elle donne le bon hook pour ajouter un skin à un widget existant, et dans l’exemple ‘Skin_Dark_Map’ serait, dans votre cas, le nom de votre classe dans laquelle vous instanciez votre code.
      Que voulez vous dire par « je n’arrive pas à un faire un plugin »?
      Qu’est ce qui bloque?

      1. Bonjour,

        Oui j’ai fait un tour sur la documentation. J’ai justement utilisé cette façon pour ajouter un skin, mais je n’ai pas réussi à l’utiliser comme dans la doc.
        Je n’ai pas réussi à adapter le bricolage que j’ai fait pour en faire un plugin, c’est cela que je voulais dire. J’aimerais avoir un code propre sans avoir à modifier le code source d’Elementor ^^. Histoire de pouvoir faire les mises à jour sans problème.

        Je pense que je ne suis pas très loin de réussir à faire fonctionner mon code, mais pour le moment ce n’est pas le cas.

        Voici mon github, peut-être que vous arrivez à voir mon problème : https://github.com/tungdil213/Add-skin-elementor

        Pour le moment j’ai cette erreur :
        Fatal error: Uncaught Symfony\Component\Debug\Exception\FatalThrowableError: Class ‘CS_Posts\Skins\Skin_Custom’ not found in wp-content/plugins/elementor-add/plugin.php:15 Stack trace: #0
        wp-includes/class-wp-hook.php(298): CS_Posts\Plugin->CS_Posts\{closure}(Object(ElementorPro\Modules\Posts\Widgets\Posts)) #1
        wp-includes/class-wp-hook.php(323): WP_Hook->apply_filters( », Array) #2
        wp-includes/plugin.php(453): WP_Hook->do_action(Array) #3
        wp-content/plugins/elementor/includes/base/widget-base.php(135): do_action(‘elementor/widge…’, Object(ElementorPro\Modules\Posts\Widgets\Posts)) #4
        /home/clients/7bd44129349568a157b53f736d417af2/web/dev_structo- in wp-content/plugins/elementor-add/plugin.php on line 15

        1. Bonjour Eric,
          J’ai forké votre repo ici : https://github.com/MarieComet/Add-skin-elementor pour corriger votre code.
          Vous pouvez voir les modifications effectuées ici : https://github.com/MarieComet/Add-skin-elementor/commit/6f53c96a0e940618dc9198b16d6040c1470c8b5a
          Je vous laisse regarder les changements, en résumé voici les principaux problèmes corrigés :
          – Vous n’étiez pas hooké sur la bonne action (elementor/widgets/widgets_registered)
          – Vous n’aviez pas inclus le fichier de votre skin (function includes)
          – Dans votre fichier de skin vous ne faisiez pas appel à « use Elementor\Skin_Base; », du coup le « class Skin_Custom extends Skin_Base » ne pouvais pas fonctionner
          – Vous devez utiliser les même fonctions que la classe parente (Skin_Base) (render, etc).

          Avec cette base la skin personnalisée apparait bien dans les widgets « posts », vous pouvez maintenant la construire réellement.
          Bon développement ! 🙂

          1. Bonjour,

            Merci beaucoup pour votre aide très précieuse. Je suis parvenu à tout faire fonctionner, j’ai maintenant un plugin qui permet d’ajouter des templates aux widgets D’Elementor.

            Je comprends mes erreurs, je manque de pratique en langage objet, et je fais parfois ce genre d’erreur.

            Pour ce qui est d’utiliser les mêmes fonctions que la classe parente, c’est effectivement, car j’utilise la classe « Skin_Base » d’Elementor pro, du coup il y a des variations.

            Encore merci pour le temps que vous avez consacré à mon problème.

            Bonne continuation.

            Monnier Eric

            1. Super nouvelle, ravie d’avoir pu aider!
              Bonne continuation.

  3. Merci pour ce tuto, ça peux servir !!
    Juste une question, je vois que tu utilise Pastacode pour partager du code source, j’ai télécharger le plugin mais il ne semble pas compatible avec elementor, il y a pas de widget WordPress Pastacode dans les widgets de Elementor, du coup je ne peux pas utiliser Pastacode.

    As-tu une idée pour le rendre compatible ?

    1. Oui j’utilise bien Pastacode, mais pas Elementor 🙂
      Est-ce qu’en insérant un widget « éditeur de texte » avec Elementor tu n’aurais pas l’outil d’insertion Pastacode dans la barre d’outil WYSIWYG ?

  4. Non justement il y a pas de possiblité d’ajouter Pastacode dans l’éditeur de texte Elementor.

    J’ai trouvé un autre moyen, il faut passer par l’éditeur de texte de WordPress, mais pas pratique et pas très fonctionnel, l’idéal reste un widget directement dans elementor ou ajouter pastacode dans l’outil WYSIWYG, mais pas très simple pour moi.

    ps: (on ne reçoit pas de notification par email quand une autre réponse est apportée sur ton blog, pas pratique)

  5. Bonsoir Marie, je travaille actuellement sur elementor pro Version 2.4.5 (bien que je sois débutante sur ce builder) avec wordpress 5.0.3, j’y ai injecté votre plugin sans souci.
    Seulement, je ne parviens pas à mettre le bouton en fixe malgré diverse manipulation du sticky. Pouvez-vous m’aider svp?
    Lorsque je scrolle, le bouton il disparaît avec le reste de ma section.

    1. Bonjour Fanny,
      je viens de faire un test ici https://mariecomet.fr/elementor-1659/ et cela fonctionne bien avec Elementor Pro en 2.4.5.
      Il se peut que vous ayez un conflit avec votre thème ou une extension.
      Votre site est en ligne ? Pouvez-vous poster l’URL?

  6. Bonjour,
    Merci pour ce tuto Marie 🙂
    Cependant j’ai découvert un plugin excellent qui pourrait intéresser certains en rapport justement avec les Widgets d’Elementor.
    Le plugin permet de créer ses propres Widgets (il faut quand même une connaissance de base en HTML/CSS ou même JS pour faire des chose plus poussé, après ça dépends de ce que l’ont souhaite faire).
    Il y a pas mal de Widgets déjà prêt en gratuit et encore plus en payant mais je vous conseil de le découvrir…
    Voici le lien vers le plugin: http://bit.ly/unlimited-elements-for-elementor

    Bonne construction 🙂
    Sam

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.

ipsum mi, quis Aenean sit mattis fringilla ut Donec