// replace responseWriter and render page content
FastStringWriter content = new FastStringWriter(1024*10);
ResponseWriter contentWriter = writer.cloneWithWriter(content);
facesContext.setResponseWriter(contentWriter);
UIComponent menubar = page.getFacet(FACET_MENUBAR);
if (menubar != null) {
menubar.getAttributes().put(ATTR_PAGE_MENU, Boolean.TRUE);
page.getOnloadScripts().add("Tobago.setElementWidth('"
+ menubar.getClientId(facesContext) + "', Tobago.getBrowserInnerWidth())");
RenderUtil.encode(facesContext, menubar);
}
UILayout.getLayout(component).encodeChildrenOfComponent(facesContext, component);
// RenderUtil.encodeChildren(facesContext, page);
// render popups into buffer
FastStringWriter popups = new FastStringWriter();
contentWriter = writer.cloneWithWriter(popups);
facesContext.setResponseWriter(contentWriter);
// write popup components
// beware of ConcurrentModificationException in cascating popups!
// no foreach
UIPopup[] popupArray = page.getPopups().toArray(new UIPopup[page.getPopups().size()]);
for (int i = 0; i < popupArray.length; i++) {
UIComponent popup = popupArray[i];
RenderUtil.encode(facesContext, popup);
}
// reset responseWriter and render page
facesContext.setResponseWriter(writer);
ResponseUtils.ensureNoCacheHeader(facesContext.getExternalContext());
if (LOG.isDebugEnabled()) {
for (Object o : page.getAttributes().entrySet()) {
Map.Entry entry = (Map.Entry) o;
LOG.debug("*** '" + entry.getKey() + "' -> '" + entry.getValue() + "'");
}
}
Application application = facesContext.getApplication();
ViewHandler viewHandler = application.getViewHandler();
String viewId = facesContext.getViewRoot().getViewId();
String formAction = viewHandler.getActionURL(facesContext, viewId);
formAction = facesContext.getExternalContext().encodeActionURL(formAction);
String contentType = writer.getContentTypeWithCharSet();
ResponseUtils.ensureContentTypeHeader(facesContext, contentType);
String title = (String) page.getAttributes().get(ATTR_LABEL);
String doctype = generateDoctype(page);
if (doctype != null) {
writer.write(doctype);
writer.write("\n");
}
writer.startElement(HtmlConstants.HTML, null);
writer.startElement(HtmlConstants.HEAD, null);
final boolean debugMode =
ClientProperties.getInstance(facesContext.getViewRoot()).isDebugMode();
//if (debugMode) {
writer.writeJavascript("var TbgHeadStart = new Date();");
//}
// meta
// this is needed, because websphere 6.0? ignores the setting of the content type on the response
writer.startElement(HtmlConstants.META, null);
writer.writeAttribute("http-equiv", "Content-Type", false);
writer.writeAttribute("content", contentType, false);
writer.endElement(HtmlConstants.META);
// title
writer.startElement(HtmlConstants.TITLE, null);
writer.writeText(title != null ? title : "");
writer.endElement(HtmlConstants.TITLE);
// style files
for (String styleFile : page.getStyleFiles()) {
List<String> styles = ResourceManagerUtil.getStyles(facesContext, styleFile);
for (String styleString : styles) {
if (styleString.length() > 0) {
writer.startElement(HtmlConstants.LINK, null);
writer.writeAttribute(HtmlAttributes.REL, "stylesheet", false);
writer.writeAttribute(HtmlAttributes.HREF, styleString, false);
// writer.writeAttribute(HtmlAttributes.MEDIA, "screen", false);
writer.writeAttribute(HtmlAttributes.TYPE, "text/css", false);
writer.endElement(HtmlConstants.LINK);
}
}
}
String icon = page.getApplicationIcon();
if (icon != null) {
// XXX unify with image renderer
if (ResourceManagerUtil.isAbsoluteResource(icon)) {
// absolute Path to image : nothing to do
} else {
icon = ResourceManagerUtil.getImageWithPath(facesContext, icon);
}
writer.startElement(HtmlConstants.LINK, null);
if (icon.endsWith(".ico")) {
writer.writeAttribute(HtmlAttributes.REL, "shortcut icon", false);
writer.writeAttribute(HtmlAttributes.HREF, icon, false);
} else {
// XXX IE only supports ICO files for favicons
writer.writeAttribute(HtmlAttributes.REL, "icon", false);
writer.writeAttribute(HtmlAttributes.TYPE, MimeTypeUtils.getMimeTypeForFile(icon), false);
writer.writeAttribute(HtmlAttributes.HREF, icon, false);
}
writer.endElement(HtmlConstants.LINK);
}
// style sniplets
Set<String> styleBlocks = page.getStyleBlocks();
if (styleBlocks.size() > 0) {
writer.startElement(HtmlConstants.STYLE, null);
for (String cssBlock : styleBlocks) {
writer.write(cssBlock);
}
writer.endElement(HtmlConstants.STYLE);
}
// script files
List<String> scriptFiles = page.getScriptFiles();
// prototype.js and tobago.js needs to be first!
addScripts(writer, facesContext, "script/prototype.js");
addScripts(writer, facesContext, "script/tobago.js");
addScripts(writer, facesContext, "script/theme-config.js");
// remove prototype.js and tobago.js from list to prevent dublicated rendering of script tags
scriptFiles.remove("script/prototype.js");
scriptFiles.remove("script/tobago.js");
scriptFiles.remove("script/theme-config.js");
int clientLogSeverity = 2;
boolean hideClientLogging = true;
// true; hideClientLogging = false;
if (debugMode) {
String severity = (String) facesContext.getExternalContext().getRequestMap().get(CLIENT_DEBUG_SEVERITY);
LOG.info("get " + CLIENT_DEBUG_SEVERITY + " = " + severity);
if (severity != null) {
try {
int index = severity.indexOf(';');
if (index == -1) {
index = severity.length();
}
clientLogSeverity = Integer.parseInt(severity.substring(0, index));
} catch (NumberFormatException e) {/* ignore; use default*/ }
hideClientLogging = !severity.contains("show");
}
scriptFiles.add("script/effects.js");
scriptFiles.add("script/dragdrop.js");
scriptFiles.add("script/logging.js");
}
// render remaining script tags
for (String scriptFile : scriptFiles) {
addScripts(writer, facesContext, scriptFile);
}
// focus id
String focusId = page.getFocusId();
if (focusId != null) {
writer.writeJavascript("Tobago.focusId = '" + focusId + "';");
}
if (component.getFacets().containsKey(FACET_ACTION)) {
UIComponent command = component.getFacet(FACET_ACTION);
if (command != null && command.isRendered()) {
int duration = ComponentUtil.getIntAttribute(command, ATTR_DELAY, 100);
boolean transition = ComponentUtil.getBooleanAttribute(command, ATTR_TRANSITION);
String target = ComponentUtil.getStringAttribute(command, ATTR_TARGET);
String action;
if (target != null) {
action = "Tobago.submitAction2(this, '" + command.getClientId(facesContext) + "', "
+ transition + ", '" + target + "')";
} else {
action = "Tobago.submitAction2(this, '"+ command.getClientId(facesContext) + "', "
+ transition + ", null)";
}
page.getOnloadScripts().add("setTimeout(\"" + action + "\", " + duration + ");\n");
}
}
if (component.getFacets().containsKey(FACET_RESIZE_ACTION)) {
UIComponent facet = component.getFacet(FACET_RESIZE_ACTION);
UIComponent command = null;
if (facet instanceof UICommand) {
command = facet;
} else if (facet instanceof UIForm && facet.getChildCount() == 1) {
command = (UIComponent) facet.getChildren().get(0);
}
if (command != null && command.isRendered()) {
writer.writeJavascript("Tobago.resizeActionId = '" + command.getClientId(facesContext) + "';");
}
}
StringBuilder script = new StringBuilder(128);
// onload script
writeEventFunction(script, page.getOnloadScripts(), "load", false);
// onunload script
writeEventFunction(script, page.getOnunloadScripts(), "unload", false);
// onexit script
writeEventFunction(script, page.getOnexitScripts(), "exit", false);
writeEventFunction(script, page.getOnsubmitScripts(), "submit", true);
int debugCounter = 0;
for (String scriptBlock : page.getScriptBlocks()) {
if (LOG.isDebugEnabled()) {
LOG.debug("write scriptblock " + ++debugCounter + " :\n" + scriptBlock);
}
script.append(scriptBlock);
script.append('\n');
}
writer.writeJavascript(script.toString());
String clientId = page.getClientId(facesContext);
String defaultActionId = page.getDefaultActionId() != null ? page.getDefaultActionId() : "";
writer.endElement(HtmlConstants.HEAD);
writer.startElement(HtmlConstants.BODY, page);
writer.writeAttribute(HtmlAttributes.ONLOAD, "Tobago.init('" + clientId + "');", false);
// writer.writeAttribute("onunload", "Tobago.onexit();", null);
//this ist for ie to prevent scrollbars where none are needed
writer.writeAttribute(HtmlAttributes.SCROLL, "auto", false);
writer.writeClassAttribute();
writer.writeIdAttribute(clientId);
StringBuilder images = new StringBuilder(256);
images.append("Tobago.pngFixBlankImage = '");
images.append(ResourceManagerUtil.getImageWithPath(facesContext, "image/blank.gif"));
images.append("';\n");
images.append("Tobago.OVERLAY_BACKGROUND = '");
images.append(ResourceManagerUtil.getImageWithPath(facesContext, "image/tobago-overlay-background.png"));
images.append("';\n");
images.append("Tobago.OVERLAY_WAIT = '");
images.append(ResourceManagerUtil.getImageWithPath(facesContext, "image/tobago-overlay-wait.gif"));
images.append("';\n");
writer.writeJavascript(images.toString());
if (debugMode) {
final String[] jsFiles = new String[]{
"script/effects.js",
"script/dragdrop.js",
"script/logging.js"
};
final String[] jsCommand = new String[]{"new LOG.LogArea({hide: " + hideClientLogging + "});"};
HtmlRendererUtil.writeScriptLoader(facesContext, jsFiles, jsCommand);
}
//if (debugMode) {
writer.writeJavascript("TbgTimer.startBody = new Date();");
//}
writer.startElement(HtmlConstants.FORM, page);
writer.writeNameAttribute(
clientId + SUBCOMPONENT_SEP + "form");
writer.writeAttribute(HtmlAttributes.ACTION, formAction, true);
writer.writeIdAttribute(page.getFormId(facesContext));
writer.writeAttribute(HtmlAttributes.METHOD, getMethod(page), false);
String enctype = (String) facesContext.getExternalContext().getRequestMap().get(UIPage.ENCTYPE_KEY);
if (enctype != null) {
writer.writeAttribute(HtmlAttributes.ENCTYPE, enctype, false);
} else {
writer.writeAttributeFromComponent(HtmlAttributes.ENCTYPE, ATTR_ENCTYPE);
}
// TODO: enable configuration of 'accept-charset'
writer.writeAttribute(HtmlAttributes.ACCEPT_CHARSET, FORM_ACCEPT_CHARSET, false);
writer.startElement(HtmlConstants.INPUT, null);
writer.writeAttribute(HtmlAttributes.TYPE, "hidden", false);
writer.writeNameAttribute(clientId + SUBCOMPONENT_SEP + "form-action");
writer.writeIdAttribute(clientId + SUBCOMPONENT_SEP + "form-action");
writer.writeAttribute(HtmlAttributes.VALUE, defaultActionId, true);
writer.endElement(HtmlConstants.INPUT);
writer.startElement(HtmlConstants.INPUT, null);
writer.writeAttribute(HtmlAttributes.TYPE, "hidden", false);
writer.writeNameAttribute(clientId + SUBCOMPONENT_SEP + "context-path");
writer.writeIdAttribute(clientId + SUBCOMPONENT_SEP + "context-path");
writer.writeAttribute(HtmlAttributes.VALUE, facesContext.getExternalContext().getRequestContextPath(), true);
writer.endElement(HtmlConstants.INPUT);
writer.startElement(HtmlConstants.INPUT, null);
writer.writeAttribute(HtmlAttributes.TYPE, "hidden", false);
writer.writeNameAttribute(clientId + SUBCOMPONENT_SEP + "action-position");
writer.writeIdAttribute(clientId + SUBCOMPONENT_SEP + "action-position");
writer.endElement(HtmlConstants.INPUT);
if (debugMode) {
writer.startElement(HtmlConstants.INPUT, null);
writer.writeAttribute(HtmlAttributes.VALUE, clientLogSeverity);
writer.writeAttribute(HtmlAttributes.ID, clientId + SUBCOMPONENT_SEP + "clientSeverity", false);
writer.writeAttribute(HtmlAttributes.NAME, clientId + SUBCOMPONENT_SEP + "clientSeverity", false);
writer.writeAttribute(HtmlAttributes.TYPE, "hidden", false);
writer.endElement(HtmlConstants.INPUT);
}
if (component.getFacet("backButtonDetector") != null) {
UIComponent hidden = component.getFacet("backButtonDetector");
RenderUtil.encode(facesContext, hidden);
}
String lastFocusId = (String) component.getAttributes().get(LAST_FOCUS_ID);
if (lastFocusId != null) {
writer.writeJavascript("Tobago.lastFocusId = '" + lastFocusId + "';");