Tagged: 3.3 dev notes RSS Toggle Comment Threads | Keyboard Shortcuts

  • Andrew Nacin 4:52 pm on December 12, 2011 Permalink | Reply
    Tags: , 3.3 dev notes   

    Use wp_enqueue_scripts, not wp_print_styles, to enqueue scripts and styles for the frontend 

    If you are enqueueing scripts and styles, you will want to use one of these three hooks:

    1. wp_enqueue_scripts (for the frontend)
    2. login_enqueue_scripts (for the login screen)
    3. admin_enqueue_scripts (for the admin dashboard)

    Don’t let the names fool you — they are for both scripts and styles. We’ll probably add equivalent *_enqueue_styles hooks in 3.4 just to make it more obvious, but these hooks have all existed for some time now.

    A possible incompatibility with WordPress 3.3 could arise if you are using the wp_print_styles hook to enqueue styles — your styles may end up in the admin.

    The fix: Use wp_enqueue_scripts instead. Yes, it’s that easy.

    Edit: Yes, the same goes for registering styles. Registering or enqueueing (styles or scripts) should occur on *_enqueue_scripts.

    (Background: #19510)

     
    • Jared 4:58 pm on December 12, 2011 Permalink | Reply

      Whoops, I’ve been using wp_print_styles – thanks for the heads up!

    • Austin Passy 5:10 pm on December 12, 2011 Permalink | Reply

      Will start the update to my plugins. Especially the login_enqueue_scripts that should come in handy for my login plugin.

    • Jamàl 5:18 pm on December 12, 2011 Permalink | Reply

      Will this effect wp_register_style(); as well?

    • Banago 5:52 pm on December 12, 2011 Permalink | Reply

      wp_enqueue_script used to put scripts i.e. JavaScript in the backend too. It it this behavior that has been changed?

    • Joachim Kudish 6:44 pm on December 12, 2011 Permalink | Reply

      Just to make sure, this is backwards compatible (at least for 3.2) as well?

      • Andrew Nacin 8:21 pm on December 12, 2011 Permalink | Reply

        Yes, 100% backwards compatible. login_enqueue_scripts was added in 3.1, but wp_enqueue_scripts and admin_enqueue_scripts were both added much earlier (2.8, I think).

    • camu 7:45 pm on December 12, 2011 Permalink | Reply

      So, in other words, this article by Scribu is not valid anymore? http://scribu.net/wordpress/optimal-script-loading.html (linked from the official WP documentation, http://codex.wordpress.org/Function_Reference/wp_enqueue_script ) I’m asking because I need the registration and the “printing” to happen separately from each other. Unless there’s some other way to enqueue scripts in the footer. I’ve tried to use the last param in wp_enqueue_scripts, but if the template doesn’t call wp_head(), it fails… Separating registration and printing is the only way to solve this issue, afaik.

      Camu

      • Andrew Nacin 8:30 pm on December 12, 2011 Permalink | Reply

        That article is fine, and doesn’t have to do with the issue here. (You’ll note that the wp_print_styles hook is not used.) However, WordPress 3.3 allows wp_enqueue_script() to work mid-page, which means most of that Jedi logic is no longer needed.

        • Camu 8:41 pm on December 12, 2011 Permalink

          Thank you for clarifying :)

    • kwight 7:58 pm on December 12, 2011 Permalink | Reply

      How does wp_enqueue_style fit in to the mix (which I believe loads on both the front- and back-end)? I’ve just been wrapping it in an is_admin conditional up to this point…

      • kwight 7:59 pm on December 12, 2011 Permalink | Reply

        Oops, just noticed the wp_register_style comment above – clears that up then.

      • Andrew Nacin 8:29 pm on December 12, 2011 Permalink | Reply

        We’re only referring to the hooks wp_print_styles and wp_enqueue_scripts. The actual functions, wp_enqueue_style() or wp_enqueue_scripts() should be called from hooks, not directly in the plugin body. (Which is what the post is about.)

    • Ken Newman 8:12 pm on December 12, 2011 Permalink | Reply

      What about scripts/styles only for particular settings pages: any gotchas? (Is “admin_print_styles-$hook_suffix” still good or is there something better?)

      • Andrew Nacin 8:27 pm on December 12, 2011 Permalink | Reply

        While admin_print_styles-$hook_suffix is not as bad as wp_print_styles, note that the admin_enqueue_scripts hook does pass the $hook_suffix as the first parameter:

        do_action('admin_enqueue_scripts', $hook_suffix);
        
    • redwall_hp 2:36 am on December 13, 2011 Permalink | Reply

      That’s good to know. I don’t think I have any hooked on print_styles, but I think I might have on init on a few sites (with an if !is_admin() inside the function). That’s probably not great either, but at least it’s not going to blow up right away. :)

  • Andrew Nacin 8:51 pm on December 8, 2011 Permalink | Reply
    Tags: , 3.3 dev notes   

    Plugin developers: The new wp_add_script_before() function has been removed from WordPress 3.3. (In r19573.)

    In an IRC discussion it was discovered that it was not architected in an ideal way, and some inconsistencies were discovered relating to how scripts are loaded. For more see the end of #11520.

    If you want to echo data to be used in your script, you can continue to use wp_localize_script() as before. Since it now uses json_encode(), it is a bit more flexible (can do nested arrays, for example). In 3.4 we hope to introduce a few more enhancements in this area.

    (For those just tuning in, please note that wp_add_script_before() was originally new to 3.3, so this will not affect existing plugins.)

     
    • Andrew Nacin 8:54 pm on December 8, 2011 Permalink | Reply

    • Andrew Nacin 9:29 pm on December 8, 2011 Permalink | Reply

      The main issue with wp_localize_script() is that it does decode HTML entities. This may not be ideal for certain forms of arbitrary data.

      wp_localize_script() now uses json_encode() which means a multidimensional array will now work for the passed data. And, HTML entity decoding only applies to the first level of the array.

      So, don’t nest localized strings, and note that you can nest arbitrary data. We will definitely make this cleaner in 3.4.

    • arena 4:52 pm on December 9, 2011 Permalink | Reply

      one question. is caching options items from options table using transients since 3.3 ?

      • Alex Mills 10:12 pm on December 9, 2011 Permalink | Reply

        No, transients have always written to the options table unless an object cache was enabled.

  • Andrew Nacin 5:53 am on December 7, 2011 Permalink | Reply
    Tags: , 3.3 dev notes   

    Admin Bar API changes in 3.3 

    Howdy! The Admin Bar API has changed quite a bit in WordPress 3.3.

    First up, what may break your plugin. The added items are no longer stored in a publicly accessible (but ideally privately used) menu property. So, if you were doing something like $wp_admin_bar->menu->..., you won’t get anything back.

    The reason for this is that the internal structure has changed. Nodes are no longer internally stored in a tree. Now, they’re stored in a flat list, and the tree is bound together just before render. This makes the internal API much more stable, and allows us to provide plugin developers some nifty new tools. Even core only handles nodes using the same APIs developers use (mostly).

    If you were to open the file you will notice there are a number of new methods and signatures. Here are the ones developers will want to know:

    • Add a node: add_node( $args ) or add_menu( $args ) (these are equivalent)
    • Remove a node: remove_node( $id ) or remove_menu( $id ) (these are equivalent)
    • Fetch a node’s properties: get_node( $id ).
    • Add a group, which wraps nodes (more on that in a bit): add_group( $args ).

    Terminology notes

    Before I continue: I’m using “item,” “node,” and “menu” synomyously throughout this post. They all are referring to a single link in the admin bar. Nodes can be parents for other nodes, which creates dropdown menus. The API previously emphasized add_menu(), but this can be confusing, so add_node() is now being promoted a bit more. Both methods do the same thing.

    Since the optional admin bar has been merged into the admin header, we’re now calling it the toolbar in the UI.

    Groups

    An example of groups in the new toolbar.


    Version 3.3 introduces the concept of groups. Groups share the same namespace (in terms of IDs) as nodes, and a node’s parent can be a group, rather than another node. Groups allow us to group nodes together into distinct sections of a menu. As an example, see the new W menu in the top left of the toolbar (screenshot at right). Here’s how it was constructed:

    • The W logo node is added. It has no parent.
    • The “About WordPress” node is added. To create a submenu, we set the parent to the W logo.
    • We add a group for external links. The group’s parent is also the W logo. It uses an additional CSS class to add the gray styling.
    • We then add the four external links, and set their parent to the external links group.

    You can see these registrations in wp_admin_bar_wp_menu() and wp_admin_bar_add_secondary_groups().

    Groups were added to provide us some styling flexibility and semantic divisions for a few different menus. (The right side of the top menu, “Howdy” and search, are their own group.) But the possibilities for plugins are pretty great. A plugin can bundle all of their nodes into a single group that then maintain visual separation from all other nodes in that menu. You can use the add_group() method to add groups.

    Moving and modifying nodes

    While this isn’t a change from WordPress 3.2, it’s worth pointing out that add_node() is able to take the ID of an existing node as an argument, and then replace the specified arguments. For example, if you want to make the Network Admin level a top-level item, try this:

    add_action( 'admin_bar_menu', 'nacin_promote_network_admin_in_toolbar', 25 );
    function nacin_promote_network_admin_in_toolbar( $wp_admin_bar ) {
        $wp_admin_bar->add_node( array(
            'id' => 'network-admin',
            'parent' => false,
        ) );
    }
    

    That was easy!

    To make modifications easier, there’s now a get_node() to fetch a node’s properties, and even get_nodes() to fetch a flat list of all nodes, in case you want to loop through them.

     
    • Jane Wells 6:22 pm on December 9, 2011 Permalink | Reply

      The toolbar in not an optional admin bar now, it is part of the actual dashboard. If someone wants to remove it with a plugin, it would be on par with redesigning the dashboard, such as with Ozh’s dropdown menus, and the plugin author would need to design alternative ways to provide the information and access points in the toolbar. The toolbar is not a removable component like the old admin bar was, because it is also the dashboard’s header.

  • Andrew Nacin 4:31 am on December 7, 2011 Permalink | Reply
    Tags: , 3.3 dev notes   

    What to watch for: Javascript and Editor changes in WordPress 3.3 

    Updated December 8.

    There was an earlier post on JavaScript changes in 3.3, but a lot has changed, so here it is again (and updated).

    If JavaScript or visual editing broke in your plugin, start here.

    jQuery 1.7.1

    This release had strong backwards compatibility over jQuery 1.6.1 (which was bundled in WordPress 3.2) but there is still a chance that plugin JavaScript has broken. We will always attempt to bundle the latest jQuery version with every major release of WordPress, so if you plan to use jQuery, you should follow that project as well.

    jQuery UI 1.8.16

    jQuery UI has been updated to the latest version, and all UI components are now included in core, including widgets and effects. This will make it a lot easier and simpler for plugins using UI components that are not used in core as they will be able to just enqueue whatever they need. (For reference, WordPress 3.2 included part of 1.8.12.)

    The wp_editor() API

    Since the last post there have been some bug fixes for wp_editor(). This is an updated API for both TinyMCE and Quicktags that outputs all parts of both editors in the same way as used on the Add / Edit Post screens. Plugins will be able to use the WordPress editor anywhere — including rendering the Visual/HTML tabs and the links to upload files and show the media library.

    Example usage:

    $content = 'The  content.';
    $editor_id = 'foo';
    $args = array(); // Optional arguments.
    wp_editor( $content, $editor_id, $args );
    

    Yeah, that’s it (though of course, you need to save it as well). Of note, there’s one pretty big gotcha: If you use wp_editor() to render the visual editor in a meta box, you risk problems. TinyMCE does not support being detached/moved in the DOM, which would occur when a meta box is dragged. (I’d look into the edit_form_advanced hook to render additional editors.)

    For more, there’s a nascent Codex page on the API.

    QuickTags

    Since the previous post there have been a few improvements for Quicktags (the HTML editor toolbar), including better loading of the default buttons and “safe” close_all_tags() functionality. The major issue here is that we updated a JavaScript “API” that was almost as old as WordPress, so maintaining compatibility has been difficult.

    Quicktags was refactored to make it fully multi-instance compatible (#16695). I think it still needs a Codex page, and I’ll ask @azaozz to post a tutorial here on how to use the new methods, and what before/after looks like in terms of converstion.

    wp_localize_script() and wp_add_script_before()

    When switching it to json_encode(), we opened up the possibility for encoding errors, so some changes were made to make this more backwards compatible. If you have previously used wp_localize_script() to pass arbitrary data (rather than localized strings), consider switching to wp_add_script_before().

    Edit, December 8: wp_add_script_before() was removed.

    Plupload

    The old SWFUpload has been replaced with Plupload. Nothing here has really changed since the previous post, other than strings and the presentation of the drop zone.

    wp_enqueue_script() now works mid-page

    Yes: wp_enqueue_script(), called mid-page, will now enqueue the script into the footer. This isn’t new from the previous update.

     
    • Marko Heijnen 7:42 am on December 7, 2011 Permalink | Reply

      If you want to use the editor in a meta box and you don’t want it to be moveable you can use this line of code:
      $(‘.wp-editor-area’).closest(‘.meta-box-sortables’).removeClass(‘meta-box-sortables’);

      It’s not the nicest solution but it is still better then weird behavior when trying to move the metabox.

    • arena 11:51 am on December 7, 2011 Permalink | Reply

      it would be “cool” to have in the new wp_editor api a setting to discard the fullscreen option such as

      ‘fullscreen’ => true/false (default = true)

    • Kenneth Newman 3:56 pm on December 7, 2011 Permalink | Reply

      ah, that wp_localize_script() thing was beating me up yesterday… good to know about wp_add_script_before() (and it also seems like a more semantic name for what we are doing).

    • arena 10:23 pm on December 7, 2011 Permalink | Reply

      Hello,

      I tried to change the_editor() with wp_editor() on my plugin page and got this :

      no buttons displayed
      when clicking on Visual/HTML got a js error :

      ed is undefined => qt._close(”, ed.canvas, ed); => line 550 => quicktags.dev.js

      any idea ?

    • Andrew Nacin 8:53 pm on December 8, 2011 Permalink | Reply

      This post was updated on December 8 to reflect that wp_add_script_before() has been removed.

    • Jason Penney 12:29 pm on December 9, 2011 Permalink | Reply

      Something that bit me, that might not be obvious: The dependencies changed between a lot of the jQuery UI components, meaning if you enqueued A and relied on the fact that A depended on B, you might be in for a surprise (especially since some of them no longer depend on jquery-ui-core).

  • Andrew Nacin 1:07 am on December 7, 2011 Permalink | Reply
    Tags: , 3.3 dev notes   

    New API in 3.3: is_main_query() 

    There’s a nifty new method for WP_Query that is available in 3.3: is_main_query().

    This enables someone to hook into pre_get_posts and modify only the main query. No more checking for suppress_filters (which was wrong), or comparing against $wp_the_query (complicated), or using query_posts() in a template.

    is_main_query(), the function, will return true if the current $wp_query is also the main query. (As an example, this would be false after query_posts() is called but before wp_reset_query() is called.) This is consistent with existing conditional tags — for example, is_page() refers to the main query, while is_page() can also be called against any WP_Query object.

    Quick example (YMMV) —

    add_action( 'pre_get_posts', 'nacin_modify_query_exclude_category' );
    function nacin_modify_query_exclude_category( $query ) {
        if ( $query->is_main_query() && ! $query->get( 'cat' ) )
            $query->set( 'cat', '-5' );
    }
    

    For more: #18677

     
    • Alex Mills 1:11 am on December 7, 2011 Permalink | Reply

      For those that want to use this while maintaining capability for old versions of WordPress (which is lame, but whatever), check this out: https://gist.github.com/1297669#gistcomment-58619

    • Rafael 1:30 am on December 7, 2011 Permalink | Reply

      And what about that discussion of is_blog(), is that to go in 3.3 or not yet?!?

    • Arnoud 1:37 am on December 7, 2011 Permalink | Reply

      There is a trailing dot in the link to the ticket. Clicking it results in a 404.

      • Andrew Nacin 3:19 am on December 7, 2011 Permalink | Reply

        Ah, thanks. It’s a bug in the P2 theme. It’s been reported (last week, actually).

      • Alex Mills 3:52 am on December 7, 2011 Permalink | Reply

        I can’t reproduce. Hmm.

      • Lance Willett 3:43 pm on December 8, 2011 Permalink | Reply

        We got the report—a fix is is the works.

        @viper007bond I am able to reproduce.

        • Lance Willett 10:32 pm on December 8, 2011 Permalink

          Found another bug. ^^ The auto-Trac link is catching a changeset out of Viper’s username. :)

          This thread is quite productive so far.

        • Alex Mills 10:53 pm on December 8, 2011 Permalink

          @lance Fixed the changeset linking issue by updating the regex to be in sync with the better regex that we use internally.

    • jeremyclarke 3:31 pm on December 8, 2011 Permalink | Reply

      Great new method, definitely something I was dying for in the past that should help clean up some of the code out there once people use it.

      BTW, found another error in P2 ;) Clicking the like button when you are not logged in loads a login box that is hidden by the background. Screenshot.

  • Andrew Nacin 12:14 am on December 7, 2011 Permalink | Reply
    Tags: , 3.3 dev notes   

    Do not include wp-admin/includes/template.php to get add_meta_box() 

    Don’t include wp-admin/includes/template.php to get add_meta_box() defined. This is a very wrong way to go about adding meta boxes.

    The proper way to call add_meta_box() is to consider it to be admin-only (because it is). What you do is call add_meta_box() on the admin_init hook, or even better, the add_meta_boxes or add_meta_boxes_{$page} hooks. (Where $page is either a post type or ‘link’ or ‘comments’.)

    Then there’s no need to include an admin file — the function will always exist when it is called.

    During 3.3′s development, we noticed that some plugins were doing this, so we wanted to make the PSA.

     
    • Marko Heijnen 12:38 am on December 7, 2011 Permalink | Reply

      I do it in one project because I also want to use it on the backend and frontend. It probably will break then
      Reason why I did it was because of reusable code and in my opinion that was to use what WordPress itself also uses.

      What would be the best way to to that? Make something simular by yourself on the frontpage that calls the functions of the meta boxes?

      • Andrew Nacin 3:21 am on December 7, 2011 Permalink | Reply

        I’ve never seen meta boxes used on the frontend. There are too many assets that need to come together for them to work well. That said, if you do need to load admin assets, then you should load the entire bootstrap: wp-admin/includes/admin.php. That’s the only way you can be sure nothing will ever break. Of course, it’s a pretty big performance and memory hit, but that’s the price to pay for using admin functions on the frontend.

        • Marko Heijnen 7:37 am on December 7, 2011 Permalink

          I did fix it now by loading screen.php too. In this case it is a project that I will maintain. I will never going to publish something like this in a plugin.

          In my case I got a post type company. A user can manage his/her company on the front-end but the customer will manage it on the backend. Do be always the same I thought to load meta boxes on the frontend. Probably I should make another set of actions to load the same functions for the frontend. So it is save to use and still one function that handles it.

    • Rafael 1:27 am on December 7, 2011 Permalink | Reply

      Damn, and Im here wondering: “who does that anyway?!” while reading the post…

  • Andrew Nacin 12:01 am on December 7, 2011 Permalink | Reply
    Tags: , 3.3 dev notes   

    The admin_user_info_links filter is gone in 3.3 

    Version 3.3 combines the admin header and the admin bar into one toolbar in the dashboard.

    As the “Howdy” dropdown menu in the admin is now part of the admin bar, we’ve dropped the admin_user_info_links filter. This filter was previously used by plugins to insert links near “Howdy, name | Logout” and eventually as items in the dropdown added in 3.2.

    Now what you can do is add links to the account menu, like so:

    add_action( 'admin_bar_menu', 'nacin_add_account_menu_item' );
    function nacin_add_account_menu_item( $wp_admin_bar ) {
        $wp_admin_bar->add_node( array(
            'id'     => 'secondary-profile-page',
            'parent' => 'user-actions',
            'title'  => 'Personal Settings',
            'href'   => menu_page_url( ... ),
        ) );
    }
    

    This follows us dropping favorite actions (and specifically the favorite_actions filter) in 3.2 as the UI continues to be refined.

     
    • Thomas Griffin 3:34 pm on December 9, 2011 Permalink | Reply

      Why is the word ‘Howdy’ still not filterable? I find I am requested to change the Howdy text on nearly all white-label projects by client request. Couldn’t it be something as simple as:

      $howdy = sprintf( __('%1$s, %2$s'), apply_filters( 'change_howdy_text', 'Howdy' ), $current_user->display_name );

      Or whatever semantic name you want to call it, and then themes/plugin authors could do this:

      add_filter( 'change_howdy_text', 'tgm_custom_howdy_text' );
      function tgm_custom_howdy_text( $howdy ) {
      return 'Welcome Back';
      }

      Maybe I just don’t understand the logic why this couldn’t be included?

      • Jane Wells 6:20 pm on December 9, 2011 Permalink | Reply

        We haven’t talked about it in a while, but in the past it’s been one of those things that was considered part of WordPress’s character, vs an all-things-to-all-people ‘feature’. Will likely come up again at the core team meetup next week.

        • Thomas Griffin 7:52 pm on December 9, 2011 Permalink

          I completely understand that, so I’d never want to see ‘Howdy’ completely gone, but the line between WordPress websites and WordPress-powered websites is increasingly most distinctive, and those on the WordPress-powered side don’t find Howdy particularly endearing. :-P

        • Bjørn Johansen 7:58 am on December 11, 2011 Permalink

          If this really is considered part of WP’s character, why does all the WP sites (e.g. http://wordpress.org/extend/plugins/) greets me with “Welcome, Bjørn Johansen”, and not “Howdy, Bjørn Johansen”?

      • Andrew Nacin 6:26 pm on December 9, 2011 Permalink | Reply

        There should probably be a targeted filter on that string. But this works:

        add_action( 'admin_bar_menu', function( $wp_admin_bar ) {
           $avatar = get_avatar( get_current_user_id(), 16 );
           if ( ! $wp_admin_bar->get_node( 'my-account' ) )
              return;
           $wp_admin_bar->add_node( array(
              'id' => 'my-account',
              'title' => sprintf( 'Hi there, %s', wp_get_current_user()->display_name ) . $avatar,
           ) );
        } );
        

        And all translated strings also run through a filter.

        • Thomas Griffin 7:55 pm on December 9, 2011 Permalink

          Both of those routes, while working, are going around your elbow to get to your arm. It’d be much more concise and simple just to filter it outright. Just my opinion. I’ll submit a ticket and patch and let the powers that be decide its fate.

      • Matt 12:59 am on December 10, 2011 Permalink | Reply

        Would rather not.

        • Thomas Griffin 2:32 am on December 10, 2011 Permalink

          I guess fate made a quick decision then. I still think it would be nice to have, but again it’s just my opinion.

    • Mark 7:49 pm on January 3, 2012 Permalink | Reply

      You guys ever heard of backward compatibility of software? You change things in new versions so all websites on old versions will break? You are Gods who can show up one day and decide to change this filter or that?
      This is what happens when kids run the world.

      • Andrew Nacin 8:29 pm on January 3, 2012 Permalink | Reply

        Hi Mark,

        We take the requirement of backwards compatibility very seriously, more than most projects in fact. While standard software versioning allows for backwards incompatible changes in major versions (3.3 is a major version for us; think of it like 33), we strive to never introduce a backwards incompatible change. Ever. There are going to be a select few every release, but we strive to never break someone’s site, even if a change ended up breaking a plugin that was doing something wrong in the first place.

        The nice thing about filters is that removing one won’t cause any fatal errors. In this case, the absolute worst thing that can happen is that a shortcut link or two might have disappeared from a dropdown that only existed for one version.

        Also of note, before removing the filter, we scanned the entire plugins directory hosted on WordPress.org to ascertain how widely used the filter was. It was limited to less than a dozen plugins. You can see our discussion here. I think it’s clear we don’t take these changes lightly.

        Cheers,
        Nacin

  • Andrew Nacin 11:33 pm on December 6, 2011 Permalink | Reply
    Tags: , 3.3 dev notes   

    Help and screen API changes in 3.3 

    WordPress 3.3 introduces a new API for working with administration screen help content. add_contextual_help( $screen, $content ) is deprecated.

    There are now tabs inside the help tab:

    The way to add these are to attach a function to an existing hook such as the load-{$pagenow} hook, then using the add_help_tab() method of the current screen object.

    For example:

    add_action( 'admin_menu', 'nacin_add_special_theme_page' );
    function nacin_add_special_theme_page() {
        $theme_page = add_theme_page( ... );
        if ( $theme_page )
            add_action( 'load-' . $theme_page, 'nacin_add_help_tabs_to_theme_page' );
    }
    function nacin_add_help_tabs_to_theme_page() {
        $screen = get_current_screen();
        $screen->add_help_tab( array(
            'id'      => 'additional-plugin-help', // This should be unique for the screen.
            'title'   => 'Special Instructions',
            'content' => '<p>This is the content for the tab.</p>',
            // Use 'callback' instead of 'content' for a function callback that renders the tab content.
        ) );
    }
    

    If you want to add a tab to an existing core screen, you’ll probably want to use the admin_head-{$pagenow} instead (to add them to the bottom), since core help tabs are not added until after load-{$pagenow}.

    Help Sidebars

    You can set the content of the right sidebar using $screen->set_help_sidebar( $content ) on the same hook where you used $screen->add_help_tab().

    Removing Help Tabs

    You can use $screen->remove_help_tab( $id ). Additionally, $screen->remove_help_tabs() will remove all tabs for a page.

    Using the new WP_Screen object to adapt to screen contexts

    The get_current_screen() function returns an object that includes the screen’s ID, base, post type, and taxonomy, among other data points. While get_current_screen() (and $current_screen, though the use of the global isn’t necessary) existed since 3.0, it now contains more accurate screen context (and the methods we covered above).

    You can use $screen->id, $screen->base, etc., to ascertain which page you are on. This is helpful as seen above, to make sure that the help tab is only added to edit-tags.php if the taxonomy is post_tag. Of course, this is also helpful on the admin_enqueue_scripts hook (to figure out which scripts or styles to enqueue on a page) as it provides more context than a simple $pagenow or $hook_suffix.

    More about what IDs and bases look like:

    • For edit.php (list for posts, pages, and post types), the ID is ‘edit-{$post_type}’ and the base is ‘edit’. The $post_type value is additionally set.
    • For post.php and post-new.php, the ID is {$post_type} and the base is ‘post’. For post-new.php, $screen->action is ‘add’.
    • For edit-tags.php, the ID is ‘edit-{$taxonomy}’ and the base is ‘edit-tags’. The $taxonomy and $post_type values are additionally set.
    • For all other core pages, the ID and base are generally the same and equivalent to the $pagenow value (minus ‘.php’).
    • For plugin pages, the ID is the value returned by add_menu_page(), add_submenu_page(), or the like, or get_plugin_page_hookname().

    Note on add_contextual_help() and the contextual_help and contextual_help_list filters

    The function and these filters continue to work, but their use is deprecated, and they are not ideal for use. They only work on a single chunk of text, rather than multiple tabs. So if the function is called or if the filters return any data, a separate ‘Overview’ tab will be added for compatibility sake.

     
    • DrewAPicture 7:26 am on December 8, 2011 Permalink | Reply

      @nacin: There’s a typo in your example, it should be admin_head-{$pagenow} rather than admin-head-{$pagenow}. Explains why I couldn’t get it to work at least.

    • Ken 10:03 pm on December 12, 2011 Permalink | Reply

      Any best practice recommendations for adding Metabox helps on (post) edit screens? (more specifically, how to not overwrite the existing sidebar for just a metabox/plugin help links.)

c
compose new post
j
next post/next comment
k
previous post/previous comment
r
reply
e
edit
o
show/hide comments
t
go to top
l
go to login
h
show/hide help
shift + esc
cancel
Follow

Get every new post delivered to your Inbox.

Join 924 other followers