View Javadoc

1   /*
2    * FCKeditor - The text editor for Internet - http://www.fckeditor.net
3    * Copyright (C) 2003-2008 Frederico Caldeira Knabben
4    * 
5    * == BEGIN LICENSE ==
6    * 
7    * Licensed under the terms of any of the following licenses at your
8    * choice:
9    * 
10   *  - GNU General Public License Version 2 or later (the "GPL")
11   *    http://www.gnu.org/licenses/gpl.html
12   * 
13   *  - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
14   *    http://www.gnu.org/licenses/lgpl.html
15   * 
16   *  - Mozilla Public License Version 1.1 or later (the "MPL")
17   *    http://www.mozilla.org/MPL/MPL-1.1.html
18   * 
19   * == END LICENSE ==
20   */
21  
22  package net.fckeditor;
23  
24  import javax.servlet.http.HttpServletRequest;
25  
26  import net.fckeditor.handlers.PropertiesLoader;
27  import net.fckeditor.tool.Compatibility;
28  import net.fckeditor.tool.Utils;
29  import net.fckeditor.tool.XHtmlTagTool;
30  
31  /**
32   * Java represantation of the FCKeditor. This class creates the html code for
33   * the FCKeditor based on the following things:
34   * <ul>
35   * <li>browser capabilities</li>
36   * <li>different properties settings managed by the {@link PropertiesLoader}</li>
37   * <li>settings from the FCKeditor tag, template engines and other systems</li>
38   * </ul>
39   * 
40   * @version $Id: FCKeditor.java 2151 2008-07-02 22:03:15Z mosipov $
41   */
42  public class FCKeditor {
43  
44  	private FCKeditorConfig config;
45  	private String instanceName;
46  	private String value;
47  	private String basePath;
48  	private HttpServletRequest request;
49  
50  	// defaults
51  	private String toolbarSet = PropertiesLoader.getProperty("fckeditor.toolbarSet");
52  	private String width = PropertiesLoader.getProperty("fckeditor.width");
53  	private String height = PropertiesLoader.getProperty("fckeditor.height");
54  	private String defaultBasePath = PropertiesLoader.getProperty("fckeditor.basePath");
55  
56  	/**
57  	 * Main constructor.<br>
58  	 * All important settings are done here and will be preset by the defaults
59  	 * taken from {@link PropertiesLoader}.
60  	 * 
61  	 * @param request
62  	 *            request object
63  	 * @param instanceName
64  	 *            unique name
65  	 * @param width
66  	 *            width
67  	 * @param height
68  	 *            height
69  	 * @param toolbarSet
70  	 *            toolbarSet name
71  	 */
72  	public FCKeditor(final HttpServletRequest request, final String instanceName,
73  	        final String width, final String height, final String toolbarSet, final String value,
74  	        final String basePath) {
75  		this.request = request;
76  		this.instanceName = instanceName;
77  		if (Utils.isNotEmpty(width))
78  			this.width = width;
79  		if (Utils.isNotEmpty(height))
80  			this.height = height;
81  		if (Utils.isNotEmpty(toolbarSet))
82  			this.toolbarSet = toolbarSet;
83  		if (Utils.isNotEmpty(value))
84  			this.value = value;
85  		if (Utils.isNotEmpty(basePath))
86  			this.basePath = request.getContextPath().concat(basePath);
87  		else
88  			this.basePath = request.getContextPath().concat(defaultBasePath);
89  
90  		config = new FCKeditorConfig();
91  	}
92  
93  	/**
94  	 * Just a wrapper to {@link FCKeditor}.
95  	 * 
96  	 * @param request
97  	 *            request object
98  	 * @param instanceName
99  	 *            unique name
100 	 */
101 
102 	public FCKeditor(final HttpServletRequest request, final String instanceName) {
103 		this(request, instanceName, null, null, null, null, null);
104 	}
105 
106 	/**
107 	 * Set the unique name of the editor
108 	 * 
109 	 * @param instanceName
110 	 *            name
111 	 */
112 	public void setInstanceName(final String instanceName) {
113 		this.instanceName = instanceName;
114 	}
115 
116 	/**
117 	 * Set the initial value to be edited as HTML markup.
118 	 * 
119 	 * @param value
120 	 *            value
121 	 */
122 	public void setValue(final String value) {
123 		this.value = value;
124 	}
125 
126 	/**
127 	 * Sets the directory where the FCKeditor resides on the server.<br />
128 	 * <strong>Remarks</strong>: Avoid using relative paths. Use an absolute
129 	 * path from the context (e.g. /fckeditor).
130 	 * 
131 	 * @param basePath
132 	 *            path
133 	 */
134 	public void setBasePath(final String basePath) {
135 		this.basePath = basePath;
136 	}
137 
138 	/**
139 	 * Set the name of the toolbar to display
140 	 * 
141 	 * @param toolbarSet
142 	 *            toolbar name
143 	 */
144 	public void setToolbarSet(final String toolbarSet) {
145 		this.toolbarSet = toolbarSet;
146 	}
147 
148 	/**
149 	 * Set the width of the textarea
150 	 * 
151 	 * @param width
152 	 *            width
153 	 */
154 	public void setWidth(final String width) {
155 		this.width = width;
156 	}
157 
158 	/**
159 	 * Set the height of the textarea
160 	 * 
161 	 * @param height
162 	 *            height
163 	 */
164 	public void setHeight(final String height) {
165 		this.height = height;
166 	}
167 
168 	/**
169 	 * Get the advanced configuration set.<br />
170 	 * By adding elements to this collection you can override the settings
171 	 * specified in the config.js file.
172 	 * 
173 	 * @return configuration collection
174 	 */
175 	public FCKeditorConfig getConfig() {
176 		return config;
177 	}
178 	/**
179 	 * Set the advanced configuation set.
180 	 * 
181 	 * @param config
182 	 *            configuration collection
183 	 */
184 	public void setConfig(FCKeditorConfig config) {
185 		this.config = config;
186 	}
187 
188 	/**
189 	 * Escape base XML entities as specified <a
190 	 * href="http://en.wikipedia.org/wiki/Xml#Entity_references">here</a>.
191 	 * 
192 	 * @param str
193 	 *            Text to escape.
194 	 * @return Escaped text.
195 	 */
196 	private String escapeXml(String str) {
197 		if (Utils.isEmpty(str))
198 			return str;
199 		
200 		/*
201 		 * TODO Strings are inefficent. It should be done like in Commons Lang
202 		 * 2.4 StringUtils#replaceEach(String, String[], String[])
203 		 */
204 		str = str.replaceAll("&", "&#38;");
205 		str = str.replaceAll("<", "&#60;");
206 		str = str.replaceAll(">", "&#62;");
207 		str = str.replaceAll("\"", "&#34;");
208 		str = str.replaceAll("'", "&#39;");
209 		return str;
210 	}
211 	
212 	/*
213 	 * (non-Javadoc)
214 	 * 
215 	 * @see #createHtml()
216 	 */
217 	/**
218 	 * This method simply wraps to {@link #createHtml()}.
219 	 * @see #createHtml()
220 	 */
221 	@Override
222 	public String toString() {
223 		return createHtml();
224 	}
225 
226 	/**
227 	 * Minimum implementation, see ticket #27 for detailed information. Generate
228 	 * the HTML Code for the editor.<br />
229 	 * Evaluate the browser capabilities and generate the editor if compatible,
230 	 * or a simple textarea otherwise.
231 	 * 
232 	 * @return FCKeditor html code
233 	 */
234 	public String createHtml() {
235 		StringBuffer strEditor = new StringBuffer();
236 
237 		strEditor.append("<div>");
238 		String encodedValue = escapeXml(value.replaceAll("((\r?\n)+|\t*)", ""));
239 
240 		if (Compatibility.check(request.getHeader("user-agent"))) {
241 			strEditor.append(createInputForVariable(instanceName, instanceName, encodedValue));
242 
243 			// create config html
244 			String configStr = config.getUrlParams();
245 			if (Utils.isNotEmpty(configStr))
246 				strEditor.append(createInputForVariable(null, instanceName.concat("___Config"),
247 				        configStr));
248 
249 			// create IFrame
250 			String sLink = basePath.concat("/editor/fckeditor.html?InstanceName=").concat(
251 			        instanceName);
252 			if (Utils.isNotEmpty(toolbarSet))
253 				sLink += "&Toolbar=".concat(toolbarSet);
254 			XHtmlTagTool iframeTag = new XHtmlTagTool("iframe", XHtmlTagTool.SPACE);
255 			iframeTag.addAttribute("id", instanceName.concat("___Frame"));
256 			iframeTag.addAttribute("src", sLink);
257 			iframeTag.addAttribute("width", width);
258 			iframeTag.addAttribute("height", height);
259 			iframeTag.addAttribute("frameborder", "no");
260 			iframeTag.addAttribute("scrolling", "no");
261 			strEditor.append(iframeTag);
262 
263 		} else {
264 			XHtmlTagTool textareaTag = new XHtmlTagTool("textarea", encodedValue);
265 			textareaTag.addAttribute("name", instanceName);
266 			textareaTag.addAttribute("rows", "4");
267 			textareaTag.addAttribute("cols", "40");
268 			textareaTag.addAttribute("wrap", "virtual");
269 			textareaTag.addAttribute("style", "width: ".concat(width).concat("; height: ").concat(
270 			        height));
271 		}
272 		strEditor.append("</div>");
273 		return strEditor.toString();
274 	}
275 
276 	private String createInputForVariable(final String name, final String id, final String value) {
277 		XHtmlTagTool tag = new XHtmlTagTool("input");
278 		if (Utils.isNotEmpty(id))
279 			tag.addAttribute("id", id);
280 		if (Utils.isNotEmpty(name))
281 			tag.addAttribute("name", name);
282 		tag.addAttribute("value", value);
283 		tag.addAttribute("type", "hidden");
284 		return tag.toString();
285 	}
286 }