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 * Definition of other commands that are not available internaly in the
22 * browser (see FCKNamedCommand).
23 */
24
25// ### General Dialog Box Commands.
26var FCKDialogCommand = function( name, title, url, width, height, getStateFunction, getStateParam )
27{
28	this.Name	= name ;
29	this.Title	= title ;
30	this.Url	= url ;
31	this.Width	= width ;
32	this.Height	= height ;
33
34	this.GetStateFunction	= getStateFunction ;
35	this.GetStateParam		= getStateParam ;
36
37	this.Resizable = false ;
38}
39
40FCKDialogCommand.prototype.Execute = function()
41{
42	FCKDialog.OpenDialog( 'FCKDialog_' + this.Name , this.Title, this.Url, this.Width, this.Height, null, null, this.Resizable ) ;
43}
44
45FCKDialogCommand.prototype.GetState = function()
46{
47	if ( this.GetStateFunction )
48		return this.GetStateFunction( this.GetStateParam ) ;
49	else
50		return FCK_TRISTATE_OFF ;
51}
52
53// Generic Undefined command (usually used when a command is under development).
54var FCKUndefinedCommand = function()
55{
56	this.Name = 'Undefined' ;
57}
58
59FCKUndefinedCommand.prototype.Execute = function()
60{
61	alert( FCKLang.NotImplemented ) ;
62}
63
64FCKUndefinedCommand.prototype.GetState = function()
65{
66	return FCK_TRISTATE_OFF ;
67}
68
69
70// ### FormatBlock
71var FCKFormatBlockCommand = function()
72{}
73
74FCKFormatBlockCommand.prototype =
75{
76	Name : 'FormatBlock',
77
78	Execute : FCKStyleCommand.prototype.Execute,
79
80	GetState : function()
81	{
82		return FCK.EditorDocument ? FCK_TRISTATE_OFF : FCK_TRISTATE_DISABLED ;
83	}
84};
85
86// ### FontName
87
88var FCKFontNameCommand = function()
89{}
90
91FCKFontNameCommand.prototype =
92{
93	Name		: 'FontName',
94	Execute		: FCKStyleCommand.prototype.Execute,
95	GetState	: FCKFormatBlockCommand.prototype.GetState
96};
97
98// ### FontSize
99var FCKFontSizeCommand = function()
100{}
101
102FCKFontSizeCommand.prototype =
103{
104	Name		: 'FontSize',
105	Execute		: FCKStyleCommand.prototype.Execute,
106	GetState	: FCKFormatBlockCommand.prototype.GetState
107};
108
109// ### Preview
110var FCKPreviewCommand = function()
111{
112	this.Name = 'Preview' ;
113}
114
115FCKPreviewCommand.prototype.Execute = function()
116{
117     FCK.Preview() ;
118}
119
120FCKPreviewCommand.prototype.GetState = function()
121{
122	return FCK_TRISTATE_OFF ;
123}
124
125// ### Save
126var FCKSaveCommand = function()
127{
128	this.Name = 'Save' ;
129}
130
131FCKSaveCommand.prototype.Execute = function()
132{
133	// Get the linked field form.
134	var oForm = FCK.GetParentForm() ;
135
136	if ( typeof( oForm.onsubmit ) == 'function' )
137	{
138		var bRet = oForm.onsubmit() ;
139		if ( bRet != null && bRet === false )
140			return ;
141	}
142
143	// Submit the form.
144	// If there's a button named "submit" then the form.submit() function is masked and
145	// can't be called in Mozilla, so we call the click() method of that button.
146	if ( typeof( oForm.submit ) == 'function' )
147		oForm.submit() ;
148	else
149		oForm.submit.click() ;
150}
151
152FCKSaveCommand.prototype.GetState = function()
153{
154	return FCK_TRISTATE_OFF ;
155}
156
157// ### NewPage
158var FCKNewPageCommand = function()
159{
160	this.Name = 'NewPage' ;
161}
162
163FCKNewPageCommand.prototype.Execute = function()
164{
165	FCKUndo.SaveUndoStep() ;
166	FCK.SetData( '' ) ;
167	FCKUndo.Typing = true ;
168	FCK.Focus() ;
169}
170
171FCKNewPageCommand.prototype.GetState = function()
172{
173	return FCK_TRISTATE_OFF ;
174}
175
176// ### Source button
177var FCKSourceCommand = function()
178{
179	this.Name = 'Source' ;
180}
181
182FCKSourceCommand.prototype.Execute = function()
183{
184	if ( FCKConfig.SourcePopup )	// Until v2.2, it was mandatory for FCKBrowserInfo.IsGecko.
185	{
186		var iWidth	= FCKConfig.ScreenWidth * 0.65 ;
187		var iHeight	= FCKConfig.ScreenHeight * 0.65 ;
188		FCKDialog.OpenDialog( 'FCKDialog_Source', FCKLang.Source, 'dialog/fck_source.html', iWidth, iHeight, null, null, true ) ;
189	}
190	else
191	    FCK.SwitchEditMode() ;
192}
193
194FCKSourceCommand.prototype.GetState = function()
195{
196	return ( FCK.EditMode == FCK_EDITMODE_WYSIWYG ? FCK_TRISTATE_OFF : FCK_TRISTATE_ON ) ;
197}
198
199// ### Undo
200var FCKUndoCommand = function()
201{
202	this.Name = 'Undo' ;
203}
204
205FCKUndoCommand.prototype.Execute = function()
206{
207	FCKUndo.Undo() ;
208}
209
210FCKUndoCommand.prototype.GetState = function()
211{
212	return ( FCKUndo.CheckUndoState() ? FCK_TRISTATE_OFF : FCK_TRISTATE_DISABLED ) ;
213}
214
215// ### Redo
216var FCKRedoCommand = function()
217{
218	this.Name = 'Redo' ;
219}
220
221FCKRedoCommand.prototype.Execute = function()
222{
223	FCKUndo.Redo() ;
224}
225
226FCKRedoCommand.prototype.GetState = function()
227{
228	return ( FCKUndo.CheckRedoState() ? FCK_TRISTATE_OFF : FCK_TRISTATE_DISABLED ) ;
229}
230
231// ### Page Break
232var FCKPageBreakCommand = function()
233{
234	this.Name = 'PageBreak' ;
235}
236
237FCKPageBreakCommand.prototype.Execute = function()
238{
239	// Take an undo snapshot before changing the document
240	FCKUndo.SaveUndoStep() ;
241
242//	var e = FCK.EditorDocument.createElement( 'CENTER' ) ;
243//	e.style.pageBreakAfter = 'always' ;
244
245	// Tidy was removing the empty CENTER tags, so the following solution has
246	// been found. It also validates correctly as XHTML 1.0 Strict.
247	var e = FCK.EditorDocument.createElement( 'DIV' ) ;
248	e.style.pageBreakAfter = 'always' ;
249	e.innerHTML = '<span style="DISPLAY:none">&nbsp;</span>' ;
250
251	var oFakeImage = FCKDocumentProcessor_CreateFakeImage( 'FCK__PageBreak', e ) ;
252	FCK.InsertElement( oFakeImage ) ;
253}
254
255FCKPageBreakCommand.prototype.GetState = function()
256{
257	return 0 ; // FCK_TRISTATE_OFF
258}
259
260// FCKUnlinkCommand - by Johnny Egeland (johnny@coretrek.com)
261var FCKUnlinkCommand = function()
262{
263	this.Name = 'Unlink' ;
264}
265
266FCKUnlinkCommand.prototype.Execute = function()
267{
268	// Take an undo snapshot before changing the document
269	FCKUndo.SaveUndoStep() ;
270
271	if ( FCKBrowserInfo.IsGeckoLike )
272	{
273		var oLink = FCK.Selection.MoveToAncestorNode( 'A' ) ;
274		// The unlink command can generate a span in Firefox, so let's do it our way. See #430
275		if ( oLink )
276			FCKTools.RemoveOuterTags( oLink ) ;
277
278		return ;
279	}
280
281	FCK.ExecuteNamedCommand( this.Name ) ;
282}
283
284FCKUnlinkCommand.prototype.GetState = function()
285{
286	var state = FCK.GetNamedCommandState( this.Name ) ;
287
288	// Check that it isn't an anchor
289	if ( state == FCK_TRISTATE_OFF && FCK.EditMode == FCK_EDITMODE_WYSIWYG )
290	{
291		var oLink = FCKSelection.MoveToAncestorNode( 'A' ) ;
292		var bIsAnchor = ( oLink && oLink.name.length > 0 && oLink.href.length == 0 ) ;
293		if ( bIsAnchor )
294			state = FCK_TRISTATE_DISABLED ;
295	}
296
297	return state ;
298}
299
300// FCKSelectAllCommand
301var FCKSelectAllCommand = function()
302{
303	this.Name = 'SelectAll' ;
304}
305
306FCKSelectAllCommand.prototype.Execute = function()
307{
308	if ( FCK.EditMode == FCK_EDITMODE_WYSIWYG )
309	{
310		FCK.ExecuteNamedCommand( 'SelectAll' ) ;
311	}
312	else
313	{
314		// Select the contents of the textarea
315		var textarea = FCK.EditingArea.Textarea ;
316		if ( FCKBrowserInfo.IsIE )
317		{
318			textarea.createTextRange().execCommand( 'SelectAll' ) ;
319		}
320		else
321		{
322			textarea.selectionStart = 0 ;
323			textarea.selectionEnd = textarea.value.length ;
324		}
325		textarea.focus() ;
326	}
327}
328
329FCKSelectAllCommand.prototype.GetState = function()
330{
331	return FCK_TRISTATE_OFF ;
332}
333
334// FCKPasteCommand
335var FCKPasteCommand = function()
336{
337	this.Name = 'Paste' ;
338}
339
340FCKPasteCommand.prototype =
341{
342	Execute : function()
343	{
344		if ( FCKBrowserInfo.IsIE )
345			FCK.Paste() ;
346		else
347			FCK.ExecuteNamedCommand( 'Paste' ) ;
348	},
349
350	GetState : function()
351	{
352		return FCK.GetNamedCommandState( 'Paste' ) ;
353	}
354} ;
355
356// FCKRuleCommand
357var FCKRuleCommand = function()
358{
359	this.Name = 'Rule' ;
360}
361
362FCKRuleCommand.prototype =
363{
364	Execute : function()
365	{
366		FCKUndo.SaveUndoStep() ;
367		FCK.InsertElement( 'hr' ) ;
368	},
369
370	GetState : function()
371	{
372		return FCK.GetNamedCommandState( 'InsertHorizontalRule' ) ;
373	}
374} ;
375
376// FCKCopyCommand
377var FCKCopyCommand = function()
378{
379	this.Name = 'Copy' ;
380}
381
382FCKCopyCommand.prototype =
383{
384	Execute : function()
385	{
386		FCK.ExecuteNamedCommand( this.Name ) ;
387	},
388
389	GetState : function()
390	{
391		// Strangely, the cut command happens to have the correct states for both Copy and Cut in all browsers.
392		return FCK.GetNamedCommandState( 'Cut' ) ;
393	}
394};
395
396var FCKAnchorDeleteCommand = function()
397{
398	this.Name = 'AnchorDelete' ;
399}
400
401FCKAnchorDeleteCommand.prototype =
402{
403	Execute : function()
404	{
405		if (FCK.Selection.GetType() == 'Control')
406		{
407			FCK.Selection.Delete();
408		}
409		else
410		{
411			var oFakeImage = FCK.Selection.GetSelectedElement() ;
412			if ( oFakeImage )
413			{
414				if ( oFakeImage.tagName == 'IMG' && oFakeImage.getAttribute('_fckanchor') )
415					oAnchor = FCK.GetRealElement( oFakeImage ) ;
416				else
417					oFakeImage = null ;
418			}
419
420			//Search for a real anchor
421			if ( !oFakeImage )
422			{
423				oAnchor = FCK.Selection.MoveToAncestorNode( 'A' ) ;
424				if ( oAnchor )
425					FCK.Selection.SelectNode( oAnchor ) ;
426			}
427
428			// If it's also a link, then just remove the name and exit
429			if ( oAnchor.href.length != 0 )
430			{
431				oAnchor.removeAttribute( 'name' ) ;
432				// Remove temporary class for IE
433				if ( FCKBrowserInfo.IsIE )
434					oAnchor.className = oAnchor.className.replace( FCKRegexLib.FCK_Class, '' ) ;
435				return ;
436			}
437
438			// We need to remove the anchor
439			// If we got a fake image, then just remove it and we're done
440			if ( oFakeImage )
441			{
442				oFakeImage.parentNode.removeChild( oFakeImage ) ;
443				return ;
444			}
445			// Empty anchor, so just remove it
446			if ( oAnchor.innerHTML.length == 0 )
447			{
448				oAnchor.parentNode.removeChild( oAnchor ) ;
449				return ;
450			}
451			// Anchor with content, leave the content
452			FCKTools.RemoveOuterTags( oAnchor ) ;
453		}
454		if ( FCKBrowserInfo.IsGecko )
455			FCK.Selection.Collapse( true ) ;
456	},
457
458	GetState : function()
459	{
460		return FCK.GetNamedCommandState( 'Unlink') ;
461	}
462};
463