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 $.fn.tinymce = function(settings) {
18 var self = this, url, ed, base, pos, lang, query = "", suffix = "";
20 // No match then just ignore the call
24 // Get editor instance
26 return tinyMCE.get(self[0].id);
28 self.css('visibility', 'hidden'); // Hide textarea to avoid flicker
31 var editors = [], initCount = 0;
33 // Apply patches to the jQuery object, only once
39 // Create an editor instance for each matched node
40 self.each(function(i, node) {
41 var ed, id = node.id, oninit = settings.oninit;
43 // Generate unique id for target element if needed
45 node.id = id = tinymce.DOM.uniqueId();
47 // Create editor instance and render it
48 ed = new tinymce.Editor(id, settings);
51 ed.onInit.add(function() {
52 var scope, func = oninit;
54 self.css('visibility', '');
56 // Run this if the oninit setting is defined
57 // this logic will fire the oninit callback ones each
58 // matched editor instance is initialized
60 // Fire the oninit event ones each editor instance is initialized
61 if (++initCount == editors.length) {
62 if (tinymce.is(func, "string")) {
63 scope = (func.indexOf(".") === -1) ? null : tinymce.resolve(func.replace(/\.\w+$/, ""));
64 func = tinymce.resolve(func);
67 // Call the oninit function with the object
68 func.apply(scope || tinymce, editors);
74 // Render the editor instances in a separate loop since we
75 // need to have the full editors array used in the onInit calls
76 $.each(editors, function(i, ed) {
81 // Load TinyMCE on demand, if we need to
82 if (!win["tinymce"] && !lazyLoading && (url = settings.script_url)) {
84 base = url.substring(0, url.lastIndexOf("/"));
86 // Check if it's a dev/src version they want to load then
87 // make sure that all plugins, themes etc are loaded in source mode aswell
88 if (/_(src|dev)\.js/g.test(url))
91 // Parse out query part, this will be appended to all scripts, css etc to clear browser cache
92 pos = url.lastIndexOf("?");
94 query = url.substring(pos + 1);
96 // Setup tinyMCEPreInit object this will later be used by the TinyMCE
97 // core script to locate other resources like CSS files, dialogs etc
98 // You can also predefined a tinyMCEPreInit object and then it will use that instead
99 win.tinyMCEPreInit = win.tinyMCEPreInit || {
105 // url contains gzip then we assume it's a compressor
106 if (url.indexOf('gzip') != -1) {
107 lang = settings.language || "en";
108 url = url + (/\?/.test(url) ? '&' : '?') + "js=true&core=true&suffix=" + escape(suffix) + "&themes=" + escape(settings.theme) + "&plugins=" + escape(settings.plugins) + "&languages=" + lang;
110 // Check if compressor script is already loaded otherwise setup a basic one
111 if (!win["tinyMCE_GZ"]) {
114 tinymce.suffix = suffix;
117 tinymce.ScriptLoader.markDone(tinyMCE.baseURI.toAbsolute(url));
120 // Add core languages
121 load("langs/" + lang + ".js");
123 // Add themes with languages
124 load("themes/" + settings.theme + "/editor_template" + suffix + ".js");
125 load("themes/" + settings.theme + "/langs/" + lang + ".js");
127 // Add plugins with languages
128 $.each(settings.plugins.split(","), function(i, name) {
130 load("plugins/" + name + "/editor_plugin" + suffix + ".js");
131 load("plugins/" + name + "/langs/" + lang + ".js");
142 // Load the script cached and execute the inits once it's done
148 success : function() {
149 tinymce.dom.Event.domLoaded = 1;
152 // Execute callback after mainscript has been loaded and before the initialization occurs
153 if (settings.script_loaded)
154 settings.script_loaded();
158 $.each(delayedInits, function(i, init) {
164 // Delay the init call until tinymce is loaded
165 if (lazyLoading === 1)
166 delayedInits.push(init);
174 // Add :tinymce psuedo selector this will select elements that has been converted into editor instances
175 // it's now possible to use things like $('*:tinymce') to get all TinyMCE bound elements.
176 $.extend($.expr[":"], {
177 tinymce : function(e) {
178 return e.id && !!tinyMCE.get(e.id);
182 // This function patches internal jQuery functions so that if
183 // you for example remove an div element containing an editor it's
184 // automatically destroyed by the TinyMCE API
185 function applyPatch() {
186 // Removes any child editor instances by looking for editor wrapper elements
187 function removeEditors(name) {
188 // If the function is remove
189 if (name === "remove") {
190 this.each(function(i, node) {
191 var ed = tinyMCEInstance(node);
198 this.find("span.mceEditor,div.mceEditor").each(function(i, node) {
199 var ed = tinyMCE.get(node.id.replace(/_parent$/, ""));
206 // Loads or saves contents from/to textarea if the value
207 // argument is defined it will set the TinyMCE internal contents
208 function loadOrSave(value) {
212 if (value !== undefined) {
213 removeEditors.call(self);
215 // Saves the contents before get/set value of textarea/div
216 self.each(function(i, node) {
219 if (ed = tinyMCE.get(node.id))
220 ed.setContent(value);
222 } else if (self.length > 0) {
224 if (ed = tinyMCE.get(self[0].id))
225 return ed.getContent();
229 // Returns tinymce instance for the specified element or null if it wasn't found
230 function tinyMCEInstance(element) {
233 (element) && (element.id) && (win["tinymce"]) && (ed = tinyMCE.get(element.id));
238 // Checks if the specified set contains tinymce instances
239 function containsTinyMCE(matchedSet) {
240 return !!((matchedSet) && (matchedSet.length) && (win["tinymce"]) && (matchedSet.is(":tinymce")));
243 // Patch various jQuery functions
246 // Patch some setter/getter functions these will
247 // now be able to set/get the contents of editor instances for
248 // example $('#editorid').html('Content'); will update the TinyMCE iframe instance
249 $.each(["text", "html", "val"], function(i, name) {
250 var origFn = jQueryFn[name] = $.fn[name],
251 textProc = (name === "text");
253 $.fn[name] = function(value) {
256 if (!containsTinyMCE(self))
257 return origFn.apply(self, arguments);
259 if (value !== undefined) {
260 loadOrSave.call(self.filter(":tinymce"), value);
261 origFn.apply(self.not(":tinymce"), arguments);
263 return self; // return original set for chaining
266 var args = arguments;
268 (textProc ? self : self.eq(0)).each(function(i, node) {
269 var ed = tinyMCEInstance(node);
271 ret += ed ? (textProc ? ed.getContent().replace(/<(?:"[^"]*"|'[^']*'|[^'">])*>/g, "") : ed.getContent()) : origFn.apply($(node), args);
279 // Makes it possible to use $('#id').append("content"); to append contents to the TinyMCE editor iframe
280 $.each(["append", "prepend"], function(i, name) {
281 var origFn = jQueryFn[name] = $.fn[name],
282 prepend = (name === "prepend");
284 $.fn[name] = function(value) {
287 if (!containsTinyMCE(self))
288 return origFn.apply(self, arguments);
290 if (value !== undefined) {
291 self.filter(":tinymce").each(function(i, node) {
292 var ed = tinyMCEInstance(node);
294 ed && ed.setContent(prepend ? value + ed.getContent() : ed.getContent() + value);
297 origFn.apply(self.not(":tinymce"), arguments);
299 return self; // return original set for chaining
304 // Makes sure that the editor instance gets properly destroyed when the parent element is removed
305 $.each(["remove", "replaceWith", "replaceAll", "empty"], function(i, name) {
306 var origFn = jQueryFn[name] = $.fn[name];
308 $.fn[name] = function() {
309 removeEditors.call(this, name);
311 return origFn.apply(this, arguments);
315 jQueryFn.attr = $.fn.attr;
317 // Makes sure that $('#tinymce_id').attr('value') gets the editors current HTML contents
318 $.fn.attr = function(name, value, type) {
321 if ((!name) || (name !== "value") || (!containsTinyMCE(self)))
322 return jQueryFn.attr.call(self, name, value, type);
324 if (value !== undefined) {
325 loadOrSave.call(self.filter(":tinymce"), value);
326 jQueryFn.attr.call(self.not(":tinymce"), name, value, type);
328 return self; // return original set for chaining
330 var node = self[0], ed = tinyMCEInstance(node);
332 return ed ? ed.getContent() : jQueryFn.attr.call($(node), name, value, type);