Presenter: Array Tags mit eindeutigen IDs rendern
[kivitendo-erp.git] / SL / Presenter / Tag.pm
index 29b57ad..e5690e7 100644 (file)
@@ -19,6 +19,15 @@ sub _call_on {
   return $object->$method(@params);
 }
 
+{ # This will give you an id for identifying html tags and such.
+  # It's guaranteed to be unique unless you exceed 10 mio calls per request.
+  # Do not use these id's to store information across requests.
+my $_id_sequence = int rand 1e7;
+sub _id {
+  return ( $_id_sequence = ($_id_sequence + 1) % 1e7 );
+}
+}
+
 
 sub stringify_attributes {
   my ($self, %params) = @_;
@@ -45,7 +54,7 @@ sub html_tag {
 sub input_tag {
   my ($self, $name, $value, %attributes) = @_;
 
-  $attributes{id}   ||= $self->name_to_id($name);
+  _set_id_attribute(\%attributes, $name);
   $attributes{type} ||= 'text';
 
   return $self->html_tag('input', undef, %attributes, name => $name, value => $value);
@@ -68,6 +77,7 @@ sub man_days_tag {
 sub name_to_id {
   my ($self, $name) = @_;
 
+  $name =~ s/\[\+?\]/ _id() /ge; # give constructs with [] or [+] unique ids
   $name =~ s/[^\w_]/_/g;
   $name =~ s/_+/_/g;
 
@@ -77,7 +87,7 @@ sub name_to_id {
 sub select_tag {
   my ($self, $name, $collection, %attributes) = @_;
 
-  $attributes{id}   ||= $self->name_to_id($name);
+  _set_id_attribute(\%attributes, $name);
 
   my $value_key       = delete($attributes{value_key})   || 'id';
   my $title_key       = delete($attributes{title_key})   || $value_key;
@@ -158,7 +168,7 @@ sub select_tag {
   };
 
   my $code  = '';
-  $code    .= $self->html_tag('option', $self->escape($empty_title || '')) if $with_empty;
+  $code    .= $self->html_tag('option', $self->escape($empty_title || ''), value => '') if $with_empty;
 
   if (!$with_optgroups) {
     $code .= $list_to_code->($collection);
@@ -173,6 +183,14 @@ sub select_tag {
   return $self->html_tag('select', $code, %attributes, name => $name);
 }
 
+sub _set_id_attribute {
+  my ($attributes, $name) = @_;
+
+  $attributes->{id} = name_to_id(undef, $name) if !delete($attributes->{no_id}) && !$attributes->{id};
+
+  return %{ $attributes };
+}
+
 1;
 __END__
 
@@ -205,6 +223,10 @@ Usage from a template:
 A module modeled a bit after Rails' ActionView helpers. Several small
 functions that create HTML tags from various kinds of data sources.
 
+The C<id> attribute is usually calculated automatically. This can be
+overridden by either specifying an C<id> attribute or by setting
+C<no_id> to trueish.
+
 =head1 FUNCTIONS
 
 =head2 LOW-LEVEL FUNCTIONS