initial commit

This commit is contained in:
Siwat Sirichai 2025-06-08 16:22:20 +07:00
commit 252dac3143
1516 changed files with 694271 additions and 0 deletions

View file

@ -0,0 +1,470 @@
/*
* FCKeditor - The text editor for Internet - http://www.fckeditor.net
* Copyright (C) 2003-2007 Frederico Caldeira Knabben
*
* == BEGIN LICENSE ==
*
* Licensed under the terms of any of the following licenses at your
* choice:
*
* - GNU General Public License Version 2 or later (the "GPL")
* http://www.gnu.org/licenses/gpl.html
*
* - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
* http://www.gnu.org/licenses/lgpl.html
*
* - Mozilla Public License Version 1.1 or later (the "MPL")
* http://www.mozilla.org/MPL/MPL-1.1.html
*
* == END LICENSE ==
*
* Definition of other commands that are not available internaly in the
* browser (see FCKNamedCommand).
*/
// ### General Dialog Box Commands.
var FCKDialogCommand = function( name, title, url, width, height, getStateFunction, getStateParam )
{
this.Name = name ;
this.Title = title ;
this.Url = url ;
this.Width = width ;
this.Height = height ;
this.GetStateFunction = getStateFunction ;
this.GetStateParam = getStateParam ;
this.Resizable = false ;
}
FCKDialogCommand.prototype.Execute = function()
{
FCKDialog.OpenDialog( 'FCKDialog_' + this.Name , this.Title, this.Url, this.Width, this.Height, null, null, this.Resizable ) ;
}
FCKDialogCommand.prototype.GetState = function()
{
if ( this.GetStateFunction )
return this.GetStateFunction( this.GetStateParam ) ;
else
return FCK_TRISTATE_OFF ;
}
// Generic Undefined command (usually used when a command is under development).
var FCKUndefinedCommand = function()
{
this.Name = 'Undefined' ;
}
FCKUndefinedCommand.prototype.Execute = function()
{
alert( FCKLang.NotImplemented ) ;
}
FCKUndefinedCommand.prototype.GetState = function()
{
return FCK_TRISTATE_OFF ;
}
// ### FormatBlock
var FCKFormatBlockCommand = function()
{}
FCKFormatBlockCommand.prototype =
{
Name : 'FormatBlock',
Execute : FCKStyleCommand.prototype.Execute,
GetState : function()
{
return FCK.EditorDocument ? FCK_TRISTATE_OFF : FCK_TRISTATE_DISABLED ;
}
};
// ### FontName
var FCKFontNameCommand = function()
{}
FCKFontNameCommand.prototype =
{
Name : 'FontName',
Execute : FCKStyleCommand.prototype.Execute,
GetState : FCKFormatBlockCommand.prototype.GetState
};
// ### FontSize
var FCKFontSizeCommand = function()
{}
FCKFontSizeCommand.prototype =
{
Name : 'FontSize',
Execute : FCKStyleCommand.prototype.Execute,
GetState : FCKFormatBlockCommand.prototype.GetState
};
// ### Preview
var FCKPreviewCommand = function()
{
this.Name = 'Preview' ;
}
FCKPreviewCommand.prototype.Execute = function()
{
FCK.Preview() ;
}
FCKPreviewCommand.prototype.GetState = function()
{
return FCK_TRISTATE_OFF ;
}
// ### Save
var FCKSaveCommand = function()
{
this.Name = 'Save' ;
}
FCKSaveCommand.prototype.Execute = function()
{
// Get the linked field form.
var oForm = FCK.GetParentForm() ;
if ( typeof( oForm.onsubmit ) == 'function' )
{
var bRet = oForm.onsubmit() ;
if ( bRet != null && bRet === false )
return ;
}
// Submit the form.
// If there's a button named "submit" then the form.submit() function is masked and
// can't be called in Mozilla, so we call the click() method of that button.
if ( typeof( oForm.submit ) == 'function' )
oForm.submit() ;
else
oForm.submit.click() ;
}
FCKSaveCommand.prototype.GetState = function()
{
return FCK_TRISTATE_OFF ;
}
// ### NewPage
var FCKNewPageCommand = function()
{
this.Name = 'NewPage' ;
}
FCKNewPageCommand.prototype.Execute = function()
{
FCKUndo.SaveUndoStep() ;
FCK.SetData( '' ) ;
FCKUndo.Typing = true ;
FCK.Focus() ;
}
FCKNewPageCommand.prototype.GetState = function()
{
return FCK_TRISTATE_OFF ;
}
// ### Source button
var FCKSourceCommand = function()
{
this.Name = 'Source' ;
}
FCKSourceCommand.prototype.Execute = function()
{
if ( FCKConfig.SourcePopup ) // Until v2.2, it was mandatory for FCKBrowserInfo.IsGecko.
{
var iWidth = FCKConfig.ScreenWidth * 0.65 ;
var iHeight = FCKConfig.ScreenHeight * 0.65 ;
FCKDialog.OpenDialog( 'FCKDialog_Source', FCKLang.Source, 'dialog/fck_source.html', iWidth, iHeight, null, null, true ) ;
}
else
FCK.SwitchEditMode() ;
}
FCKSourceCommand.prototype.GetState = function()
{
return ( FCK.EditMode == FCK_EDITMODE_WYSIWYG ? FCK_TRISTATE_OFF : FCK_TRISTATE_ON ) ;
}
// ### Undo
var FCKUndoCommand = function()
{
this.Name = 'Undo' ;
}
FCKUndoCommand.prototype.Execute = function()
{
FCKUndo.Undo() ;
}
FCKUndoCommand.prototype.GetState = function()
{
return ( FCKUndo.CheckUndoState() ? FCK_TRISTATE_OFF : FCK_TRISTATE_DISABLED ) ;
}
// ### Redo
var FCKRedoCommand = function()
{
this.Name = 'Redo' ;
}
FCKRedoCommand.prototype.Execute = function()
{
FCKUndo.Redo() ;
}
FCKRedoCommand.prototype.GetState = function()
{
return ( FCKUndo.CheckRedoState() ? FCK_TRISTATE_OFF : FCK_TRISTATE_DISABLED ) ;
}
// ### Page Break
var FCKPageBreakCommand = function()
{
this.Name = 'PageBreak' ;
}
FCKPageBreakCommand.prototype.Execute = function()
{
// Take an undo snapshot before changing the document
FCKUndo.SaveUndoStep() ;
// var e = FCK.EditorDocument.createElement( 'CENTER' ) ;
// e.style.pageBreakAfter = 'always' ;
// Tidy was removing the empty CENTER tags, so the following solution has
// been found. It also validates correctly as XHTML 1.0 Strict.
var e = FCK.EditorDocument.createElement( 'DIV' ) ;
e.style.pageBreakAfter = 'always' ;
e.innerHTML = '<span style="DISPLAY:none">&nbsp;</span>' ;
var oFakeImage = FCKDocumentProcessor_CreateFakeImage( 'FCK__PageBreak', e ) ;
var oRange = new FCKDomRange( FCK.EditorWindow ) ;
oRange.MoveToSelection() ;
var oSplitInfo = oRange.SplitBlock() ;
if ( oSplitInfo.NextBlock )
oSplitInfo.NextBlock.parentNode.insertBefore( oFakeImage, oSplitInfo.NextBlock ) ;
else
oSplitInfo.PreviousBlock.parentNode.insertBefore( oFakeImage, oSplitInfo.PreviousBlock.nextSibling ) ;
FCK.Events.FireEvent( 'OnSelectionChange' ) ;
}
FCKPageBreakCommand.prototype.GetState = function()
{
return 0 ; // FCK_TRISTATE_OFF
}
// FCKUnlinkCommand - by Johnny Egeland (johnny@coretrek.com)
var FCKUnlinkCommand = function()
{
this.Name = 'Unlink' ;
}
FCKUnlinkCommand.prototype.Execute = function()
{
// Take an undo snapshot before changing the document
FCKUndo.SaveUndoStep() ;
if ( FCKBrowserInfo.IsGeckoLike )
{
var oLink = FCK.Selection.MoveToAncestorNode( 'A' ) ;
// The unlink command can generate a span in Firefox, so let's do it our way. See #430
if ( oLink )
FCKTools.RemoveOuterTags( oLink ) ;
return ;
}
FCK.ExecuteNamedCommand( this.Name ) ;
}
FCKUnlinkCommand.prototype.GetState = function()
{
var state = FCK.GetNamedCommandState( this.Name ) ;
// Check that it isn't an anchor
if ( state == FCK_TRISTATE_OFF && FCK.EditMode == FCK_EDITMODE_WYSIWYG )
{
var oLink = FCKSelection.MoveToAncestorNode( 'A' ) ;
var bIsAnchor = ( oLink && oLink.name.length > 0 && oLink.href.length == 0 ) ;
if ( bIsAnchor )
state = FCK_TRISTATE_DISABLED ;
}
return state ;
}
// FCKSelectAllCommand
var FCKSelectAllCommand = function()
{
this.Name = 'SelectAll' ;
}
FCKSelectAllCommand.prototype.Execute = function()
{
if ( FCK.EditMode == FCK_EDITMODE_WYSIWYG )
{
FCK.ExecuteNamedCommand( 'SelectAll' ) ;
}
else
{
// Select the contents of the textarea
var textarea = FCK.EditingArea.Textarea ;
if ( FCKBrowserInfo.IsIE )
{
textarea.createTextRange().execCommand( 'SelectAll' ) ;
}
else
{
textarea.selectionStart = 0 ;
textarea.selectionEnd = textarea.value.length ;
}
textarea.focus() ;
}
}
FCKSelectAllCommand.prototype.GetState = function()
{
return FCK_TRISTATE_OFF ;
}
// FCKPasteCommand
var FCKPasteCommand = function()
{
this.Name = 'Paste' ;
}
FCKPasteCommand.prototype =
{
Execute : function()
{
if ( FCKBrowserInfo.IsIE )
FCK.Paste() ;
else
FCK.ExecuteNamedCommand( 'Paste' ) ;
},
GetState : function()
{
return FCK.GetNamedCommandState( 'Paste' ) ;
}
} ;
// FCKRuleCommand
var FCKRuleCommand = function()
{
this.Name = 'Rule' ;
}
FCKRuleCommand.prototype =
{
Execute : function()
{
FCKUndo.SaveUndoStep() ;
FCK.InsertElement( 'hr' ) ;
},
GetState : function()
{
return FCK.GetNamedCommandState( 'InsertHorizontalRule' ) ;
}
} ;
// FCKCopyCommand
var FCKCopyCommand = function()
{
this.Name = 'Copy' ;
}
FCKCopyCommand.prototype =
{
Execute : function()
{
FCK.ExecuteNamedCommand( this.Name ) ;
},
GetState : function()
{
// Strangely, the cut command happens to have the correct states for both Copy and Cut in all browsers.
return FCK.GetNamedCommandState( 'Cut' ) ;
}
};
var FCKAnchorDeleteCommand = function()
{
this.Name = 'AnchorDelete' ;
}
FCKAnchorDeleteCommand.prototype =
{
Execute : function()
{
if (FCK.Selection.GetType() == 'Control')
{
FCK.Selection.Delete();
}
else
{
var oFakeImage = FCK.Selection.GetSelectedElement() ;
if ( oFakeImage )
{
if ( oFakeImage.tagName == 'IMG' && oFakeImage.getAttribute('_fckanchor') )
oAnchor = FCK.GetRealElement( oFakeImage ) ;
else
oFakeImage = null ;
}
//Search for a real anchor
if ( !oFakeImage )
{
oAnchor = FCK.Selection.MoveToAncestorNode( 'A' ) ;
if ( oAnchor )
FCK.Selection.SelectNode( oAnchor ) ;
}
// If it's also a link, then just remove the name and exit
if ( oAnchor.href.length != 0 )
{
oAnchor.removeAttribute( 'name' ) ;
// Remove temporary class for IE
if ( FCKBrowserInfo.IsIE )
oAnchor.className = oAnchor.className.replace( FCKRegexLib.FCK_Class, '' ) ;
return ;
}
// We need to remove the anchor
// If we got a fake image, then just remove it and we're done
if ( oFakeImage )
{
oFakeImage.parentNode.removeChild( oFakeImage ) ;
return ;
}
// Empty anchor, so just remove it
if ( oAnchor.innerHTML.length == 0 )
{
oAnchor.parentNode.removeChild( oAnchor ) ;
return ;
}
// Anchor with content, leave the content
FCKTools.RemoveOuterTags( oAnchor ) ;
}
if ( FCKBrowserInfo.IsGecko )
FCK.Selection.Collapse( true ) ;
},
GetState : function()
{
return FCK.GetNamedCommandState( 'Unlink') ;
}
};

