re-work preload.tmpl and write basic documentation
authorTony Cook <tony@develop-help.com>
Fri, 31 May 2013 09:42:48 +0000 (19:42 +1000)
committerTony Cook <tony@develop-help.com>
Tue, 11 Jun 2013 00:41:43 +0000 (10:41 +1000)
MANIFEST
site/docs/preload.pod [new file with mode: 0644]
site/templates/preload.tmpl

index ad4a9ff..309f9c4 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -421,6 +421,7 @@ site/docs/Makefile
 site/docs/paypal.pod
 site/docs/pod2htmd.tmp
 site/docs/pod2htmi.tmp
+site/docs/preload.pod
 site/docs/search.html
 site/docs/secure.html
 site/docs/secure.pod
diff --git a/site/docs/preload.pod b/site/docs/preload.pod
new file mode 100644 (file)
index 0000000..4143c6f
--- /dev/null
@@ -0,0 +1,126 @@
+=head1 NAME
+
+preload.tmpl - preloaded template macros
+
+=head1 SYNOPSIS
+
+  <:.call ... -:>
+
+=head1 DESCRIPTION
+
+BSE provides F<preload.tmpl> as sample macros for use in templates.
+
+=head2 High-level form field display
+
+These require two parameters or preset variables:
+
+=over
+
+=item *
+
+C<fields> - a hash of fields
+
+=item *
+
+C<errors> - a hash or error messages for the fields
+
+=item *
+
+C<object> - an object containing the current values for an object, or
+a false value.
+
+=back
+
+=over
+
+=item *
+
+C<field> - lay out a form field, including label, input field, units,
+error indicator.
+
+=item *
+
+C<fieldset> - like C<field> but lay out the field inside a field set.
+
+=item *
+
+C<fieldro> - like C<field>, lay out a form field, but read only.  Does
+not include an error indicator.
+
+=item *
+
+C<fieldsetro> - like C<fieldset>, but read only.
+
+=back
+
+=head2 Low-level form-field display
+
+These are used by the high level field macros, do not require
+C<fields> to be set, but accept C<name> and C<field> paramaters, where
+C<field> is a value from C<fields>.
+
+=over
+
+=item *
+
+C<input> - display an input field 
+
+=item *
+
+C<display> - display a value.
+
+=item *
+
+C<inlinefield> - like C<field> but accepts C<name> and C<field>
+instead of C<name> and C<fields>.
+
+=item *
+
+C<inlinefieldro> - like C<fieldro> but accepts C<name> and C<field>
+instead of C<name> and C<fields>.
+
+=item *
+
+C<make_select> - make a single select element.  Used by C<input>.
+
+=item *
+
+C<make_multicheck> - make a multi-select checkbox set.  Used by
+C<input> etc.
+
+=item *
+
+C<old> - for older pages, render the cgi value given a field name in
+C<field>, otherwise the supplied C<default>.
+
+=back
+
+=head2 Other Utilities
+
+=over
+
+=item *
+
+C<page_list> - render a list of pages.  Accepts a base url in C<base>
+and a list of pages to render, as produced by bse.pages in C<pages>.
+
+=item *
+
+C<error_img_n> - render an error indicated for field C<field>, index
+C<index>.  The error message is taken from C<errors>.
+
+=item *
+
+C<error_img> - render an error indicator for field C<field>.
+
+=item *
+
+C<messages> - render any stored error messages.
+
+=item *
+
+C<mover> - render item move arrows.  Requires C<loop>, C<parent>.
+
+=back
+
+=cut
\ No newline at end of file
index f4f54ca..5e58062 100644 (file)
@@ -1,3 +1,4 @@
+<:# see preload.pod for documentation -:>
 <:.set groups = 0 -:>
 <:.set grouplabel = "label" -:>
 <:.set groupid = "id" -:>
   </select>
 <:-.end define -:>
 <:#
+make_multicheck expects:
+  values - list of hashes
+  default - a list of ids of checks to be checked
+  id - the name of the id field
+  desc - the name of the description field.
+  name - the name of the input elements
+  readonly - true to make it readonly
+-:>
+<:-.define make_multicheck-:>
+  <:.if !readonly -:>
+  <input type="hidden" name="_save_<:= name -:>" value="1">
+  <:.end if -:>
+  <:-.if !default.defined -:>
+    <:-.set default = [] -:>
+  <:.end if:>
+  <:.set checked = {} -:>
+  <:.for v in default -:>
+    <:% checked.set(v, 1) -:>
+  <:.end for -:>
+  <ul>
+  <:-.for i in values -:>
+    <li>
+    <:.set element_id = name _ "-" _ i.$id -:>
+    <input type="checkbox" name="<:= name :>" <:= checked[i.$id] ? 'checked ' : '' -:>
+      id="<:= element_id -:>" value="<:= i.$id :>"
+<:-# readonly attribute isn't valid for checkboxes -:>
+<:-= readonly ? " disabled" : "" -:>
+    >
+    <label for="<:= element_id :>"><:= i.$desc -:></label>
+    </li>
+  <:-.end for -:>
+  </ul>
+<:-.end define -:>
+<:#
 page_list expects:
 base - base url for links
 pages - the result of the bse.pages call
