fckblockquotecommand.js
上传用户:dbstep
上传日期:2022-08-06
资源大小:2803k
文件大小:9k
源码类别:

WEB源码(ASP,PHP,...)

开发平台:

ASP/ASPX

  1. /*
  2.  * FCKeditor - The text editor for Internet - http://www.fckeditor.net
  3.  * Copyright (C) 2003-2009 Frederico Caldeira Knabben
  4.  *
  5.  * == BEGIN LICENSE ==
  6.  *
  7.  * Licensed under the terms of any of the following licenses at your
  8.  * choice:
  9.  *
  10.  *  - GNU General Public License Version 2 or later (the "GPL")
  11.  *    http://www.gnu.org/licenses/gpl.html
  12.  *
  13.  *  - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
  14.  *    http://www.gnu.org/licenses/lgpl.html
  15.  *
  16.  *  - Mozilla Public License Version 1.1 or later (the "MPL")
  17.  *    http://www.mozilla.org/MPL/MPL-1.1.html
  18.  *
  19.  * == END LICENSE ==
  20.  *
  21.  * FCKBlockQuoteCommand Class: adds or removes blockquote tags.
  22.  */
  23. var FCKBlockQuoteCommand = function()
  24. {
  25. }
  26. FCKBlockQuoteCommand.prototype =
  27. {
  28. Execute : function()
  29. {
  30. FCKUndo.SaveUndoStep() ;
  31. var state = this.GetState() ;
  32. var range = new FCKDomRange( FCK.EditorWindow ) ;
  33. range.MoveToSelection() ;
  34. var bookmark = range.CreateBookmark() ;
  35. // Kludge for #1592: if the bookmark nodes are in the beginning of
  36. // blockquote, then move them to the nearest block element in the
  37. // blockquote.
  38. if ( FCKBrowserInfo.IsIE )
  39. {
  40. var bStart = range.GetBookmarkNode( bookmark, true ) ;
  41. var bEnd = range.GetBookmarkNode( bookmark, false ) ;
  42. var cursor ;
  43. if ( bStart
  44. && bStart.parentNode.nodeName.IEquals( 'blockquote' )
  45. && !bStart.previousSibling )
  46. {
  47. cursor = bStart ;
  48. while ( ( cursor = cursor.nextSibling ) )
  49. {
  50. if ( FCKListsLib.BlockElements[ cursor.nodeName.toLowerCase() ] )
  51. FCKDomTools.MoveNode( bStart, cursor, true ) ;
  52. }
  53. }
  54. if ( bEnd
  55. && bEnd.parentNode.nodeName.IEquals( 'blockquote' )
  56. && !bEnd.previousSibling )
  57. {
  58. cursor = bEnd ;
  59. while ( ( cursor = cursor.nextSibling ) )
  60. {
  61. if ( FCKListsLib.BlockElements[ cursor.nodeName.toLowerCase() ] )
  62. {
  63. if ( cursor.firstChild == bStart )
  64. FCKDomTools.InsertAfterNode( bStart, bEnd ) ;
  65. else
  66. FCKDomTools.MoveNode( bEnd, cursor, true ) ;
  67. }
  68. }
  69. }
  70. }
  71. var iterator = new FCKDomRangeIterator( range ) ;
  72. var block ;
  73. if ( state == FCK_TRISTATE_OFF )
  74. {
  75. var paragraphs = [] ;
  76. while ( ( block = iterator.GetNextParagraph() ) )
  77. paragraphs.push( block ) ;
  78. // If no paragraphs, create one from the current selection position.
  79. if ( paragraphs.length < 1 )
  80. {
  81. para = range.Window.document.createElement( FCKConfig.EnterMode.IEquals( 'p' ) ? 'p' : 'div' ) ;
  82. range.InsertNode( para ) ;
  83. para.appendChild( range.Window.document.createTextNode( 'ufeff' ) ) ;
  84. range.MoveToBookmark( bookmark ) ;
  85. range.MoveToNodeContents( para ) ;
  86. range.Collapse( true ) ;
  87. bookmark = range.CreateBookmark() ;
  88. paragraphs.push( para ) ;
  89. }
  90. // Make sure all paragraphs have the same parent.
  91. var commonParent = paragraphs[0].parentNode ;
  92. var tmp = [] ;
  93. for ( var i = 0 ; i < paragraphs.length ; i++ )
  94. {
  95. block = paragraphs[i] ;
  96. commonParent = FCKDomTools.GetCommonParents( block.parentNode, commonParent ).pop() ;
  97. }
  98. // The common parent must not be the following tags: table, tbody, tr, ol, ul.
  99. while ( commonParent.nodeName.IEquals( 'table', 'tbody', 'tr', 'ol', 'ul' ) )
  100. commonParent = commonParent.parentNode ;
  101. // Reconstruct the block list to be processed such that all resulting blocks
  102. // satisfy parentNode == commonParent.
  103. var lastBlock = null ;
  104. while ( paragraphs.length > 0 )
  105. {
  106. block = paragraphs.shift() ;
  107. while ( block.parentNode != commonParent )
  108. block = block.parentNode ;
  109. if ( block != lastBlock )
  110. tmp.push( block ) ;
  111. lastBlock = block ;
  112. }
  113. // If any of the selected blocks is a blockquote, remove it to prevent nested blockquotes.
  114. while ( tmp.length > 0 )
  115. {
  116. block = tmp.shift() ;
  117. if ( block.nodeName.IEquals( 'blockquote' ) )
  118. {
  119. var docFrag = FCKTools.GetElementDocument( block ).createDocumentFragment() ;
  120. while ( block.firstChild )
  121. {
  122. docFrag.appendChild( block.removeChild( block.firstChild ) ) ;
  123. paragraphs.push( docFrag.lastChild ) ;
  124. }
  125. block.parentNode.replaceChild( docFrag, block ) ;
  126. }
  127. else
  128. paragraphs.push( block ) ;
  129. }
  130. // Now we have all the blocks to be included in a new blockquote node.
  131. var bqBlock = range.Window.document.createElement( 'blockquote' ) ;
  132. commonParent.insertBefore( bqBlock, paragraphs[0] ) ;
  133. while ( paragraphs.length > 0 )
  134. {
  135. block = paragraphs.shift() ;
  136. bqBlock.appendChild( block ) ;
  137. }
  138. }
  139. else if ( state == FCK_TRISTATE_ON )
  140. {
  141. var moveOutNodes = [] ;
  142. var elementMarkers = {} ;
  143. while ( ( block = iterator.GetNextParagraph() ) )
  144. {
  145. var bqParent = null ;
  146. var bqChild = null ;
  147. while ( block.parentNode )
  148. {
  149. if ( block.parentNode.nodeName.IEquals( 'blockquote' ) )
  150. {
  151. bqParent = block.parentNode ;
  152. bqChild = block ;
  153. break ;
  154. }
  155. block = block.parentNode ;
  156. }
  157. // Remember the blocks that were recorded down in the moveOutNodes array
  158. // to prevent duplicates.
  159. if ( bqParent && bqChild && !bqChild._fckblockquotemoveout )
  160. {
  161. moveOutNodes.push( bqChild ) ;
  162. FCKDomTools.SetElementMarker( elementMarkers, bqChild, '_fckblockquotemoveout', true ) ;
  163. }
  164. }
  165. FCKDomTools.ClearAllMarkers( elementMarkers ) ;
  166. var movedNodes = [] ;
  167. var processedBlockquoteBlocks = [], elementMarkers = {} ;
  168. var noBlockLeft = function( bqBlock )
  169. {
  170. for ( var i = 0 ; i < bqBlock.childNodes.length ; i++ )
  171. {
  172. if ( FCKListsLib.BlockElements[ bqBlock.childNodes[i].nodeName.toLowerCase() ] )
  173. return false ;
  174. }
  175. return true ;
  176. } ;
  177. while ( moveOutNodes.length > 0 )
  178. {
  179. var node = moveOutNodes.shift() ;
  180. var bqBlock = node.parentNode ;
  181. // If the node is located at the beginning or the end, just take it out without splitting.
  182. // Otherwise, split the blockquote node and move the paragraph in between the two blockquote nodes.
  183. if ( node == node.parentNode.firstChild )
  184. bqBlock.parentNode.insertBefore( bqBlock.removeChild( node ), bqBlock ) ;
  185. else if ( node == node.parentNode.lastChild )
  186. bqBlock.parentNode.insertBefore( bqBlock.removeChild( node ), bqBlock.nextSibling ) ;
  187. else
  188. FCKDomTools.BreakParent( node, node.parentNode, range ) ;
  189. // Remember the blockquote node so we can clear it later (if it becomes empty).
  190. if ( !bqBlock._fckbqprocessed )
  191. {
  192. processedBlockquoteBlocks.push( bqBlock ) ;
  193. FCKDomTools.SetElementMarker( elementMarkers, bqBlock, '_fckbqprocessed', true );
  194. }
  195. movedNodes.push( node ) ;
  196. }
  197. // Clear blockquote nodes that have become empty.
  198. for ( var i = processedBlockquoteBlocks.length - 1 ; i >= 0 ; i-- )
  199. {
  200. var bqBlock = processedBlockquoteBlocks[i] ;
  201. if ( noBlockLeft( bqBlock ) )
  202. FCKDomTools.RemoveNode( bqBlock ) ;
  203. }
  204. FCKDomTools.ClearAllMarkers( elementMarkers ) ;
  205. if ( FCKConfig.EnterMode.IEquals( 'br' ) )
  206. {
  207. while ( movedNodes.length )
  208. {
  209. var node = movedNodes.shift() ;
  210. var firstTime = true ;
  211. if ( node.nodeName.IEquals( 'div' ) )
  212. {
  213. var docFrag = FCKTools.GetElementDocument( node ).createDocumentFragment() ;
  214. var needBeginBr = firstTime && node.previousSibling &&
  215. !FCKListsLib.BlockBoundaries[node.previousSibling.nodeName.toLowerCase()] ;
  216. if ( firstTime && needBeginBr )
  217. docFrag.appendChild( FCKTools.GetElementDocument( node ).createElement( 'br' ) ) ;
  218. var needEndBr = node.nextSibling &&
  219. !FCKListsLib.BlockBoundaries[node.nextSibling.nodeName.toLowerCase()] ;
  220. while ( node.firstChild )
  221. docFrag.appendChild( node.removeChild( node.firstChild ) ) ;
  222. if ( needEndBr )
  223. docFrag.appendChild( FCKTools.GetElementDocument( node ).createElement( 'br' ) ) ;
  224. node.parentNode.replaceChild( docFrag, node ) ;
  225. firstTime = false ;
  226. }
  227. }
  228. }
  229. }
  230. range.MoveToBookmark( bookmark ) ;
  231. range.Select() ;
  232. FCK.Focus() ;
  233. FCK.Events.FireEvent( 'OnSelectionChange' ) ;
  234. },
  235. GetState : function()
  236. {
  237. // Disabled if not WYSIWYG.
  238. if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG || ! FCK.EditorWindow )
  239. return FCK_TRISTATE_DISABLED ;
  240. var path = new FCKElementPath( FCKSelection.GetBoundaryParentElement( true ) ) ;
  241. var firstBlock = path.Block || path.BlockLimit ;
  242. if ( !firstBlock || firstBlock.nodeName.toLowerCase() == 'body' )
  243. return FCK_TRISTATE_OFF ;
  244. // See if the first block has a blockquote parent.
  245. for ( var i = 0 ; i < path.Elements.length ; i++ )
  246. {
  247. if ( path.Elements[i].nodeName.IEquals( 'blockquote' ) )
  248. return FCK_TRISTATE_ON ;
  249. }
  250. return FCK_TRISTATE_OFF ;
  251. }
  252. } ;