Ticket #1229: 1229_3.patch

File 1229_3.patch, 9.8 KB (added by Frederico Caldeira Knabben, 13 years ago)
  • _whatsnew.html

     
    275275                        &lt;PRE&gt; block.</li>
    276276                <li>[<a target="_blank" href="http://dev.fckeditor.net/ticket/1627">#1627</a>] Samples
    277277                        failed to load from local filesystem in IE7.</li>
     278                <li>[<a target="_blank" href="http://dev.fckeditor.net/ticket/1229">#1229</a>] Converting
     279                        multiple contiguous paragraphs to Formatted will now be merged into a single
     280                        &lt;PRE&gt; block.</li>
    278281        </ul>
    279282        <p>
    280283                <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( preBlock )
     850        {
     851                // Get the sibling element before the block.
     852                var previousBlock = FCKDomTools.GetPreviousSourceElement( preBlock, true ) ;
     853
     854                // Check if the previous block is a <pre>.
     855                if ( previousBlock.nodeName.toLowerCase() != 'pre' )
     856                        return ;
     857
     858                // Merge the previous <pre> block contents into the current <pre>
     859                // block.
     860                //
     861                // Another thing to be careful here is that currentBlock might contain
     862                // a '\n' at the beginning, and previousBlock might contain a '\n'
     863                // towards the end. These new lines are not normally displayed but they
     864                // become visible after merging.
     865                var innerHTML = previousBlock.innerHTML.replace( /\n$/, '' ) + '\n\n' +
     866                                preBlock.innerHTML.replace( /^\n/, '' ) ;
     867
     868                // Buggy IE normalizes innerHTML from <pre>, breaking whitespaces.
     869                if ( FCKBrowserInfo.IsIE )
     870                        preBlock.outerHTML = '<pre>' + innerHTML + '</pre>' ;
     871                else
     872                        preBlock.innerHTML = innerHTML ;
     873
     874                // Remove the previous <pre> block.
     875                //
     876                // The preBlock must not be moved or deleted from the DOM tree. This
     877                // guarantees the FCKDomRangeIterator in _ApplyBlockStyle would not
     878                // get lost at the next iteration.
     879                FCKDomTools.RemoveNode( previousBlock ) ;
     880        },
     881
     882        _CheckAndSplitPre : function( previousBlock )
     883        {
     884                var lastNewBlock ;
     885
     886                var cursor = previousBlock.firstChild ;
     887               
     888                // We are not splitting <br><br> at the beginning of the block, so
     889                // we'll start from the second child.
     890                cursor = cursor && cursor.nextSibling ;
     891
     892                while ( cursor )
     893                {
     894                        var next = cursor.nextSibling ;
     895
     896                        // If we have two <BR>s, and they're not at the beginning or the end,
     897                        // then we'll split up the contents following them into another block.
     898                        // Stop processing if we are at the last child couple.
     899                        if ( next && next.nextSibling && cursor.nodeName.IEquals( 'br' ) && next.nodeName.IEquals( 'br' ) )
     900                        {
     901                                // Remove the first <br>.
     902                                FCKDomTools.RemoveNode( cursor ) ;
     903
     904                                // Move to the node after the second <br>.
     905                                cursor = next.nextSibling ;
     906
     907                                // Remove the second <br>.
     908                                FCKDomTools.RemoveNode( next ) ;
     909
     910                                // Create the block that will hold the child nodes from now on.
     911                                lastNewBlock = FCKDomTools.InsertAfterNode( lastNewBlock || previousBlock, FCKDomTools.CloneElement( previousBlock ) ) ;
     912
     913                                continue ;
     914                        }
     915
     916                        // If we split it, then start moving the nodes to the new block.
     917                        if ( lastNewBlock )
     918                                FCKDomTools.MoveNode( cursor, lastNewBlock ) ;
     919
     920                        cursor = cursor.nextSibling ;
     921                }
     922        },
     923
     924        /**
    840925         * Apply an inline style to a FCKDomRange.
    841926         *
    842927         * TODO
     
    857942                var block ;
    858943                var doc = range.Window.document ;
    859944
    860                 var preBlocks = [] ;
    861                 var convertedPreBlocks = [] ;
    862 
    863945                while( ( block = iterator.GetNextParagraph() ) )                // Only one =
    864946                {
    865947                        // Create the new node right before the current one.
    866948                        var newBlock = this.BuildElement( doc ) ;
    867949
     950                        // Check if we are changing from/to <pre>.
     951                        var newBlockIsPre       = newBlock.nodeName.IEquals( 'pre' ) ;
     952                        var blockIsPre          = block.nodeName.IEquals( 'pre' ) ;
     953                       
     954                        var toPre       = newBlockIsPre && !blockIsPre ;
     955                        var fromPre     = !newBlockIsPre && blockIsPre ;
     956                       
    868957                        // 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                         {
     958                        if ( toPre )
    873959                                newBlock = this._ToPre( doc, block, newBlock ) ;
    874                                 preBlocks.push( newBlock ) ;
    875                         }
    876                         else if ( !newBlockIsPre && blockIsPre )
    877                         {
     960                        else if ( fromPre )
    878961                                newBlock = this._FromPre( doc, block, newBlock ) ;
    879                                 convertedPreBlocks.push( newBlock ) ;
    880                         }
    881962                        else    // Convering from a regular block to another regular block.
    882963                                FCKDomTools.MoveChildren( block, newBlock ) ;
    883964
    884965                        // Replace the current block.
    885966                        block.parentNode.insertBefore( newBlock, block ) ;
    886967                        FCKDomTools.RemoveNode( block ) ;
    887                 }
    888968
    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] ) ;
     969                        // Complete other tasks after inserting the node in the DOM.
     970                        if ( newBlockIsPre )
     971                                this._CheckAndMergePre( newBlock ) ;    // Merge successive <pre> blocks.
     972                        else if ( fromPre )
     973                                this._CheckAndSplitPre( newBlock ) ;    // Split <br><br> in successive <pre>s.
    900974                }
    901975
    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++ )
    908                         {
    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                                 }
    928                         }
    929                 }
    930 
    931976                // Re-select the original range.
    932977                if ( selectIt )
    933978                        range.SelectBookmark( bookmark ) ;
© 2003 – 2019 CKSource – Frederico Knabben. All rights reserved. | Terms of use | Privacy policy