Gather content of a page in named zones while rendering it

The primary purpose of ZonePlugin is to streamline the anatomy of a HTML page in a way to allow today's browsers to process it more efficiently. Page loading time has been reported to decrease significantly when all JavaScript files are removed from the HEAD element and appended to the end of the BODY element of a page. That's because the browser will stop processing a page as soon as a JavaScript file is found in the linear order of the page. The browser will only proceed after this file has been downloaded and excecuted. Notably other content like CSS files and image material will not be downloaded in parallel as long as the JavaScript interpreter hasn't finished.

Currently, Foswiki uses ADDTOHEAD to place additional CSS and JS files into the HEAD element. It does not reorder those files in any way other than specified by the explicit requires argument to the macro. Further more, it is only able to add stuff to one specific location of a HTML page, the HEAD element.

By using ADDTOZONE CSS and JS material can be added to the resulting page incrementally while the core engine parses templates and wiki applications. ADDTOZONE's first parameter is the name of the zone to add stuff to. There are two special zones: script and head. All CSS should be added to the head zone while all JS goes into the script zone.

The actual location of a zone is specified with an explicit RENDERZONE macro. This macro expands to the content of all material that has been posted to the named zone. Note, that this happens at the very end of the rendering pipeline of Foswiki. That means RENDERZONE is not processed as a normal macro obeying the evaluation order of the TML parser. Instead, all calls to ADDTOZONE are processed by the TML parser first after which all zones are expanded.

If RENDERZONE{head} and RENDERZONE{script} aren't found in the final page explicitly, they are expanded at the appropriate position, that is at </head>.

The features of this plugin have been proposed as a core feature for Foswiki to replace the standard ADDTOHEAD with the more generic ADDTOZONE tag. This plugin allows authors of extensions and wiki applications to make use of this advanced feature in a backwards-compatible way. As soon as the ADDTOZONE macro has been released as part of newer Foswiki versions, this plugin won't be of use anymore.

WARNING: Using this plugin can potentially break your installation. If you experience occasional JavaScript errors, enable {MergeHeadAndScriptZones} in configure. This mode will render the HTML page in a non-optimized way similar to how the standard ADDTOHEAD mechanism does.

In any case is it recommended to use ADDTOHEAD or ADDTOZONE to properly add this code to the page. It is not recommended to add JavaScript code otherwise.

If you rely on having JavaScript added to the page without using ADDTOHEAD or ADDTOZONE then you have to enable {MergeHeadAndScriptZones} mode most probably. In this case the HTML page cannot be optimized.




Zones are specific places in the output HTML that are marked by calls to the RENDERZONE macro. Zones are used to collect various content together, such as Javascript and CSS, that must be included in the output HTML in a specific order, and in a specific place.

You may create as many zones in addition to the standard head and script zones as you like. Interesting use cases in wiki applications:

  • Create a sidebar zone to add widgets,
  • Create a toolbar zone to add buttons icons

ADDTOZONE adds content identified with the id parameter to zone, which will later be expanded with RENDERZONE. id identifiers are unique within the zone that they are added to. An ADDTOZONE call may ensure that its content appears after the content of some other ADDTOZONE calls by specifying their ids in the requires parameter. requires may only list ids within the specified zone, except for the special case of head and script zones when {MergeHeadAndScriptZones} is set (read more).


  • "zone" optional, comma-separated list of the names of zones that the content should be added to. Defaults to head.
  • id optional, identifier for the text being added with the ADDTOZONE call, to be used in the requires parameter of other ADDTOZONE calls.
    • HELP Multiple ADDTOZONE calls with the same id parameter will simply overwrite the earlier ADDTOZONE call.
  • requires="..." optional, comma separated string of ids of text within this zone that this content should follow when the zone is rendered.
  • text="..." optional, text to be added to the named zone, mutually exclusive with topic.
  • topic="..." optional, full qualified web.topic name that contains the text to be added, mutually exclusive with text.
  • section="..." optional, section of the topic to be added, defaults to the default section between STARTINCLUDE and STOPINCLUDE.
    • HELP Using topic and section is actually a short form of
         text="$percentINCLUDE{\"topic\" section=\"section\" warn=\"off\"}$percent"

