web-dev-qa-db-fra.com

Comment influencer les informations affichées sur le widget dans wp-admin

Premièrement, je veux clarifier - ce n’est pas une question CSS.

Je souhaite modifier les données affichées du widget en mode fermé/ouvert dans l'admin wp-admin, dans une barre latérale ou un générateur de page. Voici une image à mieux expliquer.

 enter image description here 

Je veux pouvoir ajouter quelque chose/supprimer du titre du widget de manière dynamique et utiliser le widget $ instance pour le faire

Le résultat souhaité:
Ajouter une petite étiquette d’information indiquant mobile/desktop/les deux - option choisie dans le widget spécifique.

Des idées n'importe qui?

METTRE À JOUR
Depuis que je vois quelque intrest dans une solution à cette question:
@ cjbj solution fonctionne à merveille mais uniquement dans l'encadré et seulement partiellement:

add_filter ('dynamic_sidebar_params','wpse261042_change_widget_title');
function wpse261042_change_widget_title ($params) {

    $widget_id          = $params[0]['widget_id'];
    $widget_instance    = strrchr ($widget_id, '-');
    $wlen               = strlen ($widget_id);
    $ilen               = strlen ($widget_instance);
    $widget_name        = substr ($widget_id,0,$wlen-$ilen);
    $widget_instance    = substr ($widget_instance,1);

    // get the data
    $widget_instances   = get_option('widget_' . $widget_name);
    $data               = $widget_instances[$widget_instance];
    $use_mobile         = $data['use_mobile'];  // option inside my widget

    if($use_mobile == 'yes') {$string = 'desktop / mobile';} else {$string = 'desktop only';}

    $params[0]['widget_name'] .= $string;
    return $params;
}

Cependant .. vous ne pouvez pas insérer de code HTML dans cette chaîne (ou au moins je ne pourrais pas)

Mettrait à jour si je trouve une solution de travail.

6
Sagive SEO

Contexte:

La raison pour laquelle le filtrage avec dynamic_sidebar_params ne fonctionne pas avec HTMLest que WordPress supprime HTMLde l'en-tête du widget dans wp_widget_control() fonctionne comme suit:

$widget_title = esc_html( strip_tags( $sidebar_args['widget_name'] ) );

WordPress supprime également HTMLdans JavaScript par défaut dans wp-admin/js/widgets.js

Donc, sans solution personnalisée, il n'y a pas de filtre ou d'option par défaut, ni avec PHP ni avec JavaScript pour obtenir ce que vous voulez.

Personnalisation PHP Solution:

Une solution personnalisée PHP est possible et ne fonctionnera que dans wp-admin -> Appearance -> Widgets, mais pas dans Customizer -> Widgets.

WordPress ajoute fonction wp_widget_control() (qui génère une interface utilisateur de contrôle de widget) avec un hook dynamic_sidebar_params; il est donc possible de le remplacer à l'aide de ce hook de filtre. Toutefois, dans le programme de personnalisation, WordPress appelle directement fonction wp_widget_control() , cette solution ne fonctionnera donc pas pour le programme de personnalisation.

La solution fonctionne comme suit (ajoutez ce code dans un plugin personnalisé):

add_filter( 'dynamic_sidebar_params', 'wpse261042_list_widget_controls_dynamic_sidebar', 20 );
function wpse261042_list_widget_controls_dynamic_sidebar( $params ) {
    global $wp_registered_widgets;
    // we only want this in wp-admin (may need different check to enable page builder)
    if( is_admin() ) {
        if ( is_array( $params ) && is_array( $params[0] ) && $params[0]['id'] !== 'wp_inactive_widgets' ) {
            $widget_id = $params[0]['widget_id'];
            if ( $wp_registered_widgets[$widget_id]['callback'] ===  'wp_widget_control' ) {
                // here we are replacing wp_widget_control() function 
                // with our custom wpse261042_widget_control() function
                $wp_registered_widgets[$widget_id]['callback'] = 'wpse261042_widget_control';
            }
        }
    }
    return $params;
}

function wpse261042_widget_control( $sidebar_args ) {
    // here copy everything from the core wp_widget_control() function
    // and change only the part related to heading as you need 
} 

Comme je l'ai déjà dit, cette solution ne fonctionne pas pour le personnalisateur et a plus de chances de nécessiter de futures mises à jour car nous remplaçons une fonction principale.

Solution JavaScript personnalisée (recommandée):

Heureusement, il est possible de personnaliser ce comportement avec JavaScript. WordPress met quand même à jour le cap du contrôle de widget avec JavaScript. Pour ce faire, WordPress conserve une classe CSS in-widget-title et remplace celle-ci avec la valeur du champ widget titleà partir de JavaScript CODE. Nous pouvons manipuler cela pour atteindre notre objectif.

