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.lang3.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 Map<String,String> options = new HashMap<>(); 068 options.put("plugins", pluginService.getFormattedPluginsNames()); 069 pluginsOptions = options; 070 } 071 if (toolbarPluginsOptions == null) { 072 final HtmlEditorPluginService pluginService = Framework.getService(HtmlEditorPluginService.class); 073 Map<String,String> options = new HashMap<>(); 074 options.put("toolbar", pluginService.getFormattedToolbarsButtonsNames()); 075 toolbarPluginsOptions = options; 076 } 077 078 String clientId = editorComp.getClientId(context); 079 boolean disableHtmlInit = Boolean.TRUE.equals(editorComp.getDisableHtmlInit()); 080 081 // input text area 082 writer.startElement("textarea", editorComp); 083 writer.writeAttribute("id", clientId, null); 084 writer.writeAttribute("name", clientId, null); 085 String editorSelector = editorComp.getEditorSelector(); 086 if (Boolean.TRUE.equals(editorComp.getDisableHtmlInit())) { 087 writer.writeAttribute("class", editorSelector + ",disableMCEInit", null); 088 } else { 089 writer.writeAttribute("class", editorSelector, null); 090 } 091 writer.writeAttribute("rows", editorComp.getRows(), null); 092 writer.writeAttribute("cols", editorComp.getCols(), null); 093 Object currentValue = getCurrentValue(editorComp); 094 if (currentValue != null) { 095 writer.writeText(currentValue, null); 096 } else { 097 writer.writeText("", null); 098 } 099 writer.endElement("textarea"); 100 101 if (!disableHtmlInit) { 102 writer.startElement("script", editorComp); 103 writer.writeAttribute("type", "text/javascript", null); 104 String compConfiguration = editorComp.getConfiguration(); 105 if (StringUtils.isBlank(compConfiguration)) { 106 compConfiguration = "{}"; 107 } 108 // Since 5.7.3, use unique clientId instead of editorSelector value 109 // so that tiny mce editors are initialized individually: no need 110 // anymore to specify a class to know which one should or should 111 // not be initialized 112 String scriptContent = new StringBuilder().append("initTinyMCE(") 113 .append(editorComp.getWidth()) 114 .append(", ") 115 .append(editorComp.getHeight()) 116 .append(", '") 117 .append(clientId) 118 .append("', '") 119 .append(pluginsOptions.get("plugins")) 120 .append("', '") 121 .append(locale.getLanguage()) 122 .append("', '") 123 .append(toolbarPluginsOptions.get("toolbar")) 124 .append("', '") 125 .append(compConfiguration) 126 .append("');") 127 .toString(); 128 writer.writeText(scriptContent, null); 129 String ajaxScriptContent = "jsf.ajax.addOnEvent(function(data) {" // 130 + "if (data.status === 'success') {" // 131 + "removeTinyMCE('" + clientId + "');" // 132 + "addTinyMCE('" + clientId + "');" // 133 + "}});"; 134 writer.writeText(ajaxScriptContent, null); 135 String scriptContent2 = "jQuery(document.getElementById('" + clientId 136 + "')).closest('form').bind('ajaxsubmit', function() { var editor = tinyMCE.editors['" + clientId 137 + "']; if (editor != undefined) {editor.save()};});"; 138 writer.writeText(scriptContent2, null); 139 writer.endElement("script"); 140 } 141 142 writer.flush(); 143 } 144 145 protected static Object getCurrentValue(UIInput comp) { 146 Object submitted = comp.getSubmittedValue(); 147 if (submitted != null) { 148 return submitted; 149 } 150 return comp.getValue(); 151 } 152 153 protected static String generateOptions(Map<String, String> options) { 154 List<String> strOptions = new ArrayList<String>(); 155 for (Map.Entry<String, String> option : options.entrySet()) { 156 strOptions.add(option.getKey() + ": \"" + option.getValue() + "\""); 157 } 158 StringBuilder res = new StringBuilder(); 159 res.append('{'); 160 res.append(StringUtils.join(strOptions.toArray(), ", ")); 161 res.append('}'); 162 return res.toString(); 163 } 164 165}