Composr Tutorial: Tempcode programming
It also serves as a complete programming language with support for control structures, built-in core functions and variable substitutions.
Table of contents
-
Composr Tutorial: Tempcode programming
- Syntax
- Philosophy
- Placing theme images
-
Symbols
- Numbers and logic
- Further notes
- General
- Format conversion and obfuscation
- Users, Members, and Usergroups
- Composr permission querying
- Internationalisation
- Environmental/context querying
- Placement
- URLs, Zones, Pages, Scripts
- Images
- Composr configuration/status querying
- The Feedback system
- ID conversion
- Specific/advanced Composr interfacing (non-configuration, non-environment)
- Tracking and events
- Logic
- Arithmetic
- String manipulation
- Tempcode variables
- Catalogues
- Directives
- Encapsulation
-
Detailed worked examples
- Creating a new block
- Creating a template file
- Adding the block to front page
- Set randomisation example
- Number randomisation example
- Obfuscation example
- Truncation example
- Match-key example
- User-agent detection example
- Admin check example
- Group membership example
- Guest check example
- Thumbnail example
- Zebra striping example
- GUIDs
- See also
Syntax
The "syntax" of a language is simply the grammar. Tempcode's syntax is extremely simple.Tempcode provides four constructs other than the plain text of the template itself:
- Parameters: {PARAMETER} where PARAMETER is a code-name of something that was actually passed to the template.
- Language strings: {!STRING,<parameters>...} where STRING is a real language string from a loaded language file (e.g. Banner code could use strings from banners.ini, but most other code could not; global.ini contains strings usable anywhere).
- Symbols: {$SYMBOL,<parameters>...} where SYMBOL is a real symbol Composr supports. Embedding a symbol is like making a function call or running a command in the complex place, or a substitution in the simple case.
- Directives: {+START,DIRECTIVE,<parameters>...}...{+END} where DIRECTIVE is a real directive Composr supports. Directives essentially wrap portions of the template, controlling that portion; they are generally used for types of condition checking (e.g. IF) or loops. There are also directives like {+IMPLODE,<parameters>...} that do not wrap, but work outside the normal "string manipulation" bounds that symbols do.
Escaping
Any of the above 4 Tempcode constructs may be escaped. By "escaped", I mean made to fit in an encoding scheme, such as HTML or URLs, such that special text characters do not interact with that encoding scheme in an insecure/corrupting way). This is done with ease using escaping filters, just by placing the character associated with the mode of escaping before the closing '}'.For example, {BLAH*} will add the parameter BLAH, escaped for HTML output.
The following escaping filters are provided (green indicates common usage, red indicates advanced usage)…
Character | Purpose | Example | |
---|---|---|---|
Before | After | ||
HTML and XML | |||
* | Text embedded within HTML. | Hello & Goodbye | Hello & Goodbye |
= | HTML escaping (like above), if you are 100% sure you want the data escaping, even if it comes from something that might already be in HTML such as a language string. | as above | |
| | Make something appropriate for use as an HTML/XML ID, usually to be referenced by JavaScript and CSS. | This is a -terrible- ID | This__is__a____terrible____ID |
JavaScript | |||
/ | Works around a special JavaScript SGML-issue: anything looking like HTML tags within a <script> tag must be specially-escaped. | print('</p>'); | print('<\/p>'); |
% | Make something appropriate as a strict codename. This is used where JavaScript code is involved for the highest level of security. | This | This |
This is | Hack-attack triggered | ||
CSS | |||
' | Make something appropriate for use as a CSS value (anything that isn't a part of a very constrained non-string value is replaced with underscore). | green and red | green_and_red |
Both JavaScript and CSS | |||
; | Make something fit between JavaScript/CSS-style single quotes. | Who's here | Who\'s here |
# | Make something fit between JavaScript/CSS-style double quotes. | She said, "Hello" | She said, \"Hello\" |
~ | Where new lines are not allowed (text is drawn up to reside on a single line). | a b |
ab |
^ | Where new lines become \n (individual lines are drawn together with \n as a separator). | a b |
a\nb |
Comcode | |||
@ | Make sure something doesn't look like a Comcode tag. | Use the [url] tag | Use the \[url] tag |
URLs | |||
& | Make sure something fits in as a URL parameter, with special Comcode URL escaping also. | a&b | a:amp:b |
. | Make sure something fits in as a URL parameter, if you don't want extra Composr URL escaping to happen. Use this when building up non-Composr URLs. | a&b | a%26b |
Special (not actually for escaping) | |||
- | Special code to indicate that a construct should not be pre-processed. This is useful very occasionally if you want to stop something like a block being preloaded if it is buried under a Tempcode IF directive and hence doesn't always run. It also reduces the Tempcode tree memory usage a lot. Stopping pre-processing will stop any JavaScript or CSS dependencies being called up, however. | ||
> | Indicates the Tempcode should be evaluated but not output. Useful only occasionally for very special situations. | ||
+ | Must be used as the only escaping character. This indicates that something:
|
It is absolutely crucial that Tempcode programmers use the proper escaping. Without it, all kinds of insecurities and unreliabilities can develop. About 50% of parameters in the default Composr templates actually use HTML escaping so that plain text placed inside a template does not interfere with the HTML structure itself and displays literally.
If you're wondering what the characters refer to: nothing. They are just characters that are easy to type on a regular keyboard. We like the ability to be able to apply the escapings in this shorthand, in the same way that maths benefits from concise symbolic shorthand.
Escaping Tempcode itself
Tempcode features a very simple escaping system if you need to output something that looks like Tempcode literally.It is rare that you actually need escaping, as Tempcode is not going to try and parse every brace it sees, only braces that are succeeded by an alphanumeric character or any of the following characters: $ / + / ! / _. The typical brace used for JavaScript or CSS code is going to be followed by white-space.
The following escaping substitutions work:
- To escape { use \{
- To escape } use \}
- To escape , use \,
Backslashes cannot be escaped. So \\ will output literally, and \\{EXAMPLE} will output \{EXAMPLE} (i.e. Tempcode will not be triggered because the first slash outputs literally and the second slash escapes Tempcode).
This is intentional: we don't want Tempcode programmers to have to layer escaping schemes, as JavaScript and CSS feature similar backslash-based escaping.
If you really need to output a backslash without it working as an escape character on a succeeding { / } / _ character you can use the {$BACKSLASH} symbol. Or, you can drop down to a character-code scheme in the output you're generating (for example, HTML allows output characters using HTML entities, and JavaScript strings support escaped character codes).
The Tempcode tree (advanced)
Templates are composed together into a tree structure, and then the tree structure is output. This is discussed in further detail in the Composr site structure tutorial.Philosophy
Tempcode is quite different from other templating languages, and it's worth covering that.Most templating languages will try to either:
- use XML, to add programming constructs into the mark-up itself
- allow PHP code, or an abstraction of PHP code, to run within the templates
Our approach is distinctly different, as we uphold four strong principles:
- templates should be editable in an HTML editor without Tempcode being broken (although the HTML editor at this time must be able to support 'fragments of HTML')
- templates should not contain code on the same level as PHP, for security reasons (a theme should not be able to delete files, for instance)
- there should be a very clear separation of role between templates and code; code should not be put into templates simply because it is convenient, as this muddies the architecture, causing maintenance issues
- templates should not 'execute': Tempcode should act as a filter/token-placer for output, reshaping output, rather than intertwining code with it. This is again, an architectural issue
Advanced philosophy (experts only)
For those interested in 'programming language semantics', Tempcode is neither a functional or imperative language, but has aspects of both. A functional language essentially is focused on output being controlled by a complex mathematical expression. An imperative language essentially is focused on output being controlled by a sequence of commands. With Tempcode, output is focused on the stream of text coming from a template, and the composition of these streams; 'symbols' and 'directives' can control, manipulate and add to the stream, but they are more like embedded functional-language function-chains and control-tags than imperative code. Sequences of commands can be simulated by placing symbols and directives next to each other in the output stream and using variable manipulation features to bridge data across the portions of the output stream.Popular template languages such as 'Velocity' or 'Smarty' are able (and often used) to function in a similar sense to this, but their language design is imperative at core, and the result simply is just far less elegant. Tempcode just 'feels right', with its clean syntax and PHP-separation, while other languages look literally like conventional programming code has been added inside the template in an ad-hoc way (even if the full programming syntax has been simplified a bit).
Placing theme images
Party like it's 1999
(this guy's back must
be really hurting by now)
To insert an image into your template, use Composr's image symbol: {$IMG,codename}. Replace codename with the image code for the image you want to use. This will turn into the image's URL. Be aware that this does not insert any HTML for you, so to use it fully:
Code (HTML)
The advantage to using the Composr code instead of hand coding the image is two-fold. First, you can have different versions of theme images for different languages and themes. Secondly, if you ever move the image, you don't have to edit every page that ever used it to point to the new location. You can edit images from within the themes management screen (go to Admin Zone > Style > Themes).
Symbols
Numbers and logic
Tempcode does not have explicit data-types, everything is text. However we may interpret the text in symbols as follows:- Tempcode number: the text is assumed to be a number written as a normal decimal string (e.g. 12345). Numbers should not contain any special formatting other than the British English decimal point (.) symbol.
- Tempcode boolean: the text is assumed to be 0 (meaning false) or 1 (meaning true). Actually everything other than 1 is considered false.
Further notes
If a symbol is missing important parameters, it generally is skipped entirely.Some of the more advanced symbols are not fully laid-out, but they are all defined in sources/symbols.php or sources/symbols2.php in an obvious way, so advanced users can read this file.
You are very unlikely to ever want to use rows in red, as they are intended for use by core Composr code.
General
Symbol name / example | Purpose |
---|---|
(blank) | Place a comment. E.g... {$,this is a comment} |
{$RAND,min,max} | If no parameters are given, it picks a random number between 0 and 2147483647. If one is given it picks a random number between 0 and that parameter. If two are given it picks a number between the first and second parameter. |
{$SET_RAND,a,b,c} | A random choice from the given parameters |
{$CYCLE,cyclename,a,b,c} | Cycle through parameters in a sequence (intended for use across template calls to create, for example, striping effects). The first parameter is the name of the cycle, and the following parameters are the parameters of the cycle. The pointer for the named cycle will move forward/around each time the cycle symbol is referenced (e.g. {$CYCLE,mycycle,a,b,c,d} would produce "a" the first time it's called, "b" the next, "c" next, then "d", then back to "a" again). If you only provide one parameter then the cycles current index is returned. If only two parameters are provided then the second parameter is split up by commas; this is useful for programming cycles on a higher level (e.g. for making chequered patterns using floats). |
{$RESET_CYCLE,cyclename} | Reset a named cycle sequence |
{$MAILTO} | Get an obfuscated "mailto: " string (obfuscated to make it hard for e-mail scavengers to detect) |
{$CSS_DIMENSION_REDUCE,30px,2} | Reduce a CSS dimension by a certain number of px. If the input is not in px, no function is performed and the output stays as the input. |
{$BETA_CSS_PROPERTY,<css rule>} | Adds browser vendor prefixes to a CSS rule that is not widely supported yet. This effectively marks the CSS rule out, and theoretically allows new Composr versions to alter how that rule is handled without direct changes to your theme CSS. |
{$REQUIRE_JAVASCRIPT,example} | Include a JavaScript file in the output stream. If you set the second parameter to '1', then loading will be deferred until the end of the page. If you include a template into itself, then it will actually include the original version at the point of your include. This is useful for extending the default templates without duplicating them. |
{$REQUIRE_CSS,css_example} | Include a CSS file in the output stream |
{$SET_TITLE,xxx} | Set the current page title (affects things like the <title&rt;) |
Format conversion and obfuscation
Symbol name / example | Purpose |
---|---|
{$ESCAPE,what_to_escape,optional_escaping_type} | Perform escaping on the first parameter. Uses the same escaping as integrated template escaping, except a numeric constant (defined in the second parameter) is used to determine the escaping, rather than special characters (see sources/tempcode.php for a list of all the constants). Defaults to HTML escaping. |
{$OBFUSCATE,to_obfuscate} | Obfuscate a string to make it harder for e-mail scavengers |
{$STRIP_TAGS,<strong>example</strong>} | Remove HTML from some text |
{$STRIP_HTML,<strong>example</strong>} | Turn some HTML into a plain-text string (i.e. no HTML entities either). This is not in itself a security filter: in fact, it can turn escaped text into unescaped text by decoding entities. If you are therefore embedding the output in HTML it is important you escape the output of the symbol itself. |
{$ENTITY_DECODE,this & that} | Decode XML or HTML entities, so that written-out XML turns into actual parsed XML |
{$TRUNCATE_LEFT,something long,5,1,0,0,0.2} | Truncate a string, keeping what's on the left as priority. First parameter is the text to truncate. Second parameter is the truncation length. Optional third parameter is a binary value for whether to show a tooltip. Optional fourth parameter is a binary value for whether the input text is already in HTML format (output text is always in HTML format). Optional fifth parameter is a binary value for whether the length desired should be based on readable characters rather than XHTML characters. Optional sixth parameter is a decimal fraction (e.g. 0.2) that represents the tolerance that can be used to preserve grammar (paragraphs and sentence). |
{$TRUNCATE_RIGHT,something long,5,1,0,0,0.2} | As above, truncating to keep what's on the right as priority. |
{$TRUNCATE_SPREAD,something long,5,1,0,0,0.2} | As above, truncating to keep an equal left/right portion. |
{$TRUNCATE_EXPAND,something long,5,1,0,0,0.2} | As above, with any truncated text going underneath an expander. |
{$ALTERNATOR_TRUNCATED,something long,5,if truncated,if not truncated,1} | A complex symbol to allow alternation between situations when something would and would not become truncated. |
{$PARAGRAPH,something} | Add a paragraph around the contents, but only if it does not already contain any block-level elements. This is needed to combine valid (X)HTML for arbitrary Comcode insertion with the desire to have neat semantics and automatic margining. |
{$CLEAN_FILE_SIZE,10000} | Convert a number of bytes into a nice clean human readable file size. |
{$TRIM, abc } | Trim any textual or XHTML white-space from the given string. |
{$DEEP_CLEAN, abc } | Apply the deep clean process on the parameter. Clean common ugly patterns out, such as leading white-space, all-caps, or paste-from-Word problems. |
{$PROTECT_URL_PARAMETER,http://example} | Convert the format of a URL so it can be embedded as a parameter that ModSecurity and browser-based XSS filtering will not trigger security errors on. |
{$BACKSLASH} | Output a literal backslash. This is a workaround to possible complexities with escaping Tempcode. |
Users, Members, and Usergroups
Symbol name / example | Purpose |
---|---|
{$MEMBER} | The Member-ID of the current user |
{$IS_GUEST} | Whether the current user is a Guest |
{$USERNAME,2} | The username of the current user / given user (optionally takes a member ID, otherwise assumes the current user). If the second parameter is passed as '1', the display name is used (if configured). |
{$DISPLAYED_USERNAME,admin} | Turns a username into a display name, using the configured display name generator (if there is one -- otherwise, no change) |
{$AVATAR,2} | The member's avatar (optionally takes a member ID, else assumes current user) |
{$MEMBER_EMAIL,2} | The member's e-mail address (optionally takes a member ID, else assumes current user) |
{$PHOTO,2} | The member's photo (optionally takes a member ID, else assumes current user) |
{$MEMBER_PROFILE_URL,2} | The member's profile URL (optionally takes a member ID, else assumes current user) |
{$CNS_MEMBER_HTML,2} | The member's information box (optionally takes a member ID, else assumes current user) |
{$CNS_RANK_IMAGE,2} | The member's rank images in composed HTML format (optionally takes a member ID, else assumes current user) |
{$IS_IN_GROUP,1-3} | Find whether the current member is in a usergroup (parameters together constitute an Selectcode list, except if the last is primary or secondary then this specifies that the check be limited to checking such usergroup membership). |
{$CPF_VALUE,Some Custom Field} | Find the raw (unrendered) value of a Custom Profile Field (pass in the ID number of a Custom Profile Field, which can be found from the URL of where you to edit it -- or pass in the human-readable name of the field -- or pass in a field name from the f_members table). If you pass a second parameter, it will specify the member ID to use (if not passed, it will default to the current member). Note that Tempcode is not context-sensitive apart from the parameters passed into a template. The current member is whoever is logged in; if you are editing a template displaying a member's details (e.g. CNS_MEMBER_PROFILE_SCREEN) then you will need to explicitly specify the member ID in the second parameter using the member ID passed into that template (typically {MEMBER_ID}). An optional third parameter may be set to '1' to give the rendered value of the CPF (e.g. with Comcode applied); by default the raw inputted value is given. |
{$MEMBER_DATA,example,3} | Get some member data from what the cns_read_in_member_profile function can provide. See the function implementation to see what is supported. Returns blank if it can't get a match. If you leave out the member ID it will use the current member |
{$RANK_POINTS,3} | Get the number of rank points the member has |
{$POINTS_SPENT,3} | Get the total points the specified member has used (spent). |
{$POINTS_BALANCE,3} | Get the total points in the specified member's account; some of these will probably have been spent already |
{$GROUP_ID,0,3} | Find a member's nth usergroup (counting from zero), starting with the primary usergroup (first parameter is n, second parameter is member ID which defaults to the current member) |
{$GROUP_NAME,0,3} | Find the name of a members nth usergroup (counting from zero), starting with the primary usergroup (first parameter is n, second parameter is member ID which defaults to the current member) |
{$IS_FRIEND,2,3} | Detect if the second parameter/member ID (or current member if no second parameter) has befriended the first parameter/member ID. |
{$IS_ICON_IN_SVG_SPRITE,admin/add} | Detect if the provided icon name/path is compiled in an SVG sprite (internal use only). |
Composr permission querying
Permission checks are useful if you want to show screen contents in a way that somehow reflects your configured permission scheme.These are advanced symbols, and mirror Composr's internal API. The parameters are not discussed here, but you may find them from looking at the code.
Symbol name / example | Purpose |
---|---|
{$IS_STAFF,2} | Is the current user / given user staff (optionally give it a member ID else works on current member, returns Tempcode boolean) |
{$IS_ADMIN,2} | Is the current user / given user an administrator (optionally give it a member ID else works on current member, returns Tempcode boolean) |
{$HAS_PRIVILEGE,submit_midrange_content} | Member has a privilege (returns Tempcode boolean) |
{$HAS_ZONE_ACCESS,adminzone} | Member has access to a zone (returns Tempcode boolean) |
{$HAS_PAGE_ACCESS,admin_stats,adminzone} | Member has access to a page (but NOT necessarily the zone it is in) (returns Tempcode boolean) |
{$HAS_ACTUAL_PAGE_ACCESS,admin_stats,adminzone} | Member has access to a page and its zone (returns Tempcode boolean) |
{$HAS_CATEGORY_ACCESS,downloads,3} | Member has access to a category (returns Tempcode boolean) |
{$HAS_SUBMIT_PERMISSION,mid,12.34.56.78,2,cms_example,category,345} | Member has the specified kind of submit permission (returns Tempcode boolean). Parameters: range, IP address, member, CMS page, category, category_id. |
{$HAS_DELETE_PERMISSION,mid,2,2,cms_example,category,345} | Member has the specified kind of delete permission (returns Tempcode boolean). Parameters: range, owner, member, CMS page, category, category_id. |
{$HAS_EDIT_PERMISSION,mid,2,2,cms_example,category,345} | Member has the specified kind of edit permission (returns Tempcode boolean). Parameters: range, owner, member, CMS page, category, category_id. |
Internationalisation
Symbol name / example | Purpose |
---|---|
{$CURRENCY,123,USD} | Do a currency conversion (maintenance status) / Get the currency (first parameter is a number for the amount in the site's default currency, second parameter is the source currency, optional third parameter is the target currency [defaults to the site currency], optional fourth parameter defines a display method 1-6). Requires the eCommerce addon. |
{$CURRENCY_SYMBOL} | Get the nice currency symbol for the site's default currency. Requires the eCommerce addon. |
{$COUNTRY} | Find the current user's country |
{$COUNTRY_CODE_TO_NAME,UK} | Convert an ISO country code to a written country name |
{$COUNTRY_NAME_TO_CODE,United Kingdom} | Convert a written country name to an ISO country code |
{$REGION} | Find the current user's region (usually the same as the country, but may be customised within Composr to be more-specific) |
{$GEOLOCATE,12.45.67.89} | Find the/a user's ISO country-code (optionally takes an IP address, otherwise defaults to current user's IP). Requires the stats addon to be installed, and for the geolocation data to have been installed into the database (usually this is automatic) |
{$CHARSET} | Get the character set |
{$DECIMAL_POINT} | Find the decimal point character for the current language (e.g. .) |
{$LANG} | The user's current language |
{$LTR} | If the current language pack is left-to-right (most packs are) |
{$RTL} | If the current language pack is right-to-left (Arabic etc) |
{$PROVIDE_WITH_TRANSLATION} |
This symbol is designed for assistive translations of user-supplied content. Before you can use the API you must first configure it. For the Google Translate backend:
For the Bing Translator backend:
To use the symbol just wrap it around text that needs translating in templates, e.g. {$PROVIDE_WITH_TRANSLATION,{TEXT},html_block,FR}. This example translates French in [tt]{TEXT}[/tt] to the site\'s current language, within the context of a block of HTML. The original text is followed by the translated text, and as it is a block of HTML it also includes the translation backends mandatory message (e.g. "Powered by Google Translate"). Here are the available translation modes:
If you omit the source language then it will be autodetected. |
Date and time
Symbol name / example | Purpose |
---|---|
{$DATE_TIME} | The formatted current date and time (may take optional parameters, not discussed here) |
{$DATE} | The formatted current date (may take optional parameters, not discussed here) |
{$TIME} | The formatted time (may take optional parameters, not discussed here) |
{$SECONDS_PERIOD,12345} | Show the number of hours/minutes/seconds in a given period of seconds |
{$FROM_TIMESTAMP,D m Y,123456780} | Converts a time-stamp to a formatted date/time (optional first parameter is a date-function-style date/time formatting string, optional second parameter is a timestamp). If no parameters given it will simply return the current timestamp. |
{$TO_TIMESTAMP,April 1st 2009} | Converts a formatted date/time to a timestamp via auto-recognition (first parameter is a timestamp). If no parameters given it will simply return the current timestamp. |
{$MAKE_RELATIVE_DATE,123456789,1,1} | Converts a timestamp into a textually described relative time (e.g. "10 minutes" [ago]) (first parameter is a timestamp, second parameter is 1 to forcefully use a relative date regardless of the "Whether contextual dates (e.g. 'Today') should be used" option, third parameter is 1 if you expect the timestamp to occur in the future). |
{$TIME_PERIOD,1234} | Converts a number of seconds into a textually described time period (e.g. "10 minutes"). |
Environmental/context querying
Symbol name / example | Purpose |
---|---|
{$IS_VIRTUALISED_REQUEST} | Find if this is a virtualised page load, via something like the main_include_module block |
{$KEEP_POST} | Create hidden form inputs to relay POST data from the current POST environment to where a form is pointing to |
{$_POSTED} | Whether the current request was sent with POST parameters (i.e. it was a form post) |
{$METADATA,created} | Fetch a defined dublin core metadata property (by code name), relating to the current content. Also supports some Open Graph fields, HTML SEO metadata (keywords, meta_description). You can also query HTML SEO metadata for specific content item, by giving two additional parameters: the content type and the content ID |
{$REFRESH} | HTML code for a site refresh, if one is in progress |
{$FEEDS} | HTML code for metadata-linkage to RSS/Atom feeds |
{$TRANSLATION_LINKS} | HTML code for metadata-linkage to translations |
{$MOBILE,0} | Whether a mobile device is being used. The first parameter should be 1 if you are considering tablets mobile devices. Composr is designed to be pretty good at detecting this, but if you need to specify additional user agent strings you can make a text_custom/mobile_devices.txt file with mobileuseragentsubstring=0|1 lines in it (e.g. iphone=1 for iPhone to be detected as mobile, and ipad=0 for iPad to be detected as a tablet). If you want to detect smartphones in CSS we have a separate CSS_MODE directive |
{$DESKTOP} | The inverse of {$MOBILE} |
{$THEME} | The user's current theme |
{$JS_ON} | Whether JavaScript is enabled (Tempcode boolean) |
{$IS_HTTPAUTH_LOGIN} | Whether the user has an HTTP-auth login |
{$BROWSER_UA} | The user's browser, based on their user-agent string |
{$OS} | The user's OS, based on their user-agent string |
{$IS_A_COOKIE_LOGIN} | Find if a cookie login is active |
{$HIDE_HELP_PANEL} | Whether the help panel has been hidden |
{$BROWSER_MATCHES,wysiwyg} | Find whether the current browser matches a named property / has a feature. Possible properties: android, ios, wysiwyg, windows, mac, linux, odd_os, mobile, ie, gecko, safari, odd_browser, chrome, bot, simplified_attachments_ui, and itunes |
{$USER_AGENT} | The user-agent string of the current user |
{$IP_ADDRESS} | The IP address of the current user |
{$HTTP_STATUS_CODE} | Find the HTTP status code (e.g. 404) for the current request, usually 200 |
{$BROWSER,wysiwyg,You have WYSIWYG,You do not have WYSIWYG} | Conditionally chooses between two input strings, based on a browser property (see above for a list of properties). First parameter is the property, second and third are the conditional strings. |
{$FORCE_PREVIEWS} | Find whether the user has forced previews to show |
{$CURRENTLY_INVISIBLE} | Whether the current user is set to be invisible |
{$CAN_SPELLCHECK} | Whether spellchecking is possible |
{$SESSION} | Get the session ID for the current member (this is very insecure as it will expose the raw session ID of the member outside of their session cookie; consider using $SESSION_HASHED instead) |
{$SESSION_HASHED} | An MD5 hashed version of the session ID, used as a pseudo-unique identifier without revealing the user's actual session ID. Note that this will be salted with the site's secret salt. |
{$MEMBER_OVERRIDE} | The Member-ID of the account most relevant for the current page view. If you're looking at somebody else's account then this would find their member ID, otherwise it is your own member ID. This symbol can be used for displaying user-specific links and information in a panel that changes from your own if you are viewing an account. |
{$HEADER_TEXT} | Get the header text (put in the page title) |
{$SHOW_HEADER} | Whether the header will be shown |
{$SHOW_FOOTER} | Whether the footer will be shown |
{$WIDE} | Whether the side panels will be shown |
{$WIDE_HIGH} | Whether the side panels, header, and footer, will be shown |
{$LOGO_URL} | The logo URL for the current zone |
{$HAS_SU} | Whether the current user is allowed to use the Switch User feature |
{$STAFF_ACTIONS} | A drop-down of contextual actions for the current screen |
{$HELPER_PANEL_TUTORIAL} | The helper panel's tutorial |
{$HELPER_PANEL_TEXT} | The helper panel's text |
{$MESSAGES_TOP} | Attached messages, for prominent display |
{$MESSAGES_BOTTOM} | Attached messages, for less prominent display |
{$LATE_MESSAGES} | Attached messages that happened after output started (after main page generation). These will usually be errors relating to the output process itself. |
{$BREADCRUMBS} | The breadcrumbs |
{$FORUM_CONTEXT} | The ID of the forum currently within, or blank |
{$MATURITY_FILTER_REQUESTED} | Do a header check, to see if family-friendly browsing experience was requested by the user's safe header preference. |
{$DO_NOT_TRACK_REQUESTED} | Do a header check, to see if do-not-track was requested by the user's browser preferences. |
{$TAPATALK} | Whether output is being generated for a Tapatalk client |
{$PAGE_TITLE} | Get the currently set page title/td> |
{$CSS_TEMPCODE} | Get the Tempcode for all the CSS includes for this page |
{$EXTRA_HEAD} | Get the contents of this global Tempcode variable (used by some parts of the system to inject extra markup) |
{$EXTRA_FOOT} | Get the contents of this global Tempcode variable (used by some parts of the system to inject extra markup) |
{$JS_TEMPCODE} | Get the Tempcode for all the JS includes for this page |
{$HEADER_TEXT} | The header text of the current screen, taken from current zone's setting unless content is being viewed specifies it |
{$THEME_SEED} | Get the seed of the current theme |
{$THEME_DARK} | Find if the current theme is dark |
{$THEME_COLOUR_IS_BRIGHT,colour} | Find if the provided hexadecimal colour is bright (has a luminance of 50% or higher), typically used for deciding if black or white text / icons should be used on top of the specified colour |
{$CURRENT_FATALISTIC} | Find the current fatalistic mode (whether all terminal errors will throw stack traces): 0 if it is off, 1 if it is on, 2 if it is on with additional details. |
Placement
Symbol name / example | Purpose |
---|---|
{$BLOCK,block=main_search,zone=site} | Place a block into the template. Takes any number of parameters (but at least 1 for the block name), each of which defines a block parameter and its value. Parameters must include the block name, which is encoded against the special reserved name block (not just placed in there as a lone parameter). For example: {$BLOCK,block=main_news,filter=1\,2\,3} |
{$LOAD_PAGE,about,site} | Load a page into a template (first parameter is the page name, optional second parameter is the zone name which defaults to the current zone) |
{$LOAD_PANEL,panel_left,site} | Load a panel-page into a template (first parameter is the page name, optional second parameter is the zone name which defaults to the current zone) |
{$BANNER,some_banner_type} | Display a banner of specific type (first parameter is the banner type, second is an optional binary value for whether the banners should be limited to only internal banners) |
URLs, Zones, Pages, Scripts
Symbol name / example | Purpose |
---|---|
{$KEEP,0,1} | Stuff to append to a Composr URL for 'keep parameter' passing (Composr passes any parameters between screens if their names start keep_, and this symbol enables that). The first parameter should be '1' if you need to place this directly on the front of a URL. The second parameter should '1' if you need to always attach a session ID (i.e. if you are creating a link that might be used somewhere outside the current cookie context, e.g. to feed into a download manager) |
{$EXTEND_URL,http://example.com/index.php?foo=a&bar=b} | Add parameter(s) onto a URL, avoiding unreliable assumptions about how a URL is already structured (URL Schemes may cause a big diversity in the URLs Composr puts out). It puts ? or & before your parameter correctly based on an analysis of existing URL structure. It does not handle URL encoding of the appended parameter, which you should do first if applicable. |
{$URL_FOR_GET_FORM,someurl} | Strips out the query string parameters from a URL, so that this URL can be used as the action for a GET form. Symbol is paired with HIDDENS_FOR_GET_FORM |
{$HIDDENS_FOR_GET_FORM,someurl} | Takes the query string parameters of a URL and turns them into hidden form inputs, so that a GET form will relay them. Any further symbol parameters are of URL parameters to skip over (commonly done when you have input widgets for those same parameters). Symbol is paired with URL_FOR_GET_FORM |
{$FIND_SCRIPT} | Find the URL to a named Composr entry script (e.g. dload) |
{$FIND_SCRIPT_NOHTTP} | Find the URL to a named Composr entry script (e.g. dload), but as a relative URL to domain name root. This is useful for JavaScript because it makes the JavaScript portable able to run across multiple domains from a single cache pool (when you have zones on different domains) – and also so the cached JavaScript is compatible with both HTTPS and HTTP. |
{$MAKE_URL_ABSOLUTE,someurl} | Take what may be a relative URL (relative to site base URL), and make sure it is an absolute URL |
{$ENSURE_PROTOCOL_SUITABILITY,someurl} | Make sure a URL is safe to embed in the current page if the current page is HTTPS, e.g. by proxying a non-HTTPS URL |
{$PAGE_LINK,site:about} | Link to a page, using page-link syntax (e.g. "_SELF:pagename:type:1") |
{$SELF_URL,0,0,0,a=b} | Get URL to current screen. You don't need to give any parameters, but if you do: the first is whether to go to the website home page if you are at where you're at due to a form post, the second is whether to included posted parameters as parameters in the URL, the first is whether to avoid the URL Scheme facility, and further parameters are additional URL parameters. |
{$RUNNING_SCRIPT,index} | Find whether an entry script is running |
{$MATCH_KEY_MATCH,_WILD:downloads:browse} | Whether the given match-key matches the current URL |
{$ZONE} | The zone the user is in |
{$PAGE} | The page the user is in |
{$CANONICAL_URL} | Get the canonical URL (for search engines). You can also pass a parameter if you want to set the canonical URL. |
{$SELF_PAGE_LINK} | Get page-link to current screen, without any keep_* parameters. |
{$_GET,page} | Extract the requested script GET parameter |
{$QUERY_STRING} | Extract all requested script parameters (the 'query string', i.e. part of the URL after "?") |
{$FACILITATE_AJAX_BLOCK_CALL,block code,differing parameters} | This symbol generates a string parameter suitable for the Composr JavaScript $cms.callBlock function, which is used to make an AJAX call to load up a block and overwrite the contents of a specific div with it. Calling this symbol has the side-effects of triggering an include of Composr's AJAX code, and setting up a permission so that the server-side AJAX handler knows that the current session is authorised to load up this pattern of block. The symbol is best used by example -- see how it is currently used by code. |
{$ANCHOR,anchorname} | Place a named HTML anchor (intended for use from in Comcode) |
{$TUTORIAL_URL} | A tutorial URL, linking under the brand URL's docs zone |
{$PREVIEW_URL} | Find the URL to perform a preview for the form on the current screen |
Images
Symbol name / example | Purpose |
---|---|
{$IMG,bottom} | Find a named theme image code's URL (takes the theme image code). Note that this gets the image URL, it does not write the HTML out for an image element based upon it (you need to do that yourself). The URL returned is absolute. In JavaScript you should strip it back down with $util.srl, so the cached JavaScript is compatible with both HTTPS and HTTP (see {$FIND_SCRIPT_NOHTTP} and {$BASE_URL_NOHTTP}). |
{$IMG_MTIME,bottom} | Find the last-modification unix timestamp for a theme image. This is useful for adding a cache-busting parameter after an image URL and ?, e.g. <img src="{$IMG*,bottom}?{$IMG_MTIME%,bottom}" />. |
{$IMG_INLINE,bottom} | Find a named theme image code's data URL. It works the same as {$IMG,...} except the image data gets embedded directly. If there's more than 32kb of data, the normal URL will be used instead. |
{$IMG_WIDTH,bottom} | Find the width of the theme image/URL (particularly useful for making web pages render faster). Uses the persistent cache to remember values, if possible. |
{$IMG_HEIGHT,bottom} | Find the height of the theme image/URL (particularly useful for making web pages render faster). Uses the persistent cache to remember values, if possible. |
{$FAVICON} | Find the URL to the favicon. |
{$THUMBNAIL,http://example.com/pic.png,40x60,galleries} | Generate a thumbnail URL from another image URL |
{$CDN_FILTER,URL} | Take an absolute URL, under the main base URL's domain, and change it to work under the Content Delivery Network. Only use this if you know the particular URL you pass will be available via the CDN. |
{$METADATA_IMAGE_EXTRACT,CONTENT} | Scan some content and make the first suitable Open Graph image the active metadata image. If a metadata image has already been detected by Composr, this symbol will have no affect, unless a second parameter is passed and set to 1. |
Thumbnail generation
The {$THUMBNAIL} tag is actually much more sophisticated and powerful than described above. It's full syntax is as follows…Usage: {$THUMBNAIL,source_image,widthxheight,output_dir,filename,fallback_image,algorithm,where,background,only_make_smaller}
where:
- source_image is the URL to the full image
- widthxheight is the desired width/height for the thumbnail. For types (see below) of width, height, or crop, you can omit either the width or height to scale according to the aspect ratio of the source image (e.g. x20 for just a height, or 160x for just a width). If you specify both dimensions for crop or pad, the thumbnail will be cropped or padded to the exact dimensions regardless of aspect ratio. If no dimensions are specified, the default is the value of the thumb_width option, with height omitted.
- output_dir is the directory path to save the thumbnail (relative to the Composr base directory). The default is Composr's uploads directory.
- filename is the name of the thumbnail filename. If not provided, it will be automatically chosen based on the source_image. An articulation of the thumbnail settings will be prefixed to the filename in any case
- fallback_image is the URL to the image to use if no thumbnail could be generated. If not provided, the source_image will be used.
- algorithm is either:
- box for an image which should be scaled proportionally to fit into the given box dimensions, with no cropping or padding, meaning it may be an irregular size (the default)
- width for an image which is scaled to the given width dimension and a height in proportion to that
- height for an image which is scaled to the given height and a width in proportion to that
- crop for an image which has been scaled until one of its dimensions matches any of the provided dimensions, and the rest of the image has been cropped off.
- pad for an image which has been scaled proportionately until it completely fits within the given dimensions, and then padded out (padding will not be added if where is 'both' and background is 'none' -- instead, it will just make the output image dimensions smaller)
- pad_vert_crop_vert for an image where the horizontal axis is privileged; the vertical axis gets cropped and the horizontal gets padding, as necessary, to fit the given dimensions. The goal is to preserve the source image's proportions while filling the entire box.
- pad_horiz_crop_horiz for an image where the vertical axis is privileged; the horizontal axis gets cropped and the vertical gets padding, as necessary, to fit the given dimensions. The goal is to preserve the source image's proportions while filling the entire box.
- The where argument is not needed for box, width, nor height type thumbnails. For crop & pad types, this defines the anchor point for cropping / padding:
- both crops/pads around all edges; the default.
- start anchors to the top left corner; cropping and padding is done in the bottom right.
- end anchors to the bottom right corner; cropping and padding is done in the top left.
- start_if_vertical anchors to the top center; cropping and padding is done at the bottom.
- start_if_horizontal anchors to the left center; cropping and padding is done on the right side.
- end_if_vertical anchors to the bottom center; cropping and padding is done at the top.
- end_if_horizontal anchors to the right center; cropping and padding is done on the left side.
- For pad types, the background is used to pad the image. The following values are acceptable:
- an RGB hex code for a specific colour (optionally with alpha, i.e. RGBA)
- or, none for no padding (ie. the image dimensions are not those given, but will fit inside them)
- or, if the option is omitted for padded thumbnails, then the average colour of the image is calculated and used.
- only_make_smaller can be set to "1" if the image should not ever be made bigger than it already is. This parameter is ignored for crop and pad.
Composr configuration/status querying
Symbol name / example | Purpose |
---|---|
{$SITE_NAME} | The site name |
{$TIMEZONE} | The server timezone |
{$ZONE_HEADER_TEXT} | The header text of the current zone |
{$COPYRIGHT} | The site copyright |
{$STAFF_ADDRESS_PURE} | The staff address, without obfuscation |
{$STAFF_ADDRESS} | The obfuscated staff address |
{$DOMAIN} | The domain name of the site |
{$SITE_SCOPE} | The site scope |
{$FORUM_BASE_URL} | The forum base URL |
{$BASE_URL} | The base URL to the installation |
{$CUSTOM_BASE_URL} | The base URL to custom data in the installation (usually the same as BASE_URL) |
{$BASE_URL_NOHTTP} / {$CUSTOM_BASE_URL_NOHTTP} | The base URL to the installation, but just the path, no protocol or domain name. This is useful in JS files (which cache as strings, not Tempcode) because it doesn't cause JS security errors when HTTPS and HTTP variants of a site are both in action (the same JS files may be served for both HTTPS and HTTP). |
{$SSW} | Whether Sunday is the start of the week (Tempcode boolean) |
{$VALID_FILE_TYPES} | Get a comma-separated list of valid file types |
{$INLINE_STATS} | Whether to show view/download counts inside the public visible website (Tempcode boolean) |
{$SHOW_DOCS} | Whether documentation links are configured to be shown |
{$CONFIG_OPTION,optionname} | Get the value of a config option |
{$THEME_OPTION,optionname} | Get the value of a config option that can be overridden in a theme |
{$VALUE_OPTION,optionname} | Get the value of a hidden option/value |
{$ECOMMERCE_OPTION,optionname} | Get the value of a config option from the eCommerce system that supports having a separate value for live and testing stores |
{$BRAND_NAME} | The brand name, defaults to Composr |
{$BRAND_BASE_URL} | The brand URL, defaults to https://composr.app |
{$PARENTAL_CONSENT_REQUIRED} | Whether parental consent is configured to be required |
{$TAX_LABEL} | A label for identifying the tax system, in English either “VAT” or “Sales tax” |
{$TAX_NUMBER_LABEL} | A label for identifying the tax system, in English either “VAT” or “Sales tax” |
{$BUSINESS_ADDRESS} | The configured business address. Requires the eCommerce addon. |
{$LOGIN_LABEL} | The label for the username field when logging in (the label depends on how login options are configured, e.g. Username, E-mail address, Username / E-mail address) |
{$CNS} | Whether Conversr is being used (returns Tempcode boolean) |
{$VERSION_NUMBER} | Get the Composr version number |
{$VERSION} | The major version of Composr being used |
{$SESSION_COOKIE_NAME} | Get the name for the session cookie |
{$COOKIE_PATH} | Get the cookie save path |
{$COOKIE_DOMAIN} | Get the cookie save domain |
{$ADDON_INSTALLED,galleries} | Find whether an addon is installed (first parameter is the code-name of the addon) |
{$IS_MAINTAINED,some_code} | Find if a named feature is either maintained or not known. If a second parameter is given then that parameter will be output with a possible appended note. |
{$DEV_MODE} | Whether development mode is on (adds in extra errors, to pick up on coding standard violations) |
{$CSP_NONCE} | Get the CSP nonce |
{$CSP_NONCE_HTML} | Get the CSP nonce with html attribute (nonce="...") |
{$PUBLIC_CONFIG_OPTIONS_JSON} | Outputs all the config options that are marked public as JSON. Used by $cms.configOption(). |
{$FONTS} | A comma-separated list of fonts that have been configured |
The Feedback system
Symbol name / example | Purpose |
---|---|
{$COMMENT_COUNT,downloads,3} | Find the number of comments made for a resource (first parameter is the resource type code, second parameter is the resource ID) |
{$RATING,downloads,3} | Show a content type's rating. The first parameter is the content-type's code (usually the page name it's viewed from, e.g. downloads) and the second parameter is the ID for the resource. There's an optional third parameter of resource submitter, an optional fourth parameter as the content URL, an optional fifth parameter as the resource title, and an optional sixth parameter as the rating template to use (defaults to showing the raw rating value). Any optional parameters may be left blank to get to the next parameter. |
{$NUM_RATINGS,downloads,3} | Find the number of users who have rated something. |
{$SHOW_RATINGS,downloads,3,100} | Show the last 100 ratings on something. |
{$ALREADY_RATED,downloads,3} | Find if the current user has already rated something. |
{$FORM_TO_EMAIL_URL,pagename} | Used to cleanly produce a URL to the form_to_mail script. Documented in the Feedback and user interaction tutorial. |
ID conversion
Symbol name / example | Purpose |
---|---|
{$FIND_ID_VIA_URL_MONIKER,<content-type>,<url-moniker>} | Finds the ID for a given content type's URL moniker |
{$FIND_URL_MONIKER_VIA_ID,<page>,<type>,<id>} | Finds the URL moniker for an item of content's type/ID |
{$FIND_GUID_VIA_ID,<resource-type>,<resource-id>} | Find the resource GUID from the resource ID |
{$FIND_COMMANDR_FS_FILENAME_VIA_ID,<resource-type>,<resource-id>} | Find the Commandr-fs (repository) filename from the resource ID. There is an optional third parameter, which may be set to 1 if you want the resource sub-path to also be included. Sub-paths are relative to the repository-fs path for the resource-type. |
{$FIND_LABEL_VIA_ID,<resource-type>,<resource-id>} | Find the resource label from the resource ID |
{$FIND_ID_VIA_LABEL,<resource-type>,<label>} | Find the resource ID from the resource label |
{$FIND_ID_VIA_GUID,<guid>} | Find the resource ID from the resource GUID. It is assumed you as the programmer already know the resource-type. |
{$FIND_ID_VIA_COMMANDR_FS_FILENAME,<resource-type>,<filename>} | Find the resource ID from the Commandr-fs (repository) filename |
Specific/advanced Composr interfacing (non-configuration, non-environment)
Symbol name / example | Purpose |
---|---|
{$HAS_FORUM,General Chat} | Whether a forum is available (returns Tempcode boolean) |
{$ATTACHMENT_DOWNLOADS,3} | Find how many downloads an attachment has had (first parameter is the ID number of an attachment) |
{$SUPPORTS_FRACTIONAL_EDITABLE,cms:cms_example,1} | Whether some content has permissions to be editable inline, via the FRACTIONAL_EDITABLE directive. Described in the [page="_SEARCH:sup_inline_editing"]Inline editing in Composr[/page] tutorial. |
{$DISPLAY_CONCEPT,concept_name} | Displays a link to a concept, if it has been saved already from a concept table. |
{$SET_TUTORIAL_LINK,tutorial_id,page-link} | Creates a tutorial link for the given tutorial_id to the given page-link. Needs doing in Tempcode because the Comcode parser doesn't know the target page for Comcode being parsed. |
{$CPF_LIST,<field-title>} | Find all the possible values for a Custom Profile Field in a loop-iterable string |
{$AUTHOR_MEMBER,author_name} | Find the member ID associated with an author, or guest ID if none |
{$STOCK_CHECK,Product id} | Get the stock count for a shopping catalogue item |
{$VIEWS,download_downloads,download_views,3} | Show how many views a content type has had. The first parameter is the table to read from, the second parameter is the name of the field (it must contain 'views' -- the code will not allow arbitrary field calling for security reasons) the third parameter is the ID for the resource. |
{$REVIEW_STATUS,download,3} | Show the periodic content review status for the given content, if configured for the content and set as publicly visible. |
{$AWARD_ID,2} | Find the content ID assigned to the given award |
{$NOTIFICATIONS_ENABLED,download,3} | Find whether notifications are enabled for something |
{$NOTIFICATIONS_AVAILABLE,download} | Find whether notifications are allowed for this notification code (i.e. not locked down) |
{$HONEYPOT_LINK} | If a Project Honeypot (maintenance status) script is installed, this will insert a link to it, using a different method for different page names to increase the likeliness of a bot snag. |
{$INSERT_FORM_POST_SECURITY} | If spammer blackholes are enabled, this inserts a field into a form to create the blackhole. Blackholes allow automatic detection and banning of would-be spammers. Additionally, the CSRF-prevention security token is injected via this symbol. |
{$GALLERY_VIDEO_FOR_URL,uploads/galleries/foo.mov} | Get the gallery video ID for a named URL, importing to a new video if needed. This is useful for managing documentation out of Git, referencing videos that will then be synchronised with YouTube upon first reference. You'll likely use this symbol to pass as a parameter to the main_content block. |
{$GENERATE_CAPTCHA} | Force a new CAPTCHA code to generate. |
{$STAFF_TOOLTIPS_URL_PATTERNS_JSON} | JSON object of staff URL patterns to apply Comcode tooltips to. |
{$CONTENT_COUNT,content_type,selectcode_string,filtercode_string} | Find out how many content items match the given Selectcode and Filtercode strings. The content_type is a standard code representing a content_meta_aware hook filename (without [tt].php[/tt]). If the Selectcode/Filtercode strings are omitted or blank then counting happens broadly. |
{$FILE_EXISTS,file_path} | Find if the given file path exists (should be a path relative to the base directory). |
{$GEOCODE_ENABLED} | Find whether at least one Geocoding service is set up and can be used. |
Tracking and events
Symbol name / example | Purpose |
---|---|
{$SET_TRACKING_CODE,a} | Set a tracking code as being active. |
{$SPLIT_TEST,a,b} | Pick a tracking code as being active from the provided parameters ([tt]a[/tt] or [tt]b[/tt] in our example). If one of these tracking codes is already active in the session then it will be re-used. The symbol will return the picked tracking code. |
{$HAS_TRACKING_CODE,a} | Find whether a tracking code is active in the session. |
{$LOG_STATS_EVENT,event} | Log a stats event as having happened. This is useful if the successful display of some template evidences some important stats event has happened. You can create whatever event codes you like. |
{$STATS_TRACK_URL,URL,event} | Track clicks to a URL, with an optional event parameter as well. This works via a redirect: the user is sent to a Composr script first, which logs the click/event, and that script redirects to the destination URL. |
Logic
Note that all logic symbols return Tempcode boolean values (except ?). This makes them suitable for nesting with each other, or using with the 'IF' directive.Understanding of these symbols requires an understanding of basic boolean operations but they are fairly intuitive (e.g. 'AND' will return true if all its parameters are true).
Symbol name / example | Purpose |
---|---|
{$EQ,a,b} | Test for string equality (pass in any number of strings to check they are all the same) |
{$NEQ,a,b} | Test for string inequality (this is the same as {$NOT,{$EQ,...}}) |
{$NOT,1} | Boolean NOT (pass in one Tempcode boolean to get the opposite boolean out) |
{$OR,1,1} | Boolean OR (pass in any number of Tempcode booleans to check that one is true) |
{$NOR,1,1} | Boolean NOR (this is the same as {$NOT,{$OR,...}}). NOR means "Neither" |
{$XOR,1,1} | Boolean XOR (pass in two Tempcode booleans to check that just one of them is true but not both of them). XOR means "one or the other but not both" |
{$AND,1,1} | Boolean AND (pass in any number of Tempcode booleans to check they are all true) |
{$NAND,1,1} | Boolean NAND (this is the same as {$NOT,{$AND,...}}). NAND means "Not both" |
{$LT,1,2} | Test for numerical less-than inequality (pass in a Tempcode number) |
{$GT,1,2} | Test for numerical greater-than inequality (pass in a Tempcode number) |
{$IS_EMPTY,this obviously is not blank} | Find whether a string is blank |
{$IS_NON_EMPTY,this obviously is not blank} | Find whether a string is not blank |
{$?,1,shows if true,shows if not true} |
Do an inline IF test, outputting the second parameter if the first evaluates to true and the third (optional parameter) if it does not {$?,0,yes,no} → no {$?,1,yes,no} → yes {$?,0,yes} → (blank) {$?,1,yes} → yes |
{$ATTR_DEFAULTED,parameter,somevalue,defaultvalue} | This is for outputting HTML parameters only where they differ from the browser's inbuilt default (hence saving some bandwidth). It is a compact equivalent of {$?,{$NEQ,somevalue,defaultvalue}, parameter="somevalue"}. |
Arithmetic
Symbol name / example | Purpose |
---|---|
{$NEGATE,3} | Negate a number |
{$MULT,3,3} | Multiply two numbers |
{$ROUND,3.2} | Round a number |
{$MAX,3,4} | Find the maximum between two numbers |
{$MIN,3,4} | Find the minimum between two numbers |
{$MOD,3} | Make the given number positive (e.g. -3 becomes 3, 3 becomes 3) |
{$REM,10,3} | Find the remainder if the first number is divided by the second |
{$DIV,10,3} | Divide two numbers to get an integer result |
{$DIV_CEIL,10,3} | Divide two numbers to get an integer result, but round up |
{$DIV_FLOAT,10,3} | Do a division to get a decimal result |
{$SUBTRACT,4,3} | Perform a subtraction |
{$ADD,4,3} | Add two numbers |
String manipulation
Symbol name / example | Purpose |
---|---|
{$REPLACE,exemplar,something,this is exemplar} | Do a string replace (three parameters: what's being replaced, what's being replaced with, what's being replaced in) |
{$AT,something,3} | Extract a string character (first parameter is the string, second parameter is the index of the character to get counting from 0) |
{$STRPOS,something,hi} | Find the position of a string substring (first parameter is the search string, second parameter is the substring, returns Tempcode number) |
{$STARTS_WITH,something,hi} | Find whether a string starts with a substring (first parameter is the search string, second parameter is the substring) |
{$ENDS_WITH,something,hi} | Find whether a string ends with a substring (first parameter is the search string, second parameter is the substring) |
{$IN_STR,something,in} | Find whether a substring is in a string (first parameter is the search string, second parameter is the substring, returns Tempcode boolean) |
{$SUBSTR_COUNT,abacus,a} | Find how many times a substring appears (first parameter is the search string, second parameter is the substring, returns Tempcode number) |
{$SUBSTR,something,2,2} | Extract a string substring (first parameter is the string, second parameter is the index of where to extract from, third parameter is the extraction length) |
{$LENGTH,something} | Find the length of a string (give it a string, returns a Tempcode number) |
{$PAD_LEFT,12,4,0} | Pad something out on the left. This example produces 0012 |
{$PAD_RIGHT,12,4,0} | Pad something out on the right. This example produces 1200 |
{$WCASE,A b C} | Convert string to word case |
{$LCASE,A b C} | Convert string to lower case |
{$UCASE,A b C} | Convert string to upper case |
{$WORDWRAP,blah blah blah,4,<br />,1} | Word-wrap a string (first parameter is the string, second parameter is the maximum line length, optional third parameter is the divider string which defaults to an HTML line-break, optional fourth parameter is a binary value specifying whether to force hard cuts) |
{$PREG_MATCH,\d,1 2 3} | See if something matches a regular expression (first parameter is the regexp, second parameter is the subject string) |
{$PREG_REPLACE,\d,a,1 2 3} | Perform a regular expression replace (first parameter is the regexp, second parameter is the replacement string, third parameter is the subject string) |
{$COMMA_LIST_REVERSE,a\,b\,c} | Reverse a comma-separated list |
{$COMMA_LIST_GET,a=1\,b=2,a} | Find a value from a comma-separated list. |
{$COMMA_LIST_SET,a=1\,b=2,a,2} | Set a value in a comma-separated list. |
{$COMMA_LIST_FROM_BREADCRUMBS} | Convert breadcrumbs to a comma-separated list. |
{$COMMA_LIST_POP,a\,b\,c} | Remove the last element from a comma-separated list and throw that element away. |
{$COMMA_LIST_SHIFT,a\,b\,c} | Remove the first element from a comma-separated list and throw that element away. |
{$COMMA_LIST_PUSH,a\,b\,c,d} | Add an element to the end of a comma-separated list. |
{$COMMA_LIST_UNSHIFT,b\,c\,d,a} | Add an element to the start of a comma-separated list. |
{$COMMA_LIST_NICIFY,a\,b\,c} | Put a space after commas in a comma-separated list. |
{$INTEGER_FORMAT,1234} | Make a number (integer) look nice, with commas etc (takes a Tempcode number) |
{$FLOAT_FORMAT,1234.5678} | Make a decimal number look nice, with commas etc, to 2 decimal places (takes a Tempcode number) |
{$FLOAT_UNFORMAT,1234.56} | Make a decimal number that look nice with commas etc, into a rawer representation that isn't language-pack-specific |
{$TEMPCODE,{$MEMBER}} | Evaluates the given parameter as Tempcode (takes a string). This is useful for very rare situations where you want to write in symbols as parameters to Comcode tags where the parameter is treated as a plain-string. This is only useful in Comcode, when typing Tempcode you can nest Tempcode constructs almost however you like. |
{$COMCODE,[b]Comcode[/b],0} | Evaluates the given parameter as Comcode (takes a string). This is useful in conjunction with the above (TEMPCODE), as anything passed into a symbol won't be evaluated as Comcode. If the second parameter is omitted or set to 1, then Comcode will be parsed with administrative permissions – be careful about that, as you don't want to process user content like that. |
{$URLDECODE,a%20b} | Remove URL encoding |
{$SMART_LINK_STRIP,hello,3} | Remove links from the given HTML, if the member ID does not have a positive post count (a temporary measure to disincentivise spammers) |
{$JSON_ENCODE,{MY_ARRAY}} | Encodes the provided parameter into JSON. |
Tempcode variables
You can store and retrieve values in Tempcode variables. These work across templates, and also work in any-order due to the Composr Tempcode pre-processor (i.e. something can be SET after the GET for it).Symbol name / example | Purpose |
---|---|
{$ISSET,test} | Find whether a Tempcode variable is set (give it the name of a variable, returns Tempcode boolean) |
{$INIT,test,1} | Initialise a Tempcode variable to a value, but only if it is not yet set (give it the name of a variable, and a value, returns nothing) |
{$SET,test,1} | Set a Tempcode variable to a value (give it the name of a variable, and a value, returns nothing). Bear in mind that the Composr Tempcode-preprocessor will likely cause your code to run once in every code branch before it outputs (meaning even code inside IF directives that never are true will still pre-process), and once again as it outputs. So always reinitialise your variables in your template to make sure they are not dirty from the pre-processing stage. This behaviour may seem strange, but it is necessary for performance, comprehensive caching, and reasons of Composr needing conditionless output foresight. |
{$GET,test} | Get the value of a Tempcode variable (give it the name of a variable, returns the value). If you set the 2nd parameter to "1" then the Tempcode cache will be reset for the value being received (allowing it to reevaluate the value, i.e. operate fully dynamically). This must be set on all GET calls to the same value, otherwise the Tempcode may be flattened prematurely. The - must be used to do the initial SET. |
{$THEMEWIZARD_COLOR,#RRGGBB,name,equation} | Sets a Theme Wizard colour that can be retrieved from name as a Tempcode variable. The equation is actually ignored during Tempcode evaluation but is picked up by the Theme Wizard. |
{$COLOR_RGBA,#RRGGBB,name,fraction} | Take a Theme Wizard colour variable and create a CSS RGBA string with a given opacity fraction. |
{$COLOR_LIGHTEN,#RRGGBB,name,percentage} | Take a Theme Wizard colour variable and lighten it by a given percentage. |
{$COLOR_DARKEN,#RRGGBB,name,percentage} | Take a Theme Wizard colour variable and darken it by a given percentage. |
{$CSS_MODE,name,from-to,mobileModeBehaviour} | Creates a CSS mode for the CSS_MODE directive. They work both as responsive design breakpoints, and rule output control for mobile mode. from and to are numeric, or to can also be infinity. mobileModeBehaviour is either mobileModeMedia (use @media rules) or mobileModeKeep (use @media rules on desktop mode, output on mobile mode) or mobileModeDiscard (use @media rules on desktop mode, discard on mobile mode) |
{$INC,test} | Increment a Tempcode variable (give it the name of a variable, returns nothing) |
{$DEC,test} | Decrement a Tempcode variable (give it the name of a variable, returns nothing) |
Catalogues
Symbol name / example | Purpose |
---|---|
{$CATALOGUE_ENTRY_BACKREFS,123} | Get a comma-separated list of IDs of catalogue entries that reference the given catalogue entry. A second parameter may be given, which is a limit on how many to return. A third parameter may be set as the name of a content type if the backrefs should be resolved to linked content entries (for the case where the linkage is via custom fields rather than a pure catalogue). A fourth parameter of the rating type code may be given if sort-by-rating is needed (highest rated first). |
{$CATALOGUE_ENTRY_FIELD_VALUE,123,0} | Get the value of a field in a specific catalogue entry (example would be 1st field in entry #123). |
{$CATALOGUE_ENTRY_FIELD_VALUE_PLAIN,123,0} | As per CATALOGUE_ENTRY_FIELD_VALUE |
{$CATALOGUE_ENTRY_FOR,download,3} | Get the ID of the auto-maintained catalogue entry bound to the given content entry, i.e. where the content entries custom fields are stored. This can then be used with the CATALOGUE_ENTRY_FIELD_VALUE symbol (above) or the CATALOGUE_ENTRY_ALL_FIELD_VALUES symbol (below). |
{$CATALOGUE_ENTRY_ALL_FIELD_VALUES,123,0,PAGE} | Show a field-map view of all fields in the entry. You can also pass in a second param with the value '1' if you want raw field rows, rather than a table (useful for adding field-map data into an existing table). The third parameter can be PAGE (default), SEARCH, or CATEGORY and represents the set of fields read. |
Directives
Note that you cannot use directives for symbol parameters because directives control code flow rather than inline calculations. The way Tempcode logic is internally structured cannot parse/hold it. You can almost always use the <kbd>?</kbd> symbol to guide inline calculations instead.Directive name | Purpose |
---|---|
BOX |
These allow the 'standard box' layout convention to be used without duplicating a lot of HTML in different templates. CSS could never provide this itself, as the box 'styling' actually involves a large chunk of complex structure.
The parameters to the directive are (all may be blank or left out):
|
INCLUDE |
Include a template in another and pass parameters (this makes a template very much like a function in a conventional programming language). The parameters to the directive are (all may be blank or left out):
The parameters are written inside the directive, one per line in a very simple text syntax, KEY=VALUE (e.g. FOO={BAR}), where the actual parameter values are evaluated into text prior to the INCLUDE directive being evaluated. This has the result of anything after a linebreak being lost, unless you make use of the directives support for escaped line-breaks (e.g. FOO={BAR^}). There are a range of special substitutions that can also be used, again one per line in a text syntax.
Note that the CSS substitutions work by regular expressions that should work in practice, but they are not perfect to the CSS spec. If you try to include a template into itself, Composr will include the default version of that template in. |
WHILE | Do a loop until the Tempcode boolean used as the directive parameter evaluates to false. |
LOOP |
Do a loop over an array. This is not used much in default templates and only works if arrays are actually what is passed into the template (unless the third operating mode is used, see below).
It operates in 3 possible ways:
|
IF_PASSED/IF_NON_PASSED | Find if a named parameter was passed (Do not encase the parameter with {}) |
IF_PASSED_AND_TRUE/IF_NON_PASSED_OR_FALSE | Find if a named parameter was passed and its truth state (useful for robust optional boolean parameters that default to false) |
IF_EMPTY/IF_NON_EMPTY | Find if some Tempcode evaluates to empty. This is extremely useful, as it allows you to, for example, not show a table if it has no rows passed in. From a programming point of view, it allows us to avoid making new templates and improve accessibility compliance. |
IF_ARRAY_EMPTY/IF_ARRAY_NON_EMPTY | Find if an array is empty. |
IF |
This simply tests a condition. This condition is often generated by nesting symbols together. For example, {+START,IF,{$EQ,{A},{B}}}...{+END} There is no direct support for an else kind of syntax, but you can do it indirectly like: Code{$SET,check,{$EQ,{A},{B}}} |
OF | This is a non-wrapping directive that extracts a string from an array (1st directive parameter) at the specified array index (2nd directive parameter). |
IMPLODE | This is a non-wrapping directive that turns an array into a string by placing a separator between each element. |
COUNT | Find the number of elements in an array. |
SET | Like the SET symbol, but sets with surrounded block of code rather than the second parameter. |
RECONTEXTUALISE_IDS | Prefixes all the IDs contained within (prefix is given as the first parameter). Reassociates form labels correctly. This directive is useful if you need to have the same form on an HTML page more than once. |
PARAM_INFO | Shows all parameters in the current scope. Very useful for debugging what goes into a template. Use without and directive contents like, {+START,PARAM_INFO}{+END} |
FRACTIONAL_EDITABLE,The [i]Title[/i],title,cms:cms_example,1,1,1 | Used to make a string of some content editable inline. Described in the [page="_SEARCH:sup_inline_editing"]Inline editing in Composr[/page] tutorial. |
IN_ARRAY | See if something is contained in an array, returning a boolean. This only works with arrays passed into templates (not something like a delimited-list). This is rarely used because it can't be embedded easily within wider expressions. Usually you will use IF_IN_ARRAY. |
IF_IN_ARRAY,PASSED_IN_ARRAY,example | Output something if something is in an array. This only works with arrays passed into templates (not something like a delimited-list). First parameter is the name of an array, second parameter is a string to check for. |
IF_NOT_IN_ARRAY,PASSED_IN_ARRAY,example | Opposite of IF_IN_ARRAY |
NO_PREPROCESS | Don't do any pre-processing under this directive. This improves performance for complex Tempcode trees (especially for conditionally displayed blocks), but it does mean that things like CSS and JavaScript includes that are required by blocks may not be detected. |
CASES | Show different output based on the value of something |
COMMENT | A comment (i.e. does nothing) |
CSS_MODE | Takes a parameter which will usually be either mobile or desktop. Basically on mobile mode it only outputs the directive content for [tt]mobile[/tt], while on desktop mode it will output using media rules (i.e. responsive design). That said, the codes are actually configurable/extendable in . |
NO_PREPROCESSING | Avoid preprocessing of anything inside the directive. This is needed for complex cases such as when you need to do heavy optimisation of unusual code paths, or unusual GET/SET situations with shared variables which may not always exist (and need to be evaluated therefore in a strictly linear way). |
MAKE_MOBILE | On mobile mode perform some basic conversions on the enclosed HTML to make it mobile-friendly. Covered in the [page="_SEARCH:tut_mobile"]Mobile design[/page] tutorial. |
HTML_COMPRESS | Apply HTML compression techniques to an area of the output. Covered in the [page="_SEARCH:tut_performance"]Optimising Performance[/page] tutorial. |
CDN_FILTER | Mass-apply the CDN_FILTER symbol to appropriate URLs found inside the directive. Covered in the [page="_SEARCH:tut_performance"]Optimising Performance[/page] tutorial. |
TRIM | Trim the contents of the directive. Only trims strict character white-space, not HTML line-breaks. Particularly useful to remove white-space around the contents of anchor tags. |
Directive examples
The most important directives are:- IF_NON_EMPTY
- IF_EMPTY
- IF
IF_NON_EMPTY
This directive is commonly used when a box or explanation needs placing around something, unless that something happens to be blank (empty).For example, the following is a fairly typical thing to see in a template:
The IF_NON_EMPTY directive evaluates {DOWNLOADS}, to see if it is blank. If it is not blank, the contents of the directive is output, otherwise nothing happens.
As you can see from this example, we need to check for emptiness so we don't show a boxed message about downloads that refers to nothingness.
IF_EMPTY
An alternative approach to the above example is to include a special message upon emptiness, rather than skipping over. We might do this if the content being displayed is critical and thus the emptiness must be explicitly acknowledged:Note here how we are displaying {DOWNLOADS} even if it is empty. Obviously if it is empty, nothing would display, so we can get away with it. If we were being pedantic we might have wrote the following:
It's often useful to be a bit clever with the emptiness-checking directives. For example:
In this example, the directive checks if the {DOWNLOADS}{IMAGES} is blank, which is exactly the same as checking if they are both blank (because blank next to blank is still just blank).
IF
The 'IF' directive allows particular complex calculations to be done. For a simple example, we can replicate the trick in the last example in a more formal way:This checks to see if "DOWNLOADS is empty and IMAGES is empty".
Tempcode uses what is called a "prefix notation", and is similar to the way you write mathematical functions. For example, in common maths:
Code
f(a,b)
In the similar Tempcode notation you would write (assuming 'A' and 'B' are template parameters and 'F' is a real Tempcode symbol):
Code
{$F,{A},{B}}
Here's another 'IF' directive showing a more complex computation:
Background: a unix timestamp is a common measurement of time on computers -- it represents the number of seconds since 1970 and because of its nature as a simple decimal number, is very useful for performing arithmetic.
This example checks to see if ADD_DATE_RAW is less than the current unix timestamp minus 86400. 86400 is the number of seconds in a day, so in other words the example checks to see if ADD_DATE_RAW is at least a day in the past. Because ADD_DATE_RAW is often passed into templates that display content, it checks to see if the content is at least a day old.
I threw {$SITE_NAME} into the example just to demonstrate symbols are not only for use in IF directives -- this one is being used to perform a simple placement of the website name. All symbols do is compute results, so those results might be used for further computations as parameters to computational symbols (such as 'SUBTRACT'), or they might be passed into a directive, or they might be simply output. It merely depends on where they are placed.
Tempcode is extremely powerful, and hopefully now you can see how symbols, directives, and parameters, can come together to allow great things to happen!
See tempcode_test.txt for more examples on how to use symbols and directives.
CASES
Code
Capital city:
{+START,CASES,{COUNTRY}}
UK=London
Ireland=Dublin
=Unknown
{+END}
Based on the value of "Country", a different value would be shown. We have coded cases for the UK and Ireland, and anything else would default to "Unknown".
Be wary that you can't have multi-line strings for the case sections. This includes not having multi-lines within any of the Tempcode parameters/expressions.
Mode #1 is substring matching:
Code
Healthiness:
{+START,CASES,{FOOD_ITEM},1}
Cake=Unhealthy
Pie=Unhealthy
Salad=Healthy
=Unknown
{+END}
Mode #2 is regular expression matching:
Code
Head of state:
{+START,CASES,{COUNTRY},2}
^(Canada|Australia|United Kingdom)$=King/Queen
^USA$=POTUS
=Unknown
{+END}
Encapsulation
You can encapsulate Tempcode within comments of other languages, in order to not break editor syntax highlighting, and so WYSIWYG editors don't corrupt the code.Examples…
HTML comments…
Code (HTML)
Example
<!-- {+END} -->
CSS comments…
Code (CSS)
Example
/* {+END} */
HTML attributes…
Detailed worked examples
This section will provide real-world examples of using Tempcode. It goes into a minimal amount of PHP programming to provide a context for using a new template file and a context as to how Comcode pages, blocks, and templates, hold together. It explains things in terms of direct file editing rather than editing using the forms within Composr.If you are not comfortable with creating new code files you may want to glance over those parts. Ordinary themers would normally work by editing existing template files, or by placing Tempcode directly onto Comcode pages.
Creating a new block
Lets start by adding a new sample block to our front page so that we can test different examples of Tempcode. Go to the sources_custom/blocks folder and create and add a new empty file named main_first_block.php.Now lets add something to our block file. Edit main_first_block.php using your favorite text editor and add the following:
Code (PHP)
class Block_main_first_block
{
function run()
{
return do_template('BLOCK_MAIN_FIRST_BLOCK',array());
}
}
In this code we are simply creating a new class for our block and then defining the standard run() method which is executed when the block is invoked. We are calling a template file BLOCK_MAIN_FIRST_BLOCK.tpl in the run() method using the do_template() function. This tells the system to use this template file for our block. Our next step is creating a template file for the block.
Creating a template file
Go to the themes/default folder. There you should find two main templates folder templates and templates_custom. The main templates folder has all the predefined templates which the system is using already (†) so we don't have to make any changes there. The templates_custom folder will have all the user defined templates or the customised templates, so our template file will go there.Create a new blank file BLOCK_MAIN_FIRST_BLOCK.tpl and save it in to templates_custom. .tpl is the default extension we give to template files.
† Actually this isn't quite true. The css[_custom], javascript[_custom] and text[_custom] folders also hold templates. Even CSS files are handled as templates in Composr.
Adding the block to front page
Now that we have the block and template file ready, lets add the block to our front page so that we can test the examples. To add a block to the front page we will have to make the changes in the Comcode file start.txt which contains all the blocks which show up on the front page.start.txt file is located in pages/comcode_custom/EN (the same rule as templates applies here as well, i.e. the customised Comcode files should go in to _custom folder).
Edit start.txt file using your text editor, and add this on the end:
Code
[box="first block"][block]main_first_block[/block][/box]
This Comcode adds the block to our front page.
The box defines the outer section of the block and the string parameter passed to it ("first block") will be placed in the title of our box. We could have instead done the box inside the template using Tempcode or direct HTML if we had chosen to, but we wanted to mix some extra Comcode in with our example too.
The block tag includes our new block. Within the block tags we have provided the name of our new block, main_first_block.
If you go to your front page now you should see that a new box has been added with the title "first block" on the top. The box is empty right now as we are yet to add any content to the [block's] template file,
Now that we have a block set up on the front page, we can Test some Tempcode examples here by simply adding code to our template file (BLOCK_MAIN_FIRST_BLOCK.tpl).
Let's proceed to our first example…
Set randomisation example
This example demonstrates how a built-in Tempcode construct, the SET_RAND symbol, can be used to randomly make a selection from given options.Go ahead and paste the following example code into our BLOCK_MAIN_FIRST_BLOCK.tpl file and reload the front page to see the results.
(Caching should not be an issue as our test block has not defined any block caching, and (assume you haven't disabled it) the smart cache should detect the template has changed.)
This would resolve to some HTML such as:
Number randomisation example
In this example we use the symbol RAND to pick a random number between 0 and 3 and the number. This number will then be passed to an IF directive that checks if the number is less than 1 using the LT symbol. Go ahead and try this in the template file to see the results.Obfuscation example
Tempcode is also equipped with security features such as obfuscating an e-mail, getting an obfuscated mailto: string which makes it hard for e-mail scavengers to read it -- hence preventing spam.Code (HTML)
I want to let people {$OBFUSCATE,mailto:[email protected]}, but I don't want spam so I will confuse spam-bots.
</p>
Truncation example
The TRUNCATE_LEFT symbol can be used to trim data from the left, the TRUNCATE_RIGHT symbol to do the same from right, and the TRUNCATE_SPREAD symbol to keep an equal left/right portion.All the three functions have the same parameter order, which is as follows:
Code
{$TRUNCATE_LEFT, data, truncation length, optional binary value to show a tool tip, optional binary value for whether the input text is already in HTML format}
Match-key example
We can use that to show a specific message only if a match-key is satisfied.A match-key is basically the same thing as a page-link. The only difference is that a match-key is used for matching and will also match any page-links with additional parameters not mentioned in the match-key -- i.e. the match is performed against the parameters in the match-key, all other parameters are ignored. As you are probably already comfortable with the term "page-link", we'll use that henceforth.
You can test this next example in the DOWNLOAD_CATEGORY_SCREEN.tpl file:
This is an alternative way of achieving the same result as above. We perform a string equality (using the EQ symbol) on the id parameter; if it is equal then the message will be displayed.
User-agent detection example
It's sometimes useful to know which browser is being used by the user to view the web page. We might have to make some tweaks specifically for browsers like Internet Explorer to ensure cross-browser compatibility -- or perhaps we want to give out messages to users to tell them to upgrade their browsers. Ideally we would never have to do this, but the world of web browsers is kind of the wild-west, and things are always advancing and changing.Admin check example
This example shows how we could display messages or alerts specifically for admins.Group membership example
This functionality is similar to the above IS_ADMIN, but it works by usergroup. If the member belongs to any of usergroups 1, 3, 4 or 5, then the message will be displayed.(here we used Selectcode to show how we can do a range)
Guest check example
This example shows different content to guests and non-guests:Thumbnail example
This example is dynamically changing the image resolution of your avatar, using the THUMBNAIL symbol and the AVATAR symbol. The second parameter of the THUMBNAIL symbol defines the resolution we are generating.Code (HTML)
Zebra striping example
This example shows some zebra striping, within a set of boxes put out by a loop.We can use loops within Tempcode using the LOOP directive, and the loop variable can be fetched within the loop using the _loop_var parameter.
This example is not about loops; we just use loops as a way of putting out multiple boxes -- really we are trying to show how zebra striping can work. Zebra striping can also work between multiple attached instances of the same template, which is a far more common example, but would have been a bit harder for us to demonstrate via sample code.
In this example, it loops from A to I and in the loop it uses the CYCLE symbol to go through the parameters passed to it (two colours) in a sequence. The first loop iteration will result in a div element with a background property set to the first value (i.e #EEE) and _loop_var will display the current loop value for that (i.e. A). Then it proceeds through the loop, but the cycle is repeating between just two values (our zebra stripes) even though the loop goes on for nine values.
GUIDs
There is a design issue that comes to us when we design template structure… do we re-use templates so that editing is easier, load is decreased, and consistency is raised; or do we allow maximum customisation of different aspects of the system by not re-using templates?We have tended to stick to a middle ground between these extremes, and re-used templates when the usage pattern was almost identical. For example, almost all of Composr uses the same form field templates, but Wiki+ posts use different templates to forum posts. However, there are still places where we re-use templates in situations that sites may wish to develop in separate directions.
The solution to this is to make use of the GUID each template usage is given when it is used.
Each do_template call in Composr, which loads up a template, passes in a parameter, _GUID. The GUIDs may then be used along with tempcode directives to control what the template outputs.
The template editor has special support for the GUIDs, showing what GUIDs a template is used with and providing links to view the code associated with each GUID. It also provides a feature to automatically insert an 'IF' directive that differentiates against one of the GUIDs to provide a place to put output that will only be shown for it.
If you enter the template editor from the 'Template tree' screen then you will be told the GUID that was used by the node in the tree that you selected.
Concepts
- Symbol
- A special element that may be inserted into
- Parameter
- A parameter to a template; only parameters that the code calling the template supports may be used
- Directive
- A tool used to surround an area of a template between a START and an END, to apply something to it (such as only using it conditionally)
- Variable
- A named piece of memory used by Tempcode symbols that manipulate variables, or informally some internal other piece of Composr memory that Tempcode has a way of accessing
- Construct
- A Tempcode symbol, parameter, or language reference
See also
- Guide to web technologies (including HTML, CSS, and JavaScript)
- Releasing a theme
- Themeing your site
- Composr site structure
- Code Book, contents and introduction
Feedback
Have a suggestion? Report an issue on the tracker.