Adding Stuff To WordPress “Screen Options”

The Screen Options pull-down is the perfect place for those “rarely used but nice to have” settings. It’s unobtrusive and saves screen space. Some plugins could even put all of their settings in this panel and avoid cluttering the Dashboard menu with yet another “Settings” page.

While Screen Options were already present in older WP versions, only the latest 3.0 release finally introduced a sane way to add your own content to this panel – the screen_settings filter. This filter is completely undocumented, so I thought it would be helpful to create a short tutorial on how to use it. Hence this post.

The screen_settings Filter

This screen_settings filter is applied to the additional HTML code that is to be appended to the Screen Options box. The callback function attached to this filter will receive two arguments: the current HTML code and an undocumented “screen object”. This object represents the current Dashboard screen. It has an “id” property which can be used to figure out which page/screen you’re on and only attach your extra HTML to specific pages.

Note that a “screen” is not the same thing as a page or a menu. For example, both the “Add Post” and “Edit Post” pages are considered to be the same screen. Luckily, in most cases you can (ab)use the convert_to_screen function to convert the page slug to a screen object. You can then compare the converted object’s and the current screen’s “id” attributes to check what page your script is executing on.

add_filter('screen_settings', 'screen_options_demo', 10, 2);
function screen_options_demo($current, $screen){
	$desired_screen = convert_to_screen('plugins.php');
	if ( $screen->id == $desired_screen->id ){
		$current .= "Hello WordPress!";
	}
	return $current;
}

The above code will append the line “Hello WordPress!” to the Screen Options box on the Plugins page.

For some pages – e.g. the main Dashboard page and post/page editor – you’ll need to figure out the corresponding screen ID by yourself. See the set_current_screen function in /wp-includes/template.php for clues.

If you specify a page that doesn’t have its own screen options, the Screen Options box will be added automatically and its contents will be set to the HTML code returned by your callback function. You can also compare the screen id against the hook name returned by add_submenu_page and its ilk to display custom screen options on plugin pages.

A More Convenient Form

Personally, I think the screen_settings filter is too low-level for most situations. Do you really want your callback to be executed on each and every admin page, and worry about converting between “pages” and the undocumented “screens”? And then duplicate that code (boo!) in each new plugin where you want to use this WP feature? Also, the extra settings fields added via this filter lack the tasty AJAX autosave feature used by the native screen options fields, which means you’d have to reimplement that as well.

With that in mind, I wrote a wrapper script that handles all that for you. The script has one public function named add_screen_options_panel which makes adding extra screen options panels as easy as adding extra menus. The function takes these arguments :

  • id – the string to use in the ‘id’ attribute of the settings panel. Should be unique.
  • title – Title of your new settings panel. Set to an empty string to omit title.
  • callback – Function that fills the panel with the desired content. Should return a string of HTML.
  • page – The page(s) on which to show the panel.  This can be either a string specifying a single page file name (e.g. “plugins.php”) or the hook name returned by add_submenu_page (e.g. “settings_page_my_plugin”), or an array of page filenames/hook names.
  • save_callback – Optional. The name of the function that will save the settings contained in the panel.
  • autosave – Optional. If set to true, panel contents will be automatically submitted (via AJAX) when the value of any field in the panel changes, and the specified save_callback function will be called with the field values. Defaults to false.

Here’s an example of how this function is used in the latest version of my Raw HTML plugin:

include 'screen-options/screen-options.php';

//Add our panel to the "Screen Options" box
add_screen_options_panel(
	'rawhtml-default-settings',       //Panel ID
	'Raw HTML defaults',              //Panel title. 
	'rawhtml_default_settings_panel', //The function that generates panel contents.
	array('post', 'page'),            //Pages/screens where the panel is displayed. 
	'rawhtml_save_new_defaults',      //The function that gets triggered when settings are submitted/saved.
	true                              //Auto-submit settings (via AJAX) when they change. 
);

/* ...more code here...  */