Note: Foswiki uses the requires parameter to resolve the ordering of dependencies within a zone. It does not work across zones. If you have an id in requires that cannot be resolved during sorting, then RENDERZONE will generate an HTML comment to mark the problem.

How to use the head and script zones

Web browsers generally process the HTML on a page from top to bottom. When a <script> tag is encountered with a URL to some Javascript file, processing of the page will stop while the file is fetched and executed before continuing. When a page makes heavy use of Javascript you can get a "blank screen" effect in the browser while each script is downloaded. To avoid this effect, <script> tags can be moved to the end of the HTML page, so that the user may view the page content while scripts are being loaded.

Foswiki makes this move possible by providing the head and script zones. These are automatic zones - they do not require a corresponding RENDERZONE.

IDEA! Rendering the script zone at the end of the HTML body requires skin template customisation with %RENDERZONE{"script"}%

Notionally the head and script zones correspond to a point just before the HTML </HEAD> tag. Normally you should add CSS (and other HTML <HEAD> content, such as <META>) to the head zone, and Javascript <script> markup to the script zone. The setting {MergeHeadAndScriptZones} in Configure controls what happens when RENDERZONE is called.

Normally, dependencies between the individual ADDTOZONE statements are resolved within each zone. However, if {MergeHeadAndScriptZones} is enabled, then head content which requires an id that only exists in script (and vice-versa) will be re-ordered to satisfy any dependency.

ALERT! {MergeHeadAndScriptZones} is provided to maintain compatibility with legacy extensions that use ADDTOHEAD to add <script> markup and require content that is now in the script zone. {MergeHeadAndScriptZones} will be removed from a future version of Foswiki.

Workign with {MergeHeadAndScriptZones} disabled (default)
In this mode, the head and script zones are treated separately.

Working with {MergeHeadAndScriptZones} enabled
In this mode, the head and script zones are separate when adding to them, but may be treated as merged when you call RENDERZONE if there are any dependencies specified that only exist in the opposite zone. This allows an ADDTOZONE{"head"...} to to successfully require an id that has been added to script.

Only add content to the script zone that is also legal in the <HEAD>.

Example: Adding to a zone with missing dependencies

You must ensure that no head content (and no inline Javascript) depends on script content, or vice-versa. Any such dependency will be ignored. However, the HTML comment decoration which normally appears after each id's content in the rendered HTML will contain a small informative text to aid debugging
  <script type='text/javascript'>

<script type='text/javascript'>
<!-- MY::TEST: requires= missing ids: some-id-that-exists-in-script -->
On the other hand, as explained earlier - when {MergeHeadAndScriptZones} is enabled - Foswiki is able resolve such dependencies successfully.

Note that if you do have an explicit call to %RENDERZONE{"head"}% in your templates then the content expanded at that point will be the same content as would be inserted before the </HEAD>.

Example: Adding Javascript to a page

  • Make sure that all inline Javascript code in the topic (if it is allowed) is added to the page using %ADDTOZONE{"script"...requires="library-id"}% with the appropriate library-id to guarantee a correct load order. For example, jQuery code should be added as follows:
       <script type='text/javascript'>
          jQuery('#something').shake(3, 10, 180);
    where "MyApp::ShakePart" is a unique id to identify the text added to script; and JQUERYPLUGIN::SHAKE signifies that the content added with that identifier should appear beforehand.

Example: Adding CSS to a page

      <style type='text/css' media='all'>
         @import url('%PUBURLPATH%/%SYSTEMWEB%/MyCSS/foo.css');


