merb_helpers 0.9.4 → 0.9.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -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