X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;ds=sidebyside;f=_source%2Fplugins%2Fstyles%2Fplugin.js;h=65a36c21fa386c333a14bbc6cf91d4a0ae9a017a;hb=e7789c1ad838194d45eeee6ac2eb6e55f5cf35a1;hp=85cda5f84d5f179e24267e614ab3edd6b5536604;hpb=059b4c2fef02528bf1af189f7996e80652faddfb;p=ckeditor.git diff --git a/_source/plugins/styles/plugin.js b/_source/plugins/styles/plugin.js index 85cda5f..65a36c2 100644 --- a/_source/plugins/styles/plugin.js +++ b/_source/plugins/styles/plugin.js @@ -78,7 +78,7 @@ CKEDITOR.STYLE_OBJECT = 3; (function() { var blockElements = { address:1,div:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,p:1,pre:1 }; - var objectElements = { a:1,embed:1,hr:1,img:1,li:1,object:1,ol:1,table:1,td:1,tr:1,ul:1 }; + var objectElements = { a:1,embed:1,hr:1,img:1,li:1,object:1,ol:1,table:1,td:1,tr:1,th:1,ul:1,dl:1,dt:1,dd:1,form:1}; var semicolonFixRegex = /\s*(?:;\s*|$)/; @@ -127,6 +127,8 @@ CKEDITOR.STYLE_OBJECT = 3; applyInlineStyle : this.type == CKEDITOR.STYLE_BLOCK ? applyBlockStyle + : this.type == CKEDITOR.STYLE_OBJECT ? + applyObjectStyle : null ).call( this, range ); }, @@ -154,17 +156,23 @@ CKEDITOR.STYLE_OBJECT = 3; case CKEDITOR.STYLE_BLOCK : return this.checkElementRemovable( elementPath.block || elementPath.blockLimit, true ); + case CKEDITOR.STYLE_OBJECT : case CKEDITOR.STYLE_INLINE : var elements = elementPath.elements; for ( var i = 0, element ; i < elements.length ; i++ ) { - element = elements[i]; + element = elements[ i ]; - if ( element == elementPath.block || element == elementPath.blockLimit ) + if ( this.type == CKEDITOR.STYLE_INLINE + && ( element == elementPath.block || element == elementPath.blockLimit ) ) continue; + if( this.type == CKEDITOR.STYLE_OBJECT + && !( element.getName() in objectElements ) ) + continue; + if ( this.checkElementRemovable( element, true ) ) return true; } @@ -172,6 +180,21 @@ CKEDITOR.STYLE_OBJECT = 3; return false; }, + checkApplicable : function( elementPath ) + { + switch ( this.type ) + { + case CKEDITOR.STYLE_INLINE : + case CKEDITOR.STYLE_BLOCK : + break; + + case CKEDITOR.STYLE_OBJECT : + return elementPath.lastElement.getAscendant( this.element, true ); + } + + return true; + }, + // Checks if an element, or any of its attributes, is removable by the // current style definition. checkElementRemovable : function( element, fullMatch ) @@ -199,9 +222,9 @@ CKEDITOR.STYLE_OBJECT = 3; continue; var elementAttr = element.getAttribute( attName ) || ''; - if ( attribs[ attName ] == - ( attName == 'style' ? - normalizeCssText( elementAttr, false ) : elementAttr ) ) + if ( attName == 'style' ? + compareCssText( attribs[ attName ], normalizeCssText( elementAttr, false ) ) + : attribs[ attName ] == elementAttr ) { if ( !fullMatch ) return true; @@ -246,6 +269,39 @@ CKEDITOR.STYLE_OBJECT = 3; } } return false; + }, + + // Builds the preview HTML based on the styles definition. + buildPreview : function() + { + var styleDefinition = this._.definition, + html = [], + elementName = styleDefinition.element; + + // Avoid in the preview. + if ( elementName == 'bdo' ) + elementName = 'span'; + + html = [ '<', elementName ]; + + // Assign all defined attributes. + var attribs = styleDefinition.attributes; + if ( attribs ) + { + for ( var att in attribs ) + { + html.push( ' ', att, '="', attribs[ att ], '"' ); + } + } + + // Assign the style attribute. + var cssStyle = CKEDITOR.style.getStyleText( styleDefinition ); + if ( cssStyle ) + html.push( ' style="', cssStyle, '"' ); + + html.push( '>', styleDefinition.name, '' ); + + return html.join( '' ); } }; @@ -260,20 +316,31 @@ CKEDITOR.STYLE_OBJECT = 3; stylesDef = styleDefinition.styles; // Builds the StyleText. - - var stylesText = ( styleDefinition.attributes && styleDefinition.attributes[ 'style' ] ) || ''; + var stylesText = ( styleDefinition.attributes && styleDefinition.attributes[ 'style' ] ) || '', + specialStylesText = ''; if ( stylesText.length ) stylesText = stylesText.replace( semicolonFixRegex, ';' ); for ( var style in stylesDef ) - stylesText += ( style + ':' + stylesDef[ style ] ).replace( semicolonFixRegex, ';' ); + { + var styleVal = stylesDef[ style ], + text = ( style + ':' + styleVal ).replace( semicolonFixRegex, ';' ); + + // Some browsers don't support 'inherit' property value, leave them intact. (#5242) + if ( styleVal == 'inherit' ) + specialStylesText += text; + else + stylesText += text; + } // Browsers make some changes to the style when applying them. So, here // we normalize it to the browser format. if ( stylesText.length ) stylesText = normalizeCssText( stylesText ); + stylesText += specialStylesText; + // Return it, saving it to the next request. return ( styleDefinition._ST = stylesText ); }; @@ -350,10 +417,6 @@ CKEDITOR.STYLE_OBJECT = 3; var styleRange; - // Indicates that that some useful inline content has been found, so - // the style should be applied. - var hasContents; - while ( currentNode ) { var applyStyle = false; @@ -424,8 +487,6 @@ CKEDITOR.STYLE_OBJECT = 3; if ( !includedNode.$.nextSibling ) applyStyle = true; - if ( !hasContents ) - hasContents = ( nodeType != CKEDITOR.NODE_TEXT || (/[^\s\ufeff]/).test( currentNode.getText() ) ); } } else @@ -439,7 +500,7 @@ CKEDITOR.STYLE_OBJECT = 3; } // Apply the style if we have something to which apply it. - if ( applyStyle && hasContents && styleRange && !styleRange.collapsed ) + if ( applyStyle && styleRange && !styleRange.collapsed ) { // Build the style element, based on the style object definition. var styleNode = getElement( this, document ); @@ -510,6 +571,8 @@ CKEDITOR.STYLE_OBJECT = 3; // Remove the temporary marking node.(#4111) marker && marker.remove(); range.moveToBookmark( bookmark ); + // Minimize the result range to exclude empty text nodes. (#5374) + range.shrink( CKEDITOR.SHRINK_TEXT ); } function removeInlineStyle( range ) @@ -674,6 +737,13 @@ CKEDITOR.STYLE_OBJECT = 3; range.moveToBookmark( bookmark ); } + function applyObjectStyle( range ) + { + var root = range.getCommonAncestor( true, true ), + element = root.getAscendant( this.element, true ); + element && setupElement( element, this ); + } + function applyBlockStyle( range ) { // Serializible bookmarks is needed here since @@ -772,7 +842,7 @@ CKEDITOR.STYLE_OBJECT = 3; } ); var pres = []; - splitedHtml.replace( /
([\s\S]*?)<\/pre>/gi, function( match, preContent ){
+		splitedHtml.replace( /([\s\S]*?)<\/pre>/gi, function( match, preContent ){
 			pres.push( preContent );
 		} );
 		return pres;
@@ -873,31 +943,34 @@ CKEDITOR.STYLE_OBJECT = 3;
 	function removeFromElement( style, element )
 	{
 		var def = style._.definition,
-			attributes = def.attributes,
+			attributes = CKEDITOR.tools.extend( {}, def.attributes, getOverrides( style )[ element.getName() ] ),
 			styles = def.styles,
-			overrides = getOverrides( style );
+			// If the style is only about the element itself, we have to remove the element.
+			removeEmpty = CKEDITOR.tools.isEmpty( attributes ) && CKEDITOR.tools.isEmpty( styles );
 
-		function removeAttrs()
+		// Remove definition attributes/style from the elemnt.
+		for ( var attName in attributes )
 		{
-			for ( var attName in attributes )
-			{
-				// The 'class' element value must match (#1318).
-				if ( attName == 'class' && element.getAttribute( attName ) != attributes[ attName ] )
-					continue;
-				element.removeAttribute( attName );
-			}
+			// The 'class' element value must match (#1318).
+			if ( ( attName == 'class' || style._.definition.fullMatch )
+				&& element.getAttribute( attName ) != normalizeProperty( attName, attributes[ attName ] ) )
+				continue;
+			removeEmpty = element.hasAttribute( attName );
+			element.removeAttribute( attName );
 		}
 
-		// Remove definition attributes/style from the elemnt.
-		removeAttrs();
 		for ( var styleName in styles )
+		{
+			// Full match style insist on having fully equivalence. (#5018)
+			if ( style._.definition.fullMatch
+				&& element.getStyle( styleName ) != normalizeProperty( styleName, styles[ styleName ], true ) )
+				continue;
+
+			removeEmpty = removeEmpty || !!element.getStyle( styleName );
 			element.removeStyle( styleName );
+		}
 
-		// Now remove override styles on the element.
-		attributes = overrides[ element.getName() ];
-		if ( attributes )
-			removeAttrs();
-		removeNoAttribsElement( element );
+		removeEmpty && removeNoAttribsElement( element );
 	}
 
 	// Removes a style from inside an element.
@@ -1187,6 +1260,13 @@ CKEDITOR.STYLE_OBJECT = 3;
 		return overrides;
 	}
 
