问题描述

首先,我想澄清一下 – 这不是一个 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 辅助翻译的英文资料结果。如果您对结果不满意,可以加入我们改善翻译效果:薇晓朵技术论坛。