source: sandbox/filemanager/tp/fckeditor/editor/_source/internals/fck.js @ 1575

Revision 1575, 35.7 KB checked in by amuller, 14 years ago (diff)

Ticket #597 - Implentação, melhorias do modulo gerenciador de arquivos

  • Property svn:executable set to *
Line 
1/*
2 * FCKeditor - The text editor for Internet - http://www.fckeditor.net
3 * Copyright (C) 2003-2009 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 * Creation and initialization of the "FCK" object. This is the main object
22 * that represents an editor instance.
23 */
24
25// FCK represents the active editor instance.
26var FCK =
27{
28        Name                    : FCKURLParams[ 'InstanceName' ],
29        Status                  : FCK_STATUS_NOTLOADED,
30        EditMode                : FCK_EDITMODE_WYSIWYG,
31        Toolbar                 : null,
32        HasFocus                : false,
33        DataProcessor   : new FCKDataProcessor(),
34
35        GetInstanceObject       : (function()
36        {
37                var w = window ;
38                return function( name )
39                {
40                        return w[name] ;
41                }
42        })(),
43
44        AttachToOnSelectionChange : function( functionPointer )
45        {
46                this.Events.AttachEvent( 'OnSelectionChange', functionPointer ) ;
47        },
48
49        GetLinkedFieldValue : function()
50        {
51                return this.LinkedField.value ;
52        },
53
54        GetParentForm : function()
55        {
56                return this.LinkedField.form ;
57        } ,
58
59        // # START : IsDirty implementation
60
61        StartupValue : '',
62
63        IsDirty : function()
64        {
65                if ( this.EditMode == FCK_EDITMODE_SOURCE )
66                        return ( this.StartupValue != this.EditingArea.Textarea.value ) ;
67                else
68                {
69                        // It can happen switching between design and source mode in Gecko
70                        if ( ! this.EditorDocument )
71                                return false ;
72
73                        return ( this.StartupValue != this.EditorDocument.body.innerHTML ) ;
74                }
75        },
76
77        ResetIsDirty : function()
78        {
79                if ( this.EditMode == FCK_EDITMODE_SOURCE )
80                        this.StartupValue = this.EditingArea.Textarea.value ;
81                else if ( this.EditorDocument.body )
82                        this.StartupValue = this.EditorDocument.body.innerHTML ;
83        },
84
85        // # END : IsDirty implementation
86
87        StartEditor : function()
88        {
89                this.TempBaseTag = FCKConfig.BaseHref.length > 0 ? '<base href="' + FCKConfig.BaseHref + '" _fcktemp="true"></base>' : '' ;
90
91                // Setup the keystroke handler.
92                var oKeystrokeHandler = FCK.KeystrokeHandler = new FCKKeystrokeHandler() ;
93                oKeystrokeHandler.OnKeystroke = _FCK_KeystrokeHandler_OnKeystroke ;
94
95                // Set the config keystrokes.
96                oKeystrokeHandler.SetKeystrokes( FCKConfig.Keystrokes ) ;
97
98                // In IE7, if the editor tries to access the clipboard by code, a dialog is
99                // shown to the user asking if the application is allowed to access or not.
100                // Due to the IE implementation of it, the KeystrokeHandler will not work
101                //well in this case, so we must leave the pasting keys to have their default behavior.
102                if ( FCKBrowserInfo.IsIE7 )
103                {
104                        if ( ( CTRL + 86 /*V*/ ) in oKeystrokeHandler.Keystrokes )
105                                oKeystrokeHandler.SetKeystrokes( [ CTRL + 86, true ] ) ;
106
107                        if ( ( SHIFT + 45 /*INS*/ ) in oKeystrokeHandler.Keystrokes )
108                                oKeystrokeHandler.SetKeystrokes( [ SHIFT + 45, true ] ) ;
109                }
110
111                // Retain default behavior for Ctrl-Backspace. (Bug #362)
112                oKeystrokeHandler.SetKeystrokes( [ CTRL + 8, true ] ) ;
113
114                this.EditingArea = new FCKEditingArea( document.getElementById( 'xEditingArea' ) ) ;
115                this.EditingArea.FFSpellChecker = FCKConfig.FirefoxSpellChecker ;
116
117                // Set the editor's startup contents.
118                this.SetData( this.GetLinkedFieldValue(), true ) ;
119
120                // Tab key handling for source mode.
121                FCKTools.AddEventListener( document, "keydown", this._TabKeyHandler ) ;
122
123                // Add selection change listeners. They must be attached only once.
124                this.AttachToOnSelectionChange( _FCK_PaddingNodeListener ) ;
125                if ( FCKBrowserInfo.IsGecko )
126                        this.AttachToOnSelectionChange( this._ExecCheckEmptyBlock ) ;
127
128        },
129
130        Focus : function()
131        {
132                FCK.EditingArea.Focus() ;
133        },
134
135        SetStatus : function( newStatus )
136        {
137                this.Status = newStatus ;
138
139                if ( newStatus == FCK_STATUS_ACTIVE )
140                {
141                        FCKFocusManager.AddWindow( window, true ) ;
142
143                        if ( FCKBrowserInfo.IsIE )
144                                FCKFocusManager.AddWindow( window.frameElement, true ) ;
145
146                        // Force the focus in the editor.
147                        if ( FCKConfig.StartupFocus )
148                                FCK.Focus() ;
149                }
150
151                this.Events.FireEvent( 'OnStatusChange', newStatus ) ;
152
153        },
154
155        // Fixes the body by moving all inline and text nodes to appropriate block
156        // elements.
157        FixBody : function()
158        {
159                var sBlockTag = FCKConfig.EnterMode ;
160
161                // In 'br' mode, no fix must be done.
162                if ( sBlockTag != 'p' && sBlockTag != 'div' )
163                        return ;
164
165                var oDocument = this.EditorDocument ;
166
167                if ( !oDocument )
168                        return ;
169
170                var oBody = oDocument.body ;
171
172                if ( !oBody )
173                        return ;
174
175                FCKDomTools.TrimNode( oBody ) ;
176
177                var oNode = oBody.firstChild ;
178                var oNewBlock ;
179
180                while ( oNode )
181                {
182                        var bMoveNode = false ;
183
184                        switch ( oNode.nodeType )
185                        {
186                                // Element Node.
187                                case 1 :
188                                        var nodeName = oNode.nodeName.toLowerCase() ;
189                                        if ( !FCKListsLib.BlockElements[ nodeName ] &&
190                                                        nodeName != 'li' &&
191                                                        !oNode.getAttribute('_fckfakelement') &&
192                                                        oNode.getAttribute('_moz_dirty') == null )
193                                                bMoveNode = true ;
194                                        break ;
195
196                                // Text Node.
197                                case 3 :
198                                        // Ignore space only or empty text.
199                                        if ( oNewBlock || oNode.nodeValue.Trim().length > 0 )
200                                                bMoveNode = true ;
201                                        break;
202
203                                // Comment Node
204                                case 8 :
205                                        if ( oNewBlock )
206                                                bMoveNode = true ;
207                                        break;
208                        }
209
210                        if ( bMoveNode )
211                        {
212                                var oParent = oNode.parentNode ;
213
214                                if ( !oNewBlock )
215                                        oNewBlock = oParent.insertBefore( oDocument.createElement( sBlockTag ), oNode ) ;
216
217                                oNewBlock.appendChild( oParent.removeChild( oNode ) ) ;
218
219                                oNode = oNewBlock.nextSibling ;
220                        }
221                        else
222                        {
223                                if ( oNewBlock )
224                                {
225                                        FCKDomTools.TrimNode( oNewBlock ) ;
226                                        oNewBlock = null ;
227                                }
228                                oNode = oNode.nextSibling ;
229                        }
230                }
231
232                if ( oNewBlock )
233                        FCKDomTools.TrimNode( oNewBlock ) ;
234        },
235
236        GetData : function( format )
237        {
238                FCK.Events.FireEvent("OnBeforeGetData") ;
239
240                // We assume that if the user is in source editing, the editor value must
241                // represent the exact contents of the source, as the user wanted it to be.
242                if ( FCK.EditMode == FCK_EDITMODE_SOURCE )
243                                return FCK.EditingArea.Textarea.value ;
244
245                this.FixBody() ;
246
247                var oDoc = FCK.EditorDocument ;
248                if ( !oDoc )
249                        return null ;
250
251                var isFullPage = FCKConfig.FullPage ;
252
253                // Call the Data Processor to generate the output data.
254                var data = FCK.DataProcessor.ConvertToDataFormat(
255                        isFullPage ? oDoc.documentElement : oDoc.body,
256                        !isFullPage,
257                        FCKConfig.IgnoreEmptyParagraphValue,
258                        format ) ;
259
260                // Restore protected attributes.
261                data = FCK.ProtectEventsRestore( data ) ;
262
263                if ( FCKBrowserInfo.IsIE )
264                        data = data.replace( FCKRegexLib.ToReplace, '$1' ) ;
265
266                if ( isFullPage )
267                {
268                        if ( FCK.DocTypeDeclaration && FCK.DocTypeDeclaration.length > 0 )
269                                data = FCK.DocTypeDeclaration + '\n' + data ;
270
271                        if ( FCK.XmlDeclaration && FCK.XmlDeclaration.length > 0 )
272                                data = FCK.XmlDeclaration + '\n' + data ;
273                }
274
275                data = FCKConfig.ProtectedSource.Revert( data ) ;
276
277                setTimeout( function() { FCK.Events.FireEvent("OnAfterGetData") ; }, 0 ) ;
278
279                return data ;
280        },
281
282        UpdateLinkedField : function()
283        {
284                var value = FCK.GetXHTML( FCKConfig.FormatOutput ) ;
285
286                if ( FCKConfig.HtmlEncodeOutput )
287                        value = FCKTools.HTMLEncode( value ) ;
288
289                FCK.LinkedField.value = value ;
290                FCK.Events.FireEvent( 'OnAfterLinkedFieldUpdate' ) ;
291        },
292
293        RegisteredDoubleClickHandlers : new Object(),
294
295        OnDoubleClick : function( element )
296        {
297                var oCalls = FCK.RegisteredDoubleClickHandlers[ element.tagName.toUpperCase() ] ;
298
299                if ( oCalls )
300                {
301                        for ( var i = 0 ; i < oCalls.length ; i++ )
302                                oCalls[ i ]( element ) ;
303                }
304
305                // Generic handler for any element
306                oCalls = FCK.RegisteredDoubleClickHandlers[ '*' ] ;
307
308                if ( oCalls )
309                {
310                        for ( var i = 0 ; i < oCalls.length ; i++ )
311                                oCalls[ i ]( element ) ;
312                }
313
314        },
315
316        // Register objects that can handle double click operations.
317        RegisterDoubleClickHandler : function( handlerFunction, tag )
318        {
319                var nodeName = tag || '*' ;
320                nodeName = nodeName.toUpperCase() ;
321
322                var aTargets ;
323
324                if ( !( aTargets = FCK.RegisteredDoubleClickHandlers[ nodeName ] ) )
325                        FCK.RegisteredDoubleClickHandlers[ nodeName ] = [ handlerFunction ] ;
326                else
327                {
328                        // Check that the event handler isn't already registered with the same listener
329                        // It doesn't detect function pointers belonging to an object (at least in Gecko)
330                        if ( aTargets.IndexOf( handlerFunction ) == -1 )
331                                aTargets.push( handlerFunction ) ;
332                }
333
334        },
335
336        OnAfterSetHTML : function()
337        {
338                FCKDocumentProcessor.Process( FCK.EditorDocument ) ;
339                FCKUndo.SaveUndoStep() ;
340
341                FCK.Events.FireEvent( 'OnSelectionChange' ) ;
342                FCK.Events.FireEvent( 'OnAfterSetHTML' ) ;
343        },
344
345        // Saves URLs on links and images on special attributes, so they don't change when
346        // moving around.
347        ProtectUrls : function( html )
348        {
349                // <A> href
350                html = html.replace( FCKRegexLib.ProtectUrlsA   , '$& _fcksavedurl=$1' ) ;
351
352                // <IMG> src
353                html = html.replace( FCKRegexLib.ProtectUrlsImg , '$& _fcksavedurl=$1' ) ;
354
355                // <AREA> href
356                html = html.replace( FCKRegexLib.ProtectUrlsArea        , '$& _fcksavedurl=$1' ) ;
357
358                return html ;
359        },
360
361        // Saves event attributes (like onclick) so they don't get executed while
362        // editing.
363        ProtectEvents : function( html )
364        {
365                return html.replace( FCKRegexLib.TagsWithEvent, _FCK_ProtectEvents_ReplaceTags ) ;
366        },
367
368        ProtectEventsRestore : function( html )
369        {
370                return html.replace( FCKRegexLib.ProtectedEvents, _FCK_ProtectEvents_RestoreEvents ) ;
371        },
372
373        ProtectTags : function( html )
374        {
375                var sTags = FCKConfig.ProtectedTags ;
376
377                // IE doesn't support <abbr> and it breaks it. Let's protect it.
378                if ( FCKBrowserInfo.IsIE )
379                        sTags += sTags.length > 0 ? '|ABBR|XML|EMBED|OBJECT' : 'ABBR|XML|EMBED|OBJECT' ;
380
381                var oRegex ;
382                if ( sTags.length > 0 )
383                {
384                        oRegex = new RegExp( '<(' + sTags + ')(?!\w|:)', 'gi' ) ;
385                        html = html.replace( oRegex, '<FCK:$1' ) ;
386
387                        oRegex = new RegExp( '<\/(' + sTags + ')>', 'gi' ) ;
388                        html = html.replace( oRegex, '<\/FCK:$1>' ) ;
389                }
390
391                // Protect some empty elements. We must do it separately because the
392                // original tag may not contain the closing slash, like <hr>:
393                //              - <meta> tags get executed, so if you have a redirect meta, the
394                //                content will move to the target page.
395                //              - <hr> may destroy the document structure if not well
396                //                positioned. The trick is protect it here and restore them in
397                //                the FCKDocumentProcessor.
398                sTags = 'META' ;
399                if ( FCKBrowserInfo.IsIE )
400                        sTags += '|HR' ;
401
402                oRegex = new RegExp( '<((' + sTags + ')(?=\\s|>|/)[\\s\\S]*?)/?>', 'gi' ) ;
403                html = html.replace( oRegex, '<FCK:$1 />' ) ;
404
405                return html ;
406        },
407
408        SetData : function( data, resetIsDirty )
409        {
410                this.EditingArea.Mode = FCK.EditMode ;
411
412                // If there was an onSelectionChange listener in IE we must remove it to avoid crashes #1498
413                if ( FCKBrowserInfo.IsIE && FCK.EditorDocument )
414                {
415                        FCK.EditorDocument.detachEvent("onselectionchange", Doc_OnSelectionChange ) ;
416                }
417
418                FCKTempBin.Reset() ;
419
420                // Bug #2469: SelectionData.createRange becomes undefined after the editor
421                // iframe is changed by FCK.SetData().
422                FCK.Selection.Release() ;
423
424                if ( FCK.EditMode == FCK_EDITMODE_WYSIWYG )
425                {
426                        // Save the resetIsDirty for later use (async)
427                        this._ForceResetIsDirty = ( resetIsDirty === true ) ;
428
429                        // Protect parts of the code that must remain untouched (and invisible)
430                        // during editing.
431                        data = FCKConfig.ProtectedSource.Protect( data ) ;
432
433                        // Call the Data Processor to transform the data.
434                        data = FCK.DataProcessor.ConvertToHtml( data ) ;
435
436                        // Fix for invalid self-closing tags (see #152).
437                        data = data.replace( FCKRegexLib.InvalidSelfCloseTags, '$1></$2>' ) ;
438
439                        // Protect event attributes (they could get fired in the editing area).
440                        data = FCK.ProtectEvents( data ) ;
441
442                        // Protect some things from the browser itself.
443                        data = FCK.ProtectUrls( data ) ;
444                        data = FCK.ProtectTags( data ) ;
445
446                        // Insert the base tag (FCKConfig.BaseHref), if not exists in the source.
447                        // The base must be the first tag in the HEAD, to get relative
448                        // links on styles, for example.
449                        if ( FCK.TempBaseTag.length > 0 && !FCKRegexLib.HasBaseTag.test( data ) )
450                                data = data.replace( FCKRegexLib.HeadOpener, '$&' + FCK.TempBaseTag ) ;
451
452                        // Build the HTML for the additional things we need on <head>.
453                        var sHeadExtra = '' ;
454
455                        if ( !FCKConfig.FullPage )
456                                sHeadExtra += _FCK_GetEditorAreaStyleTags() ;
457
458                        if ( FCKBrowserInfo.IsIE )
459                                sHeadExtra += FCK._GetBehaviorsStyle() ;
460                        else if ( FCKConfig.ShowBorders )
461                                sHeadExtra += FCKTools.GetStyleHtml( FCK_ShowTableBordersCSS, true ) ;
462
463                        sHeadExtra += FCKTools.GetStyleHtml( FCK_InternalCSS, true ) ;
464
465                        // Attention: do not change it before testing it well (sample07)!
466                        // This is tricky... if the head ends with <meta ... content type>,
467                        // Firefox will break. But, it works if we place our extra stuff as
468                        // the last elements in the HEAD.
469                        data = data.replace( FCKRegexLib.HeadCloser, sHeadExtra + '$&' ) ;
470
471                        // Load the HTML in the editing area.
472                        this.EditingArea.OnLoad = _FCK_EditingArea_OnLoad ;
473                        this.EditingArea.Start( data ) ;
474                }
475                else
476                {
477                        // Remove the references to the following elements, as the editing area
478                        // IFRAME will be removed.
479                        FCK.EditorWindow        = null ;
480                        FCK.EditorDocument      = null ;
481                        FCKDomTools.PaddingNode = null ;
482
483                        this.EditingArea.OnLoad = null ;
484                        this.EditingArea.Start( data ) ;
485
486                        // Enables the context menu in the textarea.
487                        this.EditingArea.Textarea._FCKShowContextMenu = true ;
488
489                        // Removes the enter key handler.
490                        FCK.EnterKeyHandler = null ;
491
492                        if ( resetIsDirty )
493                                this.ResetIsDirty() ;
494
495                        // Listen for keystroke events.
496                        FCK.KeystrokeHandler.AttachToElement( this.EditingArea.Textarea ) ;
497
498                        this.EditingArea.Textarea.focus() ;
499
500                        FCK.Events.FireEvent( 'OnAfterSetHTML' ) ;
501                }
502
503                if ( window.onresize )
504                        window.onresize() ;
505        },
506
507        // This collection is used by the browser specific implementations to tell
508        // which named commands must be handled separately.
509        RedirectNamedCommands : new Object(),
510
511        ExecuteNamedCommand : function( commandName, commandParameter, noRedirect, noSaveUndo )
512        {
513                if ( !noSaveUndo )
514                        FCKUndo.SaveUndoStep() ;
515
516                if ( !noRedirect && FCK.RedirectNamedCommands[ commandName ] != null )
517                        FCK.ExecuteRedirectedNamedCommand( commandName, commandParameter ) ;
518                else
519                {
520                        FCK.Focus() ;
521                        FCK.EditorDocument.execCommand( commandName, false, commandParameter ) ;
522                        FCK.Events.FireEvent( 'OnSelectionChange' ) ;
523                }
524
525                if ( !noSaveUndo )
526                FCKUndo.SaveUndoStep() ;
527        },
528
529        GetNamedCommandState : function( commandName )
530        {
531                try
532                {
533
534                        // Bug #50 : Safari never returns positive state for the Paste command, override that.
535                        if ( FCKBrowserInfo.IsSafari && FCK.EditorWindow && commandName.IEquals( 'Paste' ) )
536                                return FCK_TRISTATE_OFF ;
537
538                        if ( !FCK.EditorDocument.queryCommandEnabled( commandName ) )
539                                return FCK_TRISTATE_DISABLED ;
540                        else
541                        {
542                                return FCK.EditorDocument.queryCommandState( commandName ) ? FCK_TRISTATE_ON : FCK_TRISTATE_OFF ;
543                        }
544                }
545                catch ( e )
546                {
547                        return FCK_TRISTATE_OFF ;
548                }
549        },
550
551        GetNamedCommandValue : function( commandName )
552        {
553                var sValue = '' ;
554                var eState = FCK.GetNamedCommandState( commandName ) ;
555
556                if ( eState == FCK_TRISTATE_DISABLED )
557                        return null ;
558
559                try
560                {
561                        sValue = this.EditorDocument.queryCommandValue( commandName ) ;
562                }
563                catch(e) {}
564
565                return sValue ? sValue : '' ;
566        },
567
568        Paste : function( _callListenersOnly )
569        {
570                // First call 'OnPaste' listeners.
571                if ( FCK.Status != FCK_STATUS_COMPLETE || !FCK.Events.FireEvent( 'OnPaste' ) )
572                        return false ;
573
574                // Then call the default implementation.
575                return _callListenersOnly || FCK._ExecPaste() ;
576        },
577
578        PasteFromWord : function()
579        {
580                FCKDialog.OpenDialog( 'FCKDialog_Paste', FCKLang.PasteFromWord, 'dialog/fck_paste.html', 400, 330, 'Word' ) ;
581        },
582
583        Preview : function()
584        {
585                var sHTML ;
586
587                if ( FCKConfig.FullPage )
588                {
589                        if ( FCK.TempBaseTag.length > 0 )
590                                sHTML = FCK.TempBaseTag + FCK.GetXHTML() ;
591                        else
592                                sHTML = FCK.GetXHTML() ;
593                }
594                else
595                {
596                        sHTML =
597                                FCKConfig.DocType +
598                                '<html dir="' + FCKConfig.ContentLangDirection + '">' +
599                                '<head>' +
600                                FCK.TempBaseTag +
601                                '<title>' + FCKLang.Preview + '</title>' +
602                                _FCK_GetEditorAreaStyleTags() +
603                                '</head><body' + FCKConfig.GetBodyAttributes() + '>' +
604                                FCK.GetXHTML() +
605                                '</body></html>' ;
606                }
607
608                var iWidth      = FCKConfig.ScreenWidth * 0.8 ;
609                var iHeight     = FCKConfig.ScreenHeight * 0.7 ;
610                var iLeft       = ( FCKConfig.ScreenWidth - iWidth ) / 2 ;
611
612                var sOpenUrl = '' ;
613                if ( FCK_IS_CUSTOM_DOMAIN && FCKBrowserInfo.IsIE)
614                {
615                        window._FCKHtmlToLoad = sHTML ;
616                        sOpenUrl = 'javascript:void( (function(){' +
617                                'document.open() ;' +
618                                'document.domain="' + document.domain + '" ;' +
619                                'document.write( window.opener._FCKHtmlToLoad );' +
620                                'document.close() ;' +
621                                'window.opener._FCKHtmlToLoad = null ;' +
622                                '})() )' ;
623                }
624
625                var oWindow = window.open( sOpenUrl, null, 'toolbar=yes,location=no,status=yes,menubar=yes,scrollbars=yes,resizable=yes,width=' + iWidth + ',height=' + iHeight + ',left=' + iLeft ) ;
626
627                if ( !FCK_IS_CUSTOM_DOMAIN || !FCKBrowserInfo.IsIE)
628                {
629                        oWindow.document.write( sHTML );
630                        oWindow.document.close();
631                }
632
633        },
634
635        SwitchEditMode : function( noUndo )
636        {
637                var bIsWysiwyg = ( FCK.EditMode == FCK_EDITMODE_WYSIWYG ) ;
638
639                // Save the current IsDirty state, so we may restore it after the switch.
640                var bIsDirty = FCK.IsDirty() ;
641
642                var sHtml ;
643
644                // Update the HTML in the view output to show, also update
645                // FCKTempBin for IE to avoid #2263.
646                if ( bIsWysiwyg )
647                {
648                        FCKCommands.GetCommand( 'ShowBlocks' ).SaveState() ;
649                        if ( !noUndo && FCKBrowserInfo.IsIE )
650                                FCKUndo.SaveUndoStep() ;
651
652                        sHtml = FCK.GetXHTML( FCKConfig.FormatSource ) ;
653
654                        if ( FCKBrowserInfo.IsIE )
655                                FCKTempBin.ToHtml() ;
656
657                        if ( sHtml == null )
658                                return false ;
659                }
660                else
661                        sHtml = this.EditingArea.Textarea.value ;
662
663                FCK.EditMode = bIsWysiwyg ? FCK_EDITMODE_SOURCE : FCK_EDITMODE_WYSIWYG ;
664
665                FCK.SetData( sHtml, !bIsDirty ) ;
666
667                // Set the Focus.
668                FCK.Focus() ;
669
670                // Update the toolbar (Running it directly causes IE to fail).
671                FCKTools.RunFunction( FCK.ToolbarSet.RefreshModeState, FCK.ToolbarSet ) ;
672
673                return true ;
674        },
675
676        InsertElement : function( element )
677        {
678                // The parameter may be a string (element name), so transform it in an element.
679                if ( typeof element == 'string' )
680                        element = this.EditorDocument.createElement( element ) ;
681
682                var elementName = element.nodeName.toLowerCase() ;
683
684                FCKSelection.Restore() ;
685
686                // Create a range for the selection. V3 will have a new selection
687                // object that may internally supply this feature.
688                var range = new FCKDomRange( this.EditorWindow ) ;
689
690                // Move to the selection and delete it.
691                range.MoveToSelection() ;
692                range.DeleteContents() ;
693
694                if ( FCKListsLib.BlockElements[ elementName ] != null )
695                {
696                        if ( range.StartBlock )
697                        {
698                                if ( range.CheckStartOfBlock() )
699                                        range.MoveToPosition( range.StartBlock, 3 ) ;
700                                else if ( range.CheckEndOfBlock() )
701                                        range.MoveToPosition( range.StartBlock, 4 ) ;
702                                else
703                                        range.SplitBlock() ;
704                        }
705
706                        range.InsertNode( element ) ;
707
708                        var next = FCKDomTools.GetNextSourceElement( element, false, null, [ 'hr','br','param','img','area','input' ], true ) ;
709
710                        // Be sure that we have something after the new element, so we can move the cursor there.
711                        if ( !next && FCKConfig.EnterMode != 'br')
712                        {
713                                next = this.EditorDocument.body.appendChild( this.EditorDocument.createElement( FCKConfig.EnterMode ) ) ;
714
715                                if ( FCKBrowserInfo.IsGeckoLike )
716                                        FCKTools.AppendBogusBr( next ) ;
717                        }
718
719                        if ( FCKListsLib.EmptyElements[ elementName ] == null )
720                                range.MoveToElementEditStart( element ) ;
721                        else if ( next )
722                                range.MoveToElementEditStart( next ) ;
723                        else
724                                range.MoveToPosition( element, 4 ) ;
725
726                        if ( FCKBrowserInfo.IsGeckoLike )
727                        {
728                                if ( next )
729                                        FCKDomTools.ScrollIntoView( next, false );
730                                FCKDomTools.ScrollIntoView( element, false );
731                        }
732                }
733                else
734                {
735                        // Insert the node.
736                        range.InsertNode( element ) ;
737
738                        // Move the selection right after the new element.
739                        // DISCUSSION: Should we select the element instead?
740                        range.SetStart( element, 4 ) ;
741                        range.SetEnd( element, 4 ) ;
742                }
743
744                range.Select() ;
745                range.Release() ;
746
747                // REMOVE IT: The focus should not really be set here. It is up to the
748                // calling code to reset the focus if needed.
749                this.Focus() ;
750
751                return element ;
752        },
753
754        _InsertBlockElement : function( blockElement )
755        {
756        },
757
758        _IsFunctionKey : function( keyCode )
759        {
760                // keys that are captured but do not change editor contents
761                if ( keyCode >= 16 && keyCode <= 20 )
762                        // shift, ctrl, alt, pause, capslock
763                        return true ;
764                if ( keyCode == 27 || ( keyCode >= 33 && keyCode <= 40 ) )
765                        // esc, page up, page down, end, home, left, up, right, down
766                        return true ;
767                if ( keyCode == 45 )
768                        // insert, no effect on FCKeditor, yet
769                        return true ;
770                return false ;
771        },
772
773        _KeyDownListener : function( evt )
774        {
775                if (! evt)
776                        evt = FCK.EditorWindow.event ;
777                if ( FCK.EditorWindow )
778                {
779                        if ( !FCK._IsFunctionKey(evt.keyCode) // do not capture function key presses, like arrow keys or shift/alt/ctrl
780                                        && !(evt.ctrlKey || evt.metaKey) // do not capture Ctrl hotkeys, as they have their snapshot capture logic
781                                        && !(evt.keyCode == 46) ) // do not capture Del, it has its own capture logic in fckenterkey.js
782                                FCK._KeyDownUndo() ;
783                }
784                return true ;
785        },
786
787        _KeyDownUndo : function()
788        {
789                if ( !FCKUndo.Typing )
790                {
791                        FCKUndo.SaveUndoStep() ;
792                        FCKUndo.Typing = true ;
793                        FCK.Events.FireEvent( "OnSelectionChange" ) ;
794                }
795
796                FCKUndo.TypesCount++ ;
797                FCKUndo.Changed = 1 ;
798
799                if ( FCKUndo.TypesCount > FCKUndo.MaxTypes )
800                {
801                        FCKUndo.TypesCount = 0 ;
802                        FCKUndo.SaveUndoStep() ;
803                }
804        },
805
806        _TabKeyHandler : function( evt )
807        {
808                if ( ! evt )
809                        evt = window.event ;
810
811                var keystrokeValue = evt.keyCode ;
812
813                // Pressing <Tab> in source mode should produce a tab space in the text area, not
814                // changing the focus to something else.
815                if ( keystrokeValue == 9 && FCK.EditMode != FCK_EDITMODE_WYSIWYG )
816                {
817                        if ( FCKBrowserInfo.IsIE )
818                        {
819                                var range = document.selection.createRange() ;
820                                if ( range.parentElement() != FCK.EditingArea.Textarea )
821                                        return true ;
822                                range.text = '\t' ;
823                                range.select() ;
824                        }
825                        else
826                        {
827                                var a = [] ;
828                                var el = FCK.EditingArea.Textarea ;
829                                var selStart = el.selectionStart ;
830                                var selEnd = el.selectionEnd ;
831                                a.push( el.value.substr(0, selStart ) ) ;
832                                a.push( '\t' ) ;
833                                a.push( el.value.substr( selEnd ) ) ;
834                                el.value = a.join( '' ) ;
835                                el.setSelectionRange( selStart + 1, selStart + 1 ) ;
836                        }
837
838                        if ( evt.preventDefault )
839                                return evt.preventDefault() ;
840
841                        return evt.returnValue = false ;
842                }
843
844                return true ;
845        }
846} ;
847
848FCK.Events = new FCKEvents( FCK ) ;
849
850// DEPRECATED in favor or "GetData".
851FCK.GetHTML     = FCK.GetXHTML = FCK.GetData ;
852
853// DEPRECATED in favor of "SetData".
854FCK.SetHTML = FCK.SetData ;
855
856// InsertElementAndGetIt and CreateElement are Deprecated : returns the same value as InsertElement.
857FCK.InsertElementAndGetIt = FCK.CreateElement = FCK.InsertElement ;
858
859// Replace all events attributes (like onclick).
860function _FCK_ProtectEvents_ReplaceTags( tagMatch )
861{
862        return tagMatch.replace( FCKRegexLib.EventAttributes, _FCK_ProtectEvents_ReplaceEvents ) ;
863}
864
865// Replace an event attribute with its respective __fckprotectedatt attribute.
866// The original event markup will be encoded and saved as the value of the new
867// attribute.
868function _FCK_ProtectEvents_ReplaceEvents( eventMatch, attName )
869{
870        return ' ' + attName + '_fckprotectedatt="' + encodeURIComponent( eventMatch ) + '"' ;
871}
872
873function _FCK_ProtectEvents_RestoreEvents( match, encodedOriginal )
874{
875        return decodeURIComponent( encodedOriginal ) ;
876}
877
878function _FCK_MouseEventsListener( evt )
879{
880        if ( ! evt )
881                evt = window.event ;
882        if ( evt.type == 'mousedown' )
883                FCK.MouseDownFlag = true ;
884        else if ( evt.type == 'mouseup' )
885                FCK.MouseDownFlag = false ;
886        else if ( evt.type == 'mousemove' )
887                FCK.Events.FireEvent( 'OnMouseMove', evt ) ;
888}
889
890function _FCK_PaddingNodeListener()
891{
892        if ( FCKConfig.EnterMode.IEquals( 'br' ) )
893                return ;
894        FCKDomTools.EnforcePaddingNode( FCK.EditorDocument, FCKConfig.EnterMode ) ;
895
896        if ( ! FCKBrowserInfo.IsIE && FCKDomTools.PaddingNode )
897        {
898                // Prevent the caret from going between the body and the padding node in Firefox.
899                // i.e. <body>|<p></p></body>
900                var sel = FCKSelection.GetSelection() ;
901                if ( sel && sel.rangeCount == 1 )
902                {
903                        var range = sel.getRangeAt( 0 ) ;
904                        if ( range.collapsed && range.startContainer == FCK.EditorDocument.body && range.startOffset == 0 )
905                        {
906                                range.selectNodeContents( FCKDomTools.PaddingNode ) ;
907                                range.collapse( true ) ;
908                                sel.removeAllRanges() ;
909                                sel.addRange( range ) ;
910                        }
911                }
912        }
913        else if ( FCKDomTools.PaddingNode )
914        {
915                // Prevent the caret from going into an empty body but not into the padding node in IE.
916                // i.e. <body><p></p>|</body>
917                var parentElement = FCKSelection.GetParentElement() ;
918                var paddingNode = FCKDomTools.PaddingNode ;
919                if ( parentElement && parentElement.nodeName.IEquals( 'body' ) )
920                {
921                        if ( FCK.EditorDocument.body.childNodes.length == 1
922                                        && FCK.EditorDocument.body.firstChild == paddingNode )
923                        {
924                                /*
925                                 * Bug #1764: Don't move the selection if the
926                                 * current selection isn't in the editor
927                                 * document.
928                                 */
929                                if ( FCKSelection._GetSelectionDocument( FCK.EditorDocument.selection ) != FCK.EditorDocument )
930                                        return ;
931
932                                var range = FCK.EditorDocument.body.createTextRange() ;
933                                var clearContents = false ;
934                                if ( !paddingNode.childNodes.firstChild )
935                                {
936                                        paddingNode.appendChild( FCKTools.GetElementDocument( paddingNode ).createTextNode( '\ufeff' ) ) ;
937                                        clearContents = true ;
938                                }
939                                range.moveToElementText( paddingNode ) ;
940                                range.select() ;
941                                if ( clearContents )
942                                        range.pasteHTML( '' ) ;
943                        }
944                }
945        }
946}
947
948function _FCK_EditingArea_OnLoad()
949{
950        // Get the editor's window and document (DOM)
951        FCK.EditorWindow        = FCK.EditingArea.Window ;
952        FCK.EditorDocument      = FCK.EditingArea.Document ;
953
954        if ( FCKBrowserInfo.IsIE )
955                FCKTempBin.ToElements() ;
956
957        FCK.InitializeBehaviors() ;
958
959        // Listen for mousedown and mouseup events for tracking drag and drops.
960        FCK.MouseDownFlag = false ;
961        FCKTools.AddEventListener( FCK.EditorDocument, 'mousemove', _FCK_MouseEventsListener ) ;
962        FCKTools.AddEventListener( FCK.EditorDocument, 'mousedown', _FCK_MouseEventsListener ) ;
963        FCKTools.AddEventListener( FCK.EditorDocument, 'mouseup', _FCK_MouseEventsListener ) ;
964        if ( FCKBrowserInfo.IsSafari )
965        {
966                // #3481: WebKit has a bug with paste where the paste contents may leak
967                // outside table cells. So add padding nodes before and after the paste.
968                FCKTools.AddEventListener( FCK.EditorDocument, 'paste', function( evt )
969                {
970                        var range = new FCKDomRange( FCK.EditorWindow );
971                        var nodeBefore = FCK.EditorDocument.createTextNode( '\ufeff' );
972                        var nodeAfter = FCK.EditorDocument.createElement( 'a' );
973                        nodeAfter.id = 'fck_paste_padding';
974                        nodeAfter.innerHTML = '&#65279;';
975                        range.MoveToSelection();
976                        range.DeleteContents();
977
978                        // Insert padding nodes.
979                        range.InsertNode( nodeBefore );
980                        range.Collapse();
981                        range.InsertNode( nodeAfter );
982
983                        // Move the selection to between the padding nodes.
984                        range.MoveToPosition( nodeAfter, 3 );
985                        range.Select();
986
987                        // Remove the padding nodes after the paste is done.
988                        setTimeout( function()
989                                {
990                                        nodeBefore.parentNode.removeChild( nodeBefore );
991                                        nodeAfter = FCK.EditorDocument.getElementById( 'fck_paste_padding' );
992                                        nodeAfter.parentNode.removeChild( nodeAfter );
993                                }, 0 );
994                } );
995        }
996
997        // Most of the CTRL key combos do not work under Safari for onkeydown and onkeypress (See #1119)
998        // But we can use the keyup event to override some of these...
999        if ( FCKBrowserInfo.IsSafari )
1000        {
1001                var undoFunc = function( evt )
1002                {
1003                        if ( ! ( evt.ctrlKey || evt.metaKey ) )
1004                                return ;
1005                        if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG )
1006                                return ;
1007                        switch ( evt.keyCode )
1008                        {
1009                                case 89:
1010                                        FCKUndo.Redo() ;
1011                                        break ;
1012                                case 90:
1013                                        FCKUndo.Undo() ;
1014                                        break ;
1015                        }
1016                }
1017
1018                FCKTools.AddEventListener( FCK.EditorDocument, 'keyup', undoFunc ) ;
1019        }
1020
1021        // Create the enter key handler
1022        FCK.EnterKeyHandler = new FCKEnterKey( FCK.EditorWindow, FCKConfig.EnterMode, FCKConfig.ShiftEnterMode, FCKConfig.TabSpaces ) ;
1023
1024        // Listen for keystroke events.
1025        FCK.KeystrokeHandler.AttachToElement( FCK.EditorDocument ) ;
1026
1027        if ( FCK._ForceResetIsDirty )
1028                FCK.ResetIsDirty() ;
1029
1030        // This is a tricky thing for IE. In some cases, even if the cursor is
1031        // blinking in the editing, the keystroke handler doesn't catch keyboard
1032        // events. We must activate the editing area to make it work. (#142).
1033        if ( FCKBrowserInfo.IsIE && FCK.HasFocus )
1034                FCK.EditorDocument.body.setActive() ;
1035
1036        FCK.OnAfterSetHTML() ;
1037
1038        // Restore show blocks status.
1039        FCKCommands.GetCommand( 'ShowBlocks' ).RestoreState() ;
1040
1041        // Check if it is not a startup call, otherwise complete the startup.
1042        if ( FCK.Status != FCK_STATUS_NOTLOADED )
1043                return ;
1044
1045        FCK.SetStatus( FCK_STATUS_ACTIVE ) ;
1046}
1047
1048function _FCK_GetEditorAreaStyleTags()
1049{
1050        return FCKTools.GetStyleHtml( FCKConfig.EditorAreaCSS ) +
1051                FCKTools.GetStyleHtml( FCKConfig.EditorAreaStyles ) ;
1052}
1053
1054function _FCK_KeystrokeHandler_OnKeystroke( keystroke, keystrokeValue )
1055{
1056        if ( FCK.Status != FCK_STATUS_COMPLETE )
1057                return false ;
1058
1059        if ( FCK.EditMode == FCK_EDITMODE_WYSIWYG )
1060        {
1061                switch ( keystrokeValue )
1062                {
1063                        case 'Paste' :
1064                                return !FCK.Paste() ;
1065
1066                        case 'Cut' :
1067                                FCKUndo.SaveUndoStep() ;
1068                                return false ;
1069                }
1070        }
1071        else
1072        {
1073                // In source mode, some actions must have their default behavior.
1074                if ( keystrokeValue.Equals( 'Paste', 'Undo', 'Redo', 'SelectAll', 'Cut' ) )
1075                        return false ;
1076        }
1077
1078        // The return value indicates if the default behavior of the keystroke must
1079        // be cancelled. Let's do that only if the Execute() call explicitly returns "false".
1080        var oCommand = FCK.Commands.GetCommand( keystrokeValue ) ;
1081
1082        // If the command is disabled then ignore the keystroke
1083        if ( oCommand.GetState() == FCK_TRISTATE_DISABLED )
1084                return false ;
1085
1086        return ( oCommand.Execute.apply( oCommand, FCKTools.ArgumentsToArray( arguments, 2 ) ) !== false ) ;
1087}
1088
1089// Set the FCK.LinkedField reference to the field that will be used to post the
1090// editor data.
1091(function()
1092{
1093        // There is a bug on IE... getElementById returns any META tag that has the
1094        // name set to the ID you are looking for. So the best way in to get the array
1095        // by names and look for the correct one.
1096        // As ASP.Net generates a ID that is different from the Name, we must also
1097        // look for the field based on the ID (the first one is the ID).
1098
1099        var oDocument = window.parent.document ;
1100
1101        // Try to get the field using the ID.
1102        var eLinkedField = oDocument.getElementById( FCK.Name ) ;
1103
1104        var i = 0;
1105        while ( eLinkedField || i == 0 )
1106        {
1107                if ( eLinkedField && eLinkedField.tagName.toLowerCase().Equals( 'input', 'textarea' ) )
1108                {
1109                        FCK.LinkedField = eLinkedField ;
1110                        break ;
1111                }
1112
1113                eLinkedField = oDocument.getElementsByName( FCK.Name )[i++] ;
1114        }
1115})() ;
1116
1117var FCKTempBin =
1118{
1119        Elements : new Array(),
1120
1121        AddElement : function( element )
1122        {
1123                var iIndex = this.Elements.length ;
1124                this.Elements[ iIndex ] = element ;
1125                return iIndex ;
1126        },
1127
1128        RemoveElement : function( index )
1129        {
1130                var e = this.Elements[ index ] ;
1131                this.Elements[ index ] = null ;
1132                return e ;
1133        },
1134
1135        Reset : function()
1136        {
1137                var i = 0 ;
1138                while ( i < this.Elements.length )
1139                        this.Elements[ i++ ] = null ;
1140                this.Elements.length = 0 ;
1141        },
1142
1143        ToHtml : function()
1144        {
1145                for ( var i = 0 ; i < this.Elements.length ; i++ )
1146                {
1147                        this.Elements[i] = '<div>&nbsp;' + this.Elements[i].outerHTML + '</div>' ;
1148                        this.Elements[i].isHtml = true ;
1149                }
1150        },
1151
1152        ToElements : function()
1153        {
1154                var node = FCK.EditorDocument.createElement( 'div' ) ;
1155                for ( var i = 0 ; i < this.Elements.length ; i++ )
1156                {
1157                        if ( this.Elements[i].isHtml )
1158                        {
1159                                node.innerHTML = this.Elements[i] ;
1160                                this.Elements[i] = node.firstChild.removeChild( node.firstChild.lastChild ) ;
1161                        }
1162                }
1163        }
1164} ;
1165
1166
1167
1168// # Focus Manager: Manages the focus in the editor.
1169var FCKFocusManager = FCK.FocusManager =
1170{
1171        IsLocked : false,
1172
1173        AddWindow : function( win, sendToEditingArea )
1174        {
1175                var oTarget ;
1176
1177                if ( FCKBrowserInfo.IsIE )
1178                        oTarget = win.nodeType == 1 ? win : win.frameElement ? win.frameElement : win.document ;
1179                else if ( FCKBrowserInfo.IsSafari )
1180                        oTarget = win ;
1181                else
1182                        oTarget = win.document ;
1183
1184                FCKTools.AddEventListener( oTarget, 'blur', FCKFocusManager_Win_OnBlur ) ;
1185                FCKTools.AddEventListener( oTarget, 'focus', sendToEditingArea ? FCKFocusManager_Win_OnFocus_Area : FCKFocusManager_Win_OnFocus ) ;
1186        },
1187
1188        RemoveWindow : function( win )
1189        {
1190                if ( FCKBrowserInfo.IsIE )
1191                        oTarget = win.nodeType == 1 ? win : win.frameElement ? win.frameElement : win.document ;
1192                else
1193                        oTarget = win.document ;
1194
1195                FCKTools.RemoveEventListener( oTarget, 'blur', FCKFocusManager_Win_OnBlur ) ;
1196                FCKTools.RemoveEventListener( oTarget, 'focus', FCKFocusManager_Win_OnFocus_Area ) ;
1197                FCKTools.RemoveEventListener( oTarget, 'focus', FCKFocusManager_Win_OnFocus ) ;
1198        },
1199
1200        Lock : function()
1201        {
1202                this.IsLocked = true ;
1203        },
1204
1205        Unlock : function()
1206        {
1207                if ( this._HasPendingBlur )
1208                        FCKFocusManager._Timer = window.setTimeout( FCKFocusManager_FireOnBlur, 100 ) ;
1209
1210                this.IsLocked = false ;
1211        },
1212
1213        _ResetTimer : function()
1214        {
1215                this._HasPendingBlur = false ;
1216
1217                if ( this._Timer )
1218                {
1219                        window.clearTimeout( this._Timer ) ;
1220                        delete this._Timer ;
1221                }
1222        }
1223} ;
1224
1225function FCKFocusManager_Win_OnBlur()
1226{
1227        if ( typeof(FCK) != 'undefined' && FCK.HasFocus )
1228        {
1229                FCKFocusManager._ResetTimer() ;
1230                FCKFocusManager._Timer = window.setTimeout( FCKFocusManager_FireOnBlur, 100 ) ;
1231        }
1232}
1233
1234function FCKFocusManager_FireOnBlur()
1235{
1236        if ( FCKFocusManager.IsLocked )
1237                FCKFocusManager._HasPendingBlur = true ;
1238        else
1239        {
1240                FCK.HasFocus = false ;
1241                FCK.Events.FireEvent( "OnBlur" ) ;
1242        }
1243}
1244
1245function FCKFocusManager_Win_OnFocus_Area()
1246{
1247        // Check if we are already focusing the editor (to avoid loops).
1248        if ( FCKFocusManager._IsFocusing )
1249                return ;
1250
1251        FCKFocusManager._IsFocusing = true ;
1252
1253        FCK.Focus() ;
1254        FCKFocusManager_Win_OnFocus() ;
1255
1256        // The above FCK.Focus() call may trigger other focus related functions.
1257        // So, to avoid a loop, we delay the focusing mark removal, so it get
1258        // executed after all othre functions have been run.
1259        FCKTools.RunFunction( function()
1260                {
1261                        delete FCKFocusManager._IsFocusing ;
1262                } ) ;
1263}
1264
1265function FCKFocusManager_Win_OnFocus()
1266{
1267        FCKFocusManager._ResetTimer() ;
1268
1269        if ( !FCK.HasFocus && !FCKFocusManager.IsLocked )
1270        {
1271                FCK.HasFocus = true ;
1272                FCK.Events.FireEvent( "OnFocus" ) ;
1273        }
1274}
1275
1276/*
1277 * #1633 : Protect the editor iframe from external styles.
1278 * Notice that we can't use FCKTools.ResetStyles here since FCKTools isn't
1279 * loaded yet.
1280 */
1281(function()
1282{
1283        var el = window.frameElement ;
1284        var width = el.width ;
1285        var height = el.height ;
1286        if ( /^\d+$/.test( width ) ) width += 'px' ;
1287        if ( /^\d+$/.test( height ) ) height += 'px' ;
1288        var style = el.style ;
1289        style.border = style.padding = style.margin = 0 ;
1290        style.backgroundColor = 'transparent';
1291        style.backgroundImage = 'none';
1292        style.width = width ;
1293        style.height = height ;
1294})() ;
Note: See TracBrowser for help on using the repository browser.