Customizing SurgeMail template files

# Customising surgemail web templates

SurgeMail web template files (for NetAuth and SurgePlus) can be customized in a similar way to WebMail template files to allow you to change the contents or style of any of the web interface pages.
SurgeMail web templates use a similar (but not identical) template parsing system to that of WebMail (see WebMail template customization documentation)

## Contents

- Introduction
- SurgeMail Style Notes
- Variables
- Comments
- Including pages within other pages
- Functions
- Conditional Statements (if, else, endif, etc)
- Repeating sections
- Variables available in all pages
- Caching
- Miscellaneous Notes
- Complete Syntax Reference
- Complete Function Reference

## Introduction

Each web page a user views when using SurgeMail is generated from a template page that is stored in the web directory within the SurgeMail installation directory. To find which source file a page you are viewing is generated from, view the page source. There will be a comment at the start with the source filename. (you can prevent source names appearing in output pages using the g_web_hide_source_names setting). Each template page is made up of standard html text, with the addition of a variable reference scheme to allow the content of the pages to change depending on what the user does.

## Surgemail Style Notes

If you are just wanting to change the overall look and feel of a SurgeMail web interface then you may just want to change some of the standard css values specified in surgemail.css in the SurgeMail web directory.
All Surgemail admin, SurgePlus, and NetAuth pages include style.htm at the top of the output pages. This page itself includes references to the default surgemail.css and surgemail.js files.

## Variables

Each variable is referenced by surrounding the name of the variable with double bars (||). For example, on the SurgePlus page that appears at the top of all pages the user sees while using SurgePlus (surgeplus_web_top.htm) something similar to the following text appears:

    ||user_field_full_name|| (||user_email||)

Here, the font tags are standard html font tags and the text ||user_field_full_name|| gets replaced by the users full name, and the text ||user_email|| gets replaced by the users email address. For example, in the output html page, the text may appear like

    John Smith (john@netwinsite.com)

Notes:
To avoid problems with variable references being confused with JavaScript or symbols, it is necessary to use the JavaScript or symbol with a space character on either side of it.
To actually display two bars in a web page, use &#124;&#124;. Most of the variables that are referenced in existing template pages are only available on that particular page. However, there are a number of variables that are defined for all template pages.

## Comments

Any line starting with a # character is a comment line and is ignored when generating the output web page. It is preferable to use this system of commenting rather than the html comment system, as the # template comments do not appear in the output web page, effectively reducing the size of the page that the user downloads. If you require an output page to start with a #, use ## at the start of a template source line and the remainder of the line after the first # will be rendered normally.

## Including pages within other pages

Often it is useful to include some template pages within other template pages. For example, the page surgeplus_web_top.htm appears at the top of all pages a user can see when logged in to the SurgePlus web interface. This is acheived by each of these other pages including the line

    ||include||surgeplus_web_top.htm||

at the top of the page. A single page can include multiple other pages and included pages can include other pages within them.

## Functions

Often a variable available in a template page is not in a format you want. For example if you have a large number, it is nice to display it with commas separating every third digit. So instead of 5242880 you want the text 5,242,880 to appear. In this case if the variable called file_size contained the number 5242880, then you can apply the function called comma to this number. This is done using the following syntax:

    ||comma(file_size)||

instead of just

    ||file_size||

Functions can be applied to the output of other functions and can take multiple parameters. If you need a paramter to a function to be treated as text (rather than the name of a variable) then you must enclose the text in brackets. For example if the variable called test has a value of Hello, then

    ||trim(test,3)||

outputs the text

    Hel

but

    ||trim((test),3)||

outputs the text

    tes

Note that the paramter 3 is not enclosed in brackets. This is because if the parameter starts with a digit, it is assumed to be a literal value rather than a variable name.
Here is a more complicated example. (if this is your first reading through this page you may want to skip over it for now)

    <select name="pref_calendar_day_start_hour">
    ||select_options(first_defined_of(pref_calendar_day_start_hour,8),(0,...,23),(hour_text))||
    </select>

