001/* 002 * (C) Copyright 2006-2007 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 * <a href="mailto:at@nuxeo.com">Anahide Tchertchian</a> 018 * 019 * $Id: HtmlEditorRenderer.java 28610 2008-01-09 17:13:52Z sfermigier $ 020 */ 021 022package org.nuxeo.ecm.platform.ui.web.component.editor; 023 024import java.io.IOException; 025import java.util.ArrayList; 026import java.util.HashMap; 027import java.util.List; 028import java.util.Locale; 029import java.util.Map; 030 031import javax.faces.component.UIComponent; 032import javax.faces.component.UIInput; 033import javax.faces.context.FacesContext; 034import javax.faces.context.ResponseWriter; 035 036import org.apache.commons.lang.StringUtils; 037import org.nuxeo.ecm.platform.ui.web.htmleditor.api.HtmlEditorPluginService; 038import org.nuxeo.runtime.api.Framework; 039 040import com.sun.faces.renderkit.html_basic.HtmlBasicInputRenderer; 041 042/** 043 * Renderer for html editor component. 044 * <p> 045 * Uses TinyMCE javascript editor. 046 * 047 * @author <a href="mailto:at@nuxeo.com">Anahide Tchertchian</a> 048 */ 049public class HtmlEditorRenderer extends HtmlBasicInputRenderer { 050 051 private static Map<String, String> pluginsOptions; 052 053 private static Map<String, String> toolbarPluginsOptions; 054 055 @Override 056 public void encodeBegin(FacesContext context, UIComponent component) throws IOException { 057 if (!component.isRendered()) { 058 return; 059 } 060 061 UIHtmlEditor editorComp = (UIHtmlEditor) component; 062 ResponseWriter writer = context.getResponseWriter(); 063 Locale locale = context.getViewRoot().getLocale(); 064 065 if (pluginsOptions == null) { 066 final HtmlEditorPluginService pluginService = Framework.getService(HtmlEditorPluginService.class); 067 pluginsOptions = new HashMap<String, String>(); 068 pluginsOptions.put("plugins", pluginService.getFormattedPluginsNames()); 069 } 070 if (toolbarPluginsOptions == null) { 071 final HtmlEditorPluginService pluginService = Framework.getService(HtmlEditorPluginService.class); 072 toolbarPluginsOptions = new HashMap<String, String>(); 073 toolbarPluginsOptions.put("toolbar", pluginService.getFormattedToolbarsButtonsNames()); 074 } 075 076 String clientId = editorComp.getClientId(context); 077 boolean disableHtmlInit = Boolean.TRUE.equals(editorComp.getDisableHtmlInit()); 078 079 // input text area 080 writer.startElement("textarea", editorComp); 081 writer.writeAttribute("id", clientId, null); 082 writer.writeAttribute("name", clientId, null); 083 String editorSelector = editorComp.getEditorSelector(); 084 if (Boolean.TRUE.equals(editorComp.getDisableHtmlInit())) { 085 writer.writeAttribute("class", editorSelector + ",disableMCEInit", null); 086 } else { 087 writer.writeAttribute("class", editorSelector, null); 088 } 089 writer.writeAttribute("rows", editorComp.getRows(), null); 090 writer.writeAttribute("cols", editorComp.getCols(), null); 091 Object currentValue = getCurrentValue(editorComp); 092 if (currentValue != null) { 093 writer.writeText(currentValue, null); 094 } else { 095 writer.writeText("", null); 096 } 097 writer.endElement("textarea"); 098 099 if (!disableHtmlInit) { 100 writer.startElement("script", editorComp); 101 writer.writeAttribute("type", "text/javascript", null); 102 String compConfiguration = editorComp.getConfiguration(); 103 if (StringUtils.isBlank(compConfiguration)) { 104 compConfiguration = "{}"; 105 } 106 // Since 5.7.3, use unique clientId instead of editorSelector value 107 // so that tiny mce editors are initialized individually: no need 108 // anymore to specify a class to know which one should or should 109 // not be initialized 110 String scriptContent = new StringBuilder().append("initTinyMCE(") 111 .append(editorComp.getWidth()) 112 .append(", ") 113 .append(editorComp.getHeight()) 114 .append(", '") 115 .append(clientId) 116 .append("', '") 117 .append(pluginsOptions.get("plugins")) 118 .append("', '") 119 .append(locale.getLanguage()) 120 .append("', '") 121 .append(toolbarPluginsOptions.get("toolbar")) 122 .append("', '") 123 .append(compConfiguration) 124 .append("');") 125 .toString(); 126 writer.writeText(scriptContent, null); 127 String ajaxScriptContent = "jsf.ajax.addOnEvent(function(data) {if (data.status == \"success\") {" 128 + scriptContent + "}});"; 129 writer.writeText(ajaxScriptContent, null); 130 String scriptContent2 = "jQuery(document.getElementById('" + clientId 131 + "')).closest('form').bind('ajaxsubmit', function() { var editor = tinyMCE.editors['" + clientId 132 + "']; if (editor != undefined) {editor.save()};});"; 133 writer.writeText(scriptContent2, null); 134 writer.endElement("script"); 135 } 136 137 writer.flush(); 138 } 139 140 protected static Object getCurrentValue(UIInput comp) { 141 Object submitted = comp.getSubmittedValue(); 142 if (submitted != null) { 143 return submitted; 144 } 145 return comp.getValue(); 146 } 147 148 protected static String generateOptions(Map<String, String> options) { 149 List<String> strOptions = new ArrayList<String>(); 150 for (Map.Entry<String, String> option : options.entrySet()) { 151 strOptions.add(option.getKey() + ": \"" + option.getValue() + "\""); 152 } 153 StringBuilder res = new StringBuilder(); 154 res.append('{'); 155 res.append(StringUtils.join(strOptions.toArray(), ", ")); 156 res.append('}'); 157 return res.toString(); 158 } 159 160}