import rt 3.8.7
[freeside.git] / rt / share / html / NoAuth / RichText / FCKeditor / editor / _source / commandclasses / fckblockquotecommand.js
diff --git a/rt/share/html/NoAuth/RichText/FCKeditor/editor/_source/commandclasses/fckblockquotecommand.js b/rt/share/html/NoAuth/RichText/FCKeditor/editor/_source/commandclasses/fckblockquotecommand.js
new file mode 100644 (file)
index 0000000..2caff1b
--- /dev/null
@@ -0,0 +1,281 @@
+/*\r
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net\r
+ * Copyright (C) 2003-2009 Frederico Caldeira Knabben\r
+ *\r
+ * == BEGIN LICENSE ==\r
+ *\r
+ * Licensed under the terms of any of the following licenses at your\r
+ * choice:\r
+ *\r
+ *  - GNU General Public License Version 2 or later (the "GPL")\r
+ *    http://www.gnu.org/licenses/gpl.html\r
+ *\r
+ *  - GNU Lesser General Public License Version 2.1 or later (the "LGPL")\r
+ *    http://www.gnu.org/licenses/lgpl.html\r
+ *\r
+ *  - Mozilla Public License Version 1.1 or later (the "MPL")\r
+ *    http://www.mozilla.org/MPL/MPL-1.1.html\r
+ *\r
+ * == END LICENSE ==\r
+ *\r
+ * FCKBlockQuoteCommand Class: adds or removes blockquote tags.\r
+ */\r
+\r
+var FCKBlockQuoteCommand = function()\r
+{\r
+}\r
+\r
+FCKBlockQuoteCommand.prototype =\r
+{\r
+       Execute : function()\r
+       {\r
+               FCKUndo.SaveUndoStep() ;\r
+\r
+               var state = this.GetState() ;\r
+\r
+               var range = new FCKDomRange( FCK.EditorWindow ) ;\r
+               range.MoveToSelection() ;\r
+\r
+               var bookmark = range.CreateBookmark() ;\r
+\r
+               // Kludge for #1592: if the bookmark nodes are in the beginning of\r
+               // blockquote, then move them to the nearest block element in the\r
+               // blockquote.\r
+               if ( FCKBrowserInfo.IsIE )\r
+               {\r
+                       var bStart      = range.GetBookmarkNode( bookmark, true ) ;\r
+                       var bEnd        = range.GetBookmarkNode( bookmark, false ) ;\r
+\r
+                       var cursor ;\r
+\r
+                       if ( bStart\r
+                                       && bStart.parentNode.nodeName.IEquals( 'blockquote' )\r
+                                       && !bStart.previousSibling )\r
+                       {\r
+                               cursor = bStart ;\r
+                               while ( ( cursor = cursor.nextSibling ) )\r
+                               {\r
+                                       if ( FCKListsLib.BlockElements[ cursor.nodeName.toLowerCase() ] )\r
+                                               FCKDomTools.MoveNode( bStart, cursor, true ) ;\r
+                               }\r
+                       }\r
+\r
+                       if ( bEnd\r
+                                       && bEnd.parentNode.nodeName.IEquals( 'blockquote' )\r
+                                       && !bEnd.previousSibling )\r
+                       {\r
+                               cursor = bEnd ;\r
+                               while ( ( cursor = cursor.nextSibling ) )\r
+                               {\r
+                                       if ( FCKListsLib.BlockElements[ cursor.nodeName.toLowerCase() ] )\r
+                                       {\r
+                                               if ( cursor.firstChild == bStart )\r
+                                                       FCKDomTools.InsertAfterNode( bStart, bEnd ) ;\r
+                                               else\r
+                                                       FCKDomTools.MoveNode( bEnd, cursor, true ) ;\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+\r
+               var iterator = new FCKDomRangeIterator( range ) ;\r
+               var block ;\r
+\r
+               if ( state == FCK_TRISTATE_OFF )\r
+               {\r
+                       var paragraphs = [] ;\r
+                       while ( ( block = iterator.GetNextParagraph() ) )\r
+                               paragraphs.push( block ) ;\r
+\r
+                       // If no paragraphs, create one from the current selection position.\r
+                       if ( paragraphs.length < 1 )\r
+                       {\r
+                               para = range.Window.document.createElement( FCKConfig.EnterMode.IEquals( 'p' ) ? 'p' : 'div' ) ;\r
+                               range.InsertNode( para ) ;\r
+                               para.appendChild( range.Window.document.createTextNode( '\ufeff' ) ) ;\r
+                               range.MoveToBookmark( bookmark ) ;\r
+                               range.MoveToNodeContents( para ) ;\r
+                               range.Collapse( true ) ;\r
+                               bookmark = range.CreateBookmark() ;\r
+                               paragraphs.push( para ) ;\r
+                       }\r
+\r
+                       // Make sure all paragraphs have the same parent.\r
+                       var commonParent = paragraphs[0].parentNode ;\r
+                       var tmp = [] ;\r
+                       for ( var i = 0 ; i < paragraphs.length ; i++ )\r
+                       {\r
+                               block = paragraphs[i] ;\r
+                               commonParent = FCKDomTools.GetCommonParents( block.parentNode, commonParent ).pop() ;\r
+                       }\r
+\r
+                       // The common parent must not be the following tags: table, tbody, tr, ol, ul.\r
+                       while ( commonParent.nodeName.IEquals( 'table', 'tbody', 'tr', 'ol', 'ul' ) )\r
+                               commonParent = commonParent.parentNode ;\r
+\r
+                       // Reconstruct the block list to be processed such that all resulting blocks\r
+                       // satisfy parentNode == commonParent.\r
+                       var lastBlock = null ;\r
+                       while ( paragraphs.length > 0 )\r
+                       {\r
+                               block = paragraphs.shift() ;\r
+                               while ( block.parentNode != commonParent )\r
+                                       block = block.parentNode ;\r
+                               if ( block != lastBlock )\r
+                                       tmp.push( block ) ;\r
+                               lastBlock = block ;\r
+                       }\r
+\r
+                       // If any of the selected blocks is a blockquote, remove it to prevent nested blockquotes.\r
+                       while ( tmp.length > 0 )\r
+                       {\r
+                               block = tmp.shift() ;\r
+                               if ( block.nodeName.IEquals( 'blockquote' ) )\r
+                               {\r
+                                       var docFrag = FCKTools.GetElementDocument( block ).createDocumentFragment() ;\r
+                                       while ( block.firstChild )\r
+                                       {\r
+                                               docFrag.appendChild( block.removeChild( block.firstChild ) ) ;\r
+                                               paragraphs.push( docFrag.lastChild ) ;\r
+                                       }\r
+                                       block.parentNode.replaceChild( docFrag, block ) ;\r
+                               }\r
+                               else\r
+                                       paragraphs.push( block ) ;\r
+                       }\r
+\r
+                       // Now we have all the blocks to be included in a new blockquote node.\r
+                       var bqBlock = range.Window.document.createElement( 'blockquote' ) ;\r
+                       commonParent.insertBefore( bqBlock, paragraphs[0] ) ;\r
+                       while ( paragraphs.length > 0 )\r
+                       {\r
+                               block = paragraphs.shift() ;\r
+                               bqBlock.appendChild( block ) ;\r
+                       }\r
+               }\r
+               else if ( state == FCK_TRISTATE_ON )\r
+               {\r
+                       var moveOutNodes = [] ;\r
+                       var elementMarkers = {} ;\r
+                       while ( ( block = iterator.GetNextParagraph() ) )\r
+                       {\r
+                               var bqParent = null ;\r
+                               var bqChild = null ;\r
+                               while ( block.parentNode )\r
+                               {\r
+                                       if ( block.parentNode.nodeName.IEquals( 'blockquote' ) )\r
+                                       {\r
+                                               bqParent = block.parentNode ;\r
+                                               bqChild = block ;\r
+                                               break ;\r
+                                       }\r
+                                       block = block.parentNode ;\r
+                               }\r
+\r
+                               // Remember the blocks that were recorded down in the moveOutNodes array\r
+                               // to prevent duplicates.\r
+                               if ( bqParent && bqChild && !bqChild._fckblockquotemoveout )\r
+                               {\r
+                                       moveOutNodes.push( bqChild ) ;\r
+                                       FCKDomTools.SetElementMarker( elementMarkers, bqChild, '_fckblockquotemoveout', true ) ;\r
+                               }\r
+                       }\r
+                       FCKDomTools.ClearAllMarkers( elementMarkers ) ;\r
+\r
+                       var movedNodes = [] ;\r
+                       var processedBlockquoteBlocks = [], elementMarkers = {} ;\r
+                       var noBlockLeft = function( bqBlock )\r
+                       {\r
+                               for ( var i = 0 ; i < bqBlock.childNodes.length ; i++ )\r
+                               {\r
+                                       if ( FCKListsLib.BlockElements[ bqBlock.childNodes[i].nodeName.toLowerCase() ] )\r
+                                               return false ;\r
+                               }\r
+                               return true ;\r
+                       } ;\r
+                       while ( moveOutNodes.length > 0 )\r
+                       {\r
+                               var node = moveOutNodes.shift() ;\r
+                               var bqBlock = node.parentNode ;\r
+\r
+                               // If the node is located at the beginning or the end, just take it out without splitting.\r
+                               // Otherwise, split the blockquote node and move the paragraph in between the two blockquote nodes.\r
+                               if ( node == node.parentNode.firstChild )\r
+                                       bqBlock.parentNode.insertBefore( bqBlock.removeChild( node ), bqBlock ) ;\r
+                               else if ( node == node.parentNode.lastChild )\r
+                                       bqBlock.parentNode.insertBefore( bqBlock.removeChild( node ), bqBlock.nextSibling ) ;\r
+                               else\r
+                                       FCKDomTools.BreakParent( node, node.parentNode, range ) ;\r
+\r
+                               // Remember the blockquote node so we can clear it later (if it becomes empty).\r
+                               if ( !bqBlock._fckbqprocessed )\r
+                               {\r
+                                       processedBlockquoteBlocks.push( bqBlock ) ;\r
+                                       FCKDomTools.SetElementMarker( elementMarkers, bqBlock, '_fckbqprocessed', true );\r
+                               }\r
+\r
+                               movedNodes.push( node ) ;\r
+                       }\r
+\r
+                       // Clear blockquote nodes that have become empty.\r
+                       for ( var i = processedBlockquoteBlocks.length - 1 ; i >= 0 ; i-- )\r
+                       {\r
+                               var bqBlock = processedBlockquoteBlocks[i] ;\r
+                               if ( noBlockLeft( bqBlock ) )\r
+                                       FCKDomTools.RemoveNode( bqBlock ) ;\r
+                       }\r
+                       FCKDomTools.ClearAllMarkers( elementMarkers ) ;\r
+\r
+                       if ( FCKConfig.EnterMode.IEquals( 'br' ) )\r
+                       {\r
+                               while ( movedNodes.length )\r
+                               {\r
+                                       var node = movedNodes.shift() ;\r
+                                       var firstTime = true ;\r
+                                       if ( node.nodeName.IEquals( 'div' ) )\r
+                                       {\r
+                                               var docFrag = FCKTools.GetElementDocument( node ).createDocumentFragment() ;\r
+                                               var needBeginBr = firstTime && node.previousSibling &&\r
+                                                       !FCKListsLib.BlockBoundaries[node.previousSibling.nodeName.toLowerCase()] ;\r
+                                               if ( firstTime && needBeginBr )\r
+                                                       docFrag.appendChild( FCKTools.GetElementDocument( node ).createElement( 'br' ) ) ;\r
+                                               var needEndBr = node.nextSibling &&\r
+                                                       !FCKListsLib.BlockBoundaries[node.nextSibling.nodeName.toLowerCase()] ;\r
+                                               while ( node.firstChild )\r
+                                                       docFrag.appendChild( node.removeChild( node.firstChild ) ) ;\r
+                                               if ( needEndBr )\r
+                                                       docFrag.appendChild( FCKTools.GetElementDocument( node ).createElement( 'br' ) ) ;\r
+                                               node.parentNode.replaceChild( docFrag, node ) ;\r
+                                               firstTime = false ;\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+               range.MoveToBookmark( bookmark ) ;\r
+               range.Select() ;\r
+\r
+               FCK.Focus() ;\r
+               FCK.Events.FireEvent( 'OnSelectionChange' ) ;\r
+       },\r
+\r
+       GetState : function()\r
+       {\r
+               // Disabled if not WYSIWYG.\r
+               if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG || ! FCK.EditorWindow )\r
+                       return FCK_TRISTATE_DISABLED ;\r
+\r
+               var path = new FCKElementPath( FCKSelection.GetBoundaryParentElement( true ) ) ;\r
+               var firstBlock = path.Block || path.BlockLimit ;\r
+\r
+               if ( !firstBlock || firstBlock.nodeName.toLowerCase() == 'body' )\r
+                       return FCK_TRISTATE_OFF ;\r
+\r
+               // See if the first block has a blockquote parent.\r
+               for ( var i = 0 ; i < path.Elements.length ; i++ )\r
+               {\r
+                       if ( path.Elements[i].nodeName.IEquals( 'blockquote' ) )\r
+                               return FCK_TRISTATE_ON ;\r
+               }\r
+               return FCK_TRISTATE_OFF ;\r
+       }\r
+} ;\r