select_options is the name of a function that takes 3 parameters. The first being the currently selected value, the second a list of select options and the third parameter is the name of a function to translate the select options into text values.
The first parameter to the select_options function in this case is first_defined_of(pref_calendar_day_start_hour,8). This calls the function first_defined_of, which means if there is a variable defined called pref_calendar_day_start_hour then it uses that, otherwise uses a value of 8.
The second paramter to the select_options function takes a comma separated list of select values. The select_options function expands the ... to include all numbers between 0 and 23.
The final parmater to select_options is the name of another function called hour_text. This function takes an integer parameter between 0 and 23 and displays it as a nice string of text identifying an hour. For example 3 pm.
Here is what the final output of this function may look like:

    <select name="pref_calendar_day_start_hour">
    <option value="0">12 am</option>
    <option value="1">1 am</option>
    <option value="2">2 am</option>
    <option value="3">3 am</option>
    <option value="4">4 am</option>
    <option value="5">5 am</option>
    <option value="6">6 am</option>
    <option value="7">7 am</option>
    <option value="8" selected>8 am</option>
    <option value="9">9 am</option>
    <option value="10">10 am</option>
    <option value="11">11 am</option>
    <option value="12">12 pm</option>
    <option value="13">1 pm</option>
    <option value="14">2 pm</option>
    <option value="15">3 pm</option>
    <option value="16">4 pm</option>
    <option value="17">5 pm</option>
    <option value="18">6 pm</option>
    <option value="19">7 pm</option>
    <option value="20">8 pm</option>
    <option value="21">9 pm</option>
    <option value="22">10 pm</option>
    <option value="23">11 pm</option>
    </select>

For a complete list of functions available, see Complete list of template functions

## Conditional Statements (if, else, endif, etc)

Often you only want a section of a page to appear under certain conditions. Earlier on we used the following example for variables:

    ||user_field_full_name|| (||user_email||)

However, the user's full name may not have been specified. So it is nicer to do something like this instead:

    ||ifdef||user_field_full_name||
    ||user_field_full_name|| (||user_email||)
    ||else||
    ||user_email||
    ||endif||

||ifdef|| (meaning if defined) displays all the text between the ||ifdef|| and the ||else|| clause if the variable user_field_full_name is defined (and not an empty string). If user_field_full_name is not defined, it displays the text between the ||else|| and ||endif|| section. The else seciton is optional and you can also extend it to use elseifdef to display one of more than two options. For example, in the SurgePlus calendar month view, we want the day to appear in green if it is today, black for a standard day, and gray if it is a day from the previous or next month.

    <a class=||ifdef||is_today||green||elseifdef||is_current_month||black||else||gray||endif|| ...

If the variable is_today is defined, then it will appear as

    <a class=green ...

Otherwise, if the variable is_current_month is defined, then it will appear as

    <a class=black ...

In all other situations it will appear as

    <a class=gray ...

## Repeating Sections

Often it is useful to repeat sections of a page multiple times where variables contain different values. For example, when listing the contents of a shared files folder, a section of the page is repeated for each file in the folder. This is done using ||begin_list|| and ||end_list|| pairs. For example

    <table>
    ||begin_list||
    <tr><td>||file_name||</td><td>||kbytes(file_size)||</td></tr>
    ||end_list||
    </table>

So that section of the page between the begin_list and end_list is repeated for each file in the folder, and the variables file_name and file_size may have different values each time it is repeated.
The actual text being displayed by begin_list and end_list will vary depending on the page being displayed. If a page needs to contain more than one repeating list section, then the begin_list and end_list will have a unique suffix for each section. For example ||begin_list_path|| and ||end_list_path||

## Variables available in all pages

Most variables used by template pages are only available within that particular page. However, some variables are available in all template pages. You can define your own variables to be available in all pages in style.htm. Variables available in addition to those defined in style.htm include

||list_line_num|| | Available between any ||begin_list||..||end_list|| pair. This variable contains a count of the list line number, starting with 1 for the first list item.
||list_is_first_line|| | Available between any ||begin_list||..||end_list|| pair. This variable contains a value of "true" for the first list item and is undefined for later items.
||list_line_is_even|| | Available between any ||begin_list||..||end_list|| pair. This variable alternates between "true" and undefined on each list item callback, starting with undefined for the first list item
||web_base_ref|| | Available in every page. Used as a prefix to the path for all images, css and js files other pages need to reference. This gets replaced by a unique string dependant on your current SurgeMail version so that SurgeMail can instruct the client browser to permanently cache these files (i.e. the browser should never ask for them again). This is intended to improve performance over default web server setups where the client browser checks if there is a new version of every image in a page each time the browser is restarted. If you upgrade your SurgeMail server or change the value of the g_web_ref_path_extension then clients will request a new copy of the images since they are now referenced in a new directory.

## Caching

For performance and caching reasons, any image you want to reference in a template page should be referred to using

    <img src="/web/||web_ref_path||image_name.gif">

instead of

    <img src="/web/image_name.gif">

