Developing Plugin Visualizations for iPeng

Browse Page Cookbook

Last modified on 2008-08-02 02:30:21 GMT. 0 comments. Top.

This is a first draft of a short “cookbook” on how to write plugins to be used with iPeng

Thanks to Erland Isaksson for his idea and support.

If you want to see examples of how this works, I recommend a look into xmlbrowse.html, search.html browse_playlist.html and edit_playlist.html.

Registering Plugins

Even though technically iPeng implements the standard interfaces for a SqueezeCenter skin, most plugins do not look like expected since they make assumptions about the interface that don’t hold on the iPhone or iPod touch. Therefore, I decided to only show plugins that register themselves as being “designed for iPeng”.

If you feel your plugin looks good with iPeng, you can do so by registering menu items under “additionalLinks.browseiPeng”, “additionalLinks.searchiPeng” or “additionalLinks.pluginsiPeng” in addition to the standard categories.

You normally make a call to the addPageLinks function from your plugin to register it like this:

Slim::Web::Pages->addPageLinks("plugins", { $name => $url });

To support the iPeng skin you will need to make two calls to this method:

Slim::Web::Pages->addPageLinks("plugins", { $name => $url });
Slim::Web::Pages->addPageLinks("pluginsiPeng", { $name => $url });

The first row will make your plugin show up as usual in the standard web interfaces, the second row will make your plugin also show up in the iPeng skin. Use the same idea when registering plugins with addPageLinks under the “browse” and “search” categories.

NOTE: Earlier editions of this cookbook claimed the parameters to be called “plugin” and “pluginiPeng”. This is wrong.

How to generate an iPeng compatible plugin

To provide code for iPeng, you can either make your standard plugin code iPeng compatible or write specific HTML and JavaScript code for iPeng. If you do the latter, you will have to place this code in your plugin’s folder structure under


Creating Pages

As usual with SqueezeCenter, pages can safely be started with

PROCESS pageheader.html

and ended with

PROCESS pagefooter.html

However, there are some additional parameters that can be used to streamline the default behavior.


title will define the text in the titlebar, if omitted, iPeng tries to exchange it for pagetitle. Supposed to be a standard parameter anyway.

homeString will define the text in the “return” button to the left of the title bar. Defaults to “Home”.

goHomeURI defines a link target for the “return” button. Expects a link target bracketed in double quotes but also accepts full ‘href=”something.html?…”‘ strings. Defaults to a link to “Home”.

noShowBar: if set to true, the whole title bar is NOT drawn.


selectedButton: currently the only supported parameter. iPeng expects the name of the page category to be given here. The bottombar-button belonging to that page will be highlighted. Currently only the fixed buttons are used:

Album‘, ‘Artist‘, ‘Playlist‘, ‘Search‘, ‘Home

To be compatible with future configuration capabilities any page should provide its name here.

Displaying Stuff

iPeng uses the same interfaces as the EN skin on SC7, that is, you can add content by wrapping it with

WRAPPER contentcontainer

and adding items using

WRAPPER contentitem

Parameters and Behavior

contentcontainer takes the following parameters:


the id the container will be given. If omitted, the container will have the default “browsedbList” id.


if given, the minimum height of the container <div>. Can be used to size accordingly to keep bottombar at bottom of page.


if set to true, no playlistCTRLcontainer item will be placed in the container. See below on the playlist control.

contentcontainer packages the content of the wrapper into a <div> container and a full-width table of class “noborder listNoAlbum”. This table is assumed to have 3 columns but under certain conditions you can also have two or four, see below. The table background is white if not otherwise specified in the stylesheet for listid.

Please be aware that you have to make sure a container has the necessary size to keep the bottombar controls at the low end of the screen. This is mainly due to the fact that you can place stuff (e.g. pagebars or input controls) above or below the container, which is something most plugins actually do but which makes calculating sizes unpredictable. The default way to do the spacing is by using containerheight.

NOTE: the containerspacer block is no longer supported for this.

Typical heights are:

323px for pages without a pagebar, the default for containerspacer

287px for pages without a pagebar

contentitem takes several parameters:


an anchor that provides a anchor heading within a table. An example are the alphabet headings in the Album or Artist views. It only takes the content itself as an argument and provides an anchor (link target) of the same name in the table.


a BLOCK of controls that will be presented to the left of the text column. Can safely be present for a subset of rows only since the column will be spanned with “colspan = 2” if omitted. This can be used e.g. to have cover display for only parts of the rows. See the search function for an example.

controls, rightcontrols

Two additional BLOCKs of controls that will be shown to the RIGHT of the main text column.

For all controls, the standard control wrappers (e.g. playlink, addlink, etc.) work, with the exception of movedownlink which will be ignored. moveuplink does not provide a link button but a clickable line between the actual item and the item above, see the Playlist Editor for an example.


For iPeng, the standard behavior for a playable item is not to show item info (like on the default skins) but to play that item and switch to NowPlaying. Therefore, the playlink button is typically omitted. To provide it’s functionality, iPeng offers the textlink parameter. This parameter takes a link that will be followed when clicking the text content of the item (via a href= link). Please be aware, that this is a link, not a complete href, so a link should read “/…/…html?…#…” instead of “href=’…’“. If you want to use JavaScript, use “javascript:command(parameters);“.

You can also use this to provide links to descend into a structure if you want the whole block of the text field to be clickable instead of only the text itself.


If the fixedwidth parameter is specified, the width of the text column will set to a fixed maximum width (using the max-width style). This is needed if you want to use the browser’s “ellipsis” function (text-overflow style) to limit the width of your text. In this case the browser will cut the text at the end on the column and add “…” to it. If you don’t specify fixedwidth you will have to take care of that for yourself or the column will become wider than the surrounding container (rendering everything to the right invisible).

