1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.primefaces.extensions.component.sheet;
17
18 import java.io.IOException;
19 import java.lang.reflect.Array;
20 import java.util.Collection;
21 import java.util.Iterator;
22 import java.util.List;
23 import java.util.Map;
24
25 import javax.faces.FacesException;
26 import javax.faces.component.UIComponent;
27 import javax.faces.component.behavior.ClientBehavior;
28 import javax.faces.component.behavior.ClientBehaviorContext;
29 import javax.faces.component.behavior.ClientBehaviorHolder;
30 import javax.faces.context.FacesContext;
31 import javax.faces.context.ResponseWriter;
32 import javax.faces.model.SelectItem;
33
34 import org.apache.commons.lang3.StringUtils;
35 import org.primefaces.behavior.ajax.AjaxBehavior;
36 import org.primefaces.extensions.util.JavascriptVarBuilder;
37 import org.primefaces.renderkit.CoreRenderer;
38 import org.primefaces.shaded.json.JSONArray;
39 import org.primefaces.shaded.json.JSONException;
40 import org.primefaces.shaded.json.JSONObject;
41 import org.primefaces.util.ComponentUtils;
42 import org.primefaces.util.Constants;
43 import org.primefaces.util.LangUtils;
44 import org.primefaces.util.WidgetBuilder;
45
46
47
48
49
50
51
52 public class SheetRenderer extends CoreRenderer {
53
54
55
56
57 @Override
58 public void encodeEnd(final FacesContext context, final UIComponent component) throws IOException {
59 final ResponseWriter responseWriter = context.getResponseWriter();
60 final Sheet sheet = (Sheet) component;
61
62
63 sheet.updateColumnMappings();
64
65
66 sheet.sortAndFilter();
67
68
69 encodeMarkup(context, sheet, responseWriter);
70
71
72 encodeScript(context, sheet, responseWriter);
73 }
74
75
76
77
78
79
80
81
82 protected void encodeMarkup(final FacesContext context, final Sheet sheet, final ResponseWriter responseWriter)
83 throws IOException {
84
85
86
87 final String styleClass = sheet.getStyleClass();
88 final String clientId = sheet.getClientId(context);
89 final Integer width = sheet.getWidth();
90 final Integer height = sheet.getHeight();
91 String style = sheet.getStyle();
92
93
94 responseWriter.startElement("div", null);
95 responseWriter.writeAttribute("id", clientId, "id");
96 responseWriter.writeAttribute("name", clientId, "clientId");
97
98
99 String divclass = "ui-handsontable ui-widget";
100 if (styleClass != null) {
101 divclass = divclass + " " + styleClass;
102 }
103 if (!sheet.isValid()) {
104 divclass = divclass + " ui-state-error";
105 }
106
107 responseWriter.writeAttribute("class", divclass, "styleClass");
108 if (width != null) {
109 responseWriter.writeAttribute("style", "width: " + width + "px;", null);
110 }
111
112 encodeHiddenInputs(responseWriter, sheet, clientId);
113 encodeFilterValues(context, responseWriter, sheet, clientId);
114 encodeHeader(context, responseWriter, sheet);
115
116
117 responseWriter.startElement("div", null);
118 responseWriter.writeAttribute("id", clientId + "_tbl", "id");
119 responseWriter.writeAttribute("name", clientId + "_tbl", "clientId");
120 responseWriter.writeAttribute("class", "handsontable-inner", "styleClass");
121
122 if (style == null) {
123 style = Constants.EMPTY_STRING;
124 }
125
126 if (width != null) {
127 style = style + "width: " + width + "px;";
128 }
129
130 if (height != null) {
131 style = style + "height: " + height + "px;";
132 }
133 else {
134 style = style + "height: 100%;";
135 }
136
137 if (style.length() > 0) {
138 responseWriter.writeAttribute("style", style, null);
139 }
140
141 responseWriter.endElement("div");
142 encodeFooter(context, responseWriter, sheet);
143 responseWriter.endElement("div");
144 }
145
146
147
148
149
150
151
152
153
154 protected void encodeOptionalAttr(final WidgetBuilder wb, final String attrName, final String value)
155 throws IOException {
156 if (value != null) {
157 wb.attr(attrName, value);
158 }
159 }
160
161
162
163
164
165
166
167
168
169 protected void encodeOptionalNativeAttr(final WidgetBuilder wb, final String attrName, final Object value)
170 throws IOException {
171 if (value != null) {
172 wb.nativeAttr(attrName, value.toString());
173 }
174 }
175
176
177
178
179
180
181
182
183 protected void encodeScript(final FacesContext context, final Sheet sheet, final ResponseWriter responseWriter)
184 throws IOException {
185 final WidgetBuilder wb = getWidgetBuilder(context);
186 final String clientId = sheet.getClientId(context);
187 wb.init("ExtSheet", sheet.resolveWidgetVar(), clientId);
188
189
190 encodeInvalidData(context, sheet, wb);
191
192 encodeData(context, sheet, wb);
193
194
195
196 wb.nativeAttr("delta", "{}");
197
198
199 encodeFilterVar(context, sheet, wb);
200
201 encodeSortVar(context, sheet, wb);
202
203 encodeBehaviors(context, sheet, wb);
204
205 encodeOptionalNativeAttr(wb, "readOnly", sheet.isReadOnly());
206 encodeOptionalNativeAttr(wb, "fixedColumnsLeft", sheet.getFixedCols());
207 encodeOptionalNativeAttr(wb, "fixedRowsTop", sheet.getFixedRows());
208 encodeOptionalNativeAttr(wb, "fixedRowsBottom", sheet.getFixedRowsBottom());
209 encodeOptionalNativeAttr(wb, "manualColumnResize", sheet.isResizableCols());
210 encodeOptionalNativeAttr(wb, "manualRowResize", sheet.isResizableRows());
211 encodeOptionalNativeAttr(wb, "manualColumnMove", sheet.isMovableCols());
212 encodeOptionalNativeAttr(wb, "manualRowMove", sheet.isMovableRows());
213 encodeOptionalNativeAttr(wb, "width", sheet.getWidth());
214 encodeOptionalNativeAttr(wb, "height", sheet.getHeight());
215 encodeOptionalNativeAttr(wb, "minRows", sheet.getMinRows());
216 encodeOptionalNativeAttr(wb, "minCols", sheet.getMinCols());
217 encodeOptionalNativeAttr(wb, "maxRows", sheet.getMaxRows());
218 encodeOptionalNativeAttr(wb, "maxCols", sheet.getMaxCols());
219 encodeOptionalAttr(wb, "stretchH", sheet.getStretchH());
220 encodeOptionalAttr(wb, "language", sheet.getLocale());
221 encodeOptionalAttr(wb, "selectionMode", sheet.getSelectionMode());
222 encodeOptionalAttr(wb, "activeHeaderClassName", sheet.getActiveHeaderStyleClass());
223 encodeOptionalAttr(wb, "commentedCellClassName", sheet.getCommentedCellStyleClass());
224 encodeOptionalAttr(wb, "currentRowClassName", sheet.getCurrentRowStyleClass());
225 encodeOptionalAttr(wb, "currentColClassName", sheet.getCurrentColStyleClass());
226 encodeOptionalAttr(wb, "currentHeaderClassName", sheet.getCurrentHeaderStyleClass());
227 encodeOptionalAttr(wb, "invalidCellClassName", sheet.getInvalidCellStyleClass());
228 encodeOptionalAttr(wb, "noWordWrapClassName", sheet.getNoWordWrapStyleClass());
229 encodeOptionalAttr(wb, "placeholderCellClassName", sheet.getPlaceholderCellStyleClass());
230 encodeOptionalAttr(wb, "readOnlyCellClassName", sheet.getReadOnlyCellStyleClass());
231 encodeOptionalNativeAttr(wb, "extender", sheet.getExtender());
232
233 String emptyMessage = sheet.getEmptyMessage();
234 if (LangUtils.isValueBlank(emptyMessage)) {
235 emptyMessage = "No Records Found";
236 }
237 encodeOptionalAttr(wb, "emptyMessage", emptyMessage);
238
239 encodeColHeaders(context, sheet, wb);
240 encodeColOptions(context, sheet, wb);
241 wb.finish();
242 }
243
244
245
246
247
248
249 protected void encodeInvalidData(final FacesContext context, final Sheet sheet, final WidgetBuilder wb)
250 throws IOException {
251 wb.attr("errors", sheet.getInvalidDataValue());
252 }
253
254
255
256
257
258
259
260
261
262 protected void encodeColHeaders(final FacesContext context, final Sheet sheet, final WidgetBuilder wb)
263 throws IOException {
264 final JavascriptVarBuilderscriptVarBuilder.html#JavascriptVarBuilder">JavascriptVarBuilder vb = new JavascriptVarBuilder(null, false);
265 for (final SheetColumn column : sheet.getColumns()) {
266 if (!column.isRendered()) {
267 continue;
268 }
269 vb.appendArrayValue(column.getHeaderText(), true);
270 }
271 wb.nativeAttr("colHeaders", vb.closeVar().toString());
272 }
273
274
275
276
277
278
279
280
281
282 protected void encodeColOptions(final FacesContext context, final Sheet sheet, final WidgetBuilder wb)
283 throws IOException {
284 final JavascriptVarBuilderscriptVarBuilder.html#JavascriptVarBuilder">JavascriptVarBuilder vb = new JavascriptVarBuilder(null, false);
285 for (final SheetColumn column : sheet.getColumns()) {
286 if (!column.isRendered()) {
287 continue;
288 }
289
290 final JavascriptVarBuildertVarBuilder.html#JavascriptVarBuilder">JavascriptVarBuilder options = new JavascriptVarBuilder(null, true);
291 options.appendProperty("type", column.getColType(), true);
292 options.appendProperty("copyable", "true", false);
293 final Integer width = column.getColWidth();
294 String calculatedWidth = null;
295 if (width != null) {
296 calculatedWidth = width.toString();
297 }
298
299
300 if (!column.isVisible()) {
301 calculatedWidth = "0.1";
302 }
303 if (calculatedWidth != null) {
304 options.appendProperty("width", calculatedWidth, false);
305 }
306 if (column.isReadOnly()) {
307 options.appendProperty("readOnly", "true", false);
308 }
309 options.appendProperty("trimWhitespace", column.isTrimWhitespace().toString(), false);
310 options.appendProperty("wordWrap", column.isWordWrap().toString(), false);
311
312
313 final String validateFunction = column.getOnvalidate();
314 if (validateFunction != null) {
315 boolean quoted = false;
316 switch (validateFunction) {
317 case "autocomplete":
318 case "date":
319 case "numeric":
320 case "time":
321 quoted = true;
322 break;
323
324 default:
325
326 quoted = false;
327 break;
328 }
329 options.appendProperty("validator", validateFunction, quoted);
330 }
331
332 switch (column.getColType()) {
333 case "password":
334 final Integer passwordLength = column.getPasswordHashLength();
335 if (passwordLength != null) {
336 options.appendProperty("hashLength", passwordLength.toString(), false);
337 }
338 final String passwordSymbol = column.getPasswordHashSymbol();
339 if (passwordSymbol != null) {
340 options.appendProperty("hashSymbol", passwordSymbol, true);
341 }
342 break;
343 case "numeric":
344 final JavascriptVarBuildertVarBuilder.html#JavascriptVarBuilder">JavascriptVarBuilder numeric = new JavascriptVarBuilder(null, true);
345 final String pattern = column.getNumericPattern();
346 if (pattern != null) {
347 numeric.appendProperty("pattern", pattern, true);
348 }
349 final String culture = column.getNumericLocale();
350 if (culture != null) {
351 numeric.appendProperty("culture", culture, true);
352 }
353 options.appendProperty("numericFormat", numeric.closeVar().toString(), false);
354 break;
355 case "date":
356 options.appendProperty("dateFormat", column.getDateFormat(), true);
357 options.appendProperty("correctFormat", "true", false);
358 final String dateConfig = column.getDatePickerConfig();
359 if (dateConfig != null) {
360 options.appendProperty("datePickerConfig", dateConfig, false);
361 }
362 break;
363 case "time":
364 options.appendProperty("timeFormat", column.getTimeFormat(), true);
365 options.appendProperty("correctFormat", "true", false);
366 break;
367 case "dropdown":
368 encodeSelectItems(column, options);
369 break;
370 case "autocomplete":
371 options.appendProperty("strict", column.isAutoCompleteStrict().toString(), false);
372 options.appendProperty("allowInvalid", column.isAutoCompleteAllowInvalid().toString(), false);
373 options.appendProperty("trimDropdown", column.isAutoCompleteTrimDropdown().toString(), false);
374 final Integer visibleRows = column.getAutoCompleteVisibleRows();
375 if (visibleRows != null) {
376 options.appendProperty("visibleRows", visibleRows.toString(), false);
377 }
378 encodeSelectItems(column, options);
379 break;
380 default:
381 break;
382 }
383
384 vb.appendArrayValue(options.closeVar().toString(), false);
385 }
386 wb.nativeAttr("columns", vb.closeVar().toString());
387 }
388
389 private void encodeSelectItems(final SheetColumn column, final JavascriptVarBuilder options) {
390 final JavascriptVarBuilderiptVarBuilder.html#JavascriptVarBuilder">JavascriptVarBuilder items = new JavascriptVarBuilder(null, false);
391 final Object value = column.getSelectItems();
392 if (value == null) {
393 return;
394 }
395 if (value.getClass().isArray()) {
396 for (int j = 0; j < Array.getLength(value); j++) {
397 final Object item = Array.get(value, j);
398 items.appendArrayValue(String.valueOf(item), true);
399 }
400 }
401 else if (value instanceof Collection) {
402 final Collection collection = (Collection) value;
403 for (final Iterator it = collection.iterator(); it.hasNext();) {
404 final Object item = it.next();
405 items.appendArrayValue(String.valueOf(item), true);
406 }
407 }
408 else if (value instanceof Map) {
409 final Map map = (Map) value;
410
411 for (final Iterator it = map.keySet().iterator(); it.hasNext();) {
412 final Object item = it.next();
413 items.appendArrayValue(String.valueOf(item), true);
414 }
415 }
416
417 options.appendProperty("source", items.closeVar().toString(), false);
418 }
419
420
421
422
423
424
425
426
427
428 protected void encodeData(final FacesContext context, final Sheet sheet, final WidgetBuilder wb)
429 throws IOException {
430
431 final JavascriptVarBuilderptVarBuilder.html#JavascriptVarBuilder">JavascriptVarBuilder jsData = new JavascriptVarBuilder(null, false);
432 final JavascriptVarBuilderarBuilder.html#JavascriptVarBuilder">JavascriptVarBuilder jsRowKeys = new JavascriptVarBuilder(null, false);
433 final JavascriptVarBuildertVarBuilder.html#JavascriptVarBuilder">JavascriptVarBuilder jsStyle = new JavascriptVarBuilder(null, true);
434 final JavascriptVarBuilderrBuilder.html#JavascriptVarBuilder">JavascriptVarBuilder jsRowStyle = new JavascriptVarBuilder(null, false);
435 final JavascriptVarBuilderrBuilder.html#JavascriptVarBuilder">JavascriptVarBuilder jsReadOnly = new JavascriptVarBuilder(null, true);
436 final JavascriptVarBuilderuilder.html#JavascriptVarBuilder">JavascriptVarBuilder jsRowHeaders = new JavascriptVarBuilder(null, false);
437
438 final boolean isCustomHeader = sheet.getRowHeaderValueExpression() != null;
439
440 final List<Object> values = sheet.getSortedValues();
441 int row = 0;
442 for (final Object value : values) {
443 context.getExternalContext().getRequestMap().put(sheet.getVar(), value);
444 final String rowKey = sheet.getRowKeyValueAsString(context);
445 jsRowKeys.appendArrayValue(rowKey, true);
446 encodeRow(context, rowKey, jsData, jsRowStyle, jsStyle, jsReadOnly, sheet, row);
447
448
449
450 if (sheet.isShowRowHeaders() && isCustomHeader) {
451 final String rowHeader = sheet.getRowHeaderValueAsString(context);
452 jsRowHeaders.appendArrayValue(rowHeader, true);
453 }
454 row++;
455 }
456
457 sheet.setRowVar(context, null);
458
459 wb.nativeAttr("data", jsData.closeVar().toString());
460 wb.nativeAttr("styles", jsStyle.closeVar().toString());
461 wb.nativeAttr("rowStyles", jsRowStyle.closeVar().toString());
462 wb.nativeAttr("readOnlyCells", jsReadOnly.closeVar().toString());
463 wb.nativeAttr("rowKeys", jsRowKeys.closeVar().toString());
464
465
466 if (!isCustomHeader) {
467 wb.nativeAttr("rowHeaders", sheet.isShowRowHeaders().toString());
468 }
469 else {
470 wb.nativeAttr("rowHeaders", jsRowHeaders.closeVar().toString());
471 }
472 }
473
474
475
476
477
478
479 protected JavascriptVarBuilder encodeRow(final FacesContext context, final String rowKey,
480 final JavascriptVarBuildertVarBuilder.html#JavascriptVarBuilder">JavascriptVarBuilder jsData, final JavascriptVarBuilder jsRowStyle,
481 final JavascriptVarBuilderVarBuilder.html#JavascriptVarBuilder">JavascriptVarBuilder jsStyle, final JavascriptVarBuilder jsReadOnly, final Sheet sheet,
482 final int rowIndex) throws IOException {
483
484 final String rowStyleClass = sheet.getRowStyleClass();
485 if (rowStyleClass == null) {
486 jsRowStyle.appendArrayValue("null", false);
487 }
488 else {
489 jsRowStyle.appendArrayValue(rowStyleClass, true);
490 }
491
492
493 final JavascriptVarBuilderiptVarBuilder.html#JavascriptVarBuilder">JavascriptVarBuilder jsRow = new JavascriptVarBuilder(null, false);
494 int renderCol = 0;
495 for (int col = 0; col < sheet.getColumns().size(); col++) {
496 final SheetColumn column = sheet.getColumns().get(col);
497 if (!column.isRendered()) {
498 continue;
499 }
500
501
502 final String value = sheet.getRenderValueForCell(context, rowKey, col);
503 jsRow.appendArrayValue(value, true);
504
505
506 final String styleClass = column.getStyleClass();
507 if (styleClass != null) {
508 jsStyle.appendRowColProperty(rowIndex, renderCol, styleClass, true);
509 }
510
511
512 final boolean readOnly = column.isReadonlyCell();
513 if (readOnly) {
514 jsReadOnly.appendRowColProperty(rowIndex, renderCol, "true", true);
515 }
516 renderCol++;
517 }
518
519 jsData.appendArrayValue(jsRow.closeVar().toString(), false);
520 return jsData;
521 }
522
523
524
525
526
527
528
529
530
531 private void encodeHiddenInputs(final ResponseWriter responseWriter, final Sheet sheet, final String clientId)
532 throws IOException {
533 responseWriter.startElement("input", null);
534 responseWriter.writeAttribute("id", clientId + "_input", "id");
535 responseWriter.writeAttribute("name", clientId + "_input", "name");
536 responseWriter.writeAttribute("type", "hidden", null);
537 responseWriter.writeAttribute("value", "", null);
538 responseWriter.endElement("input");
539
540 responseWriter.startElement("input", null);
541 responseWriter.writeAttribute("id", clientId + "_focus", "id");
542 responseWriter.writeAttribute("name", clientId + "_focus", "name");
543 responseWriter.writeAttribute("type", "hidden", null);
544 if (sheet.getFocusId() == null) {
545 responseWriter.writeAttribute("value", "", null);
546 }
547 else {
548 responseWriter.writeAttribute("value", sheet.getFocusId(), null);
549 }
550 responseWriter.endElement("input");
551
552 responseWriter.startElement("input", null);
553 responseWriter.writeAttribute("id", clientId + "_selection", "id");
554 responseWriter.writeAttribute("name", clientId + "_selection", "name");
555 responseWriter.writeAttribute("type", "hidden", null);
556 if (sheet.getSelection() == null) {
557 responseWriter.writeAttribute("value", "", null);
558 }
559 else {
560 responseWriter.writeAttribute("value", sheet.getSelection(), null);
561 }
562 responseWriter.endElement("input");
563
564
565 final int sortCol = sheet.getSortColRenderIndex();
566 responseWriter.startElement("input", null);
567 responseWriter.writeAttribute("id", clientId + "_sortby", "id");
568 responseWriter.writeAttribute("name", clientId + "_sortby", "name");
569 responseWriter.writeAttribute("type", "hidden", null);
570 responseWriter.writeAttribute("value", sortCol, null);
571 responseWriter.endElement("input");
572
573 responseWriter.startElement("input", null);
574 responseWriter.writeAttribute("id", clientId + "_sortorder", "id");
575 responseWriter.writeAttribute("name", clientId + "_sortorder", "name");
576 responseWriter.writeAttribute("type", "hidden", null);
577 responseWriter.writeAttribute("value", sheet.getSortOrder().toLowerCase(), null);
578 responseWriter.endElement("input");
579 }
580
581
582
583
584
585
586
587
588
589 private void encodeBehaviors(final FacesContext context, final Sheet sheet, final WidgetBuilder wb)
590 throws IOException {
591
592
593 final Map<String, List<ClientBehavior>> behaviors = sheet.getClientBehaviors();
594
595 wb.append(",behaviors:{");
596 final String clientId = sheet.getClientId();
597
598
599 if (behaviors.containsKey("sort")) {
600 final ClientBehaviorContext behaviorContext = ClientBehaviorContext.createClientBehaviorContext(context,
601 sheet, "sort", sheet.getClientId(context), null);
602 final AjaxBehavior ajaxBehavior = (AjaxBehavior) behaviors.get("sort").get(0);
603 ajaxBehavior.setUpdate(StringUtils.defaultString(ajaxBehavior.getUpdate()) + StringUtils.SPACE + clientId);
604 wb.append("sort").append(":").append("function(s, event)").append("{")
605 .append(behaviors.get("sort").get(0).getScript(behaviorContext)).append("}");
606 }
607 else {
608
609 wb.append("sort").append(":").append("function(s, event)").append("{").append("PrimeFaces.ab({source: '")
610 .append(clientId).append("',event: 'sort', process: '").append(clientId).append("', update: '")
611 .append(clientId).append("'});}");
612 }
613
614
615 if (behaviors.containsKey("filter")) {
616 final ClientBehaviorContext behaviorContext = ClientBehaviorContext.createClientBehaviorContext(context,
617 sheet, "filter", sheet.getClientId(context), null);
618 final AjaxBehavior ajaxBehavior = (AjaxBehavior) behaviors.get("filter").get(0);
619 ajaxBehavior.setUpdate(StringUtils.defaultString(ajaxBehavior.getUpdate()) + StringUtils.SPACE + clientId);
620 wb.callback("filter", "function(source, event)", behaviors.get("filter").get(0).getScript(behaviorContext));
621 }
622 else {
623
624 wb.callback("filter", "function(source, event)", "PrimeFaces.ab({s: '" + clientId
625 + "', event: 'filter', process: '" + clientId + "', update: '" + clientId + "'});");
626 }
627
628 if (behaviors.containsKey("change")) {
629 final ClientBehaviorContext behaviorContext = ClientBehaviorContext.createClientBehaviorContext(context,
630 sheet, "change", sheet.getClientId(context), null);
631 wb.callback("change", "function(source, event)", behaviors.get("change").get(0).getScript(behaviorContext));
632 }
633
634 if (behaviors.containsKey("cellSelect")) {
635 final ClientBehaviorContext behaviorContext = ClientBehaviorContext.createClientBehaviorContext(context,
636 sheet, "cellSelect", sheet.getClientId(context), null);
637 wb.callback("cellSelect", "function(source, event)",
638 behaviors.get("cellSelect").get(0).getScript(behaviorContext));
639 }
640
641 if (behaviors.containsKey("columnSelect")) {
642 final ClientBehaviorContext behaviorContext = ClientBehaviorContext.createClientBehaviorContext(context,
643 sheet, "columnSelect", sheet.getClientId(context), null);
644 wb.callback("columnSelect", "function(source, event)",
645 behaviors.get("columnSelect").get(0).getScript(behaviorContext));
646 }
647
648 if (behaviors.containsKey("rowSelect")) {
649 final ClientBehaviorContext behaviorContext = ClientBehaviorContext.createClientBehaviorContext(context,
650 sheet, "rowSelect", sheet.getClientId(context), null);
651 wb.callback("rowSelect", "function(source, event)",
652 behaviors.get("rowSelect").get(0).getScript(behaviorContext));
653 }
654
655 wb.append("}");
656 }
657
658
659
660
661
662
663
664
665
666 private void encodeFooter(final FacesContext context, final ResponseWriter responseWriter, final Sheet sheet)
667 throws IOException {
668
669 final UIComponent footer = sheet.getFacet("footer");
670 if (ComponentUtils.shouldRenderFacet(footer)) {
671 responseWriter.startElement("div", null);
672 responseWriter.writeAttribute("class", "ui-datatable-footer ui-widget-header ui-corner-bottom", null);
673 footer.encodeAll(context);
674 responseWriter.endElement("div");
675 }
676 }
677
678
679
680
681
682
683
684
685
686 private void encodeHeader(final FacesContext context, final ResponseWriter responseWriter, final Sheet sheet)
687 throws IOException {
688
689 final UIComponent header = sheet.getFacet("header");
690 if (ComponentUtils.shouldRenderFacet(header)) {
691 responseWriter.startElement("div", null);
692 responseWriter.writeAttribute("class", "ui-datatable-header ui-widget-header ui-corner-top", null);
693 header.encodeAll(context);
694 responseWriter.endElement("div");
695 }
696 }
697
698
699
700
701
702
703
704
705
706 protected void encodeFilterValues(final FacesContext context, final ResponseWriter responseWriter,
707 final Sheet sheet, final String clientId) throws IOException {
708 int renderCol = 0;
709 for (final SheetColumn column : sheet.getColumns()) {
710 if (!column.isRendered()) {
711 continue;
712 }
713
714 if (column.getValueExpression("filterBy") != null) {
715 responseWriter.startElement("input", null);
716 responseWriter.writeAttribute("id", clientId + "_filter_" + renderCol, "id");
717 responseWriter.writeAttribute("name", clientId + "_filter_" + renderCol, "name");
718 responseWriter.writeAttribute("type", "hidden", null);
719 responseWriter.writeAttribute("value", column.getFilterValue(), null);
720 responseWriter.endElement("input");
721 }
722
723 renderCol++;
724 }
725 }
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742 protected void encodeFilterVar(final FacesContext context, final Sheet sheet, final WidgetBuilder wb)
743 throws IOException {
744 final JavascriptVarBuilderscriptVarBuilder.html#JavascriptVarBuilder">JavascriptVarBuilder vb = new JavascriptVarBuilder(null, false);
745
746 for (final SheetColumn column : sheet.getColumns()) {
747 if (!column.isRendered()) {
748 continue;
749 }
750
751 if (column.getValueExpression("filterBy") == null) {
752 vb.appendArrayValue("false", true);
753 continue;
754 }
755
756 final Collection<SelectItem> options = column.getFilterOptions();
757 if (options == null) {
758 vb.appendArrayValue("true", true);
759 }
760 else {
761 final JavascriptVarBuilderarBuilder.html#JavascriptVarBuilder">JavascriptVarBuilder vbOptions = new JavascriptVarBuilder(null, false);
762 for (final SelectItem item : options) {
763 vbOptions.appendArrayValue(
764 "{ label: \"" + item.getLabel() + "\", value: \"" + item.getValue() + "\"}", false);
765 }
766 vb.appendArrayValue(vbOptions.closeVar().toString(), false);
767 }
768
769 }
770 wb.nativeAttr("filters", vb.closeVar().toString());
771 }
772
773
774
775
776
777
778
779
780
781
782 protected void encodeSortVar(final FacesContext context, final Sheet sheet, final WidgetBuilder wb)
783 throws IOException {
784 final JavascriptVarBuilderscriptVarBuilder.html#JavascriptVarBuilder">JavascriptVarBuilder vb = new JavascriptVarBuilder(null, false);
785
786 for (final SheetColumn column : sheet.getColumns()) {
787 if (!column.isRendered()) {
788 continue;
789 }
790
791 if (column.getValueExpression("sortBy") == null) {
792 vb.appendArrayValue("false", false);
793 }
794 else {
795 vb.appendArrayValue("true", false);
796 }
797 }
798 wb.nativeAttr("sortable", vb.closeVar().toString());
799 }
800
801
802
803
804
805
806
807
808
809
810
811
812 @Override
813 public void decode(final FacesContext context, final UIComponent component) {
814 final Sheet sheet = (Sheet) component;
815
816
817 for (final SheetColumn column : sheet.getColumns()) {
818 column.setSheet(sheet);
819 }
820
821
822 sheet.getUpdates().clear();
823
824
825
826 final Map<String, String> params = context.getExternalContext().getRequestParameterMap();
827 final String clientId = sheet.getClientId(context);
828
829
830 final String jsonUpdates = params.get(clientId + "_input");
831 final String jsonSelection = params.get(clientId + "_selection");
832
833
834 decodeSubmittedValues(context, sheet, jsonUpdates);
835
836
837 decodeSelection(context, sheet, jsonSelection);
838
839
840 decodeBehaviors(context, sheet);
841
842
843 decodeFilters(context, sheet, params, clientId);
844
845 final String sortBy = params.get(clientId + "_sortby");
846 final String sortOrder = params.get(clientId + "_sortorder");
847 if (sortBy != null) {
848 int col = Integer.valueOf(sortBy);
849 if (col >= 0) {
850 col = sheet.getMappedColumn(col);
851 sheet.saveSortByColumn(sheet.getColumns().get(col).getId());
852 }
853 }
854
855 if (sortOrder != null) {
856 sheet.setSortOrder(sortOrder);
857 }
858
859 final String focus = params.get(clientId + "_focus");
860 sheet.setFocusId(focus);
861 }
862
863
864
865
866
867
868
869
870
871 protected void decodeFilters(final FacesContext context, final Sheet sheet, final Map<String, String> params,
872 final String clientId) {
873 int renderCol = 0;
874 for (final SheetColumn column : sheet.getColumns()) {
875 if (!column.isRendered()) {
876 continue;
877 }
878
879 if (column.getValueExpression("filterBy") != null) {
880 final String value = params.get(clientId + "_filter_" + renderCol);
881 column.setFilterValue(value);
882 }
883
884 renderCol++;
885 }
886 }
887
888
889
890
891
892
893
894 @Override
895 protected void decodeBehaviors(final FacesContext context, final UIComponent component) {
896
897
898 final Map<String, List<ClientBehavior>> behaviors = ((ClientBehaviorHolder) component).getClientBehaviors();
899
900
901 if (behaviors.isEmpty()) {
902 return;
903 }
904
905
906 final Map<String, String> params = context.getExternalContext().getRequestParameterMap();
907 final String behaviorEvent = params.get("javax.faces.behavior.event");
908
909
910 if (behaviorEvent == null) {
911 return;
912 }
913
914
915 final List<ClientBehavior> behaviorsForEvent = behaviors.get(behaviorEvent);
916 if (behaviorsForEvent == null || behaviorsForEvent.isEmpty()) {
917 return;
918 }
919
920
921 final String behaviorSource = params.get("javax.faces.source");
922 final String clientId = component.getClientId();
923 if (behaviorSource != null && clientId.equals(behaviorSource)) {
924 for (final ClientBehavior behavior : behaviorsForEvent) {
925 behavior.decode(context, component);
926 }
927 }
928 }
929
930
931
932
933
934
935
936
937 private void decodeSelection(final FacesContext context, final Sheet sheet, final String jsonSelection) {
938 if (LangUtils.isValueBlank(jsonSelection)) {
939 return;
940 }
941
942 try {
943
944 final JSONArray array = new JSONArray(jsonSelection);
945 sheet.setSelectedRow(array.getInt(0));
946 sheet.setSelectedColumn(sheet.getMappedColumn(array.getInt(1)));
947 sheet.setSelectedLastRow(array.getInt(2));
948 sheet.setSelectedLastColumn(array.getInt(3));
949 sheet.setSelection(jsonSelection);
950 }
951 catch (final JSONException e) {
952 throw new FacesException("Failed parsing Ajax JSON message for cell selection event:" + e.getMessage(), e);
953 }
954 }
955
956
957
958
959
960
961
962
963 private void decodeSubmittedValues(final FacesContext context, final Sheet sheet, final String jsonData) {
964 if (LangUtils.isValueBlank(jsonData)) {
965 return;
966 }
967
968 try {
969
970
971
972
973
974 final JSONObject obj = new JSONObject(jsonData);
975 final Iterator<String> keys = obj.keys();
976 while (keys.hasNext()) {
977 final String key = keys.next();
978
979 final JSONArray update = obj.getJSONArray(key);
980
981 if (update.isNull(4)) {
982 continue;
983 }
984 final String rowKey = update.getString(4);
985 final int col = sheet.getMappedColumn(update.getInt(1));
986 final String newValue = String.valueOf(update.get(3));
987 sheet.setSubmittedValue(context, rowKey, col, newValue);
988 }
989 }
990 catch (final JSONException ex) {
991 throw new FacesException("Failed parsing Ajax JSON message for cell change event:" + ex.getMessage(), ex);
992 }
993 }
994
995
996
997
998 @Override
999 public boolean getRendersChildren() {
1000 return true;
1001 }
1002
1003 }