View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.syncope.client.ui.commons.markup.html.form;
20  
21  import de.agilecoders.wicket.core.markup.html.bootstrap.components.TooltipConfig;
22  import java.util.Iterator;
23  import java.util.List;
24  import java.util.regex.Pattern;
25  import org.apache.syncope.client.ui.commons.Constants;
26  import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
27  import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAutoCompleteBehavior;
28  import org.apache.wicket.Component;
29  import org.apache.wicket.ajax.AjaxRequestTarget;
30  import org.apache.wicket.extensions.ajax.markup.html.autocomplete.AutoCompleteBehavior;
31  import org.apache.wicket.extensions.ajax.markup.html.autocomplete.AutoCompleteSettings;
32  import org.apache.wicket.extensions.ajax.markup.html.autocomplete.AutoCompleteTextField;
33  import org.apache.wicket.extensions.ajax.markup.html.autocomplete.IAutoCompleteRenderer;
34  import org.apache.wicket.model.IModel;
35  import org.apache.wicket.model.ResourceModel;
36  import org.apache.wicket.validation.IValidator;
37  
38  public class AjaxTextFieldPanel extends FieldPanel<String> implements Cloneable {
39  
40      private static final long serialVersionUID = 238940918106696068L;
41  
42      private Component questionMarkJexlHelp;
43  
44      private List<String> choices = List.of();
45  
46      public AjaxTextFieldPanel(final String id, final String name, final IModel<String> model) {
47          this(id, name, model, true);
48      }
49  
50      public AjaxTextFieldPanel(
51              final String id, final String name, final IModel<String> model, final boolean enableOnChange) {
52          super(id, name, model);
53  
54          questionMarkJexlHelp = Constants.getJEXLPopover(this, TooltipConfig.Placement.right);
55          add(questionMarkJexlHelp.setVisible(false));
56  
57          final AutoCompleteSettings settings = new AutoCompleteSettings();
58          settings.setShowCompleteListOnFocusGain(true);
59          settings.setShowListOnEmptyInput(true);
60          settings.setCssClassName("custom-autocomplete-box");
61  
62          field = new AutoCompleteTextField<>("textField", model, settings) {
63  
64              private static final long serialVersionUID = -6648767303091874219L;
65  
66              @Override
67              protected Iterator<String> getChoices(final String input) {
68                  return AjaxTextFieldPanel.this.getChoices(input);
69              }
70  
71              @Override
72              protected AutoCompleteBehavior<String> newAutoCompleteBehavior(
73                  final IAutoCompleteRenderer<String> renderer, final AutoCompleteSettings settings) {
74                  return new IndicatorAutoCompleteBehavior<>(renderer, settings) {
75  
76                      private static final long serialVersionUID = 1070808433195962931L;
77  
78                      @Override
79                      protected Iterator<String> getChoices(final String input) {
80                          return AjaxTextFieldPanel.this.getChoices(input);
81                      }
82                  };
83              }
84          };
85          add(field.setLabel(new ResourceModel(name, name)).setOutputMarkupId(true));
86  
87          if (enableOnChange && !isReadOnly()) {
88              field.add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
89  
90                  private static final long serialVersionUID = -1107858522700306810L;
91  
92                  @Override
93                  protected void onUpdate(final AjaxRequestTarget target) {
94                      // nothing to do
95                  }
96              });
97          }
98      }
99  
100     public void addValidator(final IValidator<? super String> validator) {
101         this.field.add(validator);
102     }
103 
104     public void setChoices(final List<String> choices) {
105         if (choices != null) {
106             this.choices = choices;
107         }
108     }
109 
110     public FieldPanel<String> enableJexlHelp() {
111         questionMarkJexlHelp.setVisible(true);
112         return this;
113     }
114 
115     public FieldPanel<String> enableJexlHelp(final String... jexlExamples) {
116         questionMarkJexlHelp = Constants.getJEXLPopover(this, TooltipConfig.Placement.bottom, jexlExamples);
117         addOrReplace(questionMarkJexlHelp.setVisible(true));
118         return this;
119     }
120 
121     protected Iterator<String> getChoices(final String input) {
122         Pattern pattern = Pattern.compile(".*" + Pattern.quote(input) + ".*", Pattern.CASE_INSENSITIVE);
123         return choices.stream().filter(pattern.asMatchPredicate()).iterator();
124     }
125 
126     @Override
127     public FieldPanel<String> clone() {
128         final AjaxTextFieldPanel panel = (AjaxTextFieldPanel) super.clone();
129         panel.setChoices(choices);
130         return panel;
131     }
132 }