Ticket #2768: 2768_4.patch
File 2768_4.patch, 6.5 KB (added by , 16 years ago) |
---|
-
_source/plugins/styles/plugin.js
98 98 }; 99 99 }; 100 100 101 var applyStyle = function( document, remove ) 102 { 103 // Get all ranges from the selection. 104 var selection = document.getSelection(); 105 var ranges = selection.getRanges(); 106 var func = remove ? this.removeFromRange : this.applyToRange; 107 108 // Apply the style to the ranges. 109 for ( var i = 0 ; i < ranges.length ; i++ ) 110 func.call( this, ranges[ i ] ); 111 112 // Select the ranges again. 113 selection.selectRanges( ranges ); 114 }; 115 101 116 CKEDITOR.style.prototype = 102 117 { 103 118 apply : function( document ) 104 119 { 105 // Get all ranges from the selection. 106 var selection = document.getSelection(); 107 var ranges = selection.getRanges(); 120 applyStyle.call( this, document, false ); 121 }, 108 122 109 // Apply the style to the ranges. 110 for ( var i = 0 ; i < ranges.length ; i++ ) 111 this.applyToRange( ranges[ i ] ); 112 113 // Select the ranges again. 114 selection.selectRanges( ranges ); 123 remove : function( document ) 124 { 125 applyStyle.call( this, document, true ); 115 126 }, 116 127 117 128 applyToRange : function( range ) … … 124 135 : null ).call( this, range ); 125 136 }, 126 137 138 removeFromRange : function( range ) 139 { 140 return ( this.removeFromRange = 141 this.type == CKEDITOR.STYLE_INLINE ? 142 removeInlineStyle 143 : null ).call( this, range ); 144 }, 145 127 146 /** 128 147 * Get the style state inside an element path. Returns "true" if the 129 148 * element is active in the path. … … 359 378 360 379 // Here we do some cleanup, removing all duplicated 361 380 // elements from the style element. 362 removeFrom Element( this, styleNode );381 removeFromInsideElement( this, styleNode ); 363 382 364 383 // Insert it into the range position (it is collapsed after 365 384 // extractContents. … … 389 408 range.moveToBookmark( bookmark ); 390 409 }; 391 410 392 var applyBlockStyle = function( range )411 var removeInlineStyle = function( range ) 393 412 { 394 }; 413 /* 414 * Make sure our range has included all "collpased" parent inline nodes so 415 * that our operation logic can be simpler. 416 */ 417 range.enlarge( CKEDITOR.ENLARGE_ELEMENT ); 395 418 396 // Removes a style from inside an element. 397 var removeFromElement = function( style, element ) 398 { 399 var def = style._.definition; 400 var attribs = def.attributes; 401 var styles = def.styles; 419 var bookmark = range.createBookmark(), 420 startNode = bookmark.startNode, 421 startPath = new CKEDITOR.dom.elementPath( startNode.getParent() ); 402 422 403 var innerElements = element.getElementsByTag( style.element ); 423 if ( range.collapsed ) 424 { 425 /* 426 * If the range is collapsed, try to remove the style from all ancestor 427 * elements, until either a block boundary is reached, or the style is 428 * removed. 429 */ 430 for ( var i = 0, element ; i < startPath.elements.length && ( element = startPath.elements[i] ) ; i++ ) 431 { 432 if ( element == startPath.block || element == startPath.blockLimit ) 433 break; 404 434 405 for ( var i = innerElements.count() ; --i >= 0 ; ) 435 if ( this.checkElementRemovable( element ) ) 436 { 437 removeFromElement( this, element ); 438 break; 439 } 440 } 441 } 442 else 406 443 { 407 var innerElement = innerElements.getItem( i ); 444 /* 445 * Now our range isn't collapsed. Lets walk from the start node to the end 446 * node via DFS and remove the styles one-by-one. 447 */ 448 var endNode = bookmark.endNode, 449 endPath = new CKEDITOR.dom.elementPath( endNode.getParent() ); 450 currentNode = startNode; 408 451 409 for ( var attName in attribs ) 452 // Find out the ancestor that needs to be broken down at startNode and endNode. 453 var breakStart = null, breakEnd = null; 454 for ( var i = 0 ; i < startPath.elements.length ; i++ ) 410 455 { 411 // The 'class' element value must match (#1318).412 if ( attName == 'class' && innerElement.getAttribute( 'class' ) != attribs[ attName ] )413 continue;414 415 innerElement.removeAttribute( attName );456 if ( this.checkElementRemovable( startPath.elements[ i ] ) ) 457 { 458 breakStart = startPath.elements[ i ]; 459 break; 460 } 416 461 } 462 for ( var i = 0 ; i < endPath.elements.length ; i++ ) 463 { 464 if ( this.checkElementRemovable( endPath.elements[ i ] ) ) 465 { 466 breakEnd = endPath.elements[ i ]; 467 break; 468 } 469 } 417 470 418 for ( var styleName in styles ) 471 if ( breakEnd ) 472 endNode.breakParent( breakEnd ); 473 if ( breakStart ) 474 startNode.breakParent( breakStart ); 475 476 // Now, do the DFS walk. 477 while ( ( currentNode = currentNode.getNextSourceNode() ) && !currentNode.equals( endNode ) ) 419 478 { 420 innerElement.removeStyle( styleName ); 479 if ( currentNode.type == CKEDITOR.NODE_ELEMENT ) 480 removeFromElement( this, currentNode ); 421 481 } 482 } 483 484 range.moveToBookmark( bookmark ); 485 }; 422 486 423 removeNoAttribsElement( innerElement ); 487 var applyBlockStyle = function( range ) 488 { 489 }; 490 491 // Removes a style from an element itself, don't care about its subtree. 492 var removeFromElement = function( style, element ) 493 { 494 var def = style._.definition, 495 attributes = def.attributes, 496 styles = def.styles; 497 498 for ( var attName in attributes ) 499 { 500 // The 'class' element value must match (#1318). 501 if ( attName == 'class' && element.getAttribute( attName ) != attributes[ attName ] ) 502 continue; 503 element.removeAttribute( attName ); 424 504 } 505 506 for ( var styleName in styles ) 507 element.removeStyle( styleName ); 508 509 removeNoAttribsElement( element ); 425 510 }; 426 511 512 // Removes a style from inside an element. 513 var removeFromInsideElement = function( style, element ) 514 { 515 var def = style._.definition; 516 var attribs = def.attributes; 517 var styles = def.styles; 518 519 var innerElements = element.getElementsByTag( style.element ); 520 521 for ( var i = innerElements.count() ; --i >= 0 ; ) 522 removeFromElement( style, innerElements.getItem( i ) ); 523 }; 524 427 525 // If the element has no more attributes, remove it. 428 526 var removeNoAttribsElement = function( element ) 429 527 { … … 596 694 var doc = editor.document; 597 695 598 696 if ( doc ) 599 this.style.apply( doc ); 697 { 698 if ( this.state == CKEDITOR.TRISTATE_OFF ) 699 this.style.apply( doc ); 700 else if ( this.state == CKEDITOR.TRISTATE_ON ) 701 this.style.remove( doc ); 702 } 600 703 601 704 return !!doc; 602 705 };