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