Fichiers Core JS associés:

Vous devez d’abord savoir que WordPress charge wp-admin/js/customize-widgets.js fichier (avec customize-widgets handle) dans wp-admin -> Customize -> Widgets (personnalisateur) et wp-admin/js/widgets.js fichier (avec admin-widgets handle) dans wp-admin -> Appearance -> Widgets pour manipuler l’UI de contrôle de widget. Ces deux fichiers effectuent des opérations similaires pour les annotations d'interface utilisateur de widget et la manipulation d'interface utilisateur d'en-tête de widget, mais également dans de nombreux domaines différents. Nous devons donc en tenir compte pour notre solution basée sur JavaScript.

Considérations pour le personnaliseur:

Le personnaliseur ne charge pas le balisage de l'interface utilisateur du widget immédiatement après le chargement de la page. Il se charge plutôt avec JavaScript lorsque le panneau Widgets -> Sidebar correspondant est ouvert. Nous devons donc manipuler l'interface utilisateur du widget après le chargement de WordPress. Par exemple, comme le personnalisateur CODE est basé sur les événements, j'ai utilisé la ligne suivante de CODE pour définir le gestionnaire d'événements au bon moment:

section.expanded.bind( onExpanded );

En outre, le personnalisateur a utilisé AJAX pour charger les modifications immédiatement. C'est pourquoi j'ai utilisé la ligne suivante pour puiser dans la modification des données:

control.setting.bind( updateTitle );

De plus, je devais faire appel à l'événement widget-added avec la ligne suivante de CODE:

$( document ).on( 'widget-added', add_widget );

Commun pour Customizer & wp-admin -> Appearance -> Widgets:

Les deux fichiers JavaScript mentionnés ci-dessus déclenchent l'événement widget-updated lors de la mise à jour d'un widget. Bien que le personnalisateur le fasse immédiatement avec AJAX, alors que l’administrateur Widgettraditionnel le fait après avoir cliqué sur Save bouton. J'ai utilisé la ligne suivante de CODE pour cela:

$( document ).on( 'widget-updated', modify_widget );

Considérations pour wp-admin -> Appearance -> Widgets:

Contrairement à l'outil de personnalisation, l'administrateur Widgetstraditionnel charge l'interface utilisateur du contrôle des widgets avec PHP. J'ai donc parcouru le code HTML de l'interface utilisateur pour apporter les modifications initiales suivantes:

