1

UPDATE Refrased the question

On the backend widget page widgets.php, there is a list of available widgets. Items in this list have the same classes and a dynamically generated ID, which changes if a new widget is inserted (alphabetically) into the list. So, there is no reliable way to direct css at individual items in the list.

Is there another way to style individual items in the widget list?

Old, more narrow question

I have a theme which includes a font icon in its full name. It's defined globally like this:

$theme_data      = wp_get_theme(); // Retrieves the theme data from style.css
$theme_name      = $theme_data['Name'];
$theme_icon      = '<i class="fa fa-wrench" style="font-family:FontAwesome;"></i>';
$theme_full_name = $theme_icon . ' ' . $theme_name;

I can use $theme_full_name in menus, page titles and so on. There's one exception, however. The theme includes two widgets, which also have $theme_full_name in their name (the second parameter in the constructor). On the widgets.php page in the admin only the theme name appears. Apparently the icon is stripped away (as is, presumably, all html that might be in the widget name).

Is there a way to retain the font icon in the widget name?

4
+100

Just as @MarkKaplun mentioned in a comment, it's possible with CSS. Also with Javascript.

CSS Approach

Let's look at the Calendar widget, as an example.

The id for the widget, in the available widgets list, is of the form:

widget-{integer}_calendar-__i__

and in the sidebar it's:

widget-{integer}_calendar-{integer}

If we want to display the calendar dashicon before the widget title, then we can e.g. enqueue a custom stylesheet for the widgets.php file, with something like:

div[id*="_calendar-"].widget .widget-title h3:before{ 
    content: "\f145"; font-family: dashicons; margin-right: 0.5rem; 
}

Here we use *= to find a substring match within the id selector.

It will display like this:

calendar

If needed we could restrict this further to the right or left parts:

#widgets-right
#widgets-left

or the available widgets:

#available-widgets

The widgets.php page will also have body.widgets-php if needed for general stylesheets.

  • Smart! I hadn't thought of css-selectors in this way. Downside of the css approach is that it only works if your font icon is the first or last character in your name, not if it is halfway as in "Hello [cat icon] Kitty". But that could probably be done with jquery. – cjbj Nov 1 '16 at 10:08
  • Javascript would be better to split the title text with an icon, as you say. ps: Here I assumed a ltr language, so we might also want to adjust to rtl with body.rtl. Now I wonder if widget icons should be a core feature ;-) @cjbj – birgire Nov 1 '16 at 10:40
-1

Indeed, all html is stripped from the widget name in the backend by this line (WP 4.6) in the wp_widget_control function:

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

Now, there is no apparent way to intercept strip_tags, because it is a php function, but esc_html is a WP function, that has a filter. So, we cannot prevent the icon/html being stripped, but we can add it back again using the filter. Like this:

add_filter ('esc_html','wpse243718_add_icon_to_widget_name');

function wpse243718_add_icon_to_widget_name ($safe_text) {
    global $theme_icon;
    global $theme_name;
    global $pagenow;
    if ( ($pagenow == 'widgets.php') && (substr($safe_text, 0, strlen($theme_name)) == $theme_name) )
        return $theme_icon  . ' ' . $safe_text;
    else
        return $safe_text;
    }

This code assumes the widget name starts with $theme_name, but you could use other ways of detection as well, of course, or stuff your title with all kinds of html.

  • sorry, but IMHO it is an horrible idea to mess with that filter, double that from doing it from a plugin or theme just to make an icon be seen. Probably can be done in CSS without this kind of risk – Mark Kaplun Oct 24 '16 at 10:27
  • I see your point, but if it could be done with css, I'd have chosen that path. the problem is there are no stable id's or classes to work with. – cjbj Oct 24 '16 at 12:28
  • I am negatively surprised there is a filter at all. Anyway since your code uses globals and it will be hard not to use them, any hacker can add an innocent looking code which sets the globals and bypass the escaping to add his own evil JS – Mark Kaplun Oct 24 '16 at 12:37
  • Yup. Any hacker who gets as far as being able to manipulate globals can get his fingers on this filter anyway. (I was also quite surprised to find it, be assured that I fiddled with it and was up for more surprises where I could dump html and js in my admin interface). – cjbj Oct 24 '16 at 13:44
  • The globals are not necessary, by the way. I could also use functions to retrieve icon and name from the options table. But that doesn't change the weakness. – cjbj Oct 24 '16 at 13:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.