/* * � Copyright IBM Corp. 2014, 2015 * * 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.theme.bootstrap.renderkit.html.extlib.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.ExtLibRenderUtil; import com.ibm.xsp.extlib.util.ExtLibUtil; import com.ibm.xsp.renderkit.html_basic.HtmlRendererUtil; import com.ibm.xsp.theme.bootstrap.components.layout.ResponsiveApplicationConfiguration; import com.ibm.xsp.theme.bootstrap.renderkit.html.extlib.layout.tree.ApplicationLinksRenderer; import com.ibm.xsp.theme.bootstrap.renderkit.html.extlib.layout.tree.FooterLinksRenderer; import com.ibm.xsp.theme.bootstrap.renderkit.html.extlib.layout.tree.PlaceBarActionsRenderer; import com.ibm.xsp.theme.bootstrap.renderkit.html.extlib.layout.tree.SearchOptionsRenderer; import com.ibm.xsp.theme.bootstrap.renderkit.html.extlib.layout.tree.TitleBarTabsRenderer; import com.ibm.xsp.theme.bootstrap.renderkit.html.extlib.layout.tree.UtilityLinksRenderer; import com.ibm.xsp.theme.bootstrap.resources.Resources; import com.ibm.xsp.util.FacesUtil; import com.ibm.xsp.util.HtmlUtil; import com.ibm.xsp.util.JSUtil; import com.ibm.xsp.util.TypedUtil; public class ResponsiveAppLayoutRenderer extends FacesRendererEx { public static final boolean FLUID = true; public static final int PROP_COLUMN_TINY = 1; public static final int PROP_COLUMN_SMALL = 2; public static final int PROP_COLUMN_MEDIUM = 3; public static final int PROP_COLUMN_LARGE = 4; public static final int PROP_DEFAULT_MENU_LABEL = 10; public static final int PROP_DEFAULT_MENU_TARGET = 11; public static final int PROP_BANNER_FIXEDTOP_PADDING = 20; public static final int PROP_BANNER_FIXEDBOTTOM_PADDING = 21; public static final int PROP_BANNER_COLLAPSE_CLASS = 22; public static final int PROP_BANNER_ROLE = 24; public static final int PROP_BANNER_COLLAPSE_BUTTON_ARIALABEL = 25; public static final int PROP_TITLEBARTAG = 30; public static final int PROP_TITLEBARCLASS = 31; public static final int PROP_TITLEBARARIALABEL = 32; public static final int PROP_TITLEBARNAVTAG = 33; public static final int PROP_TITLEBARNAVARIALABEL = 34; public static final int PROP_TITLEBARNAVROLE = 35; public static final int PROP_TITLEBARNAVCLASS = 36; // Place bar public static final int PROP_PLACEBARNAMETAG = 40; public static final int PROP_PLACEBARCLASS = 41; public static final int PROP_PLACEBARARIALABEL = 42; public static final int PROP_PLACEBARACTIONSROLE = 43; public static final int PROP_PLACEBARACTIONSARIALABEL = 44; @Override protected Object getProperty(int prop) { switch (prop) { // Grid sizes case PROP_COLUMN_TINY: return "col-xs-"; // $NON-NLS-1$ case PROP_COLUMN_SMALL: return "col-sm-"; // $NON-NLS-1$ case PROP_COLUMN_MEDIUM: return "col-md-"; // $NON-NLS-1$ case PROP_COLUMN_LARGE: return "col-lg-"; // $NON-NLS-1$ // Collapsible Menu case PROP_DEFAULT_MENU_LABEL: return com.ibm.xsp.extlib.controls.ResourceHandler.getString("MenuRenderer.Menu"); // $NON-NLS-1$ case PROP_DEFAULT_MENU_TARGET: return ".applayout-column-left"; // $NON-NLS-1$ //Fixed banner padding case PROP_BANNER_FIXEDTOP_PADDING: return "body {padding-top:51px;} @media (min-width: 768px) {.applayout-main .sidebar{top:52px;bottom:0px;}}"; // $NON-NLS-1$ case PROP_BANNER_FIXEDBOTTOM_PADDING: return "body {padding-bottom:51px;} @media (min-width: 768px) {.applayout-main .sidebar{top:0px;bottom:52px;}}"; // $NON-NLS-1$ case PROP_BANNER_COLLAPSE_CLASS: return "navbar-collapse-target"; // $NON-NLS-1$ case PROP_BANNER_ROLE: return "banner"; // $NON-NLS-1$ //Title bar case PROP_TITLEBARTAG: return "div"; // $NON-NLS-1$ case PROP_TITLEBARCLASS: return "navbar navbar-static-top applayout-titlebar"; // $NON-NLS-1$ // "Title bar" case PROP_TITLEBARARIALABEL: return com.ibm.xsp.extlib.controls.ResourceHandler.getString("AbstractApplicationLayoutRenderer.Titlebar"); // $NON-NLS-1$ case PROP_TITLEBARNAVTAG: return "div"; // $NON-NLS-1$ case PROP_TITLEBARNAVCLASS: return "col-sm-12 col-md-12 applayout-titlebar-tabsarea"; // $NON-NLS-1$ // "Title bar tabs" case PROP_TITLEBARNAVARIALABEL: return com.ibm.xsp.extlib.controls.ResourceHandler.getString("AbstractApplicationLayoutRenderer.Titlebartabs"); // $NON-NLS-1$ case PROP_TITLEBARNAVROLE: return "navigation"; // $NON-NLS-1$ //Place bar case PROP_PLACEBARNAMETAG: return "h3"; // $NON-NLS-1$ case PROP_PLACEBARCLASS: return "navbar navbar-static-top applayout-placebar"; // $NON-NLS-1$ case PROP_PLACEBARARIALABEL: return com.ibm.xsp.extlib.controls.ResourceHandler.getString("AbstractApplicationLayoutRenderer.Placebar"); // $NON-NLS-1$ case PROP_PLACEBARACTIONSROLE: return "navigation"; // $NON-NLS-1$ case PROP_PLACEBARACTIONSARIALABEL: return com.ibm.xsp.extlib.controls.ResourceHandler.getString("AbstractApplicationLayoutRenderer.Placebartabs"); // $NON-NLS-1$ case PROP_BANNER_COLLAPSE_BUTTON_ARIALABEL: return "Toggle navigation menu"; // $NLS-NavbarRenderer.Togglenavigationmenu-1$ } return null; } protected String getColumnPrefix() { return (String)getProperty(PROP_COLUMN_MEDIUM); } public ResponsiveApplicationConfiguration asBootstrapConfig(BasicApplicationConfigurationImpl configuration) { if(configuration instanceof ResponsiveApplicationConfiguration) { return (ResponsiveApplicationConfiguration)configuration; } return null; } // ================================================================ // Main Frame // ================================================================ protected void writeMainFrame(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration) throws IOException { boolean invertedNavbar = false; String fixedNavbar = ResponsiveApplicationConfiguration.NAVBAR_UNFIXED_TOP; boolean collapseLeftColumn = false; String collapseLeftTarget = (String)getProperty(PROP_DEFAULT_MENU_TARGET); String collapsedLeftMenuLabel = (String)getProperty(PROP_DEFAULT_MENU_LABEL); String pageWidthClass = ""; ResponsiveApplicationConfiguration bc = asBootstrapConfig(configuration); if(bc!=null) { String configFixedNavbar = bc.getFixedNavbar(); String configLeftTarget = bc.getCollapseLeftTarget(); String configMenuLabel = bc.getCollapseLeftMenuLabel(); invertedNavbar = bc.isInvertedNavbar(); fixedNavbar = (configFixedNavbar != null ? configFixedNavbar : ResponsiveApplicationConfiguration.NAVBAR_UNFIXED_TOP); collapseLeftColumn = bc.isCollapseLeftColumn(); collapseLeftTarget = (configLeftTarget != null ? configLeftTarget : (String)getProperty(PROP_DEFAULT_MENU_TARGET)); collapsedLeftMenuLabel = (configMenuLabel != null ? configMenuLabel : (String)getProperty(PROP_DEFAULT_MENU_LABEL)); pageWidthClass = getContainerClass(bc); } //CSS required for fixed Banner if (!StringUtil.isEmpty(fixedNavbar)) { String navbarPadding = ""; boolean addStyle = false; if(fixedNavbar.equals(ResponsiveApplicationConfiguration.NAVBAR_FIXED_TOP)) { navbarPadding = (String)getProperty(PROP_BANNER_FIXEDTOP_PADDING); addStyle = true; }else if(fixedNavbar.equals(ResponsiveApplicationConfiguration.NAVBAR_FIXED_BOTTOM)) { navbarPadding = (String)getProperty(PROP_BANNER_FIXEDBOTTOM_PADDING); addStyle = true; } if(addStyle) { w.startElement("style", c); // $NON-NLS-1$ w.writeAttribute("type", "text/css", null); // $NON-NLS-1$ $NON-NLS-2$ w.writeText(navbarPadding, null); w.endElement("style"); // $NON-NLS-1$ } } // Start the mast header if (null != configuration && configuration.isMastHeader()) { writeMastHeader(context, w, c, configuration); } w.startElement("div", c); // $NON-NLS-1$ w.writeAttribute("class", "applayout-main", null); // $NON-NLS-1$ $NON-NLS-2$ 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, pageWidthClass, invertedNavbar, fixedNavbar); } // Start the title bar if (configuration.isTitleBar()) { writeTitleBar(context, w, c, configuration, pageWidthClass); } // Start the place bar if (configuration.isPlaceBar()) { writePlaceBar(context, w, c, configuration, pageWidthClass); } // Start the main content writeMainContent(context, w, c, configuration, pageWidthClass, collapseLeftColumn, collapseLeftTarget, collapsedLeftMenuLabel); // Start the footer if (configuration.isFooter()) { writeFooter(context, w, c, configuration, pageWidthClass); } // Start the legal if (configuration.isLegal()) { writeLegal(context, w, c, configuration, pageWidthClass); } } // Close the main frame w.endElement("div"); // $NON-NLS-1$ 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, String pageWidthClass, boolean navbarInverted, String navbarFixed) throws IOException { String navbarFixedClass = ""; if(!StringUtil.isEmpty(navbarFixed)){ if(navbarFixed.equals(ResponsiveApplicationConfiguration.NAVBAR_FIXED_TOP)) { navbarFixedClass = "navbar-fixed-top"; // $NON-NLS-1$ }else if(navbarFixed.equals(ResponsiveApplicationConfiguration.NAVBAR_FIXED_BOTTOM)) { navbarFixedClass = "navbar-fixed-bottom"; // $NON-NLS-1$ }else if(navbarFixed.equals(ResponsiveApplicationConfiguration.NAVBAR_UNFIXED_TOP)) { navbarFixedClass = "navbar-static-top"; // $NON-NLS-1$ } } w.startElement("div", c); // $NON-NLS-1$ String navClass = "navbar applayout-banner " + // $NON-NLS-1$ (navbarInverted ? "navbar-inverse " : "navbar-default ") + navbarFixedClass; // $NON-NLS-1$ $NON-NLS-2$ w.writeAttribute("class", navClass, null); // $NON-NLS-1$ w.writeAttribute("role", (String)getProperty(PROP_BANNER_ROLE), null); // $NON-NLS-1$ $NON-NLS-2$ //container div w.startElement("div",c); // $NON-NLS-1$ String bannerClass = ExtLibUtil.concatStyleClasses(pageWidthClass, "applayout-banner-container"); // $NON-NLS-1$ w.writeAttribute("class", bannerClass , null); // $NON-NLS-1$ writeBannerContent(context, w, c, configuration); w.endElement("div"); // $NON-NLS-1$ newLine(w, "container"); // $NON-NLS-1$ w.endElement("div"); // $NON-NLS-1$ newLine(w, "navbar"); // $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); } boolean hasChildren = c.getChildCount() > 0; ITree appLinks = TreeImpl.get(configuration.getBannerApplicationLinks()); ITree utilityLinks = TreeImpl.get(configuration.getBannerUtilityLinks()); boolean bannerHasContent = hasChildren || appLinks != null || utilityLinks != null; w.startElement("div", c); // $NON-NLS-1$ w.writeAttribute("class", "navbar-header", null); // $NON-NLS-1$ $NON-NLS-2$ if(bannerHasContent) { writeBannerLink(context, w, c, configuration); } newLine(w); writeBannerProductlogo(context, w, c, configuration); w.endElement("div"); // $NON-NLS-1$ w.startElement("div", c); // $NON-NLS-1$ w.writeAttribute("class", ExtLibUtil.concatStyleClasses((String)getProperty(PROP_BANNER_COLLAPSE_CLASS), "navbar-collapse collapse"), null); // $NON-NLS-1$ $NON-NLS-2$ newLine(w); writeBannerApplicationLinks(context, w, c, configuration); newLine(w); writeBannerUtilityLinks(context, w, c, configuration); newLine(w); w.endElement("div"); // $NON-NLS-1$ newLine(w, ""); // $NON-NLS-1$ 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("button", c); // $NON-NLS-1$ w.writeAttribute("type", "button", null); // $NON-NLS-1$ $NON-NLS-2$ w.writeAttribute("aria-label", (String)getProperty(PROP_BANNER_COLLAPSE_BUTTON_ARIALABEL), null); // $NON-NLS-1$ w.writeAttribute("class", "navbar-toggle", null); // $NON-NLS-1$ $NON-NLS-2$ w.writeAttribute("data-toggle", "collapse", null); // $NON-NLS-1$ $NON-NLS-2$ w.writeAttribute("data-target", "." + getProperty(PROP_BANNER_COLLAPSE_CLASS), null); // $NON-NLS-1$ w.startElement("span", c); // $NON-NLS-1$ w.writeAttribute("class", "sr-only", null); // $NON-NLS-1$ $NON-NLS-2$ w.writeText((String)getProperty(PROP_BANNER_COLLAPSE_BUTTON_ARIALABEL), null); // $NON-NLS-1$ w.endElement("span"); // $NON-NLS-1$ w.startElement("span", c); // $NON-NLS-1$ w.writeAttribute("class", "icon-bar", null); // $NON-NLS-1$ $NON-NLS-2$ w.endElement("span"); // $NON-NLS-1$ w.startElement("span", c); // $NON-NLS-1$ w.writeAttribute("class", "icon-bar", null); // $NON-NLS-1$ $NON-NLS-2$ w.endElement("span"); // $NON-NLS-1$ w.startElement("span", c); // $NON-NLS-1$ w.writeAttribute("class", "icon-bar", null); // $NON-NLS-1$ $NON-NLS-2$ w.endElement("span"); // $NON-NLS-1$ w.endElement("button"); // $NON-NLS-1$ } protected void writeBannerProductlogo(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration) throws IOException { w.startElement("div",c); // $NON-NLS-1$ String style = configuration.getProductLogoStyle(); if(StringUtil.isNotEmpty(style)) { w.writeAttribute("style",style,null); // $NON-NLS-1$ } String logoImg = configuration.getProductLogo(); String logoAlt = configuration.getProductLogoAlt(); if(StringUtil.isNotEmpty(logoImg)) { String clazz = ExtLibUtil.concatStyleClasses("navbar-brand-img", configuration.getProductLogoClass()); // $NON-NLS-1$ w.writeAttribute("class", clazz, null); // $NON-NLS-1$ String imgSrc = HtmlRendererUtil.getImageURL(context, logoImg); w.startElement("img",c); // $NON-NLS-1$ w.writeURIAttribute("src",imgSrc,null); // $NON-NLS-1$ if(!ExtLibRenderUtil.isAltPresent(logoAlt)) { logoAlt = com.ibm.xsp.extlib.controls.ResourceHandler.getString("AbstractApplicationLayoutRenderer.BannerProductLogo"); // $NON-NLS-1$ } w.writeAttribute("alt",logoAlt,null); // $NON-NLS-1$ String width = configuration.getProductLogoWidth(); if(StringUtil.isNotEmpty(width)) { w.writeAttribute("width",width,null); // $NON-NLS-1$ } String height = configuration.getProductLogoHeight(); if(StringUtil.isNotEmpty(height)) { w.writeAttribute("height",height,null); // $NON-NLS-1$ } w.endElement("img"); // $NON-NLS-1$ } else if ( StringUtil.isNotEmpty( logoAlt) ) { String clazz = ExtLibUtil.concatStyleClasses("navbar-brand-txt", configuration.getProductLogoClass()); // $NON-NLS-1$ w.writeAttribute("class", clazz, null); // $NON-NLS-1$ w.writeText(logoAlt, null); // $NON-NLS-1$ } w.endElement("div"); // $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 = new 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 = new 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, String pageWidthClass) throws IOException { ITree tree = TreeImpl.get(configuration.getTitleBarTabs()); SearchBar searchBar = configuration.getSearchBar(); UIComponent searchBarFacet = c.getSearchBar(); String titleBarName = configuration.getTitleBarName(); //If there is no titleBarName, seachbar or tabs to be displayed, dont render the titleBar if (StringUtil.isNotEmpty(titleBarName) || tree != null || (searchBar != null && searchBar.isRendered()) || null != searchBarFacet) { String titleBarTag = (String)getProperty(PROP_TITLEBARTAG); w.startElement(titleBarTag,c); // $NON-NLS-1$ w.writeAttribute("role", "region", null); // $NON-NLS-1$ $NON-NLS-2$ // Set A11y properties for the title bar String tbName_id = StringUtil.format("{0}_tbName", c.getClientId(context)); // $NON-NLS-1$ if( StringUtil.isNotEmpty(titleBarName) ) { // if titleBarName has been set = add aria-labelledby prop with id of titleBarName w.writeAttribute("aria-labelledby", tbName_id, null); // $NON-NLS-1$ } String titleBarLabel = configuration.getTitleBarLabel(); // if aria label has been set on title bar = add aria-label prop // if no aria label set, but titleBarName is set = add aria-label prop with titleBarName text value // if no aira label set, and no titleBarName set = add aria-label prop with default value String titleBarAriaLabel = (StringUtil.isNotEmpty(titleBarLabel) ? titleBarLabel : (StringUtil.isNotEmpty(titleBarName) ? "" : (String)getProperty(PROP_TITLEBARARIALABEL))); if( StringUtil.isNotEmpty(titleBarAriaLabel)) { w.writeAttribute("aria-label", titleBarAriaLabel, null); // $NON-NLS-1$ } //Check if the titlebar has tabs. If none, add bottom border String titleBarClass = (String)getProperty(PROP_TITLEBARCLASS); if(tree == null){ titleBarClass = ExtLibUtil.concatStyleClasses((String)getProperty(PROP_TITLEBARCLASS), "applayout-titlebar-border"); // $NON-NLS-1$ } if( StringUtil.isNotEmpty(titleBarClass) ){ w.writeAttribute("class",titleBarClass,null); // $NON-NLS-1$ } //container div w.startElement("div", c); // $NON-NLS-1$ String titleClass = ExtLibUtil.concatStyleClasses(pageWidthClass, "applayout-titlebar-inner"); // $NON-NLS-1$ w.writeAttribute("class", titleClass , null); // $NON-NLS-1$ writeSearchBar(context, w, c, configuration); if( StringUtil.isNotEmpty(titleBarName)) { w.startElement("h4",c); //$NON-NLS-1$ w.writeAttribute("id", tbName_id, null); // $NON-NLS-1$ if (tree != null) { w.writeAttribute("class","applayout-titlebar-name",null); // $NON-NLS-1$ $NON-NLS-2$ }else{ w.writeAttribute("class","applayout-titlebar-name applayout-titlebar-name-padding",null); // $NON-NLS-1$ $NON-NLS-2$ } w.writeAttribute("title",titleBarName,null); // $NON-NLS-1$ w.write(titleBarName); w.endElement("h4"); //$NON-NLS-1$ newLine(w); } writeTitleBarTabsArea(context, w, c, configuration); // Close the banner w.endElement("div"); // $NON-NLS-1$ w.endElement("div"); // $NON-NLS-1$ } } protected void writeTitleBarTabsArea(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration) throws IOException { ITree tree = TreeImpl.get(configuration.getTitleBarTabs()); if (tree != null) { AbstractTreeRenderer renderer = new TitleBarTabsRenderer(); if (renderer != null) { //Write containing div w.startElement((String)getProperty(PROP_TITLEBARNAVTAG), c); w.writeAttribute("class", (String)getProperty(PROP_TITLEBARNAVCLASS), null); // $NON-NLS-1$ String titleBarNavAriaLabel = (String)getProperty(PROP_TITLEBARNAVARIALABEL); 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$ } // Write the tabs writeTitleBarTabs(context, w, c, configuration, tree, renderer); w.endElement((String)getProperty(PROP_TITLEBARNAVTAG)); } } } protected void writeTitleBarTabs(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration, ITree tree, AbstractTreeRenderer renderer) throws IOException { 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$ w.writeAttribute("class","col-md-4 navbar-search navbar-right applayout-searchbar",null); // $NON-NLS-1$ $NON-NLS-2$ w.writeAttribute("role", "search", null); // $NON-NLS-1$ $NON-NLS-2$ 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$ w.writeAttribute("class","col-md-4 navbar-search navbar-right input-group applayout-searchbar",null); // $NON-NLS-1$ $NON-NLS-2$ w.writeAttribute("role", "search", null); // $NON-NLS-1$ $NON-NLS-2$ newLine(w); boolean searchOptions = false; ITree tree = TreeImpl.get(searchBar.getOptions()); if (tree != null) { searchOptions = true; } // Write the search options if (searchOptions) { writeSearchOptions(context, w, c, configuration, searchBar, tree); } // Write the search box writeSearchBox(context, w, c, configuration, searchBar, tree, searchOptions); writeSearchButton(context, w, c, configuration, searchBar, tree, searchOptions); 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) { w.startElement("div", c); // $NON-NLS-1$ w.writeAttribute("class","input-group-btn",null); // $NON-NLS-1$ $NON-NLS-2$ // Feels like a hack... w.writeAttribute("style","width: 30%",null); // $NON-NLS-1$ $NON-NLS-2$ newLine(w); renderer.render(context, c, "so", tree, w); // $NON-NLS-1$ w.endElement("div"); // $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 = new SearchOptionsRenderer(); renderer.setClientId(cid); String scopeTitle = searchBar.getScopeTitle(); if (null == scopeTitle) { scopeTitle = ""; } if (StringUtil.isNotEmpty(scopeTitle)) { 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$ w.writeAttribute("type", "text", null); // $NON-NLS-1$ $NON-NLS-2$ w.writeAttribute("class", "form-control search-query", null); // $NON-NLS-1$ $NON-NLS-2$ String inputTitle = searchBar.getInputTitle(); if (StringUtil.isNotEmpty(inputTitle)) { w.writeAttribute("title", inputTitle, null); // $NON-NLS-1$ } String inactiveText = searchBar.getInactiveText(); if (StringUtil.isNotEmpty(inactiveText)) { w.writeAttribute("placeHolder", inactiveText, null); // $NON-NLS-1$ } String submitSearch = "_xspAppSearchSubmit"; // $NON-NLS-1$ 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); } protected void writeSearchButton(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration, SearchBar searchBar, ITree tree, boolean searchOptions) throws IOException { String submitSearch = "_xspAppSearchSubmit"; // $NON-NLS-1$ w.startElement("div", c); // $NON-NLS-1$ w.writeAttribute("class","input-group-btn",null); // $NON-NLS-1$ $NON-NLS-2$ newLine(w); // Write the required script (done here because of Bootstrap 3 last-child selector on the input-group-btn) writeSearchScript(context, w, c, configuration, searchBar, tree, searchOptions); newLine(w); w.startElement("button",c); // $NON-NLS-1$ w.writeAttribute("class","btn btn-default applayout-searchbtn",null); // $NON-NLS-1$ $NON-NLS-2$ w.writeAttribute("onclick","javascript:"+submitSearch+"(); return false;",null); // $NON-NLS-1$ $NON-NLS-2$ $NON-NLS-3$ String searchLabel = com.ibm.xsp.extlib.controls.ResourceHandler.getString("AbstractApplicationLayoutRenderer.Search.1"); // $NON-NLS-1$ w.writeAttribute("aria-label", searchLabel,null); // $NON-NLS-1$ w.startElement("span",c); // $NON-NLS-1$ w.writeAttribute("aria-hidden","true",null); // $NON-NLS-1$ $NON-NLS-2$ w.writeAttribute("class", Resources.get().getIconClass("search"),null); // $NON-NLS-1$ $NON-NLS-2$ w.endElement("span"); // $NON-NLS-1$ w.endElement("button"); // $NON-NLS-1$ w.endElement("div"); // $NON-NLS-1$ } protected void writeSearchScript(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$ String submitSearch = "_xspAppSearchSubmit"; // $NON-NLS-1$ // "/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('"); sb.append(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('"); sb.append(oid); sb.append("'));"); // $NON-NLS-1$ if(DEBUG) { sb.append('\n'); } } sb.append("if(val){var loc='"); // $NON-NLS-1$ JSUtil.appendJavaScriptString(sb, path); sb.append("?"); String queryParam = searchBar.getQueryParam(); if(StringUtil.isEmpty(queryParam)) { queryParam = "search"; // $NON-NLS-1$ } JSUtil.appendJavaScriptString(sb, queryParam); sb.append("='+encodeURIComponent(val)"); // $NON-NLS-1$ if(options) { sb.append("+'&"); String optionsParam = searchBar.getOptionsParam(); if(StringUtil.isEmpty(optionsParam)) { optionsParam = "option"; // $NON-NLS-1$ } JSUtil.appendJavaScriptString(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$ } // ================================================================ // Place Bar // ================================================================ protected void writePlaceBar(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration, String pageWidthClass) throws IOException { w.startElement("div", c); // $NON-NLS-1$ w.writeAttribute("class", (String)getProperty(PROP_PLACEBARCLASS), null); // $NON-NLS-1$ $NON-NLS-2$ // Set A11y properties for the title bar w.writeAttribute("role", "region", null); // $NON-NLS-1$ $NON-NLS-2$ String placeBarName = configuration.getPlaceBarName(); if(StringUtil.isNotEmpty(placeBarName)) { // if titleBarName has been set = add aria-labelledby prop with id of titleBarName 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 aria label has been set on place bar = add aria-label prop // if no aria label set, but placeBarName is set = add aria-label prop with placeBarName value // if no aria label set, and no placeBarName set = add aria-label prop with default value String placeBarAriaLabel = (StringUtil.isNotEmpty(placeBarLabel) ? placeBarLabel : (StringUtil.isNotEmpty(placeBarName) ? "" : (String)getProperty(PROP_PLACEBARARIALABEL))); if (StringUtil.isNotEmpty(placeBarAriaLabel)) { w.writeAttribute("aria-label", placeBarAriaLabel, null); // $NON-NLS-1$ } //container div w.startElement("div", c); // $NON-NLS-1$ if(StringUtil.isNotEmpty(pageWidthClass)) { w.writeAttribute("class", pageWidthClass, null); // $NON-NLS-1$ } w.startElement("div", c); // $NON-NLS-1$ w.writeAttribute("class", "applayout-placebar-title", null); // $NON-NLS-1$ $NON-NLS-2$ 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); } w.endElement("div"); // $NON-NLS-1$ w.startElement("div", c); // $NON-NLS-1$ w.writeAttribute("class", "navbar navbar-right applayout-placebar-actions", null); // $NON-NLS-1$ $NON-NLS-2$ String placeBarNavAriaLabel = (String)getProperty(PROP_PLACEBARACTIONSARIALABEL); if( StringUtil.isNotEmpty(placeBarNavAriaLabel) ){ w.writeAttribute("aria-label", placeBarNavAriaLabel, null); // $NON-NLS-1$ } String placeBarNavRole = (String)getProperty(PROP_PLACEBARACTIONSROLE); if( StringUtil.isNotEmpty(placeBarNavRole) ){ w.writeAttribute("role", placeBarNavRole, null); // $NON-NLS-1$ } 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$ } w.endElement("div"); // $NON-NLS-1$ // Close the banner w.endElement("div"); // $NON-NLS-1$ w.endElement("div"); // $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); w.startElement(placeBarNameTag, c); String id = StringUtil.format("{0}_pbName", c.getClientId(context)); // $NON-NLS-1$ w.writeAttribute("id", id, null); // $NON-NLS-1$ w.writeText(placeName, null); 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 = new PlaceBarActionsRenderer(); 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, String pageWidthClass, boolean collapseLeftColumn, String collapseLeftTarget, String collapseLeftColumnButtonLabel) throws IOException { w.startElement("div", c); // $NON-NLS-1$ w.writeAttribute("role", "main", null); // $NON-NLS-1$ $NON-NLS-2$ // Empty pageWidthClass means pageWidth=none, therefore add no container class or row if (StringUtil.isNotEmpty(pageWidthClass)) { w.writeAttribute("class", pageWidthClass, null); // $NON-NLS-1$ w.startElement("div", c); // $NON-NLS-1$ w.writeAttribute("class", "row", null); // $NON-NLS-1$ $NON-NLS-2$ } boolean left = !isEmptyComponent(c.getLeftColumn()); boolean right = !isEmptyComponent(c.getRightColumn()); int contentSize = 12; int leftSize = 0; if(left) { leftSize = 2; contentSize -= leftSize; } int rightSize = 0; if(right) { rightSize = 2; contentSize -= rightSize; } // Write the 3 columns writeLeftColumn(context, w, c, leftSize, configuration, collapseLeftColumn, collapseLeftTarget, collapseLeftColumnButtonLabel); writeContentColumn(context, w, c, contentSize, configuration); writeRightColumn(context, w, c, rightSize, configuration); // Close the main content if (StringUtil.isNotEmpty(pageWidthClass)) { w.endElement("div"); // $NON-NLS-1$ newLine(w, "row"); // $NON-NLS-1$ } w.endElement("div"); // $NON-NLS-1$ } protected void writeLeftColumn(FacesContext context, ResponseWriter w, UIApplicationLayout c, int size, BasicApplicationConfigurationImpl configuration, boolean collapseLeftColumn, String collapseLeftTarget, String collapseLeftButtonLabel) throws IOException { UIComponent left = c.getLeftColumn(); if (!isEmptyComponent(left)) { if (DEBUG) { w.writeComment("Start Left Column"); // $NON-NLS-1$ newLine(w); } // Write the medium/ large screen component // if the collapseLeftColumn option is set, the large screen component is hidden on smaller screens w.startElement("div", c); // $NON-NLS-1$ String mdCol = (String)getProperty(PROP_COLUMN_MEDIUM); String smCol = (String)getProperty(PROP_COLUMN_SMALL); if (collapseLeftColumn) { w.writeAttribute("class", mdCol + size + " hidden-xs hidden-sm applayout-column-left", null); // $NON-NLS-1$ $NON-NLS-2$ } else { w.writeAttribute("class", mdCol + size + " " + smCol + (size+1) + " applayout-column-left", null); // $NON-NLS-1$ $NON-NLS-2$ $NLS-NLS-3$ } FacesUtil.renderComponent(context, left); w.endElement("div"); // $NON-NLS-1$ newLine(w); // $NON-NLS-1$ if (collapseLeftColumn) { // Write the small screen component (collapsed menu) w.startElement("script", c); // $NON-NLS-1$ w.writeText("dojo.addOnLoad( function() { XTB.initCollapsibleMenu('" + collapseLeftButtonLabel + "', '" + collapseLeftTarget + "'); } );", null); // $NON-NLS-1$ w.endElement("script"); // $NON-NLS-1$ newLine(w); } if (DEBUG) { w.writeComment("End Left Column"); // $NON-NLS-1$ newLine(w); } } } protected void writeRightColumn(FacesContext context, ResponseWriter w, UIApplicationLayout c, int size, BasicApplicationConfigurationImpl configuration) throws IOException { UIComponent right = c.getRightColumn(); if (!isEmptyComponent(right)) { if (DEBUG) { w.writeComment("Start Right Column"); // $NON-NLS-1$ newLine(w); } w.startElement("div", c); // $NON-NLS-1$ String mdCol = (String)getProperty(PROP_COLUMN_MEDIUM) + size; String smCol = (String)getProperty(PROP_COLUMN_SMALL) + (size+1); String rightColClass = "applayout-column-right"; // $NON-NLS-1$ String colClass = ExtLibUtil.concatStyleClasses(mdCol, smCol); colClass = ExtLibUtil.concatStyleClasses(colClass, rightColClass); if (StringUtil.isNotEmpty(colClass)) { w.writeAttribute("class", colClass, null); // $NON-NLS-1$ } FacesUtil.renderComponent(context, right); w.endElement("div"); // $NON-NLS-1$ newLine(w); if (DEBUG) { w.writeComment("End Right Column"); // $NON-NLS-1$ newLine(w); } } } protected void writeContentColumn(FacesContext context, ResponseWriter w, UIApplicationLayout c, int size, 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$ boolean left = !isEmptyComponent(c.getLeftColumn()); boolean right = !isEmptyComponent(c.getRightColumn()); String mdCol = (String)getProperty(PROP_COLUMN_MEDIUM) + size; String smCol = (String)getProperty(PROP_COLUMN_SMALL) + (size + (left ? -1 : 0) + (right ? -1 : 0)) ; String contentColClass = "applayout-content"; // $NON-NLS-1$ String colClass = ExtLibUtil.concatStyleClasses(mdCol, smCol); colClass = ExtLibUtil.concatStyleClasses(colClass, contentColClass); if (StringUtil.isNotEmpty(colClass)) { w.writeAttribute("class", colClass, null); // $NON-NLS-1$ } renderChildren(context, c); w.endElement("div"); // $NON-NLS-1$ newLine(w); // $NON-NLS-1$ if (DEBUG) { w.writeComment("End Content Column"); // $NON-NLS-1$ newLine(w); } } } // ================================================================ // Footer // ================================================================ protected void writeFooter(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration, String pageWidthClass) throws IOException { w.startElement("footer", c); // $NON-NLS-1$ w.writeAttribute("class", "navbar navbar-bottom applayout-footer", null); // $NON-NLS-1$ $NON-NLS-2$ w.writeAttribute("role", "navigation", null); // $NON-NLS-1$ $NON-NLS-2$ // "Footer links" String footerAriaLabel = com.ibm.xsp.extlib.controls.ResourceHandler.getString("AbstractApplicationLayoutRenderer.Footerlinks"); // $NON-NLS-1$ w.writeAttribute("aria-label", footerAriaLabel, null); // $NON-NLS-1$ //container div w.startElement("div", c); // $NON-NLS-1$ if(StringUtil.isNotEmpty(pageWidthClass)) { w.writeAttribute("class", pageWidthClass, null); // $NON-NLS-1$ } newLine(w); writeFooterLinks(context, w, c, configuration); w.endElement("div"); // $NON-NLS-1$ newLine(w, "container"); // $NON-NLS-1$ w.endElement("footer"); // $NON-NLS-1$ newLine(w, "footer"); // $NON-NLS-1$ } protected void writeFooterLinks(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration) throws IOException { ITree tree = TreeImpl.get(configuration.getFooterLinks()); if (tree != null) { AbstractTreeRenderer renderer = new 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, String pageWidthClass) throws IOException { w.startElement("footer", c); // $NON-NLS-1$ w.writeAttribute("class", "navbar navbar-bottom applayout-legal", null); // $NON-NLS-1$ $NON-NLS-2$ w.writeAttribute("role", "contentinfo", null); // $NON-NLS-1$ $NON-NLS-2$ // "Legal footer" String legalAriaLabel = com.ibm.xsp.extlib.controls.ResourceHandler.getString("AbstractApplicationLayoutRenderer.Legalfooter"); // $NON-NLS-1$ w.writeAttribute("aria-label", legalAriaLabel, null); // $NON-NLS-1$ //container div w.startElement("div", c); // $NON-NLS-1$ if(StringUtil.isNotEmpty(pageWidthClass)) { w.writeAttribute("class", pageWidthClass, null); // $NON-NLS-1$ } w.startElement("div", c); // $NON-NLS-1$ w.writeAttribute("style", "display: table; margin-left: auto; margin-right: auto; text-align: center;", null); // $NON-NLS-1$ $NON-NLS-2$ newLine(w); writeLegalLogo(context, w, c, configuration); writeLegalText(context, w, c, configuration); w.endElement("div"); // $NON-NLS-1$ newLine(w, null); // $NON-NLS-1$ $NON-NLS-2$ w.endElement("div"); // $NON-NLS-1$ newLine(w, "container"); // $NON-NLS-1$ w.endElement("footer"); // $NON-NLS-1$ newLine(w, "footer"); // $NON-NLS-1$ } protected void writeLegalLogo(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration) throws IOException { String logoImg=configuration.getLegalLogo(); if(StringUtil.isNotEmpty(logoImg)) { w.startElement("span", c); // $NON-NLS-1$ String clazz=configuration.getLegalLogoClass(); if(StringUtil.isNotEmpty(clazz)) { w.writeAttribute("class", clazz, null); // $NON-NLS-1$ } String style=ExtLibUtil.concatStyles("float:left;vertical-align:middle;margin-right: 5px;", configuration.getLegalLogoStyle()); // $NON-NLS-1$ 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.writeURIAttribute("src", imgSrc, null); // $NON-NLS-1$ String logoAlt=configuration.getLegalLogoAlt(); if(!ExtLibRenderUtil.isAltPresent(logoAlt)) { logoAlt = com.ibm.xsp.extlib.controls.ResourceHandler.getString("AbstractApplicationLayoutRenderer.LegalLogo"); // $NON-NLS-1$ } w.writeAttribute("alt", logoAlt, null); // $NON-NLS-1$ String width=configuration.getLegalLogoWidth(); if(StringUtil.isNotEmpty(width)) { w.writeAttribute("width", width, null); // $NON-NLS-1$ } String height=configuration.getLegalLogoHeight(); 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 writeLegalText(FacesContext context, ResponseWriter w, UIApplicationLayout c, BasicApplicationConfigurationImpl configuration) throws IOException { String legalText = configuration.getLegalText(); if (StringUtil.isNotEmpty(legalText)) { w.writeText(legalText, null); } } protected String getContainerClass(BasicApplicationConfigurationImpl configuration) throws IOException { ResponsiveApplicationConfiguration respConfig = asBootstrapConfig(configuration); if(respConfig != null) { String pageWidth = respConfig.getPageWidth(); if ( StringUtil.isNotEmpty(pageWidth)) { if(pageWidth.equals(ResponsiveApplicationConfiguration.WIDTH_FLUID)) { return "container-fluid"; // $NON-NLS-1$ } else if ( pageWidth.equals(ResponsiveApplicationConfiguration.WIDTH_FIXED)) { return "container"; // $NON-NLS-1$ } else if ( pageWidth.equals(ResponsiveApplicationConfiguration.WIDTH_FULL)) { return "container-full"; // $NON-NLS-1$ } else if ( pageWidth.equals(ResponsiveApplicationConfiguration.WIDTH_NONE)) { return ""; // $NON-NLS-1$ } } } // Fluid container by default return "container-fluid"; // $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; } }