~ubuntu-it-wiki/wiki-ubuntu-it/wiki-repo

« back to all changes in this revision

Viewing changes to applets/FCKeditor/editor/_source/classes/fckeditingarea.js

  • Committer: Leo Iannacone
  • Date: 2011-06-02 15:05:37 UTC
  • Revision ID: l3on@ubuntu.com-20110602150537-ycrnf58qf67uf593
Added applets for gui editor

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * FCKeditor - The text editor for Internet - http://www.fckeditor.net
 
3
 * Copyright (C) 2003-2010 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
 * FCKEditingArea Class: renders an editable area.
 
22
 */
 
23
 
 
24
/**
 
25
 * @constructor
 
26
 * @param {String} targetElement The element that will hold the editing area. Any child element present in the target will be deleted.
 
27
 */
 
28
var FCKEditingArea = function( targetElement )
 
29
{
 
30
        this.TargetElement = targetElement ;
 
31
        this.Mode = FCK_EDITMODE_WYSIWYG ;
 
32
 
 
33
        if ( FCK.IECleanup )
 
34
                FCK.IECleanup.AddItem( this, FCKEditingArea_Cleanup ) ;
 
35
}
 
36
 
 
37
 
 
38
/**
 
39
 * @param {String} html The complete HTML for the page, including DOCTYPE and the <html> tag.
 
40
 */
 
41
FCKEditingArea.prototype.Start = function( html, secondCall )
 
