Using plugins to create custom media menus in WordPress 3.3

WordPress 3.3 introduced a new, unified media menu, where the functionality that used to be accessed through several different menus is now all in one. If you are a plugin developer, and you want to create a custom media menu, you will discover WordPress’ media menu is an arcane and fickle beast. The general reason it’s challenging to work with is that the media menu lacks a complete API. I put several hours of code archaeology work into teasing out its functionality, so this post can guide you through using it. There are two approaches.

Approach one: use ThickBox directly

The WordPress media menu is displayed using ThickBox. One approach is to simply invoke ThickBox directly from your own media button, and not rely on WordPress’ filters or hooks beyond that. This is the simplest approach, and is suitable for many purposes, but it prevents you from using WordPress’ filters and hooks for applying stylesheets to it, or using menu tabs. This is the approach used by the Gravity Forms plugin. Here is the relevant parts of the Gravity Forms code, slightly re-arranged, to show how it all fits together:

  1. Add the Gravity Forms button to the media menu (“RGForms” and “GFCommon” are custom Gravity Forms classes)
    add_action('media_buttons_context', array('RGForms', 'add_form_button'));
    
    public static function add_form_button($context){
        $image_btn = GFCommon::get_base_url() . "/images/form-button.png";
        $out = '<a href="#TB_inline?width=480&inlineId=select_gravity_form" class="thickbox" id="add_gform" title="' . __("Add Gravity Form", 'gravityforms') . '"><img src="'.$image_btn.'" alt="' . __("Add Gravity Form", 'gravityform') . '" /></a>';
        return $context . $out;
    }
  2. Add to the editor page footer the javascript and html that will be shown in the thickbox window when the media button is clicked.
    if(in_array(RG_CURRENT_PAGE, array('post.php', 'page.php', 'page-new.php', 'post-new.php'))){
        add_action('admin_footer',  array('RGForms', 'add_mce_popup'));
    }
  3. In the function below I’ve removed the javascript code that reads the form inputs. The call to send_to_editor passes the resulting Gravity Forms shortcode to the editor window. After that is the html code that displays the form. The display: none style is important: the form is hidden at the bottom of the editor page, and then shown in the ThickBox window when the media button is clicked (the media button link refers to the id of this div). I’ve also removed the input form, which has all its CSS styling done inline (with this approach, there’s no straightforward way to call an external stylesheet).
    function add_mce_popup(){
        // ...not shown - javascript that reads the form inputs
    
        window.send_to_editor("[gravityform id=\"" + form_id + "\" name=\"" + form_name + "\"" + title_qs + description_qs + ajax_qs + "]");
        // ...
    
        <div id="select_gravity_form" style="display:none;">
        // ...not shown - html for the form
    }

Approach two: use WordPress’ filters and hooks

Due to a code change in WordPress 3.3, you can no longer use your own media button if you want to create a menu with custom tabs (or, at least, I couldn’t figure out how). With this approach, your menu will be accessible as a new tab in WordPress 3.3’s unified media menu. I’ll use code from my Shashin plugin as an example.

  1. Register the function that will add tabs to the media menu. The function then adds tabs to the media menu array ($tabs contains the pre-defined WordPress menu tabs)
    add_filter('media_upload_tabs', array($this, 'addMediaMenuTabs'));
    
    public function addMediaMenuTabs($tabs) {
        $shashinTabs = array(
            'shashinPhotos' => __('Shashin Photos', 'shashin'),
            'shashinAlbums' => __('Shashin Albums', 'shashin')
        );
        return array_merge($tabs, $shashinTabs);
    }
  2. Use the media_upload_* action to register the functions that will load the contents for the Shashin menus. It’s crucial that the last portion of the action name match the array keys added to the tabs in the previous step.
    add_action('media_upload_shashinPhotos', array($this, 'initPhotoMediaMenu'));
    add_action('media_upload_shashinAlbums', array($this, 'initAlbumMediaMenu'));
  3. For the remaining steps I’ll just show the “shashinPhotos” tab, as the albums one is similar. Calling admin_print_styles with -media-upload-popup lets you pass your own css file to the media menu, for your custom tab. wp_iframe loads your html into menu.
    public function initPhotoMediaMenu() {
        add_action('admin_print_styles-media-upload-popup', array($this, 'displayMediaMenuCss'));
        return wp_iframe(array($this, 'mediaDisplayPhotoMenu'));
    }
  4. Load your custom css
    public function displayMediaMenuCss() {
        $cssUrl = plugins_url('/Display/', __FILE__) .'media.css';
        wp_enqueue_style('shashinMediaMenuStyle', $cssUrl, false, $this->version);
    }
  5. It’s crucial for this function name to start with the word media. WordPress uses this as a cue to load its standard css for the ThickBox window. Without it, the tabs and other aspects of the window will not get the correct layout. media_upload_header loads the menu tabs. After that, put in your javascript and html for what you want to display for this tab. Like the Gravity Forms example above, you need to call WordPress’ send_to_editor javascript function to insert the final result into the editor.
    public function mediaDisplayPhotoMenu() {
        media_upload_header();
    
        // ... not shown - javascript and html for the menu
    }

