| HTML-DOM documentation | Contained in the HTML-DOM distribution. |
HTML::DOM::Element::Table - A Perl class for representing 'table' elements in an HTML DOM tree
use HTML::DOM;
$doc = HTML::DOM->new;
$elem = $doc->createElement('table');
$elem->tHead;
$elem->tBodies->[0];
$elem->createTFoot;
# etc
This class represents 'table' elements in an HTML::DOM tree. It implements the HTMLTableElement DOM interface and inherits from HTML::DOM::Element (q.v.).
In addition to those inherited from HTML::DOM::Element and its superclasses, this class implements the following DOM methods:
Each of these returns the table's corresponding element, if it exists, or an empty list otherwise.
Returns a collection of all table row elements, or a list in list context.
Returns a collection of all 'tbody' elements, or a list in list context.
These get (optionally set) the corresponding HTML attributes.
Returns the table's 'thead' element, creating it if it doesn't exist.
Deletes the table's 'thead' element.
Returns the table's 'tfoot' element, creating it if it doesn't exist.
Does what you would think.
Returns the table's 'caption' element, creating it if it doesn't exist.
Deletes the caption.
Insert a new 'tr' element at the index specified by the first argument, and returns that new row.
Deletes the row at the index specified by the first arg.
HTML::DOM::Element::Caption
HTML::DOM::Element::TableColumn
HTML::DOM::Element::TableSection
HTML::DOM::Element::TR
HTML::DOM::Element::TableCell
| HTML-DOM documentation | Contained in the HTML-DOM distribution. |
package HTML::DOM::Element::Table; use strict; use warnings; use HTML::DOM::Exception qw 'HIERARCHY_REQUEST_ERR INDEX_SIZE_ERR'; require HTML::DOM::Collection; require HTML::DOM::Element; #require HTML::DOM::NodeList::Magic; our @ISA = qw'HTML::DOM::Element'; our $VERSION = '0.048'; sub caption { my $old = ((my $self = shift)->content_list)[0]; undef $old unless $old and $old->tag eq 'caption'; if(@_) { my $new = shift; my $tag = (eval{$new->tag}||''); $tag eq 'caption' or die new HTML'DOM'Exception HIERARCHY_REQUEST_ERR, $tag ? "A $tag element cannot be a table caption" : "Not a valid table caption"; if ($old) { $self->replaceChild($new, $old); } else { $self->unshift_content($new) } } return $old || (); } sub tHead { my $self = shift; for($self->content_list) { (my $tag = tag $_); if($tag =~ /^t(?:head|body|foot)\z/) { if(@_) { my $new = shift; my $new_tag = (eval{$new->tag}||''); $new_tag eq 'thead' or die new HTML'DOM'Exception HIERARCHY_REQUEST_ERR, $tag ? "A $new_tag element cannot be a table header" : "Not a valid table header"; $_->${\qw[preinsert replace_with][$tag eq 'thead']}( $new ); $self->ownerDocument->_modified; } return $tag eq 'thead' ? $_:(); } } @_ and $self->appendChild(shift); return; } sub tFoot { my $self = shift; for($self->content_list) { (my $tag = tag $_); if($tag =~ /^t(?:body|foot)\z/) { if(@_) { my $new = shift; my $new_tag = (eval{$new->tag}||''); $new_tag eq 'tfoot' or die new HTML'DOM'Exception HIERARCHY_REQUEST_ERR, $tag ? "A $new_tag element cannot be a table footer" : "Not a valid table footer"; $_->${\qw[preinsert replace_with][$tag eq 'tfoot']}( $new ); $self->ownerDocument->_modified; } return $tag eq 'tfoot' ? $_ : (); } } @_ and $self->appendChild(shift); return; } sub rows { # ~~~ I need to make this cache the resulting collection obj my $self = shift; if (wantarray) { # I need a grep in order to exclude text nodes. return grep tag $_ eq 'tr', map $_->content_list, map $self->$_, qw/ tHead tBodies tFoot /; } else { my $collection = HTML::DOM::Collection->new( my $list = HTML::DOM::NodeList::Magic->new( sub { grep tag $_ eq 'tr', map $_->content_list, map $self->$_, qw/ tHead tBodies tFoot /; } )); $self->ownerDocument-> _register_magic_node_list($list); $collection; } } sub tBodies { # ~~~ I need to make this cache the resulting collection obj my $self = shift; if (wantarray) { return grep tag $_ eq 'tbody', $self->content_list; } else { my $collection = HTML::DOM::Collection->new( my $list = HTML::DOM::NodeList::Magic->new( sub { grep tag $_ eq 'tbody', $self->content_list } )); $self->ownerDocument-> _register_magic_node_list($list); $collection; } } sub align { lc shift->_attr('align' => @_) } sub bgColor { shift->_attr('bgcolor' => @_) } sub border { shift->_attr( border => @_) } sub cellPadding { shift->_attr('cellpadding' => @_) } sub cellSpacing { shift->_attr('cellspacing' => @_) } sub frame { shift->_attr('frame' => @_) } sub rules { lc shift->_attr('rules' => @_) } sub summary { shift->_attr('summary' => @_) } sub width { shift->_attr('width' => @_) } sub createTHead { my $self = shift; my $th = $self->tHead; $th and return $th; my $inserted; $th = $self->ownerDocument->createElement('thead'); for($self->content_list) { next if tag $_ =~ /^c(?:aption|ol(?:group)?)\z/; $_->preinsert($th), ++$inserted, $self->ownerDocument->_modified, last } $self->appendChild($th) unless $inserted; $th } sub deleteTHead { my $self = shift; ($self->tHead||return)->delete; # ~~~ once I weaken upward refs, should I make this less destructive? $self->ownerDocument->_modified; return; } sub createTFoot { my $self = shift; my $tf = $self->tFoot; $tf and return $tf; my $inserted; $tf = $self->ownerDocument->createElement('tfoot'); for($self->content_list) { next if tag $_ =~ /^(?:c(?:aption|ol(?:group)?)|thead)\z/; $_->preinsert($tf), ++$inserted, $self->ownerDocument->_modified, last } $self->appendChild($tf) unless $inserted; $tf } sub deleteTFoot { my $self = shift; ($self->tFoot||return)->delete; # ~~~ once I weaken upward refs, should I make this less destructive? $self->ownerDocument->_modified; return; } sub createCaption { my $self = shift; my $th; $self->caption or $self->unshift_content($th = $self->ownerDocument->createElement('caption')), $self->ownerDocument->_modified, $th; } sub deleteCaption { my $self = shift; ($self->caption||return)->delete; # ~~~ once I weaken upward refs, should I make this less destructive? $self->ownerDocument->_modified; return; } sub insertRow { my $self = shift; my $ix = shift; my $len = (my $rows = $self->rows)->length; my $row = $self->ownerDocument->createElement('tr'); if(!$len) { # worst case if(my $tb = $self->tBodies->item(0)) { $tb->appendChild($row); } else { (my $tb = $self->ownerDocument ->createElement('tbody')) ->appendChild($row); $self->appendChild($tb); } } elsif($ix == -1 || $ix == $len) { $rows->item(-1)->postinsert( $row ); $self->ownerDocument->_modified; } elsif($ix < $len && $ix >= 0) { $rows->item($ix)->preinsert($row); $self->ownerDocument->_modified } else { die new HTML::DOM::Exception INDEX_SIZE_ERR, "Index $ix is out of range" } return $row; } sub deleteRow { my $self = shift; ($self->rows->item(shift)||return)->delete; # ~~~ once I weaken upward refs, should I make this less destructive? $self->ownerDocument->_modified; return; }
# ------- HTMLTableCaptionElement interface ---------- # package HTML::DOM::Element::Caption; our $VERSION = '0.048'; our @ISA = 'HTML::DOM::Element'; *align = \&HTML::DOM::Element::Table::align; # ------- HTMLTableColElement interface ---------- # package HTML::DOM::Element::TableColumn; our $VERSION = '0.048'; our @ISA = 'HTML::DOM::Element'; *align = \&HTML::DOM::Element::Table::align; sub ch { shift->_attr('char' => @_) } sub chOff { shift->_attr( charoff => @_) } sub span { shift->_attr('span' => @_) } sub vAlign { lc shift->_attr('valign' => @_) } sub width { shift->_attr('width' => @_) } # ------- HTMLTableSectionElement interface ---------- # package HTML::DOM::Element::TableSection; our $VERSION = '0.048'; our @ISA = 'HTML::DOM::Element'; *align = \&HTML::DOM::Element::Table::align; *ch = \&HTML::DOM::Element::TableColumn::ch; *chOff = \&HTML::DOM::Element::TableColumn::chOff; *vAlign = \&HTML::DOM::Element::TableColumn::vAlign; sub rows { # ~~~ I need to make this cache the resulting collection obj my $self = shift; if (wantarray) { # I need a grep in order to exclude text nodes. return grep tag $_ eq 'tr', $self->content_list, } else { my $collection = HTML::DOM::Collection->new( my $list = HTML::DOM::NodeList::Magic->new( sub { grep tag $_ eq 'tr', $self->content_list; } )); $self->ownerDocument-> _register_magic_node_list($list); $collection; } } sub insertRow { my $self = shift; my $ix = shift||0; my $len = (my $rows = $self->rows)->length; my $row = $self->ownerDocument->createElement('tr'); if(!$len) { $self->appendChild($row); } elsif($ix == -1 || $ix == $len) { $rows->item(-1)->postinsert( $row ); $self->ownerDocument->_modified; } elsif($ix < $len && $ix >= 0) { $rows->item($ix)->preinsert($row); $self->ownerDocument->_modified; } else { die new HTML::DOM::Exception HTML::DOM::Exception::INDEX_SIZE_ERR, "Index $ix is out of range" } return $row; } *deleteRow = \&HTML::DOM::Element::Table::deleteRow; # ------- HTMLTableRowElement interface ---------- # package HTML::DOM::Element::TR; our $VERSION = '0.048'; our @ISA = 'HTML::DOM::Element'; sub rowIndex { my $self = shift; my $ix = 0; for($self->look_up(_tag => 'table')->rows){ return $ix if $self == $_; $ix++ } die "Internal error in HTML::DOM::Element::TR::rowIndex: " . "This table row is not inside the table it is inside. " . "Please report this bug." } sub sectionRowIndex { my $self = shift; my $parent = $self->parent; while(!$parent->isa('HTML::DOM::Element::TableSection')) { # If we get here, there is probably something wrong, should # I just throw an error instead? $parent = $parent->parent; } my $ix = 0; for($parent->rows){ return $ix if $self == $_; $ix++ } die "Internal error in HTML::DOM::Element::TR::sectionRowIndex: " . "This table row is not inside the table section it is " . "inside. Please report this bug." } sub cells { # ~~~ I need to make this cache the resulting collection obj my $self = shift; if (wantarray) { # I need a grep in order to exclude text nodes. return grep tag $_ =~ /^t[hd]\z/, $self->content_list, } else { my $collection = HTML::DOM::Collection->new( my $list = HTML::DOM::NodeList::Magic->new( sub { grep tag $_ =~ /^t[hd]\z/, $self->content_list; } )); $self->ownerDocument-> _register_magic_node_list($list); $collection; } } *align = \&HTML::DOM::Element::Table::align; *bgColor = \&HTML::DOM::Element::Table::bgColor; *ch = \&HTML::DOM::Element::TableColumn::ch; *chOff = \&HTML::DOM::Element::TableColumn::chOff; *vAlign = \&HTML::DOM::Element::TableColumn::vAlign; sub insertCell { my $self = shift; my $ix = shift||0; my $len = (my $cels = $self->cells)->length; my $cel = $self->ownerDocument->createElement('td'); if(!$len) { $self->appendChild($cel); } elsif($ix == -1 || $ix == $len) { $cels->item(-1)->postinsert( $cel ); $self->ownerDocument->_modified; } elsif($ix < $len && $ix >= 0) { $cels->item($ix)->preinsert($cel); $self->ownerDocument->_modified; } else { die new HTML::DOM::Exception HTML::DOM::Exception::INDEX_SIZE_ERR, "Index $ix is out of range" } return $cel; } sub deleteCell { my $self = shift; ($self->cells->item(shift)||return)->delete; # ~~~ once I weaken upward refs, should I make this less destructive? $self->ownerDocument->_modified; return; } # ------- HTMLTableCellElement interface ---------- # package HTML::DOM::Element::TableCell; our $VERSION = '0.048'; our @ISA = 'HTML::DOM::Element'; sub cellIndex { my $self = shift; my $ix = 0; for($self->parent->cells){ return $ix if $self == $_; $ix++ } die "Internal error in HTML::DOM::Element::TR::rowIndex: " . "This table row is not inside the table it is inside. " . "Please report this bug." } sub abbr { shift->_attr('abbr' => @_) } *align = \&HTML::DOM::Element::Table::align; sub axis { shift->_attr('axis' => @_) } *bgColor = \&HTML::DOM::Element::Table::bgColor; *ch = \&HTML::DOM::Element::TableColumn::ch; *chOff = \&HTML::DOM::Element::TableColumn::chOff; sub colSpan { shift->_attr('colspan' => @_) } sub headers { shift->_attr('headers' => @_) } sub height { shift->_attr('height' => @_) } sub noWrap { shift->_attr(nowrap => @_ ? $_[0] ? 'nowrap' : undef : ()) } sub rowSpan { shift->_attr('rowspan' => @_) } sub scope { lc shift->_attr('scope' => @_) } *vAlign = \&HTML::DOM::Element::TableColumn::vAlign; *width = \&HTML::DOM::Element::Table::width;