Ticket #3165: 3165_4.patch

File 3165_4.patch, 7.1 KB (added by Garry Yao, 14 years ago)
  • _source/plugins/list/plugin.js

     
    539539                }
    540540        };
    541541
     542        var dtd = CKEDITOR.dtd;
     543        var tailNbspRegex = /[\t\r\n ]*(?: |\xa0)$/;
     544       
     545        function indexOfFirstChildElement( element, tagNameList )
     546        {
     547                var children = element.children,
     548                        child,
     549                        length = children.length;
     550                for ( var i = 0; i < length; i++ )
     551                {
     552                        child = children[ i ];
     553                        if( child.name && ( child.name in tagNameList ) )
     554                                return i;
     555                }
     556        }
     557
     558        function getExtendNestedListFilter( isHtmlFilter )
     559        {
     560                // An element filter function that corrects nested list start in an empty
     561                // list item for better displaying/outputting. (#3165)
     562                return function( listItem )
     563                {
     564                        var children = listItem.children,
     565                                firstNestedListIndex = indexOfFirstChildElement( listItem, dtd.$list ),
     566                                firstNestedList = children[ firstNestedListIndex ],
     567                                nodeBefore = firstNestedList && firstNestedList.previous,
     568                                tailNbspmatch;
     569
     570                        if( nodeBefore
     571                                && ( nodeBefore.name && nodeBefore.name == 'br'
     572                                        || nodeBefore.value && ( tailNbspmatch = nodeBefore.value.match( tailNbspRegex ) ) ) )
     573                        {
     574                                var fillerNode = nodeBefore;
     575
     576                                // Always use 'nbsp' as filler node if we found a nested list appear
     577                                // in front of a list item.
     578                                if ( !( tailNbspmatch && tailNbspmatch.index ) && fillerNode == children[ 0 ] )
     579                                        children[ 0 ] = ( isHtmlFilter || CKEDITOR.env.ie ) ?
     580                                                         new CKEDITOR.htmlParser.text( '\xa0' ) :
     581                                                                         new CKEDITOR.htmlParser.element( 'br', {} );
     582
     583                                // Otherwise the filler is not needed anymore.
     584                                else if ( fillerNode.name == 'br' )
     585                                        children.splice( firstNestedListIndex - 1, 1 );
     586                                else
     587                                        fillerNode.value = fillerNode.value.replace( tailNbspRegex, '' );
     588                        }
     589
     590                };
     591        }
     592
     593        var defaultListDataFilterRules = { elements : {} };
     594        for( var i in dtd.$listItem )
     595                defaultListDataFilterRules.elements[ i ] = getExtendNestedListFilter();
     596
     597        var defaultListHtmlFilterRules = { elements : {} };
     598        for( i in dtd.$listItem )
     599                defaultListHtmlFilterRules.elements[ i ] = getExtendNestedListFilter( true );
     600
    542601        CKEDITOR.plugins.add( 'list',
    543602        {
    544603                init : function( editor )
     
    566625                        editor.on( 'selectionChange', CKEDITOR.tools.bind( onSelectionChange, bulletedListCommand ) );
    567626                },
    568627
     628                afterInit : function ( editor )
     629                {
     630                        var dataProcessor = editor.dataProcessor;
     631                        if( dataProcessor )
     632                        {
     633                                dataProcessor.dataFilter.addRules( defaultListDataFilterRules );
     634                                dataProcessor.htmlFilter.addRules( defaultListHtmlFilterRules );
     635                        }
     636                },
     637
    569638                requires : [ 'domiterator' ]
    570639        } );
    571640})();
  • _source/plugins/enterkey/plugin.js

     
    101101                if ( !isStartOfBlock && !isEndOfBlock )
    102102                {
    103103                        // If the next block is an <li> with another list tree as the first
    104                         // child, we'll need to append a placeholder or the list item
     104                        // child, we'll need to append a filler (<br>/NBSP) or the list item
    105105                        // wouldn't be editable. (#1420)
    106                         if ( nextBlock.is( 'li' ) && ( node = nextBlock.getFirst() )
    107                                         && node.is && node.is( 'ul', 'ol') )
    108                                 nextBlock.insertBefore( doc.createText( '\xa0' ), node );
     106                        if ( nextBlock.is( 'li' )
     107                                 && ( node = nextBlock.getFirst( CKEDITOR.dom.walker.invisible( true ) ) )
     108                                 && node.is && node.is( 'ul', 'ol' ) )
     109                                ( CKEDITOR.env.ie ? doc.createText( '\xa0' ) : doc.createElement( 'br' ) ).insertBefore( node );
    109110
    110111                        // Move the selection to the end block.
    111112                        if ( nextBlock )
  • _source/core/dom/element.js

     
    627627
    628628                /**
    629629                 * Gets the first child node of this element.
     630                 * @param {Function} evaluator Filtering the result node.
    630631                 * @returns {CKEDITOR.dom.node} The first child node or null if not
    631632                 *              available.
    632633                 * @example
     
    634635                 * var first = <b>element.getFirst()</b>;
    635636                 * alert( first.getName() );  // "b"
    636637                 */
    637                 getFirst : function()
     638                getFirst : function( evaluator )
    638639                {
    639                         var $ = this.$.firstChild;
    640                         return $ ? new CKEDITOR.dom.node( $ ) : null;
     640                        var first = this.$.firstChild,
     641                                retval = first && new CKEDITOR.dom.node( first );
     642                        if ( retval && evaluator && !evaluator( retval ) )
     643                                retval = retval.getNext( evaluator );
     644
     645                        return retval;
    641646                },
    642647
    643648                /**
  • _source/plugins/selection/plugin.js

     
    952952                }
    953953        };
    954954})();
     955( function()
     956{
     957var notWhitespaces = CKEDITOR.dom.walker.whitespaces( true );
     958var fillerTextRegex = /\ufeff|\u00a0/;
    955959
    956960CKEDITOR.dom.range.prototype.select =
    957961        CKEDITOR.env.ie ?
     
    9961000                                // will expand and that the cursor will be blinking on the right place.
    9971001                                // Actually, we are using this flag just to avoid using this hack in all
    9981002                                // situations, but just on those needed.
    999                                 isStartMarkerAlone = forceExpand || !startNode.hasPrevious() || ( startNode.getPrevious().is && startNode.getPrevious().is( 'br' ) );
     1003                                var next = startNode.getNext( notWhitespaces );
     1004                                isStartMarkerAlone = ( !( next && next.getText && next.getText().match( fillerTextRegex ) )     // already a filler there?
     1005                                                                          && ( forceExpand || !startNode.hasPrevious() || ( startNode.getPrevious().is && startNode.getPrevious().is( 'br' ) ) ) );
    10001006
    10011007                                // Append a temporary <span>&#65279;</span> before the selection.
    10021008                                // This is needed to avoid IE destroying selections inside empty
     
    10801086                        selection.removeAllRanges();
    10811087                        selection.addRange( nativeRange );
    10821088                };
     1089} )();
  • _source/core/dom/walker.js

     
    408408                        return isReject ^ isWhitespace;
    409409                };
    410410        };
     411
     412        /**
     413         * Whether the node is invisible in wysiwyg mode.
     414         * @param isReject
     415         */
     416        CKEDITOR.dom.walker.invisible = function( isReject )
     417        {
     418                var whitespace = CKEDITOR.dom.walker.whitespaces();
     419                return function( node )
     420                {
     421                        // Nodes that take no spaces in wysiwyg:
     422                        // 1. White-spaces but not including NBSP;
     423                        // 2. Empty inline elements, e.g. <b></b> we're checking here
     424                        // 'offsetHeight' instead of 'offsetWidth' for properly excluding
     425                        // all sorts of empty paragraph, e.g. <br />.
     426                        var isInvisible = whitespace( node ) || node.is && !node.$.offsetHeight;
     427                        return isReject ^ isInvisible;
     428                };
     429        };
     430
    411431})();
© 2003 – 2022, CKSource sp. z o.o. sp.k. All rights reserved. | Terms of use | Privacy policy