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.codemirror;
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.context.FacesContext;
30 import javax.faces.context.ResponseWriter;
31 import javax.faces.convert.Converter;
32 import javax.faces.event.PhaseId;
33
34 import org.primefaces.expression.SearchExpressionUtils;
35 import org.primefaces.extensions.event.CompleteEvent;
36 import org.primefaces.extensions.util.Attrs;
37 import org.primefaces.renderkit.InputRenderer;
38 import org.primefaces.util.ComponentUtils;
39 import org.primefaces.util.HTML;
40 import org.primefaces.util.WidgetBuilder;
41
42
43
44
45
46
47
48
49 public class CodeMirrorRenderer extends InputRenderer {
50
51 @Override
52 public void decode(final FacesContext facesContext, final UIComponent component) {
53 final CodeMirror codeMirror = (CodeMirror) component;
54
55 if (!shouldDecode(codeMirror)) {
56 return;
57 }
58
59
60 final String clientId = codeMirror.getClientId(facesContext);
61 final Map<String, String> params = facesContext.getExternalContext().getRequestParameterMap();
62 if (params.containsKey(clientId)) {
63 codeMirror.setSubmittedValue(params.get(clientId));
64 }
65
66
67 decodeBehaviors(facesContext, component);
68
69
70 final String token = params.get(clientId + "_token");
71 if (token != null) {
72 final String context = params.get(clientId + "_context");
73 final int line = Integer.parseInt(params.get(clientId + "_line"));
74 final int column = Integer.parseInt(params.get(clientId + "_column"));
75
76 final CompleteEvent autoCompleteEvent = new CompleteEvent(
77 codeMirror, token, context, line, column);
78 autoCompleteEvent.setPhaseId(PhaseId.APPLY_REQUEST_VALUES);
79 codeMirror.queueEvent(autoCompleteEvent);
80 }
81 }
82
83 @Override
84 public void encodeEnd(final FacesContext context, final UIComponent component) throws IOException {
85 final CodeMirror codeMirror = (CodeMirror) component;
86
87 final Map<String, String> params = context.getExternalContext().getRequestParameterMap();
88 final String token = params.get(codeMirror.getClientId(context) + "_token");
89
90 if (token != null) {
91 encodeSuggestions(context, codeMirror, codeMirror.getSuggestions());
92 }
93 else {
94 encodeMarkup(context, codeMirror);
95 encodeScript(context, codeMirror);
96 }
97 }
98
99 protected void encodeMarkup(final FacesContext context, final CodeMirror codeMirror) throws IOException {
100 final ResponseWriter writer = context.getResponseWriter();
101 final String clientId = codeMirror.getClientId(context);
102
103 writer.startElement("textarea", codeMirror);
104 writer.writeAttribute("id", clientId, null);
105 writer.writeAttribute("name", clientId, null);
106
107 renderAccessibilityAttributes(context, codeMirror);
108 renderPassThruAttributes(context, codeMirror, HTML.TEXTAREA_ATTRS_WITHOUT_EVENTS);
109 renderDomEvents(context, codeMirror, HTML.INPUT_TEXT_EVENTS);
110 renderValidationMetadata(context, codeMirror);
111
112 final String valueToRender = ComponentUtils.getValueToRender(context, codeMirror);
113 if (valueToRender != null) {
114 if (codeMirror.isEscape()) {
115 writer.writeText(valueToRender, null);
116 }
117 else {
118 writer.write(valueToRender);
119 }
120 }
121
122 writer.endElement("textarea");
123 }
124
125 protected void encodeScript(final FacesContext context, final CodeMirror codeMirror) throws IOException {
126 final WidgetBuilder wb = getWidgetBuilder(context);
127 wb.init("ExtCodeMirror", codeMirror);
128 wb.attr("theme", codeMirror.getTheme())
129 .attr("mode", codeMirror.getMode())
130 .attr("indentUnit", codeMirror.getIndentUnit())
131 .attr("smartIndent", codeMirror.isSmartIndent())
132 .attr("tabSize", codeMirror.getTabSize())
133 .attr("indentWithTabs", codeMirror.isIndentWithTabs())
134 .attr("electricChars", codeMirror.isElectricChars())
135 .attr("keyMap", codeMirror.getKeyMap())
136 .attr("lineWrapping", codeMirror.isLineWrapping())
137 .attr("lineNumbers", codeMirror.isLineNumbers())
138 .attr("firstLineNumber", codeMirror.getFirstLineNumber())
139 .attr("gutter", codeMirror.isGutter())
140 .attr("fixedGutter", codeMirror.isFixedGutter())
141 .attr("readOnly", codeMirror.isReadonly())
142 .attr("matchBrackets", codeMirror.isMatchBrackets())
143 .attr("workTime", codeMirror.getWorkTime())
144 .attr("workDelay", codeMirror.getWorkDelay())
145 .attr("pollInterval", codeMirror.getPollInterval())
146 .attr(Attrs.TABINDEX, codeMirror.getTabindex())
147 .attr("undoDepth", codeMirror.getUndoDepth());
148
149 if (codeMirror.getExtraKeys() != null) {
150 wb.append(",extraKeys:" + codeMirror.getExtraKeys());
151 }
152 if (!codeMirror.isGlobal()) {
153 wb.attr("global", false);
154 }
155 if (codeMirror.isAsync()) {
156 wb.attr("async", true);
157 }
158 if (codeMirror.getProcess() != null) {
159 wb.attr("process", SearchExpressionUtils.resolveClientIdsForClientSide(context, codeMirror, codeMirror.getProcess()));
160 }
161 if (codeMirror.getOnstart() != null) {
162 wb.callback("onstart", "function(request)", codeMirror.getOnstart());
163 }
164 if (codeMirror.getOncomplete() != null) {
165 wb.callback("oncomplete", "function(xhr, status, args)", codeMirror.getOncomplete());
166 }
167 if (codeMirror.getOnsuccess() != null) {
168 wb.callback("onsuccess", "function(data, status, xhr)", codeMirror.getOnsuccess());
169 }
170 if (codeMirror.getOnerror() != null) {
171 wb.callback("onerror", "function(xhr, status, error)", codeMirror.getOnerror());
172 }
173
174 encodeClientBehaviors(context, codeMirror);
175
176 wb.finish();
177 }
178
179 @Override
180 public Object getConvertedValue(final FacesContext context, final UIComponent component, final Object submittedValue) {
181 final CodeMirror codeMirror = (CodeMirror) component;
182 final String value = (String) submittedValue;
183 final Converter<?> converter = ComponentUtils.getConverter(context, component);
184
185 if (converter != null) {
186 return converter.getAsObject(context, codeMirror, value);
187 }
188
189 return value;
190 }
191
192 protected void encodeSuggestions(final FacesContext context, final CodeMirror codeMirror, final List<String> suggestions) throws IOException {
193 final ResponseWriter writer = context.getResponseWriter();
194
195 writer.startElement("ul", codeMirror);
196
197 for (final String suggestion : suggestions) {
198 writer.startElement("li", null);
199
200 if (codeMirror.isEscapeSuggestions()) {
201 writer.writeText(suggestion, null);
202 }
203 else {
204 writer.write(suggestion);
205 }
206
207 writer.endElement("li");
208 }
209
210 writer.endElement("ul");
211 }
212 }