import rt 3.8.7
[freeside.git] / rt / share / html / NoAuth / RichText / FCKeditor / editor / _source / commandclasses / fck_othercommands.js
1 /*\r
2  * FCKeditor - The text editor for Internet - http://www.fckeditor.net\r
3  * Copyright (C) 2003-2009 Frederico Caldeira Knabben\r
4  *\r
5  * == BEGIN LICENSE ==\r
6  *\r
7  * Licensed under the terms of any of the following licenses at your\r
8  * choice:\r
9  *\r
10  *  - GNU General Public License Version 2 or later (the "GPL")\r
11  *    http://www.gnu.org/licenses/gpl.html\r
12  *\r
13  *  - GNU Lesser General Public License Version 2.1 or later (the "LGPL")\r
14  *    http://www.gnu.org/licenses/lgpl.html\r
15  *\r
16  *  - Mozilla Public License Version 1.1 or later (the "MPL")\r
17  *    http://www.mozilla.org/MPL/MPL-1.1.html\r
18  *\r
19  * == END LICENSE ==\r
20  *\r
21  * Definition of other commands that are not available internaly in the\r
22  * browser (see FCKNamedCommand).\r
23  */\r
24 \r
25 // ### General Dialog Box Commands.\r
26 var FCKDialogCommand = function( name, title, url, width, height, getStateFunction, getStateParam, customValue )\r
27 {\r
28         this.Name       = name ;\r
29         this.Title      = title ;\r
30         this.Url        = url ;\r
31         this.Width      = width ;\r
32         this.Height     = height ;\r
33         this.CustomValue = customValue ;\r
34 \r
35         this.GetStateFunction   = getStateFunction ;\r
36         this.GetStateParam              = getStateParam ;\r
37 \r
38         this.Resizable = false ;\r
39 }\r
40 \r
41 FCKDialogCommand.prototype.Execute = function()\r
42 {\r
43         FCKDialog.OpenDialog( 'FCKDialog_' + this.Name , this.Title, this.Url, this.Width, this.Height, this.CustomValue, null, this.Resizable ) ;\r
44 }\r
45 \r
46 FCKDialogCommand.prototype.GetState = function()\r
47 {\r
48         if ( this.GetStateFunction )\r
49                 return this.GetStateFunction( this.GetStateParam ) ;\r
50         else\r
51                 return FCK.EditMode == FCK_EDITMODE_WYSIWYG ? FCK_TRISTATE_OFF : FCK_TRISTATE_DISABLED ;\r
52 }\r
53 \r
54 // Generic Undefined command (usually used when a command is under development).\r
55 var FCKUndefinedCommand = function()\r
56 {\r
57         this.Name = 'Undefined' ;\r
58 }\r
59 \r
60 FCKUndefinedCommand.prototype.Execute = function()\r
61 {\r
62         alert( FCKLang.NotImplemented ) ;\r
63 }\r
64 \r
65 FCKUndefinedCommand.prototype.GetState = function()\r
66 {\r
67         return FCK_TRISTATE_OFF ;\r
68 }\r
69 \r
70 \r
71 // ### FormatBlock\r
72 var FCKFormatBlockCommand = function()\r
73 {}\r
74 \r
75 FCKFormatBlockCommand.prototype =\r
76 {\r
77         Name : 'FormatBlock',\r
78 \r
79         Execute : FCKStyleCommand.prototype.Execute,\r
80 \r
81         GetState : function()\r
82         {\r
83                 return FCK.EditorDocument ? FCK_TRISTATE_OFF : FCK_TRISTATE_DISABLED ;\r
84         }\r
85 };\r
86 \r
87 // ### FontName\r
88 \r
89 var FCKFontNameCommand = function()\r
90 {}\r
91 \r
92 FCKFontNameCommand.prototype =\r
93 {\r
94         Name            : 'FontName',\r
95         Execute         : FCKStyleCommand.prototype.Execute,\r
96         GetState        : FCKFormatBlockCommand.prototype.GetState\r
97 };\r
98 \r
99 // ### FontSize\r
100 var FCKFontSizeCommand = function()\r
101 {}\r
102 \r
103 FCKFontSizeCommand.prototype =\r
104 {\r
105         Name            : 'FontSize',\r
106         Execute         : FCKStyleCommand.prototype.Execute,\r
107         GetState        : FCKFormatBlockCommand.prototype.GetState\r
108 };\r
109 \r
110 // ### Preview\r
111 var FCKPreviewCommand = function()\r
112 {\r
113         this.Name = 'Preview' ;\r
114 }\r
115 \r
116 FCKPreviewCommand.prototype.Execute = function()\r
117 {\r
118      FCK.Preview() ;\r
119 }\r
120 \r
121 FCKPreviewCommand.prototype.GetState = function()\r
122 {\r
123         return FCK_TRISTATE_OFF ;\r
124 }\r
125 \r
126 // ### Save\r
127 var FCKSaveCommand = function()\r
128 {\r
129         this.Name = 'Save' ;\r
130 }\r
131 \r
132 FCKSaveCommand.prototype.Execute = function()\r
133 {\r
134         // Get the linked field form.\r
135         var oForm = FCK.GetParentForm() ;\r
136 \r
137         if ( typeof( oForm.onsubmit ) == 'function' )\r
138         {\r
139                 var bRet = oForm.onsubmit() ;\r
140                 if ( bRet != null && bRet === false )\r
141                         return ;\r
142         }\r
143 \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
148                 oForm.submit() ;\r
149         else\r
150                 oForm.submit.click() ;\r
151 }\r
152 \r
153 FCKSaveCommand.prototype.GetState = function()\r
154 {\r
155         return FCK_TRISTATE_OFF ;\r
156 }\r
157 \r
158 // ### NewPage\r
159 var FCKNewPageCommand = function()\r
160 {\r
161         this.Name = 'NewPage' ;\r
162 }\r
163 \r
164 FCKNewPageCommand.prototype.Execute = function()\r
165 {\r
166         FCKUndo.SaveUndoStep() ;\r
167         FCK.SetData( '' ) ;\r
168         FCKUndo.Typing = true ;\r
169         FCK.Focus() ;\r
170 }\r
171 \r
172 FCKNewPageCommand.prototype.GetState = function()\r
173 {\r
174         return FCK_TRISTATE_OFF ;\r
175 }\r
176 \r
177 // ### Source button\r
178 var FCKSourceCommand = function()\r
179 {\r
180         this.Name = 'Source' ;\r
181 }\r
182 \r
183 FCKSourceCommand.prototype.Execute = function()\r
184 {\r
185         if ( FCKConfig.SourcePopup )    // Until v2.2, it was mandatory for FCKBrowserInfo.IsGecko.\r
186         {\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
190         }\r
191         else\r
192             FCK.SwitchEditMode() ;\r
193 }\r
194 \r
195 FCKSourceCommand.prototype.GetState = function()\r
196 {\r
197         return ( FCK.EditMode == FCK_EDITMODE_WYSIWYG ? FCK_TRISTATE_OFF : FCK_TRISTATE_ON ) ;\r
198 }\r
199 \r
200 // ### Undo\r
201 var FCKUndoCommand = function()\r
202 {\r
203         this.Name = 'Undo' ;\r
204 }\r
205 \r
206 FCKUndoCommand.prototype.Execute = function()\r
207 {\r
208         FCKUndo.Undo() ;\r
209 }\r
210 \r
211 FCKUndoCommand.prototype.GetState = function()\r
212 {\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
216 }\r
217 \r
218 // ### Redo\r
219 var FCKRedoCommand = function()\r
220 {\r
221         this.Name = 'Redo' ;\r
222 }\r
223 \r
224 FCKRedoCommand.prototype.Execute = function()\r
225 {\r
226         FCKUndo.Redo() ;\r
227 }\r
228 \r
229 FCKRedoCommand.prototype.GetState = function()\r
230 {\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
234 }\r
235 \r
236 // ### Page Break\r
237 var FCKPageBreakCommand = function()\r
238 {\r
239         this.Name = 'PageBreak' ;\r
240 }\r
241 \r
242 FCKPageBreakCommand.prototype.Execute = function()\r
243 {\r
244         // Take an undo snapshot before changing the document\r
245         FCKUndo.SaveUndoStep() ;\r
246 \r
247 //      var e = FCK.EditorDocument.createElement( 'CENTER' ) ;\r
248 //      e.style.pageBreakAfter = 'always' ;\r
249 \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">&nbsp;</span>' ;\r
255 \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
261 \r
262         FCK.Events.FireEvent( 'OnSelectionChange' ) ;\r
263 }\r
264 \r
265 FCKPageBreakCommand.prototype.GetState = function()\r
266 {\r
267         if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG )\r
268                 return FCK_TRISTATE_DISABLED ;\r
269         return 0 ; // FCK_TRISTATE_OFF\r
270 }\r
271 \r
272 // FCKUnlinkCommand - by Johnny Egeland (johnny@coretrek.com)\r
273 var FCKUnlinkCommand = function()\r
274 {\r
275         this.Name = 'Unlink' ;\r
276 }\r
277 \r
278 FCKUnlinkCommand.prototype.Execute = function()\r
279 {\r
280         // Take an undo snapshot before changing the document\r
281         FCKUndo.SaveUndoStep() ;\r
282 \r
283         if ( FCKBrowserInfo.IsGeckoLike )\r
284         {\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
287                 if ( oLink )\r
288                         FCKTools.RemoveOuterTags( oLink ) ;\r
289 \r
290                 return ;\r
291         }\r
292 \r
293         FCK.ExecuteNamedCommand( this.Name ) ;\r
294 }\r
295 \r
296 FCKUnlinkCommand.prototype.GetState = function()\r
297 {\r
298         if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG )\r
299                 return FCK_TRISTATE_DISABLED ;\r
300         var state = FCK.GetNamedCommandState( this.Name ) ;\r
301 \r
302         // Check that it isn't an anchor\r
303         if ( state == FCK_TRISTATE_OFF && FCK.EditMode == FCK_EDITMODE_WYSIWYG )\r
304         {\r
305                 var oLink = FCKSelection.MoveToAncestorNode( 'A' ) ;\r
306                 var bIsAnchor = ( oLink && oLink.name.length > 0 && oLink.href.length == 0 ) ;\r
307                 if ( bIsAnchor )\r
308                         state = FCK_TRISTATE_DISABLED ;\r
309         }\r
310 \r
311         return state ;\r
312 }\r
313 \r
314 var FCKVisitLinkCommand = function()\r
315 {\r
316         this.Name = 'VisitLink';\r
317 }\r
318 FCKVisitLinkCommand.prototype =\r
319 {\r
320         GetState : function()\r
321         {\r
322                 if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG )\r
323                         return FCK_TRISTATE_DISABLED ;\r
324                 var state = FCK.GetNamedCommandState( 'Unlink' ) ;\r
325 \r
326                 if ( state == FCK_TRISTATE_OFF )\r
327                 {\r
328                         var el = FCKSelection.MoveToAncestorNode( 'A' ) ;\r
329                         if ( !el.href )\r
330                                 state = FCK_TRISTATE_DISABLED ;\r
331                 }\r
332 \r
333                 return state ;\r
334         },\r
335 \r
336         Execute : function()\r
337         {\r
338                 var el = FCKSelection.MoveToAncestorNode( 'A' ) ;\r
339                 var url = el.getAttribute( '_fcksavedurl' ) || el.getAttribute( 'href', 2 ) ;\r
340 \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
344                 {\r
345                         var baseHref = FCKConfig.BaseHref ;\r
346                         var parentWindow = FCK.GetInstanceObject( 'parent' ) ;\r
347                         if ( !baseHref )\r
348                         {\r
349                                 baseHref = parentWindow.document.location.href ;\r
350                                 baseHref = baseHref.substring( 0, baseHref.lastIndexOf( '/' ) + 1 ) ;\r
351                         }\r
352 \r
353                         if ( /^\//.test( url ) )\r
354                         {\r
355                                 try\r
356                                 {\r
357                                         baseHref = baseHref.match( /^.*:\/\/+[^\/]+/ )[0] ;\r
358                                 }\r
359                                 catch ( e )\r
360                                 {\r
361                                         baseHref = parentWindow.document.location.protocol + '://' + parentWindow.parent.document.location.host ;\r
362                                 }\r
363                         }\r
364 \r
365                         url = baseHref + url ;\r
366                 }\r
367 \r
368                 if ( !window.open( url, '_blank' ) )\r
369                         alert( FCKLang.VisitLinkBlocked ) ;\r
370         }\r
371 } ;\r
372 \r
373 // FCKSelectAllCommand\r
374 var FCKSelectAllCommand = function()\r
375 {\r
376         this.Name = 'SelectAll' ;\r
377 }\r
378 \r
379 FCKSelectAllCommand.prototype.Execute = function()\r
380 {\r
381         if ( FCK.EditMode == FCK_EDITMODE_WYSIWYG )\r
382         {\r
383                 FCK.ExecuteNamedCommand( 'SelectAll' ) ;\r
384         }\r
385         else\r
386         {\r
387                 // Select the contents of the textarea\r
388                 var textarea = FCK.EditingArea.Textarea ;\r
389                 if ( FCKBrowserInfo.IsIE )\r
390                 {\r
391                         textarea.createTextRange().execCommand( 'SelectAll' ) ;\r
392                 }\r
393                 else\r
394                 {\r
395                         textarea.selectionStart = 0 ;\r
396                         textarea.selectionEnd = textarea.value.length ;\r
397                 }\r
398                 textarea.focus() ;\r
399         }\r
400 }\r
401 \r
402 FCKSelectAllCommand.prototype.GetState = function()\r
403 {\r
404         if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG )\r
405                 return FCK_TRISTATE_DISABLED ;\r
406         return FCK_TRISTATE_OFF ;\r
407 }\r
408 \r
409 // FCKPasteCommand\r
410 var FCKPasteCommand = function()\r
411 {\r
412         this.Name = 'Paste' ;\r
413 }\r
414 \r
415 FCKPasteCommand.prototype =\r
416 {\r
417         Execute : function()\r
418         {\r
419                 if ( FCKBrowserInfo.IsIE )\r
420                         FCK.Paste() ;\r
421                 else\r
422                         FCK.ExecuteNamedCommand( 'Paste' ) ;\r
423         },\r
424 \r
425         GetState : function()\r
426         {\r
427                 if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG )\r
428                         return FCK_TRISTATE_DISABLED ;\r
429                 return FCK.GetNamedCommandState( 'Paste' ) ;\r
430         }\r
431 } ;\r
432 \r
433 // FCKRuleCommand\r
434 var FCKRuleCommand = function()\r
435 {\r
436         this.Name = 'Rule' ;\r
437 }\r
438 \r
439 FCKRuleCommand.prototype =\r
440 {\r
441         Execute : function()\r
442         {\r
443                 FCKUndo.SaveUndoStep() ;\r
444                 FCK.InsertElement( 'hr' ) ;\r
445         },\r
446 \r
447         GetState : function()\r
448         {\r
449                 if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG )\r
450                         return FCK_TRISTATE_DISABLED ;\r
451                 return FCK.GetNamedCommandState( 'InsertHorizontalRule' ) ;\r
452         }\r
453 } ;\r
454 \r
455 // FCKCutCopyCommand\r
456 var FCKCutCopyCommand = function( isCut )\r
457 {\r
458         this.Name = isCut ? 'Cut' : 'Copy' ;\r
459 }\r
460 \r
461 FCKCutCopyCommand.prototype =\r
462 {\r
463         Execute : function()\r
464         {\r
465                 var enabled = false ;\r
466 \r
467                 if ( FCKBrowserInfo.IsIE )\r
468                 {\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
472 \r
473                         var onEvent = function()\r
474                         {\r
475                                 enabled = true ;\r
476                         } ;\r
477 \r
478                         var eventName = 'on' + this.Name.toLowerCase() ;\r
479 \r
480                         FCK.EditorDocument.body.attachEvent( eventName, onEvent ) ;\r
481                         FCK.ExecuteNamedCommand( this.Name ) ;\r
482                         FCK.EditorDocument.body.detachEvent( eventName, onEvent ) ;\r
483                 }\r
484                 else\r
485                 {\r
486                         try\r
487                         {\r
488                                 // Other browsers throw an error if the command is disabled.\r
489                                 FCK.ExecuteNamedCommand( this.Name ) ;\r
490                                 enabled = true ;\r
491                         }\r
492                         catch(e){}\r
493                 }\r
494 \r
495                 if ( !enabled )\r
496                         alert( FCKLang[ 'PasteError' + this.Name ] ) ;\r
497         },\r
498 \r
499         GetState : function()\r
500         {\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
506         }\r
507 };\r
508 \r
509 var FCKAnchorDeleteCommand = function()\r
510 {\r
511         this.Name = 'AnchorDelete' ;\r
512 }\r
513 \r
514 FCKAnchorDeleteCommand.prototype =\r
515 {\r
516         Execute : function()\r
517         {\r
518                 if (FCK.Selection.GetType() == 'Control')\r
519                 {\r
520                         FCK.Selection.Delete();\r
521                 }\r
522                 else\r
523                 {\r
524                         var oFakeImage = FCK.Selection.GetSelectedElement() ;\r
525                         if ( oFakeImage )\r
526                         {\r
527                                 if ( oFakeImage.tagName == 'IMG' && oFakeImage.getAttribute('_fckanchor') )\r
528                                         oAnchor = FCK.GetRealElement( oFakeImage ) ;\r
529                                 else\r
530                                         oFakeImage = null ;\r
531                         }\r
532 \r
533                         //Search for a real anchor\r
534                         if ( !oFakeImage )\r
535                         {\r
536                                 oAnchor = FCK.Selection.MoveToAncestorNode( 'A' ) ;\r
537                                 if ( oAnchor )\r
538                                         FCK.Selection.SelectNode( oAnchor ) ;\r
539                         }\r
540 \r
541                         // If it's also a link, then just remove the name and exit\r
542                         if ( oAnchor.href.length != 0 )\r
543                         {\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
548                                 return ;\r
549                         }\r
550 \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
553                         if ( oFakeImage )\r
554                         {\r
555                                 oFakeImage.parentNode.removeChild( oFakeImage ) ;\r
556                                 return ;\r
557                         }\r
558                         // Empty anchor, so just remove it\r
559                         if ( oAnchor.innerHTML.length == 0 )\r
560                         {\r
561                                 oAnchor.parentNode.removeChild( oAnchor ) ;\r
562                                 return ;\r
563                         }\r
564                         // Anchor with content, leave the content\r
565                         FCKTools.RemoveOuterTags( oAnchor ) ;\r
566                 }\r
567                 if ( FCKBrowserInfo.IsGecko )\r
568                         FCK.Selection.Collapse( true ) ;\r
569         },\r
570 \r
571         GetState : function()\r
572         {\r
573                 if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG )\r
574                         return FCK_TRISTATE_DISABLED ;\r
575                 return FCK.GetNamedCommandState( 'Unlink') ;\r
576         }\r
577 };\r
578 \r
579 var FCKDeleteDivCommand = function()\r
580 {\r
581 }\r
582 FCKDeleteDivCommand.prototype =\r
583 {\r
584         GetState : function()\r
585         {\r
586                 if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG )\r
587                         return FCK_TRISTATE_DISABLED ;\r
588 \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
592         },\r
593 \r
594         Execute : function()\r
595         {\r
596                 // Create an undo snapshot before doing anything.\r
597                 FCKUndo.SaveUndoStep() ;\r
598 \r
599                 // Find out the nodes to delete.\r
600                 var nodes = FCKDomTools.GetSelectedDivContainers() ;\r
601 \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
606 \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
610 \r
611                 // Restore selection.\r
612                 range.MoveToBookmark( bookmark ) ;\r
613                 range.Select() ;\r
614         }\r
615 } ;\r
616 \r
617 // FCKRuleCommand\r
618 var FCKNbsp = function()\r
619 {\r
620         this.Name = 'Non Breaking Space' ;\r
621 }\r
622 \r
623 FCKNbsp.prototype =\r
624 {\r
625         Execute : function()\r
626         {\r
627                 FCK.InsertHtml( '&nbsp;' ) ;\r
628         },\r
629 \r
630         GetState : function()\r
631         {\r
632                 return ( FCK.EditMode != FCK_EDITMODE_WYSIWYG ? FCK_TRISTATE_DISABLED : FCK_TRISTATE_OFF ) ;\r
633         }\r
634 } ;\r