NOTE: The text-overflow style “ellipsis” doesn’t always render correctly but still wraps around the text in certain cases resulting in taller than expected rows.


A <span> class that will be used to present the content of the wrapper. If omitted, it defaults to listFullTitle. Alternatives defined for iPeng are:


This is the format used for the Title in the Album view


This is the format used for the Artist in the Album view. smaller font and gray color.

" "

Go back to the anchor’s or table cell’s format, usually providing a big font.

The content of the wrapper will be shown in the center column of the table wrapped into a <td> and a <span>.

If you want to provide own links within the content there are a few classes that can be used to format this besides the lineclass:


tapblock generates a clickable block around the link. It’s the standard block class for multiline content.


tapblockFull tries to fill the whole content area as clickable area. Depending on the content in the other cells it will not always succeed. Generally, if you want to have the full content area consider using textlink.


tapblockHalf is intended for “middle rows” in multiline content. It gives a smaller clickable area but this also results in narrower line spacing. Used e.g. with the Search Function.

Differences between Anchor and Text formatting

Please be aware of the difference between formatting an anchor (link) and the text itself (the “<span>”). While the latter formats Font, Color and Size, formatting the anchor is mainly intended to provide a clickable block around the link that at the same time acts as a “keep out area”. This is important to make hitting a link easy on the iPhone.

Using the vertical Pagebar

For pages that use the alphama, iPeng features a vertical pagebar and a limited bottom pagebar that has switches to “next” and “previous” pages.

The pagebar itself is create, like in standard SqueezeCenter skins, using the pagebar block. Only the alphabet bar is generated in a vertical version. Whether the pagebar is shown horizontal or vertical is being controlled by the flag


If set to true, a vertical pagebar will be drawn in the actual division. Also, there is an additional parameter


if defined, this specifies the number of elements the pagebar will contain. This way you can generate the “rollover” alphamap that continues with the last character after the first. If omitted, mapSize defaults to the length of the alphamap and will spread a single alphabet bar over the height (or width, for map_vertical = false) of the current div.

That’s the “minimum” way. However, iPeng has a few functions to help build a vertical pagebar.

iPeng assumes that you use two <div>s with the utility functions: alphamap and crumblist_vert. The latter is for the horizontal pagebar and is also used as a class identifier, not a single id (it will be used twice!). The _vert part is for portrait display (as of today, there is no landscape display). It is somewhat optional you can use any other. alphamap has to be used for the vertical pagebar. Both classes are defined in iPeng’s style sheet, but for alphamap, you have to set the height manually if you don’t use expandAlphamap (see below).

There is a utility block called


If you call this with “PROCESS top_pagebar” it will create the appropriate <div> according to the setting of map_vertical and then create the pagebar within that div.

Now, along with the top pagebar iPeng usually also utilizes a bottom pagebar that is either a complete page list (for the numerical list) or just two icons to get to the previous/next pages. This lower pagebar can be created by PROCESSing


bottom_pagebar will always use the crumblist_vert class for the bottom pagebar (independent of map_vertical).

Now for the really important part: If you don’t want to size your pagebar manually (that includes mapSize AND the actual height of a vertical pagebar) you have to PROCESS


This block will simply issue a call to a JavaScript function of the same name that handles the sizing. It takes a parameter of either listid or containerid (or uses ‘browsedbList‘ if both are omitted) to identify the container<div> for your content. It then acquires the height of that container, scales alphamap accordingly and displays the necessary number of iterations of the alphamap.

If you want to use top_pagebar and bottom_pagebar you could also use the WRAPPER


which will wrap the content of the wrapper between a top/vertical pagebar and a bottom pagebar and will automatically call expandAlphamap. wrapPagebar also evaluates an additional parameter


which will have to be set to true for a pagebar to be generated. This can be used in order to dynamically determine, whether a pagebar should be shown or not, for example by evaluating the pageinfo structure.

Important Note: You will have to issue the call to axpandAlphamap after you fill the container such that it can correctly determine the size of your content. Also, if you use dynamic content, you either have to use fixed scaling (recommended,since it’s fast) or you have to call


from JavaScript again, after the content has changed.

So a typical page could look like this:

[% map_vertial = 1; has_pagebar = 1;
PROCESS top_pagebar;
WRAPPER contentcontainer listid = 'myContent';
< content goes here >
PROCESS bottom_pagebar;
PROCESS expandAlphamap; %]

or, shorter:

[% map_vertial = 1; has_pagebar = 1;
WRAPER wrapPagebar;
WRAPPER contentcontainer listid = 'myContent';
< content goes here >
END; END; %]

Using the PlaylistControls

From 0.2.6 on, iPeng has a line of standard playlist controls for browse lists. It shows up on top of the list and displays the name of the current NowPlaying playlist, a “clear playlist” control and a “save playlist” control. The control only shows up when the current playlist is not empty and hides when the playlist is cleared.

This control is present as the first item of a container using the “contentcontainer” wrapper. If it should appear in other contexts as well, it can be included using

[% PROCESS  playlistCTRLcontainer %]

To omit it (e.g. when having more than one contentcontainer), you can set the “omitPCTRL” parameter for the contentcontainer wrapper to “true”.

The control is hidden by default. There is a default script that checks, whether the playlist is empty and shows the control if not. It should be included in the contentcontainer, after a PROCESS playlistCTRLcontainer and in controls changing the playlist. It can be called with

[% PROCESS activatePLcontainer %]

or, from JavaScript, with


Attention: Since the Control is placed inside the contentcontainer, there is no need to take care of the height of the control when sizing the container!