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 * Defines the FCKToolbarSet object that is used to load and draw the
22 * toolbar.
23 */
24
25function FCKToolbarSet_Create( overhideLocation )
26{
27	var oToolbarSet ;
28
29	var sLocation = overhideLocation || FCKConfig.ToolbarLocation ;
30	switch ( sLocation )
31	{
32		case 'In' :
33			document.getElementById( 'xToolbarRow' ).style.display = '' ;
34			oToolbarSet = new FCKToolbarSet( document ) ;
35			break ;
36		case 'None' :
37			oToolbarSet = new FCKToolbarSet( document ) ;
38			break ;
39
40//		case 'OutTop' :
41			// Not supported.
42
43		default :
44			FCK.Events.AttachEvent( 'OnBlur', FCK_OnBlur ) ;
45			FCK.Events.AttachEvent( 'OnFocus', FCK_OnFocus ) ;
46
47			var eToolbarTarget ;
48
49			// Out:[TargetWindow]([TargetId])
50			var oOutMatch = sLocation.match( /^Out:(.+)\((\w+)\)$/ ) ;
51			if ( oOutMatch )
52			{
53				eToolbarTarget = eval( 'parent.' + oOutMatch[1] ).document.getElementById( oOutMatch[2] ) ;
54			}
55			else
56			{
57				// Out:[TargetId]
58				oOutMatch = sLocation.match( /^Out:(\w+)$/ ) ;
59				if ( oOutMatch )
60					eToolbarTarget = parent.document.getElementById( oOutMatch[1] ) ;
61			}
62
63			if ( !eToolbarTarget )
64			{
65				alert( 'Invalid value for "ToolbarLocation"' ) ;
66				return arguments.callee( 'In' );
67			}
68
69			// If it is a shared toolbar, it may be already available in the target element.
70			oToolbarSet = eToolbarTarget.__FCKToolbarSet ;
71			if ( oToolbarSet )
72				break ;
73
74			// Create the IFRAME that will hold the toolbar inside the target element.
75			var eToolbarIFrame = FCKTools.GetElementDocument( eToolbarTarget ).createElement( 'iframe' ) ;
76			eToolbarIFrame.src = 'javascript:void(0)' ;
77			eToolbarIFrame.frameBorder = 0 ;
78			eToolbarIFrame.width = '100%' ;
79			eToolbarIFrame.height = '10' ;
80			eToolbarTarget.appendChild( eToolbarIFrame ) ;
81			eToolbarIFrame.unselectable = 'on' ;
82
83			// Write the basic HTML for the toolbar (copy from the editor main page).
84			var eTargetDocument = eToolbarIFrame.contentWindow.document ;
85
86			// Workaround for Safari 12256. Ticket #63
87			var sBase = '' ;
88			if ( FCKBrowserInfo.IsSafari )
89				sBase = '<base href="' + window.document.location + '">' ;
90
91			// Initialize the IFRAME document body.
92			eTargetDocument.open() ;
93			eTargetDocument.write( '<html><head>' + sBase + '<script type="text/javascript"> var adjust = function() { window.frameElement.height = document.body.scrollHeight ; }; window.onresize = adjust; window.onload = function () {adjust(); window.setTimeout( adjust, 1000 ); }</script></head><body style="overflow: hidden">' + document.getElementById( 'xToolbarSpace' ).innerHTML + '</body></html>' ) ;
94			eTargetDocument.close() ;
95
96			FCKTools.AddEventListener( eTargetDocument, 'contextmenu', FCKTools.CancelEvent ) ;
97
98			// Load external resources (must be done here, otherwise Firefox will not
99			// have the document DOM ready to be used right away.
100			FCKTools.AppendStyleSheet( eTargetDocument, FCKConfig.SkinPath + 'fck_editor.css' ) ;
101
102			oToolbarSet = eToolbarTarget.__FCKToolbarSet = new FCKToolbarSet( eTargetDocument ) ;
103			oToolbarSet._IFrame = eToolbarIFrame ;
104
105			if ( FCK.IECleanup )
106				FCK.IECleanup.AddItem( eToolbarTarget, FCKToolbarSet_Target_Cleanup ) ;
107	}
108
109	oToolbarSet.CurrentInstance = FCK ;
110
111	FCK.AttachToOnSelectionChange( oToolbarSet.RefreshItemsState ) ;
112
113	return oToolbarSet ;
114}
115
116function FCK_OnBlur( editorInstance )
117{
118	var eToolbarSet = editorInstance.ToolbarSet ;
119
120	if ( eToolbarSet.CurrentInstance == editorInstance )
121		eToolbarSet.Disable() ;
122}
123
124function FCK_OnFocus( editorInstance )
125{
126	var oToolbarset = editorInstance.ToolbarSet ;
127	var oInstance = editorInstance || FCK ;
128
129	// Unregister the toolbar window from the current instance.
130	oToolbarset.CurrentInstance.FocusManager.RemoveWindow( oToolbarset._IFrame.contentWindow ) ;
131
132	// Set the new current instance.
133	oToolbarset.CurrentInstance = oInstance ;
134
135	// Register the toolbar window in the current instance.
136	oInstance.FocusManager.AddWindow( oToolbarset._IFrame.contentWindow, true ) ;
137
138	oToolbarset.Enable() ;
139}
140
141function FCKToolbarSet_Cleanup()
142{
143	this._TargetElement = null ;
144	this._IFrame = null ;
145}
146
147function FCKToolbarSet_Target_Cleanup()
148{
149	this.__FCKToolbarSet = null ;
150}
151
152var FCKToolbarSet = function( targetDocument )
153{
154	this._Document = targetDocument ;
155
156	// Get the element that will hold the elements structure.
157	this._TargetElement	= targetDocument.getElementById( 'xToolbar' ) ;
158
159	// Setup the expand and collapse handlers.
160	var eExpandHandle	= targetDocument.getElementById( 'xExpandHandle' ) ;
161	var eCollapseHandle	= targetDocument.getElementById( 'xCollapseHandle' ) ;
162
163	eExpandHandle.title		= FCKLang.ToolbarExpand ;
164	FCKTools.AddEventListener( eExpandHandle, 'click', FCKToolbarSet_Expand_OnClick ) ;
165
166	eCollapseHandle.title	= FCKLang.ToolbarCollapse ;
167	FCKTools.AddEventListener( eCollapseHandle, 'click', FCKToolbarSet_Collapse_OnClick ) ;
168
169	// Set the toolbar state at startup.
170	if ( !FCKConfig.ToolbarCanCollapse || FCKConfig.ToolbarStartExpanded )
171		this.Expand() ;
172	else
173		this.Collapse() ;
174
175	// Enable/disable the collapse handler
176	eCollapseHandle.style.display = FCKConfig.ToolbarCanCollapse ? '' : 'none' ;
177
178	if ( FCKConfig.ToolbarCanCollapse )
179		eCollapseHandle.style.display = '' ;
180	else
181		targetDocument.getElementById( 'xTBLeftBorder' ).style.display = '' ;
182
183	// Set the default properties.
184	this.Toolbars = new Array() ;
185	this.IsLoaded = false ;
186
187	if ( FCK.IECleanup )
188		FCK.IECleanup.AddItem( this, FCKToolbarSet_Cleanup ) ;
189}
190
191function FCKToolbarSet_Expand_OnClick()
192{
193	FCK.ToolbarSet.Expand() ;
194}
195
196function FCKToolbarSet_Collapse_OnClick()
197{
198	FCK.ToolbarSet.Collapse() ;
199}
200
201FCKToolbarSet.prototype.Expand = function()
202{
203	this._ChangeVisibility( false ) ;
204}
205
206FCKToolbarSet.prototype.Collapse = function()
207{
208	this._ChangeVisibility( true ) ;
209}
210
211FCKToolbarSet.prototype._ChangeVisibility = function( collapse )
212{
213	this._Document.getElementById( 'xCollapsed' ).style.display = collapse ? '' : 'none' ;
214	this._Document.getElementById( 'xExpanded' ).style.display = collapse ? 'none' : '' ;
215
216	if ( FCKBrowserInfo.IsGecko )
217	{
218		// I had to use "setTimeout" because Gecko was not responding in a right
219		// way when calling window.onresize() directly.
220		FCKTools.RunFunction( window.onresize ) ;
221	}
222}
223
224FCKToolbarSet.prototype.Load = function( toolbarSetName )
225{
226	this.Name = toolbarSetName ;
227
228	this.Items = new Array() ;
229
230	// Reset the array of toolbar items that are active only on WYSIWYG mode.
231	this.ItemsWysiwygOnly = new Array() ;
232
233	// Reset the array of toolbar items that are sensitive to the cursor position.
234	this.ItemsContextSensitive = new Array() ;
235
236	// Cleanup the target element.
237	this._TargetElement.innerHTML = '' ;
238
239	var ToolbarSet = FCKConfig.ToolbarSets[toolbarSetName] ;
240
241	if ( !ToolbarSet )
242	{
243		alert( FCKLang.UnknownToolbarSet.replace( /%1/g, toolbarSetName ) ) ;
244		return ;
245	}
246
247	this.Toolbars = new Array() ;
248
249	for ( var x = 0 ; x < ToolbarSet.length ; x++ )
250	{
251		var oToolbarItems = ToolbarSet[x] ;
252
253		// If the configuration for the toolbar is missing some element or has any extra comma
254		// this item won't be valid, so skip it and keep on processing.
255		if ( !oToolbarItems )
256			continue ;
257
258		var oToolbar ;
259
260		if ( typeof( oToolbarItems ) == 'string' )
261		{
262			if ( oToolbarItems == '/' )
263				oToolbar = new FCKToolbarBreak() ;
264		}
265		else
266		{
267			oToolbar = new FCKToolbar() ;
268
269			for ( var j = 0 ; j < oToolbarItems.length ; j++ )
270			{
271				var sItem = oToolbarItems[j] ;
272
273				if ( sItem == '-')
274					oToolbar.AddSeparator() ;
275				else
276				{
277					var oItem = FCKToolbarItems.GetItem( sItem ) ;
278					if ( oItem )
279					{
280						oToolbar.AddItem( oItem ) ;
281
282						this.Items.push( oItem ) ;
283
284						if ( !oItem.SourceView )
285							this.ItemsWysiwygOnly.push( oItem ) ;
286
287						if ( oItem.ContextSensitive )
288							this.ItemsContextSensitive.push( oItem ) ;
289					}
290				}
291			}
292
293			// oToolbar.AddTerminator() ;
294		}
295
296		oToolbar.Create( this._TargetElement ) ;
297
298		this.Toolbars[ this.Toolbars.length ] = oToolbar ;
299	}
300
301	FCKTools.DisableSelection( this._Document.getElementById( 'xCollapseHandle' ).parentNode ) ;
302
303	if ( FCK.Status != FCK_STATUS_COMPLETE )
304		FCK.Events.AttachEvent( 'OnStatusChange', this.RefreshModeState ) ;
305	else
306		this.RefreshModeState() ;
307
308	this.IsLoaded = true ;
309	this.IsEnabled = true ;
310
311	FCKTools.RunFunction( this.OnLoad ) ;
312}
313
314FCKToolbarSet.prototype.Enable = function()
315{
316	if ( this.IsEnabled )
317		return ;
318
319	this.IsEnabled = true ;
320
321	var aItems = this.Items ;
322	for ( var i = 0 ; i < aItems.length ; i++ )
323		aItems[i].RefreshState() ;
324}
325
326FCKToolbarSet.prototype.Disable = function()
327{
328	if ( !this.IsEnabled )
329		return ;
330
331	this.IsEnabled = false ;
332
333	var aItems = this.Items ;
334	for ( var i = 0 ; i < aItems.length ; i++ )
335		aItems[i].Disable() ;
336}
337
338FCKToolbarSet.prototype.RefreshModeState = function( editorInstance )
339{
340	if ( FCK.Status != FCK_STATUS_COMPLETE )
341		return ;
342
343	var oToolbarSet = editorInstance ? editorInstance.ToolbarSet : this ;
344	var aItems = oToolbarSet.ItemsWysiwygOnly ;
345
346	if ( FCK.EditMode == FCK_EDITMODE_WYSIWYG )
347	{
348		// Enable all buttons that are available on WYSIWYG mode only.
349		for ( var i = 0 ; i < aItems.length ; i++ )
350			aItems[i].Enable() ;
351
352		// Refresh the buttons state.
353		oToolbarSet.RefreshItemsState( editorInstance ) ;
354	}
355	else
356	{
357		// Refresh the buttons state.
358		oToolbarSet.RefreshItemsState( editorInstance ) ;
359
360		// Disable all buttons that are available on WYSIWYG mode only.
361		for ( var j = 0 ; j < aItems.length ; j++ )
362			aItems[j].Disable() ;
363	}
364}
365
366FCKToolbarSet.prototype.RefreshItemsState = function( editorInstance )
367{
368
369	var aItems = ( editorInstance ? editorInstance.ToolbarSet : this ).ItemsContextSensitive ;
370
371	for ( var i = 0 ; i < aItems.length ; i++ )
372		aItems[i].RefreshState() ;
373}
374