cgialt 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,1030 @@
1
+ ##
2
+ ## Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
3
+ ##
4
+ ## Copyright (C) 2000 Information-technology Promotion Agency, Japan
5
+ ##
6
+ ## Original Author: Wakou Aoyama <wakou@ruby-lang.org>
7
+ ##
8
+ ## Documentation: Wakou Aoyama (RDoc'd and embellished by William Webber)
9
+ ##
10
+
11
+ class CGI
12
+
13
+ # Base module for HTML-generation mixins.
14
+ #
15
+ # Provides methods for code generation for tags following
16
+ # the various DTD element types.
17
+ module TagMaker # :nodoc:
18
+
19
+ # Generate code for an element with required start and end tags.
20
+ #
21
+ # - -
22
+ def nn_element_def(element)
23
+ nOE_element_def(element, <<-END)
24
+ if block_given?
25
+ yield.to_s
26
+ else
27
+ ""
28
+ end +
29
+ "</#{element.upcase}>"
30
+ END
31
+ end
32
+
33
+ # Generate code for an empty element.
34
+ #
35
+ # - O EMPTY
36
+ def nOE_element_def(element, append = nil)
37
+ s = <<-END
38
+ "<#{element.upcase}" + attributes.collect{|name, value|
39
+ next unless value
40
+ " " + CGI::escapeHTML(name) +
41
+ if true == value
42
+ ""
43
+ else
44
+ '="' + CGI::escapeHTML(value) + '"'
45
+ end
46
+ }.to_s + ">"
47
+ END
48
+ s.sub!(/\Z/, " +") << append if append
49
+ s
50
+ end
51
+
52
+ # Generate code for an element for which the end (and possibly the
53
+ # start) tag is optional.
54
+ #
55
+ # O O or - O
56
+ def nO_element_def(element)
57
+ nOE_element_def(element, <<-END)
58
+ if block_given?
59
+ yield.to_s + "</#{element.upcase}>"
60
+ else
61
+ ""
62
+ end
63
+ END
64
+ end
65
+
66
+ end # TagMaker
67
+
68
+
69
+ #
70
+ # Mixin module providing HTML generation methods.
71
+ #
72
+ # For example,
73
+ # cgi.a("http://www.example.com") { "Example" }
74
+ # # => "<A HREF=\"http://www.example.com\">Example</A>"
75
+ #
76
+ # Modules Http3, Http4, etc., contain more basic HTML-generation methods
77
+ # (:title, :center, etc.).
78
+ #
79
+ # See class CGI for a detailed example.
80
+ #
81
+ module HtmlExtension
82
+
83
+
84
+ # Generate an Anchor element as a string.
85
+ #
86
+ # +href+ can either be a string, giving the URL
87
+ # for the HREF attribute, or it can be a hash of
88
+ # the element's attributes.
89
+ #
90
+ # The body of the element is the string returned by the no-argument
91
+ # block passed in.
92
+ #
93
+ # a("http://www.example.com") { "Example" }
94
+ # # => "<A HREF=\"http://www.example.com\">Example</A>"
95
+ #
96
+ # a("HREF" => "http://www.example.com", "TARGET" => "_top") { "Example" }
97
+ # # => "<A HREF=\"http://www.example.com\" TARGET=\"_top\">Example</A>"
98
+ #
99
+ def a(href = "") # :yield:
100
+ attributes = if href.kind_of?(String)
101
+ { "HREF" => href }
102
+ else
103
+ href
104
+ end
105
+ if block_given?
106
+ super(attributes){ yield }
107
+ else
108
+ super(attributes)
109
+ end
110
+ end
111
+
112
+ # Generate a Document Base URI element as a String.
113
+ #
114
+ # +href+ can either by a string, giving the base URL for the HREF
115
+ # attribute, or it can be a has of the element's attributes.
116
+ #
117
+ # The passed-in no-argument block is ignored.
118
+ #
119
+ # base("http://www.example.com/cgi")
120
+ # # => "<BASE HREF=\"http://www.example.com/cgi\">"
121
+ def base(href = "") # :yield:
122
+ attributes = if href.kind_of?(String)
123
+ { "HREF" => href }
124
+ else
125
+ href
126
+ end
127
+ if block_given?
128
+ super(attributes){ yield }
129
+ else
130
+ super(attributes)
131
+ end
132
+ end
133
+
134
+ # Generate a BlockQuote element as a string.
135
+ #
136
+ # +cite+ can either be a string, give the URI for the source of
137
+ # the quoted text, or a hash, giving all attributes of the element,
138
+ # or it can be omitted, in which case the element has no attributes.
139
+ #
140
+ # The body is provided by the passed-in no-argument block
141
+ #
142
+ # blockquote("http://www.example.com/quotes/foo.html") { "Foo!" }
143
+ # #=> "<BLOCKQUOTE CITE=\"http://www.example.com/quotes/foo.html\">Foo!</BLOCKQUOTE>
144
+ def blockquote(cite = nil) # :yield:
145
+ attributes = if cite.kind_of?(String)
146
+ { "CITE" => cite }
147
+ else
148
+ cite or ""
149
+ end
150
+ if block_given?
151
+ super(attributes){ yield }
152
+ else
153
+ super(attributes)
154
+ end
155
+ end
156
+
157
+
158
+ # Generate a Table Caption element as a string.
159
+ #
160
+ # +align+ can be a string, giving the alignment of the caption
161
+ # (one of top, bottom, left, or right). It can be a hash of
162
+ # all the attributes of the element. Or it can be omitted.
163
+ #
164
+ # The body of the element is provided by the passed-in no-argument block.
165
+ #
166
+ # caption("left") { "Capital Cities" }
167
+ # # => <CAPTION ALIGN=\"left\">Capital Cities</CAPTION>
168
+ def caption(align = nil) # :yield:
169
+ attributes = if align.kind_of?(String)
170
+ { "ALIGN" => align }
171
+ else
172
+ align or ""
173
+ end
174
+ if block_given?
175
+ super(attributes){ yield }
176
+ else
177
+ super(attributes)
178
+ end
179
+ end
180
+
181
+
182
+ # Generate a Checkbox Input element as a string.
183
+ #
184
+ # The attributes of the element can be specified as three arguments,
185
+ # +name+, +value+, and +checked+. +checked+ is a boolean value;
186
+ # if true, the CHECKED attribute will be included in the element.
187
+ #
188
+ # Alternatively, the attributes can be specified as a hash.
189
+ #
190
+ # checkbox("name")
191
+ # # = checkbox("NAME" => "name")
192
+ #
193
+ # checkbox("name", "value")
194
+ # # = checkbox("NAME" => "name", "VALUE" => "value")
195
+ #
196
+ # checkbox("name", "value", true)
197
+ # # = checkbox("NAME" => "name", "VALUE" => "value", "CHECKED" => true)
198
+ def checkbox(name = "", value = nil, checked = nil)
199
+ attributes = if name.kind_of?(String)
200
+ { "TYPE" => "checkbox", "NAME" => name,
201
+ "VALUE" => value, "CHECKED" => checked }
202
+ else
203
+ name["TYPE"] = "checkbox"
204
+ name
205
+ end
206
+ input(attributes)
207
+ end
208
+
209
+ # Generate a sequence of checkbox elements, as a String.
210
+ #
211
+ # The checkboxes will all have the same +name+ attribute.
212
+ # Each checkbox is followed by a label.
213
+ # There will be one checkbox for each value. Each value
214
+ # can be specified as a String, which will be used both
215
+ # as the value of the VALUE attribute and as the label
216
+ # for that checkbox. A single-element array has the
217
+ # same effect.
218
+ #
219
+ # Each value can also be specified as a three-element array.
220
+ # The first element is the VALUE attribute; the second is the
221
+ # label; and the third is a boolean specifying whether this
222
+ # checkbox is CHECKED.
223
+ #
224
+ # Each value can also be specified as a two-element
225
+ # array, by omitting either the value element (defaults
226
+ # to the same as the label), or the boolean checked element
227
+ # (defaults to false).
228
+ #
229
+ # checkbox_group("name", "foo", "bar", "baz")
230
+ # # <INPUT TYPE="checkbox" NAME="name" VALUE="foo">foo
231
+ # # <INPUT TYPE="checkbox" NAME="name" VALUE="bar">bar
232
+ # # <INPUT TYPE="checkbox" NAME="name" VALUE="baz">baz
233
+ #
234
+ # checkbox_group("name", ["foo"], ["bar", true], "baz")
235
+ # # <INPUT TYPE="checkbox" NAME="name" VALUE="foo">foo
236
+ # # <INPUT TYPE="checkbox" CHECKED NAME="name" VALUE="bar">bar
237
+ # # <INPUT TYPE="checkbox" NAME="name" VALUE="baz">baz
238
+ #
239
+ # checkbox_group("name", ["1", "Foo"], ["2", "Bar", true], "Baz")
240
+ # # <INPUT TYPE="checkbox" NAME="name" VALUE="1">Foo
241
+ # # <INPUT TYPE="checkbox" CHECKED NAME="name" VALUE="2">Bar
242
+ # # <INPUT TYPE="checkbox" NAME="name" VALUE="Baz">Baz
243
+ #
244
+ # checkbox_group("NAME" => "name",
245
+ # "VALUES" => ["foo", "bar", "baz"])
246
+ #
247
+ # checkbox_group("NAME" => "name",
248
+ # "VALUES" => [["foo"], ["bar", true], "baz"])
249
+ #
250
+ # checkbox_group("NAME" => "name",
251
+ # "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"])
252
+ def checkbox_group(name = "", *values)
253
+ if name.kind_of?(Hash)
254
+ values = name["VALUES"]
255
+ name = name["NAME"]
256
+ end
257
+ values.collect{|value|
258
+ if value.kind_of?(String)
259
+ checkbox(name, value) + value
260
+ else
261
+ if value[value.size - 1] == true
262
+ checkbox(name, value[0], true) +
263
+ value[value.size - 2]
264
+ else
265
+ checkbox(name, value[0]) +
266
+ value[value.size - 1]
267
+ end
268
+ end
269
+ }.to_s
270
+ end
271
+
272
+
273
+ # Generate an File Upload Input element as a string.
274
+ #
275
+ # The attributes of the element can be specified as three arguments,
276
+ # +name+, +size+, and +maxlength+. +maxlength+ is the maximum length
277
+ # of the file's _name_, not of the file's _contents_.
278
+ #
279
+ # Alternatively, the attributes can be specified as a hash.
280
+ #
281
+ # See #multipart_form() for forms that include file uploads.
282
+ #
283
+ # file_field("name")
284
+ # # <INPUT TYPE="file" NAME="name" SIZE="20">
285
+ #
286
+ # file_field("name", 40)
287
+ # # <INPUT TYPE="file" NAME="name" SIZE="40">
288
+ #
289
+ # file_field("name", 40, 100)
290
+ # # <INPUT TYPE="file" NAME="name" SIZE="40" MAXLENGTH="100">
291
+ #
292
+ # file_field("NAME" => "name", "SIZE" => 40)
293
+ # # <INPUT TYPE="file" NAME="name" SIZE="40">
294
+ def file_field(name = "", size = 20, maxlength = nil)
295
+ attributes = if name.kind_of?(String)
296
+ { "TYPE" => "file", "NAME" => name,
297
+ "SIZE" => size.to_s }
298
+ else
299
+ name["TYPE"] = "file"
300
+ name
301
+ end
302
+ attributes["MAXLENGTH"] = maxlength.to_s if maxlength
303
+ input(attributes)
304
+ end
305
+
306
+
307
+ # Generate a Form element as a string.
308
+ #
309
+ # +method+ should be either "get" or "post", and defaults to the latter.
310
+ # +action+ defaults to the current CGI script name. +enctype+
311
+ # defaults to "application/x-www-form-urlencoded".
312
+ #
313
+ # Alternatively, the attributes can be specified as a hash.
314
+ #
315
+ # See also #multipart_form() for forms that include file uploads.
316
+ #
317
+ # form{ "string" }
318
+ # # <FORM METHOD="post" ENCTYPE="application/x-www-form-urlencoded">string</FORM>
319
+ #
320
+ # form("get") { "string" }
321
+ # # <FORM METHOD="get" ENCTYPE="application/x-www-form-urlencoded">string</FORM>
322
+ #
323
+ # form("get", "url") { "string" }
324
+ # # <FORM METHOD="get" ACTION="url" ENCTYPE="application/x-www-form-urlencoded">string</FORM>
325
+ #
326
+ # form("METHOD" => "post", "ENCTYPE" => "enctype") { "string" }
327
+ # # <FORM METHOD="post" ENCTYPE="enctype">string</FORM>
328
+ def form(method = "post", action = script_name, enctype = "application/x-www-form-urlencoded")
329
+ attributes = if method.kind_of?(String)
330
+ { "METHOD" => method, "ACTION" => action,
331
+ "ENCTYPE" => enctype }
332
+ else
333
+ unless method.has_key?("METHOD")
334
+ method["METHOD"] = "post"
335
+ end
336
+ unless method.has_key?("ENCTYPE")
337
+ method["ENCTYPE"] = enctype
338
+ end
339
+ method
340
+ end
341
+ if block_given?
342
+ body = yield
343
+ else
344
+ body = ""
345
+ end
346
+ if @output_hidden
347
+ body += @output_hidden.collect{|k,v|
348
+ "<INPUT TYPE=\"HIDDEN\" NAME=\"#{k}\" VALUE=\"#{v}\">"
349
+ }.to_s
350
+ end
351
+ super(attributes){body}
352
+ end
353
+
354
+ # Generate a Hidden Input element as a string.
355
+ #
356
+ # The attributes of the element can be specified as two arguments,
357
+ # +name+ and +value+.
358
+ #
359
+ # Alternatively, the attributes can be specified as a hash.
360
+ #
361
+ # hidden("name")
362
+ # # <INPUT TYPE="hidden" NAME="name">
363
+ #
364
+ # hidden("name", "value")
365
+ # # <INPUT TYPE="hidden" NAME="name" VALUE="value">
366
+ #
367
+ # hidden("NAME" => "name", "VALUE" => "reset", "ID" => "foo")
368
+ # # <INPUT TYPE="hidden" NAME="name" VALUE="value" ID="foo">
369
+ def hidden(name = "", value = nil)
370
+ attributes = if name.kind_of?(String)
371
+ { "TYPE" => "hidden", "NAME" => name, "VALUE" => value }
372
+ else
373
+ name["TYPE"] = "hidden"
374
+ name
375
+ end
376
+ input(attributes)
377
+ end
378
+
379
+ # Generate a top-level HTML element as a string.
380
+ #
381
+ # The attributes of the element are specified as a hash. The
382
+ # pseudo-attribute "PRETTY" can be used to specify that the generated
383
+ # HTML string should be indented. "PRETTY" can also be specified as
384
+ # a string as the sole argument to this method. The pseudo-attribute
385
+ # "DOCTYPE", if given, is used as the leading DOCTYPE SGML tag; it
386
+ # should include the entire text of this tag, including angle brackets.
387
+ #
388
+ # The body of the html element is supplied as a block.
389
+ #
390
+ # html{ "string" }
391
+ # # <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><HTML>string</HTML>
392
+ #
393
+ # html("LANG" => "ja") { "string" }
394
+ # # <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><HTML LANG="ja">string</HTML>
395
+ #
396
+ # html("DOCTYPE" => false) { "string" }
397
+ # # <HTML>string</HTML>
398
+ #
399
+ # html("DOCTYPE" => '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">') { "string" }
400
+ # # <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"><HTML>string</HTML>
401
+ #
402
+ # html("PRETTY" => " ") { "<BODY></BODY>" }
403
+ # # <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
404
+ # # <HTML>
405
+ # # <BODY>
406
+ # # </BODY>
407
+ # # </HTML>
408
+ #
409
+ # html("PRETTY" => "\t") { "<BODY></BODY>" }
410
+ # # <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
411
+ # # <HTML>
412
+ # # <BODY>
413
+ # # </BODY>
414
+ # # </HTML>
415
+ #
416
+ # html("PRETTY") { "<BODY></BODY>" }
417
+ # # = html("PRETTY" => " ") { "<BODY></BODY>" }
418
+ #
419
+ # html(if $VERBOSE then "PRETTY" end) { "HTML string" }
420
+ #
421
+ def html(attributes = {}) # :yield:
422
+ if nil == attributes
423
+ attributes = {}
424
+ elsif "PRETTY" == attributes
425
+ attributes = { "PRETTY" => true }
426
+ end
427
+ pretty = attributes.delete("PRETTY")
428
+ pretty = " " if true == pretty
429
+ buf = ""
430
+
431
+ if attributes.has_key?("DOCTYPE")
432
+ if attributes["DOCTYPE"]
433
+ buf += attributes.delete("DOCTYPE")
434
+ else
435
+ attributes.delete("DOCTYPE")
436
+ end
437
+ else
438
+ buf += doctype
439
+ end
440
+
441
+ if block_given?
442
+ buf += super(attributes){ yield }
443
+ else
444
+ buf += super(attributes)
445
+ end
446
+
447
+ if pretty
448
+ CGI::pretty(buf, pretty)
449
+ else
450
+ buf
451
+ end
452
+
453
+ end
454
+
455
+ # Generate an Image Button Input element as a string.
456
+ #
457
+ # +src+ is the URL of the image to use for the button. +name+
458
+ # is the input name. +alt+ is the alternative text for the image.
459
+ #
460
+ # Alternatively, the attributes can be specified as a hash.
461
+ #
462
+ # image_button("url")
463
+ # # <INPUT TYPE="image" SRC="url">
464
+ #
465
+ # image_button("url", "name", "string")
466
+ # # <INPUT TYPE="image" SRC="url" NAME="name" ALT="string">
467
+ #
468
+ # image_button("SRC" => "url", "ATL" => "strng")
469
+ # # <INPUT TYPE="image" SRC="url" ALT="string">
470
+ def image_button(src = "", name = nil, alt = nil)
471
+ attributes = if src.kind_of?(String)
472
+ { "TYPE" => "image", "SRC" => src, "NAME" => name,
473
+ "ALT" => alt }
474
+ else
475
+ src["TYPE"] = "image"
476
+ src["SRC"] ||= ""
477
+ src
478
+ end
479
+ input(attributes)
480
+ end
481
+
482
+
483
+ # Generate an Image element as a string.
484
+ #
485
+ # +src+ is the URL of the image. +alt+ is the alternative text for
486
+ # the image. +width+ is the width of the image, and +height+ is
487
+ # its height.
488
+ #
489
+ # Alternatively, the attributes can be specified as a hash.
490
+ #
491
+ # img("src", "alt", 100, 50)
492
+ # # <IMG SRC="src" ALT="alt" WIDTH="100" HEIGHT="50">
493
+ #
494
+ # img("SRC" => "src", "ALT" => "alt", "WIDTH" => 100, "HEIGHT" => 50)
495
+ # # <IMG SRC="src" ALT="alt" WIDTH="100" HEIGHT="50">
496
+ def img(src = "", alt = "", width = nil, height = nil)
497
+ attributes = if src.kind_of?(String)
498
+ { "SRC" => src, "ALT" => alt }
499
+ else
500
+ src
501
+ end
502
+ attributes["WIDTH"] = width.to_s if width
503
+ attributes["HEIGHT"] = height.to_s if height
504
+ super(attributes)
505
+ end
506
+
507
+
508
+ # Generate a Form element with multipart encoding as a String.
509
+ #
510
+ # Multipart encoding is used for forms that include file uploads.
511
+ #
512
+ # +action+ is the action to perform. +enctype+ is the encoding
513
+ # type, which defaults to "multipart/form-data".
514
+ #
515
+ # Alternatively, the attributes can be specified as a hash.
516
+ #
517
+ # multipart_form{ "string" }
518
+ # # <FORM METHOD="post" ENCTYPE="multipart/form-data">string</FORM>
519
+ #
520
+ # multipart_form("url") { "string" }
521
+ # # <FORM METHOD="post" ACTION="url" ENCTYPE="multipart/form-data">string</FORM>
522
+ def multipart_form(action = nil, enctype = "multipart/form-data")
523
+ attributes = if action == nil
524
+ { "METHOD" => "post", "ENCTYPE" => enctype }
525
+ elsif action.kind_of?(String)
526
+ { "METHOD" => "post", "ACTION" => action,
527
+ "ENCTYPE" => enctype }
528
+ else
529
+ unless action.has_key?("METHOD")
530
+ action["METHOD"] = "post"
531
+ end
532
+ unless action.has_key?("ENCTYPE")
533
+ action["ENCTYPE"] = enctype
534
+ end
535
+ action
536
+ end
537
+ if block_given?
538
+ form(attributes){ yield }
539
+ else
540
+ form(attributes)
541
+ end
542
+ end
543
+
544
+
545
+ # Generate a Password Input element as a string.
546
+ #
547
+ # +name+ is the name of the input field. +value+ is its default
548
+ # value. +size+ is the size of the input field display. +maxlength+
549
+ # is the maximum length of the inputted password.
550
+ #
551
+ # Alternatively, attributes can be specified as a hash.
552
+ #
553
+ # password_field("name")
554
+ # # <INPUT TYPE="password" NAME="name" SIZE="40">
555
+ #
556
+ # password_field("name", "value")
557
+ # # <INPUT TYPE="password" NAME="name" VALUE="value" SIZE="40">
558
+ #
559
+ # password_field("password", "value", 80, 200)
560
+ # # <INPUT TYPE="password" NAME="name" VALUE="value" SIZE="80" MAXLENGTH="200">
561
+ #
562
+ # password_field("NAME" => "name", "VALUE" => "value")
563
+ # # <INPUT TYPE="password" NAME="name" VALUE="value">
564
+ def password_field(name = "", value = nil, size = 40, maxlength = nil)
565
+ attributes = if name.kind_of?(String)
566
+ { "TYPE" => "password", "NAME" => name,
567
+ "VALUE" => value, "SIZE" => size.to_s }
568
+ else
569
+ name["TYPE"] = "password"
570
+ name
571
+ end
572
+ attributes["MAXLENGTH"] = maxlength.to_s if maxlength
573
+ input(attributes)
574
+ end
575
+
576
+ # Generate a Select element as a string.
577
+ #
578
+ # +name+ is the name of the element. The +values+ are the options that
579
+ # can be selected from the Select menu. Each value can be a String or
580
+ # a one, two, or three-element Array. If a String or a one-element
581
+ # Array, this is both the value of that option and the text displayed for
582
+ # it. If a three-element Array, the elements are the option value, displayed
583
+ # text, and a boolean value specifying whether this option starts as selected.
584
+ # The two-element version omits either the option value (defaults to the same
585
+ # as the display text) or the boolean selected specifier (defaults to false).
586
+ #
587
+ # The attributes and options can also be specified as a hash. In this
588
+ # case, options are specified as an array of values as described above,
589
+ # with the hash key of "VALUES".
590
+ #
591
+ # popup_menu("name", "foo", "bar", "baz")
592
+ # # <SELECT NAME="name">
593
+ # # <OPTION VALUE="foo">foo</OPTION>
594
+ # # <OPTION VALUE="bar">bar</OPTION>
595
+ # # <OPTION VALUE="baz">baz</OPTION>
596
+ # # </SELECT>
597
+ #
598
+ # popup_menu("name", ["foo"], ["bar", true], "baz")
599
+ # # <SELECT NAME="name">
600
+ # # <OPTION VALUE="foo">foo</OPTION>
601
+ # # <OPTION VALUE="bar" SELECTED>bar</OPTION>
602
+ # # <OPTION VALUE="baz">baz</OPTION>
603
+ # # </SELECT>
604
+ #
605
+ # popup_menu("name", ["1", "Foo"], ["2", "Bar", true], "Baz")
606
+ # # <SELECT NAME="name">
607
+ # # <OPTION VALUE="1">Foo</OPTION>
608
+ # # <OPTION SELECTED VALUE="2">Bar</OPTION>
609
+ # # <OPTION VALUE="Baz">Baz</OPTION>
610
+ # # </SELECT>
611
+ #
612
+ # popup_menu("NAME" => "name", "SIZE" => 2, "MULTIPLE" => true,
613
+ # "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"])
614
+ # # <SELECT NAME="name" MULTIPLE SIZE="2">
615
+ # # <OPTION VALUE="1">Foo</OPTION>
616
+ # # <OPTION SELECTED VALUE="2">Bar</OPTION>
617
+ # # <OPTION VALUE="Baz">Baz</OPTION>
618
+ # # </SELECT>
619
+ def popup_menu(name = "", *values)
620
+
621
+ if name.kind_of?(Hash)
622
+ values = name["VALUES"]
623
+ size = name["SIZE"].to_s if name["SIZE"]
624
+ multiple = name["MULTIPLE"]
625
+ name = name["NAME"]
626
+ else
627
+ size = nil
628
+ multiple = nil
629
+ end
630
+
631
+ select({ "NAME" => name, "SIZE" => size,
632
+ "MULTIPLE" => multiple }){
633
+ values.collect{|value|
634
+ if value.kind_of?(String)
635
+ option({ "VALUE" => value }){ value }
636
+ else
637
+ if value[value.size - 1] == true
638
+ option({ "VALUE" => value[0], "SELECTED" => true }){
639
+ value[value.size - 2]
640
+ }
641
+ else
642
+ option({ "VALUE" => value[0] }){
643
+ value[value.size - 1]
644
+ }
645
+ end
646
+ end
647
+ }.to_s
648
+ }
649
+
650
+ end
651
+
652
+ # Generates a radio-button Input element.
653
+ #
654
+ # +name+ is the name of the input field. +value+ is the value of
655
+ # the field if checked. +checked+ specifies whether the field
656
+ # starts off checked.
657
+ #
658
+ # Alternatively, the attributes can be specified as a hash.
659
+ #
660
+ # radio_button("name", "value")
661
+ # # <INPUT TYPE="radio" NAME="name" VALUE="value">
662
+ #
663
+ # radio_button("name", "value", true)
664
+ # # <INPUT TYPE="radio" NAME="name" VALUE="value" CHECKED>
665
+ #
666
+ # radio_button("NAME" => "name", "VALUE" => "value", "ID" => "foo")
667
+ # # <INPUT TYPE="radio" NAME="name" VALUE="value" ID="foo">
668
+ def radio_button(name = "", value = nil, checked = nil)
669
+ attributes = if name.kind_of?(String)
670
+ { "TYPE" => "radio", "NAME" => name,
671
+ "VALUE" => value, "CHECKED" => checked }
672
+ else
673
+ name["TYPE"] = "radio"
674
+ name
675
+ end
676
+ input(attributes)
677
+ end
678
+
679
+ # Generate a sequence of radio button Input elements, as a String.
680
+ #
681
+ # This works the same as #checkbox_group(). However, it is not valid
682
+ # to have more than one radiobutton in a group checked.
683
+ #
684
+ # radio_group("name", "foo", "bar", "baz")
685
+ # # <INPUT TYPE="radio" NAME="name" VALUE="foo">foo
686
+ # # <INPUT TYPE="radio" NAME="name" VALUE="bar">bar
687
+ # # <INPUT TYPE="radio" NAME="name" VALUE="baz">baz
688
+ #
689
+ # radio_group("name", ["foo"], ["bar", true], "baz")
690
+ # # <INPUT TYPE="radio" NAME="name" VALUE="foo">foo
691
+ # # <INPUT TYPE="radio" CHECKED NAME="name" VALUE="bar">bar
692
+ # # <INPUT TYPE="radio" NAME="name" VALUE="baz">baz
693
+ #
694
+ # radio_group("name", ["1", "Foo"], ["2", "Bar", true], "Baz")
695
+ # # <INPUT TYPE="radio" NAME="name" VALUE="1">Foo
696
+ # # <INPUT TYPE="radio" CHECKED NAME="name" VALUE="2">Bar
697
+ # # <INPUT TYPE="radio" NAME="name" VALUE="Baz">Baz
698
+ #
699
+ # radio_group("NAME" => "name",
700
+ # "VALUES" => ["foo", "bar", "baz"])
701
+ #
702
+ # radio_group("NAME" => "name",
703
+ # "VALUES" => [["foo"], ["bar", true], "baz"])
704
+ #
705
+ # radio_group("NAME" => "name",
706
+ # "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"])
707
+ def radio_group(name = "", *values)
708
+ if name.kind_of?(Hash)
709
+ values = name["VALUES"]
710
+ name = name["NAME"]
711
+ end
712
+ values.collect{|value|
713
+ if value.kind_of?(String)
714
+ radio_button(name, value) + value
715
+ else
716
+ if value[value.size - 1] == true
717
+ radio_button(name, value[0], true) +
718
+ value[value.size - 2]
719
+ else
720
+ radio_button(name, value[0]) +
721
+ value[value.size - 1]
722
+ end
723
+ end
724
+ }.to_s
725
+ end
726
+
727
+ # Generate a reset button Input element, as a String.
728
+ #
729
+ # This resets the values on a form to their initial values. +value+
730
+ # is the text displayed on the button. +name+ is the name of this button.
731
+ #
732
+ # Alternatively, the attributes can be specified as a hash.
733
+ #
734
+ # reset
735
+ # # <INPUT TYPE="reset">
736
+ #
737
+ # reset("reset")
738
+ # # <INPUT TYPE="reset" VALUE="reset">
739
+ #
740
+ # reset("VALUE" => "reset", "ID" => "foo")
741
+ # # <INPUT TYPE="reset" VALUE="reset" ID="foo">
742
+ def reset(value = nil, name = nil)
743
+ attributes = if (not value) or value.kind_of?(String)
744
+ { "TYPE" => "reset", "VALUE" => value, "NAME" => name }
745
+ else
746
+ value["TYPE"] = "reset"
747
+ value
748
+ end
749
+ input(attributes)
750
+ end
751
+
752
+ alias scrolling_list popup_menu
753
+
754
+ # Generate a submit button Input element, as a String.
755
+ #
756
+ # +value+ is the text to display on the button. +name+ is the name
757
+ # of the input.
758
+ #
759
+ # Alternatively, the attributes can be specified as a hash.
760
+ #
761
+ # submit
762
+ # # <INPUT TYPE="submit">
763
+ #
764
+ # submit("ok")
765
+ # # <INPUT TYPE="submit" VALUE="ok">
766
+ #
767
+ # submit("ok", "button1")
768
+ # # <INPUT TYPE="submit" VALUE="ok" NAME="button1">
769
+ #
770
+ # submit("VALUE" => "ok", "NAME" => "button1", "ID" => "foo")
771
+ # # <INPUT TYPE="submit" VALUE="ok" NAME="button1" ID="foo">
772
+ def submit(value = nil, name = nil)
773
+ attributes = if (not value) or value.kind_of?(String)
774
+ { "TYPE" => "submit", "VALUE" => value, "NAME" => name }
775
+ else
776
+ value["TYPE"] = "submit"
777
+ value
778
+ end
779
+ input(attributes)
780
+ end
781
+
782
+ # Generate a text field Input element, as a String.
783
+ #
784
+ # +name+ is the name of the input field. +value+ is its initial
785
+ # value. +size+ is the size of the input area. +maxlength+
786
+ # is the maximum length of input accepted.
787
+ #
788
+ # Alternatively, the attributes can be specified as a hash.
789
+ #
790
+ # text_field("name")
791
+ # # <INPUT TYPE="text" NAME="name" SIZE="40">
792
+ #
793
+ # text_field("name", "value")
794
+ # # <INPUT TYPE="text" NAME="name" VALUE="value" SIZE="40">
795
+ #
796
+ # text_field("name", "value", 80)
797
+ # # <INPUT TYPE="text" NAME="name" VALUE="value" SIZE="80">
798
+ #
799
+ # text_field("name", "value", 80, 200)
800
+ # # <INPUT TYPE="text" NAME="name" VALUE="value" SIZE="80" MAXLENGTH="200">
801
+ #
802
+ # text_field("NAME" => "name", "VALUE" => "value")
803
+ # # <INPUT TYPE="text" NAME="name" VALUE="value">
804
+ def text_field(name = "", value = nil, size = 40, maxlength = nil)
805
+ attributes = if name.kind_of?(String)
806
+ { "TYPE" => "text", "NAME" => name, "VALUE" => value,
807
+ "SIZE" => size.to_s }
808
+ else
809
+ name["TYPE"] = "text"
810
+ name
811
+ end
812
+ attributes["MAXLENGTH"] = maxlength.to_s if maxlength
813
+ input(attributes)
814
+ end
815
+
816
+ # Generate a TextArea element, as a String.
817
+ #
818
+ # +name+ is the name of the textarea. +cols+ is the number of
819
+ # columns and +rows+ is the number of rows in the display.
820
+ #
821
+ # Alternatively, the attributes can be specified as a hash.
822
+ #
823
+ # The body is provided by the passed-in no-argument block
824
+ #
825
+ # textarea("name")
826
+ # # = textarea("NAME" => "name", "COLS" => 70, "ROWS" => 10)
827
+ #
828
+ # textarea("name", 40, 5)
829
+ # # = textarea("NAME" => "name", "COLS" => 40, "ROWS" => 5)
830
+ def textarea(name = "", cols = 70, rows = 10) # :yield:
831
+ attributes = if name.kind_of?(String)
832
+ { "NAME" => name, "COLS" => cols.to_s,
833
+ "ROWS" => rows.to_s }
834
+ else
835
+ name
836
+ end
837
+ if block_given?
838
+ super(attributes){ yield }
839
+ else
840
+ super(attributes)
841
+ end
842
+ end
843
+
844
+ end # HtmlExtension
845
+
846
+
847
+ # Mixin module for HTML version 3 generation methods.
848
+ module Html3 # :nodoc:
849
+
850
+ # The DOCTYPE declaration for this version of HTML
851
+ def doctype
852
+ %|<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">|
853
+ end
854
+
855
+ # Initialise the HTML generation methods for this version.
856
+ def element_init
857
+ extend TagMaker
858
+ methods = ""
859
+ # - -
860
+ for element in %w[ A TT I B U STRIKE BIG SMALL SUB SUP EM STRONG
861
+ DFN CODE SAMP KBD VAR CITE FONT ADDRESS DIV center MAP
862
+ APPLET PRE XMP LISTING DL OL UL DIR MENU SELECT table TITLE
863
+ STYLE SCRIPT H1 H2 H3 H4 H5 H6 TEXTAREA FORM BLOCKQUOTE
864
+ CAPTION ]
865
+ methods += <<-BEGIN + nn_element_def(element) + <<-END
866
+ def #{element.downcase}(attributes = {})
867
+ BEGIN
868
+ end
869
+ END
870
+ end
871
+
872
+ # - O EMPTY
873
+ for element in %w[ IMG BASE BASEFONT BR AREA LINK PARAM HR INPUT
874
+ ISINDEX META ]
875
+ methods += <<-BEGIN + nOE_element_def(element) + <<-END
876
+ def #{element.downcase}(attributes = {})
877
+ BEGIN
878
+ end
879
+ END
880
+ end
881
+
882
+ # O O or - O
883
+ for element in %w[ HTML HEAD BODY P PLAINTEXT DT DD LI OPTION tr
884
+ th td ]
885
+ methods += <<-BEGIN + nO_element_def(element) + <<-END
886
+ def #{element.downcase}(attributes = {})
887
+ BEGIN
888
+ end
889
+ END
890
+ end
891
+ eval(methods)
892
+ end
893
+
894
+ end # Html3
895
+
896
+
897
+ # Mixin module for HTML version 4 generation methods.
898
+ module Html4 # :nodoc:
899
+
900
+ # The DOCTYPE declaration for this version of HTML
901
+ def doctype
902
+ %|<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">|
903
+ end
904
+
905
+ # Initialise the HTML generation methods for this version.
906
+ def element_init
907
+ extend TagMaker
908
+ methods = ""
909
+ # - -
910
+ for element in %w[ TT I B BIG SMALL EM STRONG DFN CODE SAMP KBD
911
+ VAR CITE ABBR ACRONYM SUB SUP SPAN BDO ADDRESS DIV MAP OBJECT
912
+ H1 H2 H3 H4 H5 H6 PRE Q INS DEL DL OL UL LABEL SELECT OPTGROUP
913
+ FIELDSET LEGEND BUTTON TABLE TITLE STYLE SCRIPT NOSCRIPT
914
+ TEXTAREA FORM A BLOCKQUOTE CAPTION ]
915
+ methods += <<-BEGIN + nn_element_def(element) + <<-END
916
+ def #{element.downcase}(attributes = {})
917
+ BEGIN
918
+ end
919
+ END
920
+ end
921
+
922
+ # - O EMPTY
923
+ for element in %w[ IMG BASE BR AREA LINK PARAM HR INPUT COL META ]
924
+ methods += <<-BEGIN + nOE_element_def(element) + <<-END
925
+ def #{element.downcase}(attributes = {})
926
+ BEGIN
927
+ end
928
+ END
929
+ end
930
+
931
+ # O O or - O
932
+ for element in %w[ HTML BODY P DT DD LI OPTION THEAD TFOOT TBODY
933
+ COLGROUP TR TH TD HEAD]
934
+ methods += <<-BEGIN + nO_element_def(element) + <<-END
935
+ def #{element.downcase}(attributes = {})
936
+ BEGIN
937
+ end
938
+ END
939
+ end
940
+ eval(methods)
941
+ end
942
+
943
+ end # Html4
944
+
945
+
946
+ # Mixin module for HTML version 4 transitional generation methods.
947
+ module Html4Tr # :nodoc:
948
+
949
+ # The DOCTYPE declaration for this version of HTML
950
+ def doctype
951
+ %|<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">|
952
+ end
953
+
954
+ # Initialise the HTML generation methods for this version.
955
+ def element_init
956
+ extend TagMaker
957
+ methods = ""
958
+ # - -
959
+ for element in %w[ TT I B U S STRIKE BIG SMALL EM STRONG DFN
960
+ CODE SAMP KBD VAR CITE ABBR ACRONYM FONT SUB SUP SPAN BDO
961
+ ADDRESS DIV CENTER MAP OBJECT APPLET H1 H2 H3 H4 H5 H6 PRE Q
962
+ INS DEL DL OL UL DIR MENU LABEL SELECT OPTGROUP FIELDSET
963
+ LEGEND BUTTON TABLE IFRAME NOFRAMES TITLE STYLE SCRIPT
964
+ NOSCRIPT TEXTAREA FORM A BLOCKQUOTE CAPTION ]
965
+ methods += <<-BEGIN + nn_element_def(element) + <<-END
966
+ def #{element.downcase}(attributes = {})
967
+ BEGIN
968
+ end
969
+ END
970
+ end
971
+
972
+ # - O EMPTY
973
+ for element in %w[ IMG BASE BASEFONT BR AREA LINK PARAM HR INPUT
974
+ COL ISINDEX META ]
975
+ methods += <<-BEGIN + nOE_element_def(element) + <<-END
976
+ def #{element.downcase}(attributes = {})
977
+ BEGIN
978
+ end
979
+ END
980
+ end
981
+
982
+ # O O or - O
983
+ for element in %w[ HTML BODY P DT DD LI OPTION THEAD TFOOT TBODY
984
+ COLGROUP TR TH TD HEAD ]
985
+ methods += <<-BEGIN + nO_element_def(element) + <<-END
986
+ def #{element.downcase}(attributes = {})
987
+ BEGIN
988
+ end
989
+ END
990
+ end
991
+ eval(methods)
992
+ end
993
+
994
+ end # Html4Tr
995
+
996
+
997
+ # Mixin module for generating HTML version 4 with framesets.
998
+ module Html4Fr # :nodoc:
999
+
1000
+ # The DOCTYPE declaration for this version of HTML
1001
+ def doctype
1002
+ %|<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">|
1003
+ end
1004
+
1005
+ # Initialise the HTML generation methods for this version.
1006
+ def element_init
1007
+ methods = ""
1008
+ # - -
1009
+ for element in %w[ FRAMESET ]
1010
+ methods += <<-BEGIN + nn_element_def(element) + <<-END
1011
+ def #{element.downcase}(attributes = {})
1012
+ BEGIN
1013
+ end
1014
+ END
1015
+ end
1016
+
1017
+ # - O EMPTY
1018
+ for element in %w[ FRAME ]
1019
+ methods += <<-BEGIN + nOE_element_def(element) + <<-END
1020
+ def #{element.downcase}(attributes = {})
1021
+ BEGIN
1022
+ end
1023
+ END
1024
+ end
1025
+ eval(methods)
1026
+ end
1027
+
1028
+ end # Html4Fr
1029
+
1030
+ end