View file

@ -0,0 +1,250 @@
/*
* FCKeditor - The text editor for Internet - http://www.fckeditor.net
* Copyright (C) 2003-2007 Frederico Caldeira Knabben
*
* == BEGIN LICENSE ==
*
* Licensed under the terms of any of the following licenses at your
* choice:
*
* - GNU General Public License Version 2 or later (the "GPL")
* http://www.gnu.org/licenses/gpl.html
*
* - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
* http://www.gnu.org/licenses/lgpl.html
*
* - Mozilla Public License Version 1.1 or later (the "MPL")
* http://www.mozilla.org/MPL/MPL-1.1.html
*
* == END LICENSE ==
*
* FCKBlockQuoteCommand Class: adds or removes blockquote tags.
*/
var FCKBlockQuoteCommand = function()
{
}
FCKBlockQuoteCommand.prototype =
{
Execute : function()
{
FCKUndo.SaveUndoStep() ;
var state = this.GetState() ;
var range = new FCKDomRange( FCK.EditorWindow ) ;
range.MoveToSelection() ;
var bookmark = range.CreateBookmark() ;
// Kludge for #1592: if the bookmark nodes are in the beginning of
// blockquote, then move them to the nearest block element in the
// blockquote.
if ( FCKBrowserInfo.IsIE )
{
var bStart = range.GetBookmarkNode( bookmark, true ) ;
var bEnd = range.GetBookmarkNode( bookmark, false ) ;
var cursor ;
if ( bStart
&& bStart.parentNode.nodeName.IEquals( 'blockquote' )
&& !bStart.previousSibling )
{
cursor = bStart ;
while ( ( cursor = cursor.nextSibling ) )
{
if ( FCKListsLib.BlockElements[ cursor.nodeName.toLowerCase() ] )
FCKDomTools.MoveNode( bStart, cursor, true ) ;
}
}
if ( bEnd
&& bEnd.parentNode.nodeName.IEquals( 'blockquote' )
&& !bEnd.previousSibling )
{
cursor = bEnd ;
while ( ( cursor = cursor.nextSibling ) )
{
if ( FCKListsLib.BlockElements[ cursor.nodeName.toLowerCase() ] )
{
if ( cursor.firstChild == bStart )
FCKDomTools.InsertAfterNode( bStart, bEnd ) ;
else
FCKDomTools.MoveNode( bEnd, cursor, true ) ;
}
}
}
}
var iterator = new FCKDomRangeIterator( range ) ;
var block ;
if ( state == FCK_TRISTATE_OFF )
{
iterator.EnforceRealBlocks = true ;
var paragraphs = [] ;
while ( ( block = iterator.GetNextParagraph() ) )
paragraphs.push( block ) ;
// If no paragraphs, create one from the current selection position.
if ( paragraphs.length < 1 )
{
para = range.Window.document.createElement( FCKConfig.EnterMode.IEquals( 'p' ) ? 'p' : 'div' ) ;
range.InsertNode( para ) ;
para.appendChild( range.Window.document.createTextNode( '\ufeff' ) ) ;
range.MoveToBookmark( bookmark ) ;
range.MoveToNodeContents( para ) ;
range.Collapse( true ) ;
bookmark = range.CreateBookmark() ;
paragraphs.push( para ) ;
}
// Make sure all paragraphs have the same parent.
var commonParent = paragraphs[0].parentNode ;
var tmp = [] ;
for ( var i = 0 ; i < paragraphs.length ; i++ )
{
block = paragraphs[i] ;
commonParent = FCKDomTools.GetCommonParents( block.parentNode, commonParent ).pop() ;
}
var lastBlock = null ;
while ( paragraphs.length > 0 )
{
block = paragraphs.shift() ;
while ( block.parentNode != commonParent )
block = block.parentNode ;
if ( block != lastBlock )
tmp.push( block ) ;
lastBlock = block ;
}
// If any of the selected blocks is a blockquote, remove it to prevent nested blockquotes.
while ( tmp.length > 0 )
{
block = tmp.shift() ;
if ( block.nodeName.IEquals( 'blockquote' ) )
{
var docFrag = block.ownerDocument.createDocumentFragment() ;
while ( block.firstChild )
{
docFrag.appendChild( block.removeChild( block.firstChild ) ) ;
paragraphs.push( docFrag.lastChild ) ;
}
block.parentNode.replaceChild( docFrag, block ) ;
}
else
paragraphs.push( block ) ;
}
// Now we have all the blocks to be included in a new blockquote node.
var bqBlock = range.Window.document.createElement( 'blockquote' ) ;
commonParent.insertBefore( bqBlock, paragraphs[0] ) ;
while ( paragraphs.length > 0 )
{
block = paragraphs.shift() ;
bqBlock.appendChild( block ) ;
}
}
else if ( state == FCK_TRISTATE_ON )
{
var moveOutNodes = [] ;
while ( ( block = iterator.GetNextParagraph() ) )
{
var bqParent = null ;
var bqChild = null ;
while ( block.parentNode )
{
if ( block.parentNode.nodeName.IEquals( 'blockquote' ) )
{
bqParent = block.parentNode ;
bqChild = block ;
break ;
}
block = block.parentNode ;
}
if ( bqParent && bqChild )
moveOutNodes.push( bqChild ) ;
}
var movedNodes = [] ;
while ( moveOutNodes.length > 0 )
{
var node = moveOutNodes.shift() ;
var bqBlock = node.parentNode ;
// If the node is located at the beginning or the end, just take it out without splitting.
// Otherwise, split the blockquote node and move the paragraph in between the two blockquote nodes.
if ( node == node.parentNode.firstChild )
{
bqBlock.parentNode.insertBefore( bqBlock.removeChild( node ), bqBlock ) ;
if ( ! bqBlock.firstChild )
bqBlock.parentNode.removeChild( bqBlock ) ;
}
else if ( node == node.parentNode.lastChild )
{
bqBlock.parentNode.insertBefore( bqBlock.removeChild( node ), bqBlock.nextSibling ) ;
if ( ! bqBlock.firstChild )
bqBlock.parentNode.removeChild( bqBlock ) ;
}
else
FCKDomTools.BreakParent( node, node.parentNode, range ) ;
movedNodes.push( node ) ;
}
if ( FCKConfig.EnterMode.IEquals( 'br' ) )
{
while ( movedNodes.length )
{
var node = movedNodes.shift() ;
var firstTime = true ;
if ( node.nodeName.IEquals( 'div' ) )
{
var docFrag = node.ownerDocument.createDocumentFragment() ;
var needBeginBr = firstTime && node.previousSibling &&
!FCKListsLib.BlockBoundaries[node.previousSibling.nodeName.toLowerCase()] ;
if ( firstTime && needBeginBr )
docFrag.appendChild( node.ownerDocument.createElement( 'br' ) ) ;
var needEndBr = node.nextSibling &&
!FCKListsLib.BlockBoundaries[node.nextSibling.nodeName.toLowerCase()] ;
while ( node.firstChild )
docFrag.appendChild( node.removeChild( node.firstChild ) ) ;
if ( needEndBr )
docFrag.appendChild( node.ownerDocument.createElement( 'br' ) ) ;
node.parentNode.replaceChild( docFrag, node ) ;
firstTime = false ;
}
}
}
}
range.MoveToBookmark( bookmark ) ;
range.Select() ;
FCK.Focus() ;
FCK.Events.FireEvent( 'OnSelectionChange' ) ;
},
GetState : function()
{
// Disabled if not WYSIWYG.
if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG || ! FCK.EditorWindow )
return FCK_TRISTATE_DISABLED ;
var path = new FCKElementPath( FCKSelection.GetBoundaryParentElement( true ) ) ;
var firstBlock = path.Block || path.BlockLimit ;
if ( !firstBlock || firstBlock.nodeName.toLowerCase() == 'body' )
return FCK_TRISTATE_OFF ;
// See if the first block has a blockquote parent.
for ( var i = 0 ; i < path.Elements.length ; i++ )
{
if ( path.Elements[i].nodeName.IEquals( 'blockquote' ) )
return FCK_TRISTATE_ON ;
}
return FCK_TRISTATE_OFF ;
}
} ;