@@ -106,50 +141,59 @@ Page <:= pages.page :> of <:= pages.pagecount :>
 <:.define input -:>
 <:# paramaters:
   name - field name
-  fields - hash of fields (may be set by page instead)
+  field - entry from fields
   object - source for defaults in edit mode
 :>
-<:  .set f = fields[name] -:>
 <:  .if object -:>
-<:     .set default = object.get(name) -:>
-<:  .elsif f.default -:>
-<:     .set default = f.default -:>
+<:     .set default = object.$name -:>
+<:  .elsif field.default -:>
+<:     .set default = field.default -:>
 <:  .else -:>
 <:     .set default = "" -:>
 <:  .end if -:>
-<:  .if f.type and f.type eq "date" and default ne "" -:>
+<:  .if field.type and field.type eq "date" and default ne "" -:>
 <:    .set default = default.replace(/(\d+)\D+(\d+)\D+(\d+)/, "$3/$2/$1") -:>
-<:  .elsif f.type and f.type eq "time" and default ne "" -:>
+<:  .elsif field.type and field.type eq "time" and default ne "" -:>
 <:    .set default = bse.date(default =~ /:00$/ ? "%I:%M%p" : "%I:%M:%S%p", default).replace(/^0/, "").lower() -:>
 <:  .end if -:>
 <:  .if cgi.param(name).defined -:>
 <:     .set default = cgi.param(name) -:>
 <:  .end if -:>
-<:  .if f.htmltype eq "textarea" -:>
-<textarea id="<:= name | html :>" name="<:= name | html :>" rows="<:= f.height ? f.height : cfg.entry("forms", "textarea_rows", 10) :>" cols=<:= f.width ? f.width : cfg.entry("textarea_cols", 60) | html :>>
+<:  .if field.htmltype eq "textarea" -:>
+<textarea id="<:= name | html :>" name="<:= name | html :>" rows="<:= field.height ? field.height : cfg.entry("forms", "textarea_rows", 10) :>" cols=<:= field.width ? field.width : cfg.entry("textarea_cols", 60) | html :>>
 <:-= default | html -:>
 </textarea>
-<:  .elsif f.htmltype eq "checkbox" -:>
-<:.set is_checked = request.method() eq 'post' ? cgi.param(name).defined : default -:>
-<input id="<:= name | html :>" type="checkbox" name="<:= name | html :>"<:= is_checked ? ' checked="checked"' : '' :> value="<:= f.value ? f.value : 1 | html :>" />
-<:  .elsif f.htmltype eq "select" -:>
-<:.set values = f.select["values"] -:>
+<:  .elsif field.htmltype eq "checkbox" -:>
+<:.set is_checked = cgi.param("_save_" _ name) ? cgi.param(name).defined : default -:>
+<input type="hidden" name="_save_<:= name -:>" value="1">
+<input id="<:= name | html :>" type="checkbox" name="<:= name | html :>"<:= is_checked ? ' checked="checked"' : '' :> value="<:= field.value ? field.value : 1 | html :>" />
+<:  .elsif field.htmltype eq "multicheck" -:>
+<:# we expect default to be a list of selected checks -:>
+<:.set values = field.select["values"] -:>
+<:.set values = values.is_code ? values() : values -:>
+<:.set default = cgi.param("_save_" _ name) ? [ cgi.param(name) ] : default -:>
+<:.call "make_multicheck",
+  "id":field.select.id,
+  "desc":field.select.label,
+  "readonly":0 -:>
+<:  .elsif field.htmltype eq "select" -:>
+<:.set values = field.select["values"] -:>
 <:.set values = values.is_code ? values() : values -:>
 <:.call "make_select",
     "name":name,
     "default":default,
     "list":values,
-    "id":f.select.id,
-    "desc":f.select.label,
-    "groupid": (f.select.groupid or "id"),
-    "itemgroupid": (f.select.itemgroupid or "groupid"),
-    "groups": f.select.groups ? (f.select.groups.is_code ? (f.select.groups)() : f.select.groups ) : 0,
-    "grouplabel": (f.select.grouplabel or "label")
+    "id":field.select.id,
+    "desc":field.select.label,
+    "groupid": (field.select.groupid or "id"),
+    "itemgroupid": (field.select.itemgroupid or "groupid"),
+    "groups": field.select.groups ? (field.select.groups.is_code ? (field.select.groups)() : field.select.groups ) : 0,
+    "grouplabel": (field.select.grouplabel or "label")
 -:>
 <:  .else -:>
 <input id="<:= name | html :>" type="text" name="<:= name | html :>" value="<:=  default | html :>" 
