4 * Copyright 2009, Moxiecode Systems AB
5 * Released under LGPL License.
7 * License: http://tinymce.moxiecode.com/license
8 * Contributing: http://tinymce.moxiecode.com/contributing
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;
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 += '/';
28 tinymce.baseURL = new tinymce.util.URI(tinymce.documentBaseURL).toAbsolute(tinymce.baseURL);
31 * Absolute baseURI for the installation path of TinyMCE.
34 * @type tinymce.util.URI
36 tinymce.baseURI = new tinymce.util.URI(tinymce.baseURL);
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);
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);
49 * Fires when a new editor instance is added to the tinymce collection.
52 * @param {tinymce} sender TinyMCE root class/namespace.
53 * @param {tinymce.Editor} editor Editor instance.
55 * tinyMCE.execCommand("mceAddControl", false, "some_textarea");
56 * tinyMCE.onAddEditor.add(function(mgr,ed) {
57 * console.debug('A new editor is available' + ed.id);
60 tinymce.onAddEditor = new Dispatcher(tinymce);
63 * Fires when an editor instance is removed from the tinymce collection.
65 * @event onRemoveEditor
66 * @param {tinymce} sender TinyMCE root class/namespace.
67 * @param {tinymce.Editor} editor Editor instance.
69 tinymce.onRemoveEditor = new Dispatcher(tinymce);
71 tinymce.EditorManager = extend(tinymce, {
73 * Collection of editor instances.
78 * for (edId in tinyMCE.editors)
79 * tinyMCE.editors[edId].save();
84 * Collection of language pack data.
92 * Currently active editor instance.
94 * @property activeEditor
95 * @type tinymce.Editor
97 * tinyMCE.activeEditor.selection.getContent();
98 * tinymce.EditorManager.activeEditor.selection.getContent();
103 * Initializes a set of editors. This method will create a bunch of editors based in the input.
106 * @param {Object} s Settings object to be passed to each editor instance.
108 * // Initializes a editor using the longer method
109 * tinymce.EditorManager.init({
110 * some_settings : 'some value'
113 * // Initializes a editor instance using the shorter version
115 * some_settings : 'some value'
119 var t = this, pl, sl = tinymce.ScriptLoader, e, el = [], ed;
121 function execCallback(se, n, s) {
127 if (tinymce.is(f, 'string')) {
128 s = f.replace(/\.\w+$/, '');
129 s = s ? tinymce.resolve(s) : 0;
130 f = tinymce.resolve(f);
133 return f.apply(s || this, Array.prototype.slice.call(arguments, 2));
144 Event.add(document, 'init', function() {
147 execCallback(s, 'onpageload');
151 l = s.elements || '';
154 each(explode(l), function(v) {
156 ed = new tinymce.Editor(v, s);
160 each(document.forms, function(f) {
161 each(f.elements, function(e) {
163 v = 'mce_editor_' + instanceCounter++;
164 DOM.setAttrib(e, 'id', v);
166 ed = new tinymce.Editor(v, s);
178 case "specific_textareas":
179 function hasClass(n, c) {
180 return c.constructor === RegExp ? c.test(n.className) : DOM.hasClass(n, c);
183 each(DOM.select('textarea'), function(v) {
184 if (s.editor_deselector && hasClass(v, s.editor_deselector))
187 if (!s.editor_selector || hasClass(v, s.editor_selector)) {
188 // Can we use the name
193 // Generate unique name if missing or already exists
194 if (!v.id || t.get(v.id))
195 v.id = DOM.uniqueId();
197 ed = new tinymce.Editor(v.id, s);
205 // Call onInit when all editors are initialized
209 each(el, function(ed) {
212 if (!ed.initialized) {
214 ed.onInit.add(function() {
219 execCallback(s, 'oninit');
226 execCallback(s, 'oninit');
233 * Returns a editor instance by id.
236 * @param {String/Number} id Editor instance id or index to return.
237 * @return {tinymce.Editor} Editor instance to return.
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!');
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!');
250 if (id === undefined)
253 return this.editors[id];
257 * Returns a editor instance by id. This method was added for compatibility with the 2.x branch.
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.
265 getInstanceById : function(id) {
270 * Adds an editor instance to the editor collection. This will also set it as the active editor.
273 * @param {tinymce.Editor} editor Editor instance to add to the collection.
274 * @return {tinymce.Editor} The same instance that got passed in.
276 add : function(editor) {
277 var self = this, editors = self.editors;
279 // Add named and index editor instance
280 editors[editor.id] = editor;
281 editors.push(editor);
283 self._setActive(editor);
284 self.onAddEditor.dispatch(self, editor);
288 // Patch the tinymce.Editor instance with jQuery adapter logic
290 tinymce.adapter.patchEditor(editor);
298 * Removes a editor instance from the collection.
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.
304 remove : function(editor) {
305 var t = this, i, editors = t.editors;
307 // Not in the collection
308 if (!editors[editor.id])
311 delete editors[editor.id];
313 for (i = 0; i < editors.length; i++) {
314 if (editors[i] == editor) {
315 editors.splice(i, 1);
320 // Select another editor since the active one was removed
321 if (t.activeEditor == editor)
322 t._setActive(editors[0]);
325 t.onRemoveEditor.dispatch(t, editor);
331 * Executes a specific command on the currently active editor.
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.
339 execCommand : function(c, u, v) {
340 var t = this, ed = t.get(v), w;
349 case "mceAddControl":
351 new tinymce.Editor(v, t.settings).render();
355 case "mceAddFrameControl":
358 // Add tinyMCE global instance and tinymce namespace to specified window
362 tinymce.DOM.doc = w.document;
365 ed = new tinymce.Editor(v.element_id, v);
368 // Fix IE memory leaks
372 w.detachEvent('onunload', clr);
373 w = w.tinyMCE = w.tinymce = null; // IE leak
376 w.attachEvent('onunload', clr);
379 v.page_window = null;
383 case "mceRemoveEditor":
384 case "mceRemoveControl":
390 case 'mceToggleEditor':
392 t.execCommand('mceAddControl', 0, v);
404 // Run command on active editor
406 return t.activeEditor.execCommand(c, u, v);
412 * Executes a command on a specific editor by id. This method was added for compatibility with the 2.x branch.
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.
422 execInstanceCommand : function(id, c, u, v) {
423 var ed = this.get(id);
426 return ed.execCommand(c, u, v);
432 * Calls the save method on all editor instances in the collection. This can be useful when a form is to be submitted.
434 * @method triggerSave
436 * // Saves all contents
437 * tinyMCE.triggerSave();
439 triggerSave : function() {
440 each(this.editors, function(e) {
446 * Adds a language pack, this gets called by the loaded language files like en.js.
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.
452 addI18n : function(p, o) {
453 var lo, i18n = this.i18n;
455 if (!tinymce.is(p, 'string')) {
456 each(p, function(o, lc) {
457 each(o, function(o, g) {
458 each(o, function(o, k) {
460 i18n[lc + '.' + k] = o;
462 i18n[lc + '.' + g + '.' + k] = o;
467 each(o, function(o, k) {
468 i18n[p + '.' + k] = o;
475 _setActive : function(editor) {
476 this.selectedInstance = this.activeEditor = editor;
482 * Alternative name for tinymce added for 2.x compatibility.
488 * // To initialize editor instances
495 * Alternative name for tinymce added for compatibility.
498 * @property EditorManager
501 * // To initialize editor instances
502 * tinymce.EditorManager.get('editor');