View file

@ -0,0 +1,59 @@
/*
* FCKeditor - The text editor for Internet - http://www.fckeditor.net
* Copyright (C) 2003-2007 Frederico Caldeira Knabben
*
* == BEGIN LICENSE ==
*
* Licensed under the terms of any of the following licenses at your
* choice:
*
* - GNU General Public License Version 2 or later (the "GPL")
* http://www.gnu.org/licenses/gpl.html
*
* - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
* http://www.gnu.org/licenses/lgpl.html
*
* - Mozilla Public License Version 1.1 or later (the "MPL")
* http://www.mozilla.org/MPL/MPL-1.1.html
*
* == END LICENSE ==
*
* FCKCoreStyleCommand Class: controls the execution of a core style. Core
* styles are usually represented as buttons in the toolbar., like Bold and
* Italic.
*/
var FCKCoreStyleCommand = function( coreStyleName )
{
this.Name = 'CoreStyle' ;
this.StyleName = '_FCK_' + coreStyleName ;
this.IsActive = false ;
FCKStyles.AttachStyleStateChange( this.StyleName, this._OnStyleStateChange, this ) ;
}
FCKCoreStyleCommand.prototype =
{
Execute : function()
{
FCKUndo.SaveUndoStep() ;
if ( this.IsActive )
FCKStyles.RemoveStyle( this.StyleName ) ;
else
FCKStyles.ApplyStyle( this.StyleName ) ;
FCK.Focus() ;
FCK.Events.FireEvent( 'OnSelectionChange' ) ;
},
GetState : function()
{
return this.IsActive ? FCK_TRISTATE_ON : FCK_TRISTATE_OFF ;
},
_OnStyleStateChange : function( styleName, isActive )
{
this.IsActive = isActive ;
}
};

View file

@ -0,0 +1,180 @@
/*
* FCKeditor - The text editor for Internet - http://www.fckeditor.net
* Copyright (C) 2003-2007 Frederico Caldeira Knabben
*
* == BEGIN LICENSE ==
*
* Licensed under the terms of any of the following licenses at your
* choice:
*
* - GNU General Public License Version 2 or later (the "GPL")
* http://www.gnu.org/licenses/gpl.html
*
* - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
* http://www.gnu.org/licenses/lgpl.html
*
* - Mozilla Public License Version 1.1 or later (the "MPL")
* http://www.mozilla.org/MPL/MPL-1.1.html
*
* == END LICENSE ==
*
* Stretch the editor to full window size and back.
*/
var FCKFitWindow = function()
{
this.Name = 'FitWindow' ;
}
FCKFitWindow.prototype.Execute = function()
{
var eEditorFrame = window.frameElement ;
var eEditorFrameStyle = eEditorFrame.style ;
var eMainWindow = parent ;
var eDocEl = eMainWindow.document.documentElement ;
var eBody = eMainWindow.document.body ;
var eBodyStyle = eBody.style ;
var eParent ;
// No original style properties known? Go fullscreen.
if ( !this.IsMaximized )
{
// Registering an event handler when the window gets resized.
if( FCKBrowserInfo.IsIE )
eMainWindow.attachEvent( 'onresize', FCKFitWindow_Resize ) ;
else
eMainWindow.addEventListener( 'resize', FCKFitWindow_Resize, true ) ;
// Save the scrollbars position.
this._ScrollPos = FCKTools.GetScrollPosition( eMainWindow ) ;
// Save and reset the styles for the entire node tree. They could interfere in the result.
eParent = eEditorFrame ;
// The extra () is to avoid a warning with strict error checking. This is ok.
while( (eParent = eParent.parentNode) )
{
if ( eParent.nodeType == 1 )
{
eParent._fckSavedStyles = FCKTools.SaveStyles( eParent ) ;
eParent.style.zIndex = FCKConfig.FloatingPanelsZIndex - 1 ;
}
}
// Hide IE scrollbars (in strict mode).
if ( FCKBrowserInfo.IsIE )
{
this.documentElementOverflow = eDocEl.style.overflow ;
eDocEl.style.overflow = 'hidden' ;
eBodyStyle.overflow = 'hidden' ;
}
else
{
// Hide the scroolbars in Firefox.
eBodyStyle.overflow = 'hidden' ;
eBodyStyle.width = '0px' ;
eBodyStyle.height = '0px' ;
}
// Save the IFRAME styles.
this._EditorFrameStyles = FCKTools.SaveStyles( eEditorFrame ) ;
// Resize.
var oViewPaneSize = FCKTools.GetViewPaneSize( eMainWindow ) ;
eEditorFrameStyle.position = "absolute";
eEditorFrameStyle.zIndex = FCKConfig.FloatingPanelsZIndex - 1;
eEditorFrameStyle.left = "0px";
eEditorFrameStyle.top = "0px";
eEditorFrameStyle.width = oViewPaneSize.Width + "px";
eEditorFrameStyle.height = oViewPaneSize.Height + "px";
// Giving the frame some (huge) borders on his right and bottom
// side to hide the background that would otherwise show when the
// editor is in fullsize mode and the window is increased in size
// not for IE, because IE immediately adapts the editor on resize,
// without showing any of the background oddly in firefox, the
// editor seems not to fill the whole frame, so just setting the
// background of it to white to cover the page laying behind it anyway.
if ( !FCKBrowserInfo.IsIE )
{
eEditorFrameStyle.borderRight = eEditorFrameStyle.borderBottom = "9999px solid white" ;
eEditorFrameStyle.backgroundColor = "white";
}
// Scroll to top left.
eMainWindow.scrollTo(0, 0);
// Is the editor still not on the top left? Let's find out and fix that as well. (Bug #174)
var editorPos = FCKTools.GetWindowPosition( eMainWindow, eEditorFrame ) ;
if ( editorPos.x != 0 )
eEditorFrameStyle.left = ( -1 * editorPos.x ) + "px" ;
if ( editorPos.y != 0 )
eEditorFrameStyle.top = ( -1 * editorPos.y ) + "px" ;
this.IsMaximized = true ;
}
else // Resize to original size.
{
// Remove the event handler of window resizing.
if( FCKBrowserInfo.IsIE )
eMainWindow.detachEvent( "onresize", FCKFitWindow_Resize ) ;
else
eMainWindow.removeEventListener( "resize", FCKFitWindow_Resize, true ) ;
// Restore the CSS position for the entire node tree.
eParent = eEditorFrame ;
// The extra () is to avoid a warning with strict error checking. This is ok.
while( (eParent = eParent.parentNode) )
{
if ( eParent._fckSavedStyles )
{
FCKTools.RestoreStyles( eParent, eParent._fckSavedStyles ) ;
eParent._fckSavedStyles = null ;
}
}
// Restore IE scrollbars
if ( FCKBrowserInfo.IsIE )
eDocEl.style.overflow = this.documentElementOverflow ;
// Restore original size
FCKTools.RestoreStyles( eEditorFrame, this._EditorFrameStyles ) ;
// Restore the window scroll position.
eMainWindow.scrollTo( this._ScrollPos.X, this._ScrollPos.Y ) ;
this.IsMaximized = false ;
}
FCKToolbarItems.GetItem('FitWindow').RefreshState() ;
// It seams that Firefox restarts the editing area when making this changes.
// On FF 1.0.x, the area is not anymore editable. On FF 1.5+, the special
//configuration, like DisableFFTableHandles and DisableObjectResizing get
//lost, so we must reset it. Also, the cursor position and selection are
//also lost, even if you comment the following line (MakeEditable).
// if ( FCKBrowserInfo.IsGecko10 ) // Initially I thought it was a FF 1.0 only problem.
if ( FCK.EditMode == FCK_EDITMODE_WYSIWYG )
FCK.EditingArea.MakeEditable() ;
FCK.Focus() ;
}
FCKFitWindow.prototype.GetState = function()
{
if ( FCKConfig.ToolbarLocation != 'In' )
return FCK_TRISTATE_DISABLED ;
else
return ( this.IsMaximized ? FCK_TRISTATE_ON : FCK_TRISTATE_OFF );
}
function FCKFitWindow_Resize()
{
var oViewPaneSize = FCKTools.GetViewPaneSize( parent ) ;
var eEditorFrameStyle = window.frameElement.style ;
eEditorFrameStyle.width = oViewPaneSize.Width + 'px' ;
eEditorFrameStyle.height = oViewPaneSize.Height + 'px' ;
}

View file

@ -0,0 +1,280 @@
/*
* FCKeditor - The text editor for Internet - http://www.fckeditor.net
* Copyright (C) 2003-2007 Frederico Caldeira Knabben
*
* == BEGIN LICENSE ==
*
* Licensed under the terms of any of the following licenses at your
* choice:
*
* - GNU General Public License Version 2 or later (the "GPL")
* http://www.gnu.org/licenses/gpl.html
*
* - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
* http://www.gnu.org/licenses/lgpl.html
*
* - Mozilla Public License Version 1.1 or later (the "MPL")
* http://www.mozilla.org/MPL/MPL-1.1.html
*
* == END LICENSE ==
*
* FCKIndentCommand Class: controls block indentation.
*/
var FCKIndentCommand = function( name, offset )
{
this.Name = name ;
this.Offset = offset ;
this.IndentCSSProperty = FCKConfig.ContentLangDirection.IEquals( 'ltr' ) ? 'marginLeft' : 'marginRight' ;
}
FCKIndentCommand._InitIndentModeParameters = function()
{
if ( FCKConfig.IndentClasses && FCKConfig.IndentClasses.length > 0 )
{
this._UseIndentClasses = true ;
this._IndentClassMap = {} ;
for ( var i = 0 ; i < FCKConfig.IndentClasses.length ;i++ )
this._IndentClassMap[FCKConfig.IndentClasses[i]] = i + 1 ;
this._ClassNameRegex = new RegExp( '(?:^|\\s+)(' + FCKConfig.IndentClasses.join( '|' ) + ')(?=$|\\s)' ) ;
}
else
this._UseIndentClasses = false ;
}
FCKIndentCommand.prototype =
{
Execute : function()
{
// Save an undo snapshot before doing anything.
FCKUndo.SaveUndoStep() ;
var range = new FCKDomRange( FCK.EditorWindow ) ;
range.MoveToSelection() ;
var bookmark = range.CreateBookmark() ;
// Two cases to handle here: either we're in a list, or not.
// If we're in a list, then the indent/outdent operations would be done on the list nodes.
// Otherwise, apply the operation on the nearest block nodes.
var nearestListBlock = FCKDomTools.GetCommonParentNode( range.StartNode || range.StartContainer ,
range.EndNode || range.EndContainer,
['ul', 'ol'] ) ;
if ( nearestListBlock )
this._IndentList( range, nearestListBlock ) ;
else
this._IndentBlock( range ) ;
range.MoveToBookmark( bookmark ) ;
range.Select() ;
FCK.Focus() ;
FCK.Events.FireEvent( 'OnSelectionChange' ) ;
},
GetState : function()
{
// Disabled if not WYSIWYG.
if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG || ! FCK.EditorWindow )
return FCK_TRISTATE_DISABLED ;
// Initialize parameters if not already initialzed.
if ( FCKIndentCommand._UseIndentClasses == undefined )
FCKIndentCommand._InitIndentModeParameters() ;
// If we're not in a list, and the starting block's indentation is zero, and the current
// command is the outdent command, then we should return FCK_TRISTATE_DISABLED.
var startContainer = FCKSelection.GetBoundaryParentElement( true ) ;
var endContainer = FCKSelection.GetBoundaryParentElement( false ) ;
var listNode = FCKDomTools.GetCommonParentNode( startContainer, endContainer, ['ul','ol'] ) ;
if ( listNode )
{
if ( this.Name.IEquals( 'outdent' ) )
return FCK_TRISTATE_OFF ;
var firstItem = FCKTools.GetElementAscensor( startContainer, 'li' ) ;
if ( !firstItem || !firstItem.previousSibling )
return FCK_TRISTATE_DISABLED ;
return FCK_TRISTATE_OFF ;
}
if ( ! FCKIndentCommand._UseIndentClasses && this.Name.IEquals( 'indent' ) )
return FCK_TRISTATE_OFF;
var path = new FCKElementPath( startContainer ) ;
var firstBlock = path.Block || path.BlockLimit ;
if ( !firstBlock )
return FCK_TRISTATE_DISABLED ;
if ( FCKIndentCommand._UseIndentClasses )
{
var indentClass = firstBlock.className.match( FCKIndentCommand._ClassNameRegex ) ;
var indentStep = 0 ;
if ( indentClass != null )
{
indentClass = indentClass[1] ;
indentStep = FCKIndentCommand._IndentClassMap[indentClass] ;
}
if ( ( this.Name == 'outdent' && indentStep == 0 ) ||
( this.Name == 'indent' && indentStep == FCKConfig.IndentClasses.length ) )
return FCK_TRISTATE_DISABLED ;
return FCK_TRISTATE_OFF ;
}
else
{
var indent = parseInt( firstBlock.style[this.IndentCSSProperty], 10 ) ;
if ( isNaN( indent ) )
indent = 0 ;
if ( indent <= 0 )
return FCK_TRISTATE_DISABLED ;
return FCK_TRISTATE_OFF ;
}
},
_IndentBlock : function( range )
{
var iterator = new FCKDomRangeIterator( range ) ;
range.Expand( 'block_contents' ) ;
var commonParents = FCKDomTools.GetCommonParents( range.StartContainer, range.EndContainer ) ;
var nearestParent = commonParents[commonParents.length - 1] ;
var block ;
while ( ( block = iterator.GetNextParagraph() ) )
{
// We don't want to indent subtrees recursively, so only perform the indent operation
// if the block itself is the nearestParent, or the block's parent is the nearestParent.
if ( ! ( block == nearestParent || block.parentNode == nearestParent ) )
continue ;
if ( FCKIndentCommand._UseIndentClasses )
{
// Transform current class name to indent step index.
var indentClass = block.className.match( FCKIndentCommand._ClassNameRegex ) ;
var indentStep = 0 ;
if ( indentClass != null )
{
indentClass = indentClass[1] ;
indentStep = FCKIndentCommand._IndentClassMap[indentClass] ;
}
// Operate on indent step index, transform indent step index back to class name.
if ( this.Name.IEquals( 'outdent' ) )
indentStep-- ;
else if ( this.Name.IEquals( 'indent' ) )
indentStep++ ;
indentStep = Math.min( indentStep, FCKConfig.IndentClasses.length ) ;
indentStep = Math.max( indentStep, 0 ) ;
var className = block.className.replace( FCKIndentCommand._ClassNameRegex, '' ) ;
if ( indentStep < 1 )
block.className = className ;
else
block.className = ( className.length > 0 ? className + ' ' : '' ) +
FCKConfig.IndentClasses[indentStep - 1] ;
}
else
{
// Offset distance is assumed to be in pixels for now.
var currentOffset = parseInt( block.style[this.IndentCSSProperty], 10 ) ;
if ( isNaN( currentOffset ) )
currentOffset = 0 ;
currentOffset += this.Offset ;
currentOffset = Math.max( currentOffset, 0 ) ;
currentOffset = Math.ceil( currentOffset / this.Offset ) * this.Offset ;
block.style[this.IndentCSSProperty] = currentOffset ? currentOffset + FCKConfig.IndentUnit : '' ;
if ( block.getAttribute( 'style' ) == '' )
block.removeAttribute( 'style' ) ;
}
}
},
_IndentList : function( range, listNode )
{
// Our starting and ending points of the range might be inside some blocks under a list item...
// So before playing with the iterator, we need to expand the block to include the list items.
var startContainer = range.StartContainer ;
var endContainer = range.EndContainer ;
while ( startContainer && startContainer.parentNode != listNode )
startContainer = startContainer.parentNode ;
while ( endContainer && endContainer.parentNode != listNode )
endContainer = endContainer.parentNode ;
if ( ! startContainer || ! endContainer )
return ;
// Now we can iterate over the individual items on the same tree depth.
var block = startContainer ;
var itemsToMove = [] ;
var stopFlag = false ;
while ( stopFlag == false )
{
if ( block == endContainer )
stopFlag = true ;
itemsToMove.push( block ) ;
block = block.nextSibling ;
}
if ( itemsToMove.length < 1 )
return ;
// Do indent or outdent operations on the array model of the list, not the list's DOM tree itself.
// The array model demands that it knows as much as possible about the surrounding lists, we need
// to feed it the further ancestor node that is still a list.
var listParents = FCKDomTools.GetParents( listNode ) ;
for ( var i = 0 ; i < listParents.length ; i++ )
{
if ( listParents[i].nodeName.IEquals( ['ul', 'ol'] ) )
{
listNode = listParents[i] ;
break ;
}
}
var indentOffset = this.Name.IEquals( 'indent' ) ? 1 : -1 ;
var startItem = itemsToMove[0] ;
var lastItem = itemsToMove[ itemsToMove.length - 1 ] ;
var markerObj = {} ;
// Convert the list DOM tree into a one dimensional array.
var listArray = FCKDomTools.ListToArray( listNode, markerObj ) ;
// Apply indenting or outdenting on the array.
var baseIndent = listArray[lastItem._FCK_ListArray_Index].indent ;
for ( var i = startItem._FCK_ListArray_Index ; i <= lastItem._FCK_ListArray_Index ; i++ )
listArray[i].indent += indentOffset ;
for ( var i = lastItem._FCK_ListArray_Index + 1 ; i < listArray.length && listArray[i].indent > baseIndent ; i++ )
listArray[i].indent += indentOffset ;
/* For debug use only
var PrintArray = function( listArray, doc )
{
var s = [] ;
for ( var i = 0 ; i < listArray.length ; i++ )
{
for ( var j in listArray[i] )
{
if ( j != 'contents' )
s.push( j + ":" + listArray[i][j] + "; " ) ;
else
{
var docFrag = doc.createDocumentFragment() ;
var tmpNode = doc.createElement( 'span' ) ;
for ( var k = 0 ; k < listArray[i][j].length ; k++ )
docFrag.appendChild( listArray[i][j][k].cloneNode( true ) ) ;
tmpNode.appendChild( docFrag ) ;
s.push( j + ":" + tmpNode.innerHTML + "; ") ;
}
}
s.push( '\n' ) ;
}
alert( s.join('') ) ;
}
PrintArray( listArray, FCK.EditorDocument ) ;
*/
// Convert the array back to a DOM forest (yes we might have a few subtrees now).
// And replace the old list with the new forest.
var newList = FCKDomTools.ArrayToList( listArray ) ;
if ( newList )
listNode.parentNode.replaceChild( newList.listNode, listNode ) ;
// Clean up the markers.
FCKDomTools.ClearAllMarkers( markerObj ) ;
}
} ;

View file

@ -0,0 +1,173 @@
/*
* FCKeditor - The text editor for Internet - http://www.fckeditor.net
* Copyright (C) 2003-2007 Frederico Caldeira Knabben
*
* == BEGIN LICENSE ==
*
* Licensed under the terms of any of the following licenses at your
* choice:
*
* - GNU General Public License Version 2 or later (the "GPL")
* http://www.gnu.org/licenses/gpl.html
*
* - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
* http://www.gnu.org/licenses/lgpl.html
*
* - Mozilla Public License Version 1.1 or later (the "MPL")
* http://www.mozilla.org/MPL/MPL-1.1.html
*
* == END LICENSE ==
*
* FCKJustifyCommand Class: controls block justification.
*/
var FCKJustifyCommand = function( alignValue )
{
this.AlignValue = alignValue ;
// Detect whether this is the instance for the default alignment.
var contentDir = FCKConfig.ContentLangDirection.toLowerCase() ;
this.IsDefaultAlign = ( alignValue == 'left' && contentDir == 'ltr' ) ||
( alignValue == 'right' && contentDir == 'rtl' ) ;
// Get the class name to be used by this instance.
var cssClassName = this._CssClassName = ( function()
{
var classes = FCKConfig.JustifyClasses ;
if ( classes )
{
switch ( alignValue )
{
case 'left' :
return classes[0] ;
case 'center' :
return classes[1] ;
case 'right' :
return classes[2] ;
case 'justify' :
return classes[3] ;
}
}
return null ;
} )() ;
if ( cssClassName && cssClassName.length > 0 )
this._CssClassRegex = new RegExp( '(?:^|\\s+)' + cssClassName + '(?=$|\\s)' ) ;
}
FCKJustifyCommand._GetClassNameRegex = function()
{
var regex = FCKJustifyCommand._ClassRegex ;
if ( regex != undefined )
return regex ;
var names = [] ;
var classes = FCKConfig.JustifyClasses ;
if ( classes )
{
for ( var i = 0 ; i < 4 ; i++ )
{
var className = classes[i] ;
if ( className && className.length > 0 )
names.push( className ) ;
}
}
if ( names.length > 0 )
regex = new RegExp( '(?:^|\\s+)(?:' + names.join( '|' ) + ')(?=$|\\s)' ) ;
else
regex = null ;
return FCKJustifyCommand._ClassRegex = regex ;
}
FCKJustifyCommand.prototype =
{
Execute : function()
{
// Save an undo snapshot before doing anything.
FCKUndo.SaveUndoStep() ;
var range = new FCKDomRange( FCK.EditorWindow ) ;
range.MoveToSelection() ;
var currentState = this.GetState() ;
if ( currentState == FCK_TRISTATE_DISABLED )
return ;
// Store a bookmark of the selection since the paragraph iterator might
// change the DOM tree and break selections.
var bookmark = range.CreateBookmark() ;
var cssClassName = this._CssClassName ;
// Apply alignment setting for each paragraph.
var iterator = new FCKDomRangeIterator( range ) ;
var block ;
while ( ( block = iterator.GetNextParagraph() ) )
{
block.removeAttribute( 'align' ) ;
if ( cssClassName )
{
// Remove the any of the alignment classes from the className.
var className = block.className.replace( FCKJustifyCommand._GetClassNameRegex(), '' ) ;
// Append the desired class name.
if ( currentState == FCK_TRISTATE_OFF )
{
if ( className.length > 0 )
className += ' ' ;
block.className = className + cssClassName ;
}
else if ( className.length == 0 )
FCKDomTools.RemoveAttribute( block, 'class' ) ;
}
else
{
var style = block.style ;
if ( currentState == FCK_TRISTATE_OFF )
style.textAlign = this.AlignValue ;
else
{
style.textAlign = '' ;
if ( style.cssText.length == 0 )
block.removeAttribute( 'style' ) ;
}
}
}
// Restore previous selection.
range.MoveToBookmark( bookmark ) ;
range.Select() ;
FCK.Focus() ;
FCK.Events.FireEvent( 'OnSelectionChange' ) ;
},
GetState : function()
{
// Disabled if not WYSIWYG.
if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG || ! FCK.EditorWindow )
return FCK_TRISTATE_DISABLED ;
// Retrieve the first selected block.
var path = new FCKElementPath( FCKSelection.GetBoundaryParentElement( true ) ) ;
var firstBlock = path.Block || path.BlockLimit ;
if ( !firstBlock || firstBlock.nodeName.toLowerCase() == 'body' )
return FCK_TRISTATE_OFF ;
// Check if the desired style is already applied to the block.
var currentAlign ;
if ( FCKBrowserInfo.IsIE )
currentAlign = firstBlock.currentStyle.textAlign ;
else
currentAlign = FCK.EditorWindow.getComputedStyle( firstBlock, '' ).getPropertyValue( 'text-align' );
currentAlign = currentAlign.replace( /(-moz-|-webkit-|start|auto)/i, '' );
if ( ( !currentAlign && this.IsDefaultAlign ) || currentAlign == this.AlignValue )
return FCK_TRISTATE_ON ;
return FCK_TRISTATE_OFF ;
}
} ;

View file