%RENDERZONE{"zone" ...}%
See ADDTOZONE for an explanation of zones.


  • "zone" required, name of the zone.
  • format="..." optional, format string for each item added to the zone, default:
    $item <!--<literal> $id $missing</literal>-->
    • $id - id of the ADDTOZONE call within the zone currently being rendered.
    • $item - text of the ADDTOZONE call within the zone currently being rendered.
    • $zone - the "zone" currently being rendered.
    • $missing - if the ADDTOZONE call being rendered required any id which was not found, then $missing is the missingtoken parameter; empty string otherwise.
    • $missingids - comma separated list of ids that were required by the ADDTOZONE call currently being rendered but weren't found within this zone.
  • missingtoken="..." optional, this will be the string assigned to the $missing format token for use in the format parameter. Default:
    $id: requires= missing ids: $missingids
  • chomp="on" remove leading and trailing whitespace from formatted items, can be useful for pretty-printing and compression.
  • header="..." optional, prepended to the output
  • footer="..." optional, appended to the output
  • separator="..." optional, put between each item of a zone
Supports the standard format tokens in all parameters.


  • header and footer are not output if there is no content in the zone (nothing has been ADDTOZONEd ). However they are output if the output is the empty string (at least one ADDTOZONE has been processed).
  • Zones are cleared after being rendered; they are only ever rendered once.
  • head and script are automatic zones. They don't require a corresponding RENDERZONE anywhere in the templates - they are automatically inserted before the </head> tag in the output HTML page.
  • Normally, dependencies between individual ADDTOZONE statements are resolved within each zone. However, if {MergeHeadAndScriptZones} is enabled in configure, then head content which requires an id that only exists in script (and vice-versa) will be re-ordered to satisfy any dependency.
    ALERT! {MergeHeadAndScriptZones} will be removed from a future version of Foswiki.

See also ADDTOZONE for more information on zones.

Perl API

This plugin patches the Foswiki::Func API for backwards compatibility.

  • New Foswiki::Func::addToZone($zone, $id, $text, $requires)
  • Replaces Foswiki::Func::addToHEAD() to use the =head namespace of this plugin instead of Foswiki::_HTMLHEAD

The latter will try to detect text/javascrtipt and move content into the script zone. Otherwise, it will be added to the head.

Any use of ADDTOHEAD or Foswiki::Func::addToHEAD() will emit a warning to the log files (must be switched on with the Warnings flag in configure). This can be used to hunt down suboptimal use of these APIs.

Installation Instructions

You do not need to install anything in the browser to use this extension. The following instructions are for the administrator who installs the extension on the server.

Open configure, and open the "Extensions" section. Use "Find More Extensions" to get a list of available extensions. Select "Install".

If you have any problems, or if the extension isn't available in configure, then you can still install manually from the command-line. See for more help.

Author(s): Michael Daum
Copyright: © 2010 Michael Daum
License: GPL (Gnu General Public License)
Release: 3.1
Version: 9442 (2010-09-30)
Change History:  
29 Sep 2010 Foswikitask:Item9763 revert recent changes and forward port script zone to make it work on old foswiki engines
06 Sep 2010 Foswikitask:Item9588: Update ZonePlugin to match Foswiki 1.1. Removed {OptimizePageLayout}, replaced with {MergeHeadAndScriptZones}. Removed body zone, replaced with script zone. Refer to Foswikitask:Item9588 for more info
28 Mar 2010 fix problem where Foswiki 1.0.x installations would fail with "Undefined subroutine &Foswiki::Func::addToZone"
26 Mar 2010 suppressing plugin initialisation on Foswiki engines >= 1.1; renamed BackwardsCompatible switch to OptimizePageLayout (defaults to off)
19 Feb 2010 added {BackwardsCompatible} switch
15 Feb 2010 be more careful applying the monkey-patch to the Func API; parsing RENDERZONE properly but finally inserting the zone at the end of the rendering pipeline
12 Feb 2010 initial release
Dependencies: None
Home page: Foswiki:Extensions/ZonePlugin
Support: Foswiki:Support/ZonePlugin

Topic revision: r3 - 15 Feb 2010 - 09:11:15 - ProjectContributor

This site is powered by FoswikiCopyright © by the contributing authors. All material on this site is the property of the contributing authors.
Ideas, requests, problems regarding Wiki-SL? Send feedback