SL:Webdav:File.pm->store: ungeänderte Dokumente nicht doppelt speichern.
[kivitendo-erp.git] / SL / Presenter / MaterialComponents.pm
index db92562..30123b7 100644 (file)
@@ -3,13 +3,21 @@ package SL::Presenter::MaterialComponents;
 use strict;
 
 use SL::HTML::Restrict;
+use SL::MoreCommon qw(listify);
 use SL::Presenter::EscapedText qw(escape);
 use SL::Presenter::Tag qw(html_tag);
 use Scalar::Util qw(blessed);
+use List::UtilsBy qw(partition_by);
 
 use Exporter qw(import);
 our @EXPORT_OK = qw(
   button_tag
+  input_tag
+  date_tag
+  submit_tag
+  icon
+  select_tag
+  checkbox_tag
 );
 our %EXPORT_TAGS = (ALL => \@EXPORT_OK);
 
@@ -27,6 +35,7 @@ use constant MEDIUM          => 'medium';
 use constant SMALL           => 'small';
 use constant TINY            => 'tiny';
 use constant INPUT_FIELD     => 'input-field';
+use constant DATEPICKER      => 'datepicker';
 
 use constant WAVES_EFFECT    => 'waves-effect';
 use constant WAVES_LIGHT     => 'waves-light';
@@ -48,6 +57,13 @@ my %optional_classes = (
     small  => SMALL,
     tiny   => TINY,
   },
+  size => {
+    map { $_ => $_ }
+      qw(col row),
+      (map { "s$_" } 1..12),
+      (map { "m$_" } 1..12),
+      (map { "l$_" } 1..12),
+  },
 );
 
 use Carp;
@@ -94,6 +110,17 @@ sub _extract_attribute_classes {
   @classes;
 }
 
+# used to extract material classes that are passed directly as classes
+sub _extract_classes {
+  my ($attributes, $type) = @_;
+
+  my @classes = map { split / / } listify($attributes->{class});
+  my %classes = partition_by { !!$optional_classes{$type}{$_} } @classes;
+
+  $attributes->{class} = $classes{''};
+  $classes{1};
+}
+
 sub _set_id_attribute {
   my ($attributes, $name, $unique) = @_;
 
@@ -185,7 +212,7 @@ sub input_tag {
 
   _set_id_attribute(\%attributes, $attributes{name});
 
-  my $class = delete %attributes{class};
+  my $class = delete $attributes{class};
   my $icon  = $attributes{icon}
     ? icon(delete $attributes{icon}, class => 'prefix')
     : '';
@@ -204,7 +231,80 @@ sub input_tag {
   );
 }
 
+sub date_tag {
+  my ($name, $value, %attributes) = @_;
+
+  _set_id_attribute(\%attributes, $name);
+
+  my $icon  = $attributes{icon}
+    ? icon(delete $attributes{icon}, class => 'prefix')
+    : '';
+
+  my $label = $attributes{label}
+    ? html_tag('label', delete $attributes{label}, for => $attributes{id})
+    : '';
+
+  $attributes{type} = 'text'; # required for materialize
+
+  my @onchange = $attributes{onchange} ? (onChange => delete $attributes{onchange}) : ();
+  my @classes  = (delete $attributes{class});
+
+  $::request->layout->add_javascripts('kivi.Validator.js');
+  $::request->presenter->need_reinit_widgets($attributes{id});
+
+  $attributes{'data-validate'} = join(' ', "date", grep { $_ } (delete $attributes{'data-validate'}));
+
+  html_tag('div',
+    $icon .
+    html_tag('input',
+      blessed($value) ? $value->to_lxoffice : $value,
+      size   => 11, type => 'text', name => $name,
+      %attributes,
+      class => DATEPICKER, @onchange,
+    ) .
+    $label,
+    class => [ grep $_, @classes, INPUT_FIELD ],
+  );
+}
+
+sub select_tag {
+  my ($name, $collection, %attributes) = @_;
+
+
+  _set_id_attribute(\%attributes, $name);
+  my @size_classes   = _extract_classes(\%attributes, "size");
+
+
+  my $icon  = $attributes{icon}
+    ? icon(delete $attributes{icon}, class => 'prefix')
+    : '';
+
+  my $label = $attributes{label}
+    ? html_tag('label', delete $attributes{label}, for => $attributes{id})
+    : '';
+
+  my $select_html = SL::Presenter::Tag::select_tag($name, $collection, %attributes);
+
+  html_tag('div',
+    $icon . $select_html . $label,
+    class => [ INPUT_FIELD, @size_classes ],
+  );
+}
+
+sub checkbox_tag {
+  my ($name, %attributes) = @_;
 
+  _set_id_attribute(\%attributes, $name);
+
+  my $label = $attributes{label}
+    ? html_tag('span', delete $attributes{label})
+    : '';
+
+  my $checkbox_html = SL::Presenter::Tag::checkbox_tag($name, %attributes);
+
+  html_tag('label',
+    $checkbox_html . $label,
+  );
 }
 
 
@@ -224,6 +324,25 @@ SL::Presenter::MaterialComponents - MaterialCSS Component wrapper
 
 =head1 DESCRIPTION
 
+This is a collection of components in the style of L<SL::Presenter::Tag>
+intended for materialzecss. They should be useable similarly to their original
+versions but be well-behaved for materialize.
+
+They will also recognize some materialize conventions:
+
+=over 4
+
+=item icon>
+
+Most elements can be decorated with an icon by supplying the C<icon> with the name.
+
+=item grid classes
+
+Grid classes like C<s12> or C<m6> can be given as keys with any truish value or
+directly as classes.
+
+=back
+
 =head1 BUGS
 
 Nothing here yet.