fckplugin.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  1. /*
  2. * MindTouch Deki - enterprise collaboration and integration platform
  3. * Copyright (C) 2006-2009 MindTouch, Inc.
  4. * www.mindtouch.com oss@mindtouch.com
  5. *
  6. * For community documentation and downloads visit www.opengarden.org;
  7. * please review the licensing section.
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License along
  20. * with this program; if not, write to the Free Software Foundation, Inc.,
  21. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  22. * http://www.gnu.org/copyleft/gpl.html
  23. */
  24. DimensionPicker = function(element, command, onPick) {
  25. this._minCols = 5;
  26. this._minRows = 5;
  27. this.show = function ( panelX, panelY, relElement )
  28. {
  29. this._panelX = panelX ;
  30. this._panelY = panelY ;
  31. this._relEl = relElement ;
  32. this._pick( 0, 0 ) ;
  33. };
  34. this.onPick = onPick;
  35. this._setDimensionInCells = function( element, cols, rows )
  36. {
  37. element.style.width = 18 * cols + 'px' ;
  38. element.style.height = 18 * rows + 'px' ;
  39. element.cols = cols ;
  40. element.rows = rows ;
  41. };
  42. this._init = function()
  43. {
  44. this._targetDoc = FCKTools.GetElementDocument( element ) ;
  45. this._picker = element ;
  46. this._command = command ;
  47. this._mouseDiv = this._targetDoc.createElement( 'div' ) ;
  48. this._mouseDiv.className = 'dimension-picker-mouse' ;
  49. this._uhDiv = this._targetDoc.createElement( 'div' ) ;
  50. this._uhDiv.className = 'dimension-picker-unhighlighted' ;
  51. this._hDiv = this._targetDoc.createElement( 'div' ) ;
  52. this._hDiv.className = 'dimension-picker-highlighted' ;
  53. this.statusDiv = this._targetDoc.createElement( 'div' ) ;
  54. this.statusDiv.className = 'dimension-picker-status' ;
  55. this._cellsDiv = this._targetDoc.createElement( 'div' ) ;
  56. this._picker.appendChild( this._cellsDiv ) ;
  57. this._picker.appendChild( this.statusDiv ) ;
  58. this._cellsDiv.appendChild( this._mouseDiv ) ;
  59. this._cellsDiv.appendChild( this._uhDiv ) ;
  60. this._cellsDiv.appendChild( this._hDiv ) ;
  61. var dimensionPicker = this ;
  62. var k = 0 ;
  63. FCKTools.AddEventListener(this._mouseDiv, 'mousemove', function ( event ) {
  64. var current = dimensionPicker._getCurrent( event ) ;
  65. if ( dimensionPicker._changed(current.cols, current.rows) )
  66. {
  67. dimensionPicker._pick( current.cols, current.rows ) ;
  68. }
  69. k++ ;
  70. });
  71. FCKTools.AddEventListener(this._picker, 'click', function ( event ) {
  72. var current = dimensionPicker._getCurrent( event ) ;
  73. dimensionPicker.onPick( command, { 'cols' : current.cols, 'rows' : current.rows } ) ;
  74. });
  75. };
  76. this._pick = function( cols, rows )
  77. {
  78. this._setDimensionInCells( this._hDiv, cols, rows ) ;
  79. var uhCols = Math.max( this._minCols, cols ) ;
  80. var uhRows = Math.max( this._minRows, rows ) ;
  81. this._setDimensionInCells( this._uhDiv, uhCols, uhRows ) ;
  82. this.statusDiv.innerHTML = rows + 'x' + cols ;
  83. if ( FCKBrowserInfo.IsIE )
  84. {
  85. this._mouseDiv.style.width = this._cellsDiv.offsetWidth + 18 + 'px' ;
  86. this._mouseDiv.style.height = this._cellsDiv.offsetHeight + 18 + 'px' ;
  87. }
  88. var pickerWidth = this._uhDiv.offsetWidth ;
  89. var pickerHeight = this._uhDiv.offsetHeight + this.statusDiv.offsetHeight ;
  90. pickerWidth += 14 ;
  91. pickerHeight += 14;
  92. if ( FCKBrowserInfo.IsIE )
  93. {
  94. this._command._Panel.Show( this._panelX, this._panelY, this._relEl, pickerWidth + 6, pickerHeight + 6 ) ;
  95. }
  96. else
  97. {
  98. this._command._Panel._IFrame.style.width = pickerWidth + 6 + 'px' ;
  99. this._command._Panel._IFrame.style.height = pickerHeight + 6 + 'px' ;
  100. }
  101. this._command._Panel.MainNode.style.width = pickerWidth + 'px' ;
  102. this._command._Panel.MainNode.style.height = pickerHeight + 'px' ;
  103. this._picker.style.width = pickerWidth ;
  104. this._picker.style.height = pickerHeight ;
  105. };
  106. this._getCurrent = function( event )
  107. {
  108. var offset = FCKTools.GetElementPosition( this._cellsDiv, FCKTools.GetDocumentWindow(this._targetDoc) ) ;
  109. var mousePos = FCKTools.GetMousePosition( event ) ;
  110. var x = mousePos.X - offset.X ;
  111. var y = mousePos.Y - offset.Y ;
  112. if ( x <= 0 || y <= 0 )
  113. {
  114. x = y = 0 ;
  115. }
  116. var cols = Math.ceil( x / 18.0 ) ;
  117. var rows = Math.ceil( y / 18.0 ) ;
  118. return { cols: cols, rows: rows } ;
  119. };
  120. this._changed = function( cols, rows )
  121. {
  122. if ( cols != this._lastCols || rows != this._lastRows )
  123. {
  124. this._lastCols = cols ;
  125. this._lastRows = rows ;
  126. return true ;
  127. }
  128. return false ;
  129. };
  130. this._init();
  131. this._lastCols = null;
  132. this._lastRows = null;
  133. };
  134. // from quirksmode.org
  135. FCKTools.GetEventTarget = function( e )
  136. {
  137. var target = null ;
  138. if ( !e )
  139. var e = window.event ;
  140. if ( e.target )
  141. target = e.target ;
  142. else if ( e.srcElement )
  143. target = e.srcElement ;
  144. if ( target && target.nodeType == 3 ) // defeat Safari bug
  145. target = target.parentNode ;
  146. return target ;
  147. }
  148. // from quirksmode.org
  149. FCKTools.GetMousePosition = function( e )
  150. {
  151. var posx = 0 ;
  152. var posy = 0 ;
  153. if ( !e )
  154. var e = window.event ;
  155. if ( e.pageX || e.pageY )
  156. {
  157. posx = e.pageX ;
  158. posy = e.pageY ;
  159. }
  160. else if ( e.clientX || e.clientY )
  161. {
  162. posx = e.clientX + document.body.scrollLeft
  163. + document.documentElement.scrollLeft ;
  164. posy = e.clientY + document.body.scrollTop
  165. + document.documentElement.scrollTop ;
  166. }
  167. return { X : posx, Y : posy } ;
  168. }
  169. var TableDimensionPickerCommand = function( oToolbarSet )
  170. {
  171. this.Name = 'TableOC' ;
  172. this.Type = 'TableOC' ;
  173. var oWindow ;
  174. if ( FCKBrowserInfo.IsIE )
  175. oWindow = window ;
  176. else if ( oToolbarSet._IFrame )
  177. oWindow = FCKTools.GetElementWindow( oToolbarSet._IFrame ) ;
  178. else
  179. oWindow = window.parent ;
  180. this._Panel = new FCKPanel( oWindow ) ;
  181. this._Panel.AppendStyleSheet( FCKConfig.SkinEditorCSS ) ;
  182. this._Panel.AppendStyleSheet( FCKConfig.PluginsPath + 'tableoneclick/css/style.css' ) ;
  183. this._Panel.MainNode.className = 'FCK_Panel' ;
  184. this._CreatePanelBody( this._Panel.Document, this._Panel.MainNode ) ;
  185. oToolbarSet.ToolbarItems.GetItem( this.Name ).RegisterPanel( this._Panel ) ;
  186. FCKTools.DisableSelection( this._Panel.Document.body ) ;
  187. }
  188. TableDimensionPickerCommand.prototype.Execute = function( panelX, panelY, relElement )
  189. {
  190. this._Panel.Show( panelX, panelY, relElement ) ;
  191. this._Picker.show( panelX, panelY, relElement ) ;
  192. }
  193. TableDimensionPickerCommand.prototype.GetState = function()
  194. {
  195. if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG )
  196. return FCK_TRISTATE_DISABLED ;
  197. return FCK_TRISTATE_OFF ;
  198. }
  199. function TableDimensionPickerCommand_OnClick( command, dimension )
  200. {
  201. if ( dimension.cols > 0 && dimension.rows > 0 )
  202. {
  203. FCKUndo.SaveUndoStep() ;
  204. var oDoc = FCK.EditorDocument ;
  205. var oTable = oDoc.createElement( 'TABLE' ) ;
  206. oTable.style.width = '100%' ;
  207. oTable.style.tableLayout = 'fixed' ;
  208. oTable.setAttribute( 'cellPadding', 1 ) ;
  209. oTable.setAttribute( 'cellSpacing', 1 ) ;
  210. oTable.setAttribute( 'border', 1 ) ;
  211. oTable.setAttribute( '_fckstyle', oTable.style.cssText ) ;
  212. var oTbody = oDoc.createElement( 'TBODY' ) ;
  213. oTable.appendChild( oTbody ) ;
  214. for ( var i = 0 ; i < dimension.rows ; i++ )
  215. {
  216. var oRow = oDoc.createElement( 'TR' ) ;
  217. oTbody.appendChild( oRow ) ;
  218. for ( var j = 0 ; j < dimension.cols ; j++ )
  219. {
  220. var oCell = oDoc.createElement( 'TD' ) ;
  221. oRow.appendChild( oCell ) ;
  222. if ( FCKBrowserInfo.IsGeckoLike )
  223. FCKTools.AppendBogusBr( oCell ) ;
  224. }
  225. }
  226. FCK.InsertElement( oTable ) ;
  227. }
  228. FCK.Focus() ;
  229. if ( dimension.cols > 0 && dimension.rows > 0 )
  230. FCK.Events.FireEvent( 'OnSelectionChange' ) ;
  231. command._Panel.Hide() ;
  232. }
  233. TableDimensionPickerCommand.prototype._CreatePanelBody = function( targetDocument, targetDiv )
  234. {
  235. var oDiv = targetDiv.appendChild( targetDocument.createElement( "DIV" ) ) ;
  236. oDiv.id = 'dimension-picker' ;
  237. this._Picker = new DimensionPicker( oDiv, this, TableDimensionPickerCommand_OnClick ) ;
  238. }
  239. function FCKToolbarSet_Create( overhideLocation )
  240. {
  241. var oToolbarSet ;
  242. var sLocation = overhideLocation || FCKConfig.ToolbarLocation ;
  243. switch ( sLocation )
  244. {
  245. case 'In' :
  246. document.getElementById( 'xToolbarRow' ).style.display = '' ;
  247. oToolbarSet = new FCKToolbarSet( document ) ;
  248. break ;
  249. case 'None' :
  250. oToolbarSet = new FCKToolbarSet( document ) ;
  251. break ;
  252. // case 'OutTop' :
  253. // Not supported.
  254. default :
  255. FCK.Events.AttachEvent( 'OnBlur', FCK_OnBlur ) ;
  256. FCK.Events.AttachEvent( 'OnFocus', FCK_OnFocus ) ;
  257. var eToolbarTarget ;
  258. // Out:[TargetWindow]([TargetId])
  259. var oOutMatch = sLocation.match( /^Out:(.+)\((\w+)\)$/ ) ;
  260. if ( oOutMatch )
  261. {
  262. if ( FCKBrowserInfo.IsAIR )
  263. FCKAdobeAIR.ToolbarSet_GetOutElement( window, oOutMatch ) ;
  264. else
  265. eToolbarTarget = eval( 'parent.' + oOutMatch[1] ).document.getElementById( oOutMatch[2] ) ;
  266. }
  267. else
  268. {
  269. // Out:[TargetId]
  270. oOutMatch = sLocation.match( /^Out:(\w+)$/ ) ;
  271. if ( oOutMatch )
  272. eToolbarTarget = parent.document.getElementById( oOutMatch[1] ) ;
  273. }
  274. if ( !eToolbarTarget )
  275. {
  276. alert( 'Invalid value for "ToolbarLocation"' ) ;
  277. return arguments.callee( 'In' );
  278. }
  279. // If it is a shared toolbar, it may be already available in the target element.
  280. oToolbarSet = eToolbarTarget.__FCKToolbarSet ;
  281. if ( oToolbarSet )
  282. break ;
  283. // Create the IFRAME that will hold the toolbar inside the target element.
  284. var eToolbarIFrame = FCKTools.GetElementDocument( eToolbarTarget ).createElement( 'iframe' ) ;
  285. eToolbarIFrame.src = 'javascript:void(0)' ;
  286. eToolbarIFrame.frameBorder = 0 ;
  287. eToolbarIFrame.width = '100%' ;
  288. eToolbarIFrame.height = '10' ;
  289. eToolbarTarget.appendChild( eToolbarIFrame ) ;
  290. eToolbarIFrame.unselectable = 'on' ;
  291. // Write the basic HTML for the toolbar (copy from the editor main page).
  292. var eTargetDocument = eToolbarIFrame.contentWindow.document ;
  293. // Workaround for Safari 12256. Ticket #63
  294. var sBase = '' ;
  295. if ( FCKBrowserInfo.IsSafari )
  296. sBase = '<base href="' + window.document.location + '">' ;
  297. // Initialize the IFRAME document body.
  298. eTargetDocument.open() ;
  299. eTargetDocument.write( '<html><head>' + sBase + '<script type="text/javascript"> var adjust = function() { window.frameElement.height = document.body.scrollHeight ; }; '
  300. + 'window.onresize = window.onload = '
  301. + 'function(){' // poll scrollHeight until it no longer changes for 1 sec.
  302. + 'var timer = null;'
  303. + 'var lastHeight = -1;'
  304. + 'var lastChange = 0;'
  305. + 'var poller = function(){'
  306. + 'var currentHeight = document.body.scrollHeight || 0;'
  307. + 'var currentTime = (new Date()).getTime();'
  308. + 'if (currentHeight != lastHeight){'
  309. + 'lastChange = currentTime;'
  310. + 'adjust();'
  311. + 'lastHeight = document.body.scrollHeight;'
  312. + '}'
  313. + 'if (lastChange < currentTime - 1000) clearInterval(timer);'
  314. + '};'
  315. + 'timer = setInterval(poller, 100);'
  316. + '}'
  317. + '</script></head><body style="overflow: hidden">' + document.getElementById( 'xToolbarSpace' ).innerHTML + '</body></html>' ) ;
  318. eTargetDocument.close() ;
  319. if( FCKBrowserInfo.IsAIR )
  320. FCKAdobeAIR.ToolbarSet_InitOutFrame( eTargetDocument ) ;
  321. FCKTools.AddEventListener( eTargetDocument, 'contextmenu', FCKTools.CancelEvent ) ;
  322. // Load external resources (must be done here, otherwise Firefox will not
  323. // have the document DOM ready to be used right away.
  324. FCKTools.AppendStyleSheet( eTargetDocument, FCKConfig.SkinEditorCSS ) ;
  325. oToolbarSet = eToolbarTarget.__FCKToolbarSet = new FCKToolbarSet( eTargetDocument ) ;
  326. oToolbarSet._IFrame = eToolbarIFrame ;
  327. if ( FCK.IECleanup )
  328. FCK.IECleanup.AddItem( eToolbarTarget, FCKToolbarSet_Target_Cleanup ) ;
  329. }
  330. oToolbarSet.CurrentInstance = FCK ;
  331. if ( !oToolbarSet.ToolbarItems )
  332. oToolbarSet.ToolbarItems = FCKToolbarItems ;
  333. FCK.AttachToOnSelectionChange( oToolbarSet.RefreshItemsState ) ;
  334. FCK.Events.FireEvent( 'OnToolbarCreated', oToolbarSet ) ;
  335. return oToolbarSet ;
  336. }
  337. if ( FCKBrowserInfo.IsIE )
  338. {
  339. FCKTools.GetElementPosition = function( el, relativeWindow )
  340. {
  341. // Initializes the Coordinates object that will be returned by the function.
  342. var c = { X:0, Y:0 } ;
  343. var oWindow = relativeWindow || window ;
  344. // Loop throw the offset chain.
  345. while ( el )
  346. {
  347. c.X += el.offsetLeft - el.scrollLeft ;
  348. c.Y += el.offsetTop - el.scrollTop ;
  349. if ( el.offsetParent == null )
  350. {
  351. var oOwnerWindow = FCKTools.GetElementWindow( el ) ;
  352. if ( oOwnerWindow != oWindow )
  353. el = oOwnerWindow.frameElement ;
  354. else
  355. {
  356. c.X += el.scrollLeft ;
  357. c.Y += el.scrollTop ;
  358. break ;
  359. }
  360. }
  361. else
  362. el = el.offsetParent ;
  363. }
  364. // Return the Coordinates object
  365. return c ;
  366. }
  367. }
  368. FCK.Events.AttachEvent( 'OnToolbarCreated', function( oEditor, oToolbarSet )
  369. {
  370. FCKToolbarItems.RegisterItem( 'TableOC', new FCKToolbarPanelButton( 'TableOC', FCKLang.InsertTable, null, null, 39 ) ) ;
  371. FCKCommands.RegisterCommand( 'TableOC', new TableDimensionPickerCommand( oToolbarSet ) ) ;
  372. } ) ;