Make WordPress Core

Opened 14 years ago

Closed 10 years ago

#11387 closed enhancement (wontfix)

Walker Widget System

Reported by: shanef's profile ShaneF Owned by: shanef's profile ShaneF
Milestone: Priority: normal
Severity: normal Version:
Component: Widgets Keywords: has-patch
Focuses: Cc:

Description

This is a new system for Widgets. The design for this system is based on the fact that every theme is different.

Currently the widget system does not care about one theme. It will still output it's own formating structure based on it's design and then bassed on a messy 'register_sidebar' arguments wrap that data inside one another.

The idea behind a Walker Widget system is that instead of the Widget outputing the data, it send it to a Walker where it assigns the relevant information and the theme's "Widget Design" class holds how Widget boxes are created based on the values pushed through the walker.

For example in my theme functions.php file:

class Walker_Widget_Rabbit extends Walker_Widget {

	function start_widget($args, &$output) {
		
		// @todo Updated with the correct vars.
		$output .= do_action('sidebar_before_module', $id);
		$output .= do_action('sidebar_before_module_' . $id);
		
		$output .= sprintf( "<div id='%s' class='module widget %s'>", $args['widget_id'], $args['classname'] );
	}
	
	function title_widget($args, &$output) {
		$output .= "<div class='head'><h3>" . $args['title'] . "</h3></div>";
		/*
		if ((bool) $this->get_option('scrolling') && $scroll['enabled']) { 
			printf(__("navi: <a id=\"prev_%s\">prev</a>&nbsp;/&nbsp;<a id=\"next_%s\">next</a>"), $scroll['key'], $scroll['key']);
		} 
		*/
	}

	function content_widget($args, &$output) {
		$output .= "<div class='wrap'>" . $this->content_style($args, $args['output']) . "</div>";
	}

	function content_style($args, $output) {
		
		/*
		 * Here I am going to figure out how we are going to wrap most content
		 * and detirme if the information is scrolled information.
		 */

		$style = $args['style'];
		switch ($style) {
			case 'none': 
				$style = $output; 
				break;
			default: 
				$style = "<ul class='dash-strip'>" . $output . "</ul>";
		}
		return $style;
	}
	
	function content_scroll($args, $area = 'top') {
		//	@todo <div class="content-scroll-large"> and <div class="content-scroll">
	}
	
	function end_widget($args, &$output) {
		$output .= "</div>";
		// @todo Updated with the correct vars.
		$output .= do_action('sidebar_after_module', $id);
		$output .= do_action('sidebar_after_module_' . $id);
	}
	
}

This also allows users to manipulate the data/design even further once they get it from the widget.

I have tested this on the default theme of WordPress with the all 12 of the built in WordPress widgets and they act/look just like if it was hardcoded into the system itself.

Attachments (3)

walker_widget.patch (34.8 KB) - added by ShaneF 14 years ago.
walker_widget.2.patch (38.8 KB) - added by ShaneF 14 years ago.
cleaned up the walker a bit. removed some stuff from the default theme files, still working on update the archives widget with more options as well.
walker_widget.3.patch (42.5 KB) - added by ShaneF 14 years ago.

Download all attachments as: .zip

Change History (27)

#1 @hakre
14 years ago

Maybe this problem can be moved into the CSS domain? Would save us PHP code and another layer of logic on the widgets.

How can a theme provide such a "widget theme" that is applied on widgets then?

#2 @ShaneF
14 years ago

The code I have in my functions to use my Widget class is:

add_filter('widget_design', array(&$this,'widget_design'), 1, 1	);
function widget_design() {
return new Walker_Widget_Rabbit;
}

#3 @ShaneF
14 years ago

This is all I do to register the sidebars:

