/* * � Copyright IBM Corp. 2010, 2013 * * Licensed 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 com.ibm.xsp.extlib.renderkit.html_extended.layout; import java.io.IOException; import java.util.List; import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; import javax.faces.context.ResponseWriter; import com.ibm.commons.util.StringUtil; import com.ibm.xsp.component.UICallback; import com.ibm.xsp.component.xp.XspEventHandler; import com.ibm.xsp.extlib.component.layout.ApplicationConfiguration; import com.ibm.xsp.extlib.component.layout.UIApplicationLayout; import com.ibm.xsp.extlib.component.layout.impl.BasicApplicationConfigurationImpl; import com.ibm.xsp.extlib.component.layout.impl.SearchBar; import com.ibm.xsp.extlib.renderkit.html_extended.FacesRendererEx; import com.ibm.xsp.extlib.renderkit.html_extended.outline.tree.AbstractTreeRenderer; import com.ibm.xsp.extlib.renderkit.html_extended.outline.tree.ComboBoxRenderer; import com.ibm.xsp.extlib.tree.ITree; import com.ibm.xsp.extlib.tree.impl.TreeImpl; import com.ibm.xsp.extlib.util.ExtLibUtil; import com.ibm.xsp.extlib.util.ThemeUtil; import com.ibm.xsp.renderkit.html_basic.HtmlRendererUtil; import com.ibm.xsp.util.FacesUtil; import com.ibm.xsp.util.HtmlUtil; import com.ibm.xsp.util.JSUtil; import com.ibm.xsp.util.JavaScriptUtil; import com.ibm.xsp.util.TypedUtil; /** * Abstract application layout renderer. * * @author priand */ public class AbstractApplicationLayoutRenderer extends FacesRendererEx { // ========================================================================== // Rendering Properties // ========================================================================== protected static final int PROP_BLANKIMG = 1; // Main Frame protected static final int PROP_MAINFRAMETAG = 10; protected static final int PROP_MAINFRAMECLASS = 11; protected static final int PROP_MAINFRAMESTYLE = 12; // Application banner protected static final int PROP_BANNERTAG = 20; protected static final int PROP_BANNERCLASS = 21; protected static final int PROP_BANNERSTYLE = 23; protected static final int PROP_BANNERROLE = 24; protected static final int PROP_BANNERINNER1CLASS = 25; protected static final int PROP_BANNERINNER2CLASS = 26; protected static final int PROP_BANNERLINKALT = 27; protected static final int PROP_BANNERLINKACCESSKEY = 28; protected static final int PROP_BANNERLINKHREF = 29; protected static final int PROP_BANNERLINKCLASS = 30; protected static final int PROP_APPLICATIONLINKSRENDERER = 110; protected static final int PROP_PRODUCTLOGO = 111; protected static final int PROP_PRODUCTLOGOCLASS = 112; protected static final int PROP_PRODUCTLOGOSTYLE = 113; protected static final int PROP_PRODUCTLOGOALT = 114; protected static final int PROP_PRODUCTLOGOWIDTH = 115; protected static final int PROP_PRODUCTLOGOHEIGHT = 116; // Utility banner protected static final int PROP_UTILITYLINKSRENDERER = 120; // Title bar protected static final int PROP_TITLEBARLINKSRENDERER = 130; protected static final int PROP_TITLEBARTAG = 131; protected static final int PROP_TITLEBARCLASS = 132; protected static final int PROP_TITLEBARTRAILINGCORNERCLASS = 133; protected static final int PROP_TITLEBARINNERCLASS = 134; protected static final int PROP_TITLEBARNAVTAG = 135; protected static final int PROP_TITLEBARNAVARIALABEL = 136; protected static final int PROP_TITLEBARNAVROLE = 137; protected static final int PROP_TITLEBARNAMECLASS = 138; // Place bar protected static final int PROP_PLACEBARLINKSRENDERER = 140; protected static final int PROP_PLACEBARCLASS = 141; protected static final int PROP_PLACEBARTRAILINGCORNERCLASS = 142; protected static final int PROP_PLACEBARINNERCLASS = 143; protected static final int PROP_PLACEBARNAMETAG = 250; protected static final int PROP_PLACEBARNAMESTYLE = 251; protected static final int PROP_PLACEBARNAMECLASS = 252; // Search bar options protected static final int PROP_SEARCHBAROPTIONSRENDERER = 145; protected static final int PROP_SEARCHBARCLASS = 146; protected static final int PROP_SEARCHBARROLE = 147; /** * Search Bar Table Layout, int option controlling use a table * for the search bar layout. One of * <ul> * <li>Mode 1 - always use table layout, with different cells * for scope options, text box, and button.</li> * <li>Mode 2 - only use table layout when search scope present, * otherwise no containers around the different search parts. * When use table layout only use 2 cells - one for scope options, * the other for both the text box and the button. * </li> * <li>Mode 3 - never use table layout, no containers * around the different parts of the search.</li> * <ul> */ protected static final int PROP_SEARCHBARTABLELAYOUT = 200; protected static final int PROP_SEARCHBARTABLECLASS = 201; protected static final int PROP_SEARCHBARTABLECELLSPACING = 202; protected static final int PROP_SEARCHBARTABLEROLE = 203; protected static final int PROP_SEARCHBOXCLASS = 204; protected static final int PROP_SEARCHBOXSTYLE = 205; protected static final int PROP_SEARCHBOXINACTIVETEXT = 206; // Search Button Outer Tag, usually "span" or null. protected static final int PROP_SEARCHBUTTONOUTERTAG = 207; // Search Button Outer Class. protected static final int PROP_SEARCHBUTTONOUTERCLASS = 208; // Search Button Outer Title. protected static final int PROP_SEARCHBUTTONOUTERTITLE = 209; // Search Button Use Link protected static final int PROP_SEARCHBUTTONUSELINK = 210; // Search Button Class protected static final int PROP_SEARCHBUTTONCLASS = 211; // Search Button Alt protected static final int PROP_SEARCHBUTTONALT = 212; // Search Input Accessibility Title protected static final int PROP_SEARCHINPUTTITLE = 213; // Search Options Accessibility Title protected static final int PROP_SEARCHSCOPETITLE = 214; // Search Options and Keywords Accessibility Legend protected static final int PROP_SEARCHLEGEND = 215; // main content protected static final int PROP_MAINAREACLASS = 180; protected static final int PROP_COLUMNFIRSTCLASS = 181; protected static final int PROP_COLUMNLASTTAG = 182; protected static final int PROP_COLUMNLASTCLASS = 183; // Main Content Anchor ID protected static final int PROP_MAINCONTENTANCHORID = 185; protected static final int PROP_MAINCONTENTANCHORNAME = 186; protected static final int PROP_MAINCONTENTCLASS = 187; protected static final int PROP_MAINCONTENTROLE = 188; // Footer protected static final int PROP_FOOTERLINKSRENDERER = 150; protected static final int PROP_FOOTERTAG = 151; protected static final int PROP_FOOTERCLASS = 152; protected static final int PROP_FOOTERROLE = 153; // Accessibility summary protected static final int PROP_FOOTERLINKSSUMMARY = 154; // Legal protected static final int PROP_LEGALLOGO = 161; protected static final int PROP_LEGALLOGOCLASS = 162; protected static final int PROP_LEGALLOGOSTYLE = 162; protected static final int PROP_LEGALLOGOALT = 164; protected static final int PROP_LEGALLOGOWIDTH = 165; protected static final int PROP_LEGALLOGOHEIGHT = 166; protected static final int PROP_LEGALTABLECLASS = 167; protected static final int PROP_LEGALTABLECELLSPACING = 168; protected static final int PROP_LEGALTABLEROLE = 169; protected static final int PROP_LEGALTEXTCLASS = 170; @Override protected Object getProperty(int prop) { { // translating some extra strings that are unused here in the extlib.control plugin, // but are used in the other themes - e.g. the bootstrap and oneui FormTableRenderer. String str = ""; str = "Title bar"; // $NLS-AbstractApplicationLayoutRenderer.Titlebar-1$ str = "Title bar tabs"; // $NLS-AbstractApplicationLayoutRenderer.Titlebartabs-1$ str = "Place bar"; // $NLS-AbstractApplicationLayoutRenderer.Placebar-1$ str = "Place bar tabs"; // $NLS-AbstractApplicationLayoutRenderer.Placebartabs-1$ str = "Footer links"; // $NLS-AbstractApplicationLayoutRenderer.Footerlinks-1$ str = "Legal footer"; // $NLS-AbstractApplicationLayoutRenderer.Legalfooter-1$ // end xe:applicationLayout strings str.getClass(); // prevent unused variable warning }// end translating extra string return null; } // ================================================================ // Main Frame // ================================================================ protected void writeMainFrame(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration) throws IOException { // Start the mast header if(null != configuration && configuration.isMastHeader()){ writeMastHeader(context, w, c, configuration); } // Start the main frame String tag = (String)getProperty(PROP_MAINFRAMETAG); w.startElement(tag,c); String style = (String)getProperty(PROP_MAINFRAMESTYLE); if(StringUtil.isNotEmpty(style)) { w.writeAttribute("style",style,null); // $NON-NLS-1$ } String styleClass = (String)getProperty(PROP_MAINFRAMECLASS); if(StringUtil.isNotEmpty(styleClass)) { w.writeAttribute("class",styleClass,null); // $NON-NLS-1$ } if( HtmlUtil.isUserId(c.getId()) ){ w.writeAttribute("id",c.getClientId(context),null); // $NON-NLS-1$ } newLine(w); if(configuration!=null) { // Start the banner if(configuration.isBanner()) { writeBanner(context, w, c, configuration); } // Start the title bar if(configuration.isTitleBar()) { writeTitleBar(context, w, c, configuration); } // Start the place bar if(configuration.isPlaceBar()) { writePlaceBar(context, w, c, configuration); } // Start the main content writeMainContent(context, w, c, configuration); // Start the footer if(configuration.isFooter()) { writeFooter(context, w, c, configuration); } // Start the legal if(configuration.isLegal()) { writeLegal(context, w, c, configuration); } } // Close the main frame w.endElement(tag); newLine(w); // Start the mast footer if(null != configuration && configuration.isMastFooter()){ writeMastFooter(context, w, c, configuration); } } // ================================================================ // Mast Header // ================================================================ protected void writeMastHeader(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration) throws IOException { UIComponent mastHeader = c.getMastHeader(); if(!isEmptyComponent(mastHeader)) { if(DEBUG) { w.writeComment("Start Mast Header"); // $NON-NLS-1$ newLine(w); } FacesUtil.renderComponent(context, mastHeader); if(DEBUG) { w.writeComment("End Mast Header"); // $NON-NLS-1$ newLine(w); } } } // ================================================================ // Mast Footer // ================================================================ protected void writeMastFooter(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration) throws IOException { UIComponent mastFooter = c.getMastFooter(); if(!isEmptyComponent(mastFooter)) { if(DEBUG) { w.writeComment("Start Mast Footer"); // $NON-NLS-1$ newLine(w); } FacesUtil.renderComponent(context, mastFooter); if(DEBUG) { w.writeComment("End Mast Footer"); // $NON-NLS-1$ newLine(w); } } } // ================================================================ // Banner // ================================================================ protected void writeBanner(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration) throws IOException { String tag = (String)getProperty(PROP_BANNERTAG); w.startElement(tag,c); String style = (String)getProperty(PROP_BANNERSTYLE); if(StringUtil.isNotEmpty(style)) { w.writeAttribute("style",style,null); // $NON-NLS-1$ } String styleClass = (String)getProperty(PROP_BANNERCLASS); if(StringUtil.isNotEmpty(styleClass)) { w.writeAttribute("class",styleClass,null); // $NON-NLS-1$ } String role = (String)getProperty(PROP_BANNERROLE); if(StringUtil.isNotEmpty(role)) { w.writeAttribute("role",role,null); // $NON-NLS-1$ } newLine(w); w.startElement("div",c); // $NON-NLS-1$ String styleClass1 = (String)getProperty(PROP_BANNERINNER1CLASS); if(StringUtil.isNotEmpty(styleClass1)) { w.writeAttribute("class",styleClass1,null); // $NON-NLS-1$ } newLine(w); w.startElement("div",c); // $NON-NLS-1$ String styleClass2 = (String)getProperty(PROP_BANNERINNER2CLASS); if(StringUtil.isNotEmpty(styleClass2)) { w.writeAttribute("class",styleClass2,null); // $NON-NLS-1$ } newLine(w); writeBannerContent(context, w, c, configuration); // Close the banner w.endElement("div"); newLine(w,"lotusInner"); // $NON-NLS-1$ $NON-NLS-2$ w.endElement("div"); newLine(w,"lotusRightCorner"); // $NON-NLS-1$ $NON-NLS-2$ w.endElement(tag); newLine(w,"lotusBanner"); // $NON-NLS-1$ } protected void writeBannerContent(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration) throws IOException { if(DEBUG) { w.writeComment("Start Banner"); // $NON-NLS-1$ newLine(w); } //TWET97XJZA: Unnecessary now. Replaced by role='main' on lotusContent div //writeBannerLink(context, w, c, configuration); writeBannerProductlogo(context, w, c, configuration); newLine(w); writeBannerUtilityLinks(context, w, c, configuration); newLine(w); writeBannerApplicationLinks(context, w, c, configuration); newLine(w); if(DEBUG) { w.writeComment("End Banner"); // $NON-NLS-1$ newLine(w); } } protected void writeBannerLink(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration) throws IOException { w.startElement("a",c); String href = (String) getProperty(PROP_BANNERLINKHREF); if( null == href || '#' != href.charAt(0) ){ href="#"; //$NON-NLS-1$ } w.writeAttribute("href",href,null); // $NON-NLS-1$ String accesskey = (String) getProperty(PROP_BANNERLINKACCESSKEY); if( null != accesskey ){ w.writeAttribute("accesskey", accesskey, null); // $NON-NLS-1$ } String styleClass = (String) getProperty(PROP_BANNERLINKCLASS); if( StringUtil.isNotEmpty(styleClass) ){ w.writeAttribute("class",styleClass,null); // $NON-NLS-1$ } w.startElement("img",c); // $NON-NLS-1$ String bgif = (String)getProperty(PROP_BLANKIMG); if(StringUtil.isNotEmpty(bgif)) { w.writeURIAttribute("src",HtmlRendererUtil.getImageURL(context,bgif),null); // $NON-NLS-1$ } //TODO consider removing - don't think its used String alt = (String) getProperty(PROP_BANNERLINKALT); if( !isAltNotEmpty(alt) ){ alt = "Banner Link"; // // $NON-NLS-1$ } w.writeAttribute("alt",alt,null); // $NON-NLS-1$ w.endElement("img"); // $NON-NLS-1$ w.endElement("a"); // $NON-NLS-1$ } protected void writeBannerProductlogo(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration) throws IOException { w.startElement("span",c); // $NON-NLS-1$ String clazz = ExtLibUtil.concatStyleClasses((String)getProperty(PROP_PRODUCTLOGOCLASS),configuration.getProductLogoClass()); if(StringUtil.isNotEmpty(clazz)) { w.writeAttribute("class",clazz,null); // $NON-NLS-1$ } String style = ExtLibUtil.concatStyles((String)getProperty(PROP_PRODUCTLOGOSTYLE),configuration.getProductLogoStyle()); if(StringUtil.isNotEmpty(style)) { w.writeAttribute("style",style,null); // $NON-NLS-1$ } String logoImg = configuration.getProductLogo(); if(StringUtil.isEmpty(logoImg)) { logoImg = (String)getProperty(PROP_PRODUCTLOGO); } if(StringUtil.isNotEmpty(logoImg)) { String imgSrc = HtmlRendererUtil.getImageURL(context, logoImg); w.startElement("img",c); // $NON-NLS-1$ w.writeURIAttribute("src",imgSrc,null); // $NON-NLS-1$ String logoAlt = configuration.getProductLogoAlt(); if(StringUtil.isEmpty(logoAlt)) { logoAlt = (String)getProperty(PROP_PRODUCTLOGOALT); } if(!isAltNotEmpty(logoAlt)) { logoAlt = "Banner Product Logo"; // $NLS-AbstractApplicationLayoutRenderer.BannerProductLogo-1$ } w.writeAttribute("alt",logoAlt,null); // $NON-NLS-1$ String width = configuration.getProductLogoWidth(); if(StringUtil.isEmpty(width)) { width = (String)getProperty(PROP_PRODUCTLOGOWIDTH); } if(StringUtil.isNotEmpty(width)) { w.writeAttribute("width",width,null); // $NON-NLS-1$ } String height = configuration.getProductLogoHeight(); if(StringUtil.isEmpty(height)) { height = (String)getProperty(PROP_PRODUCTLOGOHEIGHT); } if(StringUtil.isNotEmpty(height)) { w.writeAttribute("height",height,null); // $NON-NLS-1$ } w.endElement("img"); // $NON-NLS-1$ } w.endElement("span"); // $NON-NLS-1$ } protected void writeBannerApplicationLinks(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration) throws IOException { ITree tree = TreeImpl.get(configuration.getBannerApplicationLinks()); if(tree!=null) { AbstractTreeRenderer renderer = (AbstractTreeRenderer)getProperty(PROP_APPLICATIONLINKSRENDERER); if(renderer!=null) { renderer.render(context, c, "al", tree, w); // $NON-NLS-1$ } } } protected void writeBannerUtilityLinks(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration) throws IOException { ITree tree = TreeImpl.get(configuration.getBannerUtilityLinks()); if(tree!=null) { AbstractTreeRenderer renderer = (AbstractTreeRenderer)getProperty(PROP_UTILITYLINKSRENDERER); if(renderer!=null) { renderer.render(context, c, "ul", tree, w); // $NON-NLS-1$ } } } // ================================================================ // Title Bar // ================================================================ protected void writeTitleBar(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration) throws IOException { // <div class="lotusTitleBar"> or <header class="lotusTitleBar"> String titleBarTag = (String)getProperty(PROP_TITLEBARTAG); String titleBarClass = null; String titleBarName = configuration.getTitleBarName(); if( StringUtil.isNotEmpty(titleBarTag) ){ w.startElement(titleBarTag,c); // $NON-NLS-1$ if( StringUtil.isNotEmpty(titleBarName)) { w.writeAttribute("role", "region", null); // $NON-NLS-1$ $NON-NLS-2$ String tbName_id = StringUtil.format("{0}_tbName", c.getClientId(context)); // $NON-NLS-1$ w.writeAttribute("aria-labelledby", tbName_id, null); // $NON-NLS-1$ } titleBarClass = (String)getProperty(PROP_TITLEBARCLASS); if( StringUtil.isNotEmpty(titleBarClass) ){ w.writeAttribute("class",titleBarClass,null); // $NON-NLS-1$ } newLine(w); } // <div class="lotusRightCorner"> w.startElement("div",c); // $NON-NLS-1$ String titleBarTrailingCornerClass = (String)getProperty(PROP_TITLEBARTRAILINGCORNERCLASS); if( StringUtil.isNotEmpty(titleBarTrailingCornerClass) ){ w.writeAttribute("class",titleBarTrailingCornerClass,null); // $NON-NLS-1$ } newLine(w); // <div class="lotusInner"> w.startElement("div",c); // $NON-NLS-1$ String titleBarInnerClass = (String)getProperty(PROP_TITLEBARINNERCLASS); if( StringUtil.isNotEmpty(titleBarInnerClass) ){ w.writeAttribute("class",titleBarInnerClass,null); // $NON-NLS-1$ } newLine(w); // (2012-05-22 updated to wrap the h2 tag as well as the tabs) // <div class="lotusTitleBarContent"> w.startElement("div", null); //$NON-NLS-1$ // TODO this is using a OneUI v3 style class in a OneUI v2 renderer w.writeAttribute("class", "lotusTitleBarContent", null); // $NON-NLS-1$ //$NON-NLS-2$ if( StringUtil.isNotEmpty(titleBarName)) { w.startElement("h2",c); //$NON-NLS-1$ String id = StringUtil.format("{0}_tbName", c.getClientId(context)); // $NON-NLS-1$ w.writeAttribute("id", id, null); // $NON-NLS-1$ String titleBarNameClass = (String)getProperty(PROP_TITLEBARNAMECLASS); if( StringUtil.isNotEmpty(titleBarNameClass) ){ w.writeAttribute("class",titleBarNameClass,null); // $NON-NLS-1$ } if(ThemeUtil.isOneUIVersionAtLeast(context, 2, 1)) { // We need this because we have <h2> under <form> // TODO hard-coded style should be in a .css file. w.writeAttribute("style","margin: 0",null); // $NON-NLS-1$ $NON-NLS-2$ } w.write(titleBarName); w.endElement("h2"); //$NON-NLS-1$ newLine(w); } writeTitleBarTabsArea(context, w, c, configuration); // </div> <!-- end lotusTitleBarContent --> w.endElement("div"); //$NON-NLS-1$ // And the search bar writeSearchBar(context, w, c, configuration); // Close the titlebar // </div> <!-- end lotusInner --> w.endElement("div"); newLine(w,titleBarInnerClass); // $NON-NLS-1$ // </div> <!-- end lotusRightCorner --> w.endElement("div"); newLine(w,titleBarTrailingCornerClass); // $NON-NLS-1$ // </div> <!-- end lotusTitleBar --> if( StringUtil.isNotEmpty(titleBarTag) ){ w.endElement(titleBarTag); newLine(w,titleBarClass); // $NON-NLS-1$ } } protected void writeTitleBarTabsArea(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration) throws IOException { // OneUIv3: <nav aria-label="Tabs navigation" role="navigation"> String titleBarNavTag = (String)getProperty(PROP_TITLEBARNAVTAG); if( StringUtil.isNotEmpty(titleBarNavTag) ){ w.startElement(titleBarNavTag, null); // TODO should this be using DIV instead of NAV? the OneUI sample has: //<!-- nav is an HTML5 element. Use div if you are using HTML4. --> //<nav role="navigation toolbar" aria-label="[Tabs navigation]"> //String titleBarNavAriaLabel = (String)getProperty(PROP_TITLEBARNAVARIALABEL); String titleBarNavAriaLabel = configuration.getTitleBarLabel(); if( StringUtil.isNotEmpty(titleBarNavAriaLabel) ){ w.writeAttribute("aria-label", titleBarNavAriaLabel, null); // $NON-NLS-1$ } String titleBarNavRole = (String)getProperty(PROP_TITLEBARNAVROLE); if( StringUtil.isNotEmpty(titleBarNavRole) ){ w.writeAttribute("role", titleBarNavRole, null); // $NON-NLS-1$ } newLine(w); } // Write the tabs writeTitleBarTabs(context, w, c, configuration); // OneUIv3: </nav> if( StringUtil.isNotEmpty(titleBarNavTag) ){ w.endElement(titleBarNavTag); newLine(w); } } protected void writeTitleBarTabs(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration) throws IOException { ITree tree = TreeImpl.get(configuration.getTitleBarTabs()); if(tree!=null) { AbstractTreeRenderer renderer = (AbstractTreeRenderer)getProperty(PROP_TITLEBARLINKSRENDERER); if(renderer!=null) { renderer.render(context, c, "tb", tree, w); // $NON-NLS-1$ } } } // ================================================================ // Search Bar (normally part of the title bar) // ================================================================ protected void writeSearchBar(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration) throws IOException { UIComponent cSearchBar = c.getSearchBar(); if(!isEmptyComponent(cSearchBar)) { if(DEBUG) { w.writeComment("Start SearchBar Facet"); // $NON-NLS-1$ newLine(w); } w.startElement("div",c); // $NON-NLS-1$ String searchBarClass = (String) getProperty(PROP_SEARCHBARCLASS); if( StringUtil.isNotEmpty(searchBarClass) ){ w.writeAttribute("class",searchBarClass,null); // $NON-NLS-1$ } String searchBarRole = (String) getProperty(PROP_SEARCHBARROLE); if( StringUtil.isNotEmpty(searchBarRole) ){ w.writeAttribute("role", searchBarRole, null); // $NON-NLS-1$ } FacesUtil.renderComponent(context, cSearchBar); w.endElement("div"); // $NON-NLS-1$ if(DEBUG) { w.writeComment("End SearchBar Facet"); // $NON-NLS-1$ newLine(w); } return; } SearchBar searchBar = configuration.getSearchBar(); if(searchBar!=null && searchBar.isRendered()) { if(DEBUG) { w.writeComment("Start Search Bar"); // $NON-NLS-1$ newLine(w); } w.startElement("div",c); // $NON-NLS-1$ String searchBarClass = (String) getProperty(PROP_SEARCHBARCLASS); if( StringUtil.isNotEmpty(searchBarClass) ){ w.writeAttribute("class",searchBarClass,null); // $NON-NLS-1$ } String searchBarRole = (String) getProperty(PROP_SEARCHBARROLE); if( StringUtil.isNotEmpty(searchBarRole) ){ w.writeAttribute("role", searchBarRole, null); // $NON-NLS-1$ } newLine(w); boolean searchOptions = false; ITree tree = TreeImpl.get(searchBar.getOptions()); if(tree!=null) { searchOptions = true; } boolean useTableLayout; boolean sameCellForSearchBoxAndButton; { Integer searchBarTableLayoutObj = (Integer)getProperty(PROP_SEARCHBARTABLELAYOUT); if( null != searchBarTableLayoutObj && 3/*never*/ == searchBarTableLayoutObj.intValue() ){ useTableLayout = false; sameCellForSearchBoxAndButton = false; }else if( null != searchBarTableLayoutObj && 2 /*when scope option*/ == searchBarTableLayoutObj.intValue() ){ useTableLayout = searchOptions; sameCellForSearchBoxAndButton = true; }else{ // default 1 - always useTableLayout = true; sameCellForSearchBoxAndButton = false; } } if( useTableLayout ){ w.startElement("table",c); // $NON-NLS-1$ String searchBarTableClass = (String) getProperty(PROP_SEARCHBARTABLECLASS); if( StringUtil.isNotEmpty(searchBarTableClass) ){ w.writeAttribute("class",searchBarTableClass,null); // $NON-NLS-1$ } String searchBarTableCellSpacing = (String) getProperty(PROP_SEARCHBARTABLECELLSPACING); if( StringUtil.isNotEmpty(searchBarTableCellSpacing) ){ w.writeAttribute("cellspacing",searchBarTableCellSpacing,null); // $NON-NLS-1$ } String searchBarTableRole = (String) getProperty(PROP_SEARCHBARTABLEROLE); if( StringUtil.isEmpty(searchBarTableRole) ){ searchBarTableRole = "presentation"; // $NON-NLS-1$ } w.writeAttribute("role",searchBarTableRole,null); // $NON-NLS-1$ $NON-NLS-2$ newLine(w); w.startElement("tr",c); // $NON-NLS-1$ newLine(w); } // Write the search options if( searchOptions ){ if( useTableLayout ){ w.startElement("td",c); // $NON-NLS-1$ } w.startElement("fieldset",c); // $NON-NLS-1$ w.startElement("legend",c); // $NON-NLS-1$ w.writeAttribute("style","display:none",null); // $NON-NLS-1$ $NON-NLS-2$ String legend = searchBar.getLegend(); if(null == legend) { legend = (String) getProperty(PROP_SEARCHLEGEND); } if(legend != null) { w.writeText(legend,null); } w.endElement("legend"); // $NON-NLS-1$ writeSearchOptions(context, w, c, configuration, searchBar, tree); // if( useTableLayout ){ // w.endElement("td"); // $NON-NLS-1$ // newLine(w); // } } // Write the search box if( useTableLayout ){ if(!searchOptions) { w.startElement("td",c); // $NON-NLS-1$ } } writeSearchBox(context, w, c, configuration, searchBar, tree, searchOptions); if( searchOptions ){ w.endElement("fieldset"); // $NON-NLS-1$ } if( useTableLayout ){ if( ! sameCellForSearchBoxAndButton ){ w.endElement("td"); // $NON-NLS-1$ newLine(w); } } // Write the button if( useTableLayout ){ if( ! sameCellForSearchBoxAndButton ){ w.startElement("td",c); // $NON-NLS-1$ } } writeSearchButton(context, w, c, configuration, searchBar, tree); if( useTableLayout ){ w.endElement("td"); // $NON-NLS-1$ newLine(w); } if( useTableLayout ){ w.endElement("tr"); // $NON-NLS-1$ newLine(w); w.endElement("table"); // $NON-NLS-1$ newLine(w); } w.endElement("div"); // $NON-NLS-1$ newLine(w); if(DEBUG) { w.writeComment("End Search Bar"); // $NON-NLS-1$ newLine(w); } } } protected void writeSearchOptions(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration, SearchBar searchBar, ITree tree) throws IOException { AbstractTreeRenderer renderer = getSearchOptionsRenderer(context, w, c, configuration, searchBar); if(renderer!=null) { renderer.render(context, c, "so", tree, w); // $NON-NLS-1$ } } protected AbstractTreeRenderer getSearchOptionsRenderer(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration, SearchBar searchBar) { String cid = c.getClientId(context)+"_searchopt"; // $NON-NLS-1$ ComboBoxRenderer renderer = (ComboBoxRenderer)getProperty(PROP_SEARCHBAROPTIONSRENDERER); renderer.setClientId(cid); String scopeTitle = searchBar.getScopeTitle(); if(null == scopeTitle) { scopeTitle = (String) getProperty(PROP_SEARCHSCOPETITLE); } if (scopeTitle != null) { renderer.setAccTitle(scopeTitle); } return renderer; } protected void writeSearchBox(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration, SearchBar searchBar, ITree tree, boolean options) throws IOException { String cid = c.getClientId(context)+"_search"; // $NON-NLS-1$ w.startElement("input",c); // $NON-NLS-1$ w.writeAttribute("id",cid,null); // $NON-NLS-1$ w.writeAttribute("name",cid,null); // $NON-NLS-1$ String searchBoxClass = (String)getProperty(PROP_SEARCHBOXCLASS); if( StringUtil.isNotEmpty(searchBoxClass) ){ w.writeAttribute("class",searchBoxClass,null); // $NON-NLS-1$ } String searchBoxStyle = (String)getProperty(PROP_SEARCHBOXSTYLE); if( StringUtil.isNotEmpty(searchBoxStyle) ){ w.writeAttribute("style",searchBoxStyle,null); // $NON-NLS-1$ } w.writeAttribute("type","text",null); // $NON-NLS-1$ $NON-NLS-2$ String inputTitle = searchBar.getInputTitle(); if(null == inputTitle) { inputTitle = (String) getProperty(PROP_SEARCHINPUTTITLE); } if(inputTitle != null) { w.writeAttribute("title", inputTitle, null); // $NON-NLS-1$ } String inactiveText = searchBar.getInactiveText(); if( null == inactiveText ){ inactiveText = (String) getProperty(PROP_SEARCHBOXINACTIVETEXT); } if(inactiveText!=null) { w.writeAttribute("value",inactiveText,null); // $NON-NLS-1$ StringBuilder onFocusScript; { // onfocus="javascript:if(this.value=='Search...'){this.value=''}" onFocusScript = new StringBuilder("javascript:"); // $NON-NLS-1$ onFocusScript.append("if(this.value=="); // $NON-NLS-1$ JSUtil.addSingleQuoteString(onFocusScript, inactiveText); onFocusScript.append("){this.value="); // $NON-NLS-1$ JSUtil.addSingleQuoteString(onFocusScript, ""); onFocusScript.append("}"); // $NON-NLS-1$ } w.writeAttribute("onfocus",onFocusScript.toString(),null); // $NON-NLS-1$ StringBuilder onBlurScript; { // onblur="javascript:if(!this.value){this.value=\"Search...'}" onBlurScript = new StringBuilder("javascript:"); // $NON-NLS-1$ onBlurScript.append("if(!this.value){this.value="); // $NON-NLS-1$ JSUtil.addSingleQuoteString(onBlurScript, inactiveText); onBlurScript.append("}"); // $NON-NLS-1$ } w.writeAttribute("onblur",onBlurScript.toString(),null); // $NON-NLS-1$ } String submitSearch = "_xspAppSearchSubmit"; // $NON-NLS-1$ // TODO accessibility w.writeAttribute("onkeypress","javascript:var kc=event.keyCode?event.keyCode:event.which;if(kc==13){"+submitSearch+"(); return false}",null); // $NON-NLS-1$ $NON-NLS-2$ $NON-NLS-3$ w.endElement("input"); // $NON-NLS-1$ newLine(w); // "/search.xsp" String searchPageName = searchBar.getPageName(); if( StringUtil.isEmpty(searchPageName) ){ searchPageName = "/"; }else{ // append .xsp if needed searchPageName = ExtLibUtil.getPageXspUrl(searchPageName); } // "/apps/XPagesExt.nsf/search.xsp" String path = context.getApplication().getViewHandler().getResourceURL(context, searchPageName); path = context.getExternalContext().encodeActionURL(path); // Compose the script function w.startElement("script",c); // $NON-NLS-1$ if(DEBUG) { newLine(w); } StringBuilder sb = new StringBuilder(); sb.append("function "); // $NON-NLS-1$ sb.append(submitSearch); sb.append("(){"); if(DEBUG) { sb.append('\n'); } //sb.append("var val=XSP.getElementById('"); sb.append(cid); sb.append("').value;"); sb.append("var val=XSP.getFieldValue(XSP.getElementById("); //$NON-NLS-1$ JavaScriptUtil.addString(sb, cid); sb.append("));"); // $NON-NLS-1$ if(DEBUG) { sb.append('\n'); } if(options) { String oid = c.getClientId(context)+"_searchopt"; // $NON-NLS-1$ sb.append("var opt=XSP.getFieldValue(XSP.getElementById("); //$NON-NLS-1$ JavaScriptUtil.addString(sb, oid); sb.append("));"); // $NON-NLS-1$ if(DEBUG) { sb.append('\n'); } } sb.append("if(val){var loc="); // $NON-NLS-1$ String loc; String queryParam = searchBar.getQueryParam(); if(StringUtil.isEmpty(queryParam)) { queryParam = "search"; // $NON-NLS-1$ } loc = path +"?"+queryParam+"="; JavaScriptUtil.addString(sb,loc); sb.append("+encodeURIComponent(val)"); // $NON-NLS-1$ if(options) { sb.append("+"); String optionsParam = searchBar.getOptionsParam(); if(StringUtil.isEmpty(optionsParam)) { optionsParam = "option"; // $NON-NLS-1$ } JavaScriptUtil.addString(sb,"&"+optionsParam+"="); sb.append("+encodeURIComponent(opt)"); // $NON-NLS-1$ } sb.append(";"); if(DEBUG) { sb.append('\n'); } sb.append("window.location.href=loc;}}"); // $NON-NLS-1$ w.writeText(sb.toString(),null); if(DEBUG) { newLine(w); } w.endElement("script"); // $NON-NLS-1$ } protected void writeSearchButton(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration, SearchBar searchBar, ITree tree) throws IOException { String submitSearch = "_xspAppSearchSubmit"; // $NON-NLS-1$ String searchButtonOuterTag = (String)getProperty(PROP_SEARCHBUTTONOUTERTAG); if( StringUtil.isNotEmpty(searchButtonOuterTag) ){ w.startElement(searchButtonOuterTag,c); // $NON-NLS-1$ String searchButtonSpanClass = (String)getProperty(PROP_SEARCHBUTTONOUTERCLASS); if( StringUtil.isNotEmpty(searchButtonSpanClass) ){ w.writeAttribute("class",searchButtonSpanClass,null); // $NON-NLS-1$ } String searchButtonSpanTitle = (String)getProperty(PROP_SEARCHBUTTONOUTERTITLE); if( StringUtil.isNotEmpty(searchButtonSpanTitle) ){ w.writeAttribute("title",searchButtonSpanTitle,null); // $NON-NLS-1$ } } Boolean searchButtonUseLinkObj = (Boolean)getProperty(PROP_SEARCHBUTTONUSELINK); if( null == searchButtonUseLinkObj || ! searchButtonUseLinkObj.booleanValue() ){ // <input type="image" class="lotusSearchButton" alt="submit search" // onclick="javascript:_xspAppSearchSubmit();return false" // src="blank.gif" /> w.startElement("input", c); // $NON-NLS-1$ w.writeAttribute("type", "image", null); // $NON-NLS-1$ $NON-NLS-2$ String searchButtonClass = (String)getProperty(PROP_SEARCHBUTTONCLASS); if( null != searchButtonClass ){ w.writeAttribute("class",searchButtonClass,null); // $NON-NLS-1$ } // note, the input "alt" attribute is alternate text // for an image input (only for type="image") //TODO consider removing as not used String searchButtonAlt = (String)getProperty(PROP_SEARCHBUTTONALT); if( !isAltNotEmpty(searchButtonAlt) ){ searchButtonAlt = "Search"; // $NLS-AbstractApplicationLayoutRenderer.Search.1-1$ } w.writeAttribute("alt",searchButtonAlt,null); // $NON-NLS-1$ w.writeAttribute("onclick","javascript:"+submitSearch+"(); return false;",null); // $NON-NLS-1$ $NON-NLS-2$ $NON-NLS-3$ // note, the input "src" attribute is the URL to an image // to display as a submit button (only for type="image") String bgif = (String)getProperty(PROP_BLANKIMG); if(StringUtil.isNotEmpty(bgif)) { w.writeURIAttribute("src",HtmlRendererUtil.getImageURL(context,bgif),null); // $NON-NLS-1$ } w.endElement("input"); // $NON-NLS-1$ }else{ // is search button use link /* The normal input captures the 'enter key' in the page - Use a link instead */ // <a class="lotusSearchButton" onclick="javascript:_xspAppSearchSubmit();return false"> // <img src="blank.gif" alt="submit search" /> // </a> w.startElement("a",c); // LHEY97CF6U - Control requires role button w.writeAttribute("role", "button", null); // $NON-NLS-1$ $NON-NLS-2$ String searchButtonClass = (String)getProperty(PROP_SEARCHBUTTONCLASS); if( null != searchButtonClass ){ w.writeAttribute("class",searchButtonClass,null); // $NON-NLS-1$ } w.writeAttribute("onclick","javascript:"+submitSearch+"(); return false;",null); // $NON-NLS-1$ $NON-NLS-2$ $NON-NLS-3$ w.startElement("img",c); // $NON-NLS-1$ String bgif = (String)getProperty(PROP_BLANKIMG); if(StringUtil.isNotEmpty(bgif)) { w.writeURIAttribute("src",HtmlRendererUtil.getImageURL(context,bgif),null); // $NON-NLS-1$ } String searchButtonAlt = (String)getProperty(PROP_SEARCHBUTTONALT); if( !isAltNotEmpty(searchButtonAlt) ){ searchButtonAlt = "Search"; // $NLS-AbstractApplicationLayoutRenderer.Search.1-1$ } w.writeAttribute("alt",searchButtonAlt,null); // $NON-NLS-1$ w.endElement("img"); // $NON-NLS-1$ w.startElement("span", c); // $NON-NLS-1$ w.writeAttribute("class", "lotusAltText", null); // $NON-NLS-1$ $NON-NLS-2$ w.writeText("Search", null); // $NLS-AbstractApplicationLayoutRenderer.Search.1-1$ w.endElement("span"); // $NON-NLS-1$ w.endElement("a"); } if( StringUtil.isNotEmpty(searchButtonOuterTag) ){ w.endElement(searchButtonOuterTag); } } /** * @param alt * @return */ private boolean isAltNotEmpty(String alt) { // Note, do not use StringUtil.isNotEmpty for alt text // because for accessibility reasons there's a difference // between alt="" and no alt attribute set, // so we treat null and "" as different for alt. // TODO throughout the ExtLib verify that alt="" is supported // and that we're not using StringUtil.isNotEmpty nor !StringUtil.isEmpty return null != alt; } // ================================================================ // Place Bar // ================================================================ protected void writePlaceBar(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration) throws IOException { w.startElement("div",c); // $NON-NLS-1$ w.writeAttribute("role", "region", null); // $NON-NLS-1$ $NON-NLS-2$ String placeBarName = configuration.getPlaceBarName(); if(StringUtil.isNotEmpty(placeBarName)) { String placeBarNameTag = (String)getProperty(PROP_PLACEBARNAMETAG); boolean isPlaceBarTag = StringUtil.isNotEmpty(placeBarNameTag); if( isPlaceBarTag ){ String pbName_id = StringUtil.format("{0}_pbName", c.getClientId(context)); // $NON-NLS-1$ w.writeAttribute("aria-labelledby", pbName_id, null); // $NON-NLS-1$ } } String placeBarLabel = configuration.getPlaceBarLabel(); if (StringUtil.isNotEmpty(placeBarLabel)) { w.writeAttribute("aria-label", placeBarLabel, null); // $NON-NLS-1$ } String placeBarClass = (String)getProperty(PROP_PLACEBARCLASS); if( StringUtil.isNotEmpty(placeBarClass) ){ w.writeAttribute("class",placeBarClass,null); // $NON-NLS-1$ } newLine(w); w.startElement("div",c); // $NON-NLS-1$ String placeBarTrailingCornerClass = (String)getProperty(PROP_PLACEBARTRAILINGCORNERCLASS); if( StringUtil.isNotEmpty(placeBarTrailingCornerClass) ){ w.writeAttribute("class",placeBarTrailingCornerClass,null); // $NON-NLS-1$ } newLine(w); w.startElement("div",c); // $NON-NLS-1$ String placeBarInnerClass = (String)getProperty(PROP_PLACEBARINNERCLASS); if( StringUtil.isNotEmpty(placeBarInnerClass) ){ w.writeAttribute("class",placeBarInnerClass,null); // $NON-NLS-1$ } newLine(w); writePlaceBarName(context, w, c, configuration); UIComponent cPlaceBarName = c.getPlaceBarName(); if(!isEmptyComponent(cPlaceBarName)) { if(DEBUG) { w.writeComment("Start PlaceBarName Facet"); // $NON-NLS-1$ newLine(w); } FacesUtil.renderComponent(context, cPlaceBarName); } writePlaceBarActions(context, w, c, configuration); UIComponent cPlaceBarActions = c.getPlaceBarActions(); if(!isEmptyComponent(cPlaceBarActions)) { if(DEBUG) { w.writeComment("Start PlaceBarActions Facet"); // $NON-NLS-1$ newLine(w); } w.startElement("div",c); // $NON-NLS-1$ w.writeAttribute("class", "lotusBtnContainer", null); //$NON-NLS-1$ $NON-NLS-2$ FacesUtil.renderComponent(context, cPlaceBarActions); w.endElement("div"); // $NON-NLS-1$ } // Close the place bar w.endElement("div"); newLine(w,placeBarInnerClass); // $NON-NLS-1$ w.endElement("div"); newLine(w,placeBarTrailingCornerClass); // $NON-NLS-1$ w.endElement("div"); newLine(w,placeBarClass); // $NON-NLS-1$ } protected void writePlaceBarName(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration) throws IOException { String placeName = configuration.getPlaceBarName(); if(StringUtil.isNotEmpty(placeName)) { String placeBarNameTag = (String)getProperty(PROP_PLACEBARNAMETAG); boolean isPlaceBarTag = StringUtil.isNotEmpty(placeBarNameTag); if( isPlaceBarTag ){ w.startElement(placeBarNameTag,c); String id = StringUtil.format("{0}_pbName", c.getClientId(context)); // $NON-NLS-1$ w.writeAttribute("id", id, null); // $NON-NLS-1$ String placeBarNameStyle = (String)getProperty(PROP_PLACEBARNAMESTYLE); if( StringUtil.isNotEmpty(placeBarNameStyle) ){ w.writeAttribute("style",placeBarNameStyle,null); // $NON-NLS-1$ } String placeBarNameClass = (String)getProperty(PROP_PLACEBARNAMECLASS); if( StringUtil.isNotEmpty(placeBarNameClass) ){ w.writeAttribute("class", placeBarNameClass, null); //$NON-NLS-1$ } } w.writeText(placeName,null); if( isPlaceBarTag ){ w.endElement(placeBarNameTag); } newLine(w); } } protected void writePlaceBarActions(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration) throws IOException { ITree tree = TreeImpl.get(configuration.getPlaceBarActions()); if(tree!=null) { AbstractTreeRenderer renderer = (AbstractTreeRenderer)getProperty(PROP_PLACEBARLINKSRENDERER); if(renderer!=null) { renderer.render(context, c, "pb", tree, w); // $NON-NLS-1$ } } } // ================================================================ // Main content // ================================================================ protected void writeMainContent(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration) throws IOException { w.startElement("div",c); // $NON-NLS-1$ String mainAreaClass = (String)getProperty(PROP_MAINAREACLASS); if( StringUtil.isNotEmpty(mainAreaClass) ){ w.writeAttribute("class",mainAreaClass,null); // $NON-NLS-1$ } writeMainContentExtraAttributes(context, w, c, configuration); newLine(w); // Write the 3 columns writeLeftColumn(context, w, c, configuration); writeRightColumn(context, w, c, configuration); writeContentColumn(context, w, c, configuration); // Close the main content w.endElement("div"); newLine(w,mainAreaClass); // $NON-NLS-1$ } protected void writeMainContentExtraAttributes(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration) throws IOException { // do nothing here, available to override in subclasses } protected void writeLeftColumn(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration) throws IOException { UIComponent left = c.getLeftColumn(); if(!isEmptyComponent(left)) { if(DEBUG) { w.writeComment("Start Left Column"); // $NON-NLS-1$ newLine(w); } w.startElement("div",c); // $NON-NLS-1$ w.writeAttribute("role", "region", null); // $NON-NLS-1$ $NON-NLS-2$ String leftColumnLabel = configuration.getLeftColumnLabel(); if (StringUtil.isNotEmpty(leftColumnLabel)) { w.writeAttribute("aria-label", leftColumnLabel, null); // $NON-NLS-1$ } String columnFirstClass = (String)getProperty(PROP_COLUMNFIRSTCLASS); if( StringUtil.isNotEmpty(columnFirstClass) ){ w.writeAttribute("class",columnFirstClass,null); // $NON-NLS-1$ } writeLeftColumnExtraAttributes(context, w, c, configuration); FacesUtil.renderComponent(context, left); w.endElement("div"); // $NON-NLS-1$ newLine(w); if(DEBUG) { w.writeComment("End Left Column"); // $NON-NLS-1$ newLine(w); } } } protected void writeLeftColumnExtraAttributes(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration) throws IOException { // do nothing here, available to override in subclasses } protected void writeRightColumn(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration) throws IOException { UIComponent right = c.getRightColumn(); if(!isEmptyComponent(right)) { if(DEBUG) { w.writeComment("Start Right Column"); // $NON-NLS-1$ newLine(w); } String columnLastTag = (String)getProperty(PROP_COLUMNLASTTAG); if( StringUtil.isNotEmpty(columnLastTag) ){ w.startElement(columnLastTag,c); w.writeAttribute("role", "region", null); // $NON-NLS-1$ $NON-NLS-2$ String rightColumnLabel = configuration.getRightColumnLabel(); if (StringUtil.isNotEmpty(rightColumnLabel)) { w.writeAttribute("aria-label", rightColumnLabel, null); // $NON-NLS-1$ } String columnLastClass = (String)getProperty(PROP_COLUMNLASTCLASS); if(StringUtil.isNotEmpty(columnLastClass) ){ w.writeAttribute("class",columnLastClass,null); // $NON-NLS-1$ } writeRightColumnExtraAttributes(context, w, c, configuration); } FacesUtil.renderComponent(context, right); if( StringUtil.isNotEmpty(columnLastTag) ){ w.endElement(columnLastTag); newLine(w); } if(DEBUG) { w.writeComment("End Right Column"); // $NON-NLS-1$ newLine(w); } } } protected void writeRightColumnExtraAttributes(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration) throws IOException { // do nothing here, available to override in subclasses } protected void writeContentColumn(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration) throws IOException { if(!isEmptyChildren(c)) { if(DEBUG) { w.writeComment("Start Content Column"); // $NON-NLS-1$ newLine(w); } w.startElement("div",c); // $NON-NLS-1$ String mainContentClass = (String)getProperty(PROP_MAINCONTENTCLASS); if( StringUtil.isNotEmpty(mainContentClass) ){ w.writeAttribute("class",mainContentClass,null); // $NON-NLS-1$ } String mainContentRole = (String)getProperty(PROP_MAINCONTENTROLE); if( StringUtil.isNotEmpty(mainContentRole) ){ w.writeAttribute("role",mainContentRole,null); // $NON-NLS-1$ } writeContentColumnExtraAttributes(context, w, c, configuration); renderChildren(context, c); w.endElement("div"); // $NON-NLS-1$ newLine(w); if(DEBUG) { w.writeComment("End Content Column"); // $NON-NLS-1$ newLine(w); } } } protected void writeContentColumnExtraAttributes(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration) throws IOException { // do nothing here, available to override in subclasses } // ================================================================ // Footer // ================================================================ protected void writeFooter(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration) throws IOException { String footerTag = (String)getProperty(PROP_FOOTERTAG); boolean isFooterTag = StringUtil.isNotEmpty(footerTag); String footerClass = null; if( isFooterTag ){ w.startElement(footerTag,c); // $NON-NLS-1$ footerClass = (String)getProperty(PROP_FOOTERCLASS); if( StringUtil.isNotEmpty(footerClass) ){ w.writeAttribute("class",footerClass,null); // $NON-NLS-1$ } String footerRole = (String)getProperty(PROP_FOOTERROLE); if( StringUtil.isNotEmpty(footerRole) ){ w.writeAttribute("role", footerRole, null); // $NON-NLS-1$ } newLine(w); } writeFooterLinks(context, w, c, configuration); if( isFooterTag ){ w.endElement(footerTag); newLine(w,footerClass); } } protected void writeFooterLinks(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration) throws IOException { ITree tree = TreeImpl.get(configuration.getFooterLinks()); if(tree!=null) { AbstractTreeRenderer renderer = (AbstractTreeRenderer)getProperty(PROP_FOOTERLINKSRENDERER); if(renderer!=null) { renderer.render(context, c, "fl", tree, w); // $NON-NLS-1$ } } } // ================================================================ // Legal // ================================================================ protected void writeLegal(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration) throws IOException { w.startElement("table",c); // $NON-NLS-1$ String legalTableClass = (String)getProperty(PROP_LEGALTABLECLASS); if( StringUtil.isNotEmpty(legalTableClass) ){ w.writeAttribute("class",legalTableClass,null); // $NON-NLS-1$ } String legalTableCellSpacing = (String)getProperty(PROP_LEGALTABLECELLSPACING); if( StringUtil.isNotEmpty(legalTableCellSpacing) ){ w.writeAttribute("cellspacing",legalTableCellSpacing,null); // $NON-NLS-1$ } String legalTableRole = (String)getProperty(PROP_LEGALTABLEROLE); if( StringUtil.isEmpty(legalTableRole) ){ legalTableRole = "presentation"; // $NON-NLS-1$ } w.writeAttribute("role",legalTableRole,null); // $NON-NLS-1$ newLine(w); w.startElement("tr",c); newLine(w); // $NON-NLS-1$ writeLegalLogo(context, w, c, configuration); writeLegalText(context, w, c, configuration); w.endElement("tr"); newLine(w); // $NON-NLS-1$ w.endElement("table"); newLine(w); // $NON-NLS-1$ } protected void writeLegalLogo(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration) throws IOException { String logoImg = configuration.getLegalLogo(); if(StringUtil.isEmpty(logoImg)) { logoImg = (String)getProperty(PROP_LEGALLOGO); } if(StringUtil.isNotEmpty(logoImg)) { w.startElement("td",c); // $NON-NLS-1$ w.startElement("span",c); // $NON-NLS-1$ String clazz = ExtLibUtil.concatStyleClasses((String)getProperty(PROP_LEGALLOGOCLASS),configuration.getLegalLogoClass()); if(StringUtil.isNotEmpty(clazz)) { w.writeAttribute("class",clazz,null); // $NON-NLS-1$ } String style = ExtLibUtil.concatStyles((String)getProperty(PROP_LEGALLOGOSTYLE),configuration.getLegalLogoStyle()); if(StringUtil.isNotEmpty(style)) { w.writeAttribute("style",style,null); // $NON-NLS-1$ } String imgSrc = HtmlRendererUtil.getImageURL(context, logoImg); w.startElement("img",c); // $NON-NLS-1$ //w.writeAttribute("class","lotusIBMLogoFooter",null); w.writeURIAttribute("src",imgSrc,null); // $NON-NLS-1$ String logoAlt = configuration.getLegalLogoAlt(); if(!isAltNotEmpty(logoAlt)) { logoAlt = "Legal Logo"; // $NLS-AbstractApplicationLayoutRenderer.LegalLogo-1$ } w.writeAttribute("alt",logoAlt,null); // $NON-NLS-1$ String width = configuration.getLegalLogoWidth(); if(StringUtil.isEmpty(width)) { width = (String)getProperty(PROP_LEGALLOGOWIDTH); } if(StringUtil.isNotEmpty(width)) { w.writeAttribute("width",width,null); // $NON-NLS-1$ } String height = configuration.getLegalLogoHeight(); if(StringUtil.isEmpty(height)) { height = (String)getProperty(PROP_LEGALLOGOHEIGHT); } if(StringUtil.isNotEmpty(height)) { w.writeAttribute("height",height,null); // $NON-NLS-1$ } w.endElement("img"); // $NON-NLS-1$ w.endElement("span"); // $NON-NLS-1$ w.endElement("td"); // $NON-NLS-1$ } } protected void writeLegalText(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration) throws IOException { String legalText = configuration.getLegalText(); if(StringUtil.isNotEmpty(legalText)) { w.startElement("td",c); // $NON-NLS-1$ String legalTextClass = (String)getProperty(PROP_LEGALTEXTCLASS); if( StringUtil.isNotEmpty(legalTextClass) ){ w.writeAttribute("class",legalTextClass,null); // $NON-NLS-1$ } w.writeText(legalText,null); w.endElement("td"); // $NON-NLS-1$ } } // ================================================================== // JSF renderer methods @Override public void decode(FacesContext context, UIComponent component) { // Nothing to decode here... } @Override public void encodeBegin(FacesContext context, UIComponent component) throws IOException { ResponseWriter w = context.getResponseWriter(); UIApplicationLayout c = (UIApplicationLayout)component; if(!c.isRendered()) { return; } ApplicationConfiguration _conf = c.findConfiguration(); if(!(_conf instanceof BasicApplicationConfigurationImpl)) { return; } BasicApplicationConfigurationImpl configuration = (BasicApplicationConfigurationImpl)_conf; writeMainFrame(context, w, c, configuration); } @Override public void encodeEnd(FacesContext context, UIComponent component) throws IOException { // All is done is encode begin... } @Override public boolean getRendersChildren() { return true; } @Override public void encodeChildren(FacesContext context, UIComponent component) throws IOException { // Forget about the children, only the facets are rendered } // ================================================================== // Renderer utilities // we should not render the children as we don't want to render the // event hander (we directly generate calls to the fireEvent methods // rather than attaching event here. protected void renderChildren(FacesContext context, UIComponent component) throws IOException { // encode component and children int count = component.getChildCount(); if(count>0) { List<?> children = component.getChildren(); for (int i=0; i<count; i++) { UIComponent child = (UIComponent)children.get(i); if(isRenderChild(context, child)) { FacesUtil.renderComponent(context, child); } } } } protected boolean isRenderChild(FacesContext context, UIComponent child) throws IOException { // Only render the non event handler components if(!(child instanceof XspEventHandler)) { return true; } return false; } protected boolean isEmptyComponent(UIComponent c) { // If the component is null, then it is considered as empty if(c==null) { return true; } // If it is not rendered, then it is empty as well if(!c.isRendered()) { return true; } // Else, if it is a UICallback, then we should check it content // a UICallback without anything in it should be considered as // and empty component. if(c instanceof UICallback) { if(c.getChildCount()>0) { for(Object child: c.getChildren()) { if(!isEmptyComponent((UIComponent)child)) { return false; } } } if(c.getFacetCount()>0) { for(Object child: c.getFacets().values()) { if(!isEmptyComponent((UIComponent)child)) { return false; } } } return true; } // Ok, the component exists so it is not considered as empty return false; } protected boolean isEmptyChildren(UIComponent c) { if(c.getChildCount()>0) { // We should check the children one by one... for(UIComponent child: TypedUtil.getChildren(c)) { if(!isEmptyComponent(child)) { return false; } } } // No children, so the list is empty return true; } }