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