42
{
 
43
        var eTargetElement      = this.TargetElement ;
 
44
        var oTargetDocument     = FCKTools.GetElementDocument( eTargetElement ) ;
 
45
 
 
46
        // Remove all child nodes from the target.
 
47
        while( eTargetElement.firstChild )
 
48
                eTargetElement.removeChild( eTargetElement.firstChild ) ;
 
49
 
 
50
        if ( this.Mode == FCK_EDITMODE_WYSIWYG )
 
51
        {
 
52
                // For FF, document.domain must be set only when different, otherwhise
 
53
                // we'll strangely have "Permission denied" issues.
 
54
                if ( FCK_IS_CUSTOM_DOMAIN )
 
55
                        html = '<script>document.domain="' + FCK_RUNTIME_DOMAIN + '";</script>' + html ;
 
56
 
 
57
                // IE has a bug with the <base> tag... it must have a </base> closer,
 
58
                // otherwise the all successive tags will be set as children nodes of the <base>.
 
59
                if ( FCKBrowserInfo.IsIE )
 
60
                        html = html.replace( /(<base[^>]*?)\s*\/?>(?!\s*<\/base>)/gi, '$1></base>' ) ;
 
61
                else if ( !secondCall )
 
62
                {
 
63
                        // Gecko moves some tags out of the body to the head, so we must use
 
64
                        // innerHTML to set the body contents (SF BUG 1526154).
 
65
 
 
66
                        // Extract the BODY contents from the html.
 
67
                        var oMatchBefore = html.match( FCKRegexLib.BeforeBody ) ;
 
68
                        var oMatchAfter = html.match( FCKRegexLib.AfterBody ) ;
 
69
 
 
70
                        if ( oMatchBefore && oMatchAfter )
 
71
                        {
 
72
                                var sBody = html.substr( oMatchBefore[1].length,
 
73
                                               html.length - oMatchBefore[1].length - oMatchAfter[1].length ) ; // This is the BODY tag contents.
 
74
 
 
75
                                html =
 
76
                                        oMatchBefore[1] +                       // This is the HTML until the <body...> tag, inclusive.
 
77
                                        '&nbsp;' +
 
78
                                        oMatchAfter[1] ;                        // This is the HTML from the </body> tag, inclusive.
 
79
 
 
80
                                // If nothing in the body, place a BOGUS tag so the cursor will appear.
 
81
                                if ( FCKBrowserInfo.IsGecko && ( sBody.length == 0 || FCKRegexLib.EmptyParagraph.test( sBody ) ) )
 
82
                                        sBody = '<br type="_moz">' ;
 
83
 
 
84
                                this._BodyHTML = sBody ;
 
85
 
 
86
                        }
 
87
                        else
 
88
                                this._BodyHTML = html ;                 // Invalid HTML input.
 
89
                }
 
90
 
 
91
                // Create the editing area IFRAME.
 
92
                var oIFrame = this.IFrame = oTargetDocument.createElement( 'iframe' ) ;
 
93
 
 
94
                // IE: Avoid JavaScript errors thrown by the editing are source (like tags events).
 
95
                // See #1055.
 
96
                var sOverrideError = '<script type="text/javascript" _fcktemp="true">window.onerror=function(){return true;};</script>' ;
 
97
 
 
98
                oIFrame.frameBorder = 0 ;
 
99
                oIFrame.style.width = oIFrame.style.height = '100%' ;
 
100
 
 
101
                if ( FCK_IS_CUSTOM_DOMAIN && FCKBrowserInfo.IsIE )
 
102
                {
 
103
                        window._FCKHtmlToLoad = html.replace( /<head>/i, '<head>' + sOverrideError ) ;
 
104
                        oIFrame.src = 'javascript:void( (function(){' +
 
105
                                'document.open() ;' +
 
106
                                'document.domain="' + document.domain + '" ;' +
 
107
                                'document.write( window.parent._FCKHtmlToLoad );' +
 
108
                                'document.close() ;' +
 
109
                                'window.parent._FCKHtmlToLoad = null ;' +
 
110
                                '})() )' ;
 
111
                }
 
112
                else if ( !FCKBrowserInfo.IsGecko )
 
113
                {
 
114
                        // Firefox will render the tables inside the body in Quirks mode if the
 
115
                        // source of the iframe is set to javascript. see #515
 
116
                        oIFrame.src = 'javascript:void(0)' ;
 
117
                }
 
118
 
 
119
                // Append the new IFRAME to the target. For IE, it must be done after
 
120
                // setting the "src", to avoid the "secure/unsecure" message under HTTPS.
 
121
                eTargetElement.appendChild( oIFrame ) ;
 
122
 
 
123
                // Get the window and document objects used to interact with the newly created IFRAME.
 
124
                this.Window = oIFrame.contentWindow ;
 
125
 
 
126
                // IE: Avoid JavaScript errors thrown by the editing are source (like tags events).
 
127
                // TODO: This error handler is not being fired.
 
128
                // this.Window.onerror = function() { alert( 'Error!' ) ; return true ; }
 
129
 
 
130
                if ( !FCK_IS_CUSTOM_DOMAIN || !FCKBrowserInfo.IsIE )
 
131
                {
 
132
                        var oDoc = this.Window.document ;
 
133
 
 
134
                        oDoc.open() ;
 
135
                        oDoc.write( html.replace( /<head>/i, '<head>' + sOverrideError ) ) ;
 
136
                        oDoc.close() ;
 
137
                }
 
138
 
 
139
                if ( FCKBrowserInfo.IsAIR )
 
140
                        FCKAdobeAIR.EditingArea_Start( oDoc, html ) ;
 
141
 
 
142
                // Firefox 1.0.x is buggy... ohh yes... so let's do it two times and it
 
143
                // will magically work.
 
144
                if ( FCKBrowserInfo.IsGecko10 && !secondCall )
 
145
                {
 
146
                        this.Start( html, true ) ;
 
147
                        return ;
 
148
                }
 
149
 
 
150
                if ( oIFrame.readyState && oIFrame.readyState != 'completed' )
 
151
                {
 
152
                        var editArea = this ;
 
153
 
 
154
                        // Using a IE alternative for DOMContentLoaded, similar to the
 
155
                        // solution proposed at http://javascript.nwbox.com/IEContentLoaded/
 
156
                        setTimeout( function()
 
157
                                        {
 
158
                                                try
 
159
                                                {
 
160
                                                        editArea.Window.document.documentElement.doScroll("left") ;
 
161
                                                }
 
162
                                                catch(e)
 
163
                                                {
 
164
                                                        setTimeout( arguments.callee, 0 ) ;
 
165
                                                        return ;
 
166
                                                }
 
167
                                                editArea.Window._FCKEditingArea = editArea ;
 
168
                                                FCKEditingArea_CompleteStart.call( editArea.Window ) ;
 
169
                                        }, 0 ) ;
 
170
                }
 
171
                else
 
172
                {
 
173
                        this.Window._FCKEditingArea = this ;
 
174
 
 
175
                        // FF 1.0.x is buggy... we must wait a lot to enable editing because
 
176
                        // sometimes the content simply disappears, for example when pasting
 
177
                        // "bla1!<img src='some_url'>!bla2" in the source and then switching
 
178
                        // back to design.
 
179
                        if ( FCKBrowserInfo.IsGecko10 )
 
180
                                this.Window.setTimeout( FCKEditingArea_CompleteStart, 500 ) ;
 
181
                        else
 
182
                                FCKEditingArea_CompleteStart.call( this.Window ) ;
 
183
                }
 
184
        }
 
185
        else
 
186
        {
 
187
                var eTextarea = this.Textarea = oTargetDocument.createElement( 'textarea' ) ;
 
188
                eTextarea.className = 'SourceField' ;
 
189
                eTextarea.dir = 'ltr' ;
 
190
                FCKDomTools.SetElementStyles( eTextarea,
 
191
                        {
 
192
                                width   : '100%',
 
193
                                height  : '100%',
 
194
                                border  : 'none',
 
195
                                resize  : 'none',
 
196
                                outline : 'none'
 
197
                        } ) ;
 
198
                eTargetElement.appendChild( eTextarea ) ;
 
199
 
 
200
                eTextarea.value = html  ;
 
201
 
 
202
                // Fire the "OnLoad" event.
 
203
                FCKTools.RunFunction( this.OnLoad ) ;
 
204
        }
 
205
}
 
