fck.js
上传用户:ah_jiwei
上传日期:2022-07-24
资源大小:54044k
文件大小:29k
源码类别:

数据库编程

开发平台:

Visual C++

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