formtastic 0.9.7 → 0.9.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.textile +69 -12
- data/Rakefile +1 -1
- data/generators/form/templates/view__form.html.erb +2 -2
- data/generators/form/templates/view__form.html.haml +2 -2
- data/generators/formtastic/templates/formtastic.css +58 -50
- data/generators/formtastic/templates/formtastic.rb +3 -0
- data/generators/formtastic/templates/formtastic_changes.css +5 -1
- data/lib/formtastic.rb +108 -37
- data/lib/formtastic/layout_helper.rb +10 -0
- data/rails/init.rb +2 -0
- data/spec/commit_button_spec.rb +26 -4
- data/spec/custom_macros.rb +0 -101
- data/spec/form_helper_spec.rb +6 -0
- data/spec/input_spec.rb +34 -0
- data/spec/inputs/boolean_input_spec.rb +9 -5
- data/spec/inputs/check_boxes_input_spec.rb +33 -10
- data/spec/inputs/date_input_spec.rb +137 -25
- data/spec/inputs/datetime_input_spec.rb +177 -54
- data/spec/inputs/hidden_input_spec.rb +9 -0
- data/spec/inputs/radio_input_spec.rb +15 -9
- data/spec/inputs/select_input_spec.rb +113 -83
- data/spec/inputs/time_input_spec.rb +151 -25
- data/spec/inputs/time_zone_input_spec.rb +4 -2
- data/spec/layout_helper_spec.rb +29 -0
- data/spec/semantic_errors_spec.rb +98 -0
- data/spec/spec_helper.rb +26 -18
- metadata +50 -22
    
        data/README.textile
    CHANGED
    
    | @@ -91,20 +91,28 @@ Then install the Formtastic gem: | |
| 91 91 | 
             
              sudo gem install formtastic
         | 
| 92 92 | 
             
            </pre>
         | 
| 93 93 |  | 
| 94 | 
            +
            And add it to your environment.rb configuration as a gem dependency:
         | 
| 95 | 
            +
             | 
| 96 | 
            +
            <pre>
         | 
| 97 | 
            +
              config.gem 'formtastic'
         | 
| 98 | 
            +
            </pre>
         | 
| 99 | 
            +
             | 
| 94 100 | 
             
            Optionally, run @./script/generate formtastic@ to copy the following files into your app:
         | 
| 95 101 |  | 
| 96 102 | 
             
            * @config/initializers/formtastic.rb@ - a commented out Formtastic config initializer
         | 
| 97 103 | 
             
            * @public/stylesheets/formtastic.css@
         | 
| 98 104 | 
             
            * @public/stylesheets/formtastic_changes.css@
         | 
| 99 105 |  | 
| 100 | 
            -
            A proof-of-concept stylesheet is provided which you can include in your layout. Customization is best achieved by overriding these styles in an additional stylesheet so that the Formtastic styles can be updated without clobbering your changes. If you want to use these stylesheets, add both to your layout:
         | 
| 106 | 
            +
            A proof-of-concept stylesheet is provided which you can include in your layout. Customization is best achieved by overriding these styles in an additional stylesheet so that the Formtastic styles can be updated without clobbering your changes. If you want to use these stylesheets, add both to your layout with this helper:
         | 
| 101 107 |  | 
| 102 108 | 
             
            <pre>
         | 
| 103 | 
            -
               | 
| 104 | 
            -
             | 
| 109 | 
            +
              <head>
         | 
| 110 | 
            +
                ...
         | 
| 111 | 
            +
                <%= formtastic_stylesheet_link_tag %>
         | 
| 112 | 
            +
                ...
         | 
| 113 | 
            +
              </head>
         | 
| 105 114 | 
             
            </pre>
         | 
| 106 115 |  | 
| 107 | 
            -
             | 
| 108 116 | 
             
            h2. Usage
         | 
| 109 117 |  | 
| 110 118 | 
             
            Forms are really boring to code... you want to get onto the good stuff as fast as possible.
         | 
| @@ -165,7 +173,7 @@ If you want to customize the label text, or render some hint text below the fiel | |
| 165 173 | 
             
              <% end %>
         | 
| 166 174 | 
             
            </pre>
         | 
| 167 175 |  | 
| 168 | 
            -
            Nested forms (Rails 2.3) are also supported. You can do it in the Rails way:
         | 