The reasons for this is explained below
In order to improve performance for both the server and client we have implemented a caching scheme in SurgeMail for caching of images, .css, and .js files. Normally, a web server will serve these files out to a client browser, which will cache copies of those files. But next time the web browser is started, it will check with the server if there is a new copy of each image, .css, and .js file required by the page. The server will return a "not-modified" response for each file (rather than giving out the entire file again), but the processing of all these requests still slows down the page loading for the user and puts unnecessary load on the server. So, in SurgeMail we have a special scheme where each image (or .css or .js file) that would normally be referenced by /web/test.gif can instead by referenced as /web/caching-number/test.gif. Here, caching-number is some unique text that changes with each new version of SurgeMail.
When SurgeMail receives a request for a file of this form, it instructs the client to permanently cache the file and to never ask for it again. This could be a problem if the file is modified by you or by us in future versions of SurgeMail, which is why the caching-number text varies from version to version. There is a g_web_ref_path_extension SurgeMail setting you can use if you manually change your image files.
Another thing to be aware of is that .css and .js files may need to contain image references. Normally .css and .js files do not have template variables in them replaced. However, if a .js or .css file is referenced using ||web_ref_path|| in the reference name, then SurgeMail will apply template variable replacement on these files so that these files can reference images using ||web_ref_path|| themself. See /web/surgemail.css for an example where we do this.
If you use your own custom web pages referenced using /web/page_name.htm then normally SurgeMail would not apply template variable replacement to these, so you would not be able to reference image files using /web/||web_ref_path||/image_name.gif. To work around this problem, you can either refer to your custom page using /web/-tpl-/page_name.htm (which means SurgeMail will apply template variable replacement to the page. The "-tpl-" option works only in versions 2.1d-8 and later), or you can refer to image files in your page using /web/-cached-/image_name.gif to force it to be permanently cached. You can adding any text you want after the -cached- text if you happen to change your images occasionally. For example /web/-cached-version-1/image_name.gif. You may find the -tpl- option (which forces template variable replacement to occur in the file) useful when using it with .css or .js files which need to contain image references. For example /web/-tpl-/surgemail.css

## Miscellaneous Notes

Any template source line ending with a \ character will not have the \ charcater appear in the output page and additionally, the end of line chactater will also not appear in the output page. You can use this to space a single complicated line out over several lines in the template source to make it easier to read.

## Complete syntax reference

Syntax: ||variable_name||
Example: ||variable_name||
Description: Displays the contents of the variable called variable_name
Syntax: ||function_name(parameter1,parameter2,...)||
Example: ||trim(file_name,7)||
Description: Applies the specfied function to the given parameters. Parameters can either variables, other function calls, or literal text. If require a parameter to be literal text that does not start with a digit, you must enclose the literal text in brackets. For example ||trim((Hello),3)|| would give Hel
Syntax: ||include||file_name||
Example: ||include||surgeplus_web_top.htm||
Includes the specified file within the current page.
Syntax: ||ifdef||variable_name||...||endif||
or: ||ifdef||variable_name||...||else||...||endif||
or: ||ifdef||variable_name||...||elseifdef||variable_name2||...||else||...||endif||
or: ||ifdef||variable_name||...||endif(variable_name)||
Example: ||ifdef||file_name||File name is ||file_name||||endif||
If the given variable name is defined, displays the given text. The ||else||, ||elseifdef|| and ||endif|| parts of this syntax are available when using any of the ||if...|| options described below.
Syntax: ||ifdef||variable_name||...||endif(variable_name)||
or: ||ifdef||variable_name||...||else(variable_name)||...||endif(variable_name)||
Example: ||ifdef||file_name||File name is ||file_name||||endif(file_name)||
This is an optional alternative syntax for ||ifdef||. It is useful in complicated pages where the ifdef and endif are not near each other so that you can see more easily which endif lines up with which ifdef. The tempate parser will generate a template error if the variable name parameter to the endif or else does not match the variable name used in the matching ifdef or ifndef.
Syntax: ||ifndef||variable_name||...||endif||
Example: ||ifndef||file_name||File name is not defined||endif||
If the given variable name is not defined, displays the given text.
Syntax: ||ifequal||variable_name||value||...||endif||
Example: ||ifequal||file_name||test.htm|||The file is called test.htm||endif||
If the given variable value is equal to the given value, displays the given text.
Syntax: ||ifnequal||variable_name||value||...||endif||
Example: ||ifnequal||file_name||test.htm|||The file is not called test.htm||endif||
If the given variable value is not equal to the given value, displays the given text.
Syntax: ||begin_list||...||end_list||
Example: ||begin_list||file name=||file_name||<br>||end_list||
Repeats the text between the ||begin_list|| and ||end_list|| with variables taking on a different value each time.