Ticket #1229: 1229_4.patch

File 1229_4.patch, 9.8 KB (added by Martin Kou, 13 years ago)
  • _whatsnew.html

     
    300300                        block.</li>
    301301                <li>[<a target="_blank" href="http://dev.fckeditor.net/ticket/1627">#1627</a>] Samples
    302302                        failed to load from local filesystem in IE7.</li>
     303                <li>[<a target="_blank" href="http://dev.fckeditor.net/ticket/1229">#1229</a>] Converting
     304                        multiple contiguous paragraphs to Formatted will now be merged into a single
     305                        &lt;PRE&gt; block.</li>
    303306        </ul>
    304307        <p>
    305308                <a href="_whatsnew_history.html">See previous versions history</a>
  • editor/_source/classes/fckstyle.js

     
    781781                        {
    782782                                if ( !isTag )
    783783                                {
    784                                         value = value.replace( /\n/g, '<BR>' ) ;
     784                                        value = value.replace( /\n/g, '<br>' ) ;
    785785                                        value = value.replace( /[ \t]{2,}/g,
    786786                                                        function ( match )
    787787                                                        {
     
    802802                // Handle converting from a regular block to a <pre> block.
    803803                var innerHTML = block.innerHTML.Trim() ;
    804804
    805                 // 1. Delete ANSI whitespaces immediately before and after <BR> because they are not visible.
    806                 // 2. Mark down any <BR /> nodes here so they can be turned into \n in the next step and avoid being compressed.
    807                 innerHTML = innerHTML.replace( /[ \t\r\n]*(<br[^>]*>)[ \t\r\n]*/gi, '<BR />' ) ;
     805                // 1. Delete ANSI whitespaces immediately before and after <BR> because
     806                //    they are not visible.
     807                // 2. Mark down any <BR /> nodes here so they can be turned into \n in
     808                //    the next step and avoid being compressed.
     809                innerHTML = innerHTML.replace( /[ \t\r\n]*(<br[^>]*>)[ \t\r\n]*/gi, '<br />' ) ;
    808810
    809                 // 3. Compress other ANSI whitespaces since they're only visible as one single space previously.
     811                // 3. Compress other ANSI whitespaces since they're only visible as one
     812                //    single space previously.
    810813                // 4. Convert &nbsp; to spaces since &nbsp; is no longer needed in <PRE>.
    811                 // 5. Convert any <BR /> to \n. This must not be done earlier because the \n would then get compressed.
     814                // 5. Convert any <BR /> to \n. This must not be done earlier because
     815                //    the \n would then get compressed.
    812816                var htmlIterator = new FCKHtmlIterator( innerHTML ) ;
    813817                var results = [] ;
    814818                htmlIterator.Each( function( isTag, value )
    815819                        {
    816820                                if ( !isTag )
    817821                                        value = value.replace( /([ \t\n\r]+|&nbsp;)/g, ' ' ) ;
    818                                 else if ( isTag && value == '<BR />' )
     822                                else if ( isTag && value == '<br />' )
    819823                                        value = '\n' ;
    820824                                results.push( value ) ;
    821825                        } ) ;
    822826
    823                 // Assigning innerHTML to <PRE> in IE causes all linebreaks to be reduced to spaces.
    824                 // Assigning outerHTML to <PRE> in IE doesn't work if the <PRE> isn't contained in another node
    825                 // since the node reference is changed after outerHTML assignment.
     827                // Assigning innerHTML to <PRE> in IE causes all linebreaks to be
     828                // reduced to spaces.
     829                // Assigning outerHTML to <PRE> in IE doesn't work if the <PRE> isn't
     830                // contained in another node since the node reference is changed after
     831                // outerHTML assignment.
    826832                // So, we need some hacks to workaround IE bugs here.
    827833                if ( FCKBrowserInfo.IsIE )
    828834                {
    829835                        var temp = doc.createElement( 'div' ) ;
    830836                        temp.appendChild( newBlock ) ;
    831                         newBlock.outerHTML = '<PRE>\n' + results.join( '' ) + '</PRE>' ;
     837                        newBlock.outerHTML = '<pre>\n' + results.join( '' ) + '</pre>' ;
    832838                        newBlock = temp.removeChild( temp.firstChild ) ;
    833839                }
    834840                else
    835841                        newBlock.innerHTML = results.join( '' ) ;
     842
    836843                return newBlock ;
    837844        },
    838845
    839846        /**
     847         * Merge a <pre> block with a previous <pre> block, if available.
     848         */
     849        _CheckAndMergePre : function( previousBlock, preBlock )
     850        {
     851                // Check if the previous block and the current block are next
     852                // to each other.
     853                if ( previousBlock != FCKDomTools.GetPreviousSourceElement( preBlock, true ) )
     854                        return ;
     855
     856                // Merge the previous <pre> block contents into the current <pre>
     857                // block.
     858                //
     859                // Another thing to be careful here is that currentBlock might contain
     860                // a '\n' at the beginning, and previousBlock might contain a '\n'
     861                // towards the end. These new lines are not normally displayed but they
     862                // become visible after merging.
     863                var innerHTML = previousBlock.innerHTML.replace( /\n$/, '' ) + '\n\n' +
     864                                preBlock.innerHTML.replace( /^\n/, '' ) ;
     865
     866                // Buggy IE normalizes innerHTML from <pre>, breaking whitespaces.
     867                if ( FCKBrowserInfo.IsIE )
     868                        preBlock.outerHTML = '<pre>' + innerHTML + '</pre>' ;
     869                else
     870                        preBlock.innerHTML = innerHTML ;
     871
     872                // Remove the previous <pre> block.
     873                //
     874                // The preBlock must not be moved or deleted from the DOM tree. This
     875                // guarantees the FCKDomRangeIterator in _ApplyBlockStyle would not
     876                // get lost at the next iteration.
     877                FCKDomTools.RemoveNode( previousBlock ) ;
     878        },
     879
     880        _CheckAndSplitPre : function( newBlock )
     881        {
     882                var lastNewBlock ;
     883
     884                var cursor = newBlock.firstChild ;
     885               
     886                // We are not splitting <br><br> at the beginning of the block, so
     887                // we'll start from the second child.
     888                cursor = cursor && cursor.nextSibling ;
     889
     890                while ( cursor )
     891                {
     892                        var next = cursor.nextSibling ;
     893
     894                        // If we have two <BR>s, and they're not at the beginning or the end,
     895                        // then we'll split up the contents following them into another block.
     896                        // Stop processing if we are at the last child couple.
     897                        if ( next && next.nextSibling && cursor.nodeName.IEquals( 'br' ) && next.nodeName.IEquals( 'br' ) )
     898                        {
     899                                // Remove the first <br>.
     900                                FCKDomTools.RemoveNode( cursor ) ;
     901
     902                                // Move to the node after the second <br>.
     903                                cursor = next.nextSibling ;
     904
     905                                // Remove the second <br>.
     906                                FCKDomTools.RemoveNode( next ) ;
     907
     908                                // Create the block that will hold the child nodes from now on.
     909                                lastNewBlock = FCKDomTools.InsertAfterNode( lastNewBlock || newBlock, FCKDomTools.CloneElement( newBlock ) ) ;
     910
     911                                continue ;
     912                        }
     913
     914                        // If we split it, then start moving the nodes to the new block.
     915                        if ( lastNewBlock )
     916                        {
     917                                cursor = cursor.previousSibling ;
     918                                FCKDomTools.MoveNode(cursor.nextSibling, lastNewBlock ) ;
     919                        }
     920
     921                        cursor = cursor.nextSibling ;
     922                }
     923        },
     924
     925        /**
    840926         * Apply an inline style to a FCKDomRange.
    841927         *
    842928         * TODO
     
    856942
    857943                var block ;
    858944                var doc = range.Window.document ;
     945                var previousPreBlock ;
    859946
    860                 var preBlocks = [] ;
    861                 var convertedPreBlocks = [] ;
    862 
    863947                while( ( block = iterator.GetNextParagraph() ) )                // Only one =
    864948                {
    865949                        // Create the new node right before the current one.
    866950                        var newBlock = this.BuildElement( doc ) ;
    867951
     952                        // Check if we are changing from/to <pre>.
     953                        var newBlockIsPre       = newBlock.nodeName.IEquals( 'pre' ) ;
     954                        var blockIsPre          = block.nodeName.IEquals( 'pre' ) ;
     955                       
     956                        var toPre       = newBlockIsPre && !blockIsPre ;
     957                        var fromPre     = !newBlockIsPre && blockIsPre ;
     958                       
    868959                        // Move everything from the current node to the new one.
    869                         var newBlockIsPre = newBlock.nodeName.IEquals( 'pre' ) ;
    870                         var blockIsPre = block.nodeName.IEquals( 'pre' ) ;
    871                         if ( newBlockIsPre && !blockIsPre )
    872                         {
     960                        if ( toPre )
    873961                                newBlock = this._ToPre( doc, block, newBlock ) ;
    874                                 preBlocks.push( newBlock ) ;
    875                         }
    876                         else if ( !newBlockIsPre && blockIsPre )
    877                         {
     962                        else if ( fromPre )
    878963                                newBlock = this._FromPre( doc, block, newBlock ) ;
    879                                 convertedPreBlocks.push( newBlock ) ;
    880                         }
    881964                        else    // Convering from a regular block to another regular block.
    882965                                FCKDomTools.MoveChildren( block, newBlock ) ;
    883966
    884967                        // Replace the current block.
    885968                        block.parentNode.insertBefore( newBlock, block ) ;
    886969                        FCKDomTools.RemoveNode( block ) ;
    887                 }
    888970
    889                 // Merge adjacent <PRE> blocks for #1229.
    890                 for ( var i = 0 ; i < preBlocks.length - 1 ; i++ )
    891                 {
    892                         // Check if the next block in HTML equals the next <PRE> block generated.
    893                         if ( FCKDomTools.GetNextSourceElement( preBlocks[i], true, [], [], true ) != preBlocks[i+1] )
    894                                 continue ;
    895 
    896                         // Merge the upper <PRE> block's content into the lower <PRE> block.
    897                         // Remove the upper <PRE> block.
    898                         preBlocks[i+1].innerHTML = preBlocks[i].innerHTML + '\n\n' + preBlocks[i+1].innerHTML ;
    899                         FCKDomTools.RemoveNode( preBlocks[i] ) ;
    900                 }
    901 
    902                 // Split converted <PRE> blocks for #1229.
    903                 for ( var i = 0 ; i < convertedPreBlocks.length ; i++ )
    904                 {
    905                         var currentBlock = convertedPreBlocks[i] ;
    906                         var lastNewBlock = null ;
    907                         for ( var j = 0 ; j < currentBlock.childNodes.length ; j++ )
     971                        // Complete other tasks after inserting the node in the DOM.
     972                        if ( newBlockIsPre )
    908973                        {
    909                                 var cursor = currentBlock.childNodes[j] ;
    910 
    911                                 // If we have two <BR>s, and they're not at the beginning or the end,
    912                                 // then we'll split up the contents following them into another block.
    913                                 if ( cursor.nodeName.IEquals( 'br' ) && j != 0 && j != currentBlock.childNodes.length - 2
    914                                                 && cursor.nextSibling && cursor.nextSibling.nodeName.IEquals( 'br' ) )
    915                                 {
    916                                         FCKDomTools.RemoveNode( cursor.nextSibling ) ;
    917                                         FCKDomTools.RemoveNode( cursor ) ;
    918                                         j-- ;   // restart at current index at next iteration
    919                                         lastNewBlock = FCKDomTools.InsertAfterNode( lastNewBlock || currentBlock, doc.createElement( currentBlock.nodeName ) ) ;
    920                                         continue ;
    921                                 }
    922 
    923                                 if ( lastNewBlock )
    924                                 {
    925                                         FCKDomTools.MoveNode( cursor, lastNewBlock ) ;
    926                                         j-- ;   // restart at current index at next iteration
    927                                 }
     974                                if ( previousPreBlock )
     975                                        this._CheckAndMergePre( previousPreBlock, newBlock ) ;  // Merge successive <pre> blocks.
     976                                previousPreBlock = newBlock ;
    928977                        }
     978                        else if ( fromPre )
     979                                this._CheckAndSplitPre( newBlock ) ;    // Split <br><br> in successive <pre>s.
    929980                }
    930981
    931982                // Re-select the original range.
© 2003 – 2019 CKSource – Frederico Knabben. All rights reserved. | Terms of use | Privacy policy