2 * FCKeditor - The text editor for Internet - http://www.fckeditor.net
\r
3 * Copyright (C) 2003-2009 Frederico Caldeira Knabben
\r
5 * == BEGIN LICENSE ==
\r
7 * Licensed under the terms of any of the following licenses at your
\r
10 * - GNU General Public License Version 2 or later (the "GPL")
\r
11 * http://www.gnu.org/licenses/gpl.html
\r
13 * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
\r
14 * http://www.gnu.org/licenses/lgpl.html
\r
16 * - Mozilla Public License Version 1.1 or later (the "MPL")
\r
17 * http://www.mozilla.org/MPL/MPL-1.1.html
\r
21 * Definition of other commands that are not available internaly in the
\r
22 * browser (see FCKNamedCommand).
\r
25 // ### General Dialog Box Commands.
\r
26 var FCKDialogCommand = function( name, title, url, width, height, getStateFunction, getStateParam, customValue )
\r
29 this.Title = title ;
\r
31 this.Width = width ;
\r
32 this.Height = height ;
\r
33 this.CustomValue = customValue ;
\r
35 this.GetStateFunction = getStateFunction ;
\r
36 this.GetStateParam = getStateParam ;
\r
38 this.Resizable = false ;
\r
41 FCKDialogCommand.prototype.Execute = function()
\r
43 FCKDialog.OpenDialog( 'FCKDialog_' + this.Name , this.Title, this.Url, this.Width, this.Height, this.CustomValue, null, this.Resizable ) ;
\r
46 FCKDialogCommand.prototype.GetState = function()
\r
48 if ( this.GetStateFunction )
\r
49 return this.GetStateFunction( this.GetStateParam ) ;
\r
51 return FCK.EditMode == FCK_EDITMODE_WYSIWYG ? FCK_TRISTATE_OFF : FCK_TRISTATE_DISABLED ;
\r
54 // Generic Undefined command (usually used when a command is under development).
\r
55 var FCKUndefinedCommand = function()
\r
57 this.Name = 'Undefined' ;
\r
60 FCKUndefinedCommand.prototype.Execute = function()
\r
62 alert( FCKLang.NotImplemented ) ;
\r
65 FCKUndefinedCommand.prototype.GetState = function()
\r
67 return FCK_TRISTATE_OFF ;
\r
72 var FCKFormatBlockCommand = function()
\r
75 FCKFormatBlockCommand.prototype =
\r
77 Name : 'FormatBlock',
\r
79 Execute : FCKStyleCommand.prototype.Execute,
\r
81 GetState : function()
\r
83 return FCK.EditorDocument ? FCK_TRISTATE_OFF : FCK_TRISTATE_DISABLED ;
\r
89 var FCKFontNameCommand = function()
\r
92 FCKFontNameCommand.prototype =
\r
95 Execute : FCKStyleCommand.prototype.Execute,
\r
96 GetState : FCKFormatBlockCommand.prototype.GetState
\r
100 var FCKFontSizeCommand = function()
\r
103 FCKFontSizeCommand.prototype =
\r
106 Execute : FCKStyleCommand.prototype.Execute,
\r
107 GetState : FCKFormatBlockCommand.prototype.GetState
\r
111 var FCKPreviewCommand = function()
\r
113 this.Name = 'Preview' ;
\r
116 FCKPreviewCommand.prototype.Execute = function()
\r
121 FCKPreviewCommand.prototype.GetState = function()
\r
123 return FCK_TRISTATE_OFF ;
\r
127 var FCKSaveCommand = function()
\r
129 this.Name = 'Save' ;
\r
132 FCKSaveCommand.prototype.Execute = function()
\r
134 // Get the linked field form.
\r
135 var oForm = FCK.GetParentForm() ;
\r
137 if ( typeof( oForm.onsubmit ) == 'function' )
\r
139 var bRet = oForm.onsubmit() ;
\r
140 if ( bRet != null && bRet === false )
\r
144 // Submit the form.
\r
145 // If there's a button named "submit" then the form.submit() function is masked and
\r
146 // can't be called in Mozilla, so we call the click() method of that button.
\r
147 if ( typeof( oForm.submit ) == 'function' )
\r
150 oForm.submit.click() ;
\r
153 FCKSaveCommand.prototype.GetState = function()
\r
155 return FCK_TRISTATE_OFF ;
\r
159 var FCKNewPageCommand = function()
\r
161 this.Name = 'NewPage' ;
\r
164 FCKNewPageCommand.prototype.Execute = function()
\r
166 FCKUndo.SaveUndoStep() ;
\r
167 FCK.SetData( '' ) ;
\r
168 FCKUndo.Typing = true ;
\r
172 FCKNewPageCommand.prototype.GetState = function()
\r
174 return FCK_TRISTATE_OFF ;
\r
177 // ### Source button
\r
178 var FCKSourceCommand = function()
\r
180 this.Name = 'Source' ;
\r
183 FCKSourceCommand.prototype.Execute = function()
\r
185 if ( FCKConfig.SourcePopup ) // Until v2.2, it was mandatory for FCKBrowserInfo.IsGecko.
\r
187 var iWidth = FCKConfig.ScreenWidth * 0.65 ;
\r
188 var iHeight = FCKConfig.ScreenHeight * 0.65 ;
\r
189 FCKDialog.OpenDialog( 'FCKDialog_Source', FCKLang.Source, 'dialog/fck_source.html', iWidth, iHeight, null, null, true ) ;
\r
192 FCK.SwitchEditMode() ;
\r
195 FCKSourceCommand.prototype.GetState = function()
\r
197 return ( FCK.EditMode == FCK_EDITMODE_WYSIWYG ? FCK_TRISTATE_OFF : FCK_TRISTATE_ON ) ;
\r
201 var FCKUndoCommand = function()
\r
203 this.Name = 'Undo' ;
\r
206 FCKUndoCommand.prototype.Execute = function()
\r
211 FCKUndoCommand.prototype.GetState = function()
\r
213 if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG )
\r
214 return FCK_TRISTATE_DISABLED ;
\r
215 return ( FCKUndo.CheckUndoState() ? FCK_TRISTATE_OFF : FCK_TRISTATE_DISABLED ) ;
\r
219 var FCKRedoCommand = function()
\r
221 this.Name = 'Redo' ;
\r
224 FCKRedoCommand.prototype.Execute = function()
\r
229 FCKRedoCommand.prototype.GetState = function()
\r
231 if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG )
\r
232 return FCK_TRISTATE_DISABLED ;
\r
233 return ( FCKUndo.CheckRedoState() ? FCK_TRISTATE_OFF : FCK_TRISTATE_DISABLED ) ;
\r
237 var FCKPageBreakCommand = function()
\r
239 this.Name = 'PageBreak' ;
\r
242 FCKPageBreakCommand.prototype.Execute = function()
\r
244 // Take an undo snapshot before changing the document
\r
245 FCKUndo.SaveUndoStep() ;
\r
247 // var e = FCK.EditorDocument.createElement( 'CENTER' ) ;
\r
248 // e.style.pageBreakAfter = 'always' ;
\r
250 // Tidy was removing the empty CENTER tags, so the following solution has
\r
251 // been found. It also validates correctly as XHTML 1.0 Strict.
\r
252 var e = FCK.EditorDocument.createElement( 'DIV' ) ;
\r
253 e.style.pageBreakAfter = 'always' ;
\r
254 e.innerHTML = '<span style="DISPLAY:none"> </span>' ;
\r
256 var oFakeImage = FCKDocumentProcessor_CreateFakeImage( 'FCK__PageBreak', e ) ;
\r
257 var oRange = new FCKDomRange( FCK.EditorWindow ) ;
\r
258 oRange.MoveToSelection() ;
\r
259 var oSplitInfo = oRange.SplitBlock() ;
\r
260 oRange.InsertNode( oFakeImage ) ;
\r
262 FCK.Events.FireEvent( 'OnSelectionChange' ) ;
\r
265 FCKPageBreakCommand.prototype.GetState = function()
\r
267 if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG )
\r
268 return FCK_TRISTATE_DISABLED ;
\r
269 return 0 ; // FCK_TRISTATE_OFF
\r
272 // FCKUnlinkCommand - by Johnny Egeland (johnny@coretrek.com)
\r
273 var FCKUnlinkCommand = function()
\r
275 this.Name = 'Unlink' ;
\r
278 FCKUnlinkCommand.prototype.Execute = function()
\r
280 // Take an undo snapshot before changing the document
\r
281 FCKUndo.SaveUndoStep() ;
\r
283 if ( FCKBrowserInfo.IsGeckoLike )
\r
285 var oLink = FCK.Selection.MoveToAncestorNode( 'A' ) ;
\r
286 // The unlink command can generate a span in Firefox, so let's do it our way. See #430
\r
288 FCKTools.RemoveOuterTags( oLink ) ;
\r
293 FCK.ExecuteNamedCommand( this.Name ) ;
\r
296 FCKUnlinkCommand.prototype.GetState = function()
\r
298 if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG )
\r
299 return FCK_TRISTATE_DISABLED ;
\r
300 var state = FCK.GetNamedCommandState( this.Name ) ;
\r
302 // Check that it isn't an anchor
\r
303 if ( state == FCK_TRISTATE_OFF && FCK.EditMode == FCK_EDITMODE_WYSIWYG )
\r
305 var oLink = FCKSelection.MoveToAncestorNode( 'A' ) ;
\r
306 var bIsAnchor = ( oLink && oLink.name.length > 0 && oLink.href.length == 0 ) ;
\r
308 state = FCK_TRISTATE_DISABLED ;
\r
314 var FCKVisitLinkCommand = function()
\r
316 this.Name = 'VisitLink';
\r
318 FCKVisitLinkCommand.prototype =
\r
320 GetState : function()
\r
322 if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG )
\r
323 return FCK_TRISTATE_DISABLED ;
\r
324 var state = FCK.GetNamedCommandState( 'Unlink' ) ;
\r
326 if ( state == FCK_TRISTATE_OFF )
\r
328 var el = FCKSelection.MoveToAncestorNode( 'A' ) ;
\r
330 state = FCK_TRISTATE_DISABLED ;
\r
336 Execute : function()
\r
338 var el = FCKSelection.MoveToAncestorNode( 'A' ) ;
\r
339 var url = el.getAttribute( '_fcksavedurl' ) || el.getAttribute( 'href', 2 ) ;
\r
341 // Check if it's a full URL.
\r
342 // If not full URL, we'll need to apply the BaseHref setting.
\r
343 if ( ! /:\/\//.test( url ) )
\r
345 var baseHref = FCKConfig.BaseHref ;
\r
346 var parentWindow = FCK.GetInstanceObject( 'parent' ) ;
\r
349 baseHref = parentWindow.document.location.href ;
\r
350 baseHref = baseHref.substring( 0, baseHref.lastIndexOf( '/' ) + 1 ) ;
\r
353 if ( /^\//.test( url ) )
\r
357 baseHref = baseHref.match( /^.*:\/\/+[^\/]+/ )[0] ;
\r
361 baseHref = parentWindow.document.location.protocol + '://' + parentWindow.parent.document.location.host ;
\r
365 url = baseHref + url ;
\r
368 if ( !window.open( url, '_blank' ) )
\r
369 alert( FCKLang.VisitLinkBlocked ) ;
\r
373 // FCKSelectAllCommand
\r
374 var FCKSelectAllCommand = function()
\r
376 this.Name = 'SelectAll' ;
\r
379 FCKSelectAllCommand.prototype.Execute = function()
\r
381 if ( FCK.EditMode == FCK_EDITMODE_WYSIWYG )
\r
383 FCK.ExecuteNamedCommand( 'SelectAll' ) ;
\r
387 // Select the contents of the textarea
\r
388 var textarea = FCK.EditingArea.Textarea ;
\r
389 if ( FCKBrowserInfo.IsIE )
\r
391 textarea.createTextRange().execCommand( 'SelectAll' ) ;
\r
395 textarea.selectionStart = 0 ;
\r
396 textarea.selectionEnd = textarea.value.length ;
\r
402 FCKSelectAllCommand.prototype.GetState = function()
\r
404 if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG )
\r
405 return FCK_TRISTATE_DISABLED ;
\r
406 return FCK_TRISTATE_OFF ;
\r
410 var FCKPasteCommand = function()
\r
412 this.Name = 'Paste' ;
\r
415 FCKPasteCommand.prototype =
\r
417 Execute : function()
\r
419 if ( FCKBrowserInfo.IsIE )
\r
422 FCK.ExecuteNamedCommand( 'Paste' ) ;
\r
425 GetState : function()
\r
427 if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG )
\r
428 return FCK_TRISTATE_DISABLED ;
\r
429 return FCK.GetNamedCommandState( 'Paste' ) ;
\r
434 var FCKRuleCommand = function()
\r
436 this.Name = 'Rule' ;
\r
439 FCKRuleCommand.prototype =
\r
441 Execute : function()
\r
443 FCKUndo.SaveUndoStep() ;
\r
444 FCK.InsertElement( 'hr' ) ;
\r
447 GetState : function()
\r
449 if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG )
\r
450 return FCK_TRISTATE_DISABLED ;
\r
451 return FCK.GetNamedCommandState( 'InsertHorizontalRule' ) ;
\r
455 // FCKCutCopyCommand
\r
456 var FCKCutCopyCommand = function( isCut )
\r
458 this.Name = isCut ? 'Cut' : 'Copy' ;
\r
461 FCKCutCopyCommand.prototype =
\r
463 Execute : function()
\r
465 var enabled = false ;
\r
467 if ( FCKBrowserInfo.IsIE )
\r
469 // The following seems to be the only reliable way to detect that
\r
470 // cut/copy is enabled in IE. It will fire the oncut/oncopy event
\r
471 // only if the security settings enabled the command to execute.
\r
473 var onEvent = function()
\r
478 var eventName = 'on' + this.Name.toLowerCase() ;
\r
480 FCK.EditorDocument.body.attachEvent( eventName, onEvent ) ;
\r
481 FCK.ExecuteNamedCommand( this.Name ) ;
\r
482 FCK.EditorDocument.body.detachEvent( eventName, onEvent ) ;
\r
488 // Other browsers throw an error if the command is disabled.
\r
489 FCK.ExecuteNamedCommand( this.Name ) ;
\r
496 alert( FCKLang[ 'PasteError' + this.Name ] ) ;
\r
499 GetState : function()
\r
501 // Strangely, the Cut command happens to have the correct states for
\r
502 // both Copy and Cut in all browsers.
\r
503 return FCK.EditMode != FCK_EDITMODE_WYSIWYG ?
\r
504 FCK_TRISTATE_DISABLED :
\r
505 FCK.GetNamedCommandState( 'Cut' ) ;
\r
509 var FCKAnchorDeleteCommand = function()
\r
511 this.Name = 'AnchorDelete' ;
\r
514 FCKAnchorDeleteCommand.prototype =
\r
516 Execute : function()
\r
518 if (FCK.Selection.GetType() == 'Control')
\r
520 FCK.Selection.Delete();
\r
524 var oFakeImage = FCK.Selection.GetSelectedElement() ;
\r
527 if ( oFakeImage.tagName == 'IMG' && oFakeImage.getAttribute('_fckanchor') )
\r
528 oAnchor = FCK.GetRealElement( oFakeImage ) ;
\r
530 oFakeImage = null ;
\r
533 //Search for a real anchor
\r
536 oAnchor = FCK.Selection.MoveToAncestorNode( 'A' ) ;
\r
538 FCK.Selection.SelectNode( oAnchor ) ;
\r
541 // If it's also a link, then just remove the name and exit
\r
542 if ( oAnchor.href.length != 0 )
\r
544 oAnchor.removeAttribute( 'name' ) ;
\r
545 // Remove temporary class for IE
\r
546 if ( FCKBrowserInfo.IsIE )
\r
547 oAnchor.className = oAnchor.className.replace( FCKRegexLib.FCK_Class, '' ) ;
\r
551 // We need to remove the anchor
\r
552 // If we got a fake image, then just remove it and we're done
\r
555 oFakeImage.parentNode.removeChild( oFakeImage ) ;
\r
558 // Empty anchor, so just remove it
\r
559 if ( oAnchor.innerHTML.length == 0 )
\r
561 oAnchor.parentNode.removeChild( oAnchor ) ;
\r
564 // Anchor with content, leave the content
\r
565 FCKTools.RemoveOuterTags( oAnchor ) ;
\r
567 if ( FCKBrowserInfo.IsGecko )
\r
568 FCK.Selection.Collapse( true ) ;
\r
571 GetState : function()
\r
573 if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG )
\r
574 return FCK_TRISTATE_DISABLED ;
\r
575 return FCK.GetNamedCommandState( 'Unlink') ;
\r
579 var FCKDeleteDivCommand = function()
\r
582 FCKDeleteDivCommand.prototype =
\r
584 GetState : function()
\r
586 if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG )
\r
587 return FCK_TRISTATE_DISABLED ;
\r
589 var node = FCKSelection.GetParentElement() ;
\r
590 var path = new FCKElementPath( node ) ;
\r
591 return path.BlockLimit && path.BlockLimit.nodeName.IEquals( 'div' ) ? FCK_TRISTATE_OFF : FCK_TRISTATE_DISABLED ;
\r
594 Execute : function()
\r
596 // Create an undo snapshot before doing anything.
\r
597 FCKUndo.SaveUndoStep() ;
\r
599 // Find out the nodes to delete.
\r
600 var nodes = FCKDomTools.GetSelectedDivContainers() ;
\r
602 // Remember the current selection position.
\r
603 var range = new FCKDomRange( FCK.EditorWindow ) ;
\r
604 range.MoveToSelection() ;
\r
605 var bookmark = range.CreateBookmark() ;
\r
607 // Delete the container DIV node.
\r
608 for ( var i = 0 ; i < nodes.length ; i++)
\r
609 FCKDomTools.RemoveNode( nodes[i], true ) ;
\r
611 // Restore selection.
\r
612 range.MoveToBookmark( bookmark ) ;
\r
618 var FCKNbsp = function()
\r
620 this.Name = 'Non Breaking Space' ;
\r
623 FCKNbsp.prototype =
\r
625 Execute : function()
\r
627 FCK.InsertHtml( ' ' ) ;
\r
630 GetState : function()
\r
632 return ( FCK.EditMode != FCK_EDITMODE_WYSIWYG ? FCK_TRISTATE_DISABLED : FCK_TRISTATE_OFF ) ;
\r