html-table 1.5.0 → 1.5.1

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.
Files changed (59) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +3 -1
  3. data.tar.gz.sig +0 -0
  4. data/CHANGES +159 -155
  5. data/MANIFEST +59 -59
  6. data/README +132 -132
  7. data/certs/djberg96_pub.pem +22 -17
  8. data/doc/attributes.rdoc +143 -143
  9. data/doc/table.rdoc +158 -158
  10. data/doc/table_body.rdoc +9 -9
  11. data/doc/table_caption.rdoc +9 -9
  12. data/doc/table_colgroup.rdoc +8 -8
  13. data/doc/table_colgroup_col.rdoc +9 -9
  14. data/doc/table_content.rdoc +15 -15
  15. data/doc/table_foot.rdoc +8 -8
  16. data/doc/table_head.rdoc +11 -11
  17. data/doc/table_row.rdoc +105 -105
  18. data/doc/table_row_data.rdoc +92 -92
  19. data/doc/table_row_header.rdoc +7 -7
  20. data/examples/advanced.rb +128 -128
  21. data/examples/intermediate1.rb +72 -72
  22. data/examples/intermediate2.rb +62 -62
  23. data/examples/intermediate3.rb +46 -46
  24. data/examples/simple1.rb +39 -39
  25. data/examples/simple2.rb +47 -47
  26. data/examples/simple3.rb +41 -41
  27. data/html-table.gemspec +28 -28
  28. data/lib/html-table.rb +1 -1
  29. data/lib/html/attribute_handler.rb +403 -403
  30. data/lib/html/body.rb +37 -37
  31. data/lib/html/caption.rb +49 -49
  32. data/lib/html/col.rb +41 -41
  33. data/lib/html/colgroup.rb +113 -113
  34. data/lib/html/content.rb +18 -18
  35. data/lib/html/data.rb +69 -69
  36. data/lib/html/foot.rb +49 -49
  37. data/lib/html/head.rb +49 -49
  38. data/lib/html/header.rb +65 -65
  39. data/lib/html/html_handler.rb +120 -120
  40. data/lib/html/row.rb +188 -188
  41. data/lib/html/table.rb +323 -323
  42. data/lib/html/tablesection.rb +48 -48
  43. data/lib/html/tag_handler.rb +121 -121
  44. data/test/test_attribute_handler.rb +361 -361
  45. data/test/test_body.rb +87 -87
  46. data/test/test_caption.rb +80 -80
  47. data/test/test_col.rb +40 -40
  48. data/test/test_colgroup.rb +89 -89
  49. data/test/test_data.rb +77 -77
  50. data/test/test_foot.rb +111 -111
  51. data/test/test_head.rb +104 -104
  52. data/test/test_header.rb +77 -77
  53. data/test/test_html_handler.rb +37 -37
  54. data/test/test_row.rb +141 -141
  55. data/test/test_table.rb +159 -158
  56. data/test/test_tablesection.rb +42 -42
  57. data/test/test_tag_handler.rb +90 -90
  58. metadata +25 -20
  59. metadata.gz.sig +0 -0
