Details
-
Improvement
-
Status: Open
-
Major
-
Resolution: Unresolved
-
1.1.9
-
None
-
None
Description
Sometimes Faces renders only HTML fragments without <head> or <body> tags. For example in partial page rendering (with RichFaces).
It would be fine if this doesn't result in errors and if script and style resources would be added nevertheless.
My suggestion to solve the problem:
HTML fragments may not contain the <head> or <body> tags, but they probably contain HTML tags which are to be replaced by PPR in a page's body.
If any HTML element is found which is a valid child of <body> and NO <body> element has been found yet, we probably deal with a HTML fragment.
and the resources are to be inserted before the first found HTML element.
In this case, the CallbackListener can be deceived by telling it the <body> element just startet - even though another HTML element started.
The ParseCallbackListener of DefaultAddResource will then set its beforeBodyPosition and resource insertion works - at least in my application.
Below you find my patch.
Related issues: 889, 992
/**
- An (incomplete) collection of HTML elements which can appear inside
- a HTML
{@code body}
element.
*/
private final static Set<String> BODY_CHILD_TAGS = new HashSet<String>(
Arrays.asList(HTML.ANCHOR_ELEM,
HTML.BR_ELEM,
HTML.BUTTON_ELEM,
HTML.DIV_ELEM,
HTML.FORM_ELEM,
HTML.H1_ELEM,
HTML.H2_ELEM,
HTML.H3_ELEM,
HTML.H4_ELEM,
HTML.H5_ELEM,
HTML.H6_ELEM,
HTML.IFRAME_ELEM,
HTML.IMG_ELEM,
HTML.INPUT_ELEM,
HTML.OL_ELEM,
HTML.SELECT_ELEM,
HTML.SPAN_ELEM,
HTML.TABLE_ELEM,
HTML.TBODY_ELEM,
HTML.TD_ELEM,
HTML.TEXTAREA_ELEM,
HTML.TFOOT_ELEM,
HTML.TH_ELEM,
HTML.THEAD_ELEM,
HTML.TR_ELEM,
HTML.UL_ELEM));
/**
- Indicator telling if {@link CallbackListener#openedStartTag(int, int)}
- has been invoked with
{@link #BODY_TAG}
.
*/
private boolean _isListenerOpenStartTagBodyCalled = false;
/**
- Invoke a callback method to inform the listener that we have found a start tag.
* - @param startOffset
- @param endOffset
- @param tagName
*/
void openedTag(int startOffset, int endOffset, String tagName)
{
//log.debug("Found open tag at " + startOffset + ":" + endOffset + ":" + tagName);
if ("head".equalsIgnoreCase(tagName))
{ _listener.openedStartTag(startOffset, HEAD_TAG); _listener.closedStartTag(endOffset, HEAD_TAG); }else if ("body".equalsIgnoreCase(tagName))
{ _listener.openedStartTag(startOffset, BODY_TAG); _listener.closedStartTag(endOffset, BODY_TAG); this._isListenerOpenStartTagBodyCalled = true; }else if ("script".equalsIgnoreCase(tagName))
{ _listener.openedStartTag(startOffset, SCRIPT_TAG); _listener.closedStartTag(endOffset, SCRIPT_TAG); } // L. Ulrich, 23.09.2009:
// If this._isListenerOpenStartTagBodyCalled is still false
// and if the tag is a valid child of <body>
// we probably deal with a HTML fragment without a <body>.
// In this case, deceive the listener and tell it
// the body has started - even though another HTML element has.
// The code of DefaultAddResource will set its beforeBodyPosition index
// and can insert the resources (stylesheets and scripts) before
// the first HTML element of the fragment.
else if (this._isListenerOpenStartTagBodyCalled == false
&& BODY_CHILD_TAGS.contains(tagName.toLowerCase()))
}