@ -0,0 +1,382 @@
/*
* FCKeditor - The text editor for Internet - http://www.fckeditor.net
* Copyright (C) 2003-2007 Frederico Caldeira Knabben
*
* == BEGIN LICENSE ==
*
* Licensed under the terms of any of the following licenses at your
* choice:
*
* - GNU General Public License Version 2 or later (the "GPL")
* http://www.gnu.org/licenses/gpl.html
*
* - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
* http://www.gnu.org/licenses/lgpl.html
*
* - Mozilla Public License Version 1.1 or later (the "MPL")
* http://www.mozilla.org/MPL/MPL-1.1.html
*
* == END LICENSE ==
*
* Implementation for the "Insert/Remove Ordered/Unordered List" commands.
*/
var FCKListCommand = function( name, tagName )
{
this.Name = name ;
this.TagName = tagName ;
}
FCKListCommand.prototype =
{
GetState : function()
{
// Disabled if not WYSIWYG.
if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG || ! FCK.EditorWindow )
return FCK_TRISTATE_DISABLED ;
// We'll use the style system's convention to determine list state here...
// If the starting block is a descendant of an <ol> or <ul> node, then we're in a list.
var startContainer = FCKSelection.GetBoundaryParentElement( true ) ;
var listNode = startContainer ;
while ( listNode )
{
if ( listNode.nodeName.IEquals( [ 'ul', 'ol' ] ) )
break ;
listNode = listNode.parentNode ;
}
if ( listNode && listNode.nodeName.IEquals( this.TagName ) )
return FCK_TRISTATE_ON ;
else
return FCK_TRISTATE_OFF ;
},
Execute : function()
{
FCKUndo.SaveUndoStep() ;
var doc = FCK.EditorDocument ;
var range = new FCKDomRange( FCK.EditorWindow ) ;
range.MoveToSelection() ;
var state = this.GetState() ;
// Midas lists rule #1 says we can create a list even in an empty document.
// But FCKDomRangeIterator wouldn't run if the document is really empty.
// So create a paragraph if the document is empty and we're going to create a list.
if ( state == FCK_TRISTATE_OFF )
{
FCKDomTools.TrimNode( doc.body ) ;
if ( ! doc.body.firstChild )
{
var paragraph = doc.createElement( 'p' ) ;
doc.body.appendChild( paragraph ) ;
range.MoveToNodeContents( paragraph ) ;
}
}
var bookmark = range.CreateBookmark() ;
// Group the blocks up because there are many cases where multiple lists have to be created,
// or multiple lists have to be cancelled.
var listGroups = [] ;
var markerObj = {} ;
var iterator = new FCKDomRangeIterator( range ) ;
var block ;
iterator.ForceBrBreak = ( state == FCK_TRISTATE_OFF ) ;
var nextRangeExists = true ;
var rangeQueue = null ;
while ( nextRangeExists )
{
while ( ( block = iterator.GetNextParagraph() ) )
{
var path = new FCKElementPath( block ) ;
var listNode = null ;
var processedFlag = false ;
var blockLimit = path.BlockLimit ;
// First, try to group by a list ancestor.
for ( var i = path.Elements.length - 1 ; i >= 0 ; i-- )
{
var el = path.Elements[i] ;
if ( el.nodeName.IEquals( ['ol', 'ul'] ) )
{
// If we've encountered a list inside a block limit
// The last group object of the block limit element should
// no longer be valid. Since paragraphs after the list
// should belong to a different group of paragraphs before
// the list. (Bug #1309)
if ( blockLimit._FCK_ListGroupObject )
blockLimit._FCK_ListGroupObject = null ;
var groupObj = el._FCK_ListGroupObject ;
if ( groupObj )
groupObj.contents.push( block ) ;
else
{
groupObj = { 'root' : el, 'contents' : [ block ] } ;
listGroups.push( groupObj ) ;
FCKDomTools.SetElementMarker( markerObj, el, '_FCK_ListGroupObject', groupObj ) ;
}
processedFlag = true ;
break ;
}
}
if ( processedFlag )
continue ;
// No list ancestor? Group by block limit.
var root = blockLimit ;
if ( root._FCK_ListGroupObject )
root._FCK_ListGroupObject.contents.push( block ) ;
else
{
var groupObj = { 'root' : root, 'contents' : [ block ] } ;
FCKDomTools.SetElementMarker( markerObj, root, '_FCK_ListGroupObject', groupObj ) ;
listGroups.push( groupObj ) ;
}
}
if ( FCKBrowserInfo.IsIE )
nextRangeExists = false ;
else
{
if ( rangeQueue == null )
{
rangeQueue = [] ;
var selectionObject = FCK.EditorWindow.getSelection() ;
if ( selectionObject && listGroups.length == 0 )
rangeQueue.push( selectionObject.getRangeAt( 0 ) ) ;
for ( var i = 1 ; selectionObject && i < selectionObject.rangeCount ; i++ )
rangeQueue.push( selectionObject.getRangeAt( i ) ) ;
}
if ( rangeQueue.length < 1 )
nextRangeExists = false ;
else
{
var internalRange = FCKW3CRange.CreateFromRange( doc, rangeQueue.shift() ) ;
range._Range = internalRange ;
range._UpdateElementInfo() ;
if ( range.StartNode.nodeName.IEquals( 'td' ) )
range.SetStart( range.StartNode, 1 ) ;
if ( range.EndNode.nodeName.IEquals( 'td' ) )
range.SetEnd( range.EndNode, 2 ) ;
iterator = new FCKDomRangeIterator( range ) ;
iterator.ForceBrBreak = ( state == FCK_TRISTATE_OFF ) ;
}
}
}
// Now we have two kinds of list groups, groups rooted at a list, and groups rooted at a block limit element.
// We either have to build lists or remove lists, for removing a list does not makes sense when we are looking
// at the group that's not rooted at lists. So we have three cases to handle.
var listsCreated = [] ;
while ( listGroups.length > 0 )
{
var groupObj = listGroups.shift() ;
if ( state == FCK_TRISTATE_OFF )
{
if ( groupObj.root.nodeName.IEquals( ['ul', 'ol'] ) )
this._ChangeListType( groupObj, markerObj, listsCreated ) ;
else
this._CreateList( groupObj, listsCreated ) ;
}
else if ( state == FCK_TRISTATE_ON && groupObj.root.nodeName.IEquals( ['ul', 'ol'] ) )
this._RemoveList( groupObj, markerObj ) ;
}
// For all new lists created, merge adjacent, same type lists.
for ( var i = 0 ; i < listsCreated.length ; i++ )
{
var listNode = listsCreated[i] ;
var stopFlag = false ;
var currentNode = listNode ;
while ( ! stopFlag )
{
currentNode = currentNode.nextSibling ;
if ( currentNode && currentNode.nodeType == 3 && currentNode.nodeValue.search( /^[\n\r\t ]*$/ ) == 0 )
continue ;
stopFlag = true ;
}
if ( currentNode && currentNode.nodeName.IEquals( this.TagName ) )
{
currentNode.parentNode.removeChild( currentNode ) ;
while ( currentNode.firstChild )
listNode.appendChild( currentNode.removeChild( currentNode.firstChild ) ) ;
}
stopFlag = false ;
currentNode = listNode ;
while ( ! stopFlag )
{
currentNode = currentNode.previousSibling ;
if ( currentNode && currentNode.nodeType == 3 && currentNode.nodeValue.search( /^[\n\r\t ]*$/ ) == 0 )
continue ;
stopFlag = true ;
}
if ( currentNode && currentNode.nodeName.IEquals( this.TagName ) )
{
currentNode.parentNode.removeChild( currentNode ) ;
while ( currentNode.lastChild )
listNode.insertBefore( currentNode.removeChild( currentNode.lastChild ),
listNode.firstChild ) ;
}
}
// Clean up, restore selection and update toolbar button states.
FCKDomTools.ClearAllMarkers( markerObj ) ;
range.MoveToBookmark( bookmark ) ;
range.Select() ;
FCK.Focus() ;
FCK.Events.FireEvent( 'OnSelectionChange' ) ;
},
_ChangeListType : function( groupObj, markerObj, listsCreated )
{
// This case is easy...
// 1. Convert the whole list into a one-dimensional array.
// 2. Change the list type by modifying the array.
// 3. Recreate the whole list by converting the array to a list.
// 4. Replace the original list with the recreated list.
var listArray = FCKDomTools.ListToArray( groupObj.root, markerObj ) ;
var selectedListItems = [] ;
for ( var i = 0 ; i < groupObj.contents.length ; i++ )
{
var itemNode = groupObj.contents[i] ;
itemNode = FCKTools.GetElementAscensor( itemNode, 'li' ) ;
if ( ! itemNode || itemNode._FCK_ListItem_Processed )
continue ;
selectedListItems.push( itemNode ) ;
FCKDomTools.SetElementMarker( markerObj, itemNode, '_FCK_ListItem_Processed', true ) ;
}
var fakeParent = groupObj.root.ownerDocument.createElement( this.TagName ) ;
for ( var i = 0 ; i < selectedListItems.length ; i++ )
{
var listIndex = selectedListItems[i]._FCK_ListArray_Index ;
listArray[listIndex].parent = fakeParent ;
}
var newList = FCKDomTools.ArrayToList( listArray, markerObj ) ;
for ( var i = 0 ; i < newList.listNode.childNodes.length ; i++ )
{
if ( newList.listNode.childNodes[i].nodeName.IEquals( this.TagName ) )
listsCreated.push( newList.listNode.childNodes[i] ) ;
}
groupObj.root.parentNode.replaceChild( newList.listNode, groupObj.root ) ;
},
_CreateList : function( groupObj, listsCreated )
{
var contents = groupObj.contents ;
var doc = groupObj.root.ownerDocument ;
var listContents = [] ;
// It is possible to have the contents returned by DomRangeIterator to be the same as the root.
// e.g. when we're running into table cells.
// In such a case, enclose the childNodes of contents[0] into a <div>.
if ( contents.length == 1 && contents[0] == groupObj.root )
{
var divBlock = doc.createElement( 'div' );
while ( contents[0].firstChild )
divBlock.appendChild( contents[0].removeChild( contents[0].firstChild ) ) ;
contents[0].appendChild( divBlock ) ;
contents[0] = divBlock ;
}
// Calculate the common parent node of all content blocks.
var commonParent = groupObj.contents[0].parentNode ;
for ( var i = 0 ; i < contents.length ; i++ )
commonParent = FCKDomTools.GetCommonParents( commonParent, contents[i].parentNode ).pop() ;
// We want to insert things that are in the same tree level only, so calculate the contents again
// by expanding the selected blocks to the same tree level.
for ( var i = 0 ; i < contents.length ; i++ )
{
var contentNode = contents[i] ;
while ( contentNode.parentNode )
{
if ( contentNode.parentNode == commonParent )
{
listContents.push( contentNode ) ;
break ;
}
contentNode = contentNode.parentNode ;
}
}
if ( listContents.length < 1 )
return ;
// Insert the list to the DOM tree.
var insertAnchor = listContents[listContents.length - 1].nextSibling ;
var listNode = doc.createElement( this.TagName ) ;
listsCreated.push( listNode ) ;
while ( listContents.length )
{
var contentBlock = listContents.shift() ;
var docFrag = doc.createDocumentFragment() ;
while ( contentBlock.firstChild )
docFrag.appendChild( contentBlock.removeChild( contentBlock.firstChild ) ) ;
contentBlock.parentNode.removeChild( contentBlock ) ;
var listItem = doc.createElement( 'li' ) ;
listItem.appendChild( docFrag ) ;
listNode.appendChild( listItem ) ;
}
commonParent.insertBefore( listNode, insertAnchor ) ;
},
_RemoveList : function( groupObj, markerObj )
{
// This is very much like the change list type operation.
// Except that we're changing the selected items' indent to -1 in the list array.
var listArray = FCKDomTools.ListToArray( groupObj.root, markerObj ) ;
var selectedListItems = [] ;
for ( var i = 0 ; i < groupObj.contents.length ; i++ )
{
var itemNode = groupObj.contents[i] ;
itemNode = FCKTools.GetElementAscensor( itemNode, 'li' ) ;
if ( ! itemNode || itemNode._FCK_ListItem_Processed )
continue ;
selectedListItems.push( itemNode ) ;
FCKDomTools.SetElementMarker( markerObj, itemNode, '_FCK_ListItem_Processed', true ) ;
}
var lastListIndex = null ;
for ( var i = 0 ; i < selectedListItems.length ; i++ )
{
var listIndex = selectedListItems[i]._FCK_ListArray_Index ;
listArray[listIndex].indent = -1 ;
lastListIndex = listIndex ;
}
// After cutting parts of the list out with indent=-1, we still have to maintain the array list
// model's nextItem.indent <= currentItem.indent + 1 invariant. Otherwise the array model of the
// list cannot be converted back to a real DOM list.
for ( var i = lastListIndex + 1; i < listArray.length ; i++ )
{
if ( listArray[i].indent > listArray[i-1].indent + 1 )
{
var indentOffset = listArray[i-1].indent + 1 - listArray[i].indent ;
var oldIndent = listArray[i].indent ;
while ( listArray[i] && listArray[i].indent >= oldIndent)
{
listArray[i].indent += indentOffset ;
i++ ;
}
i-- ;
}
}
var newList = FCKDomTools.ArrayToList( listArray, markerObj ) ;
// If groupObj.root is the last element in its parent, or its nextSibling is a <br>, then we should
// not add a <br> after the final item. So, check for the cases and trim the <br>.
if ( groupObj.root.nextSibling == null || groupObj.root.nextSibling.nodeName.IEquals( 'br' ) )
{
if ( newList.listNode.lastChild.nodeName.IEquals( 'br' ) )
newList.listNode.removeChild( newList.listNode.lastChild ) ;
}
groupObj.root.parentNode.replaceChild( newList.listNode, groupObj.root ) ;
}
};

View file

@ -0,0 +1,37 @@
/*
* FCKeditor - The text editor for Internet - http://www.fckeditor.net
* Copyright (C) 2003-2007 Frederico Caldeira Knabben
*
* == BEGIN LICENSE ==
*
* Licensed under the terms of any of the following licenses at your
* choice:
*
* - GNU General Public License Version 2 or later (the "GPL")
* http://www.gnu.org/licenses/gpl.html
*
* - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
* http://www.gnu.org/licenses/lgpl.html
*
* - Mozilla Public License Version 1.1 or later (the "MPL")
* http://www.mozilla.org/MPL/MPL-1.1.html
*
* == END LICENSE ==
*
* FCKNamedCommand Class: represents an internal browser command.
*/
var FCKNamedCommand = function( commandName )
{
this.Name = commandName ;
}
FCKNamedCommand.prototype.Execute = function()
{
FCK.ExecuteNamedCommand( this.Name ) ;
}
FCKNamedCommand.prototype.GetState = function()
{
return FCK.GetNamedCommandState( this.Name ) ;
}

View file

@ -0,0 +1,38 @@
/*
* FCKeditor - The text editor for Internet - http://www.fckeditor.net
* Copyright (C) 2003-2007 Frederico Caldeira Knabben
*
* == BEGIN LICENSE ==
*
* Licensed under the terms of any of the following licenses at your
* choice:
*
* - GNU General Public License Version 2 or later (the "GPL")
* http://www.gnu.org/licenses/gpl.html
*
* - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
* http://www.gnu.org/licenses/lgpl.html
*
* - Mozilla Public License Version 1.1 or later (the "MPL")
* http://www.mozilla.org/MPL/MPL-1.1.html
*
* == END LICENSE ==
*
* FCKPastePlainTextCommand Class: represents the
* "Paste as Plain Text" command.
*/
var FCKPastePlainTextCommand = function()
{
this.Name = 'PasteText' ;
}
FCKPastePlainTextCommand.prototype.Execute = function()
{
FCK.PasteAsPlainText() ;
}
FCKPastePlainTextCommand.prototype.GetState = function()
{
return FCK.GetNamedCommandState( 'Paste' ) ;
}

View file

@ -0,0 +1,40 @@
/*
* FCKeditor - The text editor for Internet - http://www.fckeditor.net
* Copyright (C) 2003-2007 Frederico Caldeira Knabben
*
* == BEGIN LICENSE ==
*
* Licensed under the terms of any of the following licenses at your
* choice:
*
* - GNU General Public License Version 2 or later (the "GPL")
* http://www.gnu.org/licenses/gpl.html
*
* - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
* http://www.gnu.org/licenses/lgpl.html
*
* - Mozilla Public License Version 1.1 or later (the "MPL")
* http://www.mozilla.org/MPL/MPL-1.1.html
*
* == END LICENSE ==
*
* FCKPasteWordCommand Class: represents the "Paste from Word" command.
*/
var FCKPasteWordCommand = function()
{
this.Name = 'PasteWord' ;
}
FCKPasteWordCommand.prototype.Execute = function()
{
FCK.PasteFromWord() ;
}
FCKPasteWordCommand.prototype.GetState = function()
{
if ( FCKConfig.ForcePasteAsPlainText )
return FCK_TRISTATE_DISABLED ;
else
return FCK.GetNamedCommandState( 'Paste' ) ;
}

View file

@ -0,0 +1,45 @@
/*
* FCKeditor - The text editor for Internet - http://www.fckeditor.net
* Copyright (C) 2003-2007 Frederico Caldeira Knabben
*
* == BEGIN LICENSE ==
*
* Licensed under the terms of any of the following licenses at your
* choice:
*
* - GNU General Public License Version 2 or later (the "GPL")
* http://www.gnu.org/licenses/gpl.html
*
* - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
* http://www.gnu.org/licenses/lgpl.html
*
* - Mozilla Public License Version 1.1 or later (the "MPL")
* http://www.mozilla.org/MPL/MPL-1.1.html
*
* == END LICENSE ==
*
* FCKRemoveFormatCommand Class: controls the execution of a core style. Core
* styles are usually represented as buttons in the toolbar., like Bold and
* Italic.
*/
var FCKRemoveFormatCommand = function()
{
this.Name = 'RemoveFormat' ;
}
FCKRemoveFormatCommand.prototype =
{
Execute : function()
{
FCKStyles.RemoveAll() ;
FCK.Focus() ;
FCK.Events.FireEvent( 'OnSelectionChange' ) ;
},
GetState : function()
{
return FCK.EditorWindow ? FCK_TRISTATE_OFF : FCK_TRISTATE_DISABLED ;
}
};

View file

@ -0,0 +1,74 @@
/*
* FCKeditor - The text editor for Internet - http://www.fckeditor.net
* Copyright (C) 2003-2007 Frederico Caldeira Knabben
*
* == BEGIN LICENSE ==
*
* Licensed under the terms of any of the following licenses at your
* choice:
*
* - GNU General Public License Version 2 or later (the "GPL")
* http://www.gnu.org/licenses/gpl.html
*
* - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
* http://www.gnu.org/licenses/lgpl.html
*
* - Mozilla Public License Version 1.1 or later (the "MPL")
* http://www.mozilla.org/MPL/MPL-1.1.html
*
* == END LICENSE ==
*
* FCKShowBlockCommand Class: the "Show Blocks" command.
*/
var FCKShowBlockCommand = function( name, defaultState )
{
this.Name = name ;
if ( defaultState != undefined )
this._SavedState = defaultState ;
else
this._SavedState = null ;
}
FCKShowBlockCommand.prototype.Execute = function()
{
var state = this.GetState() ;
if ( state == FCK_TRISTATE_DISABLED )
return ;
var body = FCK.EditorDocument.body ;
if ( state == FCK_TRISTATE_ON )
body.className = body.className.replace( /(^| )FCK__ShowBlocks/g, '' ) ;
else
body.className += ' FCK__ShowBlocks' ;
FCK.Events.FireEvent( 'OnSelectionChange' ) ;
}
FCKShowBlockCommand.prototype.GetState = function()
{
if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG )
return FCK_TRISTATE_DISABLED ;
// On some cases FCK.EditorDocument.body is not yet available
if ( !FCK.EditorDocument )
return FCK_TRISTATE_OFF ;
if ( /FCK__ShowBlocks(?:\s|$)/.test( FCK.EditorDocument.body.className ) )
return FCK_TRISTATE_ON ;
return FCK_TRISTATE_OFF ;
}
FCKShowBlockCommand.prototype.SaveState = function()
{
this._SavedState = this.GetState() ;
}
FCKShowBlockCommand.prototype.RestoreState = function()
{
if ( this._SavedState != null && this.GetState() != this._SavedState )
this.Execute() ;
}

View file

@ -0,0 +1,39 @@
/*
* FCKeditor - The text editor for Internet - http://www.fckeditor.net
* Copyright (C) 2003-2007 Frederico Caldeira Knabben
*
* == BEGIN LICENSE ==
*
* Licensed under the terms of any of the following licenses at your
* choice:
*
* - GNU General Public License Version 2 or later (the "GPL")
* http://www.gnu.org/licenses/gpl.html
*
* - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
* http://www.gnu.org/licenses/lgpl.html
*
* - Mozilla Public License Version 1.1 or later (the "MPL")
* http://www.mozilla.org/MPL/MPL-1.1.html
*
* == END LICENSE ==
*
* FCKStyleCommand Class: represents the "Spell Check" command.
* (Gecko specific implementation)
*/
var FCKSpellCheckCommand = function()
{
this.Name = 'SpellCheck' ;
this.IsEnabled = ( FCKConfig.SpellChecker == 'SpellerPages' ) ;
}
FCKSpellCheckCommand.prototype.Execute = function()
{
FCKDialog.OpenDialog( 'FCKDialog_SpellCheck', 'Spell Check', 'dialog/fck_spellerpages.html', 440, 480 ) ;
}
FCKSpellCheckCommand.prototype.GetState = function()
{
return this.IsEnabled ? FCK_TRISTATE_OFF : FCK_TRISTATE_DISABLED ;
}

View file

@ -0,0 +1,67 @@
/*
* FCKeditor - The text editor for Internet - http://www.fckeditor.net
* Copyright (C) 2003-2007 Frederico Caldeira Knabben
*
* == BEGIN LICENSE ==
*
* Licensed under the terms of any of the following licenses at your
* choice:
*
* - GNU General Public License Version 2 or later (the "GPL")
* http://www.gnu.org/licenses/gpl.html
*
* - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
* http://www.gnu.org/licenses/lgpl.html
*
* - Mozilla Public License Version 1.1 or later (the "MPL")
* http://www.mozilla.org/MPL/MPL-1.1.html
*
* == END LICENSE ==
*
* FCKStyleCommand Class: represents the "Spell Check" command.
* (IE specific implementation)
*/
var FCKSpellCheckCommand = function()
{
this.Name = 'SpellCheck' ;
this.IsEnabled = ( FCKConfig.SpellChecker == 'ieSpell' || FCKConfig.SpellChecker == 'SpellerPages' ) ;
}
FCKSpellCheckCommand.prototype.Execute = function()
{
switch ( FCKConfig.SpellChecker )
{
case 'ieSpell' :
this._RunIeSpell() ;
break ;
case 'SpellerPages' :
FCKDialog.OpenDialog( 'FCKDialog_SpellCheck', 'Spell Check', 'dialog/fck_spellerpages.html', 440, 480 ) ;
break ;
}
}
FCKSpellCheckCommand.prototype._RunIeSpell = function()
{
try
{
var oIeSpell = new ActiveXObject( "ieSpell.ieSpellExtension" ) ;
oIeSpell.CheckAllLinkedDocuments( FCK.EditorDocument ) ;
}
catch( e )
{
if( e.number == -2146827859 )
{
if ( confirm( FCKLang.IeSpellDownload ) )
window.open( FCKConfig.IeSpellDownloadUrl , 'IeSpellDownload' ) ;
}
else
alert( 'Error Loading ieSpell: ' + e.message + ' (' + e.number + ')' ) ;
}
}
FCKSpellCheckCommand.prototype.GetState = function()
{
return this.IsEnabled ? FCK_TRISTATE_OFF : FCK_TRISTATE_DISABLED ;
}

View file

@ -0,0 +1,60 @@
/*
* FCKeditor - The text editor for Internet - http://www.fckeditor.net
* Copyright (C) 2003-2007 Frederico Caldeira Knabben
*
* == BEGIN LICENSE ==
*
* Licensed under the terms of any of the following licenses at your
* choice:
*
* - GNU General Public License Version 2 or later (the "GPL")
* http://www.gnu.org/licenses/gpl.html
*
* - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
* http://www.gnu.org/licenses/lgpl.html
*
* - Mozilla Public License Version 1.1 or later (the "MPL")
* http://www.mozilla.org/MPL/MPL-1.1.html
*
* == END LICENSE ==
*
* FCKStyleCommand Class: represents the "Style" command.
*/
var FCKStyleCommand = function()
{}
FCKStyleCommand.prototype =
{
Name : 'Style',
Execute : function( styleName, styleComboItem )
{
FCKUndo.SaveUndoStep() ;
if ( styleComboItem.Selected )
FCK.Styles.RemoveStyle( styleComboItem.Style ) ;
else
FCK.Styles.ApplyStyle( styleComboItem.Style ) ;
FCKUndo.SaveUndoStep() ;
FCK.Focus() ;
FCK.Events.FireEvent( 'OnSelectionChange' ) ;
},
GetState : function()
{
if ( !FCK.EditorDocument )
return FCK_TRISTATE_DISABLED ;
if ( FCKSelection.GetType() == 'Control' )
{
var el = FCKSelection.GetSelectedElement() ;
if ( !el || !FCKStyles.CheckHasObjectStyle( el.nodeName.toLowerCase() ) )
return FCK_TRISTATE_DISABLED ;
}
return FCK_TRISTATE_OFF ;
}
};

View file

