Support for repeated sections
GvaScript.Repeat - Support for repeated sections
<div repeat="foo"> <h2>Foo #{foo.ix}</h2> This is the repeated foo section <table> <tr repeat="bar"> <td>Item #{bar.ix}</td> <td><input name="#{bar.path}.buz"></td> </tr> </table> <button onclick="GvaScript.Repeat.add('#{foo.path}.bar')">Add a bar</button> </div> <button onclick="GvaScript.Repeat.add('foo')">Add a foo</button>
<script> GvaScript.Repeat.init(document.body); </script
Implements a mechanism for repeated elements within an HTML page. The main use is within forms, for dynamic expansion of subforms (see Alien::GvaScript::Form); however the mechanism will work for any kind of HTML element.
At initialization stage, the DOM is inspected for finding
repeat elements (elements having a repeat
attribute).
These elements are removed from the DOM and replaced
by placeholders (empty DOM elements, just marking where
the repetition blocks should be inserted).
Each placeholder stores a template, which is
a plain string representation of the repeat element, with
special markup for template instanciation.
The template may then be dynamically instanciated into
repetition blocks by calling the /add method.
- can be nested - inspired by Web Forms
<div repeat="foo" repeat-start="3" repeat-min="2" repeat-max="6" repeat-prefix=""> <!-- content to be repeated, using #{foo.ix}, #{foo.path}, etc. --> </div>
Any element marked with a non-empty repeat
attribute is
a repeat element; the value of that attribute defines
the repeat name. Other attributes are optional.
Here is the complete list of repeat attributes :
marks the element as a repeat element, and defines the repeat name.
defines how many repetition blocks should be automatically created as initialization time. Default is 1.
minimum number of repetition blocks. Prevents deletion of repetition blocks under that number. Default is 1.
maximum number of repetition blocks. Prevents addition of repetition blocks over that number. Default is 99.
defines the initial fragment of the repeat path
(see
explanation below). Only valid for top-level repetition elements,
because nested repetition elements are automatically prefixed
by their parent repetition element. Default is the empty string.
The content of a repeat element may contain special markup for repetition variables, which will be replaced by values when the element is instanciated into a repetition block.
Variables are written #{<repetition name>.<variable>}
,
like for example #{foo.ix}
or #{bar.path}
. The repetition
name is the value of the repeat
attribute of the repeat element,
as explained above; in this namespace, the following variables
are defined
integer index of the current repetition block, starting at 1.
cumulated list of repetition name and repetition indices, separated by dots.
current number of repetition blocks for that repeat element.
value of the repeat-min
attribute.
value of the repeat-max
attribute.
The path
is unique within any nesting of repeat elements,
and therefore is typically used for ids or for
names of input elements :
<tr repeat="bar"> <td>Item #{bar.ix}</td> <td><input name="#{bar.path}.buz"></td> </tr>
Within the 3rd repetition block of bar
, nested
within the 2nd repetition block of foo
, the value of
#{bar.path}
will be foo.2.bar.3
and therefore
in this example the input name would be
foo.2.bar.3.buz
.
Implementation note: the #{...}
syntax for
variables is borrowed from prototype.js
's Template
class; however, the implementation of substitutions
is done in plain javascript, without calling
Template.evaluate()
method.
GvaScript.Repeat.init(element)
Walks down the DOM under the given element, finds all
elements having a repeat
attribute, replaces these
by placeholders.
The element
argument will be fed to prototype.js
's
$()
function, so it can be either a DOM element or
an id string.
GvaScript.Repeat.add(repeat_name)
Creates a new repetition block in the DOM, by instanciating
the repeat element repeat_name
(including prefix).
So if the repeat structure looks like
<div repeat="foo" repeat-prefix="top"> <div repeat="bar">
then a new foo
repetition block is instanciated
through add('top.foo')
, and a new bar
repetition
block is instanciated through add('#{foo.path}.bar')
.