206
 
 
207
// "this" here is FCKEditingArea.Window
 
208
function FCKEditingArea_CompleteStart()
 
209
{
 
210
        // On Firefox, the DOM takes a little to become available. So we must wait for it in a loop.
 
211
        if ( !this.document.body )
 
212
        {
 
213
                this.setTimeout( FCKEditingArea_CompleteStart, 50 ) ;
 
214
                return ;
 
215
        }
 
216
 
 
217
        var oEditorArea = this._FCKEditingArea ;
 
218
 
 
219
        // Save this reference to be re-used later.
 
220
        oEditorArea.Document = oEditorArea.Window.document ;
 
221
 
 
222
        oEditorArea.MakeEditable() ;
 
223
 
 
224
        // Fire the "OnLoad" event.
 
225
        FCKTools.RunFunction( oEditorArea.OnLoad ) ;
 
226
}
 
227
 
 
228
FCKEditingArea.prototype.MakeEditable = function()
 
229
{
 
230
        var oDoc = this.Document ;
 
231
 
 
232
        if ( FCKBrowserInfo.IsIE )
 
233
        {
 
234
                // Kludge for #141 and #523
 
235
                oDoc.body.disabled = true ;
 
236
                oDoc.body.contentEditable = true ;
 
237
                oDoc.body.removeAttribute( "disabled" ) ;
 
238
 
 
239
                /* The following commands don't throw errors, but have no effect.
 
240
                oDoc.execCommand( 'AutoDetect', false, false ) ;
 
241
                oDoc.execCommand( 'KeepSelection', false, true ) ;
 
242
                */
 
243
        }
 
244
        else
 
245
        {
 
246
                try
 
247
                {
 
248
                        // Disable Firefox 2 Spell Checker.
 
249
                        oDoc.body.spellcheck = ( this.FFSpellChecker !== false ) ;
 
250
 
 
251
                        if ( this._BodyHTML )
 
252
                        {
 
253
                                oDoc.body.innerHTML = this._BodyHTML ;
 
254
                                oDoc.body.offsetLeft ;          // Don't remove, this is a hack to fix Opera 9.50, see #2264.
 
255
                                this._BodyHTML = null ;
 
256
                        }
 
257
 
 
258
                        oDoc.designMode = 'on' ;
 
259
 
 
260
                        // Tell Gecko (Firefox 1.5+) to enable or not live resizing of objects (by Alfonso Martinez)
 
261
                        oDoc.execCommand( 'enableObjectResizing', false, !FCKConfig.DisableObjectResizing ) ;
 
262
 
 
263
                        // Disable the standard table editing features of Firefox.
 
264
                        oDoc.execCommand( 'enableInlineTableEditing', false, !FCKConfig.DisableFFTableHandles ) ;
 
265
                }
 
266
                catch (e)
 
267
                {
 
268
                        // In Firefox if the iframe is initially hidden it can't be set to designMode and it raises an exception
 
269
                        // So we set up a DOM Mutation event Listener on the HTML, as it will raise several events when the document is  visible again
 
270
                        FCKTools.AddEventListener( this.Window.frameElement, 'DOMAttrModified', FCKEditingArea_Document_AttributeNodeModified ) ;
 
271
                }
 
272
 
 
273
        }
 
274
}
 