if ( function_exists('register_sidebar') ) {
	register_sidebar( array(
		'id'	=> 'top-sidebar',
		'name'	=>	__("Top Sidebar"),
		'description'	=>	__("This sidebar will always be shown, no matter what page.")
		)
	);
	register_sidebar( array(
		'id'	=> 'primary-sidebar',
		'name'	=>	__("Primary Sidebar"),
		'description'	=>	__("Sidebar for Posts and Pages")
		)
	);
	register_sidebar( array(
		'id'	=> 'project-sidebar',
		'name'	=>	__("Project Sidebar"),
		'description'	=>	__("Sidebar for Project Page Only")
		)
	);
	register_sidebar( array(
		'id'	=> 'archive-sidebar',
		'name'	=>	__("Archive Sidebar"),
		'description'	=>	__("Sidebar for Archives Page Only")
		)
	);
}

This makes it very clean and you don't have to worry about hardcoding the CSS/Design into this function.

@ShaneF
14 years ago

cleaned up the walker a bit. removed some stuff from the default theme files, still working on update the archives widget with more options as well.

#4 @ShaneF
14 years ago

  • Owner changed from azaozz to ShaneF
  • Status changed from new to accepted

#5 follow-up: @Denis-de-Bernardy
14 years ago

*please* no more changes to the widgets API. :-(

#6 in reply to: ↑ 5 ; follow-up: @ShaneF
14 years ago

Replying to Denis-de-Bernardy:

*please* no more changes to the widgets API. :-(

Not as bad as you think. Wouldn't you rather have something that makes Widgets look the same versus having to really manipulate the output to get the look you wanted?

#7 in reply to: ↑ 6 @Denis-de-Bernardy
14 years ago

Replying to ShaneF:

Replying to Denis-de-Bernardy:

*please* no more changes to the widgets API. :-(

Not as bad as you think. Wouldn't you rather have something that makes Widgets look the same versus having to really manipulate the output to get the look you wanted?

I dunno. I like the idea of being able to override the silly lack of div tag around a widget's content.

However, I'm worried that your suggested code would break my themes, and each and every one of the widget plugins I maintain. It doesn't look like it will, but I'm dreading another round of WP 2.8-like maintenance.

It would also mean that some widgets will behave/style differently from others. And that can get *very* messy. I'm foreseeing plenty of support requests along the lines of "why is this widget not getting styled"?

#8 @ShaneF
14 years ago

In this new version I made it even easier:

		$widget_design = new Widget_Basic;
		$widget_array = array(
			'title'			=> $title,
			'before_output'	=> "<div class='textwidget'>",
			'output'		=> $instance['filter'] ? wpautop($text) : $text,
			'after_output'	=> "</div>",
			'style'			=> "none",
			'design'		=> $widget_design
		);
		return array_merge($args, $widget_array);

Inside the WP_Widget class I added a new function called 'design_widget':

	/** Generate the actual widget with design API.
	 *	Do NOT over-ride this function. */
	function design_widget ( $args ) {
		// checking to see if the widget is going to be creating more than one module.
		if ( is_array($args[0]) ) {
			foreach ($args as $widget) {
				if ( empty($widget['design']) )
					$widget['design'] = new Widget_Basic;
				$widget_design = apply_filters('widget_design', $widget['design']);
				echo call_user_func_array( array(&$widget_design, 'display'), array($widget) );
			}
		} else {
			if ( empty($args['design']) )
				$args['design'] = new Widget_Basic;
			$widget_design = apply_filters('widget_design', $args['design']);
			echo call_user_func_array( array(&$widget_design, 'display'), array($args) );
		}
	}

This way less for the widget author to convert. Everyday I come up with a new version of the API. Code sits in my brain during the night and process.

#9 @ShaneF
14 years ago

Just FYI... I did update the default widget 'WP_Widget_Archives', 'WP_Widget_Pages', and 'WP_Widget_Categories'. The latter two to use custom walker's. The Archives one I added and option to allow the different display types. If anyone can get the dropdown to work correctly after a update/save of the data -- I will <3 you forever. :)

#10 @ShaneF
14 years ago

  • Keywords has-patch needs-testing reporter-feedback dev-feedback needs-docs added

Added keywords. :)

#11 @aaroncampbell
14 years ago

  • Cc aaron@… added

#12 @hakre
14 years ago

I'm against enlarging the widget API. Instead of offering another layer of markup modification routines, the exiting widgets API should be better documented and guidelines for the output should be written. A themer can pretty much modify how widgets look right now in themes by using a technique called CSS - Cascading Style Sheets. CSS works very well and in the WP domain stylesheets save the day a lot for the lack of a fairly seperated view - even if wordpress has themes, parts of the html output are produced not within them which can lead to problems this tickets reporter is talking about.

#13 follow-up: @ShaneF
14 years ago

  • Cc ShaneF added

It's not the theme author that I am worried about.

Lets say the plugin author uses a CSS file for displaying their output, Combined that with a theme authors css, you could get some very messy look if it's a widget.

If a theme author was able to control how widgets are created and use the data that the widget author provides, the output could be presented in a correct way without having to hack the css. We are trying to minimize how much blog admins, plugin authors, and theme authors have to modify the output to be exactly on what they want.

This system eliminates that need.

1) Plugin author provides a blueprint. By default (wordpress theme) has works correctly.
2) Theme author can provide that class if they want to override the theme. Not only that, they can then get really gritty and do even more modification inside their class.
3) WordPress users all they have to do is install widgets that they want.

