Created
January 27, 2012 14:23
-
-
Save jshirley/1689003 to your computer and use it in GitHub Desktop.
Our macro.tt file for handling inputs consistently. Requires YUI3 grids to look proper.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
sub guide : Local { | |
my ( $self, $c ) = @_; | |
unless ( $c->debug ) { | |
$c->detach('/error/not_found'); | |
} | |
my $template = 'index.tt'; | |
if ( @{ $c->req->args } ) { | |
$template = $c->req->args->[0]; | |
if ( $template =~ /^\d{3}/ ) { | |
$c->detach('/error/_error', [ $template ]); | |
} | |
$template .= '.tt'; | |
} | |
unless ( -f $c->path_to('root', 'guide', $template) ) { | |
$template = 'index.tt'; | |
} | |
if ( $c->req->method eq 'POST' ) { | |
my $result = $c->model('DataManager')->verify('guide', $c->req->params); | |
if ( $result->success ) { | |
$c->message(q{Victory!}); | |
} else { | |
$c->message({ type => 'error', message => $c->loc('FORM VALIDATION ERROR') }); | |
} | |
$c->res->redirect( $c->req->uri ); | |
$c->detach; | |
} | |
$c->stash->{template} = 'guide/' . $template; | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[%~ | |
# Some illustrious documentation to get you started: | |
# | |
# The macros defined are to generate markup to save people from copy and pasting | |
# markup. They copy and paste hashes instead, which should be safer (in theory) | |
# | |
# The macros for forms are: | |
# * text_field - A text field | |
# * textarea_field - A textarea field | |
# * password_field - A password field, text_field({ type => 'password', ... }) | |
# * checkbox_field - A single checkbox, like an active checkbox | |
# * display_field - A display-only field, no hidden input for the display | |
# * readonly_field - A display-only field, with a hidden input | |
# * checkboxes_field - A group of fields, displayed in nice fashion. If a | |
# radio is needed, pass type => 'radio'. | |
# | |
# These use the YUI3 grids for rendering the markup. Without that CSS, things | |
# will not look correct. | |
# | |
# The basic structure is a containing div and the label and input is in a | |
# separate div. | |
# | |
MACRO submit_button(info) BLOCK; | |
DEFAULT info.label_column_size = "1-4"; | |
DEFAULT info.input_column_size = "3-4"; | |
DEFAULT info.button_class = "orange submit_button"; | |
IF info.no_extra; | |
info.label_column_size = "1-3"; | |
info.input_column_size = "2-3"; | |
END %] | |
<div class="field yui3-g submit-group | |
[%= info.field_classes.join(' ') ~%] | |
"> | |
<div class="yui3-u-[% info.label_column_size %]">[% info.more || " " %]</div> | |
<div class="yui3-u-[% info.input_column_size %]"> | |
[% IF info.with_reset %] | |
<input type="reset" value="[% c.loc('Cancel') %]"> | |
[% END %] | |
<input class="[% info.button_class %]" type="[% info.type || 'submit' %]" value="[% info.label || 'Submit' %]"[% IF info.defined('name') %] name="[% info.name %]"[% END %][% IF info.disabled %] disabled="disabled"[% END %]> | |
</div> | |
</div> | |
[% IF info.extra %] | |
<div class="yui3-g extra"> | |
<div class="yui3-u-[% info.label_column_size %]"> </div> | |
<div class="yui3-u-[% info.input_column_size %]">[% info.extra %]</div> | |
</div> | |
[% END; END; | |
MACRO label_field(info) BLOCK; | |
DEFAULT info.label_column_size = "1-4"; | |
IF info.no_extra; | |
info.label_column_size = "1-3"; | |
info.input_column_size = "2-3"; | |
END; | |
IF !info.error && stack && stack.count; | |
error_name = info.name; | |
IF context.scope; | |
error_name = error_name.remove("^${context.scope}\\."); | |
END; | |
info.error = c.loc( stack.for_subject(error_name).for_level('error').first_message.id ); | |
END %] | |
<label class="yui3-u-[% info.label_column_size %][% IF info.error %] error[% END; IF info.important %] important[% END %]" id="form_[% info.name %]_label" for="[% info.id %]"><span>[% c.loc(info.label, info.params) ~%] | |
[%~ IF info.tooltip %]<script type="text/javascript">new YAHOO.widget.Tooltip('tt_[% info.name %]_label', { context: 'form_[% info.name %]_label', text: "[% info.tooltip | replace('"', '\"') %]" } );</script>[?][% END ~%][% IF info.label %]:[% END %]</span> | |
</label> | |
[% END ~%] | |
[%~ | |
MACRO error_block(info) BLOCK; | |
DEFAULT info.label_column_size = '1-4'; | |
DEFAULT info.input_column_size = '3-4'; | |
IF info.error || info.extra %] | |
<div class="yui3-g [% =%] | |
[%= IF info.error =%]error[%= END =%] | |
[%= IF info.extra =%]extra[%= END ~%] | |
"> | |
<div class="yui3-u-1-4"> </div> | |
<div class="yui3-u-3-4 message"> | |
[% IF info.error %] | |
<div class="rmessage"><p>[% c.loc(info.error, info.error_message.params) %]</p></div> | |
[% END; | |
IF info.extra %] | |
<div class="gmessage"><p>[% c.loc(info.extra) %]</p></div> | |
[% END %] | |
</div> | |
</div> | |
[% END; | |
END ~%] | |
[%~ MACRO display_field(info) BLOCK; | |
IF info.filter && info.value; | |
f = info.filter; | |
IF f == "join"; | |
info.value = info.value.join(', '); | |
ELSIF f.match("^date_"); | |
info.value = format_date(info.value, f.substr(5)); | |
ELSE; | |
TRY; info.value = FILTER $f; info.value; END; CATCH; "Error!"; END; | |
END; | |
END; | |
%] | |
<div class="field yui3-g | |
[%= info.field_classes.join(' ') ~%] | |
[%~ ~%]"> | |
[% label_field(info) %] | |
<div class="yui3-u-1-2 ro [%~ IF info.extra || info.error %] message [% END ~%][%~ IF info.error %] error[% END %]"> | |
<span> | |
[%~ IF info.link %]<a href="[% info.link %]">[%~ END ~%] | |
[% info.value %] | |
[%~ IF info.link ~%]</a>[%~ END ~%]</span> | |
</div> | |
[% IF info.more %]<div class="yui3-u-1-4 more">[% c.loc(info.more) %]</div>[% END %] | |
[% error_block(info) %] | |
</div> | |
[% END ~%] | |
[%~ MACRO readonly_field(info) BLOCK; | |
IF info.filter && info.value; | |
f = info.filter; | |
IF f == "join"; | |
info.value = info.value.join(', '); | |
ELSIF f.match("^date_"); | |
info.value = format_date(info.value, f.substr(5)); | |
ELSE; | |
TRY; info.value = FILTER $f; info.value; END; CATCH; "Error!"; END; | |
END; | |
END; | |
%] | |
<div class="field yui3-g | |
[%= info.field_classes.join(' ') ~%] | |
[%~ ~%]"> | |
[% label_field(info) %] | |
<div class="yui3-u-1-2 ro [%~ IF info.extra || info.error %] message [% END ~%][%~ IF info.error %] error[% END %]"> | |
<input type="hidden" id="form_[% info.name %]" name="[% info.name %]" value="[% info.value | html %]"/><span> | |
[%~ IF info.link %]<a href="[% info.link %]">[%~ END ~%] | |
[% info.value %] | |
[%~ IF info.link ~%]</a>[%~ END ~%]</span> | |
</div> | |
[% IF info.more %]<div class="yui3-u-1-4 more">[% c.loc(info.more) %]</div>[% END %] | |
[% error_block(info) %] | |
</div> | |
[% END ~%] | |
[%~ MACRO select_field(info) BLOCK; | |
IF !info.value && results.${context.scope}; | |
value_name = info.name; | |
IF context.scope; value_name = value_name.remove("^${context.scope}\\."); END; | |
IF info.filter; | |
info.value = results.${context.scope}.get_value(value_name); | |
ELSE; | |
info.value = results.${context.scope}.get_original_value(value_name); | |
END; | |
END; | |
IF !info.error && messages.for_scope(context.scope); | |
value_name = info.name; | |
IF context.scope; value_name = value_name.remove("^${context.scope}\\."); END; | |
info.error = messages.for_scope(context.scope).for_subject(value_name).first_message.id; | |
info.error_message = messages.for_scope(context.scope).for_subject(value_name).first_message; | |
END; | |
DEFAULT info.id = "form_" _ info.name.replace('\\.', '_'); | |
%] | |
<div class="field yui3-g | |
[%= info.field_classes.join(' ') ~%] | |
[%~ ~%]"> | |
[% label_field(info); DEFAULT info.input_column_size = "1-2"; %] | |
<div class="yui3-u-[% info.input_column_size %] select [%~ IF info.extra || info.error %] [% END ~%][%~ IF info.error %] error[% END %][% IF info.input_classes %] [% info.input_classes.join(' ') %][% END %]"> | |
<[% IF info.type == 'radio'; "div"; ELSE; "select"; END %] id="form_[% info.name %]" name="[% info.name %]" | |
[% IF info.classes %] class="[% info.classes.join(' ') %]"[%~ END ~%] | |
[% IF info.disabled %] disabled="disabled"[%~ END ~%] | |
[% FOREACH datum IN info.data.pairs %] data-[% datum.key %]="[% datum.value %]"[%~ END ~%]> | |
[% IF info.type != "radio" && info.default_option %] | |
[% IF info.type == 'radio' %] | |
[% ELSE %] | |
<option value="[% info.default_option.0 | html %]">[% info.default_option.1 %]</option> | |
[% END %] | |
[% END %] | |
[% IF info.optgroups; | |
info.array = []; | |
DEFAULT info.children = 'children'; | |
FOREACH parent IN info.optgroups; | |
info.array.push({ optgroup => parent.${info.label_method} }); | |
FOREACH child IN parent.children; | |
info.array.push(child); | |
END; | |
END; | |
END %] | |
[% has_optgroup = 0; | |
FOREACH item = info.array; | |
IF item.optgroup; has_optgroup = 1; | |
IF !loop.first %]</optgroup>[% END; | |
%]<optgroup label="[% item.optgroup | html %]">[% | |
ELSE; | |
IF info.defined('value_method'); | |
SET this_value = item.${info.value_method}; | |
ELSE; | |
SET this_value = item; | |
END; | |
IF info.defined('label_method'); | |
SET this_name = item.${info.label_method}; | |
ELSE; | |
SET this_name = item; | |
END; | |
IF info.defined('elide'); | |
this_name = string_trunc.elide(this_name, info.elide); | |
END; | |
%][% IF info.type == "radio" %]<label><input type="radio" name="[% info.name %]" value="[% this_value | html %]"[% IF info.value == this_value %] checked="checked"[% END %]> [% c.loc(this_name) %]</label> | |
[% ELSE %]<option value="[% this_value | html %]" [% IF this_value == info.value %]selected="selected"[% END %]>[% c.loc(this_name) %]</option>[% END %] | |
[% END; # Not an optgroup %] | |
[% END; | |
IF has_optgroup %]</optgroup>[% END %] | |
[% IF info.type != 'radio' %]</select>[% END %] | |
[% IF info.required %]<span class="req">[% c.loc('FIELD REQUIRED SPLAT') %]</span>[% END %] | |
[% IF info.type == 'radio' %]</div>[% END %] | |
</div> | |
[% IF info.more %]<div class="yui3-u-1-4 more">[% c.loc(info.more) %]</div>[% END %] | |
[% error_block(info) %] | |
</div> | |
[% END ~%] | |
[%~ | |
MACRO password_field(info) BLOCK; | |
info.type = 'password'; | |
text_field(info); | |
END; | |
~%] | |
[%~ | |
MACRO text_field(info) BLOCK; | |
IF !info.defined('value') && results.${context.scope}; | |
value_name = info.name; | |
IF context.scope; value_name = value_name.remove("^${context.scope}\\."); END; | |
IF info.filter; | |
info.value = results.${context.scope}.get_value(value_name); | |
ELSE; | |
info.value = results.${context.scope}.get_original_value(value_name); | |
END; | |
END; | |
IF !info.error && messages.for_scope(context.scope); | |
value_name = info.name; | |
IF context.scope; value_name = value_name.remove("^${context.scope}\\."); END; | |
info.error = messages.for_scope(context.scope).for_subject(value_name).first_message.id; | |
END; | |
IF info.filter && info.value; | |
f = info.filter; | |
IF f == "join"; | |
info.value = info.value.join(', '); | |
ELSIF f.match("^date_"); | |
info.value = format_date(info.value, f.substr(5), info.timezone); | |
ELSE; | |
TRY; info.value = FILTER $f; info.value; END; CATCH; "Error!"; END; | |
END; | |
END; | |
DEFAULT info.id = "form_" _ info.name.replace('\\.', '_'); | |
%] | |
<div class="field yui3-g | |
[%= info.field_classes.join(' ') ~%] | |
[%~ ~%]"> | |
[% label_field(info); | |
# Default this here because label_field can set it. | |
DEFAULT info.input_column_size = "1-2"; | |
-%] | |
<div class="[% info.type || 'text' %] [%~ IF info.extra || info.error %] [% END ~%][%~ IF info.error %] error[% END %] yui3-u-[% info.input_column_size %]"> | |
<input type="[% info.type || 'text' %]" id="[% info.id %]" name="[% info.name %]" [% IF info.size %]size="[% info.size %]"[% END %] | |
[% IF info.pattern %] pattern="[% info.pattern %]" [% END %] | |
value="[% info.value | html %]" | |
[%~ IF info.classes %] class="[% info.classes.join(" ") %]"[% END ~%] | |
[% # The unicode char below is purely to make the placeholder junk work. %] | |
[%~ IF info.hint %] placeholder="◦ [% c.loc(info.hint) %]"[% END ~%] | |
[%~ IF info.autocomplete == 0 %] autocomplete="false"[% END ~%] | |
[%~ IF info.disabled == 1 %] disabled="disabled"[% END ~%] | |
[%~ IF info.tabindex %] tabindex="[% info.tabindex %]"[% END ~%] | |
[%~ IF info.maxlength %] maxlength="[% info.maxlength %]"[% END ~%] | |
[%~ FOREACH datum IN info.data.pairs %] data-[% datum.key %]="[% datum.value %]"[% END ~%]> | |
[% IF info.required %]<span class="req">[% c.loc('FIELD REQUIRED SPLAT') %]</span>[% END %] | |
</div> | |
[% IF info.more %]<div class="yui3-u-1-4 more">[% c.loc(info.more) %]</div> | |
[% ELSIF info.helptext %]<div class="yui3-u-1-4 more helptext"><a href="#[% info.id %]" class="helptext">[% c.loc(info.helptext) %]</a></div>[% END %] | |
[% error_block(info) %] | |
</div> | |
[% END ~%] | |
[%~ | |
MACRO textarea_field(info) BLOCK; | |
IF !info.value && results.${context.scope}; | |
value_name = info.name; | |
IF context.scope; value_name = value_name.remove("^${context.scope}\\."); END; | |
info.value = results.${context.scope}.get_original_value(value_name); | |
END; | |
IF !info.error && messages.for_scope(context.scope); | |
value_name = info.name; | |
IF context.scope; value_name = value_name.remove("^${context.scope}\\."); END; | |
info.error = messages.for_scope(context.scope).for_subject(value_name).first_message.id; | |
END; | |
%] | |
<div class="field yui3-g"> | |
[% label_field(info) %] | |
<div class="yui3-u-[% info.input_column_size %] textarea [%~ IF info.extra || info.error %] message [% END ~%][%~ IF info.error %] error[% END %]"> | |
<textarea [%= ~%] | |
id="form_[% info.name %]" name="[% info.name %]" | |
[% IF info.hint %] placeholder="[% c.loc(info.hint) %]"[% END %] | |
[%~ IF info.classes %] class="[% info.classes.join(' ') %]"[% END ~%] | |
[%~ IF info.disabled == 1 %] disabled="disabled"[% END ~%] | |
[%~ IF info.autocomplete == 0 %] autocomplete="false"[% END ~%] | |
[%~ IF info.tabindex %] tabindex="[% info.tabindex %]"[% END ~%] | |
[%~ IF info.rows %] rows="[% info.rows %]"[% END ~%] | |
[%~ IF info.cols %] cols="[% info.cols %]"[% END ~%] | |
[%~ FOREACH datum IN info.data.pairs %] data-[% datum.key %]="[% datum.value %]"[% END ~%] | |
> | |
[%~ info.value | html ~%] | |
</textarea> | |
[% IF info.required %]<span class="req">[% c.loc('FIELD REQUIRED SPLAT') %]</span>[% END %] | |
</div> | |
[% IF info.more %]<div class="yui3-u-1-4 more">[% c.loc(info.more) %]</div>[% END %] | |
[% error_block(info) %] | |
</div> | |
[% END ~%] | |
[%~ | |
MACRO checkboxes_field(info) BLOCK; | |
IF !info.value && results.${context.scope}; | |
value_name = info.name; | |
IF context.scope; value_name = value_name.remove("^${context.scope}\\."); END; | |
IF info.filter; | |
info.value = results.${context.scope}.get_value(value_name); | |
ELSE; | |
info.value = results.${context.scope}.get_original_value(value_name); | |
END; | |
END; | |
IF !info.error && messages && messages.count; | |
error_name = info.name; | |
IF context.scope; | |
error_name = error_name.remove("^${context.scope}\\."); | |
END; | |
info.error = c.loc( messages.for_subject(error_name).for_level('error').first_message.id ); | |
END; | |
%] | |
<div class="field yui3-g submit-group | |
[%= info.field_classes.join(' ') ~%] | |
"> | |
[% label_field(info); | |
# Default this here because label_field can set it. | |
DEFAULT info.input_column_size = "1-2"; | |
-%] | |
<div class="yui3-u-[% info.input_column_size %] checkboxes [%~ IF info.extra || info.error %] message [% END ~%][%~ IF info.error %] error[% END %]"> | |
<fieldset class="cwrap[% IF info.fieldset_classes %] [% info.fieldset_classes.join(' '); END %]"> | |
[% FOREACH item = info.array; | |
IF info.defined('value_method'); | |
SET this_value = item.${info.value_method}; | |
ELSE; | |
SET this_value = item; | |
END; | |
IF info.defined('label_method'); | |
SET this_name = item.${info.label_method}; | |
ELSE; | |
SET this_name = item; | |
END; | |
%]<label><input type="[% info.type || 'checkbox' %]" name="[% info.name %]" value="[% this_value | html %]"[% IF info.value == this_value || info.selected.defined(this_value) %] checked="checked"[% END %]> [% this_name %]</label> | |
[% END %] | |
</fieldset> | |
[% IF info.required %]<span class="req">[% c.loc('FIELD REQUIRED SPLAT') %]</span>[% END %] | |
</div> | |
[% IF info.more %]<div class="yui3-u-1-4 more">[% c.loc(info.more) %]</div>[% END %] | |
[% error_block(info) %] | |
</div> | |
[% END; %] | |
[%~ | |
MACRO checkbox_field(info) BLOCK; | |
DEFAULT info.label_column_size = "1-4"; | |
DEFAULT info.input_column_size = "1-2"; | |
IF info.no_extra; | |
info.label_column_size = "1-3"; | |
info.input_column_size = "2-3"; | |
END; | |
IF !info.checked && results.${context.scope}; | |
value_name = info.name; | |
IF context.scope; value_name = value_name.remove("^${context.scope}\\."); END; | |
info.checked = results.${context.scope}.get_original_value(value_name); | |
END; | |
IF !info.error && messages && messages.count; | |
error_name = info.name; | |
IF context.scope; | |
error_name = error_name.remove("^${context.scope}\\."); | |
END; | |
info.error = c.loc( messages.for_subject(error_name).for_level('error').first_message.id ); | |
END; | |
%] | |
<div class="field yui3-g"> | |
<div class="yui3-u-[% info.label_column_size %]"> </div> | |
<div class="yui3-u-[% info.input_column_size %] checkbox [%~ IF info.extra || info.error %] message [% END ~%][%~ IF info.error %] error[% END %]"> | |
<label><input type="checkbox" name="[% info.name %]" | |
[%~ IF info.value =%] value="[% info.value %]"[% END ~%] | |
[%~ IF info.checked =%] checked="checked"[% END ~%] | |
> [% c.loc(info.label, info.params) %]</label> | |
</div> | |
[% IF info.more %]<div class="yui3-u-1-4 more">[% c.loc(info.more) %]</div>[% END %] | |
[% error_block(info) %] | |
</div> | |
[%~ END ~%] | |
[%~ | |
MACRO datetime_field(info) BLOCK; | |
IF !info.defined('value') && results.${context.scope}; | |
value_name = info.name; | |
IF context.scope; value_name = value_name.remove("^${context.scope}\\."); END; | |
info.value = results.${context.scope}.get_value(value_name); | |
END; | |
IF !info.error && messages.for_scope(context.scope); | |
value_name = info.name; | |
IF context.scope; value_name = value_name.remove("^${context.scope}\\."); END; | |
info.error = messages.for_scope(context.scope).for_subject(value_name).first_message.id; | |
END; | |
DEFAULT info.id = "form_" _ info.name.replace('\\.', '_'); | |
IF info.value && info.timezone; | |
info.value = set_timezone(info.value, info.timezone); | |
END; | |
%] | |
<div class="field yui3-g | |
[%= info.field_classes.join(' ') ~%] | |
[%~ ~%]"> | |
[% label_field(info); | |
# Default this here because label_field can set it. | |
DEFAULT info.input_column_size = "1-2"; | |
-%] | |
<div class="[% info.type || 'datetime' %] [%~ IF info.extra || info.error %] [% END ~%][%~ IF info.error %] error[% END %] yui3-u-[% info.input_column_size %]"> | |
<input type="[% info.type || 'text' %]" id="[% info.id %]" name="[% info.name %].date" | |
[% IF info.pattern %] pattern="[% info.pattern %]" [% END %] | |
value="[% FILTER html; info.value.ymd || info.value; END %]" | |
[%~ IF info.classes %] class="[% info.classes.join(" ") %]"[% END ~%] | |
[% # The unicode char below is purely to make the placeholder junk work. %] | |
[%~ IF info.hint %] placeholder="◦ [% c.loc(info.hint) %]"[% END ~%] | |
[%~ IF info.autocomplete == 0 %] autocomplete="false"[% END ~%] | |
[%~ IF info.disabled == 1 %] disabled="disabled"[% END ~%] | |
[%~ IF info.tabindex %] tabindex="[% info.tabindex %]"[% END ~%] | |
[%~ IF info.maxlength %] maxlength="[% info.maxlength %]"[% END ~%] | |
[%~ FOREACH datum IN info.data.pairs %] data-[% datum.key %]="[% datum.value %]"[% END ~%]> | |
[% IF info.required %]<span class="req">[% c.loc('FIELD REQUIRED SPLAT') %]</span>[% END %] | |
<select name="[% info.name %].hour"> | |
[% FOREACH i IN [0..23] %] | |
<option value="[% i | format("%02d") %]"[% IF info.value.hour && info.value.hour == i %] selected="selected"[% END %]>[% i | format("%02d") %]</option> | |
[% END %] | |
</select> | |
<select name="[% info.name %].minute"> | |
[% FOR i IN [0, 15, 30, 45] %] | |
<option value="[% i | format("%02d") %]"[% IF info.value.minute && info.value.minute >= i && info.value.minute < i + 15 %] selected="selected"[% END %]>[% i | format("%02d") %]</option> | |
[% END %] | |
</select> | |
</div> | |
[% IF info.more %]<div class="yui3-u-1-4 more">[% c.loc(info.more) %]</div> | |
[% ELSIF info.helptext %]<div class="yui3-u-1-4 more helptext"><a href="#[% info.id %]" class="helptext">[% c.loc(info.helptext) %]</a></div>[% END %] | |
[% error_block(info) %] | |
</div> | |
[% END ~%] | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment