📄 fckstyle.js
字号:
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 + -