-<:-= f.maxlength ? ' maxlength="' _ f.maxlength _ '"' : '' :>
-<:-= f.width ? ' size="' _ f.width _ '"' : '' :> />
+<:-= field.maxlength ? ' maxlength="' _ field.maxlength _ '"' : '' |raw:>
+<:-= field.width ? ' size="' _ field.width _ '"' : '' | raw :> />
 <:  .end if -:>
 <:.end define -:>
 
@@ -158,17 +202,153 @@ Page <:= pages.page :> of <:= pages.pagecount :>
   name - field name
   fields - hash of fields (may be set by page instead)
 :>
-  <:.set f = fields[name] -:>
+  <:.if fields.is_hash -:>
+    <:.set f = fields[name] -:>
+    <:.if f -:>
+      <:.call "inlinefield", "field":f, "name":name -:>
+    <:.else -:>
+<p>Unknown field id '<b><:= name :></b>', available fields are '<:= fields.keys.join("', '") :>'</p>
+    <:.end if -:>
+  <:.else -:>
+<p>fields isn't a hash, something is wrong.</p>
+  <:.end if -:>
+<:.end define -:>
+
+<:.define inlinefield -:>
+<:# parameters:
+  name - the field name
+  field - a field, as an entry in fields
+-:>
+  <:.if field.is_hash -:>
 <div>
-  <label for="<:= name | html :>"><:= f.nolabel ? "" : f.description | html :>:</label>
+  <label for="<:= name | html :>"><:= field.nolabel ? "" : field.description | html :>:</label>
   <span><:.call "input", "name":name -:><:.call "error_img", "field":name :>
-  <:-.if f.units -:>
-    <:-= f.units | html -:>
-  <:-.end if -:>
+    <:-.if field.units -:>
+      <:-= field.units | html -:>
+    <:-.end if -:>
+  <:.end if -:>
+</span>
+</div>
+<:.end define -:>
+
+<:.define fieldset -:>
+<:# like field, but wrap in a per-field field set.
+parameters:
+  name - field name
+  fields - hash of fields (may be set by page instead)
+:>
+  <:.set f = fields[name] -:>
+  <:.if f.is_hash -:>
+<fieldset>
+    <:.if !f.nolabel -:>
+  <legend><:= f.description :></legend>
+    <:.end if -:>
+  <:.call "input", "name":name, "field":f -:>
+</fieldset>
+  <:.elsif fields.is_hash -:>
+<p>Unknown field id '<b><:= name :></b>', available fields are '<:= fields.keys.join("', '") :>'</p>
+  <:.else -:>
+<p>fields isn't a hash, something is wrong.</p>
+  <:.end if -:>
+<:.end define -:>
+
+<:.define display -:>
+<:# paramaters:
+  name - field name
+  field - entry from fields
+  object - source for defaults in edit mode
+:>
+<:  .if object -:>
+<:     .set default = object.$name -:>
+<:  .end if -:>
+<:  .if field.type and field.type eq "date" and default ne "" -:>
+<:    .set default = default.replace(/(\d+)\D+(\d+)\D+(\d+)/, "$3/$2/$1") -:>
+<:  .elsif field.type and field.type eq "time" and default ne "" -:>
+<:    .set default = bse.date(default =~ /:00$/ ? "%I:%M%p" : "%I:%M:%S%p", default).replace(/^0/, "").lower() -:>
+<:  .end if -:>
+<:  .if field.htmltype eq "textarea" -:>
+<textarea id="<:= name | html :>" name="<:= name | html :>" rows="<:= field.height ? field.height : cfg.entry("forms", "textarea_rows", 10) :>" cols=<:= field.width ? field.width : cfg.entry("textarea_cols", 60) | html :> readonly>
+<:-= default | html -:>
+</textarea>
+<:  .elsif field.htmltype eq "checkbox" -:>
+<input id="<:= name | html :>" type="checkbox" name="<:= name | html :>"<:= is_checked ? ' checked="checked"' : '' :> value="<:= field.value ? field.value : 1 | html :>" readonly>
+<:  .elsif field.htmltype eq "multicheck" -:>
+<:# we expect default to be a list of selected checks -:>
+<:.set values = field.select["values"] -:>
+<:.set values = values.is_code ? values() : values -:>
+<:.call "make_multicheck",
+  "id":field.select.id,
+  "desc":field.select.label,
+  "readonly":1 -:>
+<:  .elsif field.htmltype eq "select" -:>
+<:.set values = field.select["values"] -:>
+<:.set values = values.is_code ? values() : values -:>
+<:# find the selected value and display it's label -:>
+<:.set sid = field.select.id -:>
+<:.set sdesc = field.select.label -:>
+<:.for value in values -:>
+  <:.if value.$id eq default -:>
+    <:= value.$desc -:>
+  <:.end if -:>
+<:.end for -:>
+<:  .else -:>
+<input id="<:= name  :>" type="text" name="<:= name :>" value="<:=  default :>"
+<:-= field.width ? ' size="' _ field.width _ '"' : '' | raw :> readonly>
+<:  .end if -:>
+<:.end define -:>
+
+<:.define inlinefieldro -:>
+<:# parameters:
+  name - the field name
+  field - a field, as an entry in fields
+-:>
+  <:.if field.is_hash -:>
+<div>
+  <label for="<:= name :>"><:= field.nolabel ? "" : field.description :>:</label>
+  <span><:.call "display", "name":name -:>
+    <:-.if field.units -:>
+      <:-= field.units -:>
+    <:-.end if -:>
+  <:.end if -:>
 </span>
 </div>
 <:.end define -:>
 
