1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.primefaces.extensions.component.fuzzysearch;
23
24 import java.io.IOException;
25 import java.util.List;
26 import java.util.Map;
27
28 import javax.faces.component.UIComponent;
29 import javax.faces.component.UISelectOne;
30 import javax.faces.context.FacesContext;
31 import javax.faces.context.ResponseWriter;
32 import javax.faces.model.SelectItem;
33
34 import org.primefaces.component.inputtext.InputText;
35 import org.primefaces.extensions.util.Attrs;
36 import org.primefaces.renderkit.SelectOneRenderer;
37 import org.primefaces.shaded.json.JSONArray;
38 import org.primefaces.shaded.json.JSONObject;
39 import org.primefaces.util.ComponentUtils;
40 import org.primefaces.util.HTML;
41 import org.primefaces.util.WidgetBuilder;
42
43
44
45
46
47
48
49 public class FuzzySearchRenderer extends SelectOneRenderer {
50
51 private static final String INPUT = "_input";
52
53 @Override
54 public void decode(final FacesContext context, final UIComponent component) {
55 final FuzzySearch fuzzySearch = (FuzzySearch) component;
56 if (!shouldDecode(fuzzySearch)) {
57 return;
58 }
59
60 final String clientId = fuzzySearch.getClientId(context);
61 final Map<String, String> params = context.getExternalContext().getRequestParameterMap();
62 final String submittedValue = params.get(clientId + INPUT);
63
64 if (submittedValue != null) {
65 fuzzySearch.setSubmittedValue(submittedValue);
66 }
67
68 decodeBehaviors(context, fuzzySearch);
69 }
70
71 @Override
72 public void encodeEnd(final FacesContext context, final UIComponent component) throws IOException {
73 final FuzzySearch fuzzySearch = (FuzzySearch) component;
74
75 encodeMarkup(context, fuzzySearch);
76 encodeScript(context, fuzzySearch);
77 }
78
79 protected void encodeMarkup(final FacesContext context, final FuzzySearch fuzzySearch) throws IOException {
80 final ResponseWriter writer = context.getResponseWriter();
81
82 final String clientId = fuzzySearch.getClientId(context);
83 final List<SelectItem> selectItems = getSelectItems(context, fuzzySearch);
84 final int selectItemsSize = selectItems.size();
85 final String style = fuzzySearch.getStyle();
86 final String styleClass = getStyleClassBuilder(context)
87 .add(FuzzySearch.STYLE_CLASS)
88 .add(fuzzySearch.getStyleClass())
89 .add("ui-buttonset-" + selectItemsSize)
90 .add(!fuzzySearch.isValid(), "ui-state-error")
91 .build();
92
93 writer.startElement("div", fuzzySearch);
94 writer.writeAttribute("id", clientId, "id");
95 writer.writeAttribute(Attrs.CLASS, styleClass, "styleClass");
96 if (style != null) {
97 writer.writeAttribute(Attrs.STYLE, style, Attrs.STYLE);
98 }
99
100 writer.startElement("input", fuzzySearch);
101 writer.writeAttribute("id", clientId + INPUT, null);
102 writer.writeAttribute("name", clientId + INPUT, null);
103 writer.writeAttribute("placeholder", fuzzySearch.getPlaceholder(), null);
104 writer.writeAttribute("class", createStyleClass(fuzzySearch, InputText.STYLE_CLASS), "styleClass");
105 renderPassThruAttributes(context, fuzzySearch, HTML.TAB_INDEX);
106 renderDomEvents(context, fuzzySearch, HTML.BLUR_FOCUS_EVENTS);
107 renderAccessibilityAttributes(context, fuzzySearch);
108 renderValidationMetadata(context, fuzzySearch);
109 final String valueToRender = ComponentUtils.getValueToRender(context, fuzzySearch);
110 if (valueToRender != null) {
111 writer.writeAttribute("value", valueToRender, null);
112 }
113 writer.endElement("input");
114
115 writer.startElement("div", fuzzySearch);
116 writer.writeAttribute("id", clientId + "_fuzzysearch-search-results", null);
117
118 if (fuzzySearch.isListItemsAtTheBeginning()) {
119 encodeSelectItems(context, fuzzySearch, selectItems);
120 }
121
122 writer.endElement("div");
123
124 writer.endElement("div");
125 }
126
127 protected void encodeSelectItems(final FacesContext context, final FuzzySearch fuzzySearch, final List<SelectItem> selectItems) throws IOException {
128 for (final SelectItem selectItem : selectItems) {
129 encodeOption(context, fuzzySearch, selectItem);
130 }
131 }
132
133 protected void encodeOption(
134 final FacesContext context, final FuzzySearch fuzzySearch, final SelectItem option) throws IOException {
135
136 final ResponseWriter writer = context.getResponseWriter();
137 final String itemValueAsString = getOptionAsString(context, fuzzySearch, fuzzySearch.getConverter(), option.getValue());
138
139 final String resultStyle = fuzzySearch.getResultStyle();
140 final String resultStyleClass = getStyleClassBuilder(context)
141 .add(FuzzySearch.ITEM_CLASS)
142 .add(fuzzySearch.getResultStyleClass())
143 .build();
144
145
146 writer.startElement("div", null);
147 writer.writeAttribute("class", resultStyleClass, "resultStyleClass");
148 if (resultStyle != null) {
149 writer.writeAttribute(Attrs.STYLE, resultStyle, "resultStyle");
150 }
151 writer.writeAttribute("tabindex", fuzzySearch.getTabindex(), null);
152 if (option.getDescription() != null) {
153 writer.writeAttribute("title", option.getDescription(), null);
154 }
155 writer.writeAttribute("data-item-value", itemValueAsString, null);
156
157 if (option.isEscape()) {
158 writer.writeText(option.getLabel(), "itemLabel");
159 }
160 else {
161 writer.write(option.getLabel());
162 }
163
164 writer.endElement("div");
165 }
166
167 protected void encodeScript(final FacesContext context, final FuzzySearch fuzzySearch) throws IOException {
168 final WidgetBuilder wb = getWidgetBuilder(context);
169
170 final List<SelectItem> selectItems = getSelectItems(context, fuzzySearch);
171 final JSONArray ja = new JSONArray();
172 for (final SelectItem selectItem : selectItems) {
173 ja.put(new JSONObject(selectItem));
174 }
175 final String jsonDatasource = ja.toString();
176
177 wb.init(FuzzySearch.class.getSimpleName(), fuzzySearch)
178 .attr("resultStyle", fuzzySearch.getResultStyle())
179 .attr("resultStyleClass", fuzzySearch.getResultStyleClass())
180 .attr("listItemsAtTheBeginning", fuzzySearch.isListItemsAtTheBeginning())
181 .attr("datasource", jsonDatasource)
182 .attr("unselectable", fuzzySearch.isUnselectable(), true)
183 .attr("highlight", fuzzySearch.isHighlight(), true)
184 .callback("change", "function()", fuzzySearch.getOnchange());
185
186 encodeClientBehaviors(context, fuzzySearch);
187
188 wb.finish();
189 }
190
191 @Override
192 protected String getSubmitParam(final FacesContext context, final UISelectOne selectOne) {
193 return selectOne.getClientId(context);
194 }
195
196 }