@Test public void nestedTags() throws Exception { this.writer.startTag("span"); this.writer.writeAttribute("style", "foo"); this.writer.startTag("strong"); this.writer.appendValue("Rob Harrop"); this.writer.endTag(); this.writer.endTag(); assertEquals("<span style=\"foo\"><strong>Rob Harrop</strong></span>", this.data.toString()); }
/** * Create the {@link TagWriter} which all output will be written to. By default, * the {@link TagWriter} writes its output to the {@link javax.servlet.jsp.JspWriter} * for the current {@link javax.servlet.jsp.PageContext}. Subclasses may choose to * change the {@link java.io.Writer} to which output is actually written. */ protected TagWriter createTagWriter() { return new TagWriter(this.pageContext); }
/** * Writes the opening '{@code label}' tag and forces a block tag so * that body content is written correctly. * @return {@link javax.servlet.jsp.tagext.Tag#EVAL_BODY_INCLUDE} */ @Override protected int writeTagContent(TagWriter tagWriter) throws JspException { tagWriter.startTag(LABEL_TAG); tagWriter.writeAttribute(FOR_ATTRIBUTE, resolveFor()); writeDefaultAttributes(tagWriter); tagWriter.forceBlock(); this.tagWriter = tagWriter; return EVAL_BODY_INCLUDE; }
/** * Indicate that the currently open tag should be closed and marked * as a block level element. * <p>Useful when you plan to write additional content in the body * outside the context of the current {@link TagWriter}. */ public void forceBlock() throws JspException { if (currentState().isBlockTag()) { return; // just ignore since we are already in the block } closeTagAndMarkAsBlock(); }
/** * Close the current opening tag (if necessary) and appends the * supplied value as inner text. * @throws IllegalStateException if no tag is open */ public void appendValue(String value) throws JspException { if (!inTag()) { throw new IllegalStateException("Cannot write tag value. No open tag available."); } closeTagAndMarkAsBlock(); this.writer.append(value); }
/** * Start a new tag with the supplied name. Leaves the tag open so * that attributes, inner text or nested tags can be written into it. * @see #endTag() */ public void startTag(String tagName) throws JspException { if (inTag()) { closeTagAndMarkAsBlock(); } push(tagName); this.writer.append("<").append(tagName); }
@Test public void appendingValue() throws Exception { this.writer.startTag("span"); this.writer.appendValue("Rob "); this.writer.appendValue("Harrop"); this.writer.endTag(); assertEquals("<span>Rob Harrop</span>", this.data.toString()); }
tagWriter.startTag("select"); writeDefaultAttributes(tagWriter); if (isMultiple()) { tagWriter.writeAttribute("multiple", "multiple"); tagWriter.writeOptionalAttributeValue("size", getDisplayString(evaluate("size", getSize()))); tagWriter.endTag(true); writeHiddenTagIfNecessary(tagWriter); return SKIP_BODY; tagWriter.forceBlock(); this.tagWriter = tagWriter; this.pageContext.setAttribute(LIST_VALUE_PAGE_ATTRIBUTE, getBindStatus());
/** * If using a multi-select, a hidden element is needed to make sure all * items are correctly unselected on the server-side in response to a * {@code null} post. */ private void writeHiddenTagIfNecessary(TagWriter tagWriter) throws JspException { if (isMultiple()) { tagWriter.startTag("input"); tagWriter.writeAttribute("type", "hidden"); String name = WebDataBinder.DEFAULT_FIELD_MARKER_PREFIX + getName(); tagWriter.writeAttribute("name", name); tagWriter.writeAttribute("value", processFieldValue(name, "1", "hidden")); tagWriter.endTag(); } }
@Test public void writeInterleavedWithForceBlock() throws Exception { this.writer.startTag("span"); this.writer.forceBlock(); this.data.write("Rob Harrop"); // interleaved writing this.writer.endTag(); assertEquals("<span>Rob Harrop</span>", this.data.toString()); }
/** * Write an HTML attribute if the supplied value is not {@code null} * or zero length. * @see #writeAttribute(String, String) */ public void writeOptionalAttributeValue(String attributeName, @Nullable String attributeValue) throws JspException { if (StringUtils.hasText(attributeValue)) { writeAttribute(attributeName, attributeValue); } }
/** * Close the current tag. * <p>Correctly writes an empty tag if no inner text or nested tags * have been written. */ public void endTag() throws JspException { endTag(false); }
/** * Close the current tag, allowing to enforce a full closing tag. * <p>Correctly writes an empty tag if no inner text or nested tags * have been written. * @param enforceClosingTag whether a full closing tag should be * rendered in any case, even in case of a non-block tag */ public void endTag(boolean enforceClosingTag) throws JspException { if (!inTag()) { throw new IllegalStateException("Cannot write end of tag. No open tag available."); } boolean renderClosingTag = true; if (!currentState().isBlockTag()) { // Opening tag still needs to be closed... if (enforceClosingTag) { this.writer.append(">"); } else { this.writer.append("/>"); renderClosingTag = false; } } if (renderClosingTag) { this.writer.append("</").append(currentState().getTagName()).append(">"); } this.tagState.pop(); }
@Override protected int writeTagContent(TagWriter tagWriter) throws JspException { tagWriter.startTag("button"); writeDefaultAttributes(tagWriter); tagWriter.writeAttribute("type", getType()); writeValue(tagWriter); if (isDisabled()) { tagWriter.writeAttribute(DISABLED_ATTRIBUTE, "disabled"); } tagWriter.forceBlock(); this.tagWriter = tagWriter; return EVAL_BODY_INCLUDE; }
tagWriter.writeAttribute(ACTION_ATTRIBUTE, resolveAction()); writeOptionalAttribute(tagWriter, METHOD_ATTRIBUTE, getHttpMethod()); writeOptionalAttribute(tagWriter, TARGET_ATTRIBUTE, getTarget()); writeOptionalAttribute(tagWriter, AUTOCOMPLETE_ATTRIBUTE, getAutocomplete()); tagWriter.forceBlock();
/** * Writes the given values as hidden fields. */ private void writeHiddenFields(@Nullable Map<String, String> hiddenFields) throws JspException { if (!CollectionUtils.isEmpty(hiddenFields)) { Assert.state(this.tagWriter != null, "No TagWriter set"); this.tagWriter.appendValue("<div>\n"); for (String name : hiddenFields.keySet()) { this.tagWriter.appendValue("<input type=\"hidden\" "); this.tagWriter.appendValue("name=\"" + name + "\" value=\"" + hiddenFields.get(name) + "\" "); this.tagWriter.appendValue("/>\n"); } this.tagWriter.appendValue("</div>"); } }
/** * Closes the current opening tag and marks it as a block tag. */ private void closeTagAndMarkAsBlock() throws JspException { if (!currentState().isBlockTag()) { currentState().markAsBlockTag(); this.writer.append(">"); } }
tagWriter.writeAttribute("multiple", "multiple"); tagWriter.writeOptionalAttributeValue("size", getDisplayString(evaluate("size", getSize()))); tagWriter.forceBlock(); this.tagWriter = tagWriter; this.pageContext.setAttribute(LIST_VALUE_PAGE_ATTRIBUTE, getBindStatus());
@Override protected void renderDefaultContent(TagWriter tagWriter) throws JspException { tagWriter.startTag(getElement()); writeDefaultAttributes(tagWriter); String delimiter = ObjectUtils.getDisplayString(evaluate("delimiter", getDelimiter())); String[] errorMessages = getBindStatus().getErrorMessages(); for (int i = 0; i < errorMessages.length; i++) { String errorMessage = errorMessages[i]; if (i > 0) { tagWriter.appendValue(delimiter); } tagWriter.appendValue(getDisplayString(errorMessage)); } tagWriter.endTag(); }