Bivio::UI::HTML::Widget::Tag
# Copyright (c) 2005-2006 bivio Software, Inc. All Rights Reserved.
# $Id$
package Bivio::UI::HTML::Widget::Tag;
use strict;
use Bivio::Base 'HTMLWidget.ControlBase';
use Bivio::UI::ViewLanguageAUTOLOAD;
my($_EMPTY) = [qw(
area
base
basefont
br
col
frame
hr
img
input
isindex
link
meta
param
)];
sub NEW_ARGS {
return [qw(tag ?value ?class)];
}
sub control_on_render {
my($self, $source, $wo) = shift->widget_render_args(@_);
my($buf) = '';
$self->can('render_tag_value') ? $self->render_tag_value($source, \$buf)
: $self->render_attr('value', $source, \$buf);
$buf = $self->render_simple_attr(tag_empty_value => $source)
unless length($buf);
return unless length($buf)
|| $self->render_simple_attr('tag_if_empty', $source);
my($t) = lc(${$self->render_attr('tag', $source)});
$self->die('tag', $source, $t, ': is not a valid HTML tag')
unless $t =~ /^([a-z\d]+:)?[a-z]+\d*$/;
my($pre, $post) = $buf !~ qr{\w} ? ('', '')
: $self->render_simple_attr('bracket_value_in_comment', $source)
? ("\n<!--\n", "\n-->\n")
: map($self->render_simple_attr($_, $source),
'tag_pre_value',
'tag_post_value',
);
my($v) = '';
$self->internal_tag_render_attrs($source, \$v);
$wo->append_buffer(
"<$t$v",
(length($buf) || !_empty($t) ? ('>', \$pre, \$buf, \$post, "</$t>") : ' />'),
);
if ($self->unsafe_get('class')) {
foreach my $class (
split(' ', $self->render_simple_attr('class', $source))) {
_add_to_view_css($self, $class, $source);
}
}
return;
}
sub initialize {
my($self, $source) = @_;
my($t, $v) = $self->unsafe_get(qw(tag value));
$self->die('missing tag')
unless $t;
if (_empty($t)) {
if ($v and $v =~ /^[a-z0-9]+$/) {
$self->put_unless_exists(class => $v);
}
$self->put(value => '');
$self->put_unless_exists(tag_if_empty => 1);
}
elsif (!defined($v)) {
$self->die('"value" is a required parameter')
unless $self->can('render_tag_value');
}
elsif (!ref($t) && defined($v) && length($v) == 0) {
$self->put_unless_exists(tag_if_empty => 1);
}
$self->unsafe_initialize_attr('value', $source);
$self->initialize_attr('tag', undef, $source);
$self->die(
'bracket_value_in_comment',
undef,
'cannot specify with either tag_pre_value or tag_post_value',
) if $self->has_keys('tag_pre_value')
|| $self->has_keys('tag_post_value')
and $self->has_keys('bracket_value_in_comment');
$self->initialize_attr(bracket_value_in_comment => 0, $source);
$self->map_invoke(unsafe_initialize_attr => [qw(
tag_pre_value
tag_post_value
tag_if_empty
tag_empty_value
tag_post_value
)], undef, [$source]);
return shift->SUPER::initialize(@_);
}
sub internal_as_string {
return shift->unsafe_get('tag', 'value');
}
sub internal_tag_render_attrs {
my($self, $source, $buffer) = @_;
$self->SUPER::control_on_render($source, $buffer);
return;
}
sub _add_to_view_css {
my($self, $class, $source) = @_;
my($path) = [join('.', $self->get('tag'), $class)];
my($current) = $self->unsafe_get('parent');
while ($current) {
if ($current->isa('Bivio::UI::HTML::Widget::Tag')
|| $current->isa('Bivio::UI::HTML::Widget::TableBase')) {
my($tag) = $current->unsafe_get('tag') || '';
#TODO: can't render complex values using render_simple_attr()
# because we don't know which source was used to render the value
my($class) = $current->unsafe_get('class')
&& ! ref($current->get('class'))
? split(' ', $current->get('class'))
: '';
my($id) = $tag . ($class ? ".$class" : '');
unshift(@$path, $id)
if $id;
}
$current = $current->unsafe_get('parent');
}
b_use('View.CSS')->add_to_css($self, join(' ', @$path), $class, $source);
return;
}
sub _empty {
my($tag) = @_;
return 0
if ref($tag);
$tag = lc($tag);
return grep($tag eq $_, @$_EMPTY) ? 1 : 0;
}
1;