Before WordPress 3.3, the Shashin plugin had its own media button, that launched a media menu with two custom tabs. From what I can tell, there is no straightforward way to do this in WordPress 3.3. It used to be possible to have tabs that were independent of the tabs that are part of the standard WordPress media uploader. But now if you want to have custom tabs, you can’t have them as part of a custom menu – you have to add them to the existing media uploader tabs. So for Shashin, I decided to take this approach, as the only alternative would be to add two buttons to the media button bar, and have two separate media menus instead of one menu with two tabs.

Shashin 3.0.8

Update 12/13: the Shashin media menu is not working in WordPress 3.3. I’ll see how they’ve changed the media menu and try to have a fix in the next few days. In the meantime, you can still add shortcodes by hand (you can see the album ids and photo ids in the Shashin Tools menu).

Update 12/14: ….And I just uploaded a fix – version 3.0.9. Note that the Shashin media menus are now available as tabs within WordPress 3.3’s new, unified media menu. So Shashin no longer has it’s own media button. I’ll explain why in an upcoming post.


Last night I uploaded Shashin 3.0.8. If you were browsing photos in one album after another, in some circumstances you’d get spurious Highslide navbars stacking up on the top left side of the page. It’s fixed now. It had to do with the complexities of having different kinds of photo groupings going on at the same time in Shashin – there can be multiple groups of albums on a page, groups of photos within albums, photo-by-photo navigation within Highslide, and “page-by-page” navigation using the Shashin “next” and “previous” links. Getting all of them working together seamlessly has proven to be the most challenging (and therefore rewarding!) part of working on Shashin.

I expect this to be the last maintenance release for Shashin 3.0 (knocking on wood, crossing fingers…). For 3.1 I am planning to add support for Highslide thumbstrips and introduce lazy loading of the photos. I had done some initial work on adding Flickr support, but the Flickr API is fairly complex, so I’m going to put off Flickr to version 3.2, as I’ve been getting a lot of requests for the thumbstrips feature.

Please use the comments section for any support questions.

WordCamp Philly 2011 videos and photos

Video of my Clean Code for WordPress presentation at WordCamp Philly is available at wordpress.tv. You can also check out the other presentation videos available so far. Every session was recorded, so eventually they’ll all be online (Doug Stewart is doing a great job editing them, so they’re worth the wait). Poka Yoke Design provided the photography, and they’ve posted a bunch of great pictures. Here are a few they took of me.

WordCamp Philly 2011
WordCamp Philly 201105-Nov-2011 14:11, NIKON CORPORATION NIKON D7000, 2.8, 70.0mm, 0.005 sec, ISO 400
My presentation at WordCamp Philly 2011
My presentation at WordCamp Philly 201105-Nov-2011 11:31, NIKON CORPORATION NIKON D7000, 2.8, 70.0mm, 0.006 sec, ISO 3200
My WordCamp Philly 2011 presentation
My WordCamp Philly 2011 presentation05-Nov-2011 11:31, NIKON CORPORATION NIKON D7000, 2.8, 24.0mm, 0.006 sec, ISO 3200
 

Shashin 3.0.4 and Toppa Plugin Libraries 1.1

Update 11/21: I’ve upload Shashin 3.0.5, which fixes this issue, reported in the wordpress.org forums