$( '#widgets-right div.widgets-sortables div.widget' ).each( function() { // code } ); 

Custom Plugin CODE:

Voici un plugin complet avec une solution basée sur JavaScript qui fonctionnera à la fois dans wp-admin -> Appearance -> Widgets et Customizer -> Widgets:

wpse-widget-control.php Plugin PHP fichier:

<?php
/**
 *  Plugin Name: Widget Control
 *  Plugin URI: https://wordpress.stackexchange.com/questions/261042/how-to-influence-the-information-displayed-on-widget-inside-wp-admin
 *  Description: Display additional info on Widget Heading in wp-admin & customizer using JS
 *  Author: Fayaz
 *  Version: 1.0
 *  Author URI: http://fmy.me/
 */

    if( is_admin() ) {
        add_action( 'current_screen', 'wpse261042_widget_screen' );
    }

    function wpse261042_widget_screen() {
        $currentScreen = get_current_screen();
        if( $currentScreen->id === 'customize' ) {
            add_action( 'customize_controls_enqueue_scripts', 'wpse261042_customizer_widgets', 99 );
        }
        else if( $currentScreen->id === 'widgets' ) {
            add_action( 'admin_enqueue_scripts', 'wpse261042_admin_widgets', 99 );
        }
    }

    function wpse261042_customizer_widgets() {
        wp_enqueue_script( 'custom-widget-heading', plugin_dir_url( __FILE__ ) . 'custom-widget-heading.js', array( 'jquery', 'customize-widgets' ) );
    }

    function wpse261042_admin_widgets() {
        wp_enqueue_script( 'custom-widget-heading', plugin_dir_url( __FILE__ ) . 'custom-widget-heading.js', array( 'jquery', 'admin-widgets' ) );
    }

custom-widget-heading.js fichier JavaScript:

(function( wp, $ ) {
    var compare = {
        // field to compare
        field: 'title',
        // value to be compared with
        value: 'yes',
        // heading if compare.value matches with compare.field value
        heading: ' <i>(mobile/desktop)</i> ',
        // alternate heading
        alt_heading: ' <i>(desktop only)</i> ',
        // WP adds <span class="in-widget-title"></span> in each widget heading by default
        heading_selector: '.in-widget-title'
    };

    var widgetIdSelector = '> .widget-inside > form > .widget-id';
    // heading is added as prefix of already existing heading, modify this as needed
    function modify_heading( $Elm, isMain ) {
        var html = $Elm.html();
        if ( html.indexOf( compare.heading ) == -1 && html.indexOf( compare.alt_heading ) == -1 ) {
            if( isMain ) {
                $Elm.html( compare.heading + html );
            }
            else {
                $Elm.html( compare.alt_heading + html );
            }
        }
    };
    function parseFieldSelector( widgetId ) {
        return 'input[name="' + widgetIdToFieldPrefix( widgetId ) + '[' + compare.field + ']"]';
    };

    // @note: change this function if you don't want custom Heading change to appear for all the widgets.
    // If field variable is empty, then that means that field doesn't exist for that widget.
    // So use this logic if you don't want the custom heading manipulation if the field doesn't exist for a widget
    function modify_widget( evt, $widget, content ) {
        var field = null;
        var field_value = '';
        if( content ) {
            field = $( content ).find( parseFieldSelector( $widget.find( widgetIdSelector ).val() ) );
        }
        else {
            field = $widget.find( parseFieldSelector( $widget.find( widgetIdSelector ).val() ) );
        }
        if( field ) {
            field_value = ( ( field.attr( 'type' ) != 'radio' && field.attr( 'type' ) != 'checkbox' )
                          || field.is( ':checked' ) ) ? field.val() : '';
        }
        modify_heading( $widget.find( compare.heading_selector ), field_value == compare.value );
    }

    function parseWidgetId( widgetId ) {
        var matches, parsed = {
            number: null,
            id_base: null
        };
        matches = widgetId.match( /^(.+)-(\d+)$/ );
        if ( matches ) {
            parsed.id_base = matches[1];
            parsed.number = parseInt( matches[2], 10 );
        } else {
            parsed.id_base = widgetId;
        }
        return parsed;
    }
    function widgetIdToSettingId( widgetId ) {
        var parsed = parseWidgetId( widgetId ), settingId;
        settingId = 'widget_' + parsed.id_base;
        if ( parsed.number ) {
            settingId += '[' + parsed.number + ']';
        }
        return settingId;
    }
    function widgetIdToFieldPrefix( widgetId ) {
        var parsed = parseWidgetId( widgetId ), settingId;
        settingId = 'widget-' + parsed.id_base;
        if ( parsed.number ) {
            settingId += '[' + parsed.number + ']';
        }
        return settingId;
    }
    var api = wp.customize;
    if( api ) {
        // We ate in the customizer
        widgetIdSelector = '> .widget-inside > .form > .widget-id';
        api.bind( 'ready', function() {
            function add_widget( evt, $widget ) {
                var control;
                control = api.control( widgetIdToSettingId( $widget.find( widgetIdSelector ).val() ) );

                function updateTitle( evt ) {
                    modify_widget( null, $widget );
                };
                if ( control ) {
                    control.setting.bind( updateTitle );
                }
                updateTitle();
            };
            api.control.each( function ( control ) {
                if( control.id &&  0 === control.id.indexOf( 'widget_' ) ) {
                    api.section( control.section.get(), function( section ) {
                        function onExpanded( isExpanded ) {
                            if ( isExpanded ) {
                                section.expanded.unbind( onExpanded );
                                modify_widget( null, control.container.find( '.widget' ), control.params.widget_content );
                            }
                        };
                        if ( section.expanded() ) {
                            onExpanded( true );
                        } else {
                            section.expanded.bind( onExpanded );
                        }
                    } );
                }
            } );
            $( document ).on( 'widget-added', add_widget );
        } );
    }
    else {
        // We are in wp-admin -> Appearance -> Widgets
        // Use proper condition and CODE if you want to target any page builder
        // that doesn't use WP Core Widget Markup or Core JavaScript
        $( window ).on( 'load', function() {
            $( '#widgets-right div.widgets-sortables div.widget' ).each( function() {
                modify_widget( 'non-customizer', $( this ) );
            } );
            $( document ).on( 'widget-added', modify_widget );
        } );
    }
    $( document ).on( 'widget-updated', modify_widget );
})( window.wp, jQuery );

Utilisation du plugin:

Remarque: Avec l'exemple de code de plugin ci-dessus tel quel, si vous définissez le titled'un widget yesname__, alors il affichera (mobile/desktop) dans l'en-tête de l'interface utilisateur du contrôle de widget, tous les autres widgets auront (desktop uniquement) dans la rubrique. Dans le personnalisateur, les modifications seront immédiates. Dans wp-admin -> widgets, les modifications apparaîtront après que vous aurez modifié savename__. Bien sûr, vous pouvez modifier ce comportement en modifiant le CODE (en JavaScript) afin de modifier le titre pour un field_name différent ou d'afficher uniquement ce titre spécifique pour certains widgets et non pour tous.

Par exemple, supposons que vous ayez un champ nommé use_mobile et que vous souhaitez définir l'en-tête sur (mobile/desktop) lorsqu'il est défini sur yesname__. Puis définissez la variable compareà quelque chose comme:

var compare = {
    field: 'use_mobile',
    value: 'yes',
    heading: ' <i>(mobile/desktop)</i> ',
    alt_heading: ' <i>(desktop only)</i> ',
    heading_selector: '.in-widget-title'
};

De même, si vous souhaitez modifier l'en-tête entier (au lieu de .in-widget-title), vous pouvez modifier le paramètre heading_selector ainsi que le balisage approprié pour heading& alt_heading. Les possibilités sont infinies, mais assurez-vous que WordPress Core CODE ne génère aucune erreur si vous voulez être trop créatif avec le balisage résultant.

Intégration du générateur de page:

Le fait que l'une ou l'autre de ces solutions fonctionne ou non pour un générateur de page dépend de son implémentation. S'il utilise les méthodes fournies par WordPress pour charger l'interface utilisateur de Widget Control, il devrait fonctionner sans aucune modification. Dans le cas contraire, une implication similaire (mais modifiée) pourrait également être possible pour les constructeurs de page.

4
Fayaz

Voyons d'abord s'il est possible de changer les informations affichées dans les titres de widgets dans admin. Cette liste est générée par wp_list_widget_controls , qui appelle dynamic_sidebar , qui contient un filtre dynamic_sidebar_params pour modifier les paramètres des contrôles, y compris le titre. Essayons ça:

add_filter ('dynamic_sidebar_params','wpse261042_change_widget_title');
function wpse261042_change_widget_title ($params) {
  $string = ' Added info';
  $params[0]['widget_name'] .= $string;
  return $params;
  }

Le $string ne se trouve pas exactement à l'endroit où vous vous dirigez, mais je dirais que c'est suffisant.

Maintenant, nous devons remplacer $string par des informations provenant du widget en cours. Heureusement, nous connaissons le widget dans lequel nous nous trouvons, car $params contient également le widget_id. Je vais référez-vous à cette réponse pour une explication de la façon dont vous utilisez le widget_id pour récupérer les données du widget. Et c'est parti:

 // we need to separate the widget name and instance from the id
 $widget_id = $params[0]['widget_id'];
 $widget_instance = strrchr ($widget_id, '-');
 $wlen = strlen ($widget_id);
 $ilen = strlen ($widget_instance);
 $widget_name = substr ($widget_id,0,$wlen-$ilen);
 $widget_instance = substr ($widget_instance,1);
 // get the data
 $widget_instances = get_option('widget_' . $widget_name);
 $data = $widget_instances[$widget_instance];

Maintenant, le tableau $data contient les instances du widget et vous pouvez choisir celle que vous voulez transmettre à $string dans la fonction.

3
cjbj

WordPress a déjà une fonctionnalité similaire intégrée dans l'interface utilisateur des widgets. Voyez par exemple comment la valeur "Titre" saisie par l'utilisateur est ajoutée au titre de ce widget de recherche:

 Search widget with title appended 

Le code qui fait cela se trouve dans wp-admin/js/widgets.js :

appendTitle : function(widget) {
    var title = $('input[id*="-title"]', widget).val() || '';

    if ( title ) {
        title = ': ' + title.replace(/<[^<>]+>/g, '').replace(/</g, '&lt;').replace(/>/g, '&gt;');
    }

    $(widget).children('.widget-top').children('.widget-title').children()
            .children('.in-widget-title').html(title);

},

Il trouve l'élément input dans un widget doté d'un attribut id se terminant par -title et ajoute la valeur entrée dans cette entrée au texte de la barre de titre du widget.

Donc, si le paramètre que vous avez à l’esprit est basé sur un champ input (peu importe si type est text ou radio, etc.), il vous suffit de lui attribuer une id se terminant par -title, et WordPress se chargera du du repos.

Et de cette façon, la chaîne dans la barre de titre sera automatiquement mise à jour lorsque l'utilisateur modifiera le paramètre.

1
J.D.