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

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.  * FCKEditingArea Class: renders an editable area.
  22.  */
  23. /**
  24.  * @constructor
  25.  * @param {String} targetElement The element that will hold the editing area. Any child element present in the target will be deleted.
  26.  */
  27. var FCKEditingArea = function( targetElement )
  28. {
  29. this.TargetElement = targetElement ;
  30. this.Mode = FCK_EDITMODE_WYSIWYG ;
  31. if ( FCK.IECleanup )
  32. FCK.IECleanup.AddItem( this, FCKEditingArea_Cleanup ) ;
  33. }
  34. /**
  35.  * @param {String} html The complete HTML for the page, including DOCTYPE and the <html> tag.
  36.  */
  37. FCKEditingArea.prototype.Start = function( html, secondCall )
  38. {
  39. var eTargetElement = this.TargetElement ;
  40. var oTargetDocument = FCKTools.GetElementDocument( eTargetElement ) ;
  41. // Remove all child nodes from the target.
  42. while( eTargetElement.firstChild )
  43. eTargetElement.removeChild( eTargetElement.firstChild ) ;
  44. if ( this.Mode == FCK_EDITMODE_WYSIWYG )
  45. {
  46. // For FF, document.domain must be set only when different, otherwhise
  47. // we'll strangely have "Permission denied" issues.
  48. if ( FCK_IS_CUSTOM_DOMAIN )
  49. html = '<script>document.domain="' + FCK_RUNTIME_DOMAIN + '";</script>' + html ;
  50. // IE has a bug with the <base> tag... it must have a </base> closer,
  51. // otherwise the all successive tags will be set as children nodes of the <base>.
  52. if ( FCKBrowserInfo.IsIE )
  53. html = html.replace( /(<base[^>]*?)s*/?>(?!s*</base>)/gi, '$1></base>' ) ;
  54. else if ( !secondCall )
  55. {
  56. // Gecko moves some tags out of the body to the head, so we must use
  57. // innerHTML to set the body contents (SF BUG 1526154).
  58. // Extract the BODY contents from the html.
  59. var oMatchBefore = html.match( FCKRegexLib.BeforeBody ) ;
  60. var oMatchAfter = html.match( FCKRegexLib.AfterBody ) ;
  61. if ( oMatchBefore && oMatchAfter )
  62. {
  63. var sBody = html.substr( oMatchBefore[1].length,
  64.        html.length - oMatchBefore[1].length - oMatchAfter[1].length ) ; // This is the BODY tag contents.
  65. html =
  66. oMatchBefore[1] + // This is the HTML until the <body...> tag, inclusive.
  67. '&nbsp;' +
  68. oMatchAfter[1] ; // This is the HTML from the </body> tag, inclusive.
  69. // If nothing in the body, place a BOGUS tag so the cursor will appear.
  70. if ( FCKBrowserInfo.IsGecko && ( sBody.length == 0 || FCKRegexLib.EmptyParagraph.test( sBody ) ) )
  71. sBody = '<br type="_moz">' ;
  72. this._BodyHTML = sBody ;
  73. }
  74. else
  75. this._BodyHTML = html ; // Invalid HTML input.
  76. }
  77. // Create the editing area IFRAME.
  78. var oIFrame = this.IFrame = oTargetDocument.createElement( 'iframe' ) ;
  79. // IE: Avoid JavaScript errors thrown by the editing are source (like tags events).
  80. // See #1055.
  81. var sOverrideError = '<script type="text/javascript" _fcktemp="true">window.onerror=function(){return true;};</script>' ;
  82. oIFrame.frameBorder = 0 ;
  83. oIFrame.style.width = oIFrame.style.height = '100%' ;
  84. if ( FCK_IS_CUSTOM_DOMAIN && FCKBrowserInfo.IsIE )
  85. {
  86. window._FCKHtmlToLoad = html.replace( /<head>/i, '<head>' + sOverrideError ) ;
  87. oIFrame.src = 'javascript:void( (function(){' +
  88. 'document.open() ;' +
  89. 'document.domain="' + document.domain + '" ;' +
  90. 'document.write( window.parent._FCKHtmlToLoad );' +
  91. 'document.close() ;' +
  92. 'window.parent._FCKHtmlToLoad = null ;' +
  93. '})() )' ;
  94. }
  95. else if ( !FCKBrowserInfo.IsGecko )
  96. {
  97. // Firefox will render the tables inside the body in Quirks mode if the
  98. // source of the iframe is set to javascript. see #515
  99. oIFrame.src = 'javascript:void(0)' ;
  100. }
  101. // Append the new IFRAME to the target. For IE, it must be done after
  102. // setting the "src", to avoid the "secure/unsecure" message under HTTPS.
  103. eTargetElement.appendChild( oIFrame ) ;
  104. // Get the window and document objects used to interact with the newly created IFRAME.
  105. this.Window = oIFrame.contentWindow ;
  106. // IE: Avoid JavaScript errors thrown by the editing are source (like tags events).
  107. // TODO: This error handler is not being fired.
  108. // this.Window.onerror = function() { alert( 'Error!' ) ; return true ; }
  109. if ( !FCK_IS_CUSTOM_DOMAIN || !FCKBrowserInfo.IsIE )
  110. {
  111. var oDoc = this.Window.document ;
  112. oDoc.open() ;
  113. oDoc.write( html.replace( /<head>/i, '<head>' + sOverrideError ) ) ;
  114. oDoc.close() ;
  115. }
  116. if ( FCKBrowserInfo.IsAIR )
  117. FCKAdobeAIR.EditingArea_Start( oDoc, html ) ;
  118. // Firefox 1.0.x is buggy... ohh yes... so let's do it two times and it
  119. // will magically work.
  120. if ( FCKBrowserInfo.IsGecko10 && !secondCall )
  121. {
  122. this.Start( html, true ) ;
  123. return ;
  124. }
  125. if ( oIFrame.readyState && oIFrame.readyState != 'completed' )
  126. {
  127. var editArea = this ;
  128. // Using a IE alternative for DOMContentLoaded, similar to the
  129. // solution proposed at http://javascript.nwbox.com/IEContentLoaded/
  130. setTimeout( function()
  131. {
  132. try
  133. {
  134. editArea.Window.document.documentElement.doScroll("left") ;
  135. }
  136. catch(e)
  137. {
  138. setTimeout( arguments.callee, 0 ) ;
  139. return ;
  140. }
  141. editArea.Window._FCKEditingArea = editArea ;
  142. FCKEditingArea_CompleteStart.call( editArea.Window ) ;
  143. }, 0 ) ;
  144. }
  145. else
  146. {
  147. this.Window._FCKEditingArea = this ;
  148. // FF 1.0.x is buggy... we must wait a lot to enable editing because
  149. // sometimes the content simply disappears, for example when pasting
  150. // "bla1!<img src='some_url'>!bla2" in the source and then switching
  151. // back to design.
  152. if ( FCKBrowserInfo.IsGecko10 )
  153. this.Window.setTimeout( FCKEditingArea_CompleteStart, 500 ) ;
  154. else
  155. FCKEditingArea_CompleteStart.call( this.Window ) ;
  156. }
  157. }
  158. else
  159. {
  160. var eTextarea = this.Textarea = oTargetDocument.createElement( 'textarea' ) ;
  161. eTextarea.className = 'SourceField' ;
  162. eTextarea.dir = 'ltr' ;
  163. FCKDomTools.SetElementStyles( eTextarea,
  164. {
  165. width : '100%',
  166. height : '100%',
  167. border : 'none',
  168. resize : 'none',
  169. outline : 'none'
  170. } ) ;
  171. eTargetElement.appendChild( eTextarea ) ;
  172. eTextarea.value = html  ;
  173. // Fire the "OnLoad" event.
  174. FCKTools.RunFunction( this.OnLoad ) ;
  175. }
  176. }
  177. // "this" here is FCKEditingArea.Window
  178. function FCKEditingArea_CompleteStart()
  179. {
  180. // On Firefox, the DOM takes a little to become available. So we must wait for it in a loop.
  181. if ( !this.document.body )
  182. {
  183. this.setTimeout( FCKEditingArea_CompleteStart, 50 ) ;
  184. return ;
  185. }
  186. var oEditorArea = this._FCKEditingArea ;
  187. // Save this reference to be re-used later.
  188. oEditorArea.Document = oEditorArea.Window.document ;
  189. oEditorArea.MakeEditable() ;
  190. // Fire the "OnLoad" event.
  191. FCKTools.RunFunction( oEditorArea.OnLoad ) ;
  192. }
  193. FCKEditingArea.prototype.MakeEditable = function()
  194. {
  195. var oDoc = this.Document ;
  196. if ( FCKBrowserInfo.IsIE )
  197. {
  198. // Kludge for #141 and #523
  199. oDoc.body.disabled = true ;
  200. oDoc.body.contentEditable = true ;
  201. oDoc.body.removeAttribute( "disabled" ) ;
  202. /* The following commands don't throw errors, but have no effect.
  203. oDoc.execCommand( 'AutoDetect', false, false ) ;
  204. oDoc.execCommand( 'KeepSelection', false, true ) ;
  205. */
  206. }
  207. else
  208. {
  209. try
  210. {
  211. // Disable Firefox 2 Spell Checker.
  212. oDoc.body.spellcheck = ( this.FFSpellChecker !== false ) ;
  213. if ( this._BodyHTML )
  214. {
  215. oDoc.body.innerHTML = this._BodyHTML ;
  216. oDoc.body.offsetLeft ; // Don't remove, this is a hack to fix Opera 9.50, see #2264.
  217. this._BodyHTML = null ;
  218. }
  219. oDoc.designMode = 'on' ;
  220. // Tell Gecko (Firefox 1.5+) to enable or not live resizing of objects (by Alfonso Martinez)
  221. oDoc.execCommand( 'enableObjectResizing', false, !FCKConfig.DisableObjectResizing ) ;
  222. // Disable the standard table editing features of Firefox.
  223. oDoc.execCommand( 'enableInlineTableEditing', false, !FCKConfig.DisableFFTableHandles ) ;
  224. }
  225. catch (e)
  226. {
  227. // In Firefox if the iframe is initially hidden it can't be set to designMode and it raises an exception
  228. // So we set up a DOM Mutation event Listener on the HTML, as it will raise several events when the document is  visible again
  229. FCKTools.AddEventListener( this.Window.frameElement, 'DOMAttrModified', FCKEditingArea_Document_AttributeNodeModified ) ;
  230. }
  231. }
  232. }
  233. // This function processes the notifications of the DOM Mutation event on the document
  234. // We use it to know that the document will be ready to be editable again (or we hope so)
  235. function FCKEditingArea_Document_AttributeNodeModified( evt )
  236. {
  237. var editingArea = evt.currentTarget.contentWindow._FCKEditingArea ;
  238. // We want to run our function after the events no longer fire, so we can know that it's a stable situation
  239. if ( editingArea._timer )
  240. window.clearTimeout( editingArea._timer ) ;
  241. editingArea._timer = FCKTools.SetTimeout( FCKEditingArea_MakeEditableByMutation, 1000, editingArea ) ;
  242. }
  243. // This function ideally should be called after the document is visible, it does clean up of the
  244. // mutation tracking and tries again to make the area editable.
  245. function FCKEditingArea_MakeEditableByMutation()
  246. {
  247. // Clean up
  248. delete this._timer ;
  249. // Now we don't want to keep on getting this event
  250. FCKTools.RemoveEventListener( this.Window.frameElement, 'DOMAttrModified', FCKEditingArea_Document_AttributeNodeModified ) ;
  251. // Let's try now to set the editing area editable
  252. // If it fails it will set up the Mutation Listener again automatically
  253. this.MakeEditable() ;
  254. }
  255. FCKEditingArea.prototype.Focus = function()
  256. {
  257. try
  258. {
  259. if ( this.Mode == FCK_EDITMODE_WYSIWYG )
  260. {
  261. if ( FCKBrowserInfo.IsIE )
  262. this._FocusIE() ;
  263. else
  264. this.Window.focus() ;
  265. }
  266. else
  267. {
  268. var oDoc = FCKTools.GetElementDocument( this.Textarea ) ;
  269. if ( (!oDoc.hasFocus || oDoc.hasFocus() ) && oDoc.activeElement == this.Textarea )
  270. return ;
  271. this.Textarea.focus() ;
  272. }
  273. }
  274. catch(e) {}
  275. }
  276. FCKEditingArea.prototype._FocusIE = function()
  277. {
  278. // In IE it can happen that the document is in theory focused but the
  279. // active element is outside of it.
  280. this.Document.body.setActive() ;
  281. this.Window.focus() ;
  282. // Kludge for #141... yet more code to workaround IE bugs
  283. var range = this.Document.selection.createRange() ;
  284. var parentNode = range.parentElement() ;
  285. var parentTag = parentNode.nodeName.toLowerCase() ;
  286. // Only apply the fix when in a block, and the block is empty.
  287. if ( parentNode.childNodes.length > 0 ||
  288.  !( FCKListsLib.BlockElements[parentTag] ||
  289.     FCKListsLib.NonEmptyBlockElements[parentTag] ) )
  290. {
  291. return ;
  292. }
  293. // Force the selection to happen, in this way we guarantee the focus will
  294. // be there.
  295. range = new FCKDomRange( this.Window ) ;
  296. range.MoveToElementEditStart( parentNode ) ;
  297. range.Select() ;
  298. }
  299. function FCKEditingArea_Cleanup()
  300. {
  301. if ( this.Document )
  302. this.Document.body.innerHTML = "" ;
  303. this.TargetElement = null ;
  304. this.IFrame = null ;
  305. this.Document = null ;
  306. this.Textarea = null ;
  307. if ( this.Window )
  308. {
  309. this.Window._FCKEditingArea = null ;
  310. this.Window = null ;
  311. }
  312. }