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}