/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.formio.render;
import java.util.ArrayList;
import java.util.List;
import net.formio.BasicListFormMapping;
import net.formio.Field;
import net.formio.FormElement;
import net.formio.FormField;
import net.formio.FormMapping;
import net.formio.ajax.AjaxParams;
import net.formio.ajax.action.AjaxHandler;
import net.formio.choice.ChoiceRenderer;
import net.formio.common.MessageTranslator;
import net.formio.format.Location;
import net.formio.internal.FormUtils;
import net.formio.props.FormElementProperty;
import net.formio.props.FormProperties;
import net.formio.props.types.ButtonType;
import net.formio.props.types.InlinePosition;
import net.formio.render.tdi.TdiResponseBuilder;
import net.formio.validation.ConstraintViolationMessage;
/**
* <p>Form renderer that is using Bootstrap markup and styles.</p>
* <p>You probably want to override the rendered markup to meet your needs - you
* can create custom subclass that uses your favorite templating system and
* overrides some or all methods with "renderMarkup" prefix.</p>
* <p>Thread-safe: Immutable.</p>
*
* @author Radek Beran
*/
public class FormRenderer {
private final Location location;
// Auxiliary renderers
private final StyleRenderer styleRenderer;
private final MessageRenderer messageRenderer;
private final LabelRenderer labelRenderer;
private final DatePickerRenderer datePickerRenderer;
private final AjaxEventRenderer ajaxEventRenderer;
public static final Location DEFAULT_LOCATION = Location.ENGLISH;
public FormRenderer(Location location) {
this.location = location;
this.styleRenderer = new StyleRenderer(this);
this.messageRenderer = new MessageRenderer(this);
this.labelRenderer = new LabelRenderer(this, this.styleRenderer);
this.datePickerRenderer = new DatePickerRenderer(this);
this.ajaxEventRenderer = new AjaxEventRenderer(this);
}
public FormRenderer() {
this(null); // location is null, locale and time zone will be fetched from config of rendered form elements
}
/**
* <p>Renders given form element - form mapping or form field:</p>
* <ul>
* <li>Surrounding placeholder tag (even if the element is invisible).</li>
* <li>Form mapping or form field if it is visible (element markup).</li>
* </ul>
* <p>Visible mapping consists of mapping box with label and nested elements,
* visible form field consists of form group with label and field envelope (with nested form input).</p>
*
* @param element
* @return
*/
public <T> String renderElement(FormElement<T> element) {
String markup = renderMarkupElementPlaceholder(element, renderElementMarkup(element));
if (element instanceof FormField<?>) {
FormField<?> field = (FormField<?>)element;
if (!Field.HIDDEN.getType().equals(field.getType())) {
markup = renderMarkupFormGroup(field, markup);
}
}
return markup;
}
/**
* Renders the element itself without the surrounding placeholder tag.
* If the given element is invisible, returns empty string.
* @param element
* @return
*/
public <T> String renderElementMarkup(FormElement<T> element) {
StringBuilder sb = new StringBuilder("");
if (element.isVisible()) {
sb.append(renderVisibleElement(element));
}
return sb.toString();
}
/**
* Renders element in visible state (assuming the element is visible).
* @param element
* @return
*/
public <T> String renderVisibleElement(FormElement<T> element) {
String html = null;
if (element instanceof FormMapping) {
html = renderVisibleMapping((FormMapping<?>)element);
} else if (element instanceof FormField) {
html = renderVisibleField((FormField<?>)element);
} else if (element != null) {
throw new UnsupportedOperationException("Unsupported element " + element.getClass().getName());
}
return html;
}
/**
* Renders form mapping in visible state (assuming the mapping is visible).
* @param mapping
* @return
*/
public <T> String renderVisibleMapping(FormMapping<T> mapping) {
StringBuilder sb = new StringBuilder();
if (mapping.getProperties().isFieldsetDisplayed()) {
sb.append("<fieldset");
if (!mapping.isEnabled()) {
sb.append(" disabled=\"disabled\"");
}
sb.append(">");
}
// Label
sb.append(renderMarkupMappingLabel(mapping));
// Mapping messages
sb.append(renderMarkupMessageList(mapping));
// Nested mappings and fields
if (mapping instanceof BasicListFormMapping) {
BasicListFormMapping<?> listMapping = (BasicListFormMapping<?>)mapping;
sb.append(renderMarkupListMapping(listMapping));
} else {
for (FormElement<?> el : mapping.getElements()) {
sb.append(renderElement(el));
}
}
if (mapping.getProperties().isFieldsetDisplayed()) {
sb.append("</fieldset>").append(newLine());
}
return newLine() + renderMarkupMappingBox(mapping, sb.toString());
}
/**
* Renders visible list mapping.
* @param listMapping
* @return
*/
protected <T> String renderMarkupListMapping(BasicListFormMapping<T> listMapping) {
String pathSep = listMapping.getConfig().getPathSeparator();
StringBuilder sb = new StringBuilder();
sb.append("<div id=\"").append(listMapping.getName()).append(pathSep).append("begin\"></div>").append(newLine());
for (FormMapping<?> m : listMapping.getList()) {
sb.append(renderElement(m));
}
sb.append("<div id=\"").append(listMapping.getName()).append(pathSep).append("end\"></div>").append(newLine());
return sb.toString();
}
/**
* Renders form field in visible state (assuming the field is visible).
* @param field
* @return
*/
public <T> String renderVisibleField(FormField<T> field) {
StringBuilder sb = new StringBuilder();
String type = field.getType();
Field formComponent = Field.findByType(type);
if (formComponent != null) {
switch (formComponent) {
case HIDDEN:
sb.append(renderFieldHidden(field));
break;
case TEXT:
sb.append(renderFieldText(field));
break;
case TEXT_AREA:
sb.append(renderFieldTextArea(field));
break;
case PASSWORD:
sb.append(renderFieldPassword(field));
break;
case CHECK_BOX:
sb.append(renderFieldCheckbox(field));
break;
case DATE_PICKER:
sb.append(renderFieldDatePicker(field));
break;
case DROP_DOWN_CHOICE:
sb.append(renderFieldDropDownChoice(field));
break;
case FILE_UPLOAD:
sb.append(renderFieldFileUpload(field));
break;
case MULTIPLE_CHECK_BOX:
sb.append(renderFieldMultipleCheckbox(field));
break;
case RADIO_CHOICE:
sb.append(renderFieldRadioChoice(field));
break;
case COLOR:
sb.append(renderFieldColor(field));
break;
case DATE:
sb.append(renderFieldDate(field));
break;
case DATE_TIME:
sb.append(renderFieldDateTime(field));
break;
case DATE_TIME_LOCAL:
sb.append(renderFieldDateTimeLocal(field));
break;
case TIME:
sb.append(renderFieldTime(field));
break;
case EMAIL:
sb.append(renderFieldEmail(field));
break;
case MONTH:
sb.append(renderFieldMonth(field));
break;
case NUMBER:
sb.append(renderFieldNumber(field));
break;
case RANGE:
sb.append(renderFieldRange(field));
break;
case SEARCH:
sb.append(renderFieldSearch(field));
break;
case TEL:
sb.append(renderFieldTel(field));
break;
case URL:
sb.append(renderFieldUrl(field));
break;
case WEEK:
sb.append(renderFieldWeek(field));
break;
case BUTTON:
sb.append(renderFieldButton(field));
break;
case LINK:
sb.append(renderFieldLink(field));
break;
default:
throw new UnsupportedOperationException("Cannot render component with type " + type);
}
} else {
throw new UnsupportedOperationException("Unsupported component with type " + type);
}
return sb.toString();
}
public <T> String renderMarkupGlobalMessages(FormMapping<T> formMapping) {
return messageRenderer.renderGlobalMessages(formMapping);
}
/**
* Creates builder of AJAX response.
* @return
*/
public TdiResponseBuilder ajaxResponse() {
return new TdiResponseBuilder(this);
}
protected <T> String renderMarkupElementPlaceholder(FormElement<T> element, String innerMarkup) {
StringBuilder sb = new StringBuilder();
// Element placeholder begin - rendered even for invisible element so there is reserved
// identified place that can be updated if the element becomes visible.
sb.append("<div id=\"").append(element.getElementPlaceholderId()).append("\">").append(newLine());
// The element itself
sb.append(innerMarkup);
// Element placeholder end
sb.append("</div>").append(newLine());
return sb.toString();
}
protected <T> String renderMarkupMappingBox(FormMapping<T> mapping, String innerMarkup) {
StringBuilder sb = new StringBuilder();
String maxSevClass = getMaxSeverityClass(mapping);
if (maxSevClass != null && !maxSevClass.isEmpty()) {
sb.append("<div class=\"").append(maxSevClass).append("\">").append(newLine());
}
sb.append(innerMarkup);
if (maxSevClass != null && !maxSevClass.isEmpty()) {
sb.append("</div>").append(newLine());
}
return sb.toString();
}
protected <T> String renderMarkupFormGroup(FormField<T> field, String innerMarkup) {
StringBuilder sb = new StringBuilder();
String maxSevClass = getMaxSeverityClass(field);
int colFormWidth = field.getParent().getConfig().getColFormWidth();
InlinePosition inlinePos = field.getProperties().getInline();
if (inlinePos == null || InlinePosition.FIRST.equals(inlinePos)) {
sb.append("<div class=\"row\">").append(newLine());
sb.append("<div class=\"").append(styleRenderer.getFormGroupClasses()).append(" ").append(styleRenderer.getColWidthClassPrefix()).append(colFormWidth).append(" ").append(maxSevClass).append("\">").append(newLine());
}
sb.append(innerMarkup);
if (inlinePos == null || InlinePosition.LAST.equals(inlinePos)) {
sb.append("</div>").append(newLine());
sb.append("</div>").append(newLine()).append(newLine());
}
return sb.toString();
}
protected <T> String renderMarkupInputEnvelope(FormField<T> field, String innerMarkup) {
StringBuilder sb = new StringBuilder();
sb.append("<div class=\"").append(styleRenderer.getInputEnvelopeClasses(field)).append("\">").append(newLine());
sb.append(innerMarkup);
sb.append("</div>").append(newLine());
return sb.toString();
}
protected <T> String renderMarkupMessageList(FormElement<T> element) {
return messageRenderer.renderMessageList(element);
}
protected <T> String renderMarkupMappingLabel(FormMapping<T> mapping) {
return labelRenderer.renderMappingLabel(mapping);
}
protected <T> String renderMarkupFieldLabel(FormField<T> field) {
return labelRenderer.renderFieldLabel(field);
}
protected <T> String renderMarkupTextArea(FormField<T> field) {
StringBuilder sb = new StringBuilder();
sb.append("<textarea name=\"").append(field.getName()).append("\" id=\"").append(field.getElementId()).append("\" class=\"").append(getInputClasses(field)).append("\"");
Integer cols = field.getProperties().getProperty(FormElementProperty.COLS);
if (cols != null) {
sb.append(" cols=\"").append(cols.intValue()).append("\"");
}
Integer rows = field.getProperties().getProperty(FormElementProperty.ROWS);
if (rows != null) {
sb.append(" rows=\"").append(rows.intValue()).append("\"");
}
sb.append(getElementAttributes(field));
sb.append(getInputPlaceholderAttribute(field));
sb.append(">");
sb.append(escapeHtml(field.getValue()));
sb.append("</textarea>").append(newLine());
sb.append(renderFieldScript(field, InputMultiplicity.SINGLE));
return sb.toString();
}
protected <T> String renderMarkupInput(FormField<T> field) {
StringBuilder sb = new StringBuilder();
String typeId = field.getType();
sb.append("<input type=\"").append(field.getInputType()).append("\" name=\"").append(field.getName()).append("\" id=\"").append(field.getElementId()).append("\"");
if (Field.FILE_UPLOAD.getType().equals(typeId)) {
String accept = field.getProperties().getProperty(FormElementProperty.ACCEPT);
if (accept != null) {
sb.append(" accept=\"").append(accept).append("\"");
}
} else {
String value = escapeHtml(field.getValue());
sb.append(" value=\"").append(value).append("\"");
Integer size = field.getProperties().getProperty(FormElementProperty.SIZE);
if (size != null) {
sb.append(" size=\"").append(size.intValue()).append("\"");
}
Integer maxlength = field.getProperties().getProperty(FormElementProperty.MAX_LENGTH);
if (maxlength != null) {
sb.append(" maxlength=\"").append(maxlength.intValue()).append("\"");
}
}
sb.append(getElementAttributes(field));
sb.append(" class=\"").append(getInputClasses(field)).append("\"");
sb.append(getInputPlaceholderAttribute(field));
sb.append("/>").append(newLine());
sb.append(renderFieldScript(field, InputMultiplicity.SINGLE));
return sb.toString();
}
protected <T> String renderMarkupCheckbox(FormField<T> field) {
StringBuilder sb = new StringBuilder();
sb.append("<input type=\"").append(Field.CHECK_BOX.getInputType()).append("\" name=\"").append(field.getName()).append("\" id=\"").append(field.getElementId()).append("\" value=\"1\"");
if (field.isFilledWithTrue()) {
sb.append(" checked=\"checked\" ");
}
sb.append(getElementAttributes(field));
sb.append(" class=\"").append(getInputClasses(field)).append("\"");
sb.append("/>").append(newLine());
sb.append(renderFieldScript(field, InputMultiplicity.SINGLE));
return sb.toString();
}
protected <T> String renderMarkupSelect(FormField<T> field) {
if (field.getChoiceRenderer() == null) {
throw new IllegalStateException("Form field should have ChoiceRenderer defined");
}
StringBuilder sb = new StringBuilder();
sb.append("<select name=\"").append(field.getName()).append("\" id=\"").append(field.getElementId()).append("\"");
Boolean multiple = field.getProperties().getProperty(FormElementProperty.MULTIPLE);
if (multiple != null && multiple.booleanValue()) {
sb.append(" multiple=\"multiple\"");
}
Integer size = field.getProperties().getProperty(FormElementProperty.SIZE);
if (size != null) {
sb.append(" size=\"").append(size.intValue()).append("\"");
}
sb.append(" class=\"").append(getInputClasses(field)).append("\"");
sb.append(getElementAttributes(field));
sb.append(">").append(newLine());
if (field.getChoices() != null) {
List<T> items = toSimplyTypedItems(field.getChoices().getItems());
if (items != null) {
// First "Choose One" option
if (field.getProperties().isChooseOptionDisplayed()) {
sb.append(renderMarkupOption("", field.getProperties().getChooseOptionTitle(), false));
}
ChoiceRenderer<T> choiceRenderer = field.getChoiceRenderer();
int itemIndex = 0;
for (T item : items) {
String value = getChoiceValue(choiceRenderer, item, itemIndex);
String title = getChoiceTitle(choiceRenderer, item, itemIndex);
boolean selected = field.getFilledObjects().contains(item);
sb.append(renderMarkupOption(value, title, selected));
itemIndex++;
}
}
}
sb.append("</select>").append(newLine());
sb.append(renderFieldScript(field, InputMultiplicity.SINGLE));
return sb.toString();
}
protected <T> String renderMarkupChecks(FormField<T> field) {
if (field.getChoiceRenderer() == null) {
throw new IllegalStateException("Form field should have ChoiceRenderer defined");
}
StringBuilder sb = new StringBuilder();
if (field.getChoices() != null) {
List<T> items = toSimplyTypedItems(field.getChoices().getItems());
if (items != null) {
ChoiceRenderer<T> choiceRenderer = field.getChoiceRenderer();
int itemIndex = 0;
for (T item : items) {
String value = getChoiceValue(choiceRenderer, item, itemIndex);
String title = getChoiceTitle(choiceRenderer, item, itemIndex);
String itemId = field.getElementIdWithIndex(itemIndex);
sb.append("<div class=\"").append(field.getInputType()).append("\">").append(newLine());
if (field.getProperties().isLabelVisible()) {
sb.append("<label>");
}
sb.append("<input type=\"").append(field.getInputType()).append("\" name=\"").append(field.getName()).append("\" id=\"").append(itemId).append("\" value=\"").append(value).append("\"");
if (field.getFilledObjects().contains(item)) {
sb.append(" checked=\"checked\"");
}
sb.append(getElementAttributes(field));
sb.append(" class=\"").append(getInputClasses(field)).append("\"");
sb.append("/>");
if (field.getProperties().isLabelVisible()) {
sb.append(" ").append(title).append("</label>");
}
sb.append("</div>").append(newLine());
itemIndex++;
}
sb.append(renderFieldScript(field, InputMultiplicity.MULTIPLE));
}
}
return sb.toString();
}
protected <T> String renderMarkupButton(FormField<T> field) {
StringBuilder sb = new StringBuilder();
String type = ButtonType.SUBMIT.getTypeName();
ButtonType buttonType = field.getProperties().getProperty(FormElementProperty.BUTTON_TYPE);
if (buttonType != null) {
type = buttonType.getTypeName();
}
sb.append("<button type=\"").append(type).append("\" name=\"").append(field.getName()).append("\" value=\"").append(escapeHtml(field.getValue())).append("\" class=\"").append(getInputClasses(field)).append("\">");
MessageTranslator tr = getMessageTranslator(field);
String text = escapeHtml(tr.getMessage(field.getLabelKey()));
sb.append(text);
sb.append("</button>").append(newLine());
return sb.toString();
}
protected <T> String renderMarkupLink(FormField<T> field) {
StringBuilder sb = new StringBuilder();
String url = field.getValue();
if (url == null || url.isEmpty()) {
url = ajaxEventRenderer.getActionLinkUrl(field);
}
sb.append("<a href=\"").append(escapeHtml(url)).append("\"");
sb.append(getElementAttributes(field));
sb.append(" class=\"").append(getInputClasses(field)).append("\">");
MessageTranslator tr = getMessageTranslator(field);
String text = escapeHtml(tr.getMessage(field.getLabelKey()));
sb.append(text);
sb.append("</a>").append(newLine());
sb.append(renderFieldScript(field, InputMultiplicity.SINGLE));
return sb.toString();
}
protected <T> MessageTranslator getMessageTranslator(FormElement<T> element) {
return RenderUtils.getMessageTranslator(element, getLocation(element).getLocale());
}
/**
* Returns string will all HTML attributes of given element.
* @param element
* @return
*/
protected <T> String getElementAttributes(FormElement<T> element) {
return getAccessibilityAttributes(element) + getAjaxAttributes(element) + getJsAttributes(element);
}
protected <T> String getJsAttributes(FormElement<T> element) {
StringBuilder sb = new StringBuilder();
if (element.isEnabled()) {
if (element instanceof FormField<?>) {
FormField<?> field = (FormField<?>)element;
if (field.getProperties().getConfirmMessage() != null && !field.getProperties().getConfirmMessage().isEmpty()) {
if (field.getProperties().getAjaxHandlers() == null || field.getProperties().getAjaxHandlers().length == 0) {
sb.append(" onclick=\"return confirm('").append(escapeHtml(field.getProperties().getConfirmMessage())).append("');\"");
}
}
}
}
return sb.toString();
}
protected <T> String getAccessibilityAttributes(FormElement<T> element) {
StringBuilder sb = new StringBuilder();
if (!element.isEnabled()) {
sb.append(" disabled=\"disabled\"");
}
if (element.isReadonly()) {
sb.append(" readonly=\"readonly\"");
}
return sb.toString();
}
/**
* Returns AJAX attributes of TDI library.
* @param element
* @return
*/
protected <T> String getAjaxAttributes(FormElement<T> element) {
StringBuilder sb = new StringBuilder();
if (element instanceof FormField) {
FormField<?> field = (FormField<?>)element;
AjaxHandler<?> eventHandlerWithoutEvent = field.getProperties().getAjaxHandlerWithoutEvent();
if (eventHandlerWithoutEvent != null) {
String url = FormUtils.urlWithAppendedParameter(eventHandlerWithoutEvent.getHandlerUrl(field.getParent().getConfig().getUrlBase(), field),
AjaxParams.SRC_ELEMENT_NAME, element.getName());
sb.append(" data-ajax-url=\"").append(url).append("\"");
}
if (field.getProperties().getAjaxHandlers() != null && field.getProperties().getAjaxHandlers().length > 0) {
String confirmMsg = field.getProperties().getConfirmMessage();
if (confirmMsg != null && !confirmMsg.isEmpty()) {
sb.append(" data-confirm=\"").append(confirmMsg).append("\"");
}
}
if (field.getProperties().getAjaxRelatedElement() != null && !field.getProperties().getAjaxRelatedElement().isEmpty()) {
sb.append(" data-related-element=\"").append(field.getProperties().getAjaxRelatedElement()).append("\"");
}
if (field.getProperties().getAjaxSourceAncestorElement() != null && !field.getProperties().getAjaxSourceAncestorElement().isEmpty()) {
sb.append(" data-related-ancestor=\"").append(field.getProperties().getAjaxSourceAncestorElement()).append("\"");
}
}
return sb.toString();
}
/**
* Returns CSS classes for given form field.
* @param field
*/
protected <T> String getInputClasses(FormField<T> field) {
return styleRenderer.getInputClasses(field);
}
/**
* Returns placeholder attribute for the input of given form field.
* This attribute shows help (placeholder value) inside the form input
* before the user fills in his own value.
* @param field
* @return
*/
protected <T> String getInputPlaceholderAttribute(FormField<T> field) {
StringBuilder sb = new StringBuilder();
if (field.getProperties().getPlaceholder() != null) {
sb.append(" placeholder=\"").append(escapeHtml(field.getProperties().getPlaceholder())).append("\"");
}
return sb.toString();
}
protected <T> String renderDatePickerScript(FormField<T> field) {
return datePickerRenderer.renderDatePickerScript(field);
}
/**
* Renders client-side script for handling form field AJAX events.
* @param field
* @param inputMultiplicity whether given form field represents multiple form inputs
* @return
*/
protected <T> String renderFieldScript(FormField<T> field, InputMultiplicity inputMultiplicity) {
return ajaxEventRenderer.renderFieldScript(field, inputMultiplicity);
}
protected <T> String renderTextFieldInternal(FormField<T> field) {
return renderMarkupFieldLabel(field) +
renderMarkupInputEnvelope(field,
renderMarkupInput(field) +
renderMarkupMessageList(field));
}
// --- Various field types - begin ---
protected <T> String renderFieldButton(FormField<T> field) {
return renderMarkupInputEnvelope(field,
renderMarkupButton(field));
}
protected <T> String renderFieldLink(FormField<T> field) {
return renderMarkupInputEnvelope(field,
renderMarkupLink(field));
}
protected <T> String renderFieldHidden(FormField<T> field) {
return renderMarkupInput(field) + newLine();
}
protected <T> String renderFieldText(FormField<T> field) {
return renderTextFieldInternal(field);
}
protected <T> String renderFieldColor(FormField<T> field) {
return renderTextFieldInternal(field);
}
protected <T> String renderFieldDate(FormField<T> field) {
// TODO: Support for min, max attributes
return renderTextFieldInternal(field);
}
protected <T> String renderFieldDateTime(FormField<T> field) {
return renderTextFieldInternal(field);
}
protected <T> String renderFieldDateTimeLocal(FormField<T> field) {
return renderTextFieldInternal(field);
}
protected <T> String renderFieldTime(FormField<T> field) {
return renderTextFieldInternal(field);
}
protected <T> String renderFieldEmail(FormField<T> field) {
return renderTextFieldInternal(field);
}
protected <T> String renderFieldMonth(FormField<T> field) {
return renderTextFieldInternal(field);
}
protected <T> String renderFieldNumber(FormField<T> field) {
// TODO: Support for min, max, step attributes
return renderTextFieldInternal(field);
}
protected <T> String renderFieldRange(FormField<T> field) {
// TODO: Support for min, max attributes
return renderTextFieldInternal(field);
}
protected <T> String renderFieldSearch(FormField<T> field) {
return renderTextFieldInternal(field);
}
protected <T> String renderFieldTel(FormField<T> field) {
return renderTextFieldInternal(field);
}
protected <T> String renderFieldUrl(FormField<T> field) {
return renderTextFieldInternal(field);
}
protected <T> String renderFieldWeek(FormField<T> field) {
return renderTextFieldInternal(field);
}
protected <T> String renderFieldTextArea(FormField<T> field) {
return renderMarkupFieldLabel(field) +
renderMarkupInputEnvelope(field,
renderMarkupTextArea(field) +
renderMarkupMessageList(field));
}
protected <T> String renderFieldCheckbox(FormField<T> field) {
return "<div class=\"" + Field.CHECK_BOX.getInputType() + "\">" + newLine() +
renderMarkupInputEnvelope(field,
"<label>" +
renderMarkupCheckbox(field) +
getLabelText(field) +
"</label>" +
renderMarkupMessageList(field)
) + "</div>" + newLine();
}
protected <T> String renderFieldPassword(FormField<T> field) {
return renderMarkupFieldLabel(field) +
renderMarkupInputEnvelope(field,
renderMarkupInput(field) +
renderMarkupMessageList(field));
}
protected <T> String renderFieldFileUpload(FormField<T> field) {
return renderMarkupFieldLabel(field) +
renderMarkupInputEnvelope(field,
renderMarkupInput(field) +
renderMarkupMessageList(field));
}
protected <T> String renderFieldDatePicker(FormField<T> field) {
return renderMarkupFieldLabel(field) +
renderMarkupInputEnvelope(field,
renderMarkupInput(field) +
renderDatePickerScript(field) +
renderMarkupMessageList(field));
}
protected <T> String renderFieldDropDownChoice(FormField<T> field) {
return renderMarkupFieldLabel(field) +
renderMarkupInputEnvelope(field,
renderMarkupSelect(field) +
renderMarkupMessageList(field));
}
protected <T> String renderFieldMultipleCheckbox(FormField<T> field) {
return renderMarkupFieldLabel(field) +
renderMarkupInputEnvelope(field,
renderMarkupChecks(field) +
renderMarkupMessageList(field));
}
protected <T> String renderFieldRadioChoice(FormField<T> field) {
return renderMarkupFieldLabel(field) +
renderMarkupInputEnvelope(field,
renderMarkupChecks(field) +
renderMarkupMessageList(field));
}
// --- /Various field types - end ---
protected <T> String getLabelText(FormElement<T> element) {
return labelRenderer.getLabelText(element);
}
protected <T> String getRequiredMark(FormElement<T> element) {
return labelRenderer.getRequiredMark(element);
}
/**
* Returns region and time zone from location in this renderer; or else from configuration
* bound to given form element.
* @param element
* @return
*/
protected <T> Location getLocation(FormElement<T> element) {
Location a = null;
if (location != null) {
a = location;
} else {
if (element.getConfig() != null) {
a = element.getConfig().getLocation();
} else {
a = DEFAULT_LOCATION;
}
}
return a;
}
/**
* Region and time zone specified explicitly for this form renderer.
* If {@code null} is returned, region and time zone should be fetched from config
* of rendered form elements. Use {@link #getLocation(FormElement)} whenever
* you have reference to rendered form element.
* @return
*/
protected Location getLocation() {
return location;
}
String escapeHtml(String html) {
return RenderUtils.escapeHtml(html);
}
String newLine() {
return System.getProperty("line.separator");
}
String renderMarkupMessage(ConstraintViolationMessage msg) {
return messageRenderer.renderMessage(msg);
}
private <T> String getChoiceTitle(ChoiceRenderer<T> choiceRenderer, T item, int itemIndex) {
return escapeHtml(choiceRenderer.getItem(item, itemIndex).getTitle());
}
private <T> String getChoiceValue(ChoiceRenderer<T> choiceRenderer, T item, int itemIndex) {
return escapeHtml(choiceRenderer.getItem(item, itemIndex).getId());
}
private <T> String getMaxSeverityClass(FormElement<T> mapping) {
String maxSevClass = mapping.getMaxSeverityClass();
if (maxSevClass != null && !maxSevClass.isEmpty()) {
maxSevClass = "has-" + maxSevClass;
}
return maxSevClass;
}
private String renderMarkupOption(String value, String title, boolean selected) {
StringBuilder sb = new StringBuilder();
sb.append("<option value=\"").append(escapeHtml(value)).append("\"");
if (selected) {
sb.append(" selected=\"selected\"");
}
sb.append(">").append(escapeHtml(title)).append("</option>").append(newLine());
return sb.toString();
}
private <T> List<T> toSimplyTypedItems(List<? extends T> items) {
List<T> retItems = new ArrayList<T>();
if (items != null) {
for (T item : items) {
retItems.add(item);
}
}
return retItems;
}
}