+ 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"};
+
+ my $cal_align = delete $params{cal_align} || 'BR';
+ my $onchange = delete $params{onchange};
+ my $str_value = blessed $value ? $value->to_lxoffice : $value;
+
+ $self->input_tag($name, $str_value,
+ id => $name_e,
+ size => 11,
+ title => _H($::myconfig{dateformat}),
+ onBlur => 'check_right_date_format(this)',
+ ($onchange ? (
+ onChange => $onchange,
+ ) : ()),
+ %params,
+ ) . ((!$params{no_cal} && !$params{readonly}) ?
+ $self->html_tag('img', undef,
+ src => 'image/calendar.png',
+ alt => $::locale->text('Calendar'),
+ id => "trigger$seq",
+ title => _H($::myconfig{dateformat}),
+ %params,
+ ) .
+ $self->javascript(
+ "Calendar.setup({ inputField: '$name_e', ifFormat: '$datefmt', align: '$cal_align', button: 'trigger$seq' });"
+ ) : '');
+}
+
+sub customer_picker {
+ my ($self, $name, $value, %params) = @_;
+ my $name_e = _H($name);
+
+ $self->hidden_tag($name, (ref $value && $value->can('id')) ? $value->id : '') .
+ $self->input_tag("$name_e\_name", (ref $value && $value->can('name')) ? $value->name : '', %params) .
+ $self->javascript(<<JS);
+function autocomplete_customer (selector, column) {
+ \$(function(){ \$(selector).autocomplete({
+ source: function(req, rsp) {
+ \$.ajax({
+ url: 'controller.pl?action=Customer/ajax_autocomplete',
+ dataType: "json",
+ data: {
+ column: column,
+ term: req.term,
+ current: function() { \$('#$name_e').val() },
+ obsolete: 0,
+ },
+ success: function (data){ rsp(data) }
+ });
+ },
+ limit: 20,
+ delay: 50,
+ select: function(event, ui) {
+ \$('#$name_e').val(ui.item.id);
+ \$('#$name_e\_name').val(ui.item.name);
+ },
+ })});
+}
+autocomplete_customer('#$name_e\_name');
+JS
+}
+
+# simple version with select_tag
+sub vendor_selector {
+ my ($self, $name, $value, %params) = @_;
+
+ my $actual_vendor_id = (defined $::form->{"$name"})? ((ref $::form->{"$name"}) ? $::form->{"$name"}->id : $::form->{"$name"}) :
+ (ref $value && $value->can('id')) ? $value->id : '';
+
+ return $self->select_tag($name, SL::DB::Manager::Vendor->get_all(),
+ default => $actual_vendor_id,
+ title_sub => sub { $_[0]->vendornumber . " : " . $_[0]->name },
+ 'with_empty' => 1,
+ %params);
+}
+
+
+# simple version with select_tag
+sub part_selector {
+ my ($self, $name, $value, %params) = @_;
+
+ my $actual_part_id = (defined $::form->{"$name"})? ((ref $::form->{"$name"})? $::form->{"$name"}->id : $::form->{"$name"}) :
+ (ref $value && $value->can('id')) ? $value->id : '';
+
+ return $self->select_tag($name, SL::DB::Manager::Part->get_all(),
+ default => $actual_part_id,
+ title_sub => sub { $_[0]->partnumber . " : " . $_[0]->description },
+ with_empty => 1,
+ %params);
+}
+
+
+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, $cols);
+ my $min = delete $attributes{min_rows} || 1;
+
+ if (exists $attributes{cols}) {
+ $cols = delete $attributes{cols};
+ $rows = $::form->numtextrows($value, $cols);
+ } else {
+ $rows = delete $attributes{rows} || 1;