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

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.  * Creation and initialization of the "FCK" object. This is the main object
  22.  * that represents an editor instance.
  23.  */
  24. // FCK represents the active editor instance.
  25. var FCK =
  26. {
  27. Name : FCKURLParams[ 'InstanceName' ],
  28. Status : FCK_STATUS_NOTLOADED,
  29. EditMode : FCK_EDITMODE_WYSIWYG,
  30. Toolbar : null,
  31. HasFocus : false,
  32. DataProcessor : new FCKDataProcessor(),
  33. GetInstanceObject : (function()
  34. {
  35. var w = window ;
  36. return function( name )
  37. {
  38. return w[name] ;
  39. }
  40. })(),
  41. AttachToOnSelectionChange : function( functionPointer )
  42. {
  43. this.Events.AttachEvent( 'OnSelectionChange', functionPointer ) ;
  44. },
  45. GetLinkedFieldValue : function()
  46. {
  47. return this.LinkedField.value ;
  48. },
  49. GetParentForm : function()
  50. {
  51. return this.LinkedField.form ;
  52. } ,
  53. // # START : IsDirty implementation
  54. StartupValue : '',
  55. IsDirty : function()
  56. {
  57. if ( this.EditMode == FCK_EDITMODE_SOURCE )
  58. return ( this.StartupValue != this.EditingArea.Textarea.value ) ;
  59. else
  60. {
  61. // It can happen switching between design and source mode in Gecko
  62. if ( ! this.EditorDocument )
  63. return false ;
  64. return ( this.StartupValue != this.EditorDocument.body.innerHTML ) ;
  65. }
  66. },
  67. ResetIsDirty : function()
  68. {
  69. if ( this.EditMode == FCK_EDITMODE_SOURCE )
  70. this.StartupValue = this.EditingArea.Textarea.value ;
  71. else if ( this.EditorDocument.body )
  72. this.StartupValue = this.EditorDocument.body.innerHTML ;
  73. },
  74. // # END : IsDirty implementation
  75. StartEditor : function()
  76. {
  77. this.TempBaseTag = FCKConfig.BaseHref.length > 0 ? '<base href="' + FCKConfig.BaseHref + '" _fcktemp="true"></base>' : '' ;
  78. // Setup the keystroke handler.
  79. var oKeystrokeHandler = FCK.KeystrokeHandler = new FCKKeystrokeHandler() ;
  80. oKeystrokeHandler.OnKeystroke = _FCK_KeystrokeHandler_OnKeystroke ;
  81. // Set the config keystrokes.
  82. oKeystrokeHandler.SetKeystrokes( FCKConfig.Keystrokes ) ;
  83. // In IE7, if the editor tries to access the clipboard by code, a dialog is
  84. // shown to the user asking if the application is allowed to access or not.
  85. // Due to the IE implementation of it, the KeystrokeHandler will not work
  86. //well in this case, so we must leave the pasting keys to have their default behavior.
  87. if ( FCKBrowserInfo.IsIE7 )
  88. {
  89. if ( ( CTRL + 86 /*V*/ ) in oKeystrokeHandler.Keystrokes )
  90. oKeystrokeHandler.SetKeystrokes( [ CTRL + 86, true ] ) ;
  91. if ( ( SHIFT + 45 /*INS*/ ) in oKeystrokeHandler.Keystrokes )
  92. oKeystrokeHandler.SetKeystrokes( [ SHIFT + 45, true ] ) ;
  93. }
  94. // Retain default behavior for Ctrl-Backspace. (Bug #362)
  95. oKeystrokeHandler.SetKeystrokes( [ CTRL + 8, true ] ) ;
  96. this.EditingArea = new FCKEditingArea( document.getElementById( 'xEditingArea' ) ) ;
  97. this.EditingArea.FFSpellChecker = FCKConfig.FirefoxSpellChecker ;
  98. // Set the editor's startup contents.
  99. this.SetData( this.GetLinkedFieldValue(), true ) ;
  100. // Tab key handling for source mode.
  101. FCKTools.AddEventListener( document, "keydown", this._TabKeyHandler ) ;
  102. // Add selection change listeners. They must be attached only once.
  103. this.AttachToOnSelectionChange( _FCK_PaddingNodeListener ) ;
  104. if ( FCKBrowserInfo.IsGecko )
  105. this.AttachToOnSelectionChange( this._ExecCheckEmptyBlock ) ;
  106. },
  107. Focus : function()
  108. {
  109. FCK.EditingArea.Focus() ;
  110. },
  111. SetStatus : function( newStatus )
  112. {
  113. this.Status = newStatus ;
  114. if ( newStatus == FCK_STATUS_ACTIVE )
  115. {
  116. FCKFocusManager.AddWindow( window, true ) ;
  117. if ( FCKBrowserInfo.IsIE )
  118. FCKFocusManager.AddWindow( window.frameElement, true ) ;
  119. // Force the focus in the editor.
  120. if ( FCKConfig.StartupFocus )
  121. FCK.Focus() ;
  122. }
  123. this.Events.FireEvent( 'OnStatusChange', newStatus ) ;
  124. },
  125. // Fixes the body by moving all inline and text nodes to appropriate block
  126. // elements.
  127. FixBody : function()
  128. {
  129. var sBlockTag = FCKConfig.EnterMode ;
  130. // In 'br' mode, no fix must be done.
  131. if ( sBlockTag != 'p' && sBlockTag != 'div' )
  132. return ;
  133. var oDocument = this.EditorDocument ;
  134. if ( !oDocument )
  135. return ;
  136. var oBody = oDocument.body ;
  137. if ( !oBody )
  138. return ;
  139. FCKDomTools.TrimNode( oBody ) ;
  140. var oNode = oBody.firstChild ;
  141. var oNewBlock ;
  142. while ( oNode )
  143. {
  144. var bMoveNode = false ;
  145. switch ( oNode.nodeType )
  146. {
  147. // Element Node.
  148. case 1 :
  149. var nodeName = oNode.nodeName.toLowerCase() ;
  150. if ( !FCKListsLib.BlockElements[ nodeName ] &&
  151. nodeName != 'li' &&
  152. !oNode.getAttribute('_fckfakelement') &&
  153. oNode.getAttribute('_moz_dirty') == null )
  154. bMoveNode = true ;
  155. break ;
  156. // Text Node.
  157. case 3 :
  158. // Ignore space only or empty text.
  159. if ( oNewBlock || oNode.nodeValue.Trim().length > 0 )
  160. bMoveNode = true ;
  161. break;
  162. // Comment Node
  163. case 8 :
  164. if ( oNewBlock )
  165. bMoveNode = true ;
  166. break;
  167. }
  168. if ( bMoveNode )
  169. {
  170. var oParent = oNode.parentNode ;
  171. if ( !oNewBlock )
  172. oNewBlock = oParent.insertBefore( oDocument.createElement( sBlockTag ), oNode ) ;
  173. oNewBlock.appendChild( oParent.removeChild( oNode ) ) ;
  174. oNode = oNewBlock.nextSibling ;
  175. }
  176. else
  177. {
  178. if ( oNewBlock )
  179. {
  180. FCKDomTools.TrimNode( oNewBlock ) ;
  181. oNewBlock = null ;
  182. }
  183. oNode = oNode.nextSibling ;
  184. }
  185. }
  186. if ( oNewBlock )
  187. FCKDomTools.TrimNode( oNewBlock ) ;
  188. },
  189. GetData : function( format )
  190. {
  191. // We assume that if the user is in source editing, the editor value must
  192. // represent the exact contents of the source, as the user wanted it to be.
  193. if ( FCK.EditMode == FCK_EDITMODE_SOURCE )
  194. return FCK.EditingArea.Textarea.value ;
  195. this.FixBody() ;
  196. var oDoc = FCK.EditorDocument ;
  197. if ( !oDoc )
  198. return null ;
  199. var isFullPage = FCKConfig.FullPage ;
  200. // Call the Data Processor to generate the output data.
  201. var data = FCK.DataProcessor.ConvertToDataFormat(
  202. isFullPage ? oDoc.documentElement : oDoc.body,
  203. !isFullPage,
  204. FCKConfig.IgnoreEmptyParagraphValue,
  205. format ) ;
  206. // Restore protected attributes.
  207. data = FCK.ProtectEventsRestore( data ) ;
  208. if ( FCKBrowserInfo.IsIE )
  209. data = data.replace( FCKRegexLib.ToReplace, '$1' ) ;
  210. if ( isFullPage )
  211. {
  212. if ( FCK.DocTypeDeclaration && FCK.DocTypeDeclaration.length > 0 )
  213. data = FCK.DocTypeDeclaration + 'n' + data ;
  214. if ( FCK.XmlDeclaration && FCK.XmlDeclaration.length > 0 )
  215. data = FCK.XmlDeclaration + 'n' + data ;
  216. }
  217. return FCKConfig.ProtectedSource.Revert( data ) ;
  218. },
  219. UpdateLinkedField : function()
  220. {
  221. var value = FCK.GetXHTML( FCKConfig.FormatOutput ) ;
  222. if ( FCKConfig.HtmlEncodeOutput )
  223. value = FCKTools.HTMLEncode( value ) ;
  224. FCK.LinkedField.value = value ;
  225. FCK.Events.FireEvent( 'OnAfterLinkedFieldUpdate' ) ;
  226. },
  227. RegisteredDoubleClickHandlers : new Object(),
  228. OnDoubleClick : function( element )
  229. {
  230. var oCalls = FCK.RegisteredDoubleClickHandlers[ element.tagName.toUpperCase() ] ;
  231. if ( oCalls )
  232. {
  233. for ( var i = 0 ; i < oCalls.length ; i++ )
  234. oCalls[ i ]( element ) ;
  235. }
  236. // Generic handler for any element
  237. oCalls = FCK.RegisteredDoubleClickHandlers[ '*' ] ;
  238. if ( oCalls )
  239. {
  240. for ( var i = 0 ; i < oCalls.length ; i++ )
  241. oCalls[ i ]( element ) ;
  242. }
  243. },
  244. // Register objects that can handle double click operations.
  245. RegisterDoubleClickHandler : function( handlerFunction, tag )
  246. {
  247. var nodeName = tag || '*' ;
  248. nodeName = nodeName.toUpperCase() ;
  249. var aTargets ;
  250. if ( !( aTargets = FCK.RegisteredDoubleClickHandlers[ nodeName ] ) )
  251. FCK.RegisteredDoubleClickHandlers[ nodeName ] = [ handlerFunction ] ;
  252. else
  253. {
  254. // Check that the event handler isn't already registered with the same listener
  255. // It doesn't detect function pointers belonging to an object (at least in Gecko)
  256. if ( aTargets.IndexOf( handlerFunction ) == -1 )
  257. aTargets.push( handlerFunction ) ;
  258. }
  259. },
  260. OnAfterSetHTML : function()
  261. {
  262. FCKDocumentProcessor.Process( FCK.EditorDocument ) ;
  263. FCKUndo.SaveUndoStep() ;
  264. FCK.Events.FireEvent( 'OnSelectionChange' ) ;
  265. FCK.Events.FireEvent( 'OnAfterSetHTML' ) ;
  266. },
  267. // Saves URLs on links and images on special attributes, so they don't change when
  268. // moving around.
  269. ProtectUrls : function( html )
  270. {
  271. // <A> href
  272. html = html.replace( FCKRegexLib.ProtectUrlsA , '$& _fcksavedurl=$1' ) ;
  273. // <IMG> src
  274. html = html.replace( FCKRegexLib.ProtectUrlsImg , '$& _fcksavedurl=$1' ) ;
  275. // <AREA> href
  276. html = html.replace( FCKRegexLib.ProtectUrlsArea , '$& _fcksavedurl=$1' ) ;
  277. return html ;
  278. },
  279. // Saves event attributes (like onclick) so they don't get executed while
  280. // editing.
  281. ProtectEvents : function( html )
  282. {
  283. return html.replace( FCKRegexLib.TagsWithEvent, _FCK_ProtectEvents_ReplaceTags ) ;
  284. },
  285. ProtectEventsRestore : function( html )
  286. {
  287. return html.replace( FCKRegexLib.ProtectedEvents, _FCK_ProtectEvents_RestoreEvents ) ;
  288. },
  289. ProtectTags : function( html )
  290. {
  291. var sTags = FCKConfig.ProtectedTags ;
  292. // IE doesn't support <abbr> and it breaks it. Let's protect it.
  293. if ( FCKBrowserInfo.IsIE )
  294. sTags += sTags.length > 0 ? '|ABBR|XML|EMBED|OBJECT' : 'ABBR|XML|EMBED|OBJECT' ;
  295. var oRegex ;
  296. if ( sTags.length > 0 )
  297. {
  298. oRegex = new RegExp( '<(' + sTags + ')(?!w|:)', 'gi' ) ;
  299. html = html.replace( oRegex, '<FCK:$1' ) ;
  300. oRegex = new RegExp( '</(' + sTags + ')>', 'gi' ) ;
  301. html = html.replace( oRegex, '</FCK:$1>' ) ;
  302. }
  303. // Protect some empty elements. We must do it separately because the
  304. // original tag may not contain the closing slash, like <hr>:
  305. // - <meta> tags get executed, so if you have a redirect meta, the
  306. //   content will move to the target page.
  307. // - <hr> may destroy the document structure if not well
  308. //   positioned. The trick is protect it here and restore them in
  309. //   the FCKDocumentProcessor.
  310. sTags = 'META' ;
  311. if ( FCKBrowserInfo.IsIE )
  312. sTags += '|HR' ;
  313. oRegex = new RegExp( '<((' + sTags + ')(?=\s|>|/)[\s\S]*?)/?>', 'gi' ) ;
  314. html = html.replace( oRegex, '<FCK:$1 />' ) ;
  315. return html ;
  316. },
  317. SetData : function( data, resetIsDirty )
  318. {
  319. this.EditingArea.Mode = FCK.EditMode ;
  320. // If there was an onSelectionChange listener in IE we must remove it to avoid crashes #1498
  321. if ( FCKBrowserInfo.IsIE && FCK.EditorDocument )
  322. {
  323. FCK.EditorDocument.detachEvent("onselectionchange", Doc_OnSelectionChange ) ;
  324. }
  325. FCKTempBin.Reset() ;
  326. // Bug #2469: SelectionData.createRange becomes undefined after the editor
  327. // iframe is changed by FCK.SetData().
  328. FCK.Selection.Release() ;
  329. if ( FCK.EditMode == FCK_EDITMODE_WYSIWYG )
  330. {
  331. // Save the resetIsDirty for later use (async)
  332. this._ForceResetIsDirty = ( resetIsDirty === true ) ;
  333. // Protect parts of the code that must remain untouched (and invisible)
  334. // during editing.
  335. data = FCKConfig.ProtectedSource.Protect( data ) ;
  336. // Call the Data Processor to transform the data.
  337. data = FCK.DataProcessor.ConvertToHtml( data ) ;
  338. // Fix for invalid self-closing tags (see #152).
  339. data = data.replace( FCKRegexLib.InvalidSelfCloseTags, '$1></$2>' ) ;
  340. // Protect event attributes (they could get fired in the editing area).
  341. data = FCK.ProtectEvents( data ) ;
  342. // Protect some things from the browser itself.
  343. data = FCK.ProtectUrls( data ) ;
  344. data = FCK.ProtectTags( data ) ;
  345. // Insert the base tag (FCKConfig.BaseHref), if not exists in the source.
  346. // The base must be the first tag in the HEAD, to get relative
  347. // links on styles, for example.
  348. if ( FCK.TempBaseTag.length > 0 && !FCKRegexLib.HasBaseTag.test( data ) )
  349. data = data.replace( FCKRegexLib.HeadOpener, '$&' + FCK.TempBaseTag ) ;
  350. // Build the HTML for the additional things we need on <head>.
  351. var sHeadExtra = '' ;
  352. if ( !FCKConfig.FullPage )
  353. sHeadExtra += _FCK_GetEditorAreaStyleTags() ;
  354. if ( FCKBrowserInfo.IsIE )
  355. sHeadExtra += FCK._GetBehaviorsStyle() ;
  356. else if ( FCKConfig.ShowBorders )
  357. sHeadExtra += FCKTools.GetStyleHtml( FCK_ShowTableBordersCSS, true ) ;
  358. sHeadExtra += FCKTools.GetStyleHtml( FCK_InternalCSS, true ) ;
  359. // Attention: do not change it before testing it well (sample07)!
  360. // This is tricky... if the head ends with <meta ... content type>,
  361. // Firefox will break. But, it works if we place our extra stuff as
  362. // the last elements in the HEAD.
  363. data = data.replace( FCKRegexLib.HeadCloser, sHeadExtra + '$&' ) ;
  364. // Load the HTML in the editing area.
  365. this.EditingArea.OnLoad = _FCK_EditingArea_OnLoad ;
  366. this.EditingArea.Start( data ) ;
  367. }
  368. else
  369. {
  370. // Remove the references to the following elements, as the editing area
  371. // IFRAME will be removed.
  372. FCK.EditorWindow = null ;
  373. FCK.EditorDocument = null ;
  374. FCKDomTools.PaddingNode = null ;
  375. this.EditingArea.OnLoad = null ;
  376. this.EditingArea.Start( data ) ;
  377. // Enables the context menu in the textarea.
  378. this.EditingArea.Textarea._FCKShowContextMenu = true ;
  379. // Removes the enter key handler.
  380. FCK.EnterKeyHandler = null ;
  381. if ( resetIsDirty )
  382. this.ResetIsDirty() ;
  383. // Listen for keystroke events.
  384. FCK.KeystrokeHandler.AttachToElement( this.EditingArea.Textarea ) ;
  385. this.EditingArea.Textarea.focus() ;
  386. FCK.Events.FireEvent( 'OnAfterSetHTML' ) ;
  387. }
  388. if ( FCKBrowserInfo.IsGecko )
  389. window.onresize() ;
  390. },
  391. // This collection is used by the browser specific implementations to tell
  392. // which named commands must be handled separately.
  393. RedirectNamedCommands : new Object(),
  394. ExecuteNamedCommand : function( commandName, commandParameter, noRedirect, noSaveUndo )
  395. {
  396. if ( !noSaveUndo )
  397. FCKUndo.SaveUndoStep() ;
  398. if ( !noRedirect && FCK.RedirectNamedCommands[ commandName ] != null )
  399. FCK.ExecuteRedirectedNamedCommand( commandName, commandParameter ) ;
  400. else
  401. {
  402. FCK.Focus() ;
  403. FCK.EditorDocument.execCommand( commandName, false, commandParameter ) ;
  404. FCK.Events.FireEvent( 'OnSelectionChange' ) ;
  405. }
  406. if ( !noSaveUndo )
  407. FCKUndo.SaveUndoStep() ;
  408. },
  409. GetNamedCommandState : function( commandName )
  410. {
  411. try
  412. {
  413. // Bug #50 : Safari never returns positive state for the Paste command, override that.
  414. if ( FCKBrowserInfo.IsSafari && FCK.EditorWindow && commandName.IEquals( 'Paste' ) )
  415. return FCK_TRISTATE_OFF ;
  416. if ( !FCK.EditorDocument.queryCommandEnabled( commandName ) )
  417. return FCK_TRISTATE_DISABLED ;
  418. else
  419. {
  420. return FCK.EditorDocument.queryCommandState( commandName ) ? FCK_TRISTATE_ON : FCK_TRISTATE_OFF ;
  421. }
  422. }
  423. catch ( e )
  424. {
  425. return FCK_TRISTATE_OFF ;
  426. }
  427. },
  428. GetNamedCommandValue : function( commandName )
  429. {
  430. var sValue = '' ;
  431. var eState = FCK.GetNamedCommandState( commandName ) ;
  432. if ( eState == FCK_TRISTATE_DISABLED )
  433. return null ;
  434. try
  435. {
  436. sValue = this.EditorDocument.queryCommandValue( commandName ) ;
  437. }
  438. catch(e) {}
  439. return sValue ? sValue : '' ;
  440. },
  441. Paste : function( _callListenersOnly )
  442. {
  443. // First call 'OnPaste' listeners.
  444. if ( FCK.Status != FCK_STATUS_COMPLETE || !FCK.Events.FireEvent( 'OnPaste' ) )
  445. return false ;
  446. // Then call the default implementation.
  447. return _callListenersOnly || FCK._ExecPaste() ;
  448. },
  449. PasteFromWord : function()
  450. {
  451. FCKDialog.OpenDialog( 'FCKDialog_Paste', FCKLang.PasteFromWord, 'dialog/fck_paste.html', 400, 330, 'Word' ) ;
  452. },
  453. Preview : function()
  454. {
  455. var sHTML ;
  456. if ( FCKConfig.FullPage )
  457. {
  458. if ( FCK.TempBaseTag.length > 0 )
  459. sHTML = FCK.TempBaseTag + FCK.GetXHTML() ;
  460. else
  461. sHTML = FCK.GetXHTML() ;
  462. }
  463. else
  464. {
  465. sHTML =
  466. FCKConfig.DocType +
  467. '<html dir="' + FCKConfig.ContentLangDirection + '">' +
  468. '<head>' +
  469. FCK.TempBaseTag +
  470. '<title>' + FCKLang.Preview + '</title>' +
  471. _FCK_GetEditorAreaStyleTags() +
  472. '</head><body' + FCKConfig.GetBodyAttributes() + '>' +
  473. FCK.GetXHTML() +
  474. '</body></html>' ;
  475. }
  476. var iWidth = FCKConfig.ScreenWidth * 0.8 ;
  477. var iHeight = FCKConfig.ScreenHeight * 0.7 ;
  478. var iLeft = ( FCKConfig.ScreenWidth - iWidth ) / 2 ;
  479. var sOpenUrl = '' ;
  480. if ( FCK_IS_CUSTOM_DOMAIN && FCKBrowserInfo.IsIE)
  481. {
  482. window._FCKHtmlToLoad = sHTML ;
  483. sOpenUrl = 'javascript:void( (function(){' +
  484. 'document.open() ;' +
  485. 'document.domain="' + document.domain + '" ;' +
  486. 'document.write( window.opener._FCKHtmlToLoad );' +
  487. 'document.close() ;' +
  488. 'window.opener._FCKHtmlToLoad = null ;' +
  489. '})() )' ;
  490. }
  491. var oWindow = window.open( sOpenUrl, null, 'toolbar=yes,location=no,status=yes,menubar=yes,scrollbars=yes,resizable=yes,width=' + iWidth + ',height=' + iHeight + ',left=' + iLeft ) ;
  492. if ( !FCK_IS_CUSTOM_DOMAIN || !FCKBrowserInfo.IsIE)
  493. {
  494. oWindow.document.write( sHTML );
  495. oWindow.document.close();
  496. }
  497. },
  498. SwitchEditMode : function( noUndo )
  499. {
  500. var bIsWysiwyg = ( FCK.EditMode == FCK_EDITMODE_WYSIWYG ) ;
  501. // Save the current IsDirty state, so we may restore it after the switch.
  502. var bIsDirty = FCK.IsDirty() ;
  503. var sHtml ;
  504. // Update the HTML in the view output to show, also update
  505. // FCKTempBin for IE to avoid #2263.
  506. if ( bIsWysiwyg )
  507. {
  508. FCKCommands.GetCommand( 'ShowBlocks' ).SaveState() ;
  509. if ( !noUndo && FCKBrowserInfo.IsIE )
  510. FCKUndo.SaveUndoStep() ;
  511. sHtml = FCK.GetXHTML( FCKConfig.FormatSource ) ;
  512. if ( FCKBrowserInfo.IsIE )
  513. FCKTempBin.ToHtml() ;
  514. if ( sHtml == null )
  515. return false ;
  516. }
  517. else
  518. sHtml = this.EditingArea.Textarea.value ;
  519. FCK.EditMode = bIsWysiwyg ? FCK_EDITMODE_SOURCE : FCK_EDITMODE_WYSIWYG ;
  520. FCK.SetData( sHtml, !bIsDirty ) ;
  521. // Set the Focus.
  522. FCK.Focus() ;
  523. // Update the toolbar (Running it directly causes IE to fail).
  524. FCKTools.RunFunction( FCK.ToolbarSet.RefreshModeState, FCK.ToolbarSet ) ;
  525. return true ;
  526. },
  527. InsertElement : function( element )
  528. {
  529. // The parameter may be a string (element name), so transform it in an element.
  530. if ( typeof element == 'string' )
  531. element = this.EditorDocument.createElement( element ) ;
  532. var elementName = element.nodeName.toLowerCase() ;
  533. FCKSelection.Restore() ;
  534. // Create a range for the selection. V3 will have a new selection
  535. // object that may internally supply this feature.
  536. var range = new FCKDomRange( this.EditorWindow ) ;
  537. // Move to the selection and delete it.
  538. range.MoveToSelection() ;
  539. range.DeleteContents() ;
  540. if ( FCKListsLib.BlockElements[ elementName ] != null )
  541. {
  542. if ( range.StartBlock )
  543. {
  544. if ( range.CheckStartOfBlock() )
  545. range.MoveToPosition( range.StartBlock, 3 ) ;
  546. else if ( range.CheckEndOfBlock() )
  547. range.MoveToPosition( range.StartBlock, 4 ) ;
  548. else
  549. range.SplitBlock() ;
  550. }
  551. range.InsertNode( element ) ;
  552. var next = FCKDomTools.GetNextSourceElement( element, false, null, [ 'hr','br','param','img','area','input' ], true ) ;
  553. // Be sure that we have something after the new element, so we can move the cursor there.
  554. if ( !next && FCKConfig.EnterMode != 'br')
  555. {
  556. next = this.EditorDocument.body.appendChild( this.EditorDocument.createElement( FCKConfig.EnterMode ) ) ;
  557. if ( FCKBrowserInfo.IsGeckoLike )
  558. FCKTools.AppendBogusBr( next ) ;
  559. }
  560. if ( FCKListsLib.EmptyElements[ elementName ] == null )
  561. range.MoveToElementEditStart( element ) ;
  562. else if ( next )
  563. range.MoveToElementEditStart( next ) ;
  564. else
  565. range.MoveToPosition( element, 4 ) ;
  566. if ( FCKBrowserInfo.IsGeckoLike )
  567. {
  568. if ( next )
  569. FCKDomTools.ScrollIntoView( next, false );
  570. FCKDomTools.ScrollIntoView( element, false );
  571. }
  572. }
  573. else
  574. {
  575. // Insert the node.
  576. range.InsertNode( element ) ;
  577. // Move the selection right after the new element.
  578. // DISCUSSION: Should we select the element instead?
  579. range.SetStart( element, 4 ) ;
  580. range.SetEnd( element, 4 ) ;
  581. }
  582. range.Select() ;
  583. range.Release() ;
  584. // REMOVE IT: The focus should not really be set here. It is up to the
  585. // calling code to reset the focus if needed.
  586. this.Focus() ;
  587. return element ;
  588. },
  589. _InsertBlockElement : function( blockElement )
  590. {
  591. },
  592. _IsFunctionKey : function( keyCode )
  593. {
  594. // keys that are captured but do not change editor contents
  595. if ( keyCode >= 16 && keyCode <= 20 )
  596. // shift, ctrl, alt, pause, capslock
  597. return true ;
  598. if ( keyCode == 27 || ( keyCode >= 33 && keyCode <= 40 ) )
  599. // esc, page up, page down, end, home, left, up, right, down
  600. return true ;
  601. if ( keyCode == 45 )
  602. // insert, no effect on FCKeditor, yet
  603. return true ;
  604. return false ;
  605. },
  606. _KeyDownListener : function( evt )
  607. {
  608. if (! evt)
  609. evt = FCK.EditorWindow.event ;
  610. if ( FCK.EditorWindow )
  611. {
  612. if ( !FCK._IsFunctionKey(evt.keyCode) // do not capture function key presses, like arrow keys or shift/alt/ctrl
  613. && !(evt.ctrlKey || evt.metaKey) // do not capture Ctrl hotkeys, as they have their snapshot capture logic
  614. && !(evt.keyCode == 46) ) // do not capture Del, it has its own capture logic in fckenterkey.js
  615. FCK._KeyDownUndo() ;
  616. }
  617. return true ;
  618. },
  619. _KeyDownUndo : function()
  620. {
  621. if ( !FCKUndo.Typing )
  622. {
  623. FCKUndo.SaveUndoStep() ;
  624. FCKUndo.Typing = true ;
  625. FCK.Events.FireEvent( "OnSelectionChange" ) ;
  626. }
  627. FCKUndo.TypesCount++ ;
  628. FCKUndo.Changed = 1 ;
  629. if ( FCKUndo.TypesCount > FCKUndo.MaxTypes )
  630. {
  631. FCKUndo.TypesCount = 0 ;
  632. FCKUndo.SaveUndoStep() ;
  633. }
  634. },
  635. _TabKeyHandler : function( evt )
  636. {
  637. if ( ! evt )
  638. evt = window.event ;
  639. var keystrokeValue = evt.keyCode ;
  640. // Pressing <Tab> in source mode should produce a tab space in the text area, not
  641. // changing the focus to something else.
  642. if ( keystrokeValue == 9 && FCK.EditMode != FCK_EDITMODE_WYSIWYG )
  643. {
  644. if ( FCKBrowserInfo.IsIE )
  645. {
  646. var range = document.selection.createRange() ;
  647. if ( range.parentElement() != FCK.EditingArea.Textarea )
  648. return true ;
  649. range.text = 't' ;
  650. range.select() ;
  651. }
  652. else
  653. {
  654. var a = [] ;
  655. var el = FCK.EditingArea.Textarea ;
  656. var selStart = el.selectionStart ;
  657. var selEnd = el.selectionEnd ;
  658. a.push( el.value.substr(0, selStart ) ) ;
  659. a.push( 't' ) ;
  660. a.push( el.value.substr( selEnd ) ) ;
  661. el.value = a.join( '' ) ;
  662. el.setSelectionRange( selStart + 1, selStart + 1 ) ;
  663. }
  664. if ( evt.preventDefault )
  665. return evt.preventDefault() ;
  666. return evt.returnValue = false ;
  667. }
  668. return true ;
  669. }
  670. } ;
  671. FCK.Events = new FCKEvents( FCK ) ;
  672. // DEPRECATED in favor or "GetData".
  673. FCK.GetHTML = FCK.GetXHTML = FCK.GetData ;
  674. // DEPRECATED in favor of "SetData".
  675. FCK.SetHTML = FCK.SetData ;
  676. // InsertElementAndGetIt and CreateElement are Deprecated : returns the same value as InsertElement.
  677. FCK.InsertElementAndGetIt = FCK.CreateElement = FCK.InsertElement ;
  678. // Replace all events attributes (like onclick).
  679. function _FCK_ProtectEvents_ReplaceTags( tagMatch )
  680. {
  681. return tagMatch.replace( FCKRegexLib.EventAttributes, _FCK_ProtectEvents_ReplaceEvents ) ;
  682. }
  683. // Replace an event attribute with its respective __fckprotectedatt attribute.
  684. // The original event markup will be encoded and saved as the value of the new
  685. // attribute.
  686. function _FCK_ProtectEvents_ReplaceEvents( eventMatch, attName )
  687. {
  688. return ' ' + attName + '_fckprotectedatt="' + encodeURIComponent( eventMatch ) + '"' ;
  689. }
  690. function _FCK_ProtectEvents_RestoreEvents( match, encodedOriginal )
  691. {
  692. return decodeURIComponent( encodedOriginal ) ;
  693. }
  694. function _FCK_MouseEventsListener( evt )
  695. {
  696. if ( ! evt )
  697. evt = window.event ;
  698. if ( evt.type == 'mousedown' )
  699. FCK.MouseDownFlag = true ;
  700. else if ( evt.type == 'mouseup' )
  701. FCK.MouseDownFlag = false ;
  702. else if ( evt.type == 'mousemove' )
  703. FCK.Events.FireEvent( 'OnMouseMove', evt ) ;
  704. }
  705. function _FCK_PaddingNodeListener()
  706. {
  707. if ( FCKConfig.EnterMode.IEquals( 'br' ) )
  708. return ;
  709. FCKDomTools.EnforcePaddingNode( FCK.EditorDocument, FCKConfig.EnterMode ) ;
  710. if ( ! FCKBrowserInfo.IsIE && FCKDomTools.PaddingNode )
  711. {
  712. // Prevent the caret from going between the body and the padding node in Firefox.
  713. // i.e. <body>|<p></p></body>
  714. var sel = FCKSelection.GetSelection() ;
  715. if ( sel && sel.rangeCount == 1 )
  716. {
  717. var range = sel.getRangeAt( 0 ) ;
  718. if ( range.collapsed && range.startContainer == FCK.EditorDocument.body && range.startOffset == 0 )
  719. {
  720. range.selectNodeContents( FCKDomTools.PaddingNode ) ;
  721. range.collapse( true ) ;
  722. sel.removeAllRanges() ;
  723. sel.addRange( range ) ;
  724. }
  725. }
  726. }
  727. else if ( FCKDomTools.PaddingNode )
  728. {
  729. // Prevent the caret from going into an empty body but not into the padding node in IE.
  730. // i.e. <body><p></p>|</body>
  731. var parentElement = FCKSelection.GetParentElement() ;
  732. var paddingNode = FCKDomTools.PaddingNode ;
  733. if ( parentElement && parentElement.nodeName.IEquals( 'body' ) )
  734. {
  735. if ( FCK.EditorDocument.body.childNodes.length == 1
  736. && FCK.EditorDocument.body.firstChild == paddingNode )
  737. {
  738. /*
  739.  * Bug #1764: Don't move the selection if the
  740.  * current selection isn't in the editor
  741.  * document.
  742.  */
  743. if ( FCKSelection._GetSelectionDocument( FCK.EditorDocument.selection ) != FCK.EditorDocument )
  744. return ;
  745. var range = FCK.EditorDocument.body.createTextRange() ;
  746. var clearContents = false ;
  747. if ( !paddingNode.childNodes.firstChild )
  748. {
  749. paddingNode.appendChild( FCKTools.GetElementDocument( paddingNode ).createTextNode( 'ufeff' ) ) ;
  750. clearContents = true ;
  751. }
  752. range.moveToElementText( paddingNode ) ;
  753. range.select() ;
  754. if ( clearContents )
  755. range.pasteHTML( '' ) ;
  756. }
  757. }
  758. }
  759. }
  760. function _FCK_EditingArea_OnLoad()
  761. {
  762. // Get the editor's window and document (DOM)
  763. FCK.EditorWindow = FCK.EditingArea.Window ;
  764. FCK.EditorDocument = FCK.EditingArea.Document ;
  765. if ( FCKBrowserInfo.IsIE )
  766. FCKTempBin.ToElements() ;
  767. FCK.InitializeBehaviors() ;
  768. // Listen for mousedown and mouseup events for tracking drag and drops.
  769. FCK.MouseDownFlag = false ;
  770. FCKTools.AddEventListener( FCK.EditorDocument, 'mousemove', _FCK_MouseEventsListener ) ;
  771. FCKTools.AddEventListener( FCK.EditorDocument, 'mousedown', _FCK_MouseEventsListener ) ;
  772. FCKTools.AddEventListener( FCK.EditorDocument, 'mouseup', _FCK_MouseEventsListener ) ;
  773. // Most of the CTRL key combos do not work under Safari for onkeydown and onkeypress (See #1119)
  774. // But we can use the keyup event to override some of these...
  775. if ( FCKBrowserInfo.IsSafari )
  776. {
  777. var undoFunc = function( evt )
  778. {
  779. if ( ! ( evt.ctrlKey || evt.metaKey ) )
  780. return ;
  781. if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG )
  782. return ;
  783. switch ( evt.keyCode )
  784. {
  785. case 89:
  786. FCKUndo.Redo() ;
  787. break ;
  788. case 90:
  789. FCKUndo.Undo() ;
  790. break ;
  791. }
  792. }
  793. FCKTools.AddEventListener( FCK.EditorDocument, 'keyup', undoFunc ) ;
  794. }
  795. // Create the enter key handler
  796. FCK.EnterKeyHandler = new FCKEnterKey( FCK.EditorWindow, FCKConfig.EnterMode, FCKConfig.ShiftEnterMode, FCKConfig.TabSpaces ) ;
  797. // Listen for keystroke events.
  798. FCK.KeystrokeHandler.AttachToElement( FCK.EditorDocument ) ;
  799. if ( FCK._ForceResetIsDirty )
  800. FCK.ResetIsDirty() ;
  801. // This is a tricky thing for IE. In some cases, even if the cursor is
  802. // blinking in the editing, the keystroke handler doesn't catch keyboard
  803. // events. We must activate the editing area to make it work. (#142).
  804. if ( FCKBrowserInfo.IsIE && FCK.HasFocus )
  805. FCK.EditorDocument.body.setActive() ;
  806. FCK.OnAfterSetHTML() ;
  807. // Restore show blocks status.
  808. FCKCommands.GetCommand( 'ShowBlocks' ).RestoreState() ;
  809. // Check if it is not a startup call, otherwise complete the startup.
  810. if ( FCK.Status != FCK_STATUS_NOTLOADED )
  811. return ;
  812. FCK.SetStatus( FCK_STATUS_ACTIVE ) ;
  813. }
  814. function _FCK_GetEditorAreaStyleTags()
  815. {
  816. return FCKTools.GetStyleHtml( FCKConfig.EditorAreaCSS ) +
  817. FCKTools.GetStyleHtml( FCKConfig.EditorAreaStyles ) ;
  818. }
  819. function _FCK_KeystrokeHandler_OnKeystroke( keystroke, keystrokeValue )
  820. {
  821. if ( FCK.Status != FCK_STATUS_COMPLETE )
  822. return false ;
  823. if ( FCK.EditMode == FCK_EDITMODE_WYSIWYG )
  824. {
  825. switch ( keystrokeValue )
  826. {
  827. case 'Paste' :
  828. return !FCK.Paste() ;
  829. case 'Cut' :
  830. FCKUndo.SaveUndoStep() ;
  831. return false ;
  832. }
  833. }
  834. else
  835. {
  836. // In source mode, some actions must have their default behavior.
  837. if ( keystrokeValue.Equals( 'Paste', 'Undo', 'Redo', 'SelectAll', 'Cut' ) )
  838. return false ;
  839. }
  840. // The return value indicates if the default behavior of the keystroke must
  841. // be cancelled. Let's do that only if the Execute() call explicitly returns "false".
  842. var oCommand = FCK.Commands.GetCommand( keystrokeValue ) ;
  843. // If the command is disabled then ignore the keystroke
  844. if ( oCommand.GetState() == FCK_TRISTATE_DISABLED )
  845. return false ;
  846. return ( oCommand.Execute.apply( oCommand, FCKTools.ArgumentsToArray( arguments, 2 ) ) !== false ) ;
  847. }
  848. // Set the FCK.LinkedField reference to the field that will be used to post the
  849. // editor data.
  850. (function()
  851. {
  852. // There is a bug on IE... getElementById returns any META tag that has the
  853. // name set to the ID you are looking for. So the best way in to get the array
  854. // by names and look for the correct one.
  855. // As ASP.Net generates a ID that is different from the Name, we must also
  856. // look for the field based on the ID (the first one is the ID).
  857. var oDocument = window.parent.document ;
  858. // Try to get the field using the ID.
  859. var eLinkedField = oDocument.getElementById( FCK.Name ) ;
  860. var i = 0;
  861. while ( eLinkedField || i == 0 )
  862. {
  863. if ( eLinkedField && eLinkedField.tagName.toLowerCase().Equals( 'input', 'textarea' ) )
  864. {
  865. FCK.LinkedField = eLinkedField ;
  866. break ;
  867. }
  868. eLinkedField = oDocument.getElementsByName( FCK.Name )[i++] ;
  869. }
  870. })() ;
  871. var FCKTempBin =
  872. {
  873. Elements : new Array(),
  874. AddElement : function( element )
  875. {
  876. var iIndex = this.Elements.length ;
  877. this.Elements[ iIndex ] = element ;
  878. return iIndex ;
  879. },
  880. RemoveElement : function( index )
  881. {
  882. var e = this.Elements[ index ] ;
  883. this.Elements[ index ] = null ;
  884. return e ;
  885. },
  886. Reset : function()
  887. {
  888. var i = 0 ;
  889. while ( i < this.Elements.length )
  890. this.Elements[ i++ ] = null ;
  891. this.Elements.length = 0 ;
  892. },
  893. ToHtml : function()
  894. {
  895. for ( var i = 0 ; i < this.Elements.length ; i++ )
  896. {
  897. this.Elements[i] = '<div>&nbsp;' + this.Elements[i].outerHTML + '</div>' ;
  898. this.Elements[i].isHtml = true ;
  899. }
  900. },
  901. ToElements : function()
  902. {
  903. var node = FCK.EditorDocument.createElement( 'div' ) ;
  904. for ( var i = 0 ; i < this.Elements.length ; i++ )
  905. {
  906. if ( this.Elements[i].isHtml )
  907. {
  908. node.innerHTML = this.Elements[i] ;
  909. this.Elements[i] = node.firstChild.removeChild( node.firstChild.lastChild ) ;
  910. }
  911. }
  912. }
  913. } ;
  914. // # Focus Manager: Manages the focus in the editor.
  915. var FCKFocusManager = FCK.FocusManager =
  916. {
  917. IsLocked : false,
  918. AddWindow : function( win, sendToEditingArea )
  919. {
  920. var oTarget ;
  921. if ( FCKBrowserInfo.IsIE )
  922. oTarget = win.nodeType == 1 ? win : win.frameElement ? win.frameElement : win.document ;
  923. else if ( FCKBrowserInfo.IsSafari )
  924. oTarget = win ;
  925. else
  926. oTarget = win.document ;
  927. FCKTools.AddEventListener( oTarget, 'blur', FCKFocusManager_Win_OnBlur ) ;
  928. FCKTools.AddEventListener( oTarget, 'focus', sendToEditingArea ? FCKFocusManager_Win_OnFocus_Area : FCKFocusManager_Win_OnFocus ) ;
  929. },
  930. RemoveWindow : function( win )
  931. {
  932. if ( FCKBrowserInfo.IsIE )
  933. oTarget = win.nodeType == 1 ? win : win.frameElement ? win.frameElement : win.document ;
  934. else
  935. oTarget = win.document ;
  936. FCKTools.RemoveEventListener( oTarget, 'blur', FCKFocusManager_Win_OnBlur ) ;
  937. FCKTools.RemoveEventListener( oTarget, 'focus', FCKFocusManager_Win_OnFocus_Area ) ;
  938. FCKTools.RemoveEventListener( oTarget, 'focus', FCKFocusManager_Win_OnFocus ) ;
  939. },
  940. Lock : function()
  941. {
  942. this.IsLocked = true ;
  943. },
  944. Unlock : function()
  945. {
  946. if ( this._HasPendingBlur )
  947. FCKFocusManager._Timer = window.setTimeout( FCKFocusManager_FireOnBlur, 100 ) ;
  948. this.IsLocked = false ;
  949. },
  950. _ResetTimer : function()
  951. {
  952. this._HasPendingBlur = false ;
  953. if ( this._Timer )
  954. {
  955. window.clearTimeout( this._Timer ) ;
  956. delete this._Timer ;
  957. }
  958. }
  959. } ;
  960. function FCKFocusManager_Win_OnBlur()
  961. {
  962. if ( typeof(FCK) != 'undefined' && FCK.HasFocus )
  963. {
  964. FCKFocusManager._ResetTimer() ;
  965. FCKFocusManager._Timer = window.setTimeout( FCKFocusManager_FireOnBlur, 100 ) ;
  966. }
  967. }
  968. function FCKFocusManager_FireOnBlur()
  969. {
  970. if ( FCKFocusManager.IsLocked )
  971. FCKFocusManager._HasPendingBlur = true ;
  972. else
  973. {
  974. FCK.HasFocus = false ;
  975. FCK.Events.FireEvent( "OnBlur" ) ;
  976. }
  977. }
  978. function FCKFocusManager_Win_OnFocus_Area()
  979. {
  980. // Check if we are already focusing the editor (to avoid loops).
  981. if ( FCKFocusManager._IsFocusing )
  982. return ;
  983. FCKFocusManager._IsFocusing = true ;
  984. FCK.Focus() ;
  985. FCKFocusManager_Win_OnFocus() ;
  986. // The above FCK.Focus() call may trigger other focus related functions.
  987. // So, to avoid a loop, we delay the focusing mark removal, so it get
  988. // executed after all othre functions have been run.
  989. FCKTools.RunFunction( function()
  990. {
  991. delete FCKFocusManager._IsFocusing ;
  992. } ) ;
  993. }
  994. function FCKFocusManager_Win_OnFocus()
  995. {
  996. FCKFocusManager._ResetTimer() ;
  997. if ( !FCK.HasFocus && !FCKFocusManager.IsLocked )
  998. {
  999. FCK.HasFocus = true ;
  1000. FCK.Events.FireEvent( "OnFocus" ) ;
  1001. }
  1002. }
  1003. /*
  1004.  * #1633 : Protect the editor iframe from external styles.
  1005.  * Notice that we can't use FCKTools.ResetStyles here since FCKTools isn't
  1006.  * loaded yet.
  1007.  */
  1008. (function()
  1009. {
  1010. var el = window.frameElement ;
  1011. var width = el.width ;
  1012. var height = el.height ;
  1013. if ( /^d+$/.test( width ) ) width += 'px' ;
  1014. if ( /^d+$/.test( height ) ) height += 'px' ;
  1015. var style = el.style ;
  1016. style.border = style.padding = style.margin = 0 ;
  1017. style.backgroundColor = 'transparent';
  1018. style.backgroundImage = 'none';
  1019. style.width = width ;
  1020. style.height = height ;
  1021. })() ;