I uploaded two updates to wordpress.org last night – one for Post to Post Links II error: No post found with slug "shashin-wordpress-plugin" and one for Post to Post Links II error: No post found with slug "toppa-plugin-libraries-for-wordpress". They address a couple bugs in Shashin:

  • Automatic photo cropping is now done when appropriate when parsing the old Shashin shortcode format
  • At least a few people have had problems with showing album photos when clicking an album thumbnail. In some cases this was being caused by how I was detecting whether to use http or https for AJAX calls. This is fixed now.

Another cause of the album thumbnail clicks not working is the jQuery form validation plugin. This plugin comes with the Arras theme. I’m still investigating why (there are no forms in Shashin, so offhand I don’t know why there would be a conflict). If you want to temporarily disable the form validation in Arras, go to line 46 in its header.php file and comment it out, like this:

//wp_enqueue_script('jquery-validate', get_template_directory_uri() . '/js/jquery.validate.min.js', 'jquery', null, false);

The Toppa Plugin Libraries update also include a new class for simplifying management of plugin settings (for any plugin that wants to use it). I’ll document it shortly.

Please use the comments section of this post to report any other issues.

Shashin 3.0.3

I uploaded some Shashin fixes yesterday. Thanks everyone for the feedback. These were the changes:

  • Fixed display of “crop” input field on media menu for photos and albums (it wasn’t showing the option for you to crop)
  • Improved exception handling (there were a few cases where you could end up with an uncaught exception, which is not nice if there’s a problem)
  • Handle commas in “exposure” in EXIF data (there’s at least one camera model that included a comma in the exposure value, so Shashin now handles it as a string instead of a number).

Please use the comment section for reporting problems. I have a hectic week coming up, so it may take me a few days to respond to feedback. Thanks for your patience.

Clean code for WordPress at WordCamp Philly

Update 11/21: Video of my presentation is now available at wordpress.tv, and I put up a post yesterday with more pictures.

My Clean Code for WordPress presentation at Philly WordCampMy Clean Code for WordPress presentation at Philly WordCamp
My Clean Code for WordPress presentation at Philly WordCamp05-Nov-2011 11:19, Canon Canon PowerShot SD780 IS, 3.2, 5.9mm, 0.033 sec, ISO 400
 

WordCamp Philly this past weekend was a blast, and I met a lot of great people. The vibrancy of the WordPress community here in Philly is impressive. Giving my Clean code for WordPress presentation was also a lot of fun. I got vigorous agreement from the audience that more evangelism for clean code in WordPress plugins is definitely needed. Video of my presentation will be online at wordpress.tv in a few weeks.

The youngest attendee was 10 years old. He came to the developers’ day on Sunday too. The organizers were planning to guide him through fixing a bug in WordPress core, so he could be the youngest contributor to WordPress and get his name on the official credits. I spent the developers’ day getting started on adding Flickr support to Post to Post Links II error: No post found with slug "shashin-wordpress-plugin". I’m not a Flickr user, but I was sitting next to Captin Shmit, who is, and he had a lot of useful suggestions. Thanks Captin! (yes that’s how he spells it).

Below are the slides from my presentation (if you click the link, it will take you to slideshare.net, where you can also see my notes for the slides).

Shashin 3.0.2

Tonight I pushed a set of updates to Shashin that should address most of the issues people have reported in the last 24 hours. I tried to be thorough in the development and beta testing, so I’m glad to see most of the issues are minor. Thanks everyone for the detailed reports. Note you will also need to update Toppa Plugin Libraries for WordPress. Here’s the list of updates in Shashin 3.0.2 (from the readme file):

  • Album photos table now inherits position from parent album thumbnail table
  • Now handles Shashin 2 shashin_album_key query string arg, for old links
  • Bug fix: numeric fields (like photo count, pub date) were getting cleared when updating ‘include in random’ settings for albums
  • Bug fix: now checks for ‘include in random’ flag on albums and photos when generating random thumbnail display
  • Bug fix: fixed size for album thumbnails using old shortcode format
  • Aligned ‘update include in random’ button on Tools menu with radio button column
  • Updated explanation on Settings menu for photo thumbnails
  • Added .pot translation file

Shashin 3.0 now at wordpress.org

Over the past year I’ve worked on Shashin 3 in 20 minute pomodoro-like sessions, to give myself something interesting to do on my daily train commute back and forth to work. I’ve used it to teach myself clean code practices. How to apply clean code practices to WordPress plugin development will be the subject of my talk next weekend at Philly WordCamp.

