Ticket #3478: 3478.patch

File 3478.patch, 13.5 KB (added by Garry Yao, 10 years ago)
  • _source/core/dom/node.js

     
    602602                                        child.parentNode.removeChild( child ) ;
    603603                                }
    604604                        }
     605                },
     606               
     607                /**
     608                 * Whether the node is within the specified range.
     609                 * @param {CKEDITOR.dom.range}
     610                */
     611                within : function( range )
     612                {
     613                        if ( range.collapsed )
     614                                return false;
     615
     616                        var start = range.startContainer,
     617                                end = range.endContainer,
     618                                afterStart = ( this.getPosition( start ) | CKEDITOR.POSITION_FOLLOWING | CKEDITOR.POSITION_IDENTICAL | CKEDITOR.POSITION_IS_CONTAINED ) == ( CKEDITOR.POSITION_FOLLOWING + CKEDITOR.POSITION_IDENTICAL + CKEDITOR.POSITION_IS_CONTAINED ),
     619                                beforeEnd = ( this.getPosition( end ) | CKEDITOR.POSITION_PRECEDING | CKEDITOR.POSITION_IDENTICAL | CKEDITOR.POSITION_IS_CONTAINED ) == ( CKEDITOR.POSITION_PRECEDING + CKEDITOR.POSITION_IDENTICAL + CKEDITOR.POSITION_IS_CONTAINED );
     620                               
     621                                return afterStart && beforeEnd;
    605622                }
    606623        }
    607624);
  • _source/plugins/styles/plugin.js

     
    257257
    258258                // Builds the StyleText.
    259259
    260                 var stylesText = ( styleDefinition.attributes && styleDefinition.attributes[ 'style' ] ) || '';
     260                var stylesText =
     261                ( styleDefinition.attributes
     262                  && styleDefinition.attributes[ 'style' ] ) || '';
    261263
    262264                if ( stylesText.length )
    263265                        stylesText = stylesText.replace( semicolonFixRegex, ';' );
     
    292294                        range.insertNode( collapsedElement );
    293295
    294296                        // Place the selection right inside the empty element.
    295                         range.moveToPosition( collapsedElement, CKEDITOR.POSITION_BEFORE_END );
     297                        range.moveToPosition( collapsedElement,
     298                                                                 CKEDITOR.POSITION_BEFORE_END );
    296299
    297300                        return;
    298301                }
     
    302305                var isUnknownElement;
    303306
    304307                // Get the DTD definition for the element. Defaults to "span".
    305                 var dtd = CKEDITOR.dtd[ elementName ] || ( isUnknownElement = true, CKEDITOR.dtd.span );
     308                var dtd = CKEDITOR.dtd[ elementName ]
     309                        || ( isUnknownElement = true, CKEDITOR.dtd.span );
    306310
    307311                // Bookmark the range so we can re-select it after processing.
    308312                var bookmark = range.createBookmark();
     
    311315                range.enlarge( CKEDITOR.ENLARGE_ELEMENT );
    312316                range.trim();
    313317
    314                 // Get the first node to be processed and the last, which concludes the
    315                 // processing.
    316                 var boundaryNodes = range.getBoundaryNodes();
    317                 var firstNode = boundaryNodes.startNode;
    318                 var lastNode = boundaryNodes.endNode.getNextSourceNode( true );
    319                
    320                 // Probably the document end is reached, we need a marker node. 
    321                 if ( !lastNode )
    322                 {
    323                                 lastNode = document.createText( '' );
    324                                 lastNode.insertAfter( range.endContainer );
    325                 }
    326                 // The detection algorithm below skips the contents inside bookmark nodes, so
    327                 // we'll need to make sure lastNode isn't the   inside a bookmark node.
    328                 var lastParent = lastNode.getParent();
    329                 if ( lastParent && lastParent.getAttribute( '_fck_bookmark' ) )
    330                         lastNode = lastParent;
    331 
    332                 if ( lastNode.equals( firstNode ) )
     318                // Walking along the nodes inside current range.
     319                var walker = new CKEDITOR.dom.walker( range ),
     320                        currentNode,
     321                        // Whether pending the current node for apply style later.
     322                        applyStyle,
     323                        styleRange,
     324                        // Indicates that that some useful inline content has been found, so
     325                        // the style should be applied.
     326                        hasContents;
     327                do
    333328                {
    334                         // If the last node is the same as the the first one, we must move
    335                         // it to the next one, otherwise the first one will not be
    336                         // processed.
    337                         lastNode = lastNode.getNextSourceNode( true );
    338 
    339                         // It may happen that there are no more nodes after it (the end of
    340                         // the document), so we must add something there to make our code
    341                         // simpler.
    342                         if ( !lastNode )
     329                        currentNode = walker.next();
     330                        if ( currentNode )
    343331                        {
    344                                 lastNode = document.createText( '' );
    345                                 lastNode.insertAfter( firstNode );
    346                         }
    347                 }
    348 
    349                 var currentNode = firstNode;
    350 
    351                 var styleRange;
    352 
    353                 // Indicates that that some useful inline content has been found, so
    354                 // the style should be applied.
    355                 var hasContents;
    356 
    357                 while ( currentNode )
    358                 {
    359                         var applyStyle = false;
    360 
    361                         if ( currentNode.equals( lastNode ) )
    362                         {
    363                                 currentNode = null;
    364                                 applyStyle = true;
    365                         }
    366                         else
    367                         {
    368                                 var nodeType = currentNode.type;
    369                                 var nodeName = nodeType == CKEDITOR.NODE_ELEMENT ? currentNode.getName() : null;
    370 
     332                                applyStyle = false;
     333                                var nodeType = currentNode.type,
     334                                        nodeName = (
     335                                                nodeType == CKEDITOR.NODE_ELEMENT ?
     336                                                currentNode.getName() : null );
     337       
     338                                // Ignore bookmark nodes.
    371339                                if ( nodeName && currentNode.getAttribute( '_fck_bookmark' ) )
    372                                 {
    373                                         currentNode = currentNode.getNextSourceNode( true );
    374340                                        continue;
    375                                 }
    376 
     341       
    377342                                // Check if the current node can be a child of the style element.
    378                                 if ( !nodeName || ( dtd[ nodeName ] && ( currentNode.getPosition( lastNode ) | CKEDITOR.POSITION_PRECEDING | CKEDITOR.POSITION_IDENTICAL | CKEDITOR.POSITION_IS_CONTAINED ) == ( CKEDITOR.POSITION_PRECEDING + CKEDITOR.POSITION_IDENTICAL + CKEDITOR.POSITION_IS_CONTAINED ) ) )
     343                                if ( !nodeName || ( dtd[ nodeName ] ) )
    379344                                {
    380345                                        var currentParent = currentNode.getParent();
    381 
     346       
    382347                                        // Check if the style element can be a child of the current
    383348                                        // node parent or if the element is not defined in the DTD.
    384                                         if ( currentParent && ( ( currentParent.getDtd() || CKEDITOR.dtd.span )[ elementName ] || isUnknownElement ) )
     349                                        if ( currentParent &&
     350                                                 ( ( currentParent.getDtd()
     351                                                                || CKEDITOR.dtd.span )[ elementName ]
     352                                                        || isUnknownElement ) )
    385353                                        {
    386354                                                // This node will be part of our range, so if it has not
    387355                                                // been started, place its start right before the node.
     
    387355                                                // been started, place its start right before the node.
    388356                                                // In the case of an element node, it will be included
    389357                                                // only if it is entirely inside the range.
    390                                                 if ( !styleRange && ( !nodeName || !CKEDITOR.dtd.$removeEmpty[ nodeName ] || ( currentNode.getPosition( lastNode ) | CKEDITOR.POSITION_PRECEDING | CKEDITOR.POSITION_IDENTICAL | CKEDITOR.POSITION_IS_CONTAINED ) == ( CKEDITOR.POSITION_PRECEDING + CKEDITOR.POSITION_IDENTICAL + CKEDITOR.POSITION_IS_CONTAINED ) ) )
     358                                                if ( !styleRange
     359                                                        && ( !nodeName
     360                                                                        || !CKEDITOR.dtd.$removeEmpty[ nodeName ] ) )
    391361                                                {
    392362                                                        styleRange = new CKEDITOR.dom.range( document );
    393363                                                        styleRange.setStartBefore( currentNode );
     
    392362                                                        styleRange = new CKEDITOR.dom.range( document );
    393363                                                        styleRange.setStartBefore( currentNode );
    394364                                                }
    395 
     365       
    396366                                                // Non element nodes, or empty elements can be added
    397367                                                // completely to the range.
    398                                                 if ( nodeType == CKEDITOR.NODE_TEXT || ( nodeType == CKEDITOR.NODE_ELEMENT && !currentNode.getChildCount() ) )
     368                                                if ( nodeType == CKEDITOR.NODE_TEXT
     369                                                        || ( nodeType == CKEDITOR.NODE_ELEMENT
     370                                                                        && !currentNode.getChildCount() ) )
    399371                                                {
    400372                                                        var includedNode = currentNode;
    401373                                                        var parentNode;
    402 
     374       
    403375                                                        // This node is about to be included completelly, but,
    404376                                                        // if this is the last node in its parent, we must also
    405377                                                        // check if the parent itself can be added completelly
     
    405377                                                        // check if the parent itself can be added completelly
    406378                                                        // to the range.
    407379                                                        while ( !includedNode.$.nextSibling
    408                                                                 && ( parentNode = includedNode.getParent(), dtd[ parentNode.getName() ] )
    409                                                                 && ( parentNode.getPosition( firstNode ) | CKEDITOR.POSITION_FOLLOWING | CKEDITOR.POSITION_IDENTICAL | CKEDITOR.POSITION_IS_CONTAINED ) == ( CKEDITOR.POSITION_FOLLOWING + CKEDITOR.POSITION_IDENTICAL + CKEDITOR.POSITION_IS_CONTAINED ) )
    410                                                         {
     380                                                                                && ( parentNode = includedNode.getParent(),
     381                                                                                  dtd[ parentNode.getName() ] )
     382                                                                                && parentNode.within( range )  )
    411383                                                                includedNode = parentNode;
    412                                                         }
    413 
     384       
    414385                                                        styleRange.setEndAfter( includedNode );
    415 
     386       
    416387                                                        // If the included node still is the last node in its
    417388                                                        // parent, it means that the parent can't be included
    418389                                                        // in this style DTD, so apply the style immediately.
     
    418389                                                        // in this style DTD, so apply the style immediately.
    419390                                                        if ( !includedNode.$.nextSibling )
    420391                                                                applyStyle = true;
    421 
     392       
    422393                                                        if ( !hasContents )
    423394                                                                hasContents = ( nodeType != CKEDITOR.NODE_TEXT || (/[^\s\ufeff]/).test( currentNode.getText() ) );
    424395                                                }
     
    428399                                }
    429400                                else
    430401                                        applyStyle = true;
    431 
    432                                 // Get the next node to be processed.
    433                                 currentNode = currentNode.getNextSourceNode();
     402                               
    434403                        }
    435 
    436                         // Apply the style if we have something to which apply it.
     404                        else
     405                                applyStyle = true;
     406                       
     407                        // Apply the style to the inner sub ranges.
    437408                        if ( applyStyle && hasContents && styleRange && !styleRange.collapsed )
    438409                        {
    439                                 // Build the style element, based on the style object definition.
    440                                 var styleNode = getElement( this, document );
    441 
    442                                 // Get the element that holds the entire range.
    443                                 var parent = styleRange.getCommonAncestor();
    444 
    445                                 // Loop through the parents, removing the redundant attributes
    446                                 // from the element to be applied.
    447                                 while ( styleNode && parent )
    448                                 {
    449                                         if ( parent.getName() == elementName )
     410                                        // Build the style element, based on the style object definition.
     411                                        var styleNode = getElement( this, document );
     412       
     413                                        // Get the element that holds the entire range.
     414                                        var parent = styleRange.getCommonAncestor();
     415       
     416                                        // Loop through the parents, removing the redundant attributes
     417                                        // from the element to be applied.
     418                                        while ( styleNode && parent )
    450419                                        {
    451                                                 for ( var attName in def.attribs )
     420                                                if ( parent.getName() == elementName )
    452421                                                {
    453                                                         if ( styleNode.getAttribute( attName ) == parent.getAttribute( attName ) )
    454                                                                 styleNode.removeAttribute( attName );
     422                                                        for ( var attName in def.attribs )
     423                                                        {
     424                                                                if ( styleNode.getAttribute( attName ) == parent.getAttribute( attName ) )
     425                                                                        styleNode.removeAttribute( attName );
     426                                                        }
     427       
     428                                                        for ( var styleName in def.styles )
     429                                                        {
     430                                                                if ( styleNode.getStyle( styleName ) == parent.getStyle( styleName ) )
     431                                                                        styleNode.removeStyle( styleName );
     432                                                        }
     433       
     434                                                        if ( !styleNode.hasAttributes() )
     435                                                        {
     436                                                                styleNode = null;
     437                                                                break;
     438                                                        }
    455439                                                }
    456 
    457                                                 for ( var styleName in def.styles )
    458                                                 {
    459                                                         if ( styleNode.getStyle( styleName ) == parent.getStyle( styleName ) )
    460                                                                 styleNode.removeStyle( styleName );
    461                                                 }
    462 
    463                                                 if ( !styleNode.hasAttributes() )
    464                                                 {
    465                                                         styleNode = null;
    466                                                         break;
    467                                                 }
     440       
     441                                                parent = parent.getParent();
     442                                        }
     443       
     444                                        if ( styleNode )
     445                                        {
     446                                                // Move the contents of the range to the style element.
     447                                                styleRange.extractContents().appendTo( styleNode );
     448       
     449                                                // Here we do some cleanup, removing all duplicated
     450                                                // elements from the style element.
     451                                                removeFromInsideElement( this, styleNode );
     452       
     453                                                // Insert it into the range position (it is collapsed after
     454                                                // extractContents.
     455                                                styleRange.insertNode( styleNode );
     456       
     457                                                // Let's merge our new style with its neighbors, if possible.
     458                                                mergeSiblings( styleNode );
     459       
     460                                                // As the style system breaks text nodes constantly, let's normalize
     461                                                // things for performance.
     462                                                // With IE, some paragraphs get broken when calling normalize()
     463                                                // repeatedly. Also, for IE, we must normalize body, not documentElement.
     464                                                // IE is also known for having a "crash effect" with normalize().
     465                                                // We should try to normalize with IE too in some way, somewhere.
     466                                                if ( !CKEDITOR.env.ie )
     467                                                        styleNode.$.normalize();
    468468                                        }
    469 
    470                                         parent = parent.getParent();
    471                                 }
    472 
    473                                 if ( styleNode )
    474                                 {
    475                                         // Move the contents of the range to the style element.
    476                                         styleRange.extractContents().appendTo( styleNode );
    477 
    478                                         // Here we do some cleanup, removing all duplicated
    479                                         // elements from the style element.
    480                                         removeFromInsideElement( this, styleNode );
    481 
    482                                         // Insert it into the range position (it is collapsed after
    483                                         // extractContents.
    484                                         styleRange.insertNode( styleNode );
    485 
    486                                         // Let's merge our new style with its neighbors, if possible.
    487                                         mergeSiblings( styleNode );
    488 
    489                                         // As the style system breaks text nodes constantly, let's normalize
    490                                         // things for performance.
    491                                         // With IE, some paragraphs get broken when calling normalize()
    492                                         // repeatedly. Also, for IE, we must normalize body, not documentElement.
    493                                         // IE is also known for having a "crash effect" with normalize().
    494                                         // We should try to normalize with IE too in some way, somewhere.
    495                                         if ( !CKEDITOR.env.ie )
    496                                                 styleNode.$.normalize();
     469       
     470                                        // Style applied, let's release the range, so it gets
     471                                        // re-initialization in the next loop.
     472                                        styleRange = null;
    497473                                }
    498 
    499                                 // Style applied, let's release the range, so it gets
    500                                 // re-initialization in the next loop.
    501                                 styleRange = null;
    502                         }
     474                                       
    503475                }
    504476
    505 //              this._FixBookmarkStart( startNode );
    506 
     477                while ( currentNode )
    507478                range.moveToBookmark( bookmark );
    508479        }
    509480
© 2003 – 2019 CKSource – Frederico Knabben. All rights reserved. | Terms of use | Privacy policy