1<cfcomponent output="false" displayname="FCKeditor" hint="Create an instance of the FCKeditor.">
2
3<!---
4 * FCKeditor - The text editor for Internet - http://www.fckeditor.net
5 * Copyright (C) 2003-2007 Frederico Caldeira Knabben
6 *
7 * == BEGIN LICENSE ==
8 *
9 * Licensed under the terms of any of the following licenses at your
10 * choice:
11 *
12 *  - GNU General Public License Version 2 or later (the "GPL")
13 *    http://www.gnu.org/licenses/gpl.html
14 *
15 *  - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
16 *    http://www.gnu.org/licenses/lgpl.html
17 *
18 *  - Mozilla Public License Version 1.1 or later (the "MPL")
19 *    http://www.mozilla.org/MPL/MPL-1.1.html
20 *
21 * == END LICENSE ==
22 *
23 * ColdFusion MX integration.
24 * Note this CFC is created for use only with Coldfusion MX and above.
25 * For older version, check the fckeditor.cfm.
26 *
27 * Syntax:
28 *
29 * <cfscript>
30 * 		fckEditor = createObject("component", "fckeditor.fckeditor");
31 * 		fckEditor.instanceName="myEditor";
32 * 		fckEditor.basePath="/fckeditor/";
33 * 		fckEditor.value="<p>This is my <strong>initial</strong> html text.</p>";
34 * 		fckEditor.width="100%";
35 * 		fckEditor.height="200";
36 * 	 	// ... additional parameters ...
37 * 		fckEditor.create(); // create instance now.
38 * </cfscript>
39 *
40 * See your macromedia coldfusion mx documentation for more info.
41 *
42 * *** Note:
43 * Do not use path names with a "." (dot) in the name. This is a coldfusion
44 * limitation with the cfc invocation.
45--->
46
47<cffunction
48	name="Create"
49	access="public"
50	output="true"
51	returntype="void"
52	hint="Outputs the editor HTML in the place where the function is called"
53>
54	<cfoutput>#CreateHtml()#</cfoutput>
55</cffunction>
56
57<cffunction
58	name="CreateHtml"
59	access="public"
60	output="false"
61	returntype="string"
62	hint="Retrieves the editor HTML"
63>
64
65	<cfparam name="this.instanceName" type="string" />
66	<cfparam name="this.width" type="string" default="100%" />
67	<cfparam name="this.height" type="string" default="200" />
68	<cfparam name="this.toolbarSet" type="string" default="Default" />
69	<cfparam name="this.value" type="string" default="" />
70	<cfparam name="this.basePath" type="string" default="/fckeditor/" />
71	<cfparam name="this.checkBrowser" type="boolean" default="true" />
72	<cfparam name="this.config" type="struct" default="#structNew()#" />
73
74	<cfscript>
75	// display the html editor or a plain textarea?
76	if( isCompatible() )
77		return getHtmlEditor();
78	else
79		return getTextArea();
80	</cfscript>
81
82</cffunction>
83
84<cffunction
85	name="isCompatible"
86	access="private"
87	output="false"
88	returnType="boolean"
89	hint="Check browser compatibility via HTTP_USER_AGENT, if checkBrowser is true"
90>
91
92	<cfscript>
93	var sAgent = lCase( cgi.HTTP_USER_AGENT );
94	var stResult = "";
95	var sBrowserVersion = "";
96
97	// do not check if argument "checkBrowser" is false
98	if( not this.checkBrowser )
99		return true;
100
101	// check for Internet Explorer ( >= 5.5 )
102	if( find( "msie", sAgent ) and not find( "mac", sAgent ) and not find( "opera", sAgent ) )
103	{
104		// try to extract IE version
105		stResult = reFind( "msie ([5-9]\.[0-9])", sAgent, 1, true );
106		if( arrayLen( stResult.pos ) eq 2 )
107		{
108			// get IE Version
109			sBrowserVersion = mid( sAgent, stResult.pos[2], stResult.len[2] );
110			return ( sBrowserVersion GTE 5.5 );
111		}
112	}
113	// check for Gecko ( >= 20030210+ )
114	else if( find( "gecko/", sAgent ) )
115	{
116		// try to extract Gecko version date
117		stResult = reFind( "gecko/(200[3-9][0-1][0-9][0-3][0-9])", sAgent, 1, true );
118		if( arrayLen( stResult.pos ) eq 2 )
119		{
120			// get Gecko build (i18n date)
121			sBrowserVersion = mid( sAgent, stResult.pos[2], stResult.len[2] );
122			return ( sBrowserVersion GTE 20030210 );
123		}
124	}
125	else if( find( "opera/", sAgent ) )
126	{
127		// try to extract Opera version
128		stResult = reFind( "opera/([0-9]+\.[0-9]+)", sAgent, 1, true );
129		if( arrayLen( stResult.pos ) eq 2 )
130		{
131			return ( mid( sAgent, stResult.pos[2], stResult.len[2] ) gte 9.5);
132		}
133	}
134	else if( find( "applewebkit", sAgent ) )
135	{
136		// try to extract Gecko version date
137		stResult = reFind( "applewebkit/([0-9]+)", sAgent, 1, true );
138		if( arrayLen( stResult.pos ) eq 2 )
139		{
140			return ( mid( sAgent, stResult.pos[2], stResult.len[2] ) gte 522 );
141		}
142	}
143
144	return false;
145	</cfscript>
146</cffunction>
147
148<cffunction
149	name="getTextArea"
150	access="private"
151	output="false"
152	returnType="string"
153	hint="Create a textarea field for non-compatible browsers."
154>
155	<cfset var result = "" />
156
157	<cfscript>
158	// append unit "px" for numeric width and/or height values
159	if( isNumeric( this.width ) )
160		this.width = this.width & "px";
161	if( isNumeric( this.height ) )
162		this.height = this.height & "px";
163	</cfscript>
164
165	<cfscript>
166	result = result & "<div>" & chr(13) & chr(10);
167	result = result & "<textarea name=""#this.instanceName#"" rows=""4"" cols=""40"" style=""WIDTH: #this.width#; HEIGHT: #this.height#"">#HTMLEditFormat(this.value)#</textarea>" & chr(13) & chr(10);
168	result = result & "</div>" & chr(13) & chr(10);
169	</cfscript>
170	<cfreturn result />
171</cffunction>
172
173<cffunction
174	name="getHtmlEditor"
175	access="private"
176	output="false"
177	returnType="string"
178	hint="Create the html editor instance for compatible browsers."
179>
180	<cfset var sURL = "" />
181	<cfset var result = "" />
182
183	<cfscript>
184	// try to fix the basePath, if ending slash is missing
185	if( len( this.basePath) and right( this.basePath, 1 ) is not "/" )
186		this.basePath = this.basePath & "/";
187
188	// construct the url
189	sURL = this.basePath & "editor/fckeditor.html?InstanceName=" & this.instanceName;
190
191	// append toolbarset name to the url
192	if( len( this.toolbarSet ) )
193		sURL = sURL & "&amp;Toolbar=" & this.toolbarSet;
194	</cfscript>
195
196	<cfscript>
197	result = result & "<div>" & chr(13) & chr(10);
198	result = result & "<input type=""hidden"" id=""#this.instanceName#"" name=""#this.instanceName#"" value=""#HTMLEditFormat(this.value)#"" style=""display:none"" />" & chr(13) & chr(10);
199	result = result & "<input type=""hidden"" id=""#this.instanceName#___Config"" value=""#GetConfigFieldString()#"" style=""display:none"" />" & chr(13) & chr(10);
200	result = result & "<iframe id=""#this.instanceName#___Frame"" src=""#sURL#"" width=""#this.width#"" height=""#this.height#"" frameborder=""0"" scrolling=""no""></iframe>" & chr(13) & chr(10);
201	result = result & "</div>" & chr(13) & chr(10);
202	</cfscript>
203	<cfreturn result />
204</cffunction>
205
206<cffunction
207	name="GetConfigFieldString"
208	access="private"
209	output="false"
210	returnType="string"
211	hint="Create configuration string: Key1=Value1&Key2=Value2&... (Key/Value:HTML encoded)"
212>
213	<cfset var sParams = "" />
214	<cfset var key = "" />
215	<cfset var fieldValue = "" />
216	<cfset var fieldLabel = "" />
217	<cfset var lConfigKeys = "" />
218	<cfset var iPos = "" />
219
220	<cfscript>
221	/**
222	 * CFML doesn't store casesensitive names for structure keys, but the configuration names must be casesensitive for js.
223	 * So we need to find out the correct case for the configuration keys.
224	 * We "fix" this by comparing the caseless configuration keys to a list of all available configuration options in the correct case.
225	 * changed 20041206 hk@lwd.de (improvements are welcome!)
226	 */
227	lConfigKeys = lConfigKeys & "CustomConfigurationsPath,EditorAreaCSS,ToolbarComboPreviewCSS,DocType";
228	lConfigKeys = lConfigKeys & ",BaseHref,FullPage,Debug,AllowQueryStringDebug,SkinPath";
229	lConfigKeys = lConfigKeys & ",PreloadImages,PluginsPath,AutoDetectLanguage,DefaultLanguage,ContentLangDirection";
230	lConfigKeys = lConfigKeys & ",ProcessHTMLEntities,IncludeLatinEntities,IncludeGreekEntities,ProcessNumericEntities,AdditionalNumericEntities";
231	lConfigKeys = lConfigKeys & ",FillEmptyBlocks,FormatSource,FormatOutput,FormatIndentator";
232	lConfigKeys = lConfigKeys & ",GeckoUseSPAN,StartupFocus,ForcePasteAsPlainText,AutoDetectPasteFromWord,ForceSimpleAmpersand";
233	lConfigKeys = lConfigKeys & ",TabSpaces,ShowBorders,SourcePopup,ToolbarStartExpanded,ToolbarCanCollapse";
234	lConfigKeys = lConfigKeys & ",IgnoreEmptyParagraphValue,PreserveSessionOnFileBrowser,FloatingPanelsZIndex,TemplateReplaceAll,TemplateReplaceCheckbox";
235	lConfigKeys = lConfigKeys & ",ToolbarLocation,ToolbarSets,EnterMode,ShiftEnterMode,Keystrokes";
236	lConfigKeys = lConfigKeys & ",ContextMenu,BrowserContextMenuOnCtrl,FontColors,FontNames,FontSizes";
237	lConfigKeys = lConfigKeys & ",FontFormats,StylesXmlPath,TemplatesXmlPath,SpellChecker,IeSpellDownloadUrl";
238	lConfigKeys = lConfigKeys & ",SpellerPagesServerScript,FirefoxSpellChecker,MaxUndoLevels,DisableObjectResizing,DisableFFTableHandles";
239	lConfigKeys = lConfigKeys & ",LinkDlgHideTarget,LinkDlgHideAdvanced,ImageDlgHideLink,ImageDlgHideAdvanced,FlashDlgHideAdvanced";
240	lConfigKeys = lConfigKeys & ",ProtectedTags,BodyId,BodyClass,DefaultLinkTarget,CleanWordKeepsStructure";
241	lConfigKeys = lConfigKeys & ",LinkBrowser,LinkBrowserURL,LinkBrowserWindowWidth,LinkBrowserWindowHeight,ImageBrowser";
242	lConfigKeys = lConfigKeys & ",ImageBrowserURL,ImageBrowserWindowWidth,ImageBrowserWindowHeight,FlashBrowser,FlashBrowserURL";
243	lConfigKeys = lConfigKeys & ",FlashBrowserWindowWidth,FlashBrowserWindowHeight,LinkUpload,LinkUploadURL,LinkUploadWindowWidth";
244	lConfigKeys = lConfigKeys & ",LinkUploadWindowHeight,LinkUploadAllowedExtensions,LinkUploadDeniedExtensions,ImageUpload,ImageUploadURL";
245	lConfigKeys = lConfigKeys & ",ImageUploadAllowedExtensions,ImageUploadDeniedExtensions,FlashUpload,FlashUploadURL,FlashUploadAllowedExtensions";
246	lConfigKeys = lConfigKeys & ",FlashUploadDeniedExtensions,SmileyPath,SmileyImages,SmileyColumns,SmileyWindowWidth,SmileyWindowHeight";
247
248	for( key in this.config )
249	{
250		iPos = listFindNoCase( lConfigKeys, key );
251		if( iPos GT 0 )
252		{
253			if( len( sParams ) )
254				sParams = sParams & "&amp;";
255
256			fieldValue = this.config[key];
257			fieldName = listGetAt( lConfigKeys, iPos );
258
259			// set all boolean possibilities in CFML to true/false values
260			if( isBoolean( fieldValue) and fieldValue )
261				fieldValue = "true";
262			else if( isBoolean( fieldValue) )
263				fieldValue = "false";
264
265			sParams = sParams & HTMLEditFormat( fieldName ) & '=' & HTMLEditFormat( fieldValue );
266		}
267	}
268	return sParams;
269	</cfscript>
270
271</cffunction>
272
273</cfcomponent>
274