@ -0,0 +1,106 @@
/*
* FCKeditor - The text editor for Internet - http://www.fckeditor.net
* Copyright (C) 2003-2007 Frederico Caldeira Knabben
*
* == BEGIN LICENSE ==
*
* Licensed under the terms of any of the following licenses at your
* choice:
*
* - GNU General Public License Version 2 or later (the "GPL")
* http://www.gnu.org/licenses/gpl.html
*
* - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
* http://www.gnu.org/licenses/lgpl.html
*
* - Mozilla Public License Version 1.1 or later (the "MPL")
* http://www.mozilla.org/MPL/MPL-1.1.html
*
* == END LICENSE ==
*
* FCKPastePlainTextCommand Class: represents the
* "Paste as Plain Text" command.
*/
var FCKTableCommand = function( command )
{
this.Name = command ;
}
FCKTableCommand.prototype.Execute = function()
{
FCKUndo.SaveUndoStep() ;
if ( ! FCKBrowserInfo.IsGecko )
{
switch ( this.Name )
{
case 'TableMergeRight' :
return FCKTableHandler.MergeRight() ;
case 'TableMergeDown' :
return FCKTableHandler.MergeDown() ;
}
}
switch ( this.Name )
{
case 'TableInsertRowAfter' :
return FCKTableHandler.InsertRow( false ) ;
case 'TableInsertRowBefore' :
return FCKTableHandler.InsertRow( true ) ;
case 'TableDeleteRows' :
return FCKTableHandler.DeleteRows() ;
case 'TableInsertColumnAfter' :
return FCKTableHandler.InsertColumn( false ) ;
case 'TableInsertColumnBefore' :
return FCKTableHandler.InsertColumn( true ) ;
case 'TableDeleteColumns' :
return FCKTableHandler.DeleteColumns() ;
case 'TableInsertCellAfter' :
return FCKTableHandler.InsertCell( null, false ) ;
case 'TableInsertCellBefore' :
return FCKTableHandler.InsertCell( null, true ) ;
case 'TableDeleteCells' :
return FCKTableHandler.DeleteCells() ;
case 'TableMergeCells' :
return FCKTableHandler.MergeCells() ;
case 'TableHorizontalSplitCell' :
return FCKTableHandler.HorizontalSplitCell() ;
case 'TableVerticalSplitCell' :
return FCKTableHandler.VerticalSplitCell() ;
case 'TableDelete' :
return FCKTableHandler.DeleteTable() ;
default :
return alert( FCKLang.UnknownCommand.replace( /%1/g, this.Name ) ) ;
}
}
FCKTableCommand.prototype.GetState = function()
{
if ( FCK.EditorDocument != null && FCKSelection.HasAncestorNode( 'TABLE' ) )
{
switch ( this.Name )
{
case 'TableHorizontalSplitCell' :
case 'TableVerticalSplitCell' :
if ( FCKTableHandler.GetSelectedCells().length == 1 )
return FCK_TRISTATE_OFF ;
else
return FCK_TRISTATE_DISABLED ;
case 'TableMergeCells' :
if ( FCKTableHandler.CheckIsSelectionRectangular()
&& FCKTableHandler.GetSelectedCells().length > 1 )
return FCK_TRISTATE_OFF ;
else
return FCK_TRISTATE_DISABLED ;
case 'TableMergeRight' :
return FCKTableHandler.GetMergeRightTarget() ? FCK_TRISTATE_OFF : FCK_TRISTATE_DISABLED ;
case 'TableMergeDown' :
return FCKTableHandler.GetMergeDownTarget() ? FCK_TRISTATE_OFF : FCK_TRISTATE_DISABLED ;
default :
return FCK_TRISTATE_OFF ;
}
}
else
return FCK_TRISTATE_DISABLED;
}

View file

@ -0,0 +1,197 @@
/*
* FCKeditor - The text editor for Internet - http://www.fckeditor.net
* Copyright (C) 2003-2007 Frederico Caldeira Knabben
*
* == BEGIN LICENSE ==
*
* Licensed under the terms of any of the following licenses at your
* choice:
*
* - GNU General Public License Version 2 or later (the "GPL")
* http://www.gnu.org/licenses/gpl.html
*
* - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
* http://www.gnu.org/licenses/lgpl.html
*
* - Mozilla Public License Version 1.1 or later (the "MPL")
* http://www.mozilla.org/MPL/MPL-1.1.html
*
* == END LICENSE ==
*
* FCKTextColorCommand Class: represents the text color comand. It shows the
* color selection panel.
*/
// FCKTextColorCommand Constructor
// type: can be 'ForeColor' or 'BackColor'.
var FCKTextColorCommand = function( type )
{
this.Name = type == 'ForeColor' ? 'TextColor' : 'BGColor' ;
this.Type = type ;
var oWindow ;
if ( FCKBrowserInfo.IsIE )
oWindow = window ;
else if ( FCK.ToolbarSet._IFrame )
oWindow = FCKTools.GetElementWindow( FCK.ToolbarSet._IFrame ) ;
else
oWindow = window.parent ;
this._Panel = new FCKPanel( oWindow ) ;
this._Panel.AppendStyleSheet( FCKConfig.SkinPath + 'fck_editor.css' ) ;
this._Panel.MainNode.className = 'FCK_Panel' ;
this._CreatePanelBody( this._Panel.Document, this._Panel.MainNode ) ;
FCKTools.DisableSelection( this._Panel.Document.body ) ;
}
FCKTextColorCommand.prototype.Execute = function( panelX, panelY, relElement )
{
// Show the Color Panel at the desired position.
this._Panel.Show( panelX, panelY, relElement ) ;
}
FCKTextColorCommand.prototype.SetColor = function( color )
{
FCKUndo.SaveUndoStep() ;
var style = FCKStyles.GetStyle( '_FCK_' +
( this.Type == 'ForeColor' ? 'Color' : 'BackColor' ) ) ;
if ( !color || color.length == 0 )
FCK.Styles.RemoveStyle( style ) ;
else
{
style.SetVariable( 'Color', color ) ;
FCKStyles.ApplyStyle( style ) ;
}
FCKUndo.SaveUndoStep() ;
FCK.Focus() ;
FCK.Events.FireEvent( 'OnSelectionChange' ) ;
}
FCKTextColorCommand.prototype.GetState = function()
{
return FCK_TRISTATE_OFF ;
}
function FCKTextColorCommand_OnMouseOver()
{
this.className = 'ColorSelected' ;
}
function FCKTextColorCommand_OnMouseOut()
{
this.className = 'ColorDeselected' ;
}
function FCKTextColorCommand_OnClick( ev, command, color )
{
this.className = 'ColorDeselected' ;
command.SetColor( color ) ;
command._Panel.Hide() ;
}
function FCKTextColorCommand_AutoOnClick( ev, command )
{
this.className = 'ColorDeselected' ;
command.SetColor( '' ) ;
command._Panel.Hide() ;
}
function FCKTextColorCommand_MoreOnClick( ev, command )
{
this.className = 'ColorDeselected' ;
command._Panel.Hide() ;
FCKDialog.OpenDialog( 'FCKDialog_Color', FCKLang.DlgColorTitle, 'dialog/fck_colorselector.html', 400, 330, FCKTools.Hitch(command, 'SetColor') ) ;
}
FCKTextColorCommand.prototype._CreatePanelBody = function( targetDocument, targetDiv )
{
function CreateSelectionDiv()
{
var oDiv = targetDocument.createElement( "DIV" ) ;
oDiv.className = 'ColorDeselected' ;
FCKTools.AddEventListenerEx( oDiv, 'mouseover', FCKTextColorCommand_OnMouseOver ) ;
FCKTools.AddEventListenerEx( oDiv, 'mouseout', FCKTextColorCommand_OnMouseOut ) ;
return oDiv ;
}
// Create the Table that will hold all colors.
var oTable = targetDiv.appendChild( targetDocument.createElement( "TABLE" ) ) ;
oTable.className = 'ForceBaseFont' ; // Firefox 1.5 Bug.
oTable.style.tableLayout = 'fixed' ;
oTable.cellPadding = 0 ;
oTable.cellSpacing = 0 ;
oTable.border = 0 ;
oTable.width = 150 ;
var oCell = oTable.insertRow(-1).insertCell(-1) ;
oCell.colSpan = 8 ;
// Create the Button for the "Automatic" color selection.
var oDiv = oCell.appendChild( CreateSelectionDiv() ) ;
oDiv.innerHTML =
'<table cellspacing="0" cellpadding="0" width="100%" border="0">\
<tr>\
<td><div class="ColorBoxBorder"><div class="ColorBox" style="background-color: #000000"></div></div></td>\
<td nowrap width="100%" align="center">' + FCKLang.ColorAutomatic + '</td>\
</tr>\
</table>' ;
FCKTools.AddEventListenerEx( oDiv, 'click', FCKTextColorCommand_AutoOnClick, this ) ;
// Dirty hack for Opera, Safari and Firefox 3.
if ( !FCKBrowserInfo.IsIE )
oDiv.style.width = '96%' ;
// Create an array of colors based on the configuration file.
var aColors = FCKConfig.FontColors.toString().split(',') ;
// Create the colors table based on the array.
var iCounter = 0 ;
while ( iCounter < aColors.length )
{
var oRow = oTable.insertRow(-1) ;
for ( var i = 0 ; i < 8 ; i++, iCounter++ )
{
// The div will be created even if no more colors are available.
// Extra divs will be hidden later in the code. (#1597)
if ( iCounter < aColors.length )
{
var colorParts = aColors[iCounter].split('/') ;
var colorValue = '#' + colorParts[0] ;
var colorName = colorParts[1] || colorValue ;
}
oDiv = oRow.insertCell(-1).appendChild( CreateSelectionDiv() ) ;
oDiv.innerHTML = '<div class="ColorBoxBorder"><div class="ColorBox" style="background-color: ' + colorValue + '"></div></div>' ;
if ( iCounter >= aColors.length )
oDiv.style.visibility = 'hidden' ;
else
FCKTools.AddEventListenerEx( oDiv, 'click', FCKTextColorCommand_OnClick, [ this, colorName ] ) ;
}
}
// Create the Row and the Cell for the "More Colors..." button.
if ( FCKConfig.EnableMoreFontColors )
{
oCell = oTable.insertRow(-1).insertCell(-1) ;
oCell.colSpan = 8 ;
oDiv = oCell.appendChild( CreateSelectionDiv() ) ;
oDiv.innerHTML = '<table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td nowrap align="center">' + FCKLang.ColorMoreColors + '</td></tr></table>' ;
FCKTools.AddEventListenerEx( oDiv, 'click', FCKTextColorCommand_MoreOnClick, this ) ;
}
// Dirty hack for Opera, Safari and Firefox 3.
if ( !FCKBrowserInfo.IsIE )
oDiv.style.width = '96%' ;
}