\r
// Save the current state, so it can be compared next\r
// time.\r
- callback.state !== currentState;\r
+ callback.state = currentState;\r
}\r
}\r
});\r
}\r
\r
- // Save the callback info, so it can be checked on the next occurence of\r
+ // Save the callback info, so it can be checked on the next occurrence of\r
// selectionChange.\r
styleStateChangeCallbacks.push( { style : style, fn : callback } );\r
};\r
return false;\r
},\r
\r
+ /**\r
+ * Whether this style can be applied at the element path.\r
+ * @param elementPath\r
+ */\r
checkApplicable : function( elementPath )\r
{\r
switch ( this.type )\r
continue;\r
\r
var elementAttr = element.getAttribute( attName ) || '';\r
+\r
+ // Special treatment for 'style' attribute is required.\r
if ( attName == 'style' ?\r
compareCssText( attribs[ attName ], normalizeCssText( elementAttr, false ) )\r
: attribs[ attName ] == elementAttr )\r
\r
// Get the first node to be processed and the last, which concludes the\r
// processing.\r
- var boundaryNodes = range.getBoundaryNodes();\r
- var firstNode = boundaryNodes.startNode;\r
- var lastNode = boundaryNodes.endNode.getNextSourceNode( true );\r
-\r
- // Probably the document end is reached, we need a marker node.\r
- if ( !lastNode )\r
- {\r
- var marker;\r
- lastNode = marker = document.createText( '' );\r
- lastNode.insertAfter( range.endContainer );\r
- }\r
- // The detection algorithm below skips the contents inside bookmark nodes, so\r
- // we'll need to make sure lastNode isn't the inside a bookmark node.\r
- var lastParent = lastNode.getParent();\r
- if ( lastParent && lastParent.getAttribute( '_fck_bookmark' ) )\r
- lastNode = lastParent;\r
-\r
- if ( lastNode.equals( firstNode ) )\r
- {\r
- // If the last node is the same as the the first one, we must move\r
- // it to the next one, otherwise the first one will not be\r
- // processed.\r
- lastNode = lastNode.getNextSourceNode( true );\r
-\r
- // It may happen that there are no more nodes after it (the end of\r
- // the document), so we must add something there to make our code\r
- // simpler.\r
- if ( !lastNode )\r
- {\r
- lastNode = marker = document.createText( '' );\r
- lastNode.insertAfter( firstNode );\r
- }\r
- }\r
+ var boundaryNodes = range.createBookmark(),\r
+ firstNode = boundaryNodes.startNode,\r
+ lastNode = boundaryNodes.endNode;\r
\r
var currentNode = firstNode;\r
\r
styleRange.insertNode( styleNode );\r
\r
// Let's merge our new style with its neighbors, if possible.\r
- mergeSiblings( styleNode );\r
+ styleNode.mergeSiblings();\r
\r
// As the style system breaks text nodes constantly, let's normalize\r
// things for performance.\r
}\r
}\r
\r
- // Remove the temporary marking node.(#4111)\r
- marker && marker.remove();\r
+ firstNode.remove();\r
+ lastNode.remove();\r
range.moveToBookmark( bookmark );\r
// Minimize the result range to exclude empty text nodes. (#5374)\r
range.shrink( CKEDITOR.SHRINK_TEXT );\r
* no difference that they're separate entities in the DOM tree. So, merge\r
* them before removal.\r
*/\r
- mergeSiblings( element );\r
+ element.mergeSiblings();\r
removeFromElement( this, element );\r
\r
}\r
var iterator = range.createIterator();\r
iterator.enforceRealBlocks = true;\r
\r
+ // make recognize <br /> tag as a separator in ENTER_BR mode (#5121)\r
+ if ( this._.enterMode )\r
+ iterator.enlargeBr = ( this._.enterMode != CKEDITOR.ENTER_BR );\r
+\r
var block;\r
var doc = range.document;\r
var previousPreBlock;\r
}\r
}\r
\r
+ var nonWhitespaces = CKEDITOR.dom.walker.whitespaces( true );\r
/**\r
* Merge a <pre> block with a previous sibling if available.\r
*/\r
function mergePre( preBlock )\r
{\r
var previousBlock;\r
- if ( !( ( previousBlock = preBlock.getPreviousSourceNode( true, CKEDITOR.NODE_ELEMENT ) )\r
+ if ( !( ( previousBlock = preBlock.getPrevious( nonWhitespaces ) )\r
&& previousBlock.is\r
&& previousBlock.is( 'pre') ) )\r
return;\r
if ( firstChild )\r
{\r
// Check the cached nodes for merging.\r
- mergeSiblings( firstChild );\r
+ firstChild.type == CKEDITOR.NODE_ELEMENT && firstChild.mergeSiblings();\r
\r
- if ( lastChild && !firstChild.equals( lastChild ) )\r
- mergeSiblings( lastChild );\r
- }\r
- }\r
- }\r
-\r
- function mergeSiblings( element )\r
- {\r
- if ( !element || element.type != CKEDITOR.NODE_ELEMENT || !CKEDITOR.dtd.$removeEmpty[ element.getName() ] )\r
- return;\r
-\r
- mergeElements( element, element.getNext(), true );\r
- mergeElements( element, element.getPrevious() );\r
- }\r
-\r
- function mergeElements( element, sibling, isNext )\r
- {\r
- if ( sibling && sibling.type == CKEDITOR.NODE_ELEMENT )\r
- {\r
- var hasBookmark = sibling.getAttribute( '_fck_bookmark' );\r
-\r
- if ( hasBookmark )\r
- sibling = isNext ? sibling.getNext() : sibling.getPrevious();\r
-\r
- if ( sibling && sibling.type == CKEDITOR.NODE_ELEMENT && element.isIdentical( sibling ) )\r
- {\r
- // Save the last child to be checked too, to merge things like\r
- // <b><i></i></b><b><i></i></b> => <b><i></i></b>\r
- var innerSibling = isNext ? element.getLast() : element.getFirst();\r
-\r
- if ( hasBookmark )\r
- ( isNext ? sibling.getPrevious() : sibling.getNext() ).move( element, !isNext );\r
-\r
- sibling.moveChildren( element, !isNext );\r
- sibling.remove();\r
-\r
- // Now check the last inner child (see two comments above).\r
- if ( innerSibling )\r
- mergeSiblings( innerSibling );\r
+ if ( lastChild && !firstChild.equals( lastChild )\r
+ && lastChild.type == CKEDITOR.NODE_ELEMENT )\r
+ lastChild.mergeSiblings();\r
}\r
}\r
}\r
return overrides;\r
}\r
\r
+ // Make the comparison of attribute value easier by standardizing it.\r
function normalizeProperty( name, value, isStyle )\r
{\r
var temp = new CKEDITOR.dom.element( 'span' );\r
return temp[ isStyle ? 'getStyle' : 'getAttribute' ]( name );\r
}\r
\r
+ // Make the comparison of style text easier by standardizing it.\r
function normalizeCssText( unparsedCssText, nativeNormalize )\r
{\r
var styleText;\r
return retval;\r
}\r
\r
+ /**\r
+ * Compare two bunch of styles, with the speciality that value 'inherit'\r
+ * is treated as a wildcard which will match any value.\r
+ * @param {Object|String} source\r
+ * @param {Object|String} target\r
+ */\r
function compareCssText( source, target )\r
{\r
typeof source == 'string' && ( source = parseStyleText( source ) );\r
typeof target == 'string' && ( target = parseStyleText( target ) );\r
for( var name in source )\r
{\r
- // Value 'inherit' is treated as a wildcard,\r
- // which will match any value.\r
if ( !( name in target &&\r
( target[ name ] == source[ name ]\r
|| source[ name ] == 'inherit'\r
* Otherwise, this setting has the "name:url" syntax, making it\r
* possible to set the URL from which loading the styles file.<br>\r
* Previously this setting was available as config.stylesCombo_stylesSet<br>\r
+ * @name CKEDITOR.config.stylesSet\r
* @type String|Array\r
* @default 'default'\r
* @since 3.3\r