275
 
 
276
// This function processes the notifications of the DOM Mutation event on the document
 
277
// We use it to know that the document will be ready to be editable again (or we hope so)
 
278
function FCKEditingArea_Document_AttributeNodeModified( evt )
 
279
{
 
280
        var editingArea = evt.currentTarget.contentWindow._FCKEditingArea ;
 
281
 
 
282
        // We want to run our function after the events no longer fire, so we can know that it's a stable situation
 
283
        if ( editingArea._timer )
 
284
                window.clearTimeout( editingArea._timer ) ;
 
285
 
 
286
        editingArea._timer = FCKTools.SetTimeout( FCKEditingArea_MakeEditableByMutation, 1000, editingArea ) ;
 
287
}
 
288
 
 
289
// This function ideally should be called after the document is visible, it does clean up of the
 
290
// mutation tracking and tries again to make the area editable.
 
291
function FCKEditingArea_MakeEditableByMutation()
 
292
{
 
293
        // Clean up
 
294
        delete this._timer ;
 
295
        // Now we don't want to keep on getting this event
 
296
        FCKTools.RemoveEventListener( this.Window.frameElement, 'DOMAttrModified', FCKEditingArea_Document_AttributeNodeModified ) ;
 
297
        // Let's try now to set the editing area editable
 
298
        // If it fails it will set up the Mutation Listener again automatically
 
299
        this.MakeEditable() ;
 
300
}
 
301
 
 
302
FCKEditingArea.prototype.Focus = function()
 
303
{
 
304
        try
 
305
        {
 
306
                if ( this.Mode == FCK_EDITMODE_WYSIWYG )
 
307
                {
 
308
                        if ( FCKBrowserInfo.IsIE )
 
309
                                this._FocusIE() ;
 
310
                        else
 
311
                                this.Window.focus() ;
 
312
                }
 
313
                else
 
314
                {
 
315
                        var oDoc = FCKTools.GetElementDocument( this.Textarea ) ;
 
316
                        if ( (!oDoc.hasFocus || oDoc.hasFocus() ) && oDoc.activeElement == this.Textarea )
 
317
                                return ;
 
318
 
 
319
                        this.Textarea.focus() ;
 
320
                }
 
321
        }
 
322
        catch(e) {}
 
323
}
 
324
 
 
325
FCKEditingArea.prototype._FocusIE = function()
 
326
{
 
327
        // In IE it can happen that the document is in theory focused but the
 
328
        // active element is outside of it.
 
329
        this.Document.body.setActive() ;
 
330
 
 
331
        this.Window.focus() ;
 
332
 
 
333
        // Kludge for #141... yet more code to workaround IE bugs
 
334
        var range = this.Document.selection.createRange() ;
 
335
 
 
336
        var parentNode = range.parentElement() ;
 
337
        var parentTag = parentNode.nodeName.toLowerCase() ;
 
338
 
 
339
        // Only apply the fix when in a block, and the block is empty.
 
340
        if ( parentNode.childNodes.length > 0 ||
 
341
                 !( FCKListsLib.BlockElements[parentTag] ||
 
342
                    FCKListsLib.NonEmptyBlockElements[parentTag] ) )
 
343
        {
 
344
                return ;
 
345
        }
 
346
 
 
347
        // Force the selection to happen, in this way we guarantee the focus will
 
348
        // be there.
 
349
        range = new FCKDomRange( this.Window ) ;
 
350
        range.MoveToElementEditStart( parentNode ) ;
 
351
        range.Select() ;
 
352
}
 
353
 
 
354
function FCKEditingArea_Cleanup()
 
355
{
 
356
        if ( this.Document )
 
357
        {
 
358
                // Avoid IE crash if an object is selected on unload #2201
 
359
                this.Document.selection.empty() ;
 
360
                this.Document.body.innerHTML = "" ;
 
361
        }
 
362
        this.TargetElement = null ;
 
363
        this.IFrame = null ;
 
364
        this.Document = null ;
 
365
        this.Textarea = null ;
 
366
 
 
367
        if ( this.Window )
 
368
        {
 
369
                this.Window._FCKEditingArea = null ;
 
370
                this.Window = null ;
 
371
        }
 
372
}