001: /**********************************************************************************
002: * $URL: https://source.sakaiproject.org/svn/jsf/tags/sakai_2-4-1/widgets/src/java/org/sakaiproject/jsf/renderer/InputRichTextRenderer.java $
003: * $Id: InputRichTextRenderer.java 22295 2007-03-07 20:56:21Z joshua.ryan@asu.edu $
004: ***********************************************************************************
005: *
006: * Copyright (c) 2003, 2004 The Sakai Foundation.
007: *
008: * Licensed under the Educational Community License, Version 1.0 (the "License");
009: * you may not use this file except in compliance with the License.
010: * You may obtain a copy of the License at
011: *
012: * http://www.opensource.org/licenses/ecl1.php
013: *
014: * Unless required by applicable law or agreed to in writing, software
015: * distributed under the License is distributed on an "AS IS" BASIS,
016: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: * See the License for the specific language governing permissions and
018: * limitations under the License.
019: *
020: **********************************************************************************/package org.sakaiproject.jsf.renderer;
021:
022: import org.sakaiproject.component.cover.ServerConfigurationService;
023: import org.sakaiproject.content.cover.ContentHostingService;
024: import org.sakaiproject.jsf.model.InitObjectContainer;
025: import org.sakaiproject.jsf.util.ConfigurationResource;
026: import org.sakaiproject.jsf.util.RendererUtil;
027: import org.sakaiproject.tool.cover.ToolManager;
028:
029: import javax.faces.component.UIComponent;
030: import javax.faces.component.UIInput;
031: import javax.faces.component.ValueHolder;
032: import javax.faces.context.FacesContext;
033: import javax.faces.context.ResponseWriter;
034: import javax.faces.model.SelectItem;
035: import javax.faces.render.Renderer;
036: import java.io.IOException;
037: import java.io.StringWriter;
038: import java.text.MessageFormat;
039: import java.util.*;
040:
041: /**
042: * <p>Formerly RichTextEditArea.java</p>
043: * <p>Renders a rich text editor and toolbar within an HTML "textarea" element.</p>
044: <p>The textarea is decorated using the HTMLArea JavaScript library.</p>
045: <p>
046: HTMLArea is a free, customizable online editor. It works inside your
047: browser. It uses a non-standard feature implemented in Internet
048: Explorer 5.5 or better for Windows and Mozilla 1.3 or better (any
049: platform), therefore it will only work in one of these browsers.
050: </p>
051:
052: <p>
053: HTMLArea is copyright <a
054: href="http://interactivetools.com">InteractiveTools.com</a> and
055: released under a BSD-style license. HTMLArea is created and developed
056: upto version 2.03 by InteractiveTools.com. Version 3.0 developed by
057: <a href="http://students.infoiasi.ro/~mishoo/">Mihai Bazon</a> for
058: InteractiveTools. It contains code sponsored by other companies as
059: well.
060: </p>
061:
062: * <p>Copyright: Copyright (c) 2004 Sakai</p>
063: * @author cwen@iu.edu
064: * @author Ed Smiley esmiley@stanford.edu (modifications)
065: * @version $Id: InputRichTextRenderer.java 22295 2007-03-07 20:56:21Z joshua.ryan@asu.edu $
066: */
067: public class InputRichTextRenderer extends Renderer {
068: private static final String SCRIPT_PATH;
069: private static final String HTMLAREA_SCRIPT_PATH;
070: private static final String RESOURCE_PATH;
071: private static final String TOOLBAR_SCRIPT_NONE;
072: private static final String TOOLBAR_SCRIPT_SMALL;
073: private static final String TOOLBAR_SCRIPT_MEDIUM;
074:
075: private static final String TOOLBAR_SCRIPT_LARGE;
076: private static final int DEFAULT_WIDTH_PX;
077: private static final int DEFAULT_HEIGHT_PX;
078: private static final int DEFAULT_COLUMNS;
079: private static final int DEFAULT_ROWS;
080: private static final String INSERT_IMAGE_LOC;
081: private static final MessageFormat LIST_ITEM_FORMAT_HTML = new MessageFormat(
082: "\"{0}\" : \"<a href=''{1}''>{0}</a>\"");
083: private static final MessageFormat LIST_ITEM_FORMAT_FCK = new MessageFormat(
084: "[\"{0}\", \"{1}\"]");
085:
086: // we have static resources for our script path and built-in toolbars etc.
087: static {
088: ConfigurationResource cr = new ConfigurationResource();
089: SCRIPT_PATH = cr.get("inputRichTextScript");
090: HTMLAREA_SCRIPT_PATH = cr.get("inputRichTextHTMLArea");
091: RESOURCE_PATH = cr.get("resources");
092: TOOLBAR_SCRIPT_NONE = makeToolbarScript(cr
093: .get("inputRichText_none"));
094: TOOLBAR_SCRIPT_SMALL = makeToolbarScript(cr
095: .get("inputRichText_small"));
096: TOOLBAR_SCRIPT_MEDIUM = makeToolbarScript(cr
097: .get("inputRichText_medium"));
098: TOOLBAR_SCRIPT_LARGE = makeToolbarScript(cr
099: .get("inputRichText_large"));
100: DEFAULT_WIDTH_PX = Integer.parseInt(cr
101: .get("inputRichTextDefaultWidthPx"));
102: DEFAULT_HEIGHT_PX = Integer.parseInt(cr
103: .get("inputRichTextDefaultHeightPx"));
104: DEFAULT_COLUMNS = Integer.parseInt(cr
105: .get("inputRichTextDefaultTextareaColumns"));
106: DEFAULT_ROWS = Integer.parseInt(cr
107: .get("inputRichTextDefaultTextareaRows"));
108: INSERT_IMAGE_LOC = "/" + RESOURCE_PATH + "/"
109: + cr.get("inputRichTextFileInsertImage");
110: }
111:
112: public boolean supportsComponentType(UIComponent component) {
113: return (component instanceof org.sakaiproject.jsf.component.InputRichTextComponent);
114: }
115:
116: public void encodeBegin(FacesContext context, UIComponent component)
117: throws IOException {
118:
119: if (!component.isRendered()) {
120: return;
121: }
122:
123: String contextPath = context.getExternalContext()
124: .getRequestContextPath()
125: + SCRIPT_PATH;
126: String clientId = component.getClientId(context);
127:
128: ResponseWriter writer = context.getResponseWriter();
129:
130: String value = null;
131: if (component instanceof UIInput)
132: value = (String) ((UIInput) component).getSubmittedValue();
133: if (value == null && component instanceof ValueHolder)
134: value = (String) ((ValueHolder) component).getValue();
135:
136: ///////////////////////////////////////////////////////////////////////////
137: // attributes
138: ///////////////////////////////////////////////////////////////////////////
139:
140: // If true, only the textarea will be rendered. Defaults to false.
141: // If true, the rich text toolbar and external HTMLArea JavaScript will NOT.
142: String textareaOnly = (String) RendererUtil.getAttribute(
143: context, component, "textareaOnly");
144: // Specify toolbar from among a number precanned lists of command buttons.
145: // Allowed values are: "none", "small", "medium", "large".
146: String buttonSet = (String) RendererUtil.getAttribute(context,
147: component, "buttonSet");
148: // Comma delimited list of toolbar command buttons registered with component.
149: String buttonList = (String) RendererUtil.getAttribute(context,
150: component, "buttonList");
151: /**
152: * @todo need to do something with extensions.
153: */
154: // URL to an external JavaScript file with additional JavaScript
155: String javascriptLibraryExtensionURL = (String) RendererUtil
156: .getAttribute(context, component,
157: "javascriptLibraryExtensionURL");
158: // The URL to the directory of the HTMLArea JavaScript library.
159: String javascriptLibraryURL = (String) RendererUtil
160: .getAttribute(context, component,
161: "javascriptLibraryURL");
162: // If true show XPath at bottom of editor. Default is true.
163: String showXPath = (String) RendererUtil.getAttribute(context,
164: component, "showXPath");
165: showXPath = RendererUtil.makeSwitchString(showXPath, true,
166: true, true, false, false, true);
167:
168: ///////////////////////////////////////////////////////////////////////////
169:
170: // set up dimensions
171: int widthPx = DEFAULT_WIDTH_PX;
172: int heightPx = DEFAULT_HEIGHT_PX;
173: int textareaColumns = DEFAULT_COLUMNS;
174: int textareaRows = DEFAULT_ROWS;
175:
176: try {
177: Integer cols = (Integer) RendererUtil.getAttribute(context,
178: component, "cols");
179: Integer rows = (Integer) RendererUtil.getAttribute(context,
180: component, "rows");
181: if (cols != null)
182: textareaColumns = cols.intValue();
183: if (rows != null)
184: textareaRows = rows.intValue();
185:
186: // Width of the widget (in pixel units).
187: // If this attribute is not specified, the width is controlled by the 'cols' attribute.
188: String width = (String) RendererUtil.getAttribute(context,
189: component, "width");
190: if (width != null)
191: widthPx = Integer.parseInt(width);
192: // Height of the widget (in pixel units).
193: // If this attribute is not specified, the width is controlled by the 'rows' attribute.
194: String height = (String) RendererUtil.getAttribute(context,
195: component, "height");
196: if (height != null)
197: heightPx = Integer.parseInt(height);
198: } catch (Exception ex) {
199: //default, whatever goes awry
200: }
201:
202: if (widthPx == DEFAULT_WIDTH_PX
203: && textareaColumns != DEFAULT_COLUMNS)
204: widthPx = (DEFAULT_WIDTH_PX * textareaColumns)
205: / DEFAULT_COLUMNS;
206: if (heightPx == DEFAULT_HEIGHT_PX
207: && textareaRows != DEFAULT_ROWS)
208: heightPx = (DEFAULT_HEIGHT_PX * textareaRows)
209: / DEFAULT_ROWS;
210:
211: Locale locale = Locale.getDefault();
212:
213: String editor = ServerConfigurationService
214: .getString("wysiwyg.editor");
215: if (editor != null && !editor.equalsIgnoreCase("FCKeditor")) {
216: // Render JavaScripts.
217: writeExternalScripts(locale, writer);
218:
219: // Render base textarea.
220: writeTextArea(clientId, value, textareaRows,
221: textareaColumns, writer);
222:
223: // Make textarea rich text (unless textareaOnly is true).
224: if (!"true".equals(textareaOnly)) {
225: String toolbarScript;
226:
227: if (buttonList != null) {
228: toolbarScript = makeToolbarScript(buttonList);
229: } else {
230: toolbarScript = getStandardToolbarScript(buttonSet);
231: }
232:
233: // hook up configuration object
234: writeConfigurationScript(context, component, clientId,
235: toolbarScript, widthPx, heightPx, showXPath,
236: locale, writer);
237: }
238: } else {
239: //not as slick as the way htmlarea is rendered, but the difference in functionality doesn't all
240: //make sense for FCK at this time since it's already got the ability to insert files and such.
241: String collectionBase = (String) RendererUtil.getAttribute(
242: context, component, "collectionBase");
243: String collectionId = null;
244:
245: String connector = "/sakai-fck-connector/filemanager/connector";
246:
247: if (collectionBase != null) {
248: collectionId = collectionBase;
249: connector += collectionBase;
250: } else {
251: collectionId = ContentHostingService
252: .getSiteCollection(ToolManager
253: .getCurrentPlacement().getContext());
254: }
255:
256: writer.write("<table border=\"0\"><tr><td>");
257: writer.write("<textarea name=\"" + clientId
258: + "_inputRichText\" id=\"" + clientId
259: + "_inputRichText\"");
260: if (textareaColumns > 0)
261: writer.write(" cols=\"" + textareaColumns + "\"");
262: if (textareaRows > 0)
263: writer.write(" rows=\"" + textareaRows + "\"");
264: writer.write(">");
265: if (value != null)
266: writer.write((String) value);
267: writer.write("</textarea>");
268:
269: RendererUtil.writeExternalJSDependencies(context, writer,
270: "inputrichtext.jsf.fckeditor.js",
271: "/library/editor/FCKeditor/fckeditor.js");
272: //writer.write("<script type=\"text/javascript\" src=\"/library/editor/FCKeditor/fckeditor.js\"></script>\n");
273: writer
274: .write("<script type=\"text/javascript\" language=\"JavaScript\">\n");
275:
276: String attachmentVar = "attachment"
277: + createSafeRandomNumber();
278:
279: boolean hasAttachments = false;
280:
281: Object attchedFiles = RendererUtil.getAttribute(context,
282: component, "attachedFiles");
283: if (attchedFiles != null && getSize(attchedFiles) > 0) {
284: writeFilesArray(writer, attachmentVar, attchedFiles,
285: LIST_ITEM_FORMAT_FCK, false);
286: writer.write("\n");
287: hasAttachments = true;
288: }
289:
290: writer
291: .write("function chef_setupformattedtextarea(textarea_id){\n");
292: writer
293: .write("var oFCKeditor = new FCKeditor(textarea_id);\n");
294: writer
295: .write("oFCKeditor.BasePath = \"/library/editor/FCKeditor/\";\n");
296:
297: if (widthPx < 0)
298: widthPx = 600;
299: if (heightPx < 0)
300: heightPx = 400;
301: //FCK's toolset is larger then htmlarea and this prevents tools from ending up with all toolbar
302: //and no actual editing area.
303: if (heightPx < 200)
304: heightPx = 200;
305:
306: writer.write("oFCKeditor.Width = \"" + widthPx + "\" ;\n");
307: writer
308: .write("oFCKeditor.Height = \"" + heightPx
309: + "\" ;\n");
310:
311: if ("archival".equals(ServerConfigurationService
312: .getString("tags.focus")))
313: writer
314: .write("\n\toFCKeditor.Config['CustomConfigurationsPath'] = \"/library/editor/FCKeditor/archival_config.js\";\n");
315: else {
316:
317: writer.write("\n\t\tvar collectionId = \""
318: + collectionId + "\";");
319: writer
320: .write("\n\toFCKeditor.Config['ImageBrowserURL'] = oFCKeditor.BasePath + "
321: + "\"editor/filemanager/browser/default/browser.html?Connector="
322: + connector
323: + "&Type=Image&CurrentFolder=\" + collectionId;");
324: writer
325: .write("\n\toFCKeditor.Config['LinkBrowserURL'] = oFCKeditor.BasePath + "
326: + "\"editor/filemanager/browser/default/browser.html?Connector="
327: + connector
328: + "&Type=Link&CurrentFolder=\" + collectionId;");
329: writer
330: .write("\n\toFCKeditor.Config['FlashBrowserURL'] = oFCKeditor.BasePath + "
331: + "\"editor/filemanager/browser/default/browser.html?Connector="
332: + connector
333: + "&Type=Flash&CurrentFolder=\" + collectionId;");
334: writer
335: .write("\n\toFCKeditor.Config['ImageUploadURL'] = oFCKeditor.BasePath + "
336: + "\""
337: + connector
338: + "?Type=Image&Command=QuickUpload&Type=Image&CurrentFolder=\" + collectionId;");
339: writer
340: .write("\n\toFCKeditor.Config['FlashUploadURL'] = oFCKeditor.BasePath + "
341: + "\""
342: + connector
343: + "?Type=Flash&Command=QuickUpload&Type=Flash&CurrentFolder=\" + collectionId;");
344: writer
345: .write("\n\toFCKeditor.Config['LinkUploadURL'] = oFCKeditor.BasePath + "
346: + "\""
347: + connector
348: + "?Type=File&Command=QuickUpload&Type=Link&CurrentFolder=\" + collectionId;");
349:
350: writer
351: .write("\n\n\toFCKeditor.Config['CurrentFolder'] = collectionId;");
352:
353: writer
354: .write("\n\toFCKeditor.Config['CustomConfigurationsPath'] = \"/library/editor/FCKeditor/config.js\";\n");
355: }
356:
357: if (hasAttachments) {
358: writer
359: .write("\n\n\toFCKeditor.Config['AttachmentsVariable'] = \""
360: + attachmentVar + "\";");
361: writer
362: .write("\n\n\toFCKeditor.ToolbarSet = \"Attachments\";");
363: }
364:
365: writer.write("oFCKeditor.ReplaceTextarea();\n");
366: writer.write("} \n");
367: writer.write("</script>\n");
368: writer
369: .write("<script type=\"text/javascript\" defer=\"1\">chef_setupformattedtextarea('"
370: + clientId + "_inputRichText');</script>");
371: writer.write("</td></tr></table>\n");
372: }
373: }
374:
375: /**
376: * Return the config script portion for a standard button set.
377: * @param buttonSet
378: * @return
379: */
380: private String getStandardToolbarScript(String buttonSet) {
381: String toolbarScript;
382: if ("none".equals(buttonSet)) {
383: toolbarScript = TOOLBAR_SCRIPT_NONE;
384: } else if ("small".equals(buttonSet)) {
385: toolbarScript = TOOLBAR_SCRIPT_SMALL;
386: } else if ("medium".equals(buttonSet)) {
387: toolbarScript = TOOLBAR_SCRIPT_MEDIUM;
388: } else if ("large".equals(buttonSet)) {
389: toolbarScript = TOOLBAR_SCRIPT_LARGE;
390: } else {
391: toolbarScript = TOOLBAR_SCRIPT_MEDIUM;
392: }
393:
394: return toolbarScript;
395: }
396:
397: /**
398: * Write out HTML rextarea
399: * @param clientId
400: * @param value the textarrea value
401: * @param writer
402: * @throws IOException
403: */
404: private void writeTextArea(String clientId, String value, int rows,
405: int cols, ResponseWriter writer) throws IOException {
406:
407: // wrap the textarea in a table, so that the HTMLArea toolbar doesn't bleed to the
408: // edge of the screen.
409: writer.write("<table border=\"0\"><tr><td>\n");
410: writer.write("<textarea name=\"");
411: writer.write(clientId);
412: writer.write("_inputRichText\" id=\"");
413: writer.write(clientId);
414: writer.write("_inputRichText\"");
415: writer.write(" rows=\"" + rows + "\"");
416: writer.write(" cols=\"" + cols + "\"");
417: writer.write(">" + value + "</textarea>\n");
418: writer.write("</td></tr></table>\n");
419: }
420:
421: /**
422: * @todo do these as a document.write after testing if done
423: * @param contextPath
424: * @param writer
425: * @throws IOException
426: */
427: protected void writeExternalScripts(Locale locale,
428: ResponseWriter writer) throws IOException {
429: writer
430: .write("<script type=\"text/javascript\">var _editor_url = \""
431: + "/"
432: + RESOURCE_PATH
433: + "/"
434: + HTMLAREA_SCRIPT_PATH + "/" + "\";</script>\n");
435: writer.write("<script type=\"text/javascript\" src=\"" + "/"
436: + RESOURCE_PATH + "/" + HTMLAREA_SCRIPT_PATH + "/"
437: + "htmlarea.js\"></script>\n");
438: writer.write("<script type=\"text/javascript\" src=\"" + "/"
439: + RESOURCE_PATH + "/" + HTMLAREA_SCRIPT_PATH + "/"
440: + "dialog.js\"></script>\n");
441: writer.write("<script type=\"text/javascript\" src=\"" + "/"
442: + RESOURCE_PATH + "/" + HTMLAREA_SCRIPT_PATH + "/"
443: + "popupwin.js\"></script>\n");
444: writer.write("<script type=\"text/javascript\" src=\"" + "/"
445: + RESOURCE_PATH + "/" + HTMLAREA_SCRIPT_PATH + "/"
446: + "lang/en.js\"></script>\n");
447:
448: String language = locale.getLanguage();
449: if (!Locale.ENGLISH.equals(language)) {
450: writer.write("<script type=\"text/javascript\" src=\""
451: + "/" + RESOURCE_PATH + "/" + HTMLAREA_SCRIPT_PATH
452: + "/" + "lang/" + language + ".js\"></script>\n");
453: }
454: writer.write("<script type=\"text/javascript\" src=\"" + "/"
455: + RESOURCE_PATH + "/" + SCRIPT_PATH + "\"></script>\n");
456: }
457:
458: /**
459: * Standard decode method.
460: * @param context
461: * @param component
462: */
463: public void decode(FacesContext context, UIComponent component) {
464: if (RendererUtil.isDisabledOrReadonly(context, component))
465: return;
466:
467: if (null == context
468: || null == component
469: || !(component instanceof org.sakaiproject.jsf.component.InputRichTextComponent)) {
470: throw new IllegalArgumentException();
471: }
472:
473: String clientId = component.getClientId(context);
474:
475: Map requestParameterMap = context.getExternalContext()
476: .getRequestParameterMap();
477:
478: String newValue = (String) requestParameterMap.get(clientId
479: + "_inputRichText");
480:
481: org.sakaiproject.jsf.component.InputRichTextComponent comp = (org.sakaiproject.jsf.component.InputRichTextComponent) component;
482: comp.setSubmittedValue(newValue);
483: }
484:
485: /**
486: * Write configuration script
487: *
488: * @param clientId the client id
489: * @param toolbar the toolbar configuration string (i.e from makeToolbarScript())
490: * @param widthPx columns
491: * @param heightPx rows
492: */
493: protected void writeConfigurationScript(FacesContext context,
494: UIComponent component, String clientId, String toolbar,
495: int widthPx, int heightPx, String showXPath, Locale locale,
496: ResponseWriter writer) throws IOException {
497: // script creates unique Config object
498: String configVar = "config" + createSafeRandomNumber();
499:
500: writer.write("<script type=\"text/javascript\">\n");
501: writer.write(" sakaiSetLanguage(\""
502: + locale.getDisplayLanguage() + "\");");
503: writer
504: .write(" var " + configVar
505: + "=new HTMLArea.Config();\n");
506: writer.write(" sakaiRegisterButtons(" + configVar + ");\n");
507: writer
508: .write(" " + configVar + ".toolbar = " + toolbar
509: + ";\n");
510: writer.write(" " + configVar + ".width=\"" + widthPx
511: + "px\";\n");
512: writer.write(" " + configVar + ".height=\"" + heightPx
513: + "px\";\n");
514: writer.write(" " + configVar + ".statusBar=" + showXPath
515: + ";\n");
516: writeAdditionalConfig(context, component, configVar, clientId,
517: toolbar, widthPx, heightPx, locale, writer);
518: writer.write("sakaiSetupRichTextarea(\"");
519: writer.write(clientId);
520: writer.write("_inputRichText\"," + configVar + ");\n");
521: writer.write("</script>\n");
522: }
523:
524: /**
525: * subclasses can override to provide additonal configuration such as add buttons, etc
526: * @param context
527: * @param component
528: * @param configVar
529: * @param clientId
530: * @param toolbar
531: * @param widthPx
532: * @param heightPx
533: * @param locale
534: * @param writer
535: */
536: protected void writeAdditionalConfig(FacesContext context,
537: UIComponent component, String configVar, String clientId,
538: String toolbar, int widthPx, int heightPx, Locale locale,
539: ResponseWriter writer) throws IOException {
540: writeAttachedFiles(context, component, configVar, writer,
541: toolbar);
542: registerWithParent(component, configVar, clientId);
543: }
544:
545: protected void writeAttachedFiles(FacesContext context,
546: UIComponent component, String configVar,
547: ResponseWriter writer, String toolbar) throws IOException {
548: Object attchedFiles = RendererUtil.getAttribute(context,
549: component, "attachedFiles");
550: if (attchedFiles != null && getSize(attchedFiles) > 0) {
551: String arrayVar = configVar + "_Resources";
552:
553: writeFilesArray(writer, arrayVar, attchedFiles,
554: LIST_ITEM_FORMAT_HTML, true);
555:
556: writer.write("sakaiRegisterResourceList(");
557: writer.write(configVar + ",'" + INSERT_IMAGE_LOC + "',"
558: + arrayVar);
559: writer.write(");\n");
560:
561: writer.write(" " + configVar + ".toolbar = "
562: + addToolbar(toolbar) + ";\n");
563: }
564: }
565:
566: protected void writeFilesArray(ResponseWriter writer,
567: String arrayVar, Object attchedFiles, MessageFormat format,
568: boolean includeLabel) throws IOException {
569: StringWriter buffer = new StringWriter();
570:
571: char startChar = '[';
572: char endChar = ']';
573:
574: if (format == LIST_ITEM_FORMAT_HTML) {
575: startChar = '{';
576: endChar = '}';
577: }
578:
579: buffer.write(" var " + arrayVar + " = " + startChar + "\n");
580:
581: if (includeLabel) {
582: buffer.write("\"select a file url to insert\" : \"\"");
583: }
584:
585: if (attchedFiles instanceof Map) {
586: buffer.write(outputFiles((Map) attchedFiles, format,
587: !includeLabel));
588: } else {
589: buffer.write(outputFiles((List) attchedFiles, format,
590: !includeLabel));
591: }
592:
593: buffer.write(endChar + ";\n");
594: String result = buffer.toString();
595: writer.write(result);
596: }
597:
598: protected void registerWithParent(UIComponent component,
599: String configVar, String clientId) {
600:
601: InitObjectContainer parentContainer = null;
602:
603: UIComponent testContainer = component.getParent();
604: while (testContainer != null) {
605: if (testContainer instanceof InitObjectContainer) {
606: parentContainer = (InitObjectContainer) testContainer;
607:
608: String script = " resetRichTextEditor(\"" + clientId
609: + "_inputRichText\"," + configVar + ");\n";
610:
611: parentContainer.addInitScript(script);
612: }
613: testContainer = testContainer.getParent();
614: }
615: }
616:
617: protected String outputFiles(Map map, MessageFormat format,
618: boolean first) {
619: StringBuffer sb = new StringBuffer();
620:
621: for (Iterator i = map.entrySet().iterator(); i.hasNext();) {
622: Map.Entry entry = (Map.Entry) i.next();
623: if (!first) {
624: sb.append(',');
625: } else {
626: first = false;
627: }
628: format.format(new Object[] { entry.getValue(),
629: entry.getKey() }, sb, null);
630: }
631:
632: return sb.toString();
633: }
634:
635: protected String outputFiles(List list, MessageFormat format,
636: boolean first) {
637: StringBuffer sb = new StringBuffer();
638:
639: for (Iterator i = list.iterator(); i.hasNext();) {
640: Object value = i.next();
641:
642: String url;
643: String label;
644:
645: if (value instanceof SelectItem) {
646: SelectItem item = (SelectItem) value;
647: url = item.getValue().toString();
648: label = item.getLabel();
649: } else {
650: url = value.toString();
651: label = value.toString();
652: }
653:
654: if (!first) {
655: sb.append(',');
656: } else {
657: first = false;
658: }
659: format.format(new Object[] { label, url }, sb, null);
660: }
661:
662: return sb.toString();
663: }
664:
665: protected int getSize(Object attchedFiles) {
666: if (attchedFiles instanceof Map) {
667: return ((Map) attchedFiles).size();
668: } else {
669: return ((List) attchedFiles).size();
670: }
671: }
672:
673: protected String addToolbar(String toolbar) {
674: int pos = toolbar.lastIndexOf("]");
675: toolbar = toolbar.substring(0, pos)
676: + ",[\"filedropdown\", \"insertfile\", ]"
677: + toolbar.substring(pos);
678: return toolbar;
679: }
680:
681: /**
682: * Built toolbar part of configuration script for a list of button commands.
683: *
684: * @param buttonList csv list of buttons
685: * @return String, e.g.
686: * <code><pre>
687: * [["fontname", "space",... ]] etc.
688: * </pre></code>
689: *
690: */
691: private static String makeToolbarScript(String buttonList) {
692: StringBuffer script = new StringBuffer();
693: String q = "\"";
694:
695: script.append("[[");
696:
697: StringTokenizer st = new StringTokenizer(buttonList, ",", false);
698:
699: while (st.hasMoreTokens()) {
700: String command = st.nextToken();
701: if (!"linebreak".equals(command)) {
702: script.append(q + command + q + ", ");
703: } else {
704: script.append("],[");
705: }
706: }
707:
708: script.append("]]");
709: return script.toString();
710: }
711:
712: private String createSafeRandomNumber() {
713: return "" + (long) (Math.floor(Math.random() * 1000000000));
714: }
715:
716: }
|