/* * � Copyright IBM Corp. 2010 * * 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.containers; 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.extlib.component.containers.UIList; import com.ibm.xsp.extlib.renderkit.html_extended.FacesRendererEx; import com.ibm.xsp.extlib.util.ExtLibUtil; import com.ibm.xsp.util.FacesUtil; import com.ibm.xsp.util.HtmlUtil; import com.ibm.xsp.util.JSUtil; import com.ibm.xsp.util.TypedUtil; /** * List container renderer. */ public class ListRenderer extends FacesRendererEx { // ========================================================================== // Rendering Properties // ========================================================================== // List style protected static final int PROP_LISTTAG = 1; protected static final int PROP_LISTSTYLE = 2; protected static final int PROP_LISTSTYLECLASS = 3; protected static final int PROP_ITEMTAG = 4; protected static final int PROP_ITEMSTYLE = 5; protected static final int PROP_ITEMSTYLECLASS = 6; protected static final int PROP_FIRSTITEMSTYLE = 7; protected static final int PROP_FIRSTITEMSTYLECLASS = 8; protected static final int PROP_LASTITEMSTYLE = 9; protected static final int PROP_LASTITEMSTYLECLASS = 10; protected static final int PROP_ITEMDISPLAYNONESTYLE = 11; protected static final int PROP_LISTROLE = 12; protected static final int PROP_ITEMROLE = 13; @Override protected Object getProperty(int prop) { switch(prop) { case PROP_LISTTAG: return "ul"; // $NON-NLS-1$ case PROP_ITEMTAG: return "li"; // $NON-NLS-1$ case PROP_ITEMDISPLAYNONESTYLE: return "display: none;"; // $NON-NLS-1$ case PROP_LISTROLE: return "list"; // $NON-NLS-1$ case PROP_ITEMROLE: return "listitem"; // $NON-NLS-1$ } return super.getProperty(prop); } @Override public void decode(FacesContext context, UIComponent component) { // Nothing to decode here... } @Override public boolean getRendersChildren() { return true; } @Override public void encodeChildren(FacesContext context, UIComponent component) throws IOException { } @Override public void encodeBegin(FacesContext context, UIComponent component) throws IOException { UIList container = (UIList)component; if(!container.isRendered()) { return; } ResponseWriter w = context.getResponseWriter(); writeMainList(context, w, container); } @Override public void encodeEnd(FacesContext context, UIComponent component) throws IOException { } // ================================================================ // Main List // ================================================================ protected void writeMainList(FacesContext context, ResponseWriter w, UIList c) throws IOException { String tag = (String)getProperty(PROP_LISTTAG); if(StringUtil.isNotEmpty(tag)) { w.startElement(tag,c); writeListAttributes(context, w, c); newLine(w); } if(c.getChildCount()>0) { writeChildren(context, w, c); } if(StringUtil.isNotEmpty(tag)) { w.endElement(tag); newLine(w); } } protected void writeListAttributes(FacesContext context, ResponseWriter w, UIList c) throws IOException { HtmlUtil.writeIdAttribute(context, c); // "id" String style = ExtLibUtil.concatStyles((String)getProperty(PROP_LISTSTYLE),c.getStyle()); if(StringUtil.isNotEmpty(style)) { w.writeAttribute("style",style,null); // $NON-NLS-1$ } String styleClass = ExtLibUtil.concatStyleClasses((String)getProperty(PROP_LISTSTYLECLASS),c.getStyleClass()); if(StringUtil.isNotEmpty(styleClass)) { w.writeAttribute("class",styleClass,null); // $NON-NLS-1$ } String role = (String)getProperty(PROP_LISTROLE); if(StringUtil.isNotEmpty(role)) { w.writeAttribute("role",role,null); // $NON-NLS-1$ } } protected void writeChildren(FacesContext context, ResponseWriter w, UIList c) throws IOException { List<UIComponent> children = TypedUtil.getChildren(c); // this mostly just iterates through the children and calls writeChild // with logic control to determine whether this is the first and/or last // child where rendered evaluates to true. int count = children.size(); boolean foundFirstRendered = false; int nextRenderedIndex = -1; for(int i=0; i<count; i++) { UIComponent child = children.get(i); if( nextRenderedIndex != -1 && nextRenderedIndex < i ){ continue; }else if( i == nextRenderedIndex ){ nextRenderedIndex = -1; // will render this child }else{ // check rendered if( ! child.isRendered() ){ if(count == 1) { //SPR #TWET97NLR3 - a11y - when list is empty, render //a hidden list element writeHiddenChild(context, w, c); } continue; } } // rendered evaluated to true for this child boolean first = ! foundFirstRendered; foundFirstRendered = true; boolean last; if( i == count-1 ){ last = true; }else{ nextRenderedIndex = -1; for (int j = i+1; j < count; j++) { UIComponent sibling = children.get(j); if( sibling.isRendered() ){ nextRenderedIndex = j; break; } } last = nextRenderedIndex == -1; } writeChild(context, w, c, child, first, last); } } protected void writeChild(FacesContext context, ResponseWriter w, UIList c, UIComponent child, boolean first, boolean last) throws IOException { String tag = (String)getProperty(PROP_ITEMTAG); if(StringUtil.isNotEmpty(tag)) { w.startElement(tag,c); writeItemAttributes(context, w, c, child, first, last); newLine(w); } FacesUtil.renderComponent(context, child); if(StringUtil.isNotEmpty(tag)) { w.endElement(tag); newLine(w); } } protected void writeHiddenChild(FacesContext context, ResponseWriter w, UIList c) throws IOException { //Writes a hidden list element String tag = (String)getProperty(PROP_ITEMTAG); if(StringUtil.isNotEmpty(tag)) { w.startElement(tag,c); String style = (String)getProperty(PROP_ITEMDISPLAYNONESTYLE); if(StringUtil.isNotEmpty(style)) { w.writeAttribute("style",style,null); // $NON-NLS-1$ } } if(StringUtil.isNotEmpty(tag)) { w.endElement(tag); } JSUtil.writeTextln(w); } protected void writeItemAttributes(FacesContext context, ResponseWriter w, UIList c, UIComponent child, boolean first, boolean last) throws IOException { String style = ExtLibUtil.concatStyles((String)getProperty(PROP_ITEMSTYLE),c.getItemStyle()); if(first) { style = ExtLibUtil.concatStyles(style,(String)getProperty(PROP_FIRSTITEMSTYLE)); style = ExtLibUtil.concatStyles(style,c.getFirstItemStyle()); } if(last) { style = ExtLibUtil.concatStyles(style,(String)getProperty(PROP_LASTITEMSTYLE)); style = ExtLibUtil.concatStyles(style,c.getLastItemStyle()); } if(StringUtil.isNotEmpty(style)) { w.writeAttribute("style",style,null); // $NON-NLS-1$ } String styleClass = ExtLibUtil.concatStyleClasses((String)getProperty(PROP_ITEMSTYLECLASS),c.getItemStyleClass()); if(first) { styleClass = ExtLibUtil.concatStyleClasses(styleClass,(String)getProperty(PROP_FIRSTITEMSTYLECLASS)); styleClass = ExtLibUtil.concatStyleClasses(styleClass,c.getFirstItemStyleClass()); } if(last) { styleClass = ExtLibUtil.concatStyles(styleClass,(String)getProperty(PROP_LASTITEMSTYLECLASS)); styleClass = ExtLibUtil.concatStyleClasses(styleClass,c.getLastItemStyleClass()); } if(StringUtil.isNotEmpty(styleClass)) { w.writeAttribute("class",styleClass,null); // $NON-NLS-1$ } String role = (String)getProperty(PROP_ITEMROLE); if(StringUtil.isNotEmpty(role)) { w.writeAttribute("role",role,null); // $NON-NLS-1$ } } }