This commit was manufactured by cvs2svn to create tag 'freeside_1_9_2'.
[freeside.git] / httemplate / elements / fckeditor / fckeditor.js
1 /*\r
2  * FCKeditor - The text editor for Internet - http://www.fckeditor.net\r
3  * Copyright (C) 2003-2007 Frederico Caldeira Knabben\r
4  *\r
5  * == BEGIN LICENSE ==\r
6  *\r
7  * Licensed under the terms of any of the following licenses at your\r
8  * choice:\r
9  *\r
10  *  - GNU General Public License Version 2 or later (the "GPL")\r
11  *    http://www.gnu.org/licenses/gpl.html\r
12  *\r
13  *  - GNU Lesser General Public License Version 2.1 or later (the "LGPL")\r
14  *    http://www.gnu.org/licenses/lgpl.html\r
15  *\r
16  *  - Mozilla Public License Version 1.1 or later (the "MPL")\r
17  *    http://www.mozilla.org/MPL/MPL-1.1.html\r
18  *\r
19  * == END LICENSE ==\r
20  *\r
21  * This is the integration file for JavaScript.\r
22  *\r
23  * It defines the FCKeditor class that can be used to create editor\r
24  * instances in a HTML page in the client side. For server side\r
25  * operations, use the specific integration system.\r
26  */\r
27 \r
28 // FCKeditor Class\r
29 var FCKeditor = function( instanceName, width, height, toolbarSet, value )\r
30 {\r
31         // Properties\r
32         this.InstanceName       = instanceName ;\r
33         this.Width                      = width                 || '100%' ;\r
34         this.Height                     = height                || '200' ;\r
35         this.ToolbarSet         = toolbarSet    || 'Default' ;\r
36         this.Value                      = value                 || '' ;\r
37         this.BasePath           = '/fckeditor/' ;\r
38         this.CheckBrowser       = true ;\r
39         this.DisplayErrors      = true ;\r
40         this.EnableSafari       = false ;               // This is a temporary property, while Safari support is under development.\r
41         this.EnableOpera        = false ;               // This is a temporary property, while Opera support is under development.\r
42 \r
43         this.Config                     = new Object() ;\r
44 \r
45         // Events\r
46         this.OnError            = null ;        // function( source, errorNumber, errorDescription )\r
47 }\r
48 \r
49 FCKeditor.prototype.Version                     = '2.4.3' ;\r
50 FCKeditor.prototype.VersionBuild        = '15657' ;\r
51 \r
52 FCKeditor.prototype.Create = function()\r
53 {\r
54         document.write( this.CreateHtml() ) ;\r
55 }\r
56 \r
57 FCKeditor.prototype.CreateHtml = function()\r
58 {\r
59         // Check for errors\r
60         if ( !this.InstanceName || this.InstanceName.length == 0 )\r
61         {\r
62                 this._ThrowError( 701, 'You must specify an instance name.' ) ;\r
63                 return '' ;\r
64         }\r
65 \r
66         var sHtml = '<div>' ;\r
67 \r
68         if ( !this.CheckBrowser || this._IsCompatibleBrowser() )\r
69         {\r
70                 sHtml += '<input type="hidden" id="' + this.InstanceName + '" name="' + this.InstanceName + '" value="' + this._HTMLEncode( this.Value ) + '" style="display:none" />' ;\r
71                 sHtml += this._GetConfigHtml() ;\r
72                 sHtml += this._GetIFrameHtml() ;\r
73         }\r
74         else\r
75         {\r
76                 var sWidth  = this.Width.toString().indexOf('%')  > 0 ? this.Width  : this.Width  + 'px' ;\r
77                 var sHeight = this.Height.toString().indexOf('%') > 0 ? this.Height : this.Height + 'px' ;\r
78                 sHtml += '<textarea name="' + this.InstanceName + '" rows="4" cols="40" style="width:' + sWidth + ';height:' + sHeight + '">' + this._HTMLEncode( this.Value ) + '<\/textarea>' ;\r
79         }\r
80 \r
81         sHtml += '</div>' ;\r
82 \r
83         return sHtml ;\r
84 }\r
85 \r
86 FCKeditor.prototype.ReplaceTextarea = function()\r
87 {\r
88         if ( !this.CheckBrowser || this._IsCompatibleBrowser() )\r
89         {\r
90                 // We must check the elements firstly using the Id and then the name.\r
91                 var oTextarea = document.getElementById( this.InstanceName ) ;\r
92                 var colElementsByName = document.getElementsByName( this.InstanceName ) ;\r
93                 var i = 0;\r
94                 while ( oTextarea || i == 0 )\r
95                 {\r
96                         if ( oTextarea && oTextarea.tagName.toLowerCase() == 'textarea' )\r
97                                 break ;\r
98                         oTextarea = colElementsByName[i++] ;\r
99                 }\r
100 \r
101                 if ( !oTextarea )\r
102                 {\r
103                         alert( 'Error: The TEXTAREA with id or name set to "' + this.InstanceName + '" was not found' ) ;\r
104                         return ;\r
105                 }\r
106 \r
107                 oTextarea.style.display = 'none' ;\r
108                 this._InsertHtmlBefore( this._GetConfigHtml(), oTextarea ) ;\r
109                 this._InsertHtmlBefore( this._GetIFrameHtml(), oTextarea ) ;\r
110         }\r
111 }\r
112 \r
113 FCKeditor.prototype._InsertHtmlBefore = function( html, element )\r
114 {\r
115         if ( element.insertAdjacentHTML )       // IE\r
116                 element.insertAdjacentHTML( 'beforeBegin', html ) ;\r
117         else                                                            // Gecko\r
118         {\r
119                 var oRange = document.createRange() ;\r
120                 oRange.setStartBefore( element ) ;\r
121                 var oFragment = oRange.createContextualFragment( html );\r
122                 element.parentNode.insertBefore( oFragment, element ) ;\r
123         }\r
124 }\r
125 \r
126 FCKeditor.prototype._GetConfigHtml = function()\r
127 {\r
128         var sConfig = '' ;\r
129         for ( var o in this.Config )\r
130         {\r
131                 if ( sConfig.length > 0 ) sConfig += '&amp;' ;\r
132                 sConfig += encodeURIComponent( o ) + '=' + encodeURIComponent( this.Config[o] ) ;\r
133         }\r
134 \r
135         return '<input type="hidden" id="' + this.InstanceName + '___Config" value="' + sConfig + '" style="display:none" />' ;\r
136 }\r
137 \r
138 FCKeditor.prototype._GetIFrameHtml = function()\r
139 {\r
140         var sFile = 'fckeditor.html' ;\r
141 \r
142         try\r
143         {\r
144                 if ( (/fcksource=true/i).test( window.top.location.search ) )\r
145                         sFile = 'fckeditor.original.html' ;\r
146         }\r
147         catch (e) { /* Ignore it. Much probably we are inside a FRAME where the "top" is in another domain (security error). */ }\r
148 \r
149         var sLink = this.BasePath + 'editor/' + sFile + '?InstanceName=' + encodeURIComponent( this.InstanceName ) ;\r
150         if (this.ToolbarSet) sLink += '&amp;Toolbar=' + this.ToolbarSet ;\r
151 \r
152         return '<iframe id="' + this.InstanceName + '___Frame" src="' + sLink + '" width="' + this.Width + '" height="' + this.Height + '" frameborder="0" scrolling="no"></iframe>' ;\r
153 }\r
154 \r
155 FCKeditor.prototype._IsCompatibleBrowser = function()\r
156 {\r
157         return FCKeditor_IsCompatibleBrowser( this.EnableSafari, this.EnableOpera ) ;\r
158 }\r
159 \r
160 FCKeditor.prototype._ThrowError = function( errorNumber, errorDescription )\r
161 {\r
162         this.ErrorNumber                = errorNumber ;\r
163         this.ErrorDescription   = errorDescription ;\r
164 \r
165         if ( this.DisplayErrors )\r
166         {\r
167                 document.write( '<div style="COLOR: #ff0000">' ) ;\r
168                 document.write( '[ FCKeditor Error ' + this.ErrorNumber + ': ' + this.ErrorDescription + ' ]' ) ;\r
169                 document.write( '</div>' ) ;\r
170         }\r
171 \r
172         if ( typeof( this.OnError ) == 'function' )\r
173                 this.OnError( this, errorNumber, errorDescription ) ;\r
174 }\r
175 \r
176 FCKeditor.prototype._HTMLEncode = function( text )\r
177 {\r
178         if ( typeof( text ) != "string" )\r
179                 text = text.toString() ;\r
180 \r
181         text = text.replace(\r
182                 /&/g, "&amp;").replace(\r
183                 /"/g, "&quot;").replace(\r
184                 /</g, "&lt;").replace(\r
185                 />/g, "&gt;") ;\r
186 \r
187         return text ;\r
188 }\r
189 \r
190 function FCKeditor_IsCompatibleBrowser( enableSafari, enableOpera )\r
191 {\r
192         var sAgent = navigator.userAgent.toLowerCase() ;\r
193 \r
194         // Internet Explorer\r
195         if ( sAgent.indexOf("msie") != -1 && sAgent.indexOf("mac") == -1 && sAgent.indexOf("opera") == -1 )\r
196         {\r
197                 var sBrowserVersion = navigator.appVersion.match(/MSIE (.\..)/)[1] ;\r
198                 return ( sBrowserVersion >= 5.5 ) ;\r
199         }\r
200 \r
201         // Gecko (Opera 9 tries to behave like Gecko at this point).\r
202         if ( navigator.product == "Gecko" && navigator.productSub >= 20030210 && !( typeof(opera) == 'object' && opera.postError ) )\r
203                 return true ;\r
204 \r
205         // Opera\r
206         if ( enableOpera && sAgent.indexOf( 'opera' ) == 0 && parseInt( navigator.appVersion, 10 ) >= 9 )\r
207                         return true ;\r
208 \r
209         // Safari\r
210         if ( enableSafari && sAgent.indexOf( 'safari' ) != -1 )\r
211                 return ( sAgent.match( /safari\/(\d+)/ )[1] >= 312 ) ;  // Build must be at least 312 (1.3)\r
212 \r
213         return false ;\r
214 }