Ticket #3478: 3478.patch
File 3478.patch, 13.5 KB (added by , 14 years ago) |
---|
-
_source/core/dom/node.js
602 602 child.parentNode.removeChild( child ) ; 603 603 } 604 604 } 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; 605 622 } 606 623 } 607 624 ); -
_source/plugins/styles/plugin.js
257 257 258 258 // Builds the StyleText. 259 259 260 var stylesText = ( styleDefinition.attributes && styleDefinition.attributes[ 'style' ] ) || ''; 260 var stylesText = 261 ( styleDefinition.attributes 262 && styleDefinition.attributes[ 'style' ] ) || ''; 261 263 262 264 if ( stylesText.length ) 263 265 stylesText = stylesText.replace( semicolonFixRegex, ';' ); … … 292 294 range.insertNode( collapsedElement ); 293 295 294 296 // 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 ); 296 299 297 300 return; 298 301 } … … 302 305 var isUnknownElement; 303 306 304 307 // 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 ); 306 310 307 311 // Bookmark the range so we can re-select it after processing. 308 312 var bookmark = range.createBookmark(); … … 311 315 range.enlarge( CKEDITOR.ENLARGE_ELEMENT ); 312 316 range.trim(); 313 317 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 333 328 { 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 ) 343 331 { 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. 371 339 if ( nodeName && currentNode.getAttribute( '_fck_bookmark' ) ) 372 {373 currentNode = currentNode.getNextSourceNode( true );374 340 continue; 375 } 376 341 377 342 // 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 ] ) ) 379 344 { 380 345 var currentParent = currentNode.getParent(); 381 346 382 347 // Check if the style element can be a child of the current 383 348 // 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 ) ) 385 353 { 386 354 // This node will be part of our range, so if it has not 387 355 // been started, place its start right before the node. … … 387 355 // been started, place its start right before the node. 388 356 // In the case of an element node, it will be included 389 357 // 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 ] ) ) 391 361 { 392 362 styleRange = new CKEDITOR.dom.range( document ); 393 363 styleRange.setStartBefore( currentNode ); … … 392 362 styleRange = new CKEDITOR.dom.range( document ); 393 363 styleRange.setStartBefore( currentNode ); 394 364 } 395 365 396 366 // Non element nodes, or empty elements can be added 397 367 // 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() ) ) 399 371 { 400 372 var includedNode = currentNode; 401 373 var parentNode; 402 374 403 375 // This node is about to be included completelly, but, 404 376 // if this is the last node in its parent, we must also 405 377 // check if the parent itself can be added completelly … … 405 377 // check if the parent itself can be added completelly 406 378 // to the range. 407 379 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 ) ) 411 383 includedNode = parentNode; 412 } 413 384 414 385 styleRange.setEndAfter( includedNode ); 415 386 416 387 // If the included node still is the last node in its 417 388 // parent, it means that the parent can't be included 418 389 // in this style DTD, so apply the style immediately. … … 418 389 // in this style DTD, so apply the style immediately. 419 390 if ( !includedNode.$.nextSibling ) 420 391 applyStyle = true; 421 392 422 393 if ( !hasContents ) 423 394 hasContents = ( nodeType != CKEDITOR.NODE_TEXT || (/[^\s\ufeff]/).test( currentNode.getText() ) ); 424 395 } … … 428 399 } 429 400 else 430 401 applyStyle = true; 431 432 // Get the next node to be processed. 433 currentNode = currentNode.getNextSourceNode(); 402 434 403 } 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. 437 408 if ( applyStyle && hasContents && styleRange && !styleRange.collapsed ) 438 409 { 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 ) 450 419 { 451 for ( var attName in def.attribs)420 if ( parent.getName() == elementName ) 452 421 { 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 } 455 439 } 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(); 468 468 } 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; 497 473 } 498 499 // Style applied, let's release the range, so it gets 500 // re-initialization in the next loop. 501 styleRange = null; 502 } 474 503 475 } 504 476 505 // this._FixBookmarkStart( startNode ); 506 477 while ( currentNode ) 507 478 range.moveToBookmark( bookmark ); 508 479 } 509 480