+	function normalizeProperty( name, value, isStyle )
+	{
+		var temp = new CKEDITOR.dom.element( 'span' );
+		temp [ isStyle ? 'setStyle' : 'setAttribute' ]( name, value );
+		return temp[ isStyle ? 'getStyle' : 'getAttribute' ]( name );
+	}
+
 	function normalizeCssText( unparsedCssText, nativeNormalize )
 	{
 		var styleText;
@@ -1209,6 +1289,38 @@ CKEDITOR.STYLE_OBJECT = 3;
 							 .toLowerCase();
 	}
 
+	// Turn inline style text properties into one hash.
+	function parseStyleText( styleText )
+	{
+		var retval = {};
+		styleText
+		   .replace( /"/g, '"' )
+		   .replace( /\s*([^ :;]+)\s*:\s*([^;]+)\s*(?=;|$)/g, function( match, name, value )
+		{
+			retval[ name ] = value;
+		} );
+		return retval;
+	}
+
+	function compareCssText( source, target )
+	{
+		typeof source == 'string' && ( source = parseStyleText( source ) );
+		typeof target == 'string' && ( target = parseStyleText( target ) );
+		for( var name in source )
+		{
+			// Value 'inherit'  is treated as a wildcard,
+			// which will match any value.
+			if ( !( name in target &&
+					( target[ name ] == source[ name ]
+						|| source[ name ] == 'inherit'
+						|| target[ name ] == 'inherit' ) ) )
+			{
+				return false;
+			}
+		}
+		return true;
+	}
+
 	function applyStyle( document, remove )
 	{
 		// Get all ranges from the selection.
@@ -1256,3 +1368,75 @@ CKEDITOR.loadStylesSet = function( name, url, callback )
 		CKEDITOR.stylesSet.addExternal( name, url, '' );
 		CKEDITOR.stylesSet.load( name, callback );
 	};
+
+
+/**
+ * Gets the current styleSet for this instance
+ * @param {Function} The function to be called with the styles data.
+ * @example
+ * editor.getStylesSet( function( stylesDefinitions ) {} );
+ */
+CKEDITOR.editor.prototype.getStylesSet = function( callback )
+{
+	if ( !this._.stylesDefinitions )
+	{
+		var editor = this,
+			// Respect the backwards compatible definition entry
+			configStyleSet = editor.config.stylesCombo_stylesSet || editor.config.stylesSet || 'default';
+
+		// #5352 Allow to define the styles directly in the config object
+		if ( configStyleSet instanceof Array )
+		{
+			editor._.stylesDefinitions = configStyleSet;
+			callback( configStyleSet );
+			return;
+		}
+
+		var	partsStylesSet = configStyleSet.split( ':' ),
+			styleSetName = partsStylesSet[ 0 ],
+			externalPath = partsStylesSet[ 1 ],
+			pluginPath = CKEDITOR.plugins.registered.styles.path;
+
+		CKEDITOR.stylesSet.addExternal( styleSetName,
+				externalPath ?
+					partsStylesSet.slice( 1 ).join( ':' ) :
+					pluginPath + 'styles/' + styleSetName + '.js', '' );
+
+		CKEDITOR.stylesSet.load( styleSetName, function( stylesSet )
+			{
+				editor._.stylesDefinitions = stylesSet[ styleSetName ];
+				callback( editor._.stylesDefinitions );
+			} ) ;
+	}
+	else
+		callback( this._.stylesDefinitions );
+};
+
+/**
+ * The "styles definition set" to use in the editor. They will be used in the
+ * styles combo and the Style selector of the div container. 
+ * The styles may be defined in the page containing the editor, or can be + * loaded on demand from an external file. In the second case, if this setting + * contains only a name, the styles definition file will be loaded from the + * "styles" folder inside the styles plugin folder. + * Otherwise, this setting has the "name:url" syntax, making it + * possible to set the URL from which loading the styles file.
+ * Previously this setting was available as config.stylesCombo_stylesSet
+ * @type String|Array + * @default 'default' + * @since 3.3 + * @example + * // Load from the styles' styles folder (mystyles.js file). + * config.stylesSet = 'mystyles'; + * @example + * // Load from a relative URL. + * config.stylesSet = 'mystyles:/editorstyles/styles.js'; + * @example + * // Load from a full URL. + * config.stylesSet = 'mystyles:http://www.example.com/editorstyles/styles.js'; + * @example + * // Load from a list of definitions. + * config.stylesSet = [ + * { name : 'Strong Emphasis', element : 'strong' }, + * { name : 'Emphasis', element : 'em' }, ... ]; + */