Skip to content

En dev listing framework overview

semuel edited this page Jan 4, 2012 · 26 revisions

The Listing Framework

Description

The listing Framework provides a common listing user interface for objects that inherits MT::Object. The framework includes various functions such as filtering and sorting the list. A plugin author can use this framework to generate a list of custom objects as well as adding custom columns or filters to the existing MT objects.

Backward compatibility

In the past, the listing function used mtapp:listing template tag, to render the list in the template. In the new listing framework we don’t use it anymore, but instead use a customizable template to render lists.
However, mtapp:listing is still supported for the backward compatibility, but it does not provide new functions such as filtering or sorting.
Existing list_actions and URL links ( such as http://example.com/mt.cgi?__mode=list&_type=entry&filter=status&filter_val=2 ) should work fine in most cases.

Example

Suppose that you have a new object in your plugin, named MyPlugin::Sunrise, who is recording the sunrise times in different cities around the world. It have a few fields: country, city, date, sunrise time, and a small boolean “was I there or not”, which we will shorten to “witon”. For the object itself, we choose the descriptive model name “sunrise”.
Of course, we want to create a listing for this object. (the creation of new objects of this kind is left as an exercise to the reader, but should probably include another form)

The object’s Perl module will be something like this:

package MyPlugin::Sunrise;
use strict;
use warnings;
use base qw( MT::Object );

__PACKAGE__->install_properties({
    column_defs => {
        id         => 'integer not null auto_increment',
        country    => 'string(2)',
        city       => 'string(20)',
        time       => 'datetime',
        witon      => 'boolean not null',
    },
    datasource  => 'sunrise',
    primary_key => 'id',
});

Building the listing

The following code goes to the config.yaml file of the plugin

object_types:
    sunrise: MyPlugin::Sunrise
listing_screens:
    sunrise:
        object_label: Sunrise Listing
        primary: city
        default_sort_key: id
        condition: |
            sub {
                my ($app) = @_;
                return $app->user->is_superuser();
            }
list_properties:
    sunrise:
        country:
            label: Country
            html: $MyPlugin::MyPlugin::Sunrise::country_name
        city: City
        date:
            label: Date 
            html: |
                sub {
                    my ($prop, $obj, $app, $options) = @_;
                    return substr($obj->time, 0, 8);
                }
        time:
            label: Time
            html: |
                sub {
                    my ($prop, $obj, $app, $options) = @_;
                    return substr($obj->time, 8);
                }
        witon: Was I There

First we told MT to register a new object class, (with object_types) and informed it that we want a listing screen for it. (listing_screens) and that only a superuser is allowed to see it.
Then we specify (in list_properties) which fields should be in the listing.

Of these fields, City and witon are the easiest: we just let MT handle everything.
Country is a bit more difficult: we store in the database just the shortcut, but want to display the full country name. So we use a handler to generate the name. um, maybe we should actually write it: (in Sunrise.pm)

my %country_names = ( US => "United State", JP => "Japan", IL => "Israel");
sub country_name {
    my ($prop, $obj, $app, $options) = @_;
    my $cc = $obj->country();
    return $country_names{$cc} || $cc;
}

There. and we already handled all the important cases. (Or maybe it will be better use a module like Locale::Country)

The last two fields, date and time, are not a real fields in the object, that just keep one time field containing both day and time. we need to extract the info in both cases, and do it with inline subroutine inside the YAML.

Accessing the listing

Let’s inject some values to the database, if you still haven’t entered new objects to the system:

insert into mt_sunrise 
    (sunrise_city, sunrise_country, sunrise_time, sunrise_witon) 
    values ('Haifa', 'IL', NOW(), 0);

now use the URL:

mt.cgi?__mode=list&_type=sunrise

… and you see an empty list. before you start cursing, go to “display options” and mark all the columns. ah, now we can see a list!
You probably either want to make it a menu item, or put it as a link in other page.

Customizing the listing

Now you can customize the listing. You probably want to set the order of fields, and tell the listing to display some fields by default. Add action buttons, filters and some CSS to make it pretty. all the details are here:

CALLBACKS

See Listing Calbacks

Customizing further

list_common.tmpl

If listing/foo_list_header.tmpl exists in the template search path, it will be included automatically before the header. You can customize listing screens or add JavaScript code by accessing MTML variables in the included template.
See Template Special Variables

JavaScript and jQuery API in Common Listing Screen

The listReady event

The event listReady will be called when the list is loaded.

jQuery(window).bind('listReady', function() {
    // Do something after the List table was rendered.
})

Notes

Initializing a list

When MT receives a request like mt.cgi?__mode=list&_type=foo and if corresponding method applications/cms/methods/list_foo does not exist, the listing framework generate a list automatically from the information written in the registry ( listing_screens/foo and list_properties/foo ) .

Structure of the list

The listing framework calls XHR (XMLHttpRequest) to get listing data, and render HTML to display the listing screen. You can use various callbacks to customize either the listing data, the listing screen, or both.
The listing screen consists of HTML and JavaScript to render the list, the available filters and the actions. When the listing screen is loaded, or a user changes the filter settings, the listing screen calls XHR to get the data. The XHR contains parameters such as the filter type, the number of rows, and the requested columns. Based on the request, Movable Type loads objects from the database, convert them to proper HTML snippets, and then return the listing data in JSON format. The listing screen receives the JSON response and render it as the list.

Clone this wiki locally