Ticket #1229: 1229_3.patch

File 1229_3.patch, 9.8 kB (added by fredck, 6 months 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 ) ;