/**
 * Generate the "Raw HTML defaults" panel for Screen Options.
 * 
 * @return string
 */
function rawhtml_default_settings_panel(){
	$defaults = rawhtml_get_default_settings();
	
	//Output checkboxes 
	$fields = array(
		'disable_wptexturize' => 'Disable wptexturize',
		'disable_wpautop' => 'Disable automatic paragraphs',
		'disable_convert_chars' => 'Disable convert_chars',
		'disable_convert_smilies' => 'Disable smilies',
	 );
	 
 	$output = '';
	foreach($fields as $field => $legend){
		$esc_field = esc_attr($field);
		$output .= sprintf(
			'<label for="rawhtml_default-%s" style="line-height: 20px;">
				<input type="checkbox" name="rawhtml_default-%s" id="rawhtml_default-%s"%s>
				%s
			</label><br>',
			$esc_field,
			$esc_field,
			$esc_field,
			($defaults[$field]?' checked="checked"':''),
			$legend
		);
	}
	
	return $output;
}

/**
 * Process the "Raw HTML defaults" form fields and save new settings
 * 
 * @param array $params
 * @return void
 */
function rawhtml_save_new_defaults($params){
	//Get current defaults
	$defaults = rawhtml_get_default_settings();
	
	//Read new values from the submitted form
	foreach($defaults as $field => $old_value){
		if ( isset($params['rawhtml_default-'.$field]) && ($params['rawhtml_default-'.$field] == 'on') ){
			$defaults[$field] = true;
		} else {
			$defaults[$field] = false;
		}
	}
	
	//Store the new defaults
	rawhtml_set_default_settings($defaults);
}

And here’s the result :

You can download the wrapper script here. To use it in your plugin, just drop the “screen-options” folder into your plugin’s directory and include the screen-options.php file. Then call the add_screen_options_panel function as described above.

Bonus: the file is structured in a way that lets multiple plugins execute it without causing conflicts :)

Related posts :

12 Responses to “Adding Stuff To WordPress “Screen Options””

  1. […] Options” And “Help” document.write(get_top_adsense_ad()); Continuing from yesterday’s post about adding custom settings to the “Screen Options” panel in WP, I will now show you […]

  2. Interesting.

    Just a little warning here – the screen options code is a little fragile and will likely get a rework in the future which may not be 100% backwards compatible so this route may not work forever.

    In the long run I suspect we need a proper api to allow plugins/core to add things in the right place to get rid of all the hackery we have now.

  3. […] from yesterday’s post about adding custom settings to the “Screen Options” panel in WP, I will now show you […]

  4. Rilwis says:

    I have worked with Screen Options before, but haven’t known that there’s a function ‘convert_to_screen’ exists.

    Your wrapper script is great. Thank you.

  5. Greg says:

    This only worked when I changed add_filter to add_action

  6. Greg says:

    oops. nevermind.

  7. […] Screen Options class by Janis Elsts. […]

  8. Mikkel Breum says:

    Looks interesting, I will try it right away. And thanks to Peter for the comment on future compatibility. Looking forward to seeing what the core team will do with this.

  9. Mikkel Breum says:

    I can make it work with your example code. But I want to target the Dashboard screen (index.php) I tried changing the args from array(‘post’, ‘page’), to ‘index.php’ (or load-index.php) but this doesn’t work.. Is it supposed to, or how can I target the Default dashboard screen?

  10. Mikkel Breum says:

    Oh well, hadn’t tried the obvious: array(‘dashboard’), which works :)

  11. Mikkel Breum says:

    Jānis, the functions rawhtml_get_default_settings and rawhtml_set_default_settings are both undefined. Is there something missing in the wrapper class?

  12. Jānis Elsts says:

    The example code is just that – an example. It won’t actually run, at least not without the rest of the RawHTML plugin. In any case, you don’t need those functions to use the wrapper class.

    (In retrospect, perhaps I should’ve used a simpler example that’s usable on its own.)

Leave a Reply