#14 @aaroncampbell
14 years ago

I'm the author of the Twitter Widget Pro plugin, and the way I handle styling is simply to add CSS classes to everything and supply no styling at all. It seems that 99% of the time the user drops that into their theme and it works just fine, automatically using the styles that the theme has set up.

The main thing I run up against is theme authors that have forgot to style a header link (something like <h4><a href="...">Some Text</a></h4>) in the sidebar. No default widgets use this, so sometimes a theme author doesn't think about it and the title of my widget will be a different color or size than the others. Other than that, it really works fine.

#15 @ShaneF
14 years ago

  • Milestone changed from 3.0 to Future Release

Some of the code in this patch is dup in: #11842

Moved milestone to 3.1.

#16 @ShaneF
14 years ago

  • Milestone changed from Future Release to 3.1

Moved to 3.1 milstone.

#17 in reply to: ↑ 13 @scribu
14 years ago

Replying to ShaneF:

Lets say the plugin author uses a CSS file for displaying their output, Combined that with a theme authors css, you could get some very messy look if it's a widget.

I don't see how it would look extra messy simply because it's a widget.


If a theme author was able to control how widgets are created and use the data that the widget author provides, the output could be presented in a correct way without having to hack the css.

It seems to me that the problem here is allowing theme authors to elegantly override the default CSS provided by a plugin, rather than the widget markup.


1) Plugin author provides a blueprint. By default (wordpress theme) has works correctly.

2) Theme author can provide that class if they want to override the theme. Not only that, they can then get really gritty and do even more modification inside their class.

3) WordPress users all they have to do is install widgets that they want.

If a theme author doesn't like the output of a particular widget, he can extend that widget's class and override the widget() method. There already are several themes that do this.


I can't envision any common usecase that would require this system. Perhaps you can provide one.

#18 @scribu
14 years ago

  • Milestone changed from 3.1 to Future Release

#19 @sirzooro
14 years ago

  • Cc sirzooro added

#20 @ShaneF
14 years ago

I gave a great example last night during my Genius bar on why this is a good idea. I'll recap what I said after I put it down into a better format.

#21 @voyagerfan5761
14 years ago

  • Cc WordPress@… added

#22 @ptahdunbar
14 years ago

  • Cc trac@… added

#23 @ocean90
13 years ago

  • Keywords reporter-feedback removed

#24 @kpdesign
10 years ago

  • Keywords needs-testing dev-feedback needs-docs removed
  • Milestone Future Release deleted
  • Resolution set to wontfix
  • Status changed from accepted to closed

No activity on this for 3 years, closing.

Note: See TracTickets for help on using tickets.