Index: _source/plugins/stylescombo/plugin.js =================================================================== --- _source/plugins/stylescombo/plugin.js (revision 5949) +++ _source/plugins/stylescombo/plugin.js (revision ) @@ -106,12 +106,7 @@ var elementPath = new CKEDITOR.dom.elementPath( selection.getStartElement() ); - if ( style.type == CKEDITOR.STYLE_INLINE && style.checkActive( elementPath ) ) - style.remove( editor.document ); - else if ( style.type == CKEDITOR.STYLE_OBJECT && style.checkActive( elementPath ) ) - style.remove( editor.document ); - else - style.apply( editor.document ); + style[ style.checkActive( elementPath ) ? 'remove' : 'apply' ]( editor.document ); editor.fire( 'saveSnapshot' ); }, Index: _source/plugins/format/plugin.js =================================================================== --- _source/plugins/format/plugin.js (revision 6318) +++ _source/plugins/format/plugin.js (revision ) @@ -54,8 +54,11 @@ editor.focus(); editor.fire( 'saveSnapshot' ); - styles[ value ].apply( editor.document ); + var style = styles[ value ], + elementPath = new CKEDITOR.dom.elementPath( editor.getSelection().getStartElement() ); + style[ style.checkActive( elementPath ) ? 'remove' : 'apply' ]( editor.document ); + // Save the undo snapshot after all changes are affected. (#4899) setTimeout( function() { Index: _source/plugins/styles/plugin.js =================================================================== --- _source/plugins/styles/plugin.js (revision 6321) +++ _source/plugins/styles/plugin.js (revision ) @@ -149,6 +149,8 @@ return ( this.removeFromRange = this.type == CKEDITOR.STYLE_INLINE ? removeInlineStyle + : this.type == CKEDITOR.STYLE_BLOCK ? + removeBlockStyle : this.type == CKEDITOR.STYLE_OBJECT ? removeObjectStyle : null ).call( this, range ); @@ -881,6 +883,23 @@ range.moveToBookmark( bookmark ); } + function removeBlockStyle( range ) + { + // Serializible bookmarks is needed here since + // elements may be merged. + var bookmark = range.createBookmark( 1 ); + + var iterator = range.createIterator(); + iterator.enforceRealBlocks = true; + iterator.enlargeBr = this._.enterMode != CKEDITOR.ENTER_BR; + + var block; + while ( ( block = iterator.getNextParagraph() ) ) + this.checkElementRemovable( block ) && removeFromElement( this, block, 1 ); + + range.moveToBookmark( bookmark ); + } + // Replace the original block with new one, with special treatment // for
blocks to make sure content format is well preserved, and merging/splitting adjacent // when necessary.(#3188) @@ -1063,7 +1082,8 @@ function removeFromElement( style, element ) { var def = style._.definition, - attributes = CKEDITOR.tools.extend( {}, def.attributes, getOverrides( style )[ element.getName() ] ), + elementName = element.getName(), + attributes = CKEDITOR.tools.extend( {}, def.attributes, getOverrides( style )[ elementName ] ), styles = def.styles, // If the style is only about the element itself, we have to remove the element. removeEmpty = CKEDITOR.tools.isEmpty( attributes ) && CKEDITOR.tools.isEmpty( styles ); @@ -1090,8 +1110,14 @@ element.removeStyle( styleName ); } - removeEmpty && removeNoAttribsElement( element ); + if ( removeEmpty ) + { + ( !CKEDITOR.dtd.$block[ elementName ] || style._.enterMode == CKEDITOR.ENTER_BR ) && !element.hasAttributes() ? + removeNoAttribsElement( element ) : + element.renameNode( elementName in CKEDITOR.dtd.$block ? + style._.enterMode == CKEDITOR.ENTER_P ? 'p' : 'div' : 'span' ); - } + } + } // Removes a style from inside an element. function removeFromInsideElement( style, element ) @@ -1160,6 +1186,7 @@ removeNoAttribsElement( element ); } + var nonWhitespaces = CKEDITOR.dom.walker.whitespaces( 1 ); // If the element has no more attributes, remove it. function removeNoAttribsElement( element ) { @@ -1167,24 +1194,40 @@ // leaving its children. if ( !element.hasAttributes() ) { + if ( CKEDITOR.dtd.$block[ element.getName() ] ) + { + var previous = element.getPrevious( nonWhitespaces ), + next = element.getNext( nonWhitespaces ); + + if ( previous && ( previous.type == CKEDITOR.NODE_TEXT || !previous.isBlockBoundary( { br : 1 } ) ) ) + element.append( 'br', 1 ); + if ( next && ( next.type == CKEDITOR.NODE_TEXT || !next.isBlockBoundary( { br : 1 } ) ) ) + element.append( 'br' ); + + element.remove( true ); + } + else + { - // Removing elements may open points where merging is possible, - // so let's cache the first and last nodes for later checking. + // Removing elements may open points where merging is possible, + // so let's cache the first and last nodes for later checking. - var firstChild = element.getFirst(); + var firstChild = element.getFirst(); - var lastChild = element.getLast(); + var lastChild = element.getLast(); - element.remove( true ); + element.remove( true ); - if ( firstChild ) - { - // Check the cached nodes for merging. - firstChild.type == CKEDITOR.NODE_ELEMENT && firstChild.mergeSiblings(); + if ( firstChild ) + { + // Check the cached nodes for merging. + firstChild.type == CKEDITOR.NODE_ELEMENT && firstChild.mergeSiblings(); - if ( lastChild && !firstChild.equals( lastChild ) + if ( lastChild && !firstChild.equals( lastChild ) - && lastChild.type == CKEDITOR.NODE_ELEMENT ) + && lastChild.type == CKEDITOR.NODE_ELEMENT ) - lastChild.mergeSiblings(); - } + lastChild.mergeSiblings(); + } + - } - } + } + } + } function getElement( style, targetDocument, element ) { @@ -1436,9 +1479,7 @@ var iterator = ranges.createIterator(); while ( ( range = iterator.getNextRange() ) ) - { func.call( this, range ); - } selection.selectRanges( ranges );