+<:.define fieldro -:>
+<:# like field, but for display, not editing -:>
+  <:.if fields.is_hash -:>
+    <:.set f = fields[name] -:>
+    <:.if f -:>
+      <:.call "inlinefieldro", "field":f, "name":name -:>
+    <:.else -:>
+<p>Unknown field id '<b><:= name :></b>', available fields are '<:= fields.keys.join("', '") :>'</p>
+    <:.end if -:>
+  <:.else -:>
+<p>fields isn't a hash, something is wrong.</p>
+  <:.end if -:>
+<:.end define -:>
+
+<:.define fieldsetro -:>
+<:# like fieldro, but wrap in a per-field field set.
+parameters:
+  name - field name
+  fields - hash of fields (may be set by page instead)
+:>
+  <:.set f = fields[name] -:>
+  <:.if f.is_hash -:>
+<fieldset>
+    <:.if !f.nolabel -:>
+  <legend><:= f.description :></legend>
+    <:.end if -:>
+  <:.call "display", "name":name, "field":f -:>
+</fieldset>
+  <:.elsif fields.is_hash -:>
+<p>Unknown field id '<b><:= name :></b>', available fields are '<:= fields.keys.join("', '") :>'</p>
+  <:.else -:>
+<p>fields isn't a hash, something is wrong.</p>
+  <:.end if -:>
+<:.end define -:>
+
 <:.define messages -:>
 <:  .if request.messages.size -:>
 <div class="messages">
@@ -183,19 +363,18 @@ Page <:= pages.page :> of <:= pages.pagecount :>
 <:# expects loop, parent
   which in most cases means you can just supply parent
 -:>
-<:.set distim = cfg.entryIfVar("uri", "dist_images", "/images") -:>
 <:.set width = cfg.entry("arrows", "width", 17) -:>
 <:.set height = cfg.entry("arrows", "height", 13) -:>
 <:.set extras = 'width="' _ width _ '" height="' _ height _ '"' -:>
-<:.set blankim = '<img src="' _ (distim _ "/trans_pixel.gif").escape("html") _ '" alt="" ' _ extras _ ' />' -:>
+<:.set blankim = '<img src="' _ (dist_images_uri _ "/trans_pixel.gif").escape("html") _ '" alt="" ' _ extras _ ' />' -:>
 <:.if loop.prev -:>
-  <:.set upimg = cfg.entry("arrows", "upimg", distim _ "/admin/move_up.gif") -:>
+  <:.set upimg = cfg.entry("arrows", "upimg", dist_images_uri _ "/admin/move_up.gif") -:>
 <a href="<:= cfg.admin_url("move", { "stepparent":parent.id, "d":"swap", "id":loop.current.id, "other":loop.prev.id, "r":top.admin }) :>"><img src="<:= upimg :>" <:= extras :> /></a>
 <:.else -:>
 <:= blankim |raw-:>
 <:.end if -:>
 <:.if loop.next -:>
-  <:.set downimg = cfg.entry("arrows", "downimg", distim _ "/admin/move_down.gif") -:>
+  <:.set downimg = cfg.entry("arrows", "downimg", dist_images_uri _ "/admin/move_down.gif") -:>
 <a href="<:= cfg.admin_url("move", { "stepparent":parent.id, "d":"swap", "id":loop.current.id, "other":loop.next.id, "r":top.admin }) :>"><img src="<:= downimg :>" <:= extras :> /></a>
 <:.else -:>
 <:= blankim |raw-:>