Building on Movable Type Part 2: Re-using the Display Options Widget
In the first article of the “Building On Movable Type" series, we discussed a very simple thing you can do to make your plugin easier to use and seem more integrated with the Movable Type application; and that is to mimic Movable Type’s look and feel by re-using its CSS and Javascript classes. This week we take a departure from shear presentation and dive a little bit deeper into the code base.
In my first iterations of Media Manager I had display preferences that allowed the user to select how many items the user would like to be displayed on a page, and also to select between one of two display modes: a compact tabular view, or a more detailed view that included thumbnails of the items on the user’s media queue. To be honest, the implementation was somewhat of a nuisance, because:
- It required me to persist the state of the user’s options across multiple forms and pages using hidden form elements and query string parameters, which was highly error prone and fragile if I ever forgot to do it properly.
- The user’s selection was forgotten as soon as they left Media Manager.
- The options crowded and already cramped user interface.
Then my friend and co-worker Jamison made a very good suggestion suggestion, “why don’t you create something like the ‘display options’ widget found on any of Movable Type’s tables?�?

I must admit, I was hesitant at first because I didn’t want to cut and paste large pieces of code from MT into Media Manager when I already had a solution that worked. But a couple of iterations later, maintaining my first implementation finally took its toll. I finally relented and decided to take a look into what it would take. What I found is that reusing the display options widget is not only easy, it can be done with virtually no copying and pasting.
Hacking Your Own Custom “Display Options�?
The Display Options Widget provides a way for any developer to create “sticky" user preferences for an application or plugin. They are “sticky" because the preferences are “remembered" even if the user closes or restarts their browser. This is done without the need of a database, and virtually no new code at all. While Movable Type uses this widget for storing list preferences (e.g. the number of items to show per page, expanded vs. compact views, where to place action buttons, etc.), technically the same widget could be used to store any set of arbitrary user preferences.
To create your own Display Options Widget you must first create the subroutines in your plugin to store user preferences. Presuming you have implemented your Movable Type application to extend the MT::App framework then this is really easy. Add the following code to your application’s application handler.
package MyPlugin::App;
@MyPlugin::App::ISA = qw( MT::App );
sub update_list_prefs; *update_list_prefs =
\&MT::App::CMS::update_list_prefs;
Ok, the code above is a little obscure, so let me explain what is going on. Instead of copying and pasting the contents of the update_list_prefs subroutine found in MT::App::CMS into your application, we create a local subroutine and then map it to the subroutine already defined by Movable Type. Not only does this reduce the complexity of your own application, but it also has all the other benefits of code re-use that we as developers should all be well aware of.
Now, in your application, add the update_list_prefs mode handler in your init subroutine.
sub init {
my $app = shift;
my %param = @_;
$app->SUPER::init(%param) or return;
# Insert your initialization code here
$app->add_methods('update_list_prefs' =>
\&update_list_prefs);
return $app;
}
You now have all the backend logic complete to store user preferences. Now let’s turn our attention to the front end.
Let’s first make the “Display Options�? link visible in your application. To do this, you will need to add the following HTML to your application’s template files:
<div id="display-options">
<a href="#" onclick="return toggleDisplayOptions()">
<img src="<TMPL_VAR NAME=STATIC_URI>images/spacer.gif"
alt="" width="7" height="7"
id="display-options-spinner" />
</a>
<a href="#" onclick="return toggleDisplayOptions()">
Show Display Options
</a>
<div class="inner">
<!-- YOUR FORM WILL GO HERE -->
</div>
</div>
The HTML above adds a link called “Display Options" to the page. When the link is clicked a form will appear directly above it that contains the user’s preferences form.
There is one caveat in getting this to work. It assumes you have heeded the advice of the first article in this series and are re-using the stylesheet and javascript files of Movable Type. Specifically you will need to make sure the following HTML is found somewhere in your application:
<link rel="stylesheet"
href="<TMPL_VAR NAME=STATIC_URI>styles.css"
type="text/css" />
<script type="text/javascript"
src="<TMPL_VAR NAME=STATIC_URI>mt.js">
</script>
Now that the link is working properly, let’s create the form that will be displayed when the user clicks the “Display Options�? link.
The form itself can display and contain as many form elements you desire. But the form itself does have a few simple requirements:
- It must be submitted to your CGI script or application. This is so that the user is redirected to the proper location after the user’s preferences are saved.
- It must have a hidden form field called “__mode" (that’s two underscores) with a value of “update_list_prefs." This field, present in every single Movable Type form, directs the request to the proper application handler so that the user’s preferences are saved properly.
- It must have a hidden form field called “_type". The value of this field is the key under which your preferences will be stored and retrieved.
- It is recommended that you have a hidden form field called “return_args". The value of this field should be a query string fragment that will be used when redirecting the user back to the screen they came from immediately after submitting the form.
You can make the rest of the form contain whatever form elements you like. Below is an HTML template you can use for creating your preferences form:
<form method="get" action="<TMPL_VAR NAME=SCRIPT_URL>">
<input type="hidden" name="__mode"
value="update_list_prefs" />
<input type="hidden" name="_type"
value="<TMPL_VAR NAME=OBJECT_TYPE>" />
<input type="hidden" name="return_args"
value="<TMPL_VAR NAME=RETURN_ARGS ESCAPE=HTML>" />
<h2>Display Options</h2>
<div id="display-options-container">
<div>
<!-- INSERT YOUR OPTIONS AND FORM
ELEMENTS HERE -->
</div>
<div class="buttons">
<input type="submit" name="save"
value="Save" />
<input type="button" value="Cancel"
onclick="toggleDisplayOptions()" />
</div>
</div>
</form>
Ok, so you should have all the pieces to save and display a user’s preferences. Now for the final piece of the puzzle: loading a user’s saved preferences.
To load a user’s preferences you call the list_pref subroutine found in the MT::App::CMS module. For example, the following code will retrieve the preferences stored in the current user’s cookie:
my $list_pref = MT::App::CMS::list_pref($app,'<object type>');
The list_pref subroutine returns a Perl hash that contains as name-value pairs the user’s preferences, where the keys of the hash correspond to the form element names found in the user preferences form we created above. Once you have the hash containing the user’s preferences you can retrieve individual preferences just like you would from any other Perl hash:
my $my_pref = $list_pref->{some_pref};
Remember, you can store as many preferences as you like, and technically you could surface many different preferences dialogs on a single page, provided that you use a different key, or value for “_type" field, for each group of preferences you want to maintain.
In Summary
I can see many different ways to use the techniques discussed in this article within Media Manager, and other plugins I am working on. I personally like using the Display Options Widget because it requires so little overhead to implement and support. The widget is especially helpful if your application needs to help users maintain lists of things, for example in the way that Media Manager can maintain a large list of CDs, DVDs, Books, and other Amazon products.
And, if your application does need to help users manage lists of items, then you will be interested in our next topic: hacking pagination controls. Pagination is a wheel I have personally reinvented a million times, so it was a relief to discover that Movable Type makes this simple enough so that one doesn’t have to do all the simple, but tedious math to figure out the links for paging through your list.



5 Comments
And, if your application does need to help users manage lists of items, then you will be interested in our next topic: hacking pagination controls. Pagination is a wheel I have personally reinvented a million times, so it was a relief to discover that Movable Type makes this simple enough so that one doesn’t have to do all the simple, but tedious math to figure out the links for paging through your list. I fully agree.
Thanks for the code, works flawlessly for me.
wow complicated stuff here...
code works great for me too
thanks for the article... good stuff here