if ( applyStyle && styleRange && !styleRange.collapsed )\r
{\r
// Build the style element, based on the style object definition.\r
- var styleNode = getElement( this, document );\r
+ var styleNode = getElement( this, document ),\r
+ styleHasAttrs = styleNode.hasAttributes();\r
\r
// Get the element that holds the entire range.\r
var parent = styleRange.getCommonAncestor();\r
\r
+ var removeList = {\r
+ styles : {},\r
+ attrs : {},\r
+ // Styles cannot be removed.\r
+ blockedStyles : {},\r
+ // Attrs cannot be removed.\r
+ blockedAttrs : {}\r
+ };\r
+\r
+ var attName, styleName, value;\r
+\r
// Loop through the parents, removing the redundant attributes\r
// from the element to be applied.\r
while ( styleNode && parent )\r
{\r
if ( parent.getName() == elementName )\r
{\r
- for ( var attName in def.attributes )\r
+ for ( attName in def.attributes )\r
{\r
- if ( styleNode.getAttribute( attName ) == parent.getAttribute( attName ) )\r
- styleNode.removeAttribute( attName );\r
- }\r
+ if ( removeList.blockedAttrs[ attName ] || !( value = parent.getAttribute( styleName ) ) )\r
+ continue;\r
\r
- for ( var styleName in def.styles )\r
- {\r
- if ( styleNode.getStyle( styleName ) == parent.getStyle( styleName ) )\r
- styleNode.removeStyle( styleName );\r
+ if ( styleNode.getAttribute( attName ) == value )\r
+ removeList.attrs[ attName ] = 1;\r
+ else\r
+ removeList.blockedAttrs[ attName ] = 1;\r
}\r
\r
- if ( !styleNode.hasAttributes() )\r
+ for ( styleName in def.styles )\r
{\r
- styleNode = null;\r
- break;\r
+ if ( removeList.blockedStyles[ styleName ] || !( value = parent.getStyle( styleName ) ) )\r
+ continue;\r
+\r
+ if ( styleNode.getStyle( styleName ) == value )\r
+ removeList.styles[ styleName ] = 1;\r
+ else\r
+ removeList.blockedStyles[ styleName ] = 1;\r
}\r
}\r
\r
parent = parent.getParent();\r
}\r
\r
+ for ( attName in removeList.attrs )\r
+ styleNode.removeAttribute( attName );\r
+\r
+ for ( styleName in removeList.styles )\r
+ styleNode.removeStyle( styleName );\r
+\r
+ if ( styleHasAttrs && !styleNode.hasAttributes() )\r
+ styleNode = null;\r
+\r
if ( styleNode )\r
{\r
// Move the contents of the range to the style element.\r
if ( !CKEDITOR.env.ie )\r
styleNode.$.normalize();\r
}\r
+ // Style already inherit from parents, left just to clear up any internal overrides. (#5931)\r
+ else\r
+ {\r
+ styleNode = new CKEDITOR.dom.element( 'span' );\r
+ styleRange.extractContents().appendTo( styleNode );\r
+ styleRange.insertNode( styleNode );\r
+ removeFromInsideElement( this, styleNode );\r
+ styleNode.remove( true );\r
+ }\r
\r
// Style applied, let's release the range, so it gets\r
// re-initialization in the next loop.\r
\r
while ( ( block = iterator.getNextParagraph() ) ) // Only one =\r
{\r
- var newBlock = getElement( this, doc );\r
+ var newBlock = getElement( this, doc, block );\r
replaceBlock( block, newBlock );\r
}\r
\r
}\r
}\r
\r
- function getElement( style, targetDocument )\r
+ function getElement( style, targetDocument, element )\r
{\r
var el;\r
\r
// Create the element.\r
el = new CKEDITOR.dom.element( elementName, targetDocument );\r
\r
+ // #6226: attributes should be copied before the new ones are applied\r
+ if ( element )\r
+ element.copyAttributes( el );\r
+\r
return setupElement( el, style );\r
}\r
\r
}\r
\r
// Assign all defined styles.\r
- if ( def.styles )\r
- {\r
- for ( var i in def.styles )\r
- {\r
- if ( !def.styles.hasOwnProperty( i ) )\r
- continue;\r
-\r
- el.setStyle( i, def.styles[ i ] );\r
- }\r
- }\r
+ if( styles )\r
+ el.setAttribute( 'style', styles );\r
\r
return el;\r
}\r
// Compensate tail semi-colon.\r
return styleText.replace( /\s*([;:])\s*/, '$1' )\r
.replace( /([^\s;])$/, '$1;')\r
- .replace( /,\s+/g, ',' ) // Trimming spaces after comma (e.g. font-family name)(#4107).\r
+ // Trimming spaces after comma(#4107),\r
+ // remove quotations(#6403),\r
+ // mostly for differences on "font-family".\r
+ .replace( /,\s+/g, ',' )\r
+ .replace( /\"/g,'' )\r
.toLowerCase();\r
}\r
\r
{\r
var selection = document.getSelection(),\r
// Bookmark the range so we can re-select it after processing.\r
- bookmarks = selection.createBookmarks(),\r
- ranges = selection.getRanges( true ),\r
+ bookmarks = selection.createBookmarks( 1 ),\r
+ ranges = selection.getRanges( 1 ),\r
func = remove ? this.removeFromRange : this.applyToRange,\r
range;\r
\r
if ( bookmarks.length == 1 && bookmarks[0].collapsed )\r
{\r
selection.selectRanges( ranges );\r
- bookmarks[0].startNode.remove();\r
+ document.getById( bookmarks[ 0 ].startNode ).remove();\r
}\r
else\r
selection.selectBookmarks( bookmarks );\r