Add class to before_widget for all widgets with a dropdown and a counter

Some predefined widgets offer the option to use a select element (dropdown) and/or a counter after each entry. How can I add the CSS classes widget-with-dropdown or widget-with-counters to these widgets?

There are already solutions for custom widgets, known sidebar ids or positions, but I have to inspect the parameters for the current instance, and I want to catch all possible positions or widgets (if they follow the WordPress naming scheme).

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

The CSS classes are applied in the function dynamic_sidebar(). There is no specific filter for that:

// Substitute HTML id and class attributes into before_widget
$classname_ = '';
foreach ( (array) $wp_registered_widgets[$id]['classname'] as $cn ) {
    if ( is_string($cn) )
        $classname_ .= '_' . $cn;
    elseif ( is_object($cn) )
        $classname_ .= '_' . get_class($cn);
}
$classname_ = ltrim($classname_, '_');
$params[0]['before_widget'] = sprintf($params[0]['before_widget'], $id, $classname_);

But there is a filter for $params right after this code block:

$params = apply_filters( 'dynamic_sidebar_params', $params );

To get the settings for the current widget, we have to search in the global variable $wp_registered_widgets for an entry with the key $params[ 0 ][ 'widget_id' ].
If it exists, it has a class instance as callback, and we can use that object’s method get_settings() to … well … get the settings.
The returned array has probably a key that equals $params[1][ 'number' ].
Associated with this key is an array again, and here we might find another key dropdown (or count) with a value of 0 or 1.
If it is 1, we add the new classes to the string in $params[0]['before_widget'].

I think this easier to read as code:

is_admin() || add_filter( 'dynamic_sidebar_params', 'wpse_widget_classes' );

/**
 * Add classes for widgets with counters or dropdowns.
 *
 * @param  array $params
 * @return array
 */
function wpse_widget_classes( $params ) {

    global $wp_registered_widgets;

    $classes     = array();
    $instance_id = $params[1][ 'number' ];
    $widget_id   = $params[ 0 ][ 'widget_id' ];
    $settings    = $wp_registered_widgets[ $widget_id ][ 'callback' ][ 0 ]->get_settings();

    if ( empty ( $settings[ $instance_id ] ) )
        return $params;

    if ( ! empty ( $settings[ $instance_id ][ 'dropdown' ] ) )
        $classes[] = 'widget-with-dropdown';

    if ( ! empty ( $settings[ $instance_id ][ 'count' ] ) )
        $classes[] = 'widget-with-counters';

    if ( empty ( $classes ) )
        return $params;

    $params[0]['before_widget'] = str_replace(
        'class="',
        'class="' . join( ' ', $classes ) . ' ',
        $params[0]['before_widget']
    );

    return $params;
}

Method 2

Or, you can just use a plugin:

Both plugins are doing pretty much the same as @toscho showed in his answer.

Widget CSS Classes plugin

$this_id    = $params[0]['id']; // Get the id for the current sidebar we're processing
$widget_id  = $params[0]['widget_id'];
$widget_obj = $wp_registered_widgets[$widget_id];
$widget_num = $widget_obj['params'][0]['number'];

Source link to v1.2.1

Custom Widget Classes plugin

global $wp_registered_widgets;
$widget_id    = $params[0]['widget_id'];
$widget_obj    = $wp_registered_widgets[$widget_id];
$widget_opt    = get_option($widget_obj['callback'][0]->option_name);
$widget_num    = $widget_obj['params'][0]['number'];

Source link to v1.1

Just to prove that @toscho is right and there seems to be no other option to go on this.

Method 3

first add a custom placeholder class in the constructor

<?php
public function __construct() {
   $widget_ops  = array(
      'classname'                   =>; 'widget_text eaa __eaa__', //__eaa__ is my placeholder css class
      'description'                 =>; __( 'AdSense ads, arbitrary text, HTML or JS.','eaa' ),
      'customize_selective_refresh' =>; true,
   );
   $control_ops = array( 'width' =>; 400, 'height' =>; 350 );
   parent::__construct( 'eaa', __( 'Easy AdSense Ads &amp; Scripts', 'eaa' ), $widget_ops, $control_ops );
}
?>

Then replace it with the class/es of your choice based on the widget options like this

<?php
if ( $instance['no_padding'] ) {
   $args['before_widget'] = str_replace( '__eaa__', 'eaa-clean', $args['before_widget'] );
}
?>

We are using the place holder to limit the ways in which the html of before_widget may affect our plugin functionality

You can find the details with example at
http://satishgandham.com/2017/03/adding-dynamic-classes-custom-wordpress-widgets/


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x