@@ -1,105 +1,105 @@
1
- = Description
2
- A Table::Row object represents a single <TR></TR> instance for an HTML
3
- Table. Although it is nested under Table, it is not a subclass of Table.
4
- It is, however, a subclass of Array.
5
-
6
- == Synopsis
7
- require "html/table"
8
- include HTML
9
-
10
- table = HTML::Table.new
11
-
12
- row1 = Table::Row.new{ |r|
13
- r.align = "left"
14
- r.bgcolor = "green"
15
- r.content = ["foo","bar","baz"]
16
- }
17
-
18
- row2 = Table::Row.new{ |r|
19
- r.align = "right"
20
- r.bgcolor = "blue"
21
- r.content = "hello world"
22
- }
23
-
24
- table.push row1, row2
25
-
26
- row1.content = "foofoo"
27
- row1.configure(3){ |d| d.bgcolor = "pink" }
28
-
29
- row1.push Table::Row::Header.new{ |h|
30
- h.colspan = 2
31
- h.content = "This is a table header"
32
- }
33
-
34
- row2.push Table::Row::Header.new{ |h|
35
- h.colspan = 2
36
- h.content = "This is also a table header"
37
- }
38
-
39
- puts table.html
40
-
41
- #### output ####
42
- <table>
43
- <tr align='left' bgcolor='green'>
44
- <td>foo</td>
45
- <td>bar</td>
46
- <td>baz</td>
47
- <td bgcolor='pink'>foofoo</td>
48
- <th colspan=2>This is a table header</th>
49
- </tr>
50
- <tr align='right' bgcolor='blue'>
51
- <td>hello world</td>
52
- <th colspan=2>This is also a table header</th>
53
- </tr>
54
- </table>
55
-
56
- See the 'examples' directory for more examples.
57
-
58
- == Mixins
59
- Table::Row is a subclass of Array and therefore mixes in Enumerable. It
60
- also mixes in Attribute_Handler.
61
-
62
- == Class Methods
63
- Table::Row.new(arg=nil)
64
- Table::Row.new(arg=nil){ |t| ... }
65
- Creates a new table. You can set attributes for the TableRow by passing
66
- a block.
67
-
68
- If +arg+ is supplied, it is automatically interpreted to be content.
69
- This is a shortcut for Table::Row.new{ |r| r.content = '...' }.
70
-
71
- == Instance Methods
72
- Table::Row#[]=(index,obj)
73
- Assigns +obj+ to index. The +obj+ must be a Table::Row::Header or
74
- Table::Row::Data object, or a TypeError is raised.
75
-
76
- Table::Row#content
77
- Returns the HTML content of the TableRow instance, i.e. the stuff between
78
- the <TR> and </TR> tags.
79
-
80
- Table::Row#content=(args)
81
- Because a Table::Row doesn't store any of its own content, the arguments
82
- to this method must be a Table::Row::Data object, a Table::Row::Header
83
- object, or a String (or an array of any of these). In the latter case,
84
- a single Table::Row::Data object is created for each string.
85
-
86
- Table::Row#html
87
- Returns the entire HTML content of the TableRow instance.
88
-
89
- Table::Row#push(obj)
90
- Pushes +obj+ onto the Table::Row. The +obj+ must be a
91
- Table::Row::Data or Table::Row::Header object, or a TypeError is
92
- raised.
93
-
94
- Table::Row#unshift(obj)
95
- Unshifts +obj+ onto the Table::Row. The same rules for push apply
96
- to unshift as well.
97
-
98
- == Notes
99
- String attributes are quoted. Numeric attributes are not.
100
-
101
- Some attributes have type checking. Some check for valid arguments. In
102
- the latter case, it is case-insensitive.
103
-
104
- Using a non-standard extension (e.g. "background") will send a warning to
105
- STDERR in $VERBOSE (-w) mode.
1
+ = Description
2
+ A Table::Row object represents a single <TR></TR> instance for an HTML
3
+ Table. Although it is nested under Table, it is not a subclass of Table.
4
+ It is, however, a subclass of Array.
5
+
6
+ == Synopsis
7
+ require "html/table"
8
+ include HTML
9
+
10
+ table = HTML::Table.new
11
+
12
+ row1 = Table::Row.new{ |r|
13
+ r.align = "left"
14
+ r.bgcolor = "green"
15
+ r.content = ["foo","bar","baz"]
16
+ }
17
+
18
+ row2 = Table::Row.new{ |r|
19
+ r.align = "right"
20
+ r.bgcolor = "blue"
21
+ r.content = "hello world"
22
+ }
23
+
24
+ table.push row1, row2
25
+
26
+ row1.content = "foofoo"
27
+ row1.configure(3){ |d| d.bgcolor = "pink" }
28
+
29
+ row1.push Table::Row::Header.new{ |h|
30
+ h.colspan = 2
31
+ h.content = "This is a table header"
32
+ }
33
+
34
+ row2.push Table::Row::Header.new{ |h|
35
+ h.colspan = 2
36
+ h.content = "This is also a table header"
37
+ }
38
+
39
+ puts table.html
40
+
41
+ #### output ####
42
+ <table>
43
+ <tr align='left' bgcolor='green'>
44
+ <td>foo</td>
45
+ <td>bar</td>
46
+ <td>baz</td>
47
+ <td bgcolor='pink'>foofoo</td>
48
+ <th colspan=2>This is a table header</th>
49
+ </tr>
50
+ <tr align='right' bgcolor='blue'>
51
+ <td>hello world</td>
52
+ <th colspan=2>This is also a table header</th>
53
+ </tr>
54
+ </table>
55
+
56
+ See the 'examples' directory for more examples.
57
+
58
+ == Mixins
59
+ Table::Row is a subclass of Array and therefore mixes in Enumerable. It
60
+ also mixes in Attribute_Handler.
61
+
62
+ == Class Methods
63
+ Table::Row.new(arg=nil)
64
+ Table::Row.new(arg=nil){ |t| ... }
65
+ Creates a new table. You can set attributes for the TableRow by passing
66
+ a block.
67
+
68
+ If +arg+ is supplied, it is automatically interpreted to be content.
69
+ This is a shortcut for Table::Row.new{ |r| r.content = '...' }.
70
+
71
+ == Instance Methods
72
+ Table::Row#[]=(index,obj)
73
+ Assigns +obj+ to index. The +obj+ must be a Table::Row::Header or
74
+ Table::Row::Data object, or a TypeError is raised.
75
+
76
+ Table::Row#content
77
+ Returns the HTML content of the TableRow instance, i.e. the stuff between
78
+ the <TR> and </TR> tags.
79
+
80
+ Table::Row#content=(args)
81
+ Because a Table::Row doesn't store any of its own content, the arguments
82
+ to this method must be a Table::Row::Data object, a Table::Row::Header
83
+ object, or a String (or an array of any of these). In the latter case,
84
+ a single Table::Row::Data object is created for each string.
85
+
86
+ Table::Row#html
87
+ Returns the entire HTML content of the TableRow instance.
88
+
89
+ Table::Row#push(obj)
90
+ Pushes +obj+ onto the Table::Row. The +obj+ must be a
91
+ Table::Row::Data or Table::Row::Header object, or a TypeError is
92
+ raised.
93
+
94
+ Table::Row#unshift(obj)
95
+ Unshifts +obj+ onto the Table::Row. The same rules for push apply
96
+ to unshift as well.
97
+
98
+ == Notes
99
+ String attributes are quoted. Numeric attributes are not.
100
+
101
+ Some attributes have type checking. Some check for valid arguments. In
102
+ the latter case, it is case-insensitive.
103
+
104
+ Using a non-standard extension (e.g. "background") will send a warning to
105
+ STDERR in $VERBOSE (-w) mode.
@@ -1,92 +1,92 @@
1
- == Description
2
- A Table::Row::Data object represents a single <TD></TD> instance for an HTML
3
- Table. For purposes of html-table, it also represents a "column"
4
-
5
- == Synopsis
6
- require "html/table"
7
- require HTML
8
-
9
- Table::Row.end_tags = false
10
- Table::Row::Data.end_tags = false
11
-
12
- table = Table.new{ |t| t.border = 1 }
13
- row = Table::Row.new
14
-
15
- col1 = Table::Row::Data.new{ |d|
16
- d.abbr = "test"
17
- d.align = "right"
18
- d.content = "hello world"
19
- }
20
-
21
- col2 = Table::Row::Data.new{ |d|
22
- d.align = "center"
23
- d.content = "Matz rules!"
24
- }
25
-
26
- col3 = Table::Row::Data.new{ |d|
27
- d.align = "left"
28
- d.content = "Foo!"
29
- }
30
-
31
- row.push col1, col2, col3
32
-
33
- puts table.html
34
-
35
- #### output ####
36
- <table border=1>
37
- <tr>
38
- <td abbr='test' align='right'>hello world
39
- <td align='center'>Matz rules!
40
- <td align='left'>Foo!
41
- </table>
42
-
43
- See the 'examples' directory under 'doc' for more examples.
44
-
45
- == Mixins
46
- Table::Row::Data mixes in Attribute_Handler.
47
-
48
- == Class Methods
49
- Table::Row::Data.new(arg=nil)
50
- Table::Row::Data.new(arg=nil){ |t| ... }
51
- Creates a new table. You can set attributes for the Table::Row::Data by
52
- passing a block.
53
-
54
- If +arg+ is supplied, it is automatically interpreted to be content.
55
- This is a shortcut for Table::Row::Data.new{ |d| d.content = '...' }.
56
-
57
- Table::Row::Data.end_tags
58
- Returns true or false to indicate whether end tags are included or not.
59
-
60
- Table::Row::Data.end_tags=(bool)
61
- Sets whether or not end tags are included in the html.
62
-
63
- Table::Row::Data.indent_level
64
- Returns the current number of spaces that <TD> tags are indented. The
65
- default is 6.
66
-
67
- Table::Row::Data.indent_level=(num)
68
- Sets the number of spaces that <TD> tags are indented.
69
-
70
- == Instance Methods
71
- TableData#content
72
- Returns the content of the TableData object, i.e. the stuff between <TD>
73
- and </TD>.
74
-
75
- Table::Row::Data#content=(string)
76
- Sets the content for the TableData object, i.e. the stuff between <TD>
77
- and </TD>.
78
-
79
- Table::Row::Data#html
80
- Returns all html content for the TableData instance.
81
-
82
- == Notes
83
- The end tags for Table::Row::Data objects are are the same line as the
84
- begin tags.
85
-
86
- String attributes are quoted. Numeric attributes are not.
87
-
88
- Some attributes have type checking. Some check for valid arguments. In
89
- the latter case, it is case-insensitive.
90
-
91
- Using a non-standard extension (e.g. "background") will send a warning to
92
- STDERR in $VERBOSE (-w) mode.
1
+ == Description
2
+ A Table::Row::Data object represents a single <TD></TD> instance for an HTML
3
+ Table. For purposes of html-table, it also represents a "column"
4
+
5
+ == Synopsis
6
+ require "html/table"
7
+ require HTML
8
+
9
+ Table::Row.end_tags = false
10
+ Table::Row::Data.end_tags = false
11
+
12
+ table = Table.new{ |t| t.border = 1 }
13
+ row = Table::Row.new
14
+
15
+ col1 = Table::Row::Data.new{ |d|
16
+ d.abbr = "test"
17
+ d.align = "right"
18
+ d.content = "hello world"
19
+ }
20
+
21
+ col2 = Table::Row::Data.new{ |d|
22
+ d.align = "center"
23
+ d.content = "Matz rules!"
24
+ }
25
+
26
+ col3 = Table::Row::Data.new{ |d|
27
+ d.align = "left"
28
+ d.content = "Foo!"
29
+ }
30
+
31
+ row.push col1, col2, col3
32
+
33
+ puts table.html
34
+
35
+ #### output ####
36
+ <table border=1>
37
+ <tr>
38
+ <td abbr='test' align='right'>hello world
39
+ <td align='center'>Matz rules!
40
+ <td align='left'>Foo!
41
+ </table>
42
+
43
+ See the 'examples' directory under 'doc' for more examples.
44
+
45
+ == Mixins
46
+ Table::Row::Data mixes in Attribute_Handler.
47
+
48
+ == Class Methods
49
+ Table::Row::Data.new(arg=nil)
50
+ Table::Row::Data.new(arg=nil){ |t| ... }
51
+ Creates a new table. You can set attributes for the Table::Row::Data by
52
+ passing a block.
53
+
54
+ If +arg+ is supplied, it is automatically interpreted to be content.
55
+ This is a shortcut for Table::Row::Data.new{ |d| d.content = '...' }.
56
+
57
+ Table::Row::Data.end_tags
58
+ Returns true or false to indicate whether end tags are included or not.
59
+
60
+ Table::Row::Data.end_tags=(bool)
61
+ Sets whether or not end tags are included in the html.
62
+
63
+ Table::Row::Data.indent_level
64
+ Returns the current number of spaces that <TD> tags are indented. The
65
+ default is 6.
66
+
67
+ Table::Row::Data.indent_level=(num)
68
+ Sets the number of spaces that <TD> tags are indented.
69
+
70
+ == Instance Methods
71
+ TableData#content
72
+ Returns the content of the TableData object, i.e. the stuff between <TD>
73
+ and </TD>.
74
+
75
+ Table::Row::Data#content=(string)
76
+ Sets the content for the TableData object, i.e. the stuff between <TD>
77
+ and </TD>.
78
+
79
+ Table::Row::Data#html
80
+ Returns all html content for the TableData instance.
81
+
82
+ == Notes
83
+ The end tags for Table::Row::Data objects are are the same line as the
84
+ begin tags.
85
+
86
+ String attributes are quoted. Numeric attributes are not.
87
+
88
+ Some attributes have type checking. Some check for valid arguments. In
89
+ the latter case, it is case-insensitive.
90
+
91
+ Using a non-standard extension (e.g. "background") will send a warning to
92
+ STDERR in $VERBOSE (-w) mode.
@@ -1,7 +1,7 @@
1
- == Description
2
- A Table::Row::Header object represents a single <TH></TH> instance for
3
- an HTML Table.
4
-
5
- == Notes
6
- The Table::Row::Header class is identical in every way to the
7
- Table::Row::Data class, except for the begin and end tags.
1
+ == Description
2
+ A Table::Row::Header object represents a single <TH></TH> instance for
3
+ an HTML Table.
4
+
5
+ == Notes
6
+ The Table::Row::Header class is identical in every way to the
7
+ Table::Row::Data class, except for the begin and end tags.
@@ -1,128 +1,128 @@
1
- ##############################################################################
2
- # advanced1.rb
3
- #
4
- # For this example we'll use every feature I can think of to come up with
5
- # the example found in "HTML: The Definitive Guide", pp. 395-396 (O'Reilly
6
- # & Associates, 3rd ed).
7
- #
8
- # You can run this example via the 'example:advanced' rake task.
9
- ##############################################################################
10
- require 'html/table'
11
- include HTML
12
-
13
- Table::Row::Data.end_tags = false
14
- Table::Row::Header.end_tags = false
15
-
16
- # Demonstrates the DSL style syntax
17
- table = Table.new do
18
- border 1
19
- cellspacing 0
20
- cellpadding 0
21
- rules 'groups'
22
- end
23
-
24
- # Demonstrates the use of setters after object creation
25
- caption = Table::Caption.new
26
- caption.align = "bottom"
27
- caption.content = "Kumquat versus a poked eye, by gender"
28
-
29
- thead = Table::Head.create
30
- tbody = Table::Body.new
31
- tfoot = Table::Foot.create
32
-
33
- # Add a row with a td and th, then configure after the fact.
34
- thead.push Table::Row.new{ |r|
35
- r.content = Table::Row::Data.new, Table::Row::Header.new
36
- }
37
-
38
- # And again, longhand
39
- hrow = Table::Row.new
40
- h1 = Table::Row::Header.new('Eating Kumquats')
41
- h2 = Table::Row::Header.new('Poke In The Eye')
42
- hrow.push h1, h2
43
- thead.push hrow
44
-
45
- # Configure a row after the fact
46
- thead.configure(0,0){ |d|
47
- d.colspan = 2
48
- d.rowspan = 2
49
- }
50
-
51
- thead.configure(0,1){ |h|
52
- h.colspan = 2
53
- h.align = "center"
54
- h.content = "Preference"
55
- }
56
-
57
- # Ugly, but just to show you that it's possible
58
- tbody.push(
59
- Table::Row.new{ |r|
60
- r.align = "center"
61
- r.content =
62
- Table::Row::Header.new{ |h|
63
- h.rowspan = 2
64
- h.content = "Gender"
65
- },
66
- Table::Row::Header.new{ |h| h.content = "Male" },
67
- "73%",
68
- "27%"
69
- }
70
- )
71
-
72
- brow = Table::Row.new{ |r| r.align = "center" }
73
- bheader = Table::Row::Header.new('Female')
74
- brow.push(bheader,"16%","84%")
75
-
76
- tbody.push(brow)
77
-
78
- frow = Table::Row.new{ |r|
79
- r.content = Table::Row::Data.new{ |d|
80
- d.colspan = 4
81
- d.align = "center"
82
- d.content = "Note: eye pokes did not result in permanent injury"
83
- }
84
- }
85
-
86
- tfoot[0] = frow
87
-
88
- table.push thead, tbody, tfoot
89
-
90
- # caption is added last, but does the right thing
91
- table.push caption
92
-
93
- puts table.html
94
-
95
- =begin
96
- ### OUTPUT ###
97
- <table border=1 cellspacing=0 cellpadding=0 rules='groups'>
98
- <caption align='bottom'>Kumquat versus a poked eye, by gender</caption>
99
- <thead>
100
- <tr>
101
- <td colspan=2 rowspan=2>
102
- <th colspan=2 align='center'>Preference
103
- </tr>
104
- <tr>
105
- <th>Eating Kumquats
106
- <th>Poke In The Eye
107
- </tr>
108
- </thead>
109
- <tbody>
110
- <tr align='center'>
111
- <th rowspan=2>Gender
112
- <th>Male
113
- <td>73%
114
- <td>27%
115
- </tr>
116
- <tr align='center'>
117
- <th>Female
118
- <td>16%
119
- <td>84%
120
- </tr>
121
- </tbody>
122
- <tfoot>
123
- <tr>
124
- <td colspan=4 align='center'>Note: eye pokes did not result in permanent injury
125
- </tr>
126
- </tfoot>
127
- </table>
128
- =end
1
+ ##############################################################################
2
+ # advanced1.rb
3
+ #
4
+ # For this example we'll use every feature I can think of to come up with
5
+ # the example found in "HTML: The Definitive Guide", pp. 395-396 (O'Reilly
6
+ # & Associates, 3rd ed).
7
+ #
8
+ # You can run this example via the 'example:advanced' rake task.
9
+ ##############################################################################
10
+ require 'html/table'
11
+ include HTML
12
+
13
+ Table::Row::Data.end_tags = false
14
+ Table::Row::Header.end_tags = false
15
+
16
+ # Demonstrates the DSL style syntax
17
+ table = Table.new do
18
+ border 1
19
+ cellspacing 0
20
+ cellpadding 0
21
+ rules 'groups'
22
+ end
23
+
24
+ # Demonstrates the use of setters after object creation
25
+ caption = Table::Caption.new
26
+ caption.align = "bottom"
27
+ caption.content = "Kumquat versus a poked eye, by gender"
28
+
29
+ thead = Table::Head.create
30
+ tbody = Table::Body.new
31
+ tfoot = Table::Foot.create
32
+
33
+ # Add a row with a td and th, then configure after the fact.
34
+ thead.push Table::Row.new{ |r|
35
+ r.content = Table::Row::Data.new, Table::Row::Header.new
36
+ }
37
+
38
+ # And again, longhand
39
+ hrow = Table::Row.new
40
+ h1 = Table::Row::Header.new('Eating Kumquats')
41
+ h2 = Table::Row::Header.new('Poke In The Eye')
42
+ hrow.push h1, h2
43
+ thead.push hrow
44
+
45
+ # Configure a row after the fact
46
+ thead.configure(0,0){ |d|
47
+ d.colspan = 2
48
+ d.rowspan = 2
49
+ }
50
+
51
+ thead.configure(0,1){ |h|
52
+ h.colspan = 2
53
+ h.align = "center"
54
+ h.content = "Preference"
55
+ }
56
+
57
+ # Ugly, but just to show you that it's possible
58
+ tbody.push(
59
+ Table::Row.new{ |r|
60
+ r.align = "center"
61
+ r.content =
62
+ Table::Row::Header.new{ |h|
63
+ h.rowspan = 2
64
+ h.content = "Gender"
65
+ },
66
+ Table::Row::Header.new{ |h| h.content = "Male" },
67
+ "73%",
68
+ "27%"
69
+ }
70
+ )
71
+
72
+ brow = Table::Row.new{ |r| r.align = "center" }
73
+ bheader = Table::Row::Header.new('Female')
74
+ brow.push(bheader,"16%","84%")
75
+
76
+ tbody.push(brow)
77
+
78
+ frow = Table::Row.new{ |r|
79
+ r.content = Table::Row::Data.new{ |d|
80
+ d.colspan = 4
81
+ d.align = "center"
82
+ d.content = "Note: eye pokes did not result in permanent injury"
83
+ }
84
+ }
85
+
86
+ tfoot[0] = frow
87
+
88
+ table.push thead, tbody, tfoot
89
+
90
+ # caption is added last, but does the right thing
91
+ table.push caption
92
+
93
+ puts table.html
94
+
95
+ =begin
96
+ ### OUTPUT ###
97
+ <table border=1 cellspacing=0 cellpadding=0 rules='groups'>
98
+ <caption align='bottom'>Kumquat versus a poked eye, by gender</caption>
99
+ <thead>
100
+ <tr>
101
+ <td colspan=2 rowspan=2>
102
+ <th colspan=2 align='center'>Preference
103
+ </tr>
104
+ <tr>
105
+ <th>Eating Kumquats
106
+ <th>Poke In The Eye
107
+ </tr>
108
+ </thead>
109
+ <tbody>
110
+ <tr align='center'>
111
+ <th rowspan=2>Gender
112
+ <th>Male
113
+ <td>73%
114
+ <td>27%
115
+ </tr>
116
+ <tr align='center'>
117
+ <th>Female
118
+ <td>16%
119
+ <td>84%
120
+ </tr>
121
+ </tbody>
122
+ <tfoot>
123
+ <tr>
124
+ <td colspan=4 align='center'>Note: eye pokes did not result in permanent injury
125
+ </tr>
126
+ </tfoot>
127
+ </table>
128
+ =end