source: sandbox/filemanager/tp/fckeditor/editor/_source/classes/fckenterkey.js @ 1575

Revision 1575, 20.6 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 * Controls the [Enter] keystroke behavior in a document.
22 */
23
24/*
25 *      Constructor.
26 *              @targetDocument : the target document.
27 *              @enterMode : the behavior for the <Enter> keystroke.
28 *                      May be "p", "div", "br". Default is "p".
29 *              @shiftEnterMode : the behavior for the <Shift>+<Enter> keystroke.
30 *                      May be "p", "div", "br". Defaults to "br".
31 */
32var FCKEnterKey = function( targetWindow, enterMode, shiftEnterMode, tabSpaces )
33{
34        this.Window                     = targetWindow ;
35        this.EnterMode          = enterMode || 'p' ;
36        this.ShiftEnterMode     = shiftEnterMode || 'br' ;
37
38        // Setup the Keystroke Handler.
39        var oKeystrokeHandler = new FCKKeystrokeHandler( false ) ;
40        oKeystrokeHandler._EnterKey = this ;
41        oKeystrokeHandler.OnKeystroke = FCKEnterKey_OnKeystroke ;
42
43        oKeystrokeHandler.SetKeystrokes( [
44                [ 13            , 'Enter' ],
45                [ SHIFT + 13, 'ShiftEnter' ],
46                [ 8                     , 'Backspace' ],
47                [ CTRL + 8      , 'CtrlBackspace' ],
48                [ 46            , 'Delete' ]
49        ] ) ;
50
51        this.TabText = '' ;
52
53        // Safari by default inserts 4 spaces on TAB, while others make the editor
54        // loose focus. So, we need to handle it here to not include those spaces.
55        if ( tabSpaces > 0 || FCKBrowserInfo.IsSafari )
56        {
57                while ( tabSpaces-- )
58                        this.TabText += '\xa0' ;
59
60                oKeystrokeHandler.SetKeystrokes( [ 9, 'Tab' ] );
61        }
62
63        oKeystrokeHandler.AttachToElement( targetWindow.document ) ;
64}
65
66
67function FCKEnterKey_OnKeystroke(  keyCombination, keystrokeValue )
68{
69        var oEnterKey = this._EnterKey ;
70
71        try
72        {
73                switch ( keystrokeValue )
74                {
75                        case 'Enter' :
76                                return oEnterKey.DoEnter() ;
77                                break ;
78                        case 'ShiftEnter' :
79                                return oEnterKey.DoShiftEnter() ;
80                                break ;
81                        case 'Backspace' :
82                                return oEnterKey.DoBackspace() ;
83                                break ;
84                        case 'Delete' :
85                                return oEnterKey.DoDelete() ;
86                                break ;
87                        case 'Tab' :
88                                return oEnterKey.DoTab() ;
89                                break ;
90                        case 'CtrlBackspace' :
91                                return oEnterKey.DoCtrlBackspace() ;
92                                break ;
93                }
94        }
95        catch (e)
96        {
97                // If for any reason we are not able to handle it, go
98                // ahead with the browser default behavior.
99        }
100
101        return false ;
102}
103
104/*
105 * Executes the <Enter> key behavior.
106 */
107FCKEnterKey.prototype.DoEnter = function( mode, hasShift )
108{
109        // Save an undo snapshot before doing anything
110        FCKUndo.SaveUndoStep() ;
111
112        this._HasShift = ( hasShift === true ) ;
113
114        var parentElement = FCKSelection.GetParentElement() ;
115        var parentPath = new FCKElementPath( parentElement ) ;
116        var sMode = mode || this.EnterMode ;
117
118        if ( sMode == 'br' || parentPath.Block && parentPath.Block.tagName.toLowerCase() == 'pre' )
119                return this._ExecuteEnterBr() ;
120        else
121                return this._ExecuteEnterBlock( sMode ) ;
122}
123
124/*
125 * Executes the <Shift>+<Enter> key behavior.
126 */
127FCKEnterKey.prototype.DoShiftEnter = function()
128{
129        return this.DoEnter( this.ShiftEnterMode, true ) ;
130}
131
132/*
133 * Executes the <Backspace> key behavior.
134 */
135FCKEnterKey.prototype.DoBackspace = function()
136{
137        var bCustom = false ;
138
139        // Get the current selection.
140        var oRange = new FCKDomRange( this.Window ) ;
141        oRange.MoveToSelection() ;
142
143        // Kludge for #247
144        if ( FCKBrowserInfo.IsIE && this._CheckIsAllContentsIncluded( oRange, this.Window.document.body ) )
145        {
146                this._FixIESelectAllBug( oRange ) ;
147                return true ;
148        }
149
150        var isCollapsed = oRange.CheckIsCollapsed() ;
151
152        if ( !isCollapsed )
153        {
154                // Bug #327, Backspace with an img selection would activate the default action in IE.
155                // Let's override that with our logic here.
156                if ( FCKBrowserInfo.IsIE && this.Window.document.selection.type.toLowerCase() == "control" )
157                {
158                        var controls = this.Window.document.selection.createRange() ;
159                        for ( var i = controls.length - 1 ; i >= 0 ; i-- )
160                        {
161                                var el = controls.item( i ) ;
162                                el.parentNode.removeChild( el ) ;
163                        }
164                        return true ;
165                }
166
167                return false ;
168        }
169
170        // On IE, it is better for us handle the deletion if the caret is preceeded
171        // by a <br> (#1383).
172        if ( FCKBrowserInfo.IsIE )
173        {
174                var previousElement = FCKDomTools.GetPreviousSourceElement( oRange.StartNode, true ) ;
175
176                if ( previousElement && previousElement.nodeName.toLowerCase() == 'br' )
177                {
178                        // Create a range that starts after the <br> and ends at the
179                        // current range position.
180                        var testRange = oRange.Clone() ;
181                        testRange.SetStart( previousElement, 4 ) ;
182
183                        // If that range is empty, we can proceed cleaning that <br> manually.
184                        if ( testRange.CheckIsEmpty() )
185                        {
186                                previousElement.parentNode.removeChild( previousElement ) ;
187                                return true ;
188                        }
189                }
190        }
191
192        var oStartBlock = oRange.StartBlock ;
193        var oEndBlock = oRange.EndBlock ;
194
195        // The selection boundaries must be in the same "block limit" element
196        if ( oRange.StartBlockLimit == oRange.EndBlockLimit && oStartBlock && oEndBlock )
197        {
198                if ( !isCollapsed )
199                {
200                        var bEndOfBlock = oRange.CheckEndOfBlock() ;
201
202                        oRange.DeleteContents() ;
203
204                        if ( oStartBlock != oEndBlock )
205                        {
206                                oRange.SetStart(oEndBlock,1) ;
207                                oRange.SetEnd(oEndBlock,1) ;
208
209//                              if ( bEndOfBlock )
210//                                      oEndBlock.parentNode.removeChild( oEndBlock ) ;
211                        }
212
213                        oRange.Select() ;
214
215                        bCustom = ( oStartBlock == oEndBlock ) ;
216                }
217
218                if ( oRange.CheckStartOfBlock() )
219                {
220                        var oCurrentBlock = oRange.StartBlock ;
221
222                        var ePrevious = FCKDomTools.GetPreviousSourceElement( oCurrentBlock, true, [ 'BODY', oRange.StartBlockLimit.nodeName ], ['UL','OL'] ) ;
223
224                        bCustom = this._ExecuteBackspace( oRange, ePrevious, oCurrentBlock ) ;
225                }
226                else if ( FCKBrowserInfo.IsGeckoLike )
227                {
228                        // Firefox and Opera (#1095) loose the selection when executing
229                        // CheckStartOfBlock, so we must reselect.
230                        oRange.Select() ;
231                }
232        }
233
234        oRange.Release() ;
235        return bCustom ;
236}
237
238FCKEnterKey.prototype.DoCtrlBackspace = function()
239{
240        FCKUndo.SaveUndoStep() ;
241        var oRange = new FCKDomRange( this.Window ) ;
242        oRange.MoveToSelection() ;
243        if ( FCKBrowserInfo.IsIE && this._CheckIsAllContentsIncluded( oRange, this.Window.document.body ) )
244        {
245                this._FixIESelectAllBug( oRange ) ;
246                return true ;
247        }
248        return false ;
249}
250
251FCKEnterKey.prototype._ExecuteBackspace = function( range, previous, currentBlock )
252{
253        var bCustom = false ;
254
255        // We could be in a nested LI.
256        if ( !previous && currentBlock && currentBlock.nodeName.IEquals( 'LI' ) && currentBlock.parentNode.parentNode.nodeName.IEquals( 'LI' ) )
257        {
258                this._OutdentWithSelection( currentBlock, range ) ;
259                return true ;
260        }
261
262        if ( previous && previous.nodeName.IEquals( 'LI' ) )
263        {
264                var oNestedList = FCKDomTools.GetLastChild( previous, ['UL','OL'] ) ;
265
266                while ( oNestedList )
267                {
268                        previous = FCKDomTools.GetLastChild( oNestedList, 'LI' ) ;
269                        oNestedList = FCKDomTools.GetLastChild( previous, ['UL','OL'] ) ;
270                }
271        }
272
273        if ( previous && currentBlock )
274        {
275                // If we are in a LI, and the previous block is not an LI, we must outdent it.
276                if ( currentBlock.nodeName.IEquals( 'LI' ) && !previous.nodeName.IEquals( 'LI' ) )
277                {
278                        this._OutdentWithSelection( currentBlock, range ) ;
279                        return true ;
280                }
281
282                // Take a reference to the parent for post processing cleanup.
283                var oCurrentParent = currentBlock.parentNode ;
284
285                var sPreviousName = previous.nodeName.toLowerCase() ;
286                if ( FCKListsLib.EmptyElements[ sPreviousName ] != null || sPreviousName == 'table' )
287                {
288                        FCKDomTools.RemoveNode( previous ) ;
289                        bCustom = true ;
290                }
291                else
292                {
293                        // Remove the current block.
294                        FCKDomTools.RemoveNode( currentBlock ) ;
295
296                        // Remove any empty tag left by the block removal.
297                        while ( oCurrentParent.innerHTML.Trim().length == 0 )
298                        {
299                                var oParent = oCurrentParent.parentNode ;
300                                oParent.removeChild( oCurrentParent ) ;
301                                oCurrentParent = oParent ;
302                        }
303
304                        // Cleanup the previous and the current elements.
305                        FCKDomTools.LTrimNode( currentBlock ) ;
306                        FCKDomTools.RTrimNode( previous ) ;
307
308                        // Append a space to the previous.
309                        // Maybe it is not always desirable...
310                        // previous.appendChild( this.Window.document.createTextNode( ' ' ) ) ;
311
312                        // Set the range to the end of the previous element and bookmark it.
313                        range.SetStart( previous, 2, true ) ;
314                        range.Collapse( true ) ;
315                        var oBookmark = range.CreateBookmark( true ) ;
316
317                        // Move the contents of the block to the previous element and delete it.
318                        // But for some block types (e.g. table), moving the children to the previous block makes no sense.
319                        // So a check is needed. (See #1081)
320                        if ( ! currentBlock.tagName.IEquals( [ 'TABLE' ] ) )
321                                FCKDomTools.MoveChildren( currentBlock, previous ) ;
322
323                        // Place the selection at the bookmark.
324                        range.SelectBookmark( oBookmark ) ;
325
326                        bCustom = true ;
327                }
328        }
329
330        return bCustom ;
331}
332
333/*
334 * Executes the <Delete> key behavior.
335 */
336FCKEnterKey.prototype.DoDelete = function()
337{
338        // Save an undo snapshot before doing anything
339        // This is to conform with the behavior seen in MS Word
340        FCKUndo.SaveUndoStep() ;
341
342        // The <Delete> has the same effect as the <Backspace>, so we have the same
343        // results if we just move to the next block and apply the same <Backspace> logic.
344
345        var bCustom = false ;
346
347        // Get the current selection.
348        var oRange = new FCKDomRange( this.Window ) ;
349        oRange.MoveToSelection() ;
350
351        // Kludge for #247
352        if ( FCKBrowserInfo.IsIE && this._CheckIsAllContentsIncluded( oRange, this.Window.document.body ) )
353        {
354                this._FixIESelectAllBug( oRange ) ;
355                return true ;
356        }
357
358        // There is just one special case for collapsed selections at the end of a block.
359        if ( oRange.CheckIsCollapsed() && oRange.CheckEndOfBlock( FCKBrowserInfo.IsGeckoLike ) )
360        {
361                var oCurrentBlock = oRange.StartBlock ;
362                var eCurrentCell = FCKTools.GetElementAscensor( oCurrentBlock, 'td' );
363
364                var eNext = FCKDomTools.GetNextSourceElement( oCurrentBlock, true, [ oRange.StartBlockLimit.nodeName ],
365                                ['UL','OL','TR'], true ) ;
366
367                // Bug #1323 : if we're in a table cell, and the next node belongs to a different cell, then don't
368                // delete anything.
369                if ( eCurrentCell )
370                {
371                        var eNextCell = FCKTools.GetElementAscensor( eNext, 'td' );
372                        if ( eNextCell != eCurrentCell )
373                                return true ;
374                }
375
376                bCustom = this._ExecuteBackspace( oRange, oCurrentBlock, eNext ) ;
377        }
378
379        oRange.Release() ;
380        return bCustom ;
381}
382
383/*
384 * Executes the <Tab> key behavior.
385 */
386FCKEnterKey.prototype.DoTab = function()
387{
388        var oRange = new FCKDomRange( this.Window );
389        oRange.MoveToSelection() ;
390
391        // If the user pressed <tab> inside a table, we should give him the default behavior ( moving between cells )
392        // instead of giving him more non-breaking spaces. (Bug #973)
393        var node = oRange._Range.startContainer ;
394        while ( node )
395        {
396                if ( node.nodeType == 1 )
397                {
398                        var tagName = node.tagName.toLowerCase() ;
399                        if ( tagName == "tr" || tagName == "td" || tagName == "th" || tagName == "tbody" || tagName == "table" )
400                                return false ;
401                        else
402                                break ;
403                }
404                node = node.parentNode ;
405        }
406
407        if ( this.TabText )
408        {
409                oRange.DeleteContents() ;
410                oRange.InsertNode( this.Window.document.createTextNode( this.TabText ) ) ;
411                oRange.Collapse( false ) ;
412                oRange.Select() ;
413        }
414        return true ;
415}
416
417FCKEnterKey.prototype._ExecuteEnterBlock = function( blockTag, range )
418{
419        // Get the current selection.
420        var oRange = range || new FCKDomRange( this.Window ) ;
421
422        var oSplitInfo = oRange.SplitBlock( blockTag ) ;
423
424        if ( oSplitInfo )
425        {
426                // Get the current blocks.
427                var ePreviousBlock      = oSplitInfo.PreviousBlock ;
428                var eNextBlock          = oSplitInfo.NextBlock ;
429
430                var bIsStartOfBlock     = oSplitInfo.WasStartOfBlock ;
431                var bIsEndOfBlock       = oSplitInfo.WasEndOfBlock ;
432
433                // If there is one block under a list item, modify the split so that the list item gets split as well. (Bug #1647)
434                if ( eNextBlock )
435                {
436                        if ( eNextBlock.parentNode.nodeName.IEquals( 'li' ) )
437                        {
438                                FCKDomTools.BreakParent( eNextBlock, eNextBlock.parentNode ) ;
439                                FCKDomTools.MoveNode( eNextBlock, eNextBlock.nextSibling, true ) ;
440                        }
441                }
442                else if ( ePreviousBlock && ePreviousBlock.parentNode.nodeName.IEquals( 'li' ) )
443                {
444                        FCKDomTools.BreakParent( ePreviousBlock, ePreviousBlock.parentNode ) ;
445                        oRange.MoveToElementEditStart( ePreviousBlock.nextSibling );
446                        FCKDomTools.MoveNode( ePreviousBlock, ePreviousBlock.previousSibling ) ;
447                }
448
449                // If we have both the previous and next blocks, it means that the
450                // boundaries were on separated blocks, or none of them where on the
451                // block limits (start/end).
452                if ( !bIsStartOfBlock && !bIsEndOfBlock )
453                {
454                        // If the next block is an <li> with another list tree as the first child
455                        // We'll need to append a placeholder or the list item wouldn't be editable. (Bug #1420)
456                        if ( eNextBlock.nodeName.IEquals( 'li' ) && eNextBlock.firstChild
457                                        && eNextBlock.firstChild.nodeName.IEquals( ['ul', 'ol'] ) )
458                                eNextBlock.insertBefore( FCKTools.GetElementDocument( eNextBlock ).createTextNode( '\xa0' ), eNextBlock.firstChild ) ;
459                        // Move the selection to the end block.
460                        if ( eNextBlock )
461                                oRange.MoveToElementEditStart( eNextBlock ) ;
462                }
463                else
464                {
465                        if ( bIsStartOfBlock && bIsEndOfBlock && ePreviousBlock.tagName.toUpperCase() == 'LI' )
466                        {
467                                oRange.MoveToElementStart( ePreviousBlock ) ;
468                                this._OutdentWithSelection( ePreviousBlock, oRange ) ;
469                                oRange.Release() ;
470                                return true ;
471                        }
472
473                        var eNewBlock ;
474
475                        if ( ePreviousBlock )
476                        {
477                                var sPreviousBlockTag = ePreviousBlock.tagName.toUpperCase() ;
478
479                                // If is a header tag, or we are in a Shift+Enter (#77),
480                                // create a new block element (later in the code).
481                                if ( !this._HasShift && !(/^H[1-6]$/).test( sPreviousBlockTag ) )
482                                {
483                                        // Otherwise, duplicate the previous block.
484                                        eNewBlock = FCKDomTools.CloneElement( ePreviousBlock ) ;
485                                }
486                        }
487                        else if ( eNextBlock )
488                                eNewBlock = FCKDomTools.CloneElement( eNextBlock ) ;
489
490                        if ( !eNewBlock )
491                                eNewBlock = this.Window.document.createElement( blockTag ) ;
492
493                        // Recreate the inline elements tree, which was available
494                        // before the hitting enter, so the same styles will be
495                        // available in the new block.
496                        var elementPath = oSplitInfo.ElementPath ;
497                        if ( elementPath )
498                        {
499                                for ( var i = 0, len = elementPath.Elements.length ; i < len ; i++ )
500                                {
501                                        var element = elementPath.Elements[i] ;
502
503                                        if ( element == elementPath.Block || element == elementPath.BlockLimit )
504                                                break ;
505
506                                        if ( FCKListsLib.InlineChildReqElements[ element.nodeName.toLowerCase() ] )
507                                        {
508                                                element = FCKDomTools.CloneElement( element ) ;
509                                                FCKDomTools.MoveChildren( eNewBlock, element ) ;
510                                                eNewBlock.appendChild( element ) ;
511                                        }
512                                }
513                        }
514
515                        if ( FCKBrowserInfo.IsGeckoLike )
516                                FCKTools.AppendBogusBr( eNewBlock ) ;
517
518                        oRange.InsertNode( eNewBlock ) ;
519
520                        // This is tricky, but to make the new block visible correctly
521                        // we must select it.
522                        if ( FCKBrowserInfo.IsIE )
523                        {
524                                // Move the selection to the new block.
525                                oRange.MoveToElementEditStart( eNewBlock ) ;
526                                oRange.Select() ;
527                        }
528
529                        // Move the selection to the new block.
530                        oRange.MoveToElementEditStart( bIsStartOfBlock && !bIsEndOfBlock ? eNextBlock : eNewBlock ) ;
531                }
532
533                if ( FCKBrowserInfo.IsGeckoLike )
534                {
535                        if ( eNextBlock )
536                        {
537                                // If we have split the block, adds a temporary span at the
538                                // range position and scroll relatively to it.
539                                var tmpNode = this.Window.document.createElement( 'span' ) ;
540
541                                // We need some content for Safari.
542                                tmpNode.innerHTML = '&nbsp;';
543
544                                oRange.InsertNode( tmpNode ) ;
545                                FCKDomTools.ScrollIntoView( tmpNode, false ) ;
546                                oRange.DeleteContents() ;
547                        }
548                        else
549                        {
550                                // We may use the above scroll logic for the new block case
551                                // too, but it gives some weird result with Opera.
552                                FCKDomTools.ScrollIntoView( eNextBlock || eNewBlock, false ) ;
553                        }
554                }
555
556                oRange.Select() ;
557        }
558
559        // Release the resources used by the range.
560        oRange.Release() ;
561
562        return true ;
563}
564
565FCKEnterKey.prototype._ExecuteEnterBr = function( blockTag )
566{
567        // Get the current selection.
568        var oRange = new FCKDomRange( this.Window ) ;
569        oRange.MoveToSelection() ;
570
571        // The selection boundaries must be in the same "block limit" element.
572        if ( oRange.StartBlockLimit == oRange.EndBlockLimit )
573        {
574                oRange.DeleteContents() ;
575
576                // Get the new selection (it is collapsed at this point).
577                oRange.MoveToSelection() ;
578
579                var bIsStartOfBlock     = oRange.CheckStartOfBlock() ;
580                var bIsEndOfBlock       = oRange.CheckEndOfBlock() ;
581
582                var sStartBlockTag = oRange.StartBlock ? oRange.StartBlock.tagName.toUpperCase() : '' ;
583
584                var bHasShift = this._HasShift ;
585                var bIsPre = false ;
586
587                if ( !bHasShift && sStartBlockTag == 'LI' )
588                        return this._ExecuteEnterBlock( null, oRange ) ;
589
590                // If we are at the end of a header block.
591                if ( !bHasShift && bIsEndOfBlock && (/^H[1-6]$/).test( sStartBlockTag ) )
592                {
593                        // Insert a BR after the current paragraph.
594                        FCKDomTools.InsertAfterNode( oRange.StartBlock, this.Window.document.createElement( 'br' ) ) ;
595
596                        // The space is required by Gecko only to make the cursor blink.
597                        if ( FCKBrowserInfo.IsGecko )
598                                FCKDomTools.InsertAfterNode( oRange.StartBlock, this.Window.document.createTextNode( '' ) ) ;
599
600                        // IE and Gecko have different behaviors regarding the position.
601                        oRange.SetStart( oRange.StartBlock.nextSibling, FCKBrowserInfo.IsIE ? 3 : 1 ) ;
602                }
603                else
604                {
605                        var eLineBreak ;
606                        bIsPre = sStartBlockTag.IEquals( 'pre' ) ;
607                        if ( bIsPre )
608                                eLineBreak = this.Window.document.createTextNode( FCKBrowserInfo.IsIE ? '\r' : '\n' ) ;
609                        else
610                                eLineBreak = this.Window.document.createElement( 'br' ) ;
611
612                        oRange.InsertNode( eLineBreak ) ;
613
614                        // The space is required by Gecko only to make the cursor blink.
615                        if ( FCKBrowserInfo.IsGecko )
616                                FCKDomTools.InsertAfterNode( eLineBreak, this.Window.document.createTextNode( '' ) ) ;
617
618                        // If we are at the end of a block, we must be sure the bogus node is available in that block.
619                        if ( bIsEndOfBlock && FCKBrowserInfo.IsGeckoLike )
620                                FCKTools.AppendBogusBr( eLineBreak.parentNode ) ;
621
622                        if ( FCKBrowserInfo.IsIE )
623                                oRange.SetStart( eLineBreak, 4 ) ;
624                        else
625                                oRange.SetStart( eLineBreak.nextSibling, 1 ) ;
626
627                        if ( ! FCKBrowserInfo.IsIE )
628                        {
629                                var dummy = null ;
630                                if ( FCKBrowserInfo.IsOpera )
631                                        dummy = this.Window.document.createElement( 'span' ) ;
632                                else
633                                        dummy = this.Window.document.createElement( 'br' ) ;
634
635                                eLineBreak.parentNode.insertBefore( dummy, eLineBreak.nextSibling ) ;
636
637                                FCKDomTools.ScrollIntoView( dummy, false ) ;
638
639                                dummy.parentNode.removeChild( dummy ) ;
640                        }
641                }
642
643                // This collapse guarantees the cursor will be blinking.
644                oRange.Collapse( true ) ;
645
646                oRange.Select( bIsPre ) ;
647        }
648
649        // Release the resources used by the range.
650        oRange.Release() ;
651
652        return true ;
653}
654
655// Outdents a LI, maintaining the selection defined on a range.
656FCKEnterKey.prototype._OutdentWithSelection = function( li, range )
657{
658        var oBookmark = range.CreateBookmark() ;
659
660        FCKListHandler.OutdentListItem( li ) ;
661
662        range.MoveToBookmark( oBookmark ) ;
663        range.Select() ;
664}
665
666// Is all the contents under a node included by a range?
667FCKEnterKey.prototype._CheckIsAllContentsIncluded = function( range, node )
668{
669        var startOk = false ;
670        var endOk = false ;
671
672        /*
673        FCKDebug.Output( 'sc='+range.StartContainer.nodeName+
674                        ',so='+range._Range.startOffset+
675                        ',ec='+range.EndContainer.nodeName+
676                        ',eo='+range._Range.endOffset ) ;
677        */
678        if ( range.StartContainer == node || range.StartContainer == node.firstChild )
679                startOk = ( range._Range.startOffset == 0 ) ;
680
681        if ( range.EndContainer == node || range.EndContainer == node.lastChild )
682        {
683                var nodeLength = range.EndContainer.nodeType == 3 ? range.EndContainer.length : range.EndContainer.childNodes.length ;
684                endOk = ( range._Range.endOffset == nodeLength ) ;
685        }
686
687        return startOk && endOk ;
688}
689
690// Kludge for #247
691FCKEnterKey.prototype._FixIESelectAllBug = function( range )
692{
693        var doc = this.Window.document ;
694        doc.body.innerHTML = '' ;
695        var editBlock ;
696        if ( FCKConfig.EnterMode.IEquals( ['div', 'p'] ) )
697        {
698                editBlock = doc.createElement( FCKConfig.EnterMode ) ;
699                doc.body.appendChild( editBlock ) ;
700        }
701        else
702                editBlock = doc.body ;
703
704        range.MoveToNodeContents( editBlock ) ;
705        range.Collapse( true ) ;
706        range.Select() ;
707        range.Release() ;
708}
Note: See TracBrowser for help on using the repository browser.