001/* 002 * (C) Copyright 2012 Nuxeo SA (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Anahide Tchertchian 016 */ 017package org.nuxeo.ecm.platform.ui.web.renderer; 018 019import static com.sun.faces.renderkit.Attribute.attr; 020import static com.sun.faces.util.CollectionsUtils.ar; 021 022import java.io.IOException; 023import java.util.Map; 024import java.util.logging.Level; 025 026import javax.faces.component.UIComponent; 027import javax.faces.component.UIGraphic; 028import javax.faces.context.FacesContext; 029import javax.faces.context.ResponseWriter; 030 031import org.apache.commons.lang.StringUtils; 032 033import com.sun.faces.RIConstants; 034import com.sun.faces.renderkit.Attribute; 035import com.sun.faces.renderkit.RenderKitUtils; 036import com.sun.faces.renderkit.html_basic.ImageRenderer; 037 038/** 039 * Renderer that does not display an empty "img" tag as well as empty width and height attributes (as it's an issue for 040 * IE) 041 * 042 * @since 5.6 043 */ 044public class NXImageRenderer extends ImageRenderer { 045 046 // remove attributes height and width from default attributes to avoid 047 // adding them when empty 048 protected static final Attribute[] ATTRIBUTES = ar( 049 // 050 attr("alt"), 051 // 052 attr("dir"), 053 // 054 // attr("height"), 055 // 056 attr("lang"), 057 // 058 attr("longdesc"), 059 // 060 attr("onclick", "click"), 061 attr("ondblclick", "dblclick"), 062 // 063 attr("onkeydown", "keydown"), attr("onkeypress", "keypress"), attr("onkeyup", "keyup"), 064 attr("onmousedown", "mousedown"), 065 // 066 attr("onmousemove", "mousemove"), attr("onmouseout", "mouseout"), attr("onmouseover", "mouseover"), 067 attr("onmouseup", "mouseup"), 068 // 069 attr("role"), attr("style"), attr("title"), attr("usemap") 070 // 071 // attr("width") 072 ); 073 074 public static final String RENDERER_TYPE = "javax.faces.NXImage"; 075 076 @Override 077 public void encodeEnd(FacesContext context, UIComponent component) throws IOException { 078 079 rendererParamsNotNull(context, component); 080 081 if (!shouldEncode(component)) { 082 return; 083 } 084 085 ResponseWriter writer = context.getResponseWriter(); 086 087 // do not even render tag if url is empty 088 String src = src(context, component); 089 if (StringUtils.isBlank(src)) { 090 if (logger.isLoggable(Level.FINER)) { 091 logger.log(Level.FINER, 092 "Do not render empty img tag with empty src value for component " + component.getId()); 093 } 094 } else { 095 Map<String, Object> attrs = component.getAttributes(); 096 097 // Get the attributes 098 String width = (String) attrs.get("width"); 099 String height = (String) attrs.get("height"); 100 String enableContainer = (String) attrs.get("enableContainer"); 101 102 boolean hasDivContainer = false; 103 if (enableContainer != null && Boolean.parseBoolean(enableContainer) == true) { 104 hasDivContainer = true; 105 } 106 107 if (hasDivContainer) { 108 writer.startElement("div", component); 109 writer.writeAttribute("class", "pictureContainer", "class"); 110 111 StringBuilder styleBuilder = new StringBuilder(); 112 if (!StringUtils.isEmpty(width)) { 113 styleBuilder.append("width:"); 114 styleBuilder.append(width); 115 styleBuilder.append("px;"); 116 } 117 if (!StringUtils.isEmpty(height)) { 118 styleBuilder.append("height:"); 119 styleBuilder.append(height); 120 styleBuilder.append("px;"); 121 } 122 if (styleBuilder.length() > 0) { 123 writer.writeAttribute("style", styleBuilder.toString(), "style"); 124 } 125 } 126 127 writer.startElement("img", component); 128 writeIdAttributeIfNecessary(context, writer, component); 129 writer.writeURIAttribute("src", src, "value"); 130 131 // if we're writing XHTML and we have a null alt attribute 132 if (writer.getContentType().equals(RIConstants.XHTML_CONTENT_TYPE) && null == attrs.get("alt")) { 133 // write out an empty alt 134 writer.writeAttribute("alt", "", "alt"); 135 } 136 137 RenderKitUtils.renderPassThruAttributes(context, writer, component, ATTRIBUTES); 138 // If the container is not activated and the width and/or height are defined, these attributes are set on 139 // the img directly 140 if (!hasDivContainer) { 141 if (!StringUtils.isBlank(width)) { 142 writer.writeAttribute("width", width, "width"); 143 } 144 if (!StringUtils.isBlank(height)) { 145 writer.writeAttribute("height", height, "height"); 146 } 147 } 148 149 RenderKitUtils.renderXHTMLStyleBooleanAttributes(writer, component); 150 151 String styleClass = (String) attrs.get("styleClass"); 152 if (!StringUtils.isBlank(styleClass)) { 153 writer.writeAttribute("class", styleClass, "styleClass"); 154 } 155 156 writer.endElement("img"); 157 158 if (hasDivContainer) { 159 writer.endElement("div"); 160 } 161 } 162 163 if (logger.isLoggable(Level.FINER)) { 164 logger.log(Level.FINER, "End encoding component " + component.getId()); 165 } 166 167 } 168 169 protected static String src(FacesContext context, UIComponent component) { 170 String value = (String) ((UIGraphic) component).getValue(); 171 if (value == null) { 172 return ""; 173 } 174 value = context.getApplication().getViewHandler().getResourceURL(context, value); 175 return (context.getExternalContext().encodeResourceURL(value)); 176 } 177 178}