問題描述

首先,我想澄清一下 – 這不是一個 CSS 問題。

在 wp-admin,邊欄或頁面構建器中處於關閉/開啟模式時,我想更改顯示該小工具的資料。這是一個更好的解釋的形象。

我想要能夠動態地新增東西/從 widget 的標題中刪除,並使用 widget $ instance 這樣做

所需的結果:新增一個說明移動/桌面/兩者的小資訊標籤 – 這是特定小工具內的選項

想法嗎?

更新由於我在這個問題的解決方案中看到一些 intrest:@cjbj 解決方案精美地工作,只能在側邊欄中,只有部分:

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

但是.. 你不能在該字串中插入任何 html(或至少我 cannt)

如果我找到一個工作的解決方案將更新。

最佳解決方案

背景:

dynamic_sidebar_params 不能使用 HTML 進行過濾的原因是因為 WordPress 從 wp_widget_control()中的 Widget 標題中剝離 HTML,功能如下:

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

WordPress 還在 wp-admin/js/widgets.js 中預設使用 HTML

所以沒有一個定製的解決方案,沒有預設的過濾器或選項與 PHP 或 JavaScript 來實現你想要的。

自定義 PHP 解決方案:

一個自定義 PHP 解決方案是可行的,只能在 wp-admin -> Appearance -> Widgets 中使用,但不能在 Customizer -> Widgets 中使用。

WordPress 使用 dynamic_sidebar_params 鉤子新增 wp_widget_control()函式 (生成小工具控制元件 UI),因此可以使用此過濾器鉤子覆蓋它。但是,在定製程式中,WordPress 直接呼叫 wp_widget_control()功能,因此此解決方案將無法為定製程式生效。

該解決方案的工作原理如下 (在自定義外掛中新增此程式碼):

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 
} 

正如我之前所說,這個解決方案對於定製程式不起作用,更有可能需要將來的更新,因為我們覆蓋核心功能。

自定義 JavaScript 解決方案 (推薦):

幸運的是,可以使用 JavaScript 自定義此行為。 WordPress 更新 Widget 控制標題 JavaScript 。要做到這一點 WordPress 保留一個佔位符 in-widget-title CSS 類,並使用小工具 title 欄位值從 JavaScript 程式碼更新。我們可以操縱這個來實現我們的目標。

相關的核心 JS 檔案:

首先,您需要知道 WordPress 在 wp-admin 中載入 wp-admin /js /customize-widgets.js 檔案 (使用 customize-widgets 控制程式碼) – > 自定義 – > wp-admin 中的 Widgets(定製程式) 和 wp-admin /js /widgets.js 檔案 (帶有 admin-widgets 控制程式碼) – > 外觀 – > 控制視窗小工具控制元件 UI 。這兩個檔案對 Widget UI 標記和 Widget 標題 UI 操作進行類似的操作,但也有很多不同的事情。所以我們需要考慮到我們基於 JavaScript 的解決方案。

定製器的注意事項:

定製器在頁面載入後立即不載入 Widget UI 標記,而是在相應的 Widgets -> Sidebar 面板開啟時載入 JavaScript 。所以我們需要在 WordPress 載入後操作 Widget UI 。例如,由於定製程式 CODE 是基於事件的,所以我使用以下程式碼行將事件處理程序設定在正確的時刻:

section.expanded.bind( onExpanded );

此外,定製程式使用 AJAX 立即載入更改,這就是為什麼我已經使用以下行來瀏覽資料更改:

control.setting.bind( updateTitle );

此外,我需要使用以下程式碼行進入 widget-added 事件:

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

普通使用者 wp-admin -> Appearance -> Widgets

當更新小工具時,上述 JavaScript 檔案都會觸發 widget-updated 事件。儘管自定義程式立即使用 AJAX,但傳統的 Widget 管理員在您點選 Save 按鈕後即可執行此操作。我使用以下程式碼行程式碼:

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

wp-admin -> Appearance -> Widgets 的注意事項:

與定製器相反,傳統的 Widgets 管理員用 PHP 載入 Widget 控制介面,所以我已經遍歷了 UI HTML,進行如下初始更改:

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

自定義外掛程式碼:

以下是一個完整的基於 JavaScript 的解決方案外掛,可以在 wp-admin -> Appearance -> WidgetsCustomizer -> Widgets 中使用:

wpse-widget-control.php 外掛 PHP 檔案:

<?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 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 );

外掛用法:

Note: With the above sample Plugin CODE as it is, if you set the title of a Widget to yes, then it’ll show (mobile/desktop) within the Widget Control UI heading, all the other Widget’s will have (desktop only) in the Heading. In the customizer the change will be immediate, in wp-admin -> widgets the change will show after you save the changes. Of course you can change this behaviour by modifying the CODE (in JavaScript) to do the heading change for a different field_name or to only show that specific heading to some widgets and not to all of them.

例如,假設您有一個名為 use_mobile 的欄位,並且要將標題設定為 (移動/桌面) 時設定為 yes 。然後將 compare 變數設定為:

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

此外,如果要更改整個標題 (而不僅僅是.in-widget-title),那麼您可以更改 heading_selector 設定以及 heading& alt_heading 這樣做。可能性是無止境的,但是如果您想要對結果標記產生太多的創意,請確保 WordPress 核心程式碼不會產生任何錯誤。

頁面構建器整合:

這些解決方案是否適用於頁面構建器將取決於該頁面構建器實現。如果它使用 WordPress 提供的方法來載入 Widget Control UI,那麼它應該沒有任何修改,否則類似 (但修改) 的含義也可能是頁面構建器。

次佳解決方案

首先看看是否可以更改管理員中小工具標題中顯示的資訊。該列表由 wp_list_widget_controls 生成,wp_list_widget_controls 呼叫 dynamic_sidebar,其中包含一個過濾器 dynamic_sidebar_params 來更改控制元件中的引數,包括標題。我們來試試:

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

$string 不完全在你所指的地方,但我會說這是足夠好的。

現在,我們需要用 $string 替換當前小工具內部的一些資訊。幸運的是,我們知道我們在哪個小工具,因為 $params 還包含 widget_id 。我將 refer to this answer 解釋如何使用 widget_id 來檢索視窗小工具資料。開始了:

 // 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];

現在,陣列 $data 包含視窗小工具的例項,您可以選擇要傳遞給 $string 的函式。

參考文獻

注:本文內容整合自 Google/Baidu/Bing 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。