Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision 78fedd6a

Von Tamino Steinert vor fast 2 Jahren hinzugefügt

  • ID 78fedd6a7801e3cdcc2eef999ab4ad92a6530b8c
  • Vorgänger 0fbbccdf
  • Nachfolger d71c833a

multi_level_select_tag hinzugefüht

Dieser Tag dient um aus verschachtelten Objekten mehrere
hierarchische select tags zu erzeugen

Unterschiede anzeigen:

SL/Presenter/Tag.pm
11 11
  html_tag input_tag hidden_tag javascript man_days_tag name_to_id select_tag
12 12
  checkbox_tag button_tag submit_tag ajax_submit_tag input_number_tag
13 13
  stringify_attributes textarea_tag link_tag date_tag
14
  div_tag radio_button_tag img_tag);
14
  div_tag radio_button_tag img_tag multi_level_select_tag);
15 15
our %EXPORT_TAGS = (ALL => \@EXPORT_OK);
16 16

  
17 17
use Carp;
......
244 244
  return $select_html;
245 245
}
246 246

  
247
sub multi_level_select_tag {
248
  my ($name, $collection, $levels, %attributes) = @_;
249

  
250
  _set_id_attribute(\%attributes, $name);
251
  my $id = $attributes{id};
252

  
253
  $collection = [] if defined($collection) && !ref($collection) && ($collection eq '');
254

  
255
  my $surround_tag = delete(%attributes{surround_tag});
256

  
257
  my $multi_level_select_tag = "";
258
  my %level_keys = ();
259

  
260
  my $base_attributes  = delete($attributes{"level_1"}) || {};
261

  
262
  my $base_name        = delete($base_attributes->{name});
263
  my $base_value_key   = $base_attributes->{value_key} || 'id';
264
  my $base_title_key   = $base_attributes->{title_key} || $base_value_key;
265
  my $base_default     = $base_attributes->{default};
266
  my $base_default_key = $base_attributes->{default_key};
267

  
268
  $level_keys{1} = {
269
    "value" => $base_value_key,
270
    "title" => $base_title_key,
271
  };
272
  $base_attributes->{id} = $id . "_level_1";
273
  $base_attributes->{onchange} = $id . "_on_chanche_level_1(this)";
274
  my $current_select = select_tag(
275
    $base_name,
276
    $collection,
277
    %{$base_attributes}
278
  );
279
  if ($surround_tag) {
280
    $multi_level_select_tag .= html_tag($surround_tag, $current_select);
281
  } else {
282
    $multi_level_select_tag .= $current_select;
283
  }
284

  
285
  my $last_object;
286
  if ($base_default) {
287
    ($last_object) = grep { $_->{$base_value_key} eq $base_default } @{$collection};
288
  } elsif ($base_default_key) {
289
    ($last_object) = grep { $_->{$base_default_key} } @{$collection};
290
  } else {
291
    $last_object = $collection->[0];
292
  }
293
  foreach my $level (2 .. $levels) {
294
    my $current_attributes = delete($attributes{"level_$level"}) || {};
295

  
296
    my $current_name          = delete($current_attributes->{name});
297
    my $current_value_key     = $current_attributes->{value_key} || 'id';
298
    my $current_title_key     = $current_attributes->{title_key} || $current_value_key;
299
    my $current_default       = $current_attributes->{default};
300
    my $current_default_key   = $current_attributes->{default_key};
301
    my $current_object_key    = delete($current_attributes->{object_key});
302
    die "need object_key in level_$level in multi_level_select_tag" unless $current_object_key;
303

  
304
    $level_keys{$level} = {
305
      "value"  => $current_value_key,
306
      "title"  => $current_title_key,
307
      "object" => $current_object_key,
308
    };
309

  
310
    $current_attributes->{id} = $id . "_level_$level";
311
    $current_attributes->{onchange} = $id . "_on_chanche_level_${level}(this)" unless $level eq $levels;
312
    my $current_collection = $last_object->{$current_object_key};
313
    my $current_select = select_tag(
314
      $current_name,
315
      $current_collection,
316
      %{$current_attributes}
317
    );
318
    if ($surround_tag) {
319
      $multi_level_select_tag .= html_tag($surround_tag, $current_select);
320
    } else {
321
      $multi_level_select_tag .= $current_select;
322
    }
323

  
324
    if ($current_default) {
325
      ($last_object) = grep { $_->{$current_value_key} eq $current_default } @{$current_collection};
326
    } elsif ($current_default_key) {
327
      ($last_object) = grep { $_->{$current_default_key} } @{$current_collection};
328
    } else {
329
      $last_object = $current_collection->[0];
330
    }
331
  }
332

  
333
  my $code = "";
334

  
335
  if ($levels > 1) {
336
    my $js_option_string = ""; # js hash map (level->value->{[value: 1, title: 'foo'], ...})
337

  
338
    my @current_collections = @{$collection};
339
    my @next_collections = ();
340
    foreach my $level (1 .. ($levels - 1)) {
341
      $js_option_string .= "'${level}': {";
342
      foreach my $option (@current_collections) {
343
        $js_option_string .= "'" . $option->{$level_keys{$level}{value}} . "': [";
344
        map { $js_option_string .= "{ value: '" . $_->{$level_keys{$level + 1}{value}}
345
                                .  "', title: '" . $_->{$level_keys{$level + 1}{title}}
346
                                .  "'}," } @{$option->{$level_keys{$level + 1}{object}}};
347
        $js_option_string .= "],";
348
        push @next_collections, @{$option->{$level_keys{$level + 1}{object}}};
349
      }
350
      $js_option_string .= "},";
351
      @current_collections = @next_collections;
352
      @next_collections = ();
353
    }
354

  
355
    $code .= javascript( qq|
356
      var ${id}_options = {
357
        $js_option_string
358
      };
359
    |);
360
    foreach my $level (1 .. ($levels - 1)) {
361
      my $next_level = $level + 1;
362
      $code .= javascript( qq|
363
      function ${id}_on_chanche_level_${level}(select_${level}) {
364
        var value = select_${level}.value;
365
        for (var i = ${next_level}; i < $levels + 1; i++) {
366
          var id = '${id}_level_' + i;
367
          var select_i = document.getElementById(id);
368
          while (select_i.options.length) {
369
            select_i.options.remove(0);
370
          }
371
          select_i.disabled = true;
372
        }
373
        var id_${next_level} = '${id}_level_${next_level}';
374
        var select_${next_level} = document.getElementById(id_${next_level});
375
        for (var i=0; i < ${id}_options[${level}][value].length; i++) {
376
          var option = new Option(${id}_options[${level}][value][i].title, ${id}_options[${level}][value][i].value)
377
          select_${next_level}.options.add(option);
378
        }
379
        select_${next_level}.disabled = false;
380
        select_${next_level}.selectedIndex = -1;
381
      }
382
      |);
383
    }
384
  }
385

  
386
  return $multi_level_select_tag . $code;
387
}
388

  
247 389
sub checkbox_tag {
248 390
  my ($name, %attributes) = @_;
249 391

  
......
706 848
  # Later in the template:
707 849
  [% L.select_tag('the_selection', COLLECTION, with_optgroups=1, title_key='name') %]
708 850

  
851
=item C<multi_level_select_tag $name, \@collection, $levels, %attributes>
852

  
853
Creates multiple HTML 'select' tags, one for each level. Each tag ist created
854
with C<select_tag>.
855

  
856
The parameters for C<select_tag> are created from the values stored in the
857
corrosponding level attributes. The attributes for each level are in
858
C<%attributes{level_i}>, starting with 1.
859

  
860
The following are used directly from each level:
861

  
862
=over 12
863

  
864
=item I<name> is deleted from level attributes.
865
The I<name> is used for the for the name of the 'select' tag.
866

  
867
=item I<object_key> is deleted from level attriutes.
868
The I<object_key> is used to get the level objects for the current level
869
from the object of the previous level, this is intended for the use of RSDB object.
870
Each level attributes musst contain I<object_key>, except level_1.
871

  
872
=item I<id> is overridden.
873
The I<id> is set to a specific value for use in JavaScript.
874

  
875
=item I<value_key> names the key for the value of level object. Defaults to
876
C<id>.
877

  
878
=item I<title_key> names the key for the titel of level object. Defaults to
879
C<$attributes{value_key}>.
880

  
881
=item I<default> is used to find the default level object.
882

  
883
=tiem I<default_key> names the key for the default feld of level object. Is
884
ignored if I<default> is set.
885

  
886
=back
887

  
888

  
889
<\@collection> is used for the level object of level 1. The objects of the next
890
level are taken from the previous level via the <object_key>. On each level the
891
objects must be a hash reference or a blessed reference.
892

  
893
A I<surround_tag> can be specified, which generates a C<html_tag> with the
894
corrosponding tag around evey C<select_tag>.
895

  
896
Example:
897

  
898
  # First in a controller:
899
    my @collection = (
900
    { 'description' => 'foo_1', 'id' => '1',
901
      'key_1' => [
902
        { 'id' => 3, 'description' => "bar_1",
903
          'key_2' => [
904
            { 'id' => 1, 'value' => "foobar_1", },
905
            { 'id' => 2, 'value' => "foobar_2", },
906
          ], },
907
        { 'id' => 4, 'description' => "bar_2",
908
        'key_2' => [], },
909
      ], },
910
    { 'description' => 'foo_2', 'id' => '2',
911
      'key_1' => [
912
        { 'id' => 1, 'description' => "bar_1",
913
          'key_2' => [
914
            { 'id' => 3, 'value' => "foobar_3", },
915
            { 'id' => 4, 'value' => "foobar_4", },
916
          ], },
917
        { 'id' => 2, 'description' => "bar_2",
918
          'stock' => [
919
            { 'id' => 5, 'value' => "test_5", },
920
          ], },
921
      ], },
922
  );
923

  
924
  # Later in the template (in a table):
925
  [% L.multi_level_select_tag("multi_select_foo_bar_foobar", COLLECTION, 3,
926
      surround_tag="td",
927
      level_1={
928
        name="foo.id",
929
        value_key="id",
930
        title_key="description",
931
        default="2",
932
      },
933
      level_2={
934
        object_key="key_1",
935
        name="bar.id",
936
        value_key="id",
937
        title_key="description",
938
        default="1",
939
      },
940
      level_3={
941
        object_key="key_2",
942
        name="foobar.id",
943
        value_key="id",
944
        title_key="value",
945
        default="4",
946
      },
947
  ) %]
948

  
709 949
=back
710 950

  
711 951
=head1 BUGS
SL/Template/Plugin/L.pm
87 87
sub img_tag                  { return _call_presenter('img_tag',                  @_); }
88 88
sub restricted_html          { return _call_presenter('restricted_html',          @_); }
89 89
sub stripped_html            { return _call_presenter('stripped_html',            @_); }
90
sub multi_level_select_tag   { return _call_presenter('multi_level_select_tag',   @_); }
90 91

  
91 92
sub _set_id_attribute {
92 93
  my ($attributes, $name, $unique) = @_;

Auch abrufbar als: Unified diff