| 176 | 
            +
            Nested forms (Rails 2.3) are also supported (don't forget your models need to be setup correctly with accepts_nested_attributes_for – search the Rails docs). You can do it in the Rails way:
         | 
| 169 177 |  | 
| 170 178 | 
             
            <pre>
         | 
| 171 179 | 
             
              <% semantic_form_for @post do |form| %>
         | 
| @@ -231,6 +239,23 @@ Customize the HTML attributes for the @<li>@ wrapper around every input with the | |
| 231 239 | 
             
              <% end %>
         | 
| 232 240 | 
             
            </pre>
         | 
| 233 241 |  | 
| 242 | 
            +
            Many inputs provide a collection of options to choose from (like @:select@, @:radio@, @:check_boxes@, @:boolean@). In many cases, Formtastic can find choices through the model associations, but if you want to use your own set of choices, the @:collection@ option is what you want.  You can pass in an Array of objects, an array of Strings, a Hash... Throw almost anything at it! Examples:
         | 
| 243 | 
            +
             | 
| 244 | 
            +
            <pre>
         | 
| 245 | 
            +
              f.input :authors, :as => :check_boxes, :collection => User.find(:all, :order => "last_name ASC")
         | 
| 246 | 
            +
              f.input :authors, :as => :check_boxes, :collection => current_user.company.users.active
         | 
| 247 | 
            +
              f.input :authors, :as => :check_boxes, :collection => [@justin, @kate]
         | 
| 248 | 
            +
              f.input :authors, :as => :check_boxes, :collection => ["Justin", "Kate", "Amelia", "Gus", "Meg"]
         | 
| 249 | 
            +
              f.input :author,  :as => :select,      :collection => Author.find(:all)
         | 
| 250 | 
            +
              f.input :author,  :as => :select,      :collection => { @justin.name => @justin.id, @kate.name => @kate.id }
         | 
| 251 | 
            +
              f.input :author,  :as => :select,      :collection => ["Justin", "Kate", "Amelia", "Gus", "Meg"]
         | 
| 252 | 
            +
              f.input :author,  :as => :radio,       :collection => User.find(:all)
         | 
| 253 | 
            +
              f.input :author,  :as => :radio,       :collection => [@justin, @kate]
         | 
| 254 | 
            +
              f.input :author,  :as => :radio,       :collection => { @justin.name => @justin.id, @kate.name => @kate.id }
         | 
| 255 | 
            +
              f.input :author,  :as => :radio,       :collection => ["Justin", "Kate", "Amelia", "Gus", "Meg"]
         | 
| 256 | 
            +
              f.input :admin,   :as => :radio,       :collection => ["Yes!", "No"]
         | 
| 257 | 
            +
            </pre>
         | 
| 258 | 
            +
             | 
| 234 259 |  | 
| 235 260 | 
             
            h2. The Available Inputs
         | 
| 236 261 |  | 
| @@ -252,7 +277,19 @@ The Formtastic input types: | |
| 252 277 | 
             
            * @:country@ - a select menu of country names. Default for column types: :string with name @"country"@ - requires a *country_select* plugin to be installed.
         | 
| 253 278 | 
             
            * @:hidden@ - a hidden field. Creates a hidden field (added for compatibility).
         | 
| 254 279 |  | 
| 255 | 
            -
            The  | 
| 280 | 
            +
            The comments in the code are pretty good for each of these (what it does, what the output is, what the options are, etc.) so go check it out.
         | 
| 281 | 
            +
             | 
| 282 | 
            +
             | 
| 283 | 
            +
            h2. Delegation for label lookups
         | 
| 284 | 
            +
             | 
| 285 | 
            +
            Formtastic decides which label to use in the following order:
         | 
| 286 | 
            +
             | 
| 287 | 
            +
            <pre>
         | 
| 288 | 
            +
              1. :label             # :label => "Choose Title"
         | 
| 289 | 
            +
              2. Formtastic i18n    # if either :label => true || i18n_lookups_by_default = true (see Internationalization)
         | 
| 290 | 
            +
              3. Activerecord i18n  # if localization file found for the given attribute
         | 
| 291 | 
            +
              4. label_str_method   # if nothing provided this defaults to :humanize but can be set to a custom method 
         | 
| 292 | 
            +
            </pre>
         | 
| 256 293 |  | 
| 257 294 | 
             
            h2. Internationalization (I18n)
         | 
| 258 295 |  | 
| @@ -406,6 +443,17 @@ For more flexible forms; Formtastic find translations using a bottom-up approach | |
| 406 443 | 
             
            Values for @labels@/@hints@/@actions@ are can take values: @String@ (explicit value), @Symbol@ (i18n-lookup-key relative to the current "type", e.g. actions:), @true@ (force I18n lookup), @false@ (force no I18n lookup). Titles (legends) can only take: @String@ and @Symbol@ - true/false have no meaning.
         | 
| 407 444 |  | 
| 408 445 |  | 
| 446 | 
            +
            h2. Semantic errors
         | 
| 447 | 
            +
             | 
| 448 | 
            +
            You can show errors on base (by default) and any other attribute just passing it name to semantic_errors method:
         | 
| 449 | 
            +
             | 
| 450 | 
            +
            <pre>
         | 
| 451 | 
            +
              <% semantic_form_for @post do |form| %>
         | 
| 452 | 
            +
                <%= form.semantic_errors :state %>
         | 
| 453 | 
            +
              <% end %>
         | 
| 454 | 
            +
            </pre>
         | 
| 455 | 
            +
             | 
| 456 | 
            +
             | 
| 409 457 | 
             
            h2. ValidationReflection plugin
         | 
| 410 458 |  | 
| 411 459 | 
             
            If you have the "ValidationReflection":http://github.com/redinger/validation_reflection plugin installed, you won't have to specify the @:required@ option (it checks the validations on the model instead).
         | 
| @@ -428,10 +476,10 @@ $ ./script/generate form Post | |
| 428 476 | 
             
            #  GENERATED FORMTASTIC CODE
         | 
| 429 477 | 
             
            # ---------------------------------------------------------
         | 
| 430 478 |  | 
| 431 | 
            -
            <%  | 
| 432 | 
            -
              <%=  | 
| 433 | 
            -
              <%=  | 
| 434 | 
            -
              <%=  | 
| 479 | 
            +
            <% f.inputs do %>
         | 
| 480 | 
            +
              <%= f.input :title, :label => 'Title' %>
         | 
| 481 | 
            +
              <%= f.input :body, :label => 'Body' %>
         | 
| 482 | 
            +
              <%= f.input :published, :label => 'Published' %>
         | 
| 435 483 | 
             
            <% end %>
         | 
| 436 484 |  | 
| 437 485 | 
             
            # ---------------------------------------------------------
         | 
| @@ -497,9 +545,18 @@ Well...there's a TextMate-bundle in town, dedicated to make usage of Formtastic | |
| 497 545 | 
             
            "Formtastic.tmbundle":http://github.com/grimen/formtastic_tmbundle
         | 
| 498 546 |  | 
| 499 547 |  | 
| 500 | 
            -
            h2.  | 
| 548 | 
            +
            h2. How to contribute
         | 
| 549 | 
            +
             | 
| 550 | 
            +
            *Before you send a pull request*, please ensure that you provide appropriate spec/test coverage and ensure the documentation is up-to-date.  Bonus points if you perform your changes in a clean topic branch rather than master.
         | 
| 551 | 
            +
             | 
| 552 | 
            +
            Please also keep your commits *atomic* so that they are more likely to apply cleanly.  That means that each commit should contain the smallest possible logical change.  Don't commit two features at once, don't update the gemspec at the same time you add a feature, don't fix a whole bunch of whitespace in a file at the same time you change a few lines, etc, etc.
         | 
| 553 | 
            +
             | 
| 554 | 
            +
            For significant changes, you may wish to discuss your idea on the Formtastic Google group before coding to ensure that your change is likely to be accepted.  Formtastic relies heavily on i18n, so if you're unsure of the impact this has on your changes, please discuss them with the group.
         | 
| 555 | 
            +
             | 
| 556 | 
            +
             | 
| 557 | 
            +
            h2. Maintainers & Contributors
         | 
| 501 558 |  | 
| 502 | 
            -
            Formtastic is maintained by "Justin French":http://justinfrench.com, "José Valim":http://github.com/josevalim and "Jonas Grimfelt":http://github.com/grimen, but it wouldn't be as awesome as it is today without help from over  | 
| 559 | 
            +
            Formtastic is maintained by "Justin French":http://justinfrench.com, "José Valim":http://github.com/josevalim and "Jonas Grimfelt":http://github.com/grimen, but it wouldn't be as awesome as it is today without help from over 40 contributors.
         | 
| 503 560 |  | 
| 504 561 | 
             
            @git shortlog -n -s --no-merges@
         | 
| 505 562 |  | 
    
        data/Rakefile
    CHANGED
    
    | @@ -27,7 +27,7 @@ begin | |
| 27 27 | 
             
              a config initializer into your application:
         | 
| 28 28 | 
             
                ./script/generate formtastic
         | 
| 29 29 |  | 
| 30 | 
            -
              To generate some semantic form markup for your  | 
| 30 | 
            +
              To generate some semantic form markup for your existing models, just run:
         | 
| 31 31 | 
             
                ./script/generate form MODEL_NAME
         | 
| 32 32 |  | 
| 33 33 | 
             
              Find out more and get involved:
         | 
| @@ -1,5 +1,5 @@ | |
| 1 | 
            -
            <%%  | 
| 1 | 
            +
            <%% f.inputs do %>
         | 
| 2 2 | 
             
            <% attributes.each do |attribute| -%>
         | 
| 3 | 
            -
              <%%=  | 
| 3 | 
            +
              <%%= f.input :<%= attribute.name %>, :label => '<%= attribute.name.humanize %>' %>
         | 
| 4 4 | 
             
            <% end -%>
         | 
| 5 5 | 
             
            <%% end %>
         | 
| @@ -19,7 +19,13 @@ form.formtastic ol, form.formtastic ul { list-style:none; } | |
| 19 19 | 
             
            form.formtastic abbr, form.formtastic acronym { border:0; font-variant:normal; }
         | 
| 20 20 | 
             
            form.formtastic input, form.formtastic textarea, form.formtastic select { font-family:inherit; font-size:inherit; font-weight:inherit; }
         | 
| 21 21 | 
             
            form.formtastic input, form.formtastic textarea, form.formtastic select { font-size:100%; }
         | 
| 22 | 
            -
            form.formtastic legend { color:#000; }
         | 
| 22 | 
            +
            form.formtastic legend { white-space:normal; color:#000; }
         | 
| 23 | 
            +
             | 
| 24 | 
            +
             | 
| 25 | 
            +
            /* SEMANTIC ERRORS
         | 
| 26 | 
            +
            --------------------------------------------------------------------------------------------------*/
         | 
| 27 | 
            +
            form.formtastic ul.errors { color:#cc0000; margin:0.5em 0 1.5em 25%; list-style:square; }
         | 
| 28 | 
            +
            form.formtastic ul.errors li { padding:0; border:none; display:list-item; }
         | 
| 23 29 |  | 
| 24 30 |  | 
| 25 31 | 
             
            /* FIELDSETS & LISTS
         | 
| @@ -39,100 +45,102 @@ html[xmlns] form.formtastic fieldset { display: block; } | |
| 39 45 |  | 
| 40 46 | 
             
            /* INPUT LIs
         | 
| 41 47 | 
             
            --------------------------------------------------------------------------------------------------*/
         | 
| 42 | 
            -
            form.formtastic fieldset ol li { margin-bottom:1.5em; }
         | 
| 48 | 
            +
            form.formtastic fieldset > ol > li { margin-bottom:1.5em; }
         | 
| 43 49 |  | 
| 44 50 | 
             
            /* clearfixing the li's */
         | 
| 45 | 
            -
            form.formtastic fieldset ol li { display: inline-block; }
         | 
| 46 | 
            -
            form.formtastic fieldset ol li:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
         | 
| 47 | 
            -
            html[xmlns] form.formtastic fieldset ol li { display: block; }
         | 
| 48 | 
            -
            * html form.formtastic fieldset ol li { height: 1%; }
         | 
| 49 | 
            -
             | 
| 50 | 
            -
            form.formtastic fieldset ol li.required { }
         | 
| 51 | 
            -
            form.formtastic fieldset ol li.optional { }
         | 
| 52 | 
            -
            form.formtastic fieldset ol li.error { }
         | 
| 51 | 
            +
            form.formtastic fieldset > ol > li { display: inline-block; }
         | 
| 52 | 
            +
            form.formtastic fieldset > ol > li:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
         | 
| 53 | 
            +
            html[xmlns] form.formtastic fieldset > ol > li { display: block; }
         | 
| 54 | 
            +
            * html form.formtastic fieldset > ol > li { height: 1%; }
         | 
| 55 | 
            +
             | 
| 56 | 
            +
            form.formtastic fieldset > ol > li.required { }
         | 
| 57 | 
            +
            form.formtastic fieldset > ol > li.optional { }
         | 
| 58 | 
            +
            form.formtastic fieldset > ol > li.error { }
         | 
| 53 59 |  | 
| 54 60 |  | 
| 55 61 | 
             
            /* LABELS
         | 
| 56 62 | 
             
            --------------------------------------------------------------------------------------------------*/
         | 
| 57 | 
            -
            form.formtastic fieldset ol li label { display:block; width:25%; float:left; padding-top:.2em; }
         | 
| 58 | 
            -
            form.formtastic fieldset ol li li label { line-height:100%; padding-top:0; }
         | 
| 59 | 
            -
            form.formtastic fieldset ol li li label input { line-height:100%; vertical-align:middle; margin-top:-0.1em;}
         | 
| 63 | 
            +
            form.formtastic fieldset > ol > li label { display:block; width:25%; float:left; padding-top:.2em; }
         | 
| 64 | 
            +
            form.formtastic fieldset > ol > li > li label { line-height:100%; padding-top:0; }
         | 
| 65 | 
            +
            form.formtastic fieldset > ol > li > li label input { line-height:100%; vertical-align:middle; margin-top:-0.1em;}
         | 
| 60 66 |  | 
| 61 67 |  | 
| 62 68 | 
             
            /* NESTED FIELDSETS AND LEGENDS (radio, check boxes and date/time inputs use nested fieldsets)
         | 
| 63 69 | 
             
            --------------------------------------------------------------------------------------------------*/
         | 
| 64 | 
            -
            form.formtastic fieldset ol li fieldset { position:relative; }
         | 
| 65 | 
            -
            form.formtastic fieldset ol li fieldset legend { position:absolute; width: | 
| 66 | 
            -
            form.formtastic fieldset ol li fieldset legend span { position:absolute; }
         | 
| 67 | 
            -
            form.formtastic fieldset ol li fieldset legend.label label { position:absolute; }
         | 
| 68 | 
            -
            form.formtastic fieldset ol li fieldset ol { float:left; width:74%; margin:0; padding:0 0 0 25%; }
         | 
| 69 | 
            -
            form.formtastic fieldset ol li fieldset ol li { padding:0; border:0; }
         | 
| 70 | 
            +
            form.formtastic fieldset > ol > li fieldset { position:relative; }
         | 
| 71 | 
            +
            form.formtastic fieldset > ol > li fieldset legend { position:absolute; width:95%; padding-top:0.1em; left: 0px; }
         | 
| 72 | 
            +
            form.formtastic fieldset > ol > li fieldset legend span { position:absolute; }
         | 
| 73 | 
            +
            form.formtastic fieldset > ol > li fieldset legend.label label { position:absolute; }
         | 
| 74 | 
            +
            form.formtastic fieldset > ol > li fieldset ol { float:left; width:74%; margin:0; padding:0 0 0 25%; }
         | 
| 75 | 
            +
            form.formtastic fieldset > ol > li fieldset ol li { padding:0; border:0; }
         | 
| 70 76 |  | 
| 71 77 |  | 
| 72 78 | 
             
            /* INLINE HINTS
         | 
| 73 79 | 
             
            --------------------------------------------------------------------------------------------------*/
         | 
| 74 | 
            -
            form.formtastic fieldset ol li p.inline-hints { color:#666; margin:0.5em 0 0 25%; }
         | 
| 80 | 
            +
            form.formtastic fieldset > ol > li p.inline-hints { color:#666; margin:0.5em 0 0 25%; }
         | 
| 75 81 |  | 
| 76 82 |  | 
| 77 83 | 
             
            /* INLINE ERRORS
         | 
| 78 84 | 
             
            --------------------------------------------------------------------------------------------------*/
         | 
| 79 | 
            -
            form.formtastic fieldset ol li p.inline-errors { color:#cc0000; margin:0.5em 0 0 25%; }
         | 
| 80 | 
            -
            form.formtastic fieldset ol li ul.errors { color:#cc0000; margin:0.5em 0 0 25%; list-style:square; }
         | 
| 81 | 
            -
            form.formtastic fieldset ol li ul.errors li { padding:0; border:none; display:list-item; }
         | 
| 85 | 
            +
            form.formtastic fieldset > ol > li p.inline-errors { color:#cc0000; margin:0.5em 0 0 25%; }
         | 
| 86 | 
            +
            form.formtastic fieldset > ol > li ul.errors { color:#cc0000; margin:0.5em 0 0 25%; list-style:square; }
         | 
| 87 | 
            +
            form.formtastic fieldset > ol > li ul.errors li { padding:0; border:none; display:list-item; }
         | 
| 82 88 |  | 
| 83 89 |  | 
| 84 90 | 
             
            /* STRING & NUMERIC OVERRIDES
         | 
| 85 91 | 
             
            --------------------------------------------------------------------------------------------------*/
         | 
| 86 | 
            -
            form.formtastic fieldset ol li.string input { width:74%; }
         | 
| 87 | 
            -
            form.formtastic fieldset ol li.password input { width: | 
| 88 | 
            -
            form.formtastic fieldset ol li.numeric input { width:74%; }
         | 
| 92 | 
            +
            form.formtastic fieldset > ol > li.string input { max-width:74%; }
         | 
| 93 | 
            +
            form.formtastic fieldset > ol > li.password input { max-width: 13em; }
         | 
| 94 | 
            +
            form.formtastic fieldset > ol > li.numeric input { max-width:74%; }
         | 
| 89 95 |  | 
| 90 96 |  | 
| 91 97 | 
             
            /* TEXTAREA OVERRIDES
         | 
| 92 98 | 
             
            --------------------------------------------------------------------------------------------------*/
         | 
| 93 | 
            -
            form.formtastic fieldset ol li.text textarea { width:74%; }
         | 
| 99 | 
            +
            form.formtastic fieldset > ol > li.text textarea { width:74%; }
         | 
| 94 100 |  | 
| 95 101 |  | 
| 96 102 | 
             
            /* HIDDEN OVERRIDES
         | 
| 103 | 
            +
            The dual declarations are required because of our clearfix display hack on the LIs, which is more
         | 
| 104 | 
            +
            specific than the more general rule below. TODO: Revist the clearing hack and this rule.
         | 
| 97 105 | 
             
            --------------------------------------------------------------------------------------------------*/
         | 
| 98 | 
            -
            form.formtastic fieldset ol li.hidden | 
| 99 | 
            -
             | 
| 106 | 
            +
            form.formtastic fieldset ol li.hidden,
         | 
| 107 | 
            +
            html[xmlns] form.formtastic fieldset ol li.hidden { display:none; }
         | 
| 100 108 |  | 
| 101 109 | 
             
            /* BOOLEAN OVERRIDES
         | 
| 102 110 | 
             
            --------------------------------------------------------------------------------------------------*/
         | 
| 103 | 
            -
            form.formtastic fieldset ol li.boolean label { padding-left:25%; width:auto; }
         | 
| 104 | 
            -
            form.formtastic fieldset ol li.boolean label input { margin:0 0.5em 0 0.2em; }
         | 
| 111 | 
            +
            form.formtastic fieldset > ol > li.boolean label { padding-left:25%; width:auto; }
         | 
| 112 | 
            +
            form.formtastic fieldset > ol > li.boolean label input { margin:0 0.5em 0 0.2em; }
         | 
| 105 113 |  | 
| 106 114 |  | 
| 107 115 | 
             
            /* RADIO OVERRIDES
         | 
| 108 116 | 
             
            --------------------------------------------------------------------------------------------------*/
         | 
| 109 | 
            -
            form.formtastic fieldset ol li.radio { }
         | 
| 110 | 
            -
            form.formtastic fieldset ol li.radio fieldset ol { margin-bottom:-0.6em; }
         | 
| 111 | 
            -
            form.formtastic fieldset ol li.radio fieldset ol li { margin:0.1em 0 0.5em 0; }
         | 
| 112 | 
            -
            form.formtastic fieldset ol li.radio fieldset ol li label { float:none; width:100%; }
         | 
| 113 | 
            -
            form.formtastic fieldset ol li.radio fieldset ol li label input { margin-right:0.2em; }
         | 
| 117 | 
            +
            form.formtastic fieldset > ol > li.radio { }
         | 
| 118 | 
            +
            form.formtastic fieldset > ol > li.radio fieldset ol { margin-bottom:-0.6em; }
         | 
| 119 | 
            +
            form.formtastic fieldset > ol > li.radio fieldset ol li { margin:0.1em 0 0.5em 0; }
         | 
| 120 | 
            +
            form.formtastic fieldset > ol > li.radio fieldset ol li label { float:none; width:100%; }
         | 
| 121 | 
            +
            form.formtastic fieldset > ol > li.radio fieldset ol li label input { margin-right:0.2em; }
         | 
| 114 122 |  | 
| 115 123 |  | 
| 116 124 | 
             
            /* CHECK BOXES (COLLECTION) OVERRIDES
         | 
| 117 125 | 
             
            --------------------------------------------------------------------------------------------------*/
         | 
| 118 | 
            -
            form.formtastic fieldset ol li.check_boxes { }
         | 
| 119 | 
            -
            form.formtastic fieldset ol li.check_boxes fieldset ol { margin-bottom:-0.6em; }
         | 
| 120 | 
            -
            form.formtastic fieldset ol li.check_boxes fieldset ol li { margin:0.1em 0 0.5em 0; }
         | 
| 121 | 
            -
            form.formtastic fieldset ol li.check_boxes fieldset ol li label { float:none; width:100%; }
         | 
| 122 | 
            -
            form.formtastic fieldset ol li.check_boxes fieldset ol li label input { margin-right:0.2em; }
         | 
| 126 | 
            +
            form.formtastic fieldset > ol > li.check_boxes { }
         | 
| 127 | 
            +
            form.formtastic fieldset > ol > li.check_boxes fieldset ol { margin-bottom:-0.6em; }
         | 
| 128 | 
            +
            form.formtastic fieldset > ol > li.check_boxes fieldset ol li { margin:0.1em 0 0.5em 0; }
         | 
| 129 | 
            +
            form.formtastic fieldset > ol > li.check_boxes fieldset ol li label { float:none; width:100%; }
         | 
| 130 | 
            +
            form.formtastic fieldset > ol > li.check_boxes fieldset ol li label input { margin-right:0.2em; }
         | 
| 123 131 |  | 
| 124 132 |  | 
| 125 133 |  | 
| 126 134 | 
             
            /* DATE & TIME OVERRIDES
         | 
| 127 135 | 
             
            --------------------------------------------------------------------------------------------------*/
         | 
| 128 | 
            -
            form.formtastic fieldset ol li.date fieldset ol li,
         | 
| 129 | 
            -
            form.formtastic fieldset ol li.time fieldset ol li,
         | 
| 130 | 
            -
            form.formtastic fieldset ol li.datetime fieldset ol li { float:left; width:auto; margin:0 .3em 0 0; }
         | 
| 136 | 
            +
            form.formtastic fieldset > ol > li.date fieldset ol li,
         | 
| 137 | 
            +
            form.formtastic fieldset > ol > li.time fieldset ol li,
         | 
| 138 | 
            +
            form.formtastic fieldset > ol > li.datetime fieldset ol li { float:left; width:auto; margin:0 .3em 0 0; }
         | 
| 131 139 |  | 
| 132 | 
            -
            form.formtastic fieldset ol li.date fieldset ol li label,
         | 
| 133 | 
            -
            form.formtastic fieldset ol li.time fieldset ol li label,
         | 
| 134 | 
            -
            form.formtastic fieldset ol li.datetime fieldset ol li label { display:none; }
         | 
| 140 | 
            +
            form.formtastic fieldset > ol > li.date fieldset ol li label,
         | 
| 141 | 
            +
            form.formtastic fieldset > ol > li.time fieldset ol li label,
         | 
| 142 | 
            +
            form.formtastic fieldset > ol > li.datetime fieldset ol li label { display:none; }
         | 
| 135 143 |  | 
| 136 | 
            -
            form.formtastic fieldset ol li.date fieldset ol li label input, 
         | 
| 137 | 
            -
            form.formtastic fieldset ol li.time fieldset ol li label input, 
         | 
| 138 | 
            -
            form.formtastic fieldset ol li.datetime fieldset ol li label input { display:inline; margin:0; padding:0;  }
         | 
| 144 | 
            +
            form.formtastic fieldset > ol > li.date fieldset ol li label input, 
         | 
| 145 | 
            +
            form.formtastic fieldset > ol > li.time fieldset ol li label input, 
         | 
| 146 | 
            +
            form.formtastic fieldset > ol > li.datetime fieldset ol li label input { display:inline; margin:0; padding:0;  }
         | 
| @@ -1,6 +1,9 @@ | |
| 1 1 | 
             
            # Set the default text field size when input is a string. Default is 50.
         | 
| 2 2 | 
             
            # Formtastic::SemanticFormBuilder.default_text_field_size = 50
         | 
| 3 3 |  | 
| 4 | 
            +
            # Set the default text area height when input is a text. Default is 20.
         | 
| 5 | 
            +
            # Formtastic::SemanticFormBuilder.default_text_area_height = 5
         | 
| 6 | 
            +
             | 
| 4 7 | 
             
            # Should all fields be considered "required" by default?
         | 
| 5 8 | 
             
            # Defaults to true, see ValidationReflection notes below.
         | 
| 6 9 | 
             
            # Formtastic::SemanticFormBuilder.all_fields_required_by_default = true
         | 
| @@ -5,6 +5,10 @@ This will allow you to update formtastic.css with new releases without clobberin | |
| 5 5 |  | 
| 6 6 | 
             
            For example, to make the inline hint paragraphs a little darker in color than the standard #666:
         | 
| 7 7 |  | 
| 8 | 
            -
            form.formtastic fieldset ol li p.inline-hints { color:#333; }
         | 
| 8 | 
            +
            form.formtastic fieldset > ol > li p.inline-hints { color:#333; }
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            HINT:
         | 
| 11 | 
            +
            The following style may be *conditionally* included for improved support on older versions of IE(<8)
         | 
| 12 | 
            +
            form.formtastic fieldset ol li fieldset legend { margin-left: -6px;}
         | 
| 9 13 |  | 
| 10 14 | 
             
            --------------------------------------------------------------------------------------------------*/
         | 
    
        data/lib/formtastic.rb
    CHANGED
    
    | @@ -6,6 +6,7 @@ module Formtastic #:nodoc: | |
| 6 6 | 
             
              class SemanticFormBuilder < ActionView::Helpers::FormBuilder
         | 
| 7 7 |  | 
| 8 8 | 
             
                @@default_text_field_size = 50
         | 
| 9 | 
            +
                @@default_text_area_height = 20
         | 
| 9 10 | 
             
                @@all_fields_required_by_default = true
         | 
| 10 11 | 
             
                @@include_blank_for_select_by_default = true
         | 
| 11 12 | 
             
                @@required_string = proc { %{<abbr title="#{::Formtastic::I18n.t(:required)}">*</abbr>} }
         | 
| @@ -14,12 +15,12 @@ module Formtastic #:nodoc: | |
| 14 15 | 
             
                @@label_str_method = :humanize
         | 
| 15 16 | 
             
                @@collection_label_methods = %w[to_label display_name full_name name title username login value to_s]
         | 
| 16 17 | 
             
                @@inline_order = [ :input, :hints, :errors ]
         | 
| 17 | 
            -
                @@file_methods = [ :file?, :public_filename ]
         | 
| 18 | 
            +
                @@file_methods = [ :file?, :public_filename, :filename ]
         | 
| 18 19 | 
             
                @@priority_countries = ["Australia", "Canada", "United Kingdom", "United States"]
         | 
| 19 20 | 
             
                @@i18n_lookups_by_default = false
         | 
| 20 21 | 
             
                @@default_commit_button_accesskey = nil 
         | 
| 21 22 |  | 
| 22 | 
            -
                cattr_accessor :default_text_field_size, :all_fields_required_by_default, :include_blank_for_select_by_default,
         | 
| 23 | 
            +
                cattr_accessor :default_text_field_size, :default_text_area_height, :all_fields_required_by_default, :include_blank_for_select_by_default,
         | 
| 23 24 | 
             
                               :required_string, :optional_string, :inline_errors, :label_str_method, :collection_label_methods,
         | 
| 24 25 | 
             
                               :inline_order, :file_methods, :priority_countries, :i18n_lookups_by_default, :default_commit_button_accesskey 
         | 
| 25 26 |  | 
| @@ -75,6 +76,13 @@ module Formtastic #:nodoc: | |
| 75 76 | 
             
                #   <% end %>
         | 
| 76 77 | 
             
                #
         | 
| 77 78 | 
             
                def input(method, options = {})
         | 
| 79 | 
            +
                  if options.key?(:selected) || options.key?(:checked) || options.key?(:default)
         | 
| 80 | 
            +
                    ::ActiveSupport::Deprecation.warn(
         | 
| 81 | 
            +
                      "The :selected, :checked (and :default) options are deprecated in Formtastic and will be removed from 1.0. " <<
         | 
| 82 | 
            +
                      "Please set default values in your models (using an after_initialize callback) or in your controller set-up. " <<
         | 
| 83 | 
            +
                      "See http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html for more information.", caller)
         | 
| 84 | 
            +
                  end
         | 
| 85 | 
            +
                  
         | 
| 78 86 | 
             
                  options[:required] = method_required?(method) unless options.key?(:required)
         | 
| 79 87 | 
             
                  options[:as]     ||= default_input_type(method, options)
         | 
| 80 88 |  | 
| @@ -91,7 +99,7 @@ module Formtastic #:nodoc: | |
| 91 99 | 
             
                  end
         | 
| 92 100 |  | 
| 93 101 | 
             
                  input_parts = @@inline_order.dup
         | 
| 94 | 
            -
                  input_parts | 
| 102 | 
            +
                  input_parts = input_parts - [:errors, :hints] if options[:as] == :hidden
         | 
| 95 103 |  | 
| 96 104 | 
             
                  list_item_content = input_parts.map do |type|
         | 
| 97 105 | 
             
                    send(:"inline_#{type}_for", method, options)
         | 
| @@ -310,9 +318,17 @@ module Formtastic #:nodoc: | |
| 310 318 | 
             
                  options = args.extract_options!
         | 
| 311 319 | 
             
                  text = options.delete(:label) || args.shift
         | 
| 312 320 |  | 
| 313 | 
            -
                  if @object
         | 
| 321 | 
            +
                  if @object && @object.respond_to?(:new_record?)
         | 
| 314 322 | 
             
                    key = @object.new_record? ? :create : :update
         | 
| 315 | 
            -
                     | 
| 323 | 
            +
                    
         | 
| 324 | 
            +
                    # Deal with some complications with ActiveRecord::Base.human_name and two name models (eg UserPost)
         | 
| 325 | 
            +
                    # ActiveRecord::Base.human_name falls back to ActiveRecord::Base.name.humanize ("Userpost") 
         | 
| 326 | 
            +
                    # if there's no i18n, which is pretty crappy.  In this circumstance we want to detect this
         | 
| 327 | 
            +
                    # fall back (human_name == name.humanize) and do our own thing name.underscore.humanize ("User Post")
         | 
| 328 | 
            +
                    object_human_name = @object.class.human_name                # default is UserPost => "Userpost", but i18n may do better ("User post")
         | 
| 329 | 
            +
                    crappy_human_name = @object.class.name.humanize             # UserPost => "Userpost"
         | 
| 330 | 
            +
                    decent_human_name = @object.class.name.underscore.humanize  # UserPost => "User post"
         | 
| 331 | 
            +
                    object_name = (object_human_name == crappy_human_name) ? decent_human_name : object_human_name
         | 
| 316 332 | 
             
                  else
         | 
| 317 333 | 
             
                    key = :submit
         | 
| 318 334 | 
             
                    object_name = @object_name.to_s.send(@@label_str_method)
         | 
| @@ -414,6 +430,32 @@ module Formtastic #:nodoc: | |
| 414 430 | 
             
                end
         | 
| 415 431 | 
             
                alias :errors_on :inline_errors_for
         | 
| 416 432 |  | 
| 433 | 
            +
                # Generates error messages for given method names and for base.
         | 
| 434 | 
            +
                # You can pass a hash with html options that will be added to ul tag
         | 
| 435 | 
            +
                #
         | 
| 436 | 
            +
                # == Examples
         | 
| 437 | 
            +
                #
         | 
| 438 | 
            +
                #  f.semantic_errors # This will show only errors on base
         | 
| 439 | 
            +
                #  f.semantic_errors :state # This will show errors on base and state
         | 
| 440 | 
            +
                #  f.semantic_errors :state, :class => "awesome" # errors will be rendered in ul.awesome
         | 
| 441 | 
            +
                #
         | 
| 442 | 
            +
                def semantic_errors(*args)
         | 
| 443 | 
            +
                  html_options = args.extract_options!
         | 
| 444 | 
            +
                  full_errors = args.inject([]) do |array, method|
         | 
| 445 | 
            +
                    attribute = localized_string(method, method.to_sym, :label) || humanized_attribute_name(method)
         | 
| 446 | 
            +
                    errors = Array(@object.errors[method.to_sym]).to_sentence
         | 
| 447 | 
            +
                    errors.present? ? array << [attribute, errors].join(" ") : array ||= []
         | 
| 448 | 
            +
                  end
         | 
| 449 | 
            +
                  full_errors << @object.errors.on_base
         | 
| 450 | 
            +
                  full_errors.flatten!
         | 
| 451 | 
            +
                  full_errors.compact!
         | 
| 452 | 
            +
                  return nil if full_errors.blank?
         | 
| 453 | 
            +
                  html_options[:class] ||= "errors"
         | 
| 454 | 
            +
                  template.content_tag(:ul, html_options) do
         | 
| 455 | 
            +
                    full_errors.map { |error| template.content_tag(:li, error) }.join
         | 
| 456 | 
            +
                  end
         | 
| 457 | 
            +
                end
         | 
| 458 | 
            +
             | 
| 417 459 | 
             
                protected
         | 
| 418 460 |  | 
| 419 461 | 
             
                  def render_inline_errors?
         | 
| @@ -523,7 +565,7 @@ module Formtastic #:nodoc: | |
| 523 565 |  | 
| 524 566 | 
             
                  def basic_input_helper(form_helper_method, type, method, options) #:nodoc:
         | 
| 525 567 | 
             
                    html_options = options.delete(:input_html) || {}
         | 
| 526 | 
            -
                    html_options = default_string_options(method, type).merge(html_options) if [:numeric, :string, :password].include?(type)
         | 
| 568 | 
            +
                    html_options = default_string_options(method, type).merge(html_options) if [:numeric, :string, :password, :text].include?(type)
         | 
| 527 569 |  | 
| 528 570 | 
             
                    self.label(method, options_for_label(options)) <<
         | 
| 529 571 | 
             
                    self.send(form_helper_method, method, html_options)
         | 
| @@ -825,13 +867,15 @@ module Formtastic #:nodoc: | |
| 825 867 | 
             
                      template.content_tag(:li, li_content, li_options)
         | 
| 826 868 | 
             
                    end
         | 
| 827 869 |  | 
| 828 | 
            -
                    field_set_and_list_wrapping_for_method(method, options | 
| 870 | 
            +
                    field_set_and_list_wrapping_for_method(method, options, list_item_content)
         | 
| 829 871 | 
             
                  end
         | 
| 830 872 | 
             
                  alias :boolean_radio_input :radio_input
         | 
| 831 873 |  | 
| 832 874 | 
             
                  # Outputs a fieldset with a legend for the method label, and a ordered list (ol) of list
         | 
| 833 875 | 
             
                  # items (li), one for each fragment for the date (year, month, day).  Each li contains a label
         | 
| 834 | 
            -
                  # (eg "Year") and a select box. | 
| 876 | 
            +
                  # (eg "Year") and a select box. Overwriting the label is possible by adding the :labels option.
         | 
| 877 | 
            +
                  # :labels should be a hash with the field (e.g. day) as key and the label text as value.
         | 
| 878 | 
            +
                  # See date_or_datetime_input for a more detailed output example.
         | 
| 835 879 | 
             
                  #
         | 
| 836 880 | 
             
                  # You can pre-select a specific option value by passing in the :selected option.
         | 
| 837 881 | 
             
                  # 
         | 
| @@ -839,9 +883,10 @@ module Formtastic #:nodoc: | |
| 839 883 | 
             
                  # 
         | 
| 840 884 | 
             
                  #   f.input :created_at, :as => :date, :selected => 1.day.ago
         | 
| 841 885 | 
             
                  #   f.input :created_at, :as => :date, :selected => nil   # override any defaults: select none
         | 
| 886 | 
            +
                  #   f.input :created_at, :as => :date, :labels => { :year => "Year", :month => "Month", :day => "Day" }
         | 
| 842 887 | 
             
                  #
         | 
| 843 | 
            -
                  # Some of Rails' options for select_date are supported, but not everything yet | 
| 844 | 
            -
                  #
         | 
| 888 | 
            +
                  # Some of Rails' options for select_date are supported, but not everything yet, see 
         | 
| 889 | 
            +
                  # documentation of date_or_datetime_input() for more information.
         | 
| 845 890 | 
             
                  def date_input(method, options)
         | 
| 846 891 | 
             
                    options = set_include_blank(options)
         | 
| 847 892 | 
             
                    date_or_datetime_input(method, options.merge(:discard_hour => true))
         | 
| @@ -849,8 +894,9 @@ module Formtastic #:nodoc: | |
| 849 894 |  | 
| 850 895 | 
             
                  # Outputs a fieldset with a legend for the method label, and a ordered list (ol) of list
         | 
| 851 896 | 
             
                  # items (li), one for each fragment for the date (year, month, day, hour, min, sec).  Each li
         | 
| 852 | 
            -
                  # contains a label (eg "Year") and a select box. | 
| 853 | 
            -
                  #  | 
| 897 | 
            +
                  # contains a label (eg "Year") and a select box. Overwriting the label is possible by adding
         | 
| 898 | 
            +
                  # the :labels option. :labels should be a hash with the field (e.g. day) as key and the label
         | 
| 899 | 
            +
                  # text as value.  See date_or_datetime_input for a more detailed output example.
         | 
| 854 900 | 
             
                  #
         | 
| 855 901 | 
             
                  # You can pre-select a specific option value by passing in the :selected option.
         | 
| 856 902 | 
             
                  # 
         | 
| @@ -858,9 +904,11 @@ module Formtastic #:nodoc: | |
| 858 904 | 
             
                  # 
         | 
| 859 905 | 
             
                  #   f.input :created_at, :as => :datetime, :selected => 1.day.ago
         | 
| 860 906 | 
             
                  #   f.input :created_at, :as => :datetime, :selected => nil   # override any defaults: select none
         | 
| 907 | 
            +
                  #   f.input :created_at, :as => :date, :labels => { :year => "Year", :month => "Month", :day => "Day",
         | 
| 908 | 
            +
                  #                                                   :hour => "Hour", :minute => "Minute" }
         | 
| 861 909 | 
             
                  #
         | 
| 862 | 
            -
                  # Some of Rails' options for select_date are supported, but not everything yet | 
| 863 | 
            -
                  #
         | 
| 910 | 
            +
                  # Some of Rails' options for select_date are supported, but not everything yet, see 
         | 
| 911 | 
            +
                  # documentation of date_or_datetime_input() for more information.
         | 
| 864 912 | 
             
                  def datetime_input(method, options)
         | 
| 865 913 | 
             
                    options = set_include_blank(options)
         | 
| 866 914 | 
             
                    date_or_datetime_input(method, options)
         | 
| @@ -868,7 +916,9 @@ module Formtastic #:nodoc: | |
| 868 916 |  | 
| 869 917 | 
             
                  # Outputs a fieldset with a legend for the method label, and a ordered list (ol) of list
         | 
| 870 918 | 
             
                  # items (li), one for each fragment for the time (hour, minute, second).  Each li contains a label
         | 
| 871 | 
            -
                  # (eg "Hour") and a select box. | 
| 919 | 
            +
                  # (eg "Hour") and a select box. Overwriting the label is possible by adding the :labels option.
         | 
| 920 | 
            +
                  # :labels should be a hash with the field (e.g. day) as key and the label text as value.
         | 
| 921 | 
            +
                  # See date_or_datetime_input for a more detailed output example.
         | 
| 872 922 | 
             
                  #
         | 
| 873 923 | 
             
                  # You can pre-select a specific option value by passing in the :selected option.
         | 
| 874 924 | 
             
                  # 
         | 
| @@ -876,14 +926,19 @@ module Formtastic #:nodoc: | |
| 876 926 | 
             
                  # 
         | 
| 877 927 | 
             
                  #   f.input :created_at, :as => :time, :selected => 1.hour.ago
         | 
| 878 928 | 
             
                  #   f.input :created_at, :as => :time, :selected => nil   # override any defaults: select none
         | 
| 929 | 
            +
                  #   f.input :created_at, :as => :date, :labels => { :hour => "Hour", :minute => "Minute" }
         | 
| 879 930 | 
             
                  #
         | 
| 880 | 
            -
                  # Some of Rails' options for select_time are supported, but not everything yet | 
| 881 | 
            -
                  #
         | 
| 931 | 
            +
                  # Some of Rails' options for select_time are supported, but not everything yet, see 
         | 
| 932 | 
            +
                  # documentation of date_or_datetime_input() for more information.
         | 
| 882 933 | 
             
                  def time_input(method, options)
         | 
| 883 934 | 
             
                    options = set_include_blank(options)
         | 
| 884 935 | 
             
                    date_or_datetime_input(method, options.merge(:discard_year => true, :discard_month => true, :discard_day => true))
         | 
| 885 936 | 
             
                  end
         | 
| 886 | 
            -
             | 
| 937 | 
            +
                  
         | 
| 938 | 
            +
                  # Helper method used by :as => (:date|:datetime|:time).  Generates a fieldset containing a 
         | 
| 939 | 
            +
                  # legend (for what would normally be considered the label), and an ordered list of list items 
         | 
| 940 | 
            +
                  # for year, month, day, hour, etc, each containing a label and a select.  Example:
         | 
| 941 | 
            +
                  #
         | 
| 887 942 | 
             
                  # <fieldset>
         | 
| 888 943 | 
             
                  #   <legend>Created At</legend>
         | 
| 889 944 | 
             
                  #   <ol>
         | 
| @@ -916,23 +971,32 @@ module Formtastic #:nodoc: | |
| 916 971 | 
             
                  #
         | 
| 917 972 | 
             
                  # This is an absolute abomination, but so is the official Rails select_date().
         | 
| 918 973 | 
             
                  #
         | 
| 974 | 
            +
                  # Options:
         | 
| 975 | 
            +
                  #
         | 
| 976 | 
            +
                  #   * @:order => [:month, :day, :year]@
         | 
| 977 | 
            +
                  #   * @:include_seconds@ => true@
         | 
| 978 | 
            +
                  #   * @:selected => Time.mktime(2008)@
         | 
| 979 | 
            +
                  #   * @:selected => Date.new(2008)@
         | 
| 980 | 
            +
                  #   * @:selected => nil@
         | 
| 981 | 
            +
                  #   * @:discard_(year|month|day|hour|minute) => true@
         | 
| 982 | 
            +
                  #   * @:include_blank => true@
         | 
| 983 | 
            +
                  #   * @:labels => {}@
         | 
| 919 984 | 
             
                  def date_or_datetime_input(method, options)
         | 
| 920 985 | 
             
                    position = { :year => 1, :month => 2, :day => 3, :hour => 4, :minute => 5, :second => 6 }
         | 
| 921 986 | 
             
                    i18n_date_order = ::I18n.t(:order, :scope => [:date])
         | 
| 922 987 | 
             
                    i18n_date_order = nil unless i18n_date_order.is_a?(Array)
         | 
| 923 988 | 
             
                    inputs   = options.delete(:order) || i18n_date_order || [:year, :month, :day]
         | 
| 989 | 
            +
                    labels   = options.delete(:labels) || {}
         | 
| 924 990 |  | 
| 925 991 | 
             
                    time_inputs = [:hour, :minute]
         | 
| 926 | 
            -
                    time_inputs <<  | 
| 992 | 
            +
                    time_inputs << :second if options[:include_seconds]
         | 
| 927 993 |  | 
| 928 994 | 
             
                    list_items_capture = ""
         | 
| 929 995 | 
             
                    hidden_fields_capture = ""
         | 
| 930 996 |  | 
| 931 | 
            -
                     | 
| 997 | 
            +
                    datetime = options.key?(:selected) ? options[:selected] : Time.now # can't do an || because nil is an important value
         | 
| 998 | 
            +
                    datetime = @object.send(method) if @object && @object.send(method) # object trumps :selected
         | 
| 932 999 |  | 
| 933 | 
            -
                    # Gets the datetime object. It can be a Fixnum, Date or Time, or nil.
         | 
| 934 | 
            -
                    datetime = options[:selected] || (@object ? @object.send(method) : default_time) || default_time
         | 
| 935 | 
            -
                    
         | 
| 936 1000 | 
             
                    html_options = options.delete(:input_html) || {}
         | 
| 937 1001 | 
             
                    input_ids    = []
         | 
| 938 1002 |  | 
| @@ -943,15 +1007,16 @@ module Formtastic #:nodoc: | |
| 943 1007 | 
             
                      if options[:"discard_#{input}"]
         | 
| 944 1008 | 
             
                        break if time_inputs.include?(input)
         | 
| 945 1009 |  | 
| 946 | 
            -
                        hidden_value = datetime.respond_to?(input) ? datetime.send(input | 
| 1010 | 
            +
                        hidden_value = datetime.respond_to?(input) ? datetime.send(input) : datetime
         | 
| 947 1011 | 
             
                        hidden_fields_capture << template.hidden_field_tag("#{@object_name}[#{field_name}]", (hidden_value || 1), :id => input_id)
         | 
| 948 1012 | 
             
                      else
         | 
| 949 1013 | 
             
                        opts = strip_formtastic_options(options).merge(:prefix => @object_name, :field_name => field_name, :default => datetime)
         | 
| 950 | 
            -
                        item_label_text = ::I18n.t(input.to_s, :default => input.to_s.humanize, :scope => [:datetime, :prompts])
         | 
| 1014 | 
            +
                        item_label_text = labels[input] || ::I18n.t(input.to_s, :default => input.to_s.humanize, :scope => [:datetime, :prompts])
         | 
| 951 1015 |  | 
| 952 | 
            -
                        list_items_capture << template.content_tag(:li,
         | 
| 953 | 
            -
             | 
| 954 | 
            -
             | 
| 1016 | 
            +
                        list_items_capture << template.content_tag(:li, [
         | 
| 1017 | 
            +
                            !item_label_text.blank? ? template.content_tag(:label, item_label_text, :for => input_id) : "",
         | 
| 1018 | 
            +
                            template.send(:"select_#{input}", datetime, opts, html_options.merge(:id => input_id))
         | 
| 1019 | 
            +
                          ].join("")
         | 
| 955 1020 | 
             
                        )
         | 
| 956 1021 | 
             
                      end
         | 
| 957 1022 | 
             
                    end
         | 
| @@ -1064,7 +1129,7 @@ module Formtastic #:nodoc: | |
| 1064 1129 | 
             
                      template.content_tag(:li, li_content, li_options)
         | 
| 1065 1130 | 
             
                    end
         | 
| 1066 1131 |  | 
| 1067 | 
            -
                    field_set_and_list_wrapping_for_method(method, options | 
| 1132 | 
            +
                    field_set_and_list_wrapping_for_method(method, options, list_item_content)
         | 
| 1068 1133 | 
             
                  end
         | 
| 1069 1134 |  | 
| 1070 1135 | 
             
                  # Outputs a country select input, wrapping around a regular country_select helper. 
         | 
| @@ -1406,7 +1471,7 @@ module Formtastic #:nodoc: | |
| 1406 1471 | 
             
                      if [:has_and_belongs_to_many, :has_many].include?(reflection.macro)
         | 
| 1407 1472 | 
             
                        "#{method.to_s.singularize}_ids"
         | 
| 1408 1473 | 
             
                      else
         | 
| 1409 | 
            -
                        reflection.options[:foreign_key] || "#{method}_id"
         | 
| 1474 | 
            +
                        reflection.options[:foreign_key] || reflection.options[:class_name].try(:foreign_key) || "#{method}_id"
         | 
| 1410 1475 | 
             
                      end
         | 
| 1411 1476 | 
             
                    else
         | 
| 1412 1477 | 
             
                      method
         | 
| @@ -1432,7 +1497,9 @@ module Formtastic #:nodoc: | |
| 1432 1497 | 
             
                  def default_string_options(method, type) #:nodoc:
         | 
| 1433 1498 | 
             
                    column = self.column_for(method)
         | 
| 1434 1499 |  | 
| 1435 | 
            -
                    if type == : | 
| 1500 | 
            +
                    if type == :text
         | 
| 1501 | 
            +
                      { :cols => @@default_text_field_size, :rows => @@default_text_area_height }
         | 
| 1502 | 
            +
                    elsif type == :numeric || column.nil? || column.limit.nil?
         | 
| 1436 1503 | 
             
                      { :size => @@default_text_field_size }
         | 
| 1437 1504 | 
             
                    else
         | 
| 1438 1505 | 
             
                      { :maxlength => column.limit, :size => [column.limit, @@default_text_field_size].min }
         | 
| @@ -1479,7 +1546,12 @@ module Formtastic #:nodoc: | |
| 1479 1546 |  | 
| 1480 1547 | 
             
                  def humanized_attribute_name(method) #:nodoc:
         | 
| 1481 1548 | 
             
                    if @object && @object.class.respond_to?(:human_attribute_name)
         | 
| 1482 | 
            -
                      @object.class.human_attribute_name(method.to_s)
         | 
| 1549 | 
            +
                      humanized_name = @object.class.human_attribute_name(method.to_s)
         | 
| 1550 | 
            +
                      if humanized_name == method.to_s.send(:humanize)
         | 
| 1551 | 
            +
                        method.to_s.send(@@label_str_method)
         | 
| 1552 | 
            +
                      else
         | 
| 1553 | 
            +
                        humanized_name
         | 
| 1554 | 
            +
                      end
         | 
| 1483 1555 | 
             
                    else
         | 
| 1484 1556 | 
             
                      method.to_s.send(@@label_str_method)
         | 
| 1485 1557 | 
             
                    end
         | 
| @@ -1612,18 +1684,18 @@ module Formtastic #:nodoc: | |
| 1612 1684 | 
             
                end
         | 
| 1613 1685 |  | 
| 1614 1686 | 
             
                [:form_for, :fields_for, :remote_form_for].each do |meth|
         | 
| 1615 | 
            -
                   | 
| 1687 | 
            +
                  module_eval <<-END_SRC, __FILE__, __LINE__ + 1
         | 
| 1616 1688 | 
             
                    def semantic_#{meth}(record_or_name_or_array, *args, &proc)
         | 
| 1617 1689 | 
             
                      options = args.extract_options!
         | 
| 1618 1690 | 
             
                      options[:builder] ||= @@builder
         | 
| 1619 1691 | 
             
                      options[:html] ||= {}
         | 
| 1620 | 
            -
             | 
| 1692 | 
            +
             | 
| 1621 1693 | 
             
                      class_names = options[:html][:class] ? options[:html][:class].split(" ") : []
         | 
| 1622 1694 | 
             
                      class_names << "formtastic"
         | 
| 1623 1695 | 
             
                      class_names << case record_or_name_or_array
         | 
| 1624 1696 | 
             
                        when String, Symbol then record_or_name_or_array.to_s               # :post => "post"
         | 
| 1625 | 
            -
                        when Array then record_or_name_or_array.last.class | 
| 1626 | 
            -
                        else record_or_name_or_array.class | 
| 1697 | 
            +
                        when Array then ActionController::RecordIdentifier.singular_class_name(record_or_name_or_array.last.class)  # [@post, @comment] # => "comment"
         | 
| 1698 | 
            +
                        else ActionController::RecordIdentifier.singular_class_name(record_or_name_or_array.class)                  # @post => "post"
         | 
| 1627 1699 | 
             
                      end
         | 
| 1628 1700 | 
             
                      options[:html][:class] = class_names.join(" ")
         | 
| 1629 1701 |  | 
| @@ -1632,7 +1704,6 @@ module Formtastic #:nodoc: | |
| 1632 1704 | 
             
                      end
         | 
| 1633 1705 | 
             
                    end
         | 
| 1634 1706 | 
             
                  END_SRC
         | 
| 1635 | 
            -
                  module_eval src, __FILE__, __LINE__
         | 
| 1636 1707 | 
             
                end
         | 
| 1637 1708 | 
             
                alias :semantic_form_remote_for :semantic_remote_form_for
         | 
| 1638 1709 |  |