]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - include/javascript/tiny_mce/classes/EditorManager.js
Release 6.5.0
[Github/sugarcrm.git] / include / javascript / tiny_mce / classes / EditorManager.js
1 /**
2  * EditorManager.js
3  *
4  * Copyright 2009, Moxiecode Systems AB
5  * Released under LGPL License.
6  *
7  * License: http://tinymce.moxiecode.com/license
8  * Contributing: http://tinymce.moxiecode.com/contributing
9  */
10
11 (function(tinymce) {
12         /**
13          * @class tinymce
14          */
15
16         // Shorten names
17         var each = tinymce.each, extend = tinymce.extend,
18                 DOM = tinymce.DOM, Event = tinymce.dom.Event,
19                 ThemeManager = tinymce.ThemeManager, PluginManager = tinymce.PluginManager,
20                 explode = tinymce.explode,
21                 Dispatcher = tinymce.util.Dispatcher, undefined, instanceCounter = 0;
22
23         // Setup some URLs where the editor API is located and where the document is
24         tinymce.documentBaseURL = window.location.href.replace(/[\?#].*$/, '').replace(/[\/\\][^\/]+$/, '');
25         if (!/[\/\\]$/.test(tinymce.documentBaseURL))
26                 tinymce.documentBaseURL += '/';
27
28         tinymce.baseURL = new tinymce.util.URI(tinymce.documentBaseURL).toAbsolute(tinymce.baseURL);
29
30         /**
31          * Absolute baseURI for the installation path of TinyMCE.
32          *
33          * @property baseURI
34          * @type tinymce.util.URI
35          */
36         tinymce.baseURI = new tinymce.util.URI(tinymce.baseURL);
37
38         // Add before unload listener
39         // This was required since IE was leaking memory if you added and removed beforeunload listeners
40         // with attachEvent/detatchEvent so this only adds one listener and instances can the attach to the onBeforeUnload event
41         tinymce.onBeforeUnload = new Dispatcher(tinymce);
42
43         // Must be on window or IE will leak if the editor is placed in frame or iframe
44         Event.add(window, 'beforeunload', function(e) {
45                 tinymce.onBeforeUnload.dispatch(tinymce, e);
46         });
47
48         /**
49          * Fires when a new editor instance is added to the tinymce collection.
50          *
51          * @event onAddEditor
52          * @param {tinymce} sender TinyMCE root class/namespace.
53          * @param {tinymce.Editor} editor Editor instance.
54          * @example
55          * tinyMCE.execCommand("mceAddControl", false, "some_textarea");
56          * tinyMCE.onAddEditor.add(function(mgr,ed) {
57          *     console.debug('A new editor is available' + ed.id);
58          * });
59          */
60         tinymce.onAddEditor = new Dispatcher(tinymce);
61
62         /**
63          * Fires when an editor instance is removed from the tinymce collection.
64          *
65          * @event onRemoveEditor
66          * @param {tinymce} sender TinyMCE root class/namespace.
67          * @param {tinymce.Editor} editor Editor instance.
68          */
69         tinymce.onRemoveEditor = new Dispatcher(tinymce);
70
71         tinymce.EditorManager = extend(tinymce, {
72                 /**
73                  * Collection of editor instances.
74                  *
75                  * @property editors
76                  * @type Object
77                  * @example
78                  * for (edId in tinyMCE.editors)
79                  *     tinyMCE.editors[edId].save();
80                  */
81                 editors : [],
82
83                 /**
84                  * Collection of language pack data.
85                  *
86                  * @property i18n
87                  * @type Object
88                  */
89                 i18n : {},
90
91                 /**
92                  * Currently active editor instance.
93                  *
94                  * @property activeEditor
95                  * @type tinymce.Editor
96                  * @example
97                  * tinyMCE.activeEditor.selection.getContent();
98                  * tinymce.EditorManager.activeEditor.selection.getContent();
99                  */
100                 activeEditor : null,
101
102                 /**
103                  * Initializes a set of editors. This method will create a bunch of editors based in the input.
104                  *
105                  * @method init
106                  * @param {Object} s Settings object to be passed to each editor instance.
107                  * @example
108                  * // Initializes a editor using the longer method
109                  * tinymce.EditorManager.init({
110                  *    some_settings : 'some value'
111                  * });
112                  * 
113                  * // Initializes a editor instance using the shorter version
114                  * tinyMCE.init({
115                  *    some_settings : 'some value'
116                  * });
117                  */
118                 init : function(s) {
119                         var t = this, pl, sl = tinymce.ScriptLoader, e, el = [], ed;
120
121                         function execCallback(se, n, s) {
122                                 var f = se[n];
123
124                                 if (!f)
125                                         return;
126
127                                 if (tinymce.is(f, 'string')) {
128                                         s = f.replace(/\.\w+$/, '');
129                                         s = s ? tinymce.resolve(s) : 0;
130                                         f = tinymce.resolve(f);
131                                 }
132
133                                 return f.apply(s || this, Array.prototype.slice.call(arguments, 2));
134                         };
135
136                         s = extend({
137                                 theme : "simple",
138                                 language : "en"
139                         }, s);
140
141                         t.settings = s;
142
143                         // Legacy call
144                         Event.add(document, 'init', function() {
145                                 var l, co;
146
147                                 execCallback(s, 'onpageload');
148
149                                 switch (s.mode) {
150                                         case "exact":
151                                                 l = s.elements || '';
152
153                                                 if(l.length > 0) {
154                                                         each(explode(l), function(v) {
155                                                                 if (DOM.get(v)) {
156                                                                         ed = new tinymce.Editor(v, s);
157                                                                         el.push(ed);
158                                                                         ed.render(1);
159                                                                 } else {
160                                                                         each(document.forms, function(f) {
161                                                                                 each(f.elements, function(e) {
162                                                                                         if (e.name === v) {
163                                                                                                 v = 'mce_editor_' + instanceCounter++;
164                                                                                                 DOM.setAttrib(e, 'id', v);
165
166                                                                                                 ed = new tinymce.Editor(v, s);
167                                                                                                 el.push(ed);
168                                                                                                 ed.render(1);
169                                                                                         }
170                                                                                 });
171                                                                         });
172                                                                 }
173                                                         });
174                                                 }
175                                                 break;
176
177                                         case "textareas":
178                                         case "specific_textareas":
179                                                 function hasClass(n, c) {
180                                                         return c.constructor === RegExp ? c.test(n.className) : DOM.hasClass(n, c);
181                                                 };
182
183                                                 each(DOM.select('textarea'), function(v) {
184                                                         if (s.editor_deselector && hasClass(v, s.editor_deselector))
185                                                                 return;
186
187                                                         if (!s.editor_selector || hasClass(v, s.editor_selector)) {
188                                                                 // Can we use the name
189                                                                 e = DOM.get(v.name);
190                                                                 if (!v.id && !e)
191                                                                         v.id = v.name;
192
193                                                                 // Generate unique name if missing or already exists
194                                                                 if (!v.id || t.get(v.id))
195                                                                         v.id = DOM.uniqueId();
196
197                                                                 ed = new tinymce.Editor(v.id, s);
198                                                                 el.push(ed);
199                                                                 ed.render(1);
200                                                         }
201                                                 });
202                                                 break;
203                                 }
204
205                                 // Call onInit when all editors are initialized
206                                 if (s.oninit) {
207                                         l = co = 0;
208
209                                         each(el, function(ed) {
210                                                 co++;
211
212                                                 if (!ed.initialized) {
213                                                         // Wait for it
214                                                         ed.onInit.add(function() {
215                                                                 l++;
216
217                                                                 // All done
218                                                                 if (l == co)
219                                                                         execCallback(s, 'oninit');
220                                                         });
221                                                 } else
222                                                         l++;
223
224                                                 // All done
225                                                 if (l == co)
226                                                         execCallback(s, 'oninit');                                      
227                                         });
228                                 }
229                         });
230                 },
231
232                 /**
233                  * Returns a editor instance by id.
234                  *
235                  * @method get
236                  * @param {String/Number} id Editor instance id or index to return.
237                  * @return {tinymce.Editor} Editor instance to return.
238                  * @example
239                  * // Adds an onclick event to an editor by id (shorter version)
240                  * tinyMCE.get('mytextbox').onClick.add(function(ed, e) {
241                  *    ed.windowManager.alert('Hello world!');
242                  * });
243                  * 
244                  * // Adds an onclick event to an editor by id (longer version)
245                  * tinymce.EditorManager.get('mytextbox').onClick.add(function(ed, e) {
246                  *    ed.windowManager.alert('Hello world!');
247                  * });
248                  */
249                 get : function(id) {
250                         if (id === undefined)
251                                 return this.editors;
252
253                         return this.editors[id];
254                 },
255
256                 /**
257                  * Returns a editor instance by id. This method was added for compatibility with the 2.x branch.
258                  *
259                  * @method getInstanceById
260                  * @param {String} id Editor instance id to return.
261                  * @return {tinymce.Editor} Editor instance to return.
262                  * @deprecated Use get method instead.
263                  * @see #get
264                  */
265                 getInstanceById : function(id) {
266                         return this.get(id);
267                 },
268
269                 /**
270                  * Adds an editor instance to the editor collection. This will also set it as the active editor.
271                  *
272                  * @method add
273                  * @param {tinymce.Editor} editor Editor instance to add to the collection.
274                  * @return {tinymce.Editor} The same instance that got passed in.
275                  */
276                 add : function(editor) {
277                         var self = this, editors = self.editors;
278
279                         // Add named and index editor instance
280                         editors[editor.id] = editor;
281                         editors.push(editor);
282
283                         self._setActive(editor);
284                         self.onAddEditor.dispatch(self, editor);
285
286                         // #ifdef jquery
287
288                         // Patch the tinymce.Editor instance with jQuery adapter logic
289                         if (tinymce.adapter)
290                                 tinymce.adapter.patchEditor(editor);
291
292                         // #endif
293
294                         return editor;
295                 },
296
297                 /**
298                  * Removes a editor instance from the collection.
299                  *
300                  * @method remove
301                  * @param {tinymce.Editor} e Editor instance to remove.
302                  * @return {tinymce.Editor} The editor that got passed in will be return if it was found otherwise null.
303                  */
304                 remove : function(editor) {
305                         var t = this, i, editors = t.editors;
306
307                         // Not in the collection
308                         if (!editors[editor.id])
309                                 return null;
310
311                         delete editors[editor.id];
312
313                         for (i = 0; i < editors.length; i++) {
314                                 if (editors[i] == editor) {
315                                         editors.splice(i, 1);
316                                         break;
317                                 }
318                         }
319
320                         // Select another editor since the active one was removed
321                         if (t.activeEditor == editor)
322                                 t._setActive(editors[0]);
323
324                         editor.destroy();
325                         t.onRemoveEditor.dispatch(t, editor);
326
327                         return editor;
328                 },
329
330                 /**
331                  * Executes a specific command on the currently active editor.
332                  *
333                  * @method execCommand
334                  * @param {String} c Command to perform for example Bold.
335                  * @param {Boolean} u Optional boolean state if a UI should be presented for the command or not.
336                  * @param {String} v Optional value parameter like for example an URL to a link.
337                  * @return {Boolean} true/false if the command was executed or not.
338                  */
339                 execCommand : function(c, u, v) {
340                         var t = this, ed = t.get(v), w;
341
342                         // Manager commands
343                         switch (c) {
344                                 case "mceFocus":
345                                         ed.focus();
346                                         return true;
347
348                                 case "mceAddEditor":
349                                 case "mceAddControl":
350                                         if (!t.get(v))
351                                                 new tinymce.Editor(v, t.settings).render();
352
353                                         return true;
354
355                                 case "mceAddFrameControl":
356                                         w = v.window;
357
358                                         // Add tinyMCE global instance and tinymce namespace to specified window
359                                         w.tinyMCE = tinyMCE;
360                                         w.tinymce = tinymce;
361
362                                         tinymce.DOM.doc = w.document;
363                                         tinymce.DOM.win = w;
364
365                                         ed = new tinymce.Editor(v.element_id, v);
366                                         ed.render();
367
368                                         // Fix IE memory leaks
369                                         if (tinymce.isIE) {
370                                                 function clr() {
371                                                         ed.destroy();
372                                                         w.detachEvent('onunload', clr);
373                                                         w = w.tinyMCE = w.tinymce = null; // IE leak
374                                                 };
375
376                                                 w.attachEvent('onunload', clr);
377                                         }
378
379                                         v.page_window = null;
380
381                                         return true;
382
383                                 case "mceRemoveEditor":
384                                 case "mceRemoveControl":
385                                         if (ed)
386                                                 ed.remove();
387
388                                         return true;
389
390                                 case 'mceToggleEditor':
391                                         if (!ed) {
392                                                 t.execCommand('mceAddControl', 0, v);
393                                                 return true;
394                                         }
395
396                                         if (ed.isHidden())
397                                                 ed.show();
398                                         else
399                                                 ed.hide();
400
401                                         return true;
402                         }
403
404                         // Run command on active editor
405                         if (t.activeEditor)
406                                 return t.activeEditor.execCommand(c, u, v);
407
408                         return false;
409                 },
410
411                 /**
412                  * Executes a command on a specific editor by id. This method was added for compatibility with the 2.x branch.
413                  *
414                  * @deprecated Use the execCommand method of a editor instance instead.
415                  * @method execInstanceCommand
416                  * @param {String} id Editor id to perform the command on.
417                  * @param {String} c Command to perform for example Bold.
418                  * @param {Boolean} u Optional boolean state if a UI should be presented for the command or not.
419                  * @param {String} v Optional value parameter like for example an URL to a link.
420                  * @return {Boolean} true/false if the command was executed or not.
421                  */
422                 execInstanceCommand : function(id, c, u, v) {
423                         var ed = this.get(id);
424
425                         if (ed)
426                                 return ed.execCommand(c, u, v);
427
428                         return false;
429                 },
430
431                 /**
432                  * Calls the save method on all editor instances in the collection. This can be useful when a form is to be submitted.
433                  *
434                  * @method triggerSave
435                  * @example
436                  * // Saves all contents
437                  * tinyMCE.triggerSave();
438                  */
439                 triggerSave : function() {
440                         each(this.editors, function(e) {
441                                 e.save();
442                         });
443                 },
444
445                 /**
446                  * Adds a language pack, this gets called by the loaded language files like en.js.
447                  *
448                  * @method addI18n
449                  * @param {String} p Prefix for the language items. For example en.myplugin
450                  * @param {Object} o Name/Value collection with items to add to the language group.
451                  */
452                 addI18n : function(p, o) {
453                         var lo, i18n = this.i18n;
454
455                         if (!tinymce.is(p, 'string')) {
456                                 each(p, function(o, lc) {
457                                         each(o, function(o, g) {
458                                                 each(o, function(o, k) {
459                                                         if (g === 'common')
460                                                                 i18n[lc + '.' + k] = o;
461                                                         else
462                                                                 i18n[lc + '.' + g + '.' + k] = o;
463                                                 });
464                                         });
465                                 });
466                         } else {
467                                 each(o, function(o, k) {
468                                         i18n[p + '.' + k] = o;
469                                 });
470                         }
471                 },
472
473                 // Private methods
474
475                 _setActive : function(editor) {
476                         this.selectedInstance = this.activeEditor = editor;
477                 }
478         });
479 })(tinymce);
480
481 /**
482  * Alternative name for tinymce added for 2.x compatibility.
483  *
484  * @member
485  * @property tinyMCE
486  * @type tinymce
487  * @example
488  * // To initialize editor instances
489  * tinyMCE.init({
490  *    ...
491  * });
492  */
493
494 /**
495  * Alternative name for tinymce added for compatibility.
496  *
497  * @member tinymce
498  * @property EditorManager
499  * @type tinymce
500  * @example
501  * // To initialize editor instances
502  * tinymce.EditorManager.get('editor');
503  */