Hi all,
I've got a big demo set up for tomorrow. Hopefully after that I can
start getting caught up on hobousers again. In the meantime, here's
a tag and some css that I'll probably put into hobo-contrib. Please
try it out. Enjoy!
<!--- This tag is very similar to Rapid's `field-list`. However,
instead of rendering a table, it renders what [Anatoli Papirovski
calls "perfect form markup"](
http://fecklessmind.com/2009/01/23/how-to-
reliable-css-forms/)
It takes the same attributes & parameters as [field-list](http://
cookbook.hobocentral.net/api_tag_defs/field-list), with the addition
of a `legend` parameter and a `required` attribute.
The `required` attribute is a list of methods. If the current field
is included in the list, the field div has the `required` class added
to it.
The accompanying css allows this fieldset to be rendered in three
different ways. You may trigger these by setting a class of
`horizontal`, `vertical` or `inline-vertical`. `inline-vertical`
fieldset's may also be nested inside of a `horizontal` fieldset.
### Example
Simple example:
<form>
<feckless-fieldset class="vertical"/>
</form>
And a more complicated one that you may actually want to steal:
<extend tag="signup-form" for="User">
<old-signup-form >
<field-list: replace>
<fieldset class="horizontal">
<legend>New Account Registration</legend>
<div class="field name-field">
<label class="name-label" for="user_name">Name</label>
<feckless-fieldset id="user_name" class="inline-
vertical" fields="salutation, first_name, last_name, suffix"
required="first_name, last_name" />
</div>
<div class="field contact-field">
<label class="contact-label" for="user_contact">Contact</
label>
<feckless-fieldset id="user_contact" class="inline-
vertical" fields="email_address, phone_number"
required="email_address" />
</div>
<div class="field passwords-field">
<label class="passwords-label"
for="user_contact">Password</label>
<feckless-fieldset id="user_passwords" class="inline-
vertical" fields="password, password_confirmation" required="password,
password_confirmation">
<password-label:></password-label:>
<password-confirmation-label:>Confirmation</password-
confirmation-label:>
</feckless-fieldset>
</div>
</fieldset>
</field-list:>
</old-signup-form>
</extend>
-->
<def tag="feckless-fieldset" attrs="tag, no-edit, required">
<% tag ||= scope.in_form ? "input" : "view"; no_edit ||= "skip" -%>
<% required ||= "" ; required = comma_split(required.gsub('-', '_'))
-%>
<fieldset class="feckless-fields" merge-attrs="&attributes -
attrs_for(:with_fields)">
<legend param if="¶meters[:legend]" />
<with-fields merge-attrs="&attributes & attrs_for(:with_fields)">
<% field_name = this_field_name
input_attrs = {:no_edit => no_edit} if tag == "input" &&
no_edit == "disable"
field_method = this_field.to_s.sub('?', '')
id_for_this = param_name_for_this.gsub('[', '_').gsub(']', '')
-%>
<div class="field #{field_method}-field #{'required' if
required.include?(field_method)} " unless="&tag == 'input' && no_edit
== 'skip' && !can_edit?">
<label for="&id_for_this" param="#{field_method}-label"
unless="&field_name.blank?">
<%= field_name %>
</label>
<do param="#{field_method}-view">
<do param="view"><call-tag tag="&tag" param="#{field_method}-
tag" merge-attrs="&input_attrs"/></do>
</do>
<span param="#{field_method}-help" class="input-help"
if="&tag.to_sym == :input && !this_field_help.blank?">
<%= this_field_help %>
</span>
</div>
</with-fields>
</fieldset>
</def>
css:
/* see:
http://fecklessmind.com/2009/01/23/how-to-reliable-css-forms/
*/
/* put a class of 'vertical', 'horizontal' or 'inline-vertical' on
your fieldset to choose your layout. */
/* fieldset {clear: both;} */
legend {padding: 0 0 1.286em; font-size: 1.167em; font-weight: 700;}
fieldset fieldset legend {padding: 0 0 1.5em; font-size: 1em;}
* html legend {margin-left: -7px;} /* ie6 */
*+html legend {margin-left: -7px;} /* ie7 */
fieldset .field, fieldset .buttons {/* clear: both; */ margin: 0 0
1.0em;}
fieldset .field label, fieldset .field .input-help {display: block;}
fieldset ul.fields {margin: 0 0 1.0em; padding: 0;}
fieldset ul.fields li {list-style-type: none; margin: 0;}
fieldset ul.inline li, fieldset ul.inline label {display: inline;}
fieldset ul.inline li {padding: 0 .75em 0 0;}
input.radio, input.checkbox {vertical-align: top;}
label, button, input.submit, input.image {cursor: pointer;}
* html input.radio, * html input.checkbox {vertical-align: middle;} /*
ie6 */
*+html input.radio, *+html input.checkbox {vertical-align: middle;} /*
ie7 */
textarea {overflow: auto;}
input.text, input.string, input.email-address, input.password,
textarea, select {margin: 0; font: 1em/1.3 Helvetica, Arial,
"Liberation Sans", "Bitstream Vera Sans", sans-serif; vertical-align:
baseline;}
input.text, input.string, input.email-address, input.password,
textarea {border: 1px solid #444; padding: 2px;}
/* horizontal layout */
fieldset.horizontal .field {padding-left: 150px; }
fieldset.horizontal .field label {display: inline; float: left; width:
140px; margin-left: -150px; clear:none;}
fieldset.horizontal .input-help { display: inline; margin-left:
0.5em; }
/* inline vertical layout. We make sure to undue all the
fieldset.horizontal styles so that this can be nested inside a
fieldset.horizontal */
fieldset.inline-vertical .field {padding-left: 0; display: inline-
block; float: none; margin-left: 0; clear: none; height:1%;
*display:inline;}
fieldset.inline-vertical .field label {display: block; float: none;
width: 100%; margin-left: 0;}
fieldset.inline-vertical .input-help { display: block; margin-left:
0; }
fieldset .field.required {color: red; }