%META:TOPICINFO{author="ProjectContributor" date="1655468868" format="1.1" version="1"}%
%META:TOPICPARENT{name="Macros"}%
---+ ADDTOZONE -- add content to a named zone on the page

---++ Parameters
   | *Parameter* | *Description* | *Default* |
   | ="zone"= | comma-separated list of the names of zones that the content should be added to. The only zones guaranteed to exist are =head=, =script= and =body=.| =head= |
   | =id= | =identifier= for the text being added with the =ADDTOZONE= call, to be used in the =requires= parameter of other =ADDTOZONE= calls. %H% Multiple =ADDTOZONE= calls with the same =id= parameter will simply overwrite the earlier =ADDTOZONE= call. | |
   | =requires= | comma separated string of =ids= of text within this =zone= that this content should follow when the zone is rendered.  The content will be rendered even if a specified =id= is missing.| |
   | =text= | text to be added to the named zone, mutually exclusive with =topic=.| |
   | =topic= | full qualified =web.topic= name that contains the text to be added, mutually exclusive with =text=. | =%<nop>BASETOPIC%=|
   | =section= | section of the =topic= to be added | the default section between [[VarSTARTINCLUDE][STARTINCLUDE]] and [[VarSTOPINCLUDE][STOPINCLUDE]] |

---++ What is a "Zone"?
_Zones_ are specific places in the output HTML that are marked by calls to the
[[VarRENDERZONE][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.

There are three special zones called =head=, =script= and =body=. The =head= zone is rendered
as part of the HTML head section. It is the catch-all container for any content supposed
to be placed into the HTML head section, except Javascript, which is collected in the
=script= zone. 

All Javascript _must_ always be added to the =script= zone exclusively, in order to
grant ordering constraints among scripts are resolved properly. Never add Javascript to
the =head= zone -- never add non-Javascript content to the =script= zone.

Both =head= and =script= zones are added to the HTML head section automatically just before the
closing &lt;/head> tag as if they were specified explicitly in the skin templates using:
<verbatim class="tml">
<head>
...
%RENDERZONE{"head"}%
%RENDERZONE{"script"}%
</head>
</verbatim>

The =body= zone is added to the end of the rendered page just prior to the
closing =&lt;body&gt;= tag.  

<div class="foswikiHelp">The =body= zone is new with Foswiki 2.1.5.  It was
added for improved compatibility with the NatSkin. </div>

You may create as many zones in addition to the standard =head= and =script=
zones as you like.  For any non-standard zone specified in
[[%TOPIC%][ADDTOZONE]] you will also need to provide an appropriate
[[VarRENDERZONE][RENDERZONE]]. 

Interesting use cases in wiki applications:
   * Create a =sidebar= zone to add widgets,
   * Create a =toolbar= zone to add buttons icons
   * Create a =menu= zone to add menu entries

---+++ Adding content to a zone
[[%TOPIC%][ADDTOZONE]] adds content to a zone identified with the =id= parameter.
An =id= identifier is unique within the zone that they are added to. 
When the same =id= is used in multiple calls to [[%TOPIC%][ADDTOZONE]] the 
last call will win, that is previous content of the same =id= will be overwritten.

---+++ Enforcing a linear order of content within a zone
An [[%TOPIC%][ADDTOZONE]] call may ensure that its content appears _after_ the
content of some other [[%TOPIC%][ADDTOZONE]] calls by specifying their =ids= in
the =requires= parameter. The =requires= parameter constraints the linear order
of content added to a zone. When a zone is rendered, all ordering constraints
expressed via =requires= are satisfied.  Those =ids= not found in a zone don't
have any influence on the final ordering. Missing =ids= aren't considered an error
rather than an over-specified ordering problem.

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

Even when =head= and =script= zones are treated separately, the =head= zone will
always be rendered before the =script= zone, unless otherwise specified using [[VarRENDERZONE][RENDERZONE]] explicitly.
So any content in the =script= zone that depends on content placed into
the =head= zone is satisfied intrinsicly as they are both rendered as specified above.

---+++ 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 [[VarRENDERZONE][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=.

<div class="foswikiHelp">
  %X% ={MergeHeadAndScriptZones}= is provided to
  maintain compatibility with legacy extensions that use
  [[VarADDTOHEAD][ADDTOHEAD]] to add =&lt;script&gt;= markup and require content
  that is now in the =script= zone. ={MergeHeadAndScriptZones}= will be removed
  from a future version of Foswiki.
</div>

---++ Examples
---+++ Adding to a zone with missing dependencies
You must ensure that no =head= content (and no inline Javascript) depends on
=script= content.  Any such dependency will be _ignored_. 

In real world application this isn't a problem as Javascript is never added
to the =head= zone or Javascript zone part of the =script= zone never really
depends on non-Javascript content part of the =head= zone.

HTML comment decoration which normally appears after each id's
content in the rendered HTML will contain a small informative text to aid
debugging.

*Example* 
<verbatim class="tml">
%ADDTOZONE{
  "script"
  text="
  <script type='text/javascript'>
    alert('test');
  </script>"
  requires="some-id-that-exists-in-script"
  id="MY::TEST"
}%
</verbatim>

*Result*
<verbatim class="html">
<script type='text/javascript'>
  alert('test');
</script>
<!-- MY::TEST: requires= missing ids: some-id-that-exists-in-script -->
</verbatim>

---+++ 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 =%<nop>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:

<verbatim class="tml">
%JQREQUIRE{"shake"}%
%ADDTOZONE{
   "script"
   id="MyApp::ShakePart"
   text="
   <script type='text/javascript'>
      jQuery('#something').shake(3, 10, 180);
   </script>"
   requires="JQUERYPLUGIN::SHAKE"
}%
</verbatim> 

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.

---+++ Adding CSS to a page
<verbatim class="tml">
%ADDTOZONE{"head"
   id="MyCSS"
   text="
      <style type='text/css' media='all'>
         @import url('%PUBURLPATH%/%SYSTEMWEB%/MyCSS/foo.css');
      </style>"
}%
</verbatim>

%STOPINCLUDE%
---++ Related
[[VarRENDERZONE][RENDERZONE]],
[[Foswiki:Development.UsingADDTOZONE][Using ADDTOZONE]],
[[Foswiki:Development.UpdatingExtensionsScriptZone][Updating applications to use =script= zone]]
