⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fckstyle.js

📁 一个用javascript写的可视化编辑器
💻 JS
📖 第 1 页 / 共 4 页
字号:
			else
				applyStyle = true ;

			// Get the next node to be processed.
			currentNode = FCKDomTools.GetNextSourceNode( currentNode ) ;

			// If we have reached the end of the selection, just apply the
			// style ot the range, and stop looping.
			if ( currentNode == endNode )
			{
				currentNode = null ;
				applyStyle = true ;
			}

			// Apply the style if we have something to which apply it.
			if ( applyStyle && range.CheckHasRange() && !range.CheckIsCollapsed() )
			{
				// Build the style element, based on the style object definition.
				styleNode = this.BuildElement( doc ) ;

				// Move the contents of the range to the style element.
				range.ExtractContents().AppendTo( styleNode ) ;

				// If it is not empty.
				if ( styleNode.innerHTML.RTrim().length > 0 )
				{
					// Insert it in the range position (it is collapsed after
					// ExtractContents.
					range.InsertNode( styleNode ) ;

					// Here we do some cleanup, removing all duplicated
					// elements from the style element.
					this.RemoveFromElement( styleNode ) ;

					// Let's merge our new style with its neighbors, if possible.
					this._MergeSiblings( styleNode, this._GetAttribsForComparison() ) ;

					// As the style system breaks text nodes constantly, let's normalize
					// things for performance.
					// With IE, some paragraphs get broken when calling normalize()
					// repeatedly. Also, for IE, we must normalize body, not documentElement.
					// IE is also known for having a "crash effect" with normalize().
					// We should try to normalize with IE too in some way, somewhere.
					if ( !FCKBrowserInfo.IsIE )
						styleNode.normalize() ;
				}

				// Style applied, let's release the range, so it gets marked to
				// re-initialization in the next loop.
				range.Release( true ) ;
			}
		}

		this._FixBookmarkStart( startNode ) ;

		// Re-select the original range.
		if ( selectIt )
			range.SelectBookmark( bookmark ) ;

		if ( updateRange )
			range.MoveToBookmark( bookmark ) ;
	},

	_FixBookmarkStart : function( startNode )
	{
		// After appliying or removing an inline style, the start boundary of
		// the selection must be placed inside all inline elements it is
		// bordering.
		var startSibling ;
		while ( ( startSibling = startNode.nextSibling ) )	// Only one "=".
		{
			if ( startSibling.nodeType == 1
				&& FCKListsLib.InlineNonEmptyElements[ startSibling.nodeName.toLowerCase() ] )
			{
				// If it is an empty inline element, we can safely remove it.
				if ( !startSibling.firstChild )
					FCKDomTools.RemoveNode( startSibling ) ;
				else
					FCKDomTools.MoveNode( startNode, startSibling, true ) ;
				continue ;
			}

			// Empty text nodes can be safely removed to not disturb.
			if ( startSibling.nodeType == 3 && startSibling.length == 0 )
			{
				FCKDomTools.RemoveNode( startSibling ) ;
				continue ;
			}

			break ;
		}
	},

	/**
	 * Merge an element with its similar siblings.
	 * "attribs" is and object computed with _CreateAttribsForComparison.
	 */
	_MergeSiblings : function( element, attribs )
	{
		if ( !element || element.nodeType != 1 || !FCKListsLib.InlineNonEmptyElements[ element.nodeName.toLowerCase() ] )
			return ;

		this._MergeNextSibling( element, attribs ) ;
		this._MergePreviousSibling( element, attribs ) ;
	},

	/**
	 * Merge an element with its similar siblings after it.
	 * "attribs" is and object computed with _CreateAttribsForComparison.
	 */
	_MergeNextSibling : function( element, attribs )
	{
		// Check the next sibling.
		var sibling = element.nextSibling ;

		// Check if the next sibling is a bookmark element. In this case, jump it.
		var hasBookmark = ( sibling && sibling.nodeType == 1 && sibling.getAttribute( '_fck_bookmark' ) ) ;
		if ( hasBookmark )
			sibling = sibling.nextSibling ;

		if ( sibling && sibling.nodeType == 1 && sibling.nodeName == element.nodeName )
		{
			if ( !attribs )
				attribs = this._CreateElementAttribsForComparison( element ) ;

			if ( this._CheckAttributesMatch( sibling, attribs ) )
			{
				// Save the last child to be checked too (to merge things like <b><i></i></b><b><i></i></b>).
				var innerSibling = element.lastChild ;

				if ( hasBookmark )
					FCKDomTools.MoveNode( element.nextSibling, element ) ;

				// Move contents from the sibling.
				FCKDomTools.MoveChildren( sibling, element ) ;
				FCKDomTools.RemoveNode( sibling ) ;

				// Now check the last inner child (see two comments above).
				if ( innerSibling )
					this._MergeNextSibling( innerSibling ) ;
			}
		}
	},

	/**
	 * Merge an element with its similar siblings before it.
	 * "attribs" is and object computed with _CreateAttribsForComparison.
	 */
	_MergePreviousSibling : function( element, attribs )
	{
		// Check the previous sibling.
		var sibling = element.previousSibling ;

		// Check if the previous sibling is a bookmark element. In this case, jump it.
		var hasBookmark = ( sibling && sibling.nodeType == 1 && sibling.getAttribute( '_fck_bookmark' ) ) ;
		if ( hasBookmark )
			sibling = sibling.previousSibling ;

		if ( sibling && sibling.nodeType == 1 && sibling.nodeName == element.nodeName )
		{
			if ( !attribs )
				attribs = this._CreateElementAttribsForComparison( element ) ;

			if ( this._CheckAttributesMatch( sibling, attribs ) )
			{
				// Save the first child to be checked too (to merge things like <b><i></i></b><b><i></i></b>).
				var innerSibling = element.firstChild ;

				if ( hasBookmark )
					FCKDomTools.MoveNode( element.previousSibling, element, true ) ;

				// Move contents to the sibling.
				FCKDomTools.MoveChildren( sibling, element, true ) ;
				FCKDomTools.RemoveNode( sibling ) ;

				// Now check the first inner child (see two comments above).
				if ( innerSibling )
					this._MergePreviousSibling( innerSibling ) ;
			}
		}
	},

	/**
	 * Build the cssText based on the styles definition.
	 */
	_GetStyleText : function()
	{
		var stylesDef = this._StyleDesc.Styles ;

		// Builds the StyleText.
		var stylesText = ( this._StyleDesc.Attributes ? this._StyleDesc.Attributes['style'] || '' : '' ) ;

		if ( stylesText.length > 0 )
			stylesText += ';' ;

		for ( var style in stylesDef )
			stylesText += style + ':' + stylesDef[style] + ';' ;

		// Browsers make some changes to the style when applying them. So, here
		// we normalize it to the browser format. We'll not do that if there
		// are variables inside the style.
		if ( stylesText.length > 0 && !( /#\(/.test( stylesText ) ) )
		{
			stylesText = FCKTools.NormalizeCssText( stylesText ) ;
		}

		return (this._GetStyleText = function() { return stylesText ; })() ;
	},

	/**
	 * Get the the collection used to compare the attributes defined in this
	 * style with attributes in an element. All information in it is lowercased.
	 */
	_GetAttribsForComparison : function()
	{
		// If we have already computed it, just return it.
		var attribs = this._GetAttribsForComparison_$ ;
		if ( attribs )
			return attribs ;

		attribs = new Object() ;

		// Loop through all defined attributes.
		var styleAttribs = this._StyleDesc.Attributes ;
		if ( styleAttribs )
		{
			for ( var styleAtt in styleAttribs )
			{
				attribs[ styleAtt.toLowerCase() ] = styleAttribs[ styleAtt ].toLowerCase() ;
			}
		}

		// Includes the style definitions.
		if ( this._GetStyleText().length > 0 )
		{
			attribs['style'] = this._GetStyleText().toLowerCase() ;
		}

		// Appends the "length" information to the object.
		FCKTools.AppendLengthProperty( attribs, '_length' ) ;

		// Return it, saving it to the next request.
		return ( this._GetAttribsForComparison_$ = attribs ) ;
	},

	/**
	 * Get the the collection used to compare the elements and attributes,
	 * defined in this style overrides, with other element. All information in
	 * it is lowercased.
	 */
	_GetOverridesForComparison : function()
	{
		// If we have already computed it, just return it.
		var overrides = this._GetOverridesForComparison_$ ;
		if ( overrides )
			return overrides ;

		overrides = new Object() ;

		var overridesDesc = this._StyleDesc.Overrides ;

		if ( overridesDesc )
		{
			// The override description can be a string, object or array.
			// Internally, well handle arrays only, so transform it if needed.
			if ( !FCKTools.IsArray( overridesDesc ) )
				overridesDesc = [ overridesDesc ] ;

			// Loop through all override definitions.
			for ( var i = 0 ; i < overridesDesc.length ; i++ )
			{
				var override = overridesDesc[i] ;
				var elementName ;
				var overrideEl ;
				var attrs ;

				// If can be a string with the element name.
				if ( typeof override == 'string' )
					elementName = override.toLowerCase() ;
				// Or an object.
				else
				{
					elementName = override.Element ? override.Element.toLowerCase() : this.Element ;
					attrs = override.Attributes ;
				}

				// We can have more than one override definition for the same
				// element name, so we attempt to simply append information to
				// it if it already exists.
				overrideEl = overrides[ elementName ] || ( overrides[ elementName ] = {} ) ;

				if ( attrs )
				{
					// The returning attributes list is an array, because we
					// could have different override definitions for the same
					// attribute name.
					var overrideAttrs = ( overrideEl.Attributes = overrideEl.Attributes || new Array() ) ;
					for ( var attName in attrs )
					{
						// Each item in the attributes array is also an array,
						// where [0] is the attribute name and [1] is the
						// override value.
						overrideAttrs.push( [ attName.toLowerCase(), attrs[ attName ] ] ) ;
					}
				}
			}
		}

		return ( this._GetOverridesForComparison_$ = overrides ) ;
	},

	/*
	 * Create and object containing all attributes specified in an element,
	 * added by a "_length" property. All values are lowercased.
	 */
	_CreateElementAttribsForComparison : function( element )
	{
		var attribs = new Object() ;
		var attribsCount = 0 ;

		for ( var i = 0 ; i < element.attributes.length ; i++ )
		{
			var att = element.attributes[i] ;

			if ( att.specified )
			{
				attribs[ att.nodeName.toLowerCase() ] = FCKDomTools.GetAttributeValue( element, att ).toLowerCase() ;
				attribsCount++ ;
			}
		}

		attribs._length = attribsCount ;

		return attribs ;
	},

	/**
	 * Checks is the element attributes have a perfect match with the style
	 * attributes.
	 */
	_CheckAttributesMatch : function( element, styleAttribs )
	{
		// Loop through all specified attributes. The same number of
		// attributes must be found and their values must match to
		// declare them as equal.

		var elementAttrbs = element.attributes ;
		var matchCount = 0 ;

		for ( var i = 0 ; i < elementAttrbs.length ; i++ )
		{
			var att = elementAttrbs[i] ;
			if ( att.specified )
			{
				var attName = att.nodeName.toLowerCase() ;
				var styleAtt = styleAttribs[ attName ] ;

				// The attribute is not defined in the style.
				if ( !styleAtt )
					break ;

				// The values are different.
				if ( styleAtt != FCKDomTools.GetAttributeValue( element, att ).toLowerCase() )
					break ;

				matchCount++ ;
			}
		}

		return ( matchCount == styleAttribs._length ) ;
	}
} ;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -