merb_helpers 0.9.4 → 0.9.5

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.
@@ -0,0 +1,410 @@
1
+ # Form helpers provide a number of methods to simplify the creation of HTML forms.
2
+ # They can work directly with models (bound) or standalone (unbound).
3
+ #
4
+ # The core method of this helper, +form_for+, gives you the ability to create a form for a resource.
5
+ # For example, let's say that you have a model <tt>Person</tt> and want to create a new instance of it:
6
+ module Merb::Helpers::Form
7
+
8
+ def _singleton_form_context
9
+ @_singleton_form_context ||=
10
+ self._form_class.new(nil, nil, self)
11
+ end
12
+
13
+ def form_contexts
14
+ @_form_contexts ||= []
15
+ end
16
+
17
+ def current_form_context
18
+ form_contexts.last || _singleton_form_context
19
+ end
20
+
21
+ def _new_form_context(name, builder)
22
+ if name.is_a?(String) || name.is_a?(Symbol)
23
+ ivar = instance_variable_get("@#{name}")
24
+ else
25
+ ivar, name = name, name.class.to_s.snake_case
26
+ end
27
+ builder ||= current_form_context.class if current_form_context
28
+ (builder || self._form_class).new(ivar, name, self)
29
+ end
30
+
31
+ def with_form_context(name, builder)
32
+ form_contexts.push(_new_form_context(name, builder))
33
+ ret = yield
34
+ form_contexts.pop
35
+ ret
36
+ end
37
+
38
+ # Generates a form tag, which accepts a block that is not directly based on resource attributes
39
+ #
40
+ # ==== Parameters
41
+ # attrs<Hash>:: HTML attributes
42
+ #
43
+ # ==== Returns
44
+ # String:: HTML
45
+ #
46
+ # ==== Notes
47
+ # * Block helpers use the <%= =%> syntax
48
+ # * a multipart enctype is automatically set if the form contains a file upload field
49
+ #
50
+ # ==== Example
51
+ # <%= form :action => url(:controller => "foo", :action => "bar", :id => 1) do %>
52
+ # <%= text_field :name => "first_name", :label => "First Name" %>
53
+ # <%= submit "Create" %>
54
+ # <% end =%>
55
+ #
56
+ # Generates the HTML:
57
+ #
58
+ # <form action="/foo/bar/1" method="post">
59
+ # <label for="first_name">First Name</label>
60
+ # <input type="text" id="first_name" name="first_name" />
61
+ # <input type="submit" value="Create" />
62
+ # </form>
63
+ def form(*args, &blk)
64
+ _singleton_form_context.form(*args, &blk)
65
+ end
66
+
67
+ # Generates a resource specific form tag which accepts a block, this also provides automatic resource routing.
68
+ #
69
+ # ==== Parameters
70
+ # name<Symbol>:: Model or Resource
71
+ # attrs<Hash>:: HTML attributes
72
+ #
73
+ # ==== Returns
74
+ # String:: HTML
75
+ #
76
+ # ==== Notes
77
+ # * Block helpers use the <%= =%> syntax
78
+ #
79
+ # ==== Example
80
+ # <%= form_for @person do %>
81
+ # <%= text_field :first_name, :label => "First Name" %>
82
+ # <%= text_field :last_name, :label => "Last Name" %>
83
+ # <%= submit "Create" %>
84
+ # <% end =%>
85
+ #
86
+ # The HTML generated for this would be:
87
+ #
88
+ # <form action="/people" method="post">
89
+ # <label for="person_first_name">First Name</label>
90
+ # <input type="text" id="person_first_name" name="person[first_name]" />
91
+ # <label for="person_last_name">Last Name</label>
92
+ # <input type="text" id="person_last_name" name="person[last_name]" />
93
+ # <input type="submit" value="Create" />
94
+ # </form>
95
+ def form_for(name, attrs = {}, &blk)
96
+ with_form_context(name, attrs.delete(:builder)) do
97
+ current_form_context.form(attrs, &blk)
98
+ end
99
+ end
100
+
101
+ # Creates a scope around a specific resource object like form_for, but doesnt create the form tags themselves.
102
+ # This makes fields_for suitable for specifying additional resource objects in the same form.
103
+ #
104
+ # ==== Examples
105
+ # <%= form_for @person do %>
106
+ # <%= text_field :first_name, :label => "First Name" %>
107
+ # <%= text_field :last_name, :label => "Last Name" %>
108
+ # <% fields_for :permission do %>
109
+ # <%= check_box :is_admin, :label => "Administrator" %>
110
+ # <% end %>
111
+ # <%= submit "Create" %>
112
+ # <% end =%>
113
+ def fields_for(name, attrs = {}, &blk)
114
+ attrs ||= {}
115
+ with_form_context(name, attrs.delete(:builder)) do
116
+ current_form_context.concat(attrs, &blk)
117
+ end
118
+ end
119
+
120
+ # Provides the ability to create quick fieldsets as blocks for your forms.
121
+ #
122
+ # ==== Parameters
123
+ # attrs<Hash>:: HTML attributes and options
124
+ #
125
+ # ==== Options
126
+ # +legend+:: Adds a legend tag within the fieldset
127
+ #
128
+ # ==== Returns
129
+ # String:: HTML
130
+ #
131
+ # ==== Notes
132
+ # Block helpers use the <%= =%> syntax
133
+ #
134
+ # ==== Example
135
+ # <%= fieldset :legend => "Customer Options" do %>
136
+ # ...your form elements
137
+ # <% end =%>
138
+ #
139
+ # Generates the HTML:
140
+ #
141
+ # <fieldset>
142
+ # <legend>Customer Options</legend>
143
+ # ...your form elements
144
+ # </fieldset>
145
+ def fieldset(attrs = {}, &blk)
146
+ _singleton_form_context.fieldset(attrs, &blk)
147
+ end
148
+
149
+ def fieldset_for(name, attrs = {}, &blk)
150
+ with_form_context(name, attrs.delete(:builder)) do
151
+ current_form_context.fieldset(attrs, &blk)
152
+ end
153
+ end
154
+
155
+ # Provides a HTML text input tag
156
+ #
157
+ # ==== Parameters
158
+ # name<Symbol>:: Model or Resource
159
+ # attrs<Hash>:: HTML attributes
160
+ #
161
+ # ==== Returns
162
+ # String:: HTML
163
+ #
164
+ # ==== Example
165
+ # <%= text_field :name => :fav_color, :label => "Your Favorite Color" %>
166
+ # # => <label for="fav_color">Your Favorite Color</label><input type="text" id="fav_color" name="fav_color" />
167
+ #
168
+ # Used with a model:
169
+ #
170
+ # <%= form_for @person do %>
171
+ # <%= text_field :first_name, :label => "First Name" %>
172
+ # <% end =%>
173
+ def text_field; end
174
+
175
+ # Provides a HTML password input.
176
+ #
177
+ # ==== Parameters
178
+ # name<Symbol>:: Model or Resource
179
+ # attrs<Hash>:: HTML attributes
180
+ #
181
+ # ==== Returns
182
+ # String:: HTML
183
+ #
184
+ # ==== Example
185
+ # <%= password_field :name => :password, :label => "Password" %>
186
+ # # => <label for="password">Password</label><input type="password" id="password" name="password" />
187
+ #
188
+ # Used with a model:
189
+ #
190
+ # <%= password_field :password, :label => 'New Password' %>
191
+ def password_field; end
192
+
193
+ # Provides a HTML hidden input field
194
+ #
195
+ # ==== Parameters
196
+ # name<Symbol>:: Model or Resource
197
+ # attrs<Hash>:: HTML attributes
198
+ #
199
+ # ==== Returns
200
+ # String:: HTML
201
+ #
202
+ # ==== Example
203
+ # <%= hidden_field :name => "secret", :value => "some secret value" %>
204
+ #
205
+ # Used with a model:
206
+ #
207
+ # <%= hidden_field :identifier %>
208
+ # # => <input type="hidden" id="person_identifier" name="person[identifier]" value="#{@person.identifier}" />
209
+ def hidden_field; end
210
+
211
+ # Provides a HTML file input
212
+ #
213
+ # ==== Parameters
214
+ # name<Symbol>:: Model or Resource
215
+ # attrs<Hash>:: HTML attributes
216
+ #
217
+ # ==== Returns
218
+ # String:: HTML
219
+ #
220
+ # ==== Example
221
+ # <%= file_field :name => "file", :label => "File" %>
222
+ #
223
+ # Used with a model:
224
+ #
225
+ # <%= file_field :file, :label => "Choose a file" %>
226
+ def file_field; end
227
+
228
+ # Provides a HTML textarea tag
229
+ #
230
+ # ==== Parameters
231
+ # contents<String>:: Contents of the text area
232
+ # attrs<Hash>:: HTML attributes
233
+ #
234
+ # ==== Returns
235
+ # String:: HTML
236
+ #
237
+ # ==== Example
238
+ # <%= text_area "my comments", :name => "comments" %>
239
+ #
240
+ # Used with a model:
241
+ #
242
+ # <%= text_area :comments %>
243
+ def text_area; end
244
+
245
+ # Provides a HTML select
246
+ #
247
+ # ==== Parameters
248
+ # method<Symbol>:: Resource attribute
249
+ # attrs<Hash>:: HTML attributes and options
250
+ #
251
+ # ==== Options
252
+ # +prompt+:: Adds an additional option tag with the provided string with no value.
253
+ # +selected+:: The value of a selected object, which may be either a string or an array.
254
+ # +include_blank+:: Adds an additional blank option tag with no value.
255
+ # +collection+:: The collection for the select options
256
+ # +text_method+:: Method to determine text of an option (as a symbol). Ex: :text_method => :name will call .name on your record object for what text to display.
257
+ # +value_method+:: Method to determine value of an option (as a symbol).
258
+ #
259
+ # ==== Returns
260
+ # String:: HTML
261
+ #
262
+ # ==== Example
263
+ # <%= select :name, :collection => %w(one two three) %>
264
+ def select; end
265
+
266
+ # Provides a generic HTML checkbox input tag.
267
+ # There are two ways this tag can be generated, based on the
268
+ # option :boolean. If not set to true, a "magic" input is generated.
269
+ # Otherwise, an input is created that can be easily used for passing
270
+ # an array of values to the application.
271
+ #
272
+ # ==== Parameters
273
+ # method<Symbol>:: Resource attribute
274
+ # attrs<Hash>:: HTML attributes and options
275
+ #
276
+ # ==== Returns
277
+ # String:: HTML
278
+ #
279
+ # ==== Example
280
+ # <%= check_box :name => "is_activated", :value => "1" %>
281
+ # <%= check_box :name => "choices[]", :boolean => false, :value => "dog" %>
282
+ # <%= check_box :name => "choices[]", :boolean => false, :value => "cat" %>
283
+ # <%= check_box :name => "choices[]", :boolean => false, :value => "weasle" %>
284
+ #
285
+ # Used with a model:
286
+ #
287
+ # <%= check_box :is_activated, :label => "Activated?" %>
288
+ def check_box; end
289
+
290
+ # Provides a HTML radio input tag
291
+ #
292
+ # ==== Parameters
293
+ # method<Symbol>:: Resource attribute
294
+ # attrs<Hash>:: HTML attributes and options
295
+ #
296
+ # ==== Returns
297
+ # String:: HTML
298
+ #
299
+ # ==== Example
300
+ # <%= radio_button :name => "radio_options", :value => "1", :label => "One" %>
301
+ # <%= radio_button :name => "radio_options", :value => "2", :label => "Two" %>
302
+ # <%= radio_button :name => "radio_options", :value => "3", :label => "Three", :checked => true %>
303
+ #
304
+ # Used with a model:
305
+ #
306
+ # <%= form_for @person do %>
307
+ # <%= radio_button :first_name %>
308
+ # <% end =%>
309
+ def radio_button; end
310
+
311
+ # Provides a radio group based on a resource attribute.
312
+ # This is generally used within a resource block such as +form_for+.
313
+ #
314
+ # ==== Parameters
315
+ # method<Symbol>:: Resource attribute
316
+ # arr<Array>:: Choices
317
+ #
318
+ # ==== Returns
319
+ # String:: HTML
320
+ #
321
+ # ==== Examples
322
+ # <%# the labels are the options %>
323
+ # <%= radio_group :my_choice, [5,6,7] %>
324
+ #
325
+ # <%# custom labels %>
326
+ # <%= radio_group :my_choice, [{:value => 5, :label => "five"}] %>
327
+ def radio_group; end
328
+
329
+ # @todo radio_group helper still needs to be implemented
330
+ %w(text_field password_field hidden_field file_field
331
+ text_area select check_box radio_button radio_group).each do |kind|
332
+ self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
333
+ def #{kind}(*args)
334
+ if bound?(*args)
335
+ current_form_context.bound_#{kind}(*args)
336
+ else
337
+ current_form_context.unbound_#{kind}(*args)
338
+ end
339
+ end
340
+ RUBY
341
+ end
342
+
343
+ # Generates a HTML button.
344
+ #
345
+ # ==== Parameters
346
+ # contents<String>:: HTML contained within the button tag
347
+ # attrs<Hash>:: HTML attributes
348
+ #
349
+ # ==== Returns
350
+ # String:: HTML
351
+ #
352
+ # ==== Notes
353
+ # * Buttons do not always work as planned in IE
354
+ # http://www.peterbe.com/plog/button-tag-in-IE
355
+ # * Not all mobile browsers support buttons
356
+ # http://nickcowie.com/2007/time-to-stop-using-the-button-element/
357
+ #
358
+ # ==== Example
359
+ # <%= button "Initiate Launch Sequence" %>
360
+ def button(contents, attrs = {})
361
+ current_form_context.button(contents, attrs)
362
+ end
363
+
364
+ # Generates a HTML submit button.
365
+ #
366
+ # ==== Parameters
367
+ # value<String>:: Sets the value="" attribute
368
+ # attrs<Hash>:: HTML attributes
369
+ #
370
+ # ==== Returns
371
+ # String:: HTML
372
+ #
373
+ # ==== Example
374
+ # <%= submit "Process" %>
375
+ def submit(contents, attrs = {})
376
+ current_form_context.submit(contents, attrs)
377
+ end
378
+
379
+ # Provides a HTML formatted display of resource errors in an unordered list with a h2 form submission error
380
+ #
381
+ # ==== Parameters
382
+ # obj<Symbol>:: Model or Resource
383
+ # error_class<String>:: CSS class to use for error container
384
+ # build_li<String>:: Custom li tag to wrap each error in
385
+ # header<String>:: Custom header text for the error container
386
+ # before<Boolean>:: Display the errors before or inside of the form
387
+ #
388
+ # ==== Returns
389
+ # String:: HTML
390
+ #
391
+ # ==== Examples
392
+ # <%= error_messages_for :person %>
393
+ # <%= error_messages_for :person {|errors| "You can has probs nao: #{errors.size} of em!"}
394
+ # <%= error_messages_for :person, lambda{|error| "<li class='aieeee'>#{error.join(' ')}"} %>
395
+ # <%= error_messages_for :person, nil, 'bad_mojo' %>
396
+ def error_messages_for(obj = nil, opts = {})
397
+ current_form_context.error_messages_for(obj, opts[:error_class] || "error",
398
+ opts[:build_li] || "<li>%s</li>",
399
+ opts[:header] || "<h2>Form submission failed because of %s problem%s</h2>",
400
+ opts.key?(:before) ? opts[:before] : true)
401
+ end
402
+ alias error_messages error_messages_for
403
+
404
+ private
405
+
406
+ def bound?(*args)
407
+ args.first.is_a?(Symbol)
408
+ end
409
+
410
+ end