If you haven’t seen the posts I’ve been writing while I’ve been working on it, see the Post to Post Links II error: No post found with slug "shashin-wordpress-plugin" and Post to Post Links II error: No post found with slug "shashin-3-development-progress" to see the new features. It’s been a lot of work, and a lot of fun. Many thanks to everyone who helped with testing of the alpha and beta versions.

Please use the comments section of this post for any questions or bug reports. Note if you overlook the notice that tells you to install Post to Post Links II error: No post found with slug "toppa-plugin-libraries-for-wordpress" before upgrading Shashin, and you use WordPress’ automatic plugin upgrade feature, you won’t see Shashin’s warning telling you that Toppa Libraries is missing. So you will need to install the Toppa Libraries, and then de-activate and re-activate Shashin in order to complete the upgrade.

Twitpic and Youtube with Shashin

A dragonfly in the Imperial Palace GardensA dragonfly in the Imperial Palace Gardens
A dragonfly in the Imperial Palace Gardens07-Jul-2010 23:14, SONY DSC-W55, 5.2, 18.9mm, 0.005 sec, ISO 100
 
NoMeansNo - Bumbershoot 2011 - Slave (half of song only)NoMeansNo - Bumbershoot 2011 - Slave (half of song only)
NoMeansNo - Bumbershoot 2011 - Slave (half of song only)04-Sep-2011 00:00
 
Last meal in Tokyo :-( some delicious ramenLast meal in Tokyo 🙁 some delicious ramen
Last meal in Tokyo 🙁 some delicious ramen08-Jul-2010 14:56
 

I just did something that’s a no-no with beta software – I added new features. I just couldn’t resist 🙂 . Shashin 3 now works with Twitpic and Youtube. To your right are a photo from Picasa, a photo from my Twitpic account, and a Youtube video I uploaded, all shown using a single Shashin shortcode. Here’s the shortcode:

[shashin type="photo" id="2655,1507,1453" size="small" columns="1" order="user" crop="y" caption="y" position="right"]

If you go to my Post to Post Links II error: No post found with slug "photo-albums", you can see my Twitpic and YouTube feeds now appear as albums, right alongside my Picasa albums.

Albums, photos, and videos from Twitpic, Picasa, and Youtube will all show up in the WordPress post editor’s Shashin media browser, so you can find and add them by point and click (so you don’t need to look up their ID numbers or even type the shortcode).

In your WordPress admin, on the Shashin Tools page, expand the “Examples” section to see how to add Twitpic and Youtube feeds. Youtube doesn’t advertise the existence of their feeds, but they’re there! In addition to a feed for your own account, you can get feeds for their most popular videos, trending videos, top rated, etc and have Shashin automatically update itself daily. So you can do things like feature the current most popular Youtube videos on your site.

Another change I made is photos will now scale to the size you indicate. So if you want the size to be, say, 213 pixels, it’ll be 213 pixels (if it’s not a size available from the photo hosting service, Shashin will find the next largest size available and scale it down). I did this to accommodate showing photos from different services side by side, since they don’t all make their photos available in the same sizes. This also means you can now show album thumbnails in any size, cropped or not cropped (note I changed the size labels to reflect this, so a “large” album thumbnail is now the same size as a “large” photo thumbnail).

You can download the latest version from GitHub. If you already have Shashin 3 beta installed, please 1. deactivate it, 2. delete your current files, 3. upload the new files, and then 4. reactivate (you don’t need to uninstall the plugin – I renamed several files, so this is just to cleanup your Shashin files).

Assuming no major bugs come up in the next few days, I’ll push Shashin 3 to wordpress.org this weekend, and officially retire Shashin 2.

Shashin Documentation and Examples

Writing good documentation is hard work 🙂

  • Post to Post Links II error: No post found with slug "shashin-wordpress-plugin" now contains detailed documentation for installing and using Shashin 3 (the beta version is currently available at GitHub).
  • I modified the Shashin 3 progress status page so it is now a demo page, with Post to Post Links II error: No post found with slug "shashin-3-development-progress".
  • I created a new, temporary page for Post to Post Links II error: No post found with slug "shashin-2-documentation", since it is still available for download at wordpress.org (I’ll replace it with Shashin 3 when beta testing is complete, in about a week).