Plugin documentation follows this short message from our sponsor ;-)
If you like my code and find it useful, feel free to show your appreciation with something from my UK Amazon wish list (or US) or donate to the Stef Dawson community coding pot by following the Donate button below to PayPal. Thanks!
smd_style
Manage your alternate stylesheets and (optionally) switch between them via Javascript.
Features:
- Provide a list of style sheet names derived from:
- a given list
- any article field
- a
<txp:variable /> - a URL variable
- some combination of the above
- Use either the built-in stylesheet switching ability of modern browsers or the plugin’s javascript switcher
- Stores current style in a cookie and can be instructed to load that style first on subsequent pages
- Compatible with TXP stylesheets, ‘real’ stylesheets and the rvm_css plugin
- Optionally build your own stylesheet syntax via a form/container
- Put TXP tags inside your stylesheets if you wish (requires TXP-style sheet processing, i.e real_sheets must be off)
Author
Installation / Uninstallation
Download the plugin from either textpattern.org, or the software page, paste the code into the TXP Admin -> Plugins pane, install and enable the plugin. Visit the forum thread for more info and to report the success (or otherwise) of this plugin.
To uninstall, simply delete from the Admin -> Plugins page.
Usage
There are two tags available: one for use in the <head> of your page to set up the alternate styles, and the other can optionally add a javascript stylesheet switcher to the page, wherever you want it to appear.
smd_style
Somewhere in your HTML <head> tag, add a call to smd_style to include a list of alternate stylesheets. Use the following attributes to customise the output:
Attributes
- sheets : a comma-separated list of stylesheets to include. These are their TXP names as given on the Presentation->Styles tab. See sheet names for more
- form : the TXP form in which to build your own
<link>tags. See replacement tags. If not specified (and no container is used) a standard XHTML link will be output - use_default : the list of stylesheets given in the
sheetsparameter does not usually contain the ‘default’ stylesheet associated with the section. This allows you to always include a ‘global’ sheet with core rules in it and have the alternates override/fill in the gaps. If, however, you wish smd_style to output the default stylesheet so you don’t have to do it elsewhere, specifyuse_default="1" - promote_recent : Determine what to do when the page loads and the visitor has already switched to an alternate stylesheet. This can be useful to try and help prevent ‘flashes of unstyled content’ in good browsers. Can take one of three values:
0: do nothing, i.e. sheets are always loaded in the given order1(the default) : any style sheet that has been chosen by the visitor will be loaded as soon as possible after any core sheets (i.e. sheets that you want to be non-alternate). Thus if you have 2 ‘core’ sheets and the visitor chooses the alternate sheet that used to be #4 in the list, it will now be loaded 3rd2: any style sheet that has been chosen by the visitor will be loaded first, i.e. the chosen sheet will always be promoted to the #1 slot
- skip : in the list of sheets, skip this number of sheets before starting to label them as ‘alternate’. The special default setting of
autobehaves thus:- if
use_default="1", the first sheet in the list will be skipped (i.e. will always be a true stylesheet). Equivalent toskip="1" - if
use_default="0"the first sheet in the list will be an alternate stylesheet (i.e. equivalent toskip="0")
- if
- skip_titles : in the list of sheets, skip this number of sheets before starting to add
titleattributes. The special default setting ofautoworks the same as for theskipattribute. Note that some combinations of skip/skip_title are not permitted by the HTML specification so are disallowed. See skipping for more details - show_empty : by default, if any field (e.g. a custom field) has no value assigned to it and you try to read a sheet name, the field will be ignored. Setting this to
1will include a stylesheet with the name of the field itself. See Example 5 for a practical application of this - real_sheets : normally, standard
css.php?n=sheet_namereferences are output. If you prefer ‘real’ stylesheet filename references, set this attribute to1. Note you will have to ensure that the stylesheet files really exist on your server in the given directory (seesheets_dir) - sheets_dir : location (relative to the root of your textpattern installation) where your stylesheets are to be found if using
real_sheets="1". If you have the rvm_css plugin installed it will default to the directory specified in Admin -> Preferences -> Advanced -> Style directory - parse_tags : if you wish to be able to put TXP tags inside your style sheets and have them parsed, you now can. Set this attribute to
1to enable tag parsing. Note that this only works ifreal_styles="0"because there’s no way for Textpattern to intercept a direct call to a stylesheet - delim : the delimiter to use between
sheets. Default is the comma (,) - param_delim : the delimiter to use between additional sheet information. Default is the colon (
:)
Sheet names
When using the sheets attribute, if you precede any sheet name with a ? the TXP environment will be searched for a matching location. For example, sheets="core, ?custom3" would load core.css and then look in the custom3 field for a further list of stylesheets to load. The order in which the locations are searched is: 1) Article fields; 2) <txp:variable />; 3) The URL. If a ? value is supplied and a suitable location cannot be found, the value you gave will be used verbatim.
You may also specify up to two additional pieces of information in each sheet definition: 1) the sheet’s “pretty name” that people will see, and 2) its media type (usually screen). To do this, separate the values with colons (unless changed via the param_delim attribute) like this:
<txp:smd_style use_default="1"
sheets="core, cats:Cats of the world, printer:Print layout:print" />
That would output something similar to the following:
<link rel="stylesheet" type="text/css" media="screen"
title="default" href="http://site.com/textpattern/css.php?n=default" />
<link rel="alternate stylesheet" type="text/css" media="screen"
title="flowers" href="http://site.com/textpattern/css.php?n=flowers" />
<link rel="alternate stylesheet" type="text/css" media="screen"
title="Cats of the world" href="http://site.com/textpattern/css.php?n=cats" />
<link rel="alternate stylesheet" type="text/css" media="print"
title="Print layout" href="http://site.com/textpattern/css.php?n=printer" />
Replacement tags
If you don’t like the standard output or wish to fashion your own <link> tags then you can specify container content or a form with which to process the results. There are replacement variables you can employ within your layout to insert the relevant content for each stylesheet:
{smd_style_name}: the stylesheet name as given in the TXP Styles tab{smd_style_url}: the complete URL (TXP-style or ‘real’ depending on thereal_sheetsattribute){smd_style_media}: the type of stylesheet (e.g. screen, print…){smd_style_rel}: the stylesheet relationship (either ‘stylesheet’ or ‘alternate stylesheet’){smd_style_title}: the human-friendly title you have assigned to the styelsheet. If not specified, it defaults to the stylesheet name{smd_style_counter}: the current stylesheet number being processed{smd_style_total}: the total number of stylesheets in the list
Skipping
The HTML specification allows for three types of stylesheet:
- Persistent : ones that are forced on the user unless they choose No Styles from their browser menu
- Preferred : ones that are always loaded but can be swapped out for others
- Alternate : ones that are not loaded by default but can be switched in and out freely by the user
With a combination of use_default, skip and skip_title you can offer any of these types. Some combinations of skip and skip_title are not permitted because they would render illegal HTML (e.g. the case when you have an alternate stylesheet without a title).
To try and make it a little easier to visualise, here is a table that shows which of the stylesheet flavours are served with varying values of these attributes. Assuming you have two stylesheets labelled A and B, sheet A will be set to one of the following flavours:
| skip=0 | skip=1 | |
| skip_title=0 | Alternate | Preferred |
| skip_title=1 | (disallowed) Alternate | Persistent |
The same logic applies if using the auto parameter and/or the use_default attribute. The first sheet in the list will become one of those flavours of Stylesheet where the values of skip and skip_title intersect. If using values of ‘N’ or more, the first ‘N’ sheets become those particular flavours.
smd_styleswitch
Requires jQuery to be loaded on your page, before the call to smd_styleswitch. Tested with the latest version (1.2.6 as of this writing).
On its own the smd_style tag gives the visitor the ability to switch styles via the ‘View alternate stylesheet’ facility of modern browsers. If you wish to offer them a way of instantaneously switching (and remembering) the chosen theme from within your content, use smd_styleswitch somewhere in the flow of your page to insert a stylesheet switcher. It can be customised as follows:
Attributes
- wraptag : standard (X)HTML tag to wrap the entire switcher with. Default is
ul. If you do not specify this attribute you_must_ create your own container somewhere else in the page - class : CSS class to apply to the wraptag. Default is
smd_switcher. If you have not specified awraptag, your own container must be given this class name so the switcher can be inserted - break : standard (X)HTML tag to wrap each stylesheet name and link with. Default is
li. Note that this does not have to operate as a container tag (see thebreak_is_tagattribute) - break_is_tag : if the
breakattribute is a tag, this should be set to1(which it is by default). If you wish to use something else between each stylesheet name (e.g.break=" | ") set this to0 - linkclass : CSS class to apply to each stylesheet link. Default is
smd_styleswitch - activeclass : CSS class to indicate the currently selected stylesheet link. Default is
smd_currstyle - alt_only : if set to
1will only offer stylesheets with a rel that includes ‘alternate’ in the list. The default behaviour (0) is to list all stylesheets on the page that contain a ‘title’ attribute - sort : set to
1(the default) to sort the stylesheets in alphabetical order. If set to 0, the most recently used stylesheet will be shown at the head of the list - case_sensitive : whether the
sortis case sensitive (1) or not (0). Default is 0 - expiry : number of days after which the cookie that holds the current stylesheet remains valid. Default is
7days
The stylesheet switcher that is inserted at the given location consists of an anchor tag with a link to the new stylesheet. The text within the anchor is the stylesheet title (if supplied) or its name if not. Note that the switcher will pick up all stylesheets that have a title attribute so if any of your other stylesheets not controlled by the plugin have titles, they will be included as well. This could be considered a feature(!)
If you are a neatness buff and prefer that all javascript goes in the <head>, using wraptag="" will allow you to insert the <txp:smd_styleswitch /> tag in the head of your document while locating your switching container elsewhere.
Examples
Example 1
<txp:smd_style
sheets="yellow, green, brown, blue, pink, black" />
<txp:smd_styleswitch wraptag="" />
Somewhere further down the page you would have to add:
<ul class="smd_switcher"></ul>
That will add six alternate stylesheets to the page and add a switcher wherever your <ul> appears on the page. A few modifications are possible:
- with rvm_css installed, adding
real_sheets="1"to thesmd_styletag would change the URLs to ‘real’ CSS file paths - adding
use_default="1"will add the current section’s stylesheet to the list as well. If it happens to be the same as one of the ones in the list already, it will only be used once - adding
skip="2"will cause the ‘yellow’ and ‘green’ sheets to be static (non-alternate) - using
promote_recentwill change the load order as follows:0: load order will always be yellow, green, brown, blue, pink, black1: promote the chosen sheet up the list. Withuse_default="1" skip="2", if the visitor chose ‘pink’ as their theme and refreshed the page, the load order would be: yellow, pink, green, brown, blue, black (yellow and pink would be listed as “static” stylesheets)2: force whichever sheet was most recently chosen to be the first loaded. Again, if the visitor chose ‘pink’ as their preferred sheet and refreshed the page, the load order would be pink, yellow, green, brown, blue, black (pink and yellow would be static sheets)
Example 2
To set up the names of the stylesheets you want to include in a <txp:variable /> try this:
<txp:variable name="alt_styles"
value="girls:Girly theme, boys:Lads only" />
<txp:smd_style sheets="?alt_styles" />
Example 3
Grab the default sheet, the “fixed” sheet (and make them both ‘static’) then look in the custom field labelled alt_styles and the URL variable mytheme for more sheet definitions.
<txp:smd_style sheets="fixed, ?alt_styles, ?mytheme"
use_default="1" skip="2" />
Note that no distinction is made where to find the variables, they are just checked in order and the first one it finds that matches (if at all) will be used. Thus if you had a custom field labelled alt_styles and someone put site.com/my_page?alt_styles=two,three,four on the URL, you would still have them read from the custom field because it is ‘higher’ in the hierarchy. One caveat is that if the custom field is empty, the next place in the list is checked until all locations are exhausted, though you can ignore empty fields with show_empty="0".
Example 4
For a non-XHTML DTD you may need to drop the trailing / on the <link> elements, so you could do this:
<txp:smd_style sheets="blue, red, green">
<link rel="{smd_style_rel}" type="text/css"
media="{smd_style_media}" href="{smd_style_url}"
title="{smd_style_title}">
</txp:smd_style>
Example 5
The show_empty attribute seems fairly pointless on the surface, but imagine this scenario: you set up a custom field called default_style. When authoring articles, people can insert the name of a stylesheet in there to style the page with. But if they leave it blank you could ensure the page renders with at least some default content by creating a stylesheet called “default_style” (i.e. the same name as the custom field) and using a tag like this:
<txp:smd_style sheets="?default_style"
show_empty="1" />
If the custom field is empty, the plugin converts the request to <txp:smd_style sheets="default_style" />.
Example 6
Tag parsing.
<txp:smd_style sheets="first, second, third"
parse_tags="1" />
If one of your stylesheets contained the following:
.filler {
background:url(<txp:site_url />images/bg.jpg);
color:red;
}
The TXP tag would be replaced with the contents before being served. This does have a performance penalty as the stylesheet is fetched and parsed, but can be very useful. You may use <txp:php></txp:php> tags in the stylesheet as long as the admin preference to allow page level PHP is enabled. Many thanks to akokskis for some of the code from ako_cssParse that enables this feature.
Changelog
- 12 Oct 08 | 0.1 | Initial release
- 18 Oct 08 | 0.2 | Added
parse_tags(thanks akokskis / johnstephens) ; addedskip_title; fixed invalid link tags ;real_sheetsnow work without a form/container
Experimental software
If you’re feeling brave, or fancy trying something new, you can test out some of my beta code. It can be found on the plugin beta page.
Legacy software
If, for some inexplicable reason, you need an old version of a plugin, it can probably be found on the plugin archive page.
