问题描述
首先,我想澄清一下 – 这不是一个 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 -> Widgets
和 Customizer -> 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 toyes
, 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, inwp-admin -> widgets
the change will show after yousave
the changes. Of course you can change this behaviour by modifying the CODE (in JavaScript) to do the heading change for a differentfield_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 辅助翻译的英文资料结果。如果您对结果不满意,可以加入我们改善翻译效果:薇晓朵技术论坛。