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