/source/Plug-in/fck/editor/_source/commandclasses/fckblockquotecommand.js
http://prosporous.googlecode.com/ · JavaScript · 250 lines · 192 code · 25 blank · 33 comment · 62 complexity · aaa3f5fc9b49f12b15406144bcbccc2d MD5 · raw file
- /*
- * 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 ;
- }
- } ;