+sub javascript {
+ my ($self, $data) = @_;
+ return $self->html_tag('script', $data, type => 'text/javascript');
+}
+
+sub stylesheet_tag {
+ my $self = shift;
+ my $code = '';
+
+ foreach my $file (@_) {
+ $file .= '.css' unless $file =~ m/\.css$/;
+ $file = "css/${file}" unless $file =~ m|/|;
+
+ $code .= qq|<link rel="stylesheet" href="${file}" type="text/css" media="screen" />|;
+ }
+
+ return $code;
+}
+
+sub date_tag {
+ my ($self, $name, $value, @slurp) = @_;
+ my %params = _hashify(@slurp);
+ my $name_e = _H($name);
+ my $seq = _tag_id();
+ my $datefmt = apply {
+ s/d+/\%d/gi;
+ s/m+/\%m/gi;
+ s/y+/\%Y/gi;
+ } $::myconfig{"dateformat"};
+
+ $params{cal_align} ||= 'BR';
+
+ $self->input_tag($name, $value,
+ id => $name_e,
+ size => 11,
+ title => _H($::myconfig{dateformat}),
+ onBlur => 'check_right_date_format(this)',
+ %params,
+ ) . ((!$params{no_cal}) ?
+ $self->html_tag('img', undef,
+ src => 'image/calendar.png',
+ id => "trigger$seq",
+ title => _H($::myconfig{dateformat}),
+ %params,
+ ) .
+ $self->javascript(
+ "Calendar.setup({ inputField: '$name_e', ifFormat: '$datefmt', align: '$params{cal_align}', button: 'trigger$seq' });"
+ ) : '');
+}
+
+sub javascript_tag {
+ my $self = shift;
+ my $code = '';
+
+ foreach my $file (@_) {
+ $file .= '.js' unless $file =~ m/\.js$/;
+ $file = "js/${file}" unless $file =~ m|/|;
+
+ $code .= qq|<script type="text/javascript" src="${file}"></script>|;
+ }
+
+ return $code;
+}
+
+sub tabbed {
+ my ($self, $tabs, @slurp) = @_;
+ my %params = _hashify(@slurp);
+ my $id = $params{id} || 'tab_' . _tag_id();
+
+ $params{selected} *= 1;
+
+ die 'L.tabbed needs an arrayred of tabs for first argument'
+ unless ref $tabs eq 'ARRAY';
+
+ my (@header, @blocks);
+ for my $i (0..$#$tabs) {
+ my $tab = $tabs->[$i];
+
+ next if $tab eq '';
+
+ my $selected = $params{selected} == $i;
+ my $tab_id = "__tab_id_$i";
+ push @header, $self->li_tag(
+ $self->link('', $tab->{name}, rel => $tab_id),
+ ($selected ? (class => 'selected') : ())
+ );
+ push @blocks, $self->div_tag($tab->{data},
+ id => $tab_id, class => 'tabcontent');
+ }
+
+ return '' unless @header;
+ return $self->ul_tag(
+ join('', @header), id => $id, class => 'shadetabs'
+ ) .
+ $self->div_tag(
+ join('', @blocks), class => 'tabcontentstyle'
+ ) .
+ $self->javascript(
+ qq|var $id = new ddtabcontent("$id");$id.setpersist(true);| .
+ qq|$id.setselectedClassTarget("link");$id.init();|
+ );
+}
+
+sub tab {
+ my ($self, $name, $src, @slurp) = @_;
+ my %params = _hashify(@slurp);
+
+ $params{method} ||= 'process';
+
+ return () if defined $params{if} && !$params{if};
+
+ my $data;
+ if ($params{method} eq 'raw') {
+ $data = $src;
+ } elsif ($params{method} eq 'process') {
+ $data = $self->_context->process($src, %{ $params{args} || {} });
+ } else {
+ die "unknown tag method '$params{method}'";
+ }
+
+ return () unless $data;
+
+ return +{ name => $name, data => $data };
+}
+
+sub areainput_tag {
+ my ($self, $name, $value, @slurp) = @_;
+ my %attributes = _hashify(@slurp);
+
+ my $rows = delete $attributes{rows} || 1;
+ my $min = delete $attributes{min_rows} || 1;
+
+ return $rows > 1
+ ? $self->textarea_tag($name, $value, %attributes, rows => max $rows, $min)
+ : $self->input_tag($name, $value, %attributes);
+}
+
+sub multiselect2side {
+ my ($self, $id, @slurp) = @_;
+ my %params = _hashify(@slurp);
+
+ $params{labelsx} = "\"" . _J($params{labelsx} || $::locale->text('Available')) . "\"";
+ $params{labeldx} = "\"" . _J($params{labeldx} || $::locale->text('Selected')) . "\"";
+ $params{moveOptions} = 'false';
+
+ my $vars = join(', ', map { "${_}: " . $params{$_} } keys %params);
+ my $code = <<EOCODE;
+<script type="text/javascript">
+ \$().ready(function() {
+ \$('#${id}').multiselect2side({ ${vars} });
+ });
+</script>
+EOCODE
+
+ return $code;
+}
+
+sub dump {
+ my $self = shift;
+ require Data::Dumper;
+ return '<pre>' . Data::Dumper::Dumper(@_) . '</pre>';
+}
+