Ticket #1229: 1229_4.patch

File 1229_4.patch, 9.8 kB (added by martinkou, 6 months 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.