2
* FCKeditor - The text editor for Internet - http://www.fckeditor.net
3
* Copyright (C) 2003-2008 Frederico Caldeira Knabben
7
* Licensed under the terms of any of the following licenses at your
10
* - GNU General Public License Version 2 or later (the "GPL")
11
* http://www.gnu.org/licenses/gpl.html
13
* - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
14
* http://www.gnu.org/licenses/lgpl.html
16
* - Mozilla Public License Version 1.1 or later (the "MPL")
17
* http://www.mozilla.org/MPL/MPL-1.1.html
21
* Component that creates floating panels. It is used by many
22
* other components, like the toolbar items, context menu, etc...
25
var FCKPanel = function( parentWindow )
27
this.IsRTL = ( FCKLang.Dir == 'rtl' ) ;
28
this.IsContextMenu = false ;
29
this._LockCounter = 0 ;
31
this._Window = parentWindow || window ;
35
if ( FCKBrowserInfo.IsIE )
37
// Create the Popup that will hold the panel.
38
// The popup has to be created before playing with domain hacks, see #1666.
39
this._Popup = this._Window.createPopup() ;
41
// this._Window cannot be accessed while playing with domain hacks, but local variable is ok.
43
var pDoc = this._Window.document ;
45
// This is a trick to IE6 (not IE7). The original domain must be set
46
// before creating the popup, so we are able to take a refence to the
47
// document inside of it, and the set the proper domain for it. (#123)
48
if ( FCK_IS_CUSTOM_DOMAIN && !FCKBrowserInfo.IsIE7 )
50
pDoc.domain = FCK_ORIGINAL_DOMAIN ;
51
document.domain = FCK_ORIGINAL_DOMAIN ;
54
oDocument = this.Document = this._Popup.document ;
56
// Set the proper domain inside the popup.
57
if ( FCK_IS_CUSTOM_DOMAIN )
59
oDocument.domain = FCK_RUNTIME_DOMAIN ;
60
pDoc.domain = FCK_RUNTIME_DOMAIN ;
61
document.domain = FCK_RUNTIME_DOMAIN ;
64
FCK.IECleanup.AddItem( this, FCKPanel_Cleanup ) ;
68
var oIFrame = this._IFrame = this._Window.document.createElement('iframe') ;
69
FCKTools.ResetStyles( oIFrame );
70
oIFrame.src = 'javascript:void(0)' ;
71
oIFrame.allowTransparency = true ;
72
oIFrame.frameBorder = '0' ;
73
oIFrame.scrolling = 'no' ;
74
oIFrame.style.width = oIFrame.style.height = '0px' ;
75
FCKDomTools.SetElementStyles( oIFrame,
77
position : 'absolute',
78
zIndex : FCKConfig.FloatingPanelsZIndex
81
this._Window.document.body.appendChild( oIFrame ) ;
83
var oIFrameWindow = oIFrame.contentWindow ;
85
oDocument = this.Document = oIFrameWindow.document ;
87
// Workaround for Safari 12256. Ticket #63
89
if ( FCKBrowserInfo.IsSafari )
90
sBase = '<base href="' + window.document.location + '">' ;
92
// Initialize the IFRAME document body.
94
oDocument.write( '<html><head>' + sBase + '<\/head><body style="margin:0px;padding:0px;"><\/body><\/html>' ) ;
97
if( FCKBrowserInfo.IsAIR )
98
FCKAdobeAIR.Panel_Contructor( oDocument, window.document.location ) ;
100
FCKTools.AddEventListenerEx( oIFrameWindow, 'focus', FCKPanel_Window_OnFocus, this ) ;
101
FCKTools.AddEventListenerEx( oIFrameWindow, 'blur', FCKPanel_Window_OnBlur, this ) ;
104
oDocument.dir = FCKLang.Dir ;
106
FCKTools.AddEventListener( oDocument, 'contextmenu', FCKTools.CancelEvent ) ;
109
// Create the main DIV that is used as the panel base.
110
this.MainNode = oDocument.body.appendChild( oDocument.createElement('DIV') ) ;
112
// The "float" property must be set so Firefox calculates the size correctly.
113
this.MainNode.style.cssFloat = this.IsRTL ? 'right' : 'left' ;
117
FCKPanel.prototype.AppendStyleSheet = function( styleSheet )
119
FCKTools.AppendStyleSheet( this.Document, styleSheet ) ;
122
FCKPanel.prototype.Preload = function( x, y, relElement )
124
// The offsetWidth and offsetHeight properties are not available if the
125
// element is not visible. So we must "show" the popup with no size to
126
// be able to use that values in the second call (IE only).
128
this._Popup.show( x, y, 0, 0, relElement ) ;
131
FCKPanel.prototype.Show = function( x, y, relElement, width, height )
134
var eMainNode = this.MainNode ;
138
// The offsetWidth and offsetHeight properties are not available if the
139
// element is not visible. So we must "show" the popup with no size to
140
// be able to use that values in the second call.
141
this._Popup.show( x, y, 0, 0, relElement ) ;
143
// The following lines must be place after the above "show", otherwise it
144
// doesn't has the desired effect.
145
FCKDomTools.SetElementStyles( eMainNode,
147
width : width ? width + 'px' : '',
148
height : height ? height + 'px' : ''
151
iMainWidth = eMainNode.offsetWidth ;
155
if ( this.IsContextMenu )
156
x = x - iMainWidth + 1 ;
157
else if ( relElement )
158
x = ( x * -1 ) + relElement.offsetWidth - iMainWidth ;
161
// Second call: Show the Popup at the specified location, with the correct size.
162
this._Popup.show( x, y, iMainWidth, eMainNode.offsetHeight, relElement ) ;
167
CheckPopupOnHide.call( this, true ) ;
169
this._Timer = FCKTools.SetInterval( CheckPopupOnHide, 100, this ) ;
174
// Do not fire OnBlur while the panel is opened.
175
if ( typeof( FCK.ToolbarSet.CurrentInstance.FocusManager ) != 'undefined' )
176
FCK.ToolbarSet.CurrentInstance.FocusManager.Lock() ;
178
if ( this.ParentPanel )
180
this.ParentPanel.Lock() ;
182
// Due to a bug on FF3, we must ensure that the parent panel will
184
FCKPanel_Window_OnBlur( null, this.ParentPanel ) ;
187
// Toggle the iframe scrolling attribute to prevent the panel
188
// scrollbars from disappearing in FF Mac. (#191)
189
if ( FCKBrowserInfo.IsGecko && FCKBrowserInfo.IsMac )
191
this._IFrame.scrolling = '' ;
192
FCKTools.RunFunction( function(){ this._IFrame.scrolling = 'no'; }, this ) ;
195
// Be sure we'll not have more than one Panel opened at the same time.
196
// Do not unlock focus manager here because we're displaying another floating panel
197
// instead of returning the editor to a "no panel" state (Bug #1514).
198
if ( FCK.ToolbarSet.CurrentInstance.GetInstanceObject( 'FCKPanel' )._OpenedPanel &&
199
FCK.ToolbarSet.CurrentInstance.GetInstanceObject( 'FCKPanel' )._OpenedPanel != this )
200
FCK.ToolbarSet.CurrentInstance.GetInstanceObject( 'FCKPanel' )._OpenedPanel.Hide( false, true ) ;
202
FCKDomTools.SetElementStyles( eMainNode,
204
width : width ? width + 'px' : '',
205
height : height ? height + 'px' : ''
208
iMainWidth = eMainNode.offsetWidth ;
210
if ( !width ) this._IFrame.width = 1 ;
211
if ( !height ) this._IFrame.height = 1 ;
213
// This is weird... but with Firefox, we must get the offsetWidth before
214
// setting the _IFrame size (which returns "0"), and then after that,
215
// to return the correct width. Remove the first step and it will not
216
// work when the editor is in RTL.
218
// The "|| eMainNode.firstChild.offsetWidth" part has been added
219
// for Opera compatibility (see #570).
220
iMainWidth = eMainNode.offsetWidth || eMainNode.firstChild.offsetWidth ;
222
// Base the popup coordinates upon the coordinates of relElement.
223
var oPos = FCKTools.GetDocumentPosition( this._Window,
224
relElement.nodeType == 9 ?
225
( FCKTools.IsStrictMode( relElement ) ? relElement.documentElement : relElement.body ) :
228
// Minus the offsets provided by any positioned parent element of the panel iframe.
229
var positionedAncestor = FCKDomTools.GetPositionedAncestor( this._IFrame.parentNode ) ;
230
if ( positionedAncestor )
232
var nPos = FCKTools.GetDocumentPosition( FCKTools.GetElementWindow( positionedAncestor ), positionedAncestor ) ;
237
if ( this.IsRTL && !this.IsContextMenu )
245
if ( this.IsContextMenu )
246
x = x - iMainWidth + 1 ;
247
else if ( relElement )
248
x = x + relElement.offsetWidth - iMainWidth ;
252
var oViewPaneSize = FCKTools.GetViewPaneSize( this._Window ) ;
253
var oScrollPosition = FCKTools.GetScrollPosition( this._Window ) ;
255
var iViewPaneHeight = oViewPaneSize.Height + oScrollPosition.Y ;
256
var iViewPaneWidth = oViewPaneSize.Width + oScrollPosition.X ;
258
if ( ( x + iMainWidth ) > iViewPaneWidth )
259
x -= x + iMainWidth - iViewPaneWidth ;
261
if ( ( y + eMainNode.offsetHeight ) > iViewPaneHeight )
262
y -= y + eMainNode.offsetHeight - iViewPaneHeight ;
265
// Set the context menu DIV in the specified location.
266
FCKDomTools.SetElementStyles( this._IFrame,
272
// Move the focus to the IFRAME so we catch the "onblur".
273
this._IFrame.contentWindow.focus() ;
274
this._IsOpened = true ;
277
this._resizeTimer = setTimeout( function()
279
var iWidth = eMainNode.offsetWidth || eMainNode.firstChild.offsetWidth ;
280
var iHeight = eMainNode.offsetHeight ;
281
me._IFrame.style.width = iWidth + 'px' ;
282
me._IFrame.style.height = iHeight + 'px' ;
286
FCK.ToolbarSet.CurrentInstance.GetInstanceObject( 'FCKPanel' )._OpenedPanel = this ;
289
FCKTools.RunFunction( this.OnShow, this ) ;
292
FCKPanel.prototype.Hide = function( ignoreOnHide, ignoreFocusManagerUnlock )
298
if ( !this._IsOpened || this._LockCounter > 0 )
301
// Enable the editor to fire the "OnBlur".
302
if ( typeof( FCKFocusManager ) != 'undefined' && !ignoreFocusManagerUnlock )
303
FCKFocusManager.Unlock() ;
305
// It is better to set the sizes to 0, otherwise Firefox would have
306
// rendering problems.
307
this._IFrame.style.width = this._IFrame.style.height = '0px' ;
309
this._IsOpened = false ;
311
if ( this._resizeTimer )
313
clearTimeout( this._resizeTimer ) ;
314
this._resizeTimer = null ;
317
if ( this.ParentPanel )
318
this.ParentPanel.Unlock() ;
321
FCKTools.RunFunction( this.OnHide, this ) ;
325
FCKPanel.prototype.CheckIsOpened = function()
328
return this._Popup.isOpen ;
330
return this._IsOpened ;
333
FCKPanel.prototype.CreateChildPanel = function()
335
var oWindow = this._Popup ? FCKTools.GetDocumentWindow( this.Document ) : this._Window ;
337
var oChildPanel = new FCKPanel( oWindow ) ;
338
oChildPanel.ParentPanel = this ;
343
FCKPanel.prototype.Lock = function()
345
this._LockCounter++ ;
348
FCKPanel.prototype.Unlock = function()
350
if ( --this._LockCounter == 0 && !this.HasFocus )
356
function FCKPanel_Window_OnFocus( e, panel )
358
panel.HasFocus = true ;
361
function FCKPanel_Window_OnBlur( e, panel )
363
panel.HasFocus = false ;
365
if ( panel._LockCounter == 0 )
366
FCKTools.RunFunction( panel.Hide, panel ) ;
369
function CheckPopupOnHide( forceHide )
371
if ( forceHide || !this._Popup.isOpen )
373
window.clearInterval( this._Timer ) ;
376
FCKTools.RunFunction( this.OnHide, this ) ;
380
function FCKPanel_Cleanup()
383
this._Window = null ;
384
this.Document = null ;
385
this.MainNode = null ;