L/P.select_tag: Unterstützung für Text-Filter
authorMoritz Bunkus <m.bunkus@linet.de>
Mon, 16 Nov 2020 14:16:19 +0000 (15:16 +0100)
committerMoritz Bunkus <m.bunkus@linet.de>
Mon, 16 Nov 2020 16:17:59 +0000 (17:17 +0100)
Gedacht für Selects mit size="123"-Attribut, die also als Liste und
nicht als Combobox gerendert werden.

Es wird direkt oberhalb der Select eine Text-Eingabezeile angezeigt,
die als dynamischer Filter für die Optionen verwendet wird. Bei jeder
Änderung (keyup) werden nur noch diejenigen Einträge in der Select
angezeigt, in deren Text der Suchfilter-Begriff irgendwo
vorkommt (ohne Berücksichtigung von Groß-/Kleinschreibung).

• with_filter=1 schaltet den Filter an
• filter_placeholder=LxERP.t8("Placeholder text") gibt einen
  Platzhalter-Text an

SL/Presenter/Tag.pm
css/kivitendo/main.css
css/lx-office-erp/main.css
image/glass14x14.png [new file with mode: 0644]
js/kivi.js

index 5b261e6..2b45d97 100644 (file)
@@ -113,6 +113,8 @@ sub select_tag {
 
   $collection         = [] if defined($collection) && !ref($collection) && ($collection eq '');
 
+  my $with_filter     = delete($attributes{with_filter});
+  my $fil_placeholder = delete($attributes{filter_placeholder});
   my $value_key       = delete($attributes{value_key})   || 'id';
   my $title_key       = delete($attributes{title_key})   || $value_key;
   my $default_key     = delete($attributes{default_key}) || 'selected';
@@ -208,7 +210,28 @@ sub select_tag {
     } @{ $collection };
   }
 
-  html_tag('select', $code, %attributes, name => $name);
+  my $select_html = html_tag('select', $code, %attributes, name => $name);
+
+  if ($with_filter) {
+    my $input_style;
+
+    if (($attributes{style} // '') =~ m{width: *(\d+) *px}i) {
+      $input_style = "width: " . ($1 - 22) . "px";
+    }
+
+    my $input_html = html_tag(
+      'input', undef,
+      autocomplete     => 'off',
+      type             => 'text',
+      id               => $attributes{id} . '_filter',
+      'data-select-id' => $attributes{id},
+      (placeholder     => $fil_placeholder) x !!$fil_placeholder,
+      (style           => $input_style)     x !!$input_style,
+    );
+    $select_html = html_tag('div', $input_html . $select_html, class => "filtered_select");
+  }
+
+  return $select_html;
 }
 
 sub checkbox_tag {
index 0c22493..563bda9 100644 (file)
@@ -614,3 +614,25 @@ body > div.admin {
 .cke_button {
   padding: 0px; 6px !important;
 }
+
+/* selects with text filters */
+div.filtered_select input, div.filtered_select select {
+  display: block;
+}
+
+div.filtered_select input {
+  background-image: url(../../image/glass14x14.png);
+  background-repeat: no-repeat;
+  background-position: 2px 2px;
+  border-radius: 0px;
+  border: solid #a0a0a0 1px;
+  border-bottom: none;
+  padding: 0px;
+  padding-left: 20px;
+  margin: 0;
+  width: 500px;
+}
+
+div.filtered_select select {
+  width: 522px;
+}
index a2a4ad0..36fe035 100644 (file)
@@ -611,3 +611,25 @@ div.layout-actionbar .layout-actionbar-default-action {
 .cke_button {
   padding: 0px; 6px !important;
 }
+
+/* selects with text filters */
+div.filtered_select input, div.filtered_select select {
+  display: block;
+}
+
+div.filtered_select > input {
+  background-image: url(../../image/glass14x14.png);
+  background-repeat: no-repeat;
+  background-position: 2px 2px;
+  border-radius: 0px;
+  border: solid #a0a0a0 1px;
+  border-bottom: none;
+  padding: 0px;
+  padding-left: 20px;
+  margin: 0;
+  width: 500px;
+}
+
+div.filtered_select select {
+  width: 522px;
+}
diff --git a/image/glass14x14.png b/image/glass14x14.png
new file mode 100644 (file)
index 0000000..e6c9d1b
Binary files /dev/null and b/image/glass14x14.png differ
index a76ad8a..b2b39e1 100644 (file)
@@ -350,6 +350,19 @@ namespace("kivi", function(ns) {
       editor.on('instanceReady', function() { ns.focus_ckeditor($e); });
   };
 
+  ns.filter_select = function() {
+    var $input  = $(this);
+    var $select = $('#' + $input.data('select-id'));
+    var filter  = $input.val().toLocaleLowerCase();
+
+    $select.find('option').each(function() {
+      if ($(this).text().toLocaleLowerCase().indexOf(filter) != -1)
+        $(this).show();
+      else
+        $(this).hide();
+    });
+  };
+
   ns.reinit_widgets = function() {
     ns.run_once_for('.datepicker', 'datepicker', function(elt) {
       $(elt).datepicker();
@@ -369,6 +382,9 @@ namespace("kivi", function(ns) {
         kivi.ChartPicker($(elt));
       });
 
+    ns.run_once_for('div.filtered_select input', 'filtered_select', function(elt) {
+      $(elt).bind('change keyup', ns.filter_select);
+    });
 
     var func = kivi.get_function_by_name('local_reinit_widgets');
     if (func)