]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - include/javascript/tiny_mce/classes/tinymce.js
Release 6.5.0
[Github/sugarcrm.git] / include / javascript / tiny_mce / classes / tinymce.js
1 /**
2  * tinymce.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(win) {
12         var whiteSpaceRe = /^\s*|\s*$/g,
13                 undefined, isRegExpBroken = 'B'.replace(/A(.)|B/, '$1') === '$1';
14
15         /**
16          * Core namespace with core functionality for the TinyMCE API all sub classes will be added to this namespace/object.
17          *
18          * @static
19          * @class tinymce
20          * @example
21          * // Using each method
22          * tinymce.each([1, 2, 3], function(v, i) {
23          *   console.log(i + '=' + v);
24          * });
25          *
26          * // Checking for a specific browser
27          * if (tinymce.isIE)
28          *   console.log("IE");
29          */
30         var tinymce = {
31                 /**
32                  * Major version of TinyMCE build.
33                  *
34                  * @property majorVersion
35                  * @type String
36                  */
37                 majorVersion : '@@tinymce_major_version@@',
38
39                 /**
40                  * Major version of TinyMCE build.
41                  *
42                  * @property minorVersion
43                  * @type String
44                  */
45                 minorVersion : '@@tinymce_minor_version@@',
46
47                 /**
48                  * Release date of TinyMCE build.
49                  *
50                  * @property releaseDate
51                  * @type String
52                  */
53                 releaseDate : '@@tinymce_release_date@@',
54
55                 /**
56                  * Initializes the TinyMCE global namespace this will setup browser detection and figure out where TinyMCE is running from.
57                  */
58                 _init : function() {
59                         var t = this, d = document, na = navigator, ua = na.userAgent, i, nl, n, base, p, v;
60
61                         /**
62                          * Constant that is true if the browser is Opera.
63                          *
64                          * @property isOpera
65                          * @type Boolean
66                          * @final
67                          */
68                         t.isOpera = win.opera && opera.buildNumber;
69
70                         /**
71                          * Constant that is true if the browser is WebKit (Safari/Chrome).
72                          *
73                          * @property isWebKit
74                          * @type Boolean
75                          * @final
76                          */
77                         t.isWebKit = /WebKit/.test(ua);
78
79                         /**
80                          * Constant that is true if the browser is IE.
81                          *
82                          * @property isIE
83                          * @type Boolean
84                          * @final
85                          */
86                         t.isIE = !t.isWebKit && !t.isOpera && (/MSIE/gi).test(ua) && (/Explorer/gi).test(na.appName);
87
88                         /**
89                          * Constant that is true if the browser is IE 6 or older.
90                          *
91                          * @property isIE6
92                          * @type Boolean
93                          * @final
94                          */
95                         t.isIE6 = t.isIE && /MSIE [56]/.test(ua);
96
97                         /**
98                          * Constant that is true if the browser is IE 7.
99                          *
100                          * @property isIE7
101                          * @type Boolean
102                          * @final
103                          */
104                         t.isIE7 = t.isIE && /MSIE [7]/.test(ua);
105
106                         /**
107                          * Constant that is true if the browser is IE 8.
108                          *
109                          * @property isIE8
110                          * @type Boolean
111                          * @final
112                          */
113                         t.isIE8 = t.isIE && /MSIE [8]/.test(ua);
114
115                         /**
116                          * Constant that is true if the browser is IE 9.
117                          *
118                          * @property isIE9
119                          * @type Boolean
120                          * @final
121                          */
122                         t.isIE9 = t.isIE && /MSIE [9]/.test(ua);
123
124                         /**
125                          * Constant that is true if the browser is Gecko.
126                          *
127                          * @property isGecko
128                          * @type Boolean
129                          * @final
130                          */
131                         t.isGecko = !t.isWebKit && /Gecko/.test(ua);
132
133                         /**
134                          * Constant that is true if the os is Mac OS.
135                          *
136                          * @property isMac
137                          * @type Boolean
138                          * @final
139                          */
140                         t.isMac = ua.indexOf('Mac') != -1;
141
142                         /**
143                          * Constant that is true if the runtime is Adobe Air.
144                          *
145                          * @property isAir
146                          * @type Boolean
147                          * @final
148                          */
149                         t.isAir = /adobeair/i.test(ua);
150
151                         /**
152                          * Constant that tells if the current browser is an iPhone or iPad.
153                          *
154                          * @property isIDevice
155                          * @type Boolean
156                          * @final
157                          */
158                         t.isIDevice = /(iPad|iPhone)/.test(ua);
159                         
160                         /**
161                          * Constant that is true if the current browser is running on iOS 5 or greater.
162                          *
163                          * @property isIOS5
164                          * @type Boolean
165                          * @final
166                          */
167                         t.isIOS5 = t.isIDevice && ua.match(/AppleWebKit\/(\d*)/)[1]>=534;
168
169                         // TinyMCE .NET webcontrol might be setting the values for TinyMCE
170                         if (win.tinyMCEPreInit) {
171                                 t.suffix = tinyMCEPreInit.suffix;
172                                 t.baseURL = tinyMCEPreInit.base;
173                                 t.query = tinyMCEPreInit.query;
174                                 return;
175                         }
176
177                         // Get suffix and base
178                         t.suffix = '';
179
180                         // If base element found, add that infront of baseURL
181                         nl = d.getElementsByTagName('base');
182                         for (i=0; i<nl.length; i++) {
183                                 if (v = nl[i].href) {
184                                         // Host only value like http://site.com or http://site.com:8008
185                                         if (/^https?:\/\/[^\/]+$/.test(v))
186                                                 v += '/';
187
188                                         base = v ? v.match(/.*\//)[0] : ''; // Get only directory
189                                 }
190                         }
191
192                         function getBase(n) {
193                                 if (n.src && /tiny_mce(|_gzip|_jquery|_prototype|_full)(_dev|_src)?.js/.test(n.src)) {
194                                         if (/_(src|dev)\.js/g.test(n.src))
195                                                 t.suffix = '_src';
196
197                                         if ((p = n.src.indexOf('?')) != -1)
198                                                 t.query = n.src.substring(p + 1);
199
200                                         t.baseURL = n.src.substring(0, n.src.lastIndexOf('/'));
201
202                                         // If path to script is relative and a base href was found add that one infront
203                                         // the src property will always be an absolute one on non IE browsers and IE 8
204                                         // so this logic will basically only be executed on older IE versions
205                                         if (base && t.baseURL.indexOf('://') == -1 && t.baseURL.indexOf('/') !== 0)
206                                                 t.baseURL = base + t.baseURL;
207
208                                         return t.baseURL;
209                                 }
210
211                                 return null;
212                         };
213
214                         // Check document
215                         nl = d.getElementsByTagName('script');
216                         for (i=0; i<nl.length; i++) {
217                                 if (getBase(nl[i]))
218                                         return;
219                         }
220
221                         // Check head
222                         n = d.getElementsByTagName('head')[0];
223                         if (n) {
224                                 nl = n.getElementsByTagName('script');
225                                 for (i=0; i<nl.length; i++) {
226                                         if (getBase(nl[i]))
227                                                 return;
228                                 }
229                         }
230
231                         return;
232                 },
233
234                 /**
235                  * Checks if a object is of a specific type for example an array.
236                  *
237                  * @method is
238                  * @param {Object} o Object to check type of.
239                  * @param {string} t Optional type to check for.
240                  * @return {Boolean} true/false if the object is of the specified type.
241                  */
242                 is : function(o, t) {
243                         if (!t)
244                                 return o !== undefined;
245
246                         if (t == 'array' && (o.hasOwnProperty && o instanceof Array))
247                                 return true;
248
249                         return typeof(o) == t;
250                 },
251
252                 /**
253                  * Makes a name/object map out of an array with names.
254                  *
255                  * @method makeMap
256                  * @param {Array/String} items Items to make map out of.
257                  * @param {String} delim Optional delimiter to split string by.
258                  * @param {Object} map Optional map to add items to.
259                  * @return {Object} Name/value map of items.
260                  */
261                 makeMap : function(items, delim, map) {
262                         var i;
263
264                         items = items || [];
265                         delim = delim || ',';
266
267                         if (typeof(items) == "string")
268                                 items = items.split(delim);
269
270                         map = map || {};
271
272                         i = items.length;
273                         while (i--)
274                                 map[items[i]] = {};
275
276                         return map;
277                 },
278
279                 /**
280                  * Performs an iteration of all items in a collection such as an object or array. This method will execure the
281                  * callback function for each item in the collection, if the callback returns false the iteration will terminate.
282                  * The callback has the following format: cb(value, key_or_index).
283                  *
284                  * @method each
285                  * @param {Object} o Collection to iterate.
286                  * @param {function} cb Callback function to execute for each item.
287                  * @param {Object} s Optional scope to execute the callback in.
288                  * @example
289                  * // Iterate an array
290                  * tinymce.each([1,2,3], function(v, i) {
291                  *     console.debug("Value: " + v + ", Index: " + i);
292                  * });
293                  * 
294                  * // Iterate an object
295                  * tinymce.each({a : 1, b : 2, c: 3], function(v, k) {
296                  *     console.debug("Value: " + v + ", Key: " + k);
297                  * });
298                  */
299                 each : function(o, cb, s) {
300                         var n, l;
301
302                         if (!o)
303                                 return 0;
304
305                         s = s || o;
306
307                         if (o.length !== undefined) {
308                                 // Indexed arrays, needed for Safari
309                                 for (n=0, l = o.length; n < l; n++) {
310                                         if (cb.call(s, o[n], n, o) === false)
311                                                 return 0;
312                                 }
313                         } else {
314                                 // Hashtables
315                                 for (n in o) {
316                                         if (o.hasOwnProperty(n)) {
317                                                 if (cb.call(s, o[n], n, o) === false)
318                                                         return 0;
319                                         }
320                                 }
321                         }
322
323                         return 1;
324                 },
325
326                 // #ifndef jquery
327
328                 /**
329                  * Creates a new array by the return value of each iteration function call. This enables you to convert
330                  * one array list into another.
331                  *
332                  * @method map
333                  * @param {Array} a Array of items to iterate.
334                  * @param {function} f Function to call for each item. It's return value will be the new value.
335                  * @return {Array} Array with new values based on function return values.
336                  */
337                 map : function(a, f) {
338                         var o = [];
339
340                         tinymce.each(a, function(v) {
341                                 o.push(f(v));
342                         });
343
344                         return o;
345                 },
346
347                 /**
348                  * Filters out items from the input array by calling the specified function for each item.
349                  * If the function returns false the item will be excluded if it returns true it will be included.
350                  *
351                  * @method grep
352                  * @param {Array} a Array of items to loop though.
353                  * @param {function} f Function to call for each item. Include/exclude depends on it's return value.
354                  * @return {Array} New array with values imported and filtered based in input.
355                  * @example
356                  * // Filter out some items, this will return an array with 4 and 5
357                  * var items = tinymce.grep([1,2,3,4,5], function(v) {return v > 3;});
358                  */
359                 grep : function(a, f) {
360                         var o = [];
361
362                         tinymce.each(a, function(v) {
363                                 if (!f || f(v))
364                                         o.push(v);
365                         });
366
367                         return o;
368                 },
369
370                 /**
371                  * Returns the index of a value in an array, this method will return -1 if the item wasn't found.
372                  *
373                  * @method inArray
374                  * @param {Array} a Array/Object to search for value in.
375                  * @param {Object} v Value to check for inside the array.
376                  * @return {Number/String} Index of item inside the array inside an object. Or -1 if it wasn't found.
377                  * @example
378                  * // Get index of value in array this will alert 1 since 2 is at that index
379                  * alert(tinymce.inArray([1,2,3], 2));
380                  */
381                 inArray : function(a, v) {
382                         var i, l;
383
384                         if (a) {
385                                 for (i = 0, l = a.length; i < l; i++) {
386                                         if (a[i] === v)
387                                                 return i;
388                                 }
389                         }
390
391                         return -1;
392                 },
393
394                 /**
395                  * Extends an object with the specified other object(s).
396                  *
397                  * @method extend
398                  * @param {Object} o Object to extend with new items.
399                  * @param {Object} e..n Object(s) to extend the specified object with.
400                  * @return {Object} o New extended object, same reference as the input object.
401                  * @example
402                  * // Extends obj1 with two new fields
403                  * var obj = tinymce.extend(obj1, {
404                  *     somefield1 : 'a',
405                  *     somefield2 : 'a'
406                  * });
407                  * 
408                  * // Extends obj with obj2 and obj3
409                  * tinymce.extend(obj, obj2, obj3);
410                  */
411                 extend : function(o, e) {
412                         var i, l, a = arguments;
413
414                         for (i = 1, l = a.length; i < l; i++) {
415                                 e = a[i];
416
417                                 tinymce.each(e, function(v, n) {
418                                         if (v !== undefined)
419                                                 o[n] = v;
420                                 });
421                         }
422
423                         return o;
424                 },
425
426                 // #endif
427
428                 /**
429                  * Removes whitespace from the beginning and end of a string.
430                  *
431                  * @method trim
432                  * @param {String} s String to remove whitespace from.
433                  * @return {String} New string with removed whitespace.
434                  */
435                 trim : function(s) {
436                         return (s ? '' + s : '').replace(whiteSpaceRe, '');
437                 },
438
439                 /**
440                  * Creates a class, subclass or static singleton.
441                  * More details on this method can be found in the Wiki.
442                  *
443                  * @method create
444                  * @param {String} s Class name, inheritage and prefix.
445                  * @param {Object} p Collection of methods to add to the class.
446                  * @param {Object} root Optional root object defaults to the global window object.
447                  * @example
448                  * // Creates a basic class
449                  * tinymce.create('tinymce.somepackage.SomeClass', {
450                  *     SomeClass : function() {
451                  *         // Class constructor
452                  *     },
453                  * 
454                  *     method : function() {
455                  *         // Some method
456                  *     }
457                  * });
458                  *
459                  * // Creates a basic subclass class
460                  * tinymce.create('tinymce.somepackage.SomeSubClass:tinymce.somepackage.SomeClass', {
461                  *     SomeSubClass: function() {
462                  *         // Class constructor
463                  *         this.parent(); // Call parent constructor
464                  *     },
465                  * 
466                  *     method : function() {
467                  *         // Some method
468                  *         this.parent(); // Call parent method
469                  *     },
470                  * 
471                  *     'static' : {
472                  *         staticMethod : function() {
473                  *             // Static method
474                  *         }
475                  *     }
476                  * });
477                  *
478                  * // Creates a singleton/static class
479                  * tinymce.create('static tinymce.somepackage.SomeSingletonClass', {
480                  *     method : function() {
481                  *         // Some method
482                  *     }
483                  * });
484                  */
485                 create : function(s, p, root) {
486                         var t = this, sp, ns, cn, scn, c, de = 0;
487
488                         // Parse : <prefix> <class>:<super class>
489                         s = /^((static) )?([\w.]+)(:([\w.]+))?/.exec(s);
490                         cn = s[3].match(/(^|\.)(\w+)$/i)[2]; // Class name
491
492                         // Create namespace for new class
493                         ns = t.createNS(s[3].replace(/\.\w+$/, ''), root);
494
495                         // Class already exists
496                         if (ns[cn])
497                                 return;
498
499                         // Make pure static class
500                         if (s[2] == 'static') {
501                                 ns[cn] = p;
502
503                                 if (this.onCreate)
504                                         this.onCreate(s[2], s[3], ns[cn]);
505
506                                 return;
507                         }
508
509                         // Create default constructor
510                         if (!p[cn]) {
511                                 p[cn] = function() {};
512                                 de = 1;
513                         }
514
515                         // Add constructor and methods
516                         ns[cn] = p[cn];
517                         t.extend(ns[cn].prototype, p);
518
519                         // Extend
520                         if (s[5]) {
521                                 sp = t.resolve(s[5]).prototype;
522                                 scn = s[5].match(/\.(\w+)$/i)[1]; // Class name
523
524                                 // Extend constructor
525                                 c = ns[cn];
526                                 if (de) {
527                                         // Add passthrough constructor
528                                         ns[cn] = function() {
529                                                 return sp[scn].apply(this, arguments);
530                                         };
531                                 } else {
532                                         // Add inherit constructor
533                                         ns[cn] = function() {
534                                                 this.parent = sp[scn];
535                                                 return c.apply(this, arguments);
536                                         };
537                                 }
538                                 ns[cn].prototype[cn] = ns[cn];
539
540                                 // Add super methods
541                                 t.each(sp, function(f, n) {
542                                         ns[cn].prototype[n] = sp[n];
543                                 });
544
545                                 // Add overridden methods
546                                 t.each(p, function(f, n) {
547                                         // Extend methods if needed
548                                         if (sp[n]) {
549                                                 ns[cn].prototype[n] = function() {
550                                                         this.parent = sp[n];
551                                                         return f.apply(this, arguments);
552                                                 };
553                                         } else {
554                                                 if (n != cn)
555                                                         ns[cn].prototype[n] = f;
556                                         }
557                                 });
558                         }
559
560                         // Add static methods
561                         t.each(p['static'], function(f, n) {
562                                 ns[cn][n] = f;
563                         });
564
565                         if (this.onCreate)
566                                 this.onCreate(s[2], s[3], ns[cn].prototype);
567                 },
568
569                 /**
570                  * Executed the specified function for each item in a object tree.
571                  *
572                  * @method walk
573                  * @param {Object} o Object tree to walk though.
574                  * @param {function} f Function to call for each item.
575                  * @param {String} n Optional name of collection inside the objects to walk for example childNodes.
576                  * @param {String} s Optional scope to execute the function in.
577                  */
578                 walk : function(o, f, n, s) {
579                         s = s || this;
580
581                         if (o) {
582                                 if (n)
583                                         o = o[n];
584
585                                 tinymce.each(o, function(o, i) {
586                                         if (f.call(s, o, i, n) === false)
587                                                 return false;
588
589                                         tinymce.walk(o, f, n, s);
590                                 });
591                         }
592                 },
593
594                 /**
595                  * Creates a namespace on a specific object.
596                  *
597                  * @method createNS
598                  * @param {String} n Namespace to create for example a.b.c.d.
599                  * @param {Object} o Optional object to add namespace to, defaults to window.
600                  * @return {Object} New namespace object the last item in path.
601                  * @example
602                  * // Create some namespace
603                  * tinymce.createNS('tinymce.somepackage.subpackage');
604                  *
605                  * // Add a singleton
606                  * var tinymce.somepackage.subpackage.SomeSingleton = {
607                  *     method : function() {
608                  *         // Some method
609                  *     }
610                  * };
611                  */
612                 createNS : function(n, o) {
613                         var i, v;
614
615                         o = o || win;
616
617                         n = n.split('.');
618                         for (i=0; i<n.length; i++) {
619                                 v = n[i];
620
621                                 if (!o[v])
622                                         o[v] = {};
623
624                                 o = o[v];
625                         }
626
627                         return o;
628                 },
629
630                 /**
631                  * Resolves a string and returns the object from a specific structure.
632                  *
633                  * @method resolve
634                  * @param {String} n Path to resolve for example a.b.c.d.
635                  * @param {Object} o Optional object to search though, defaults to window.
636                  * @return {Object} Last object in path or null if it couldn't be resolved.
637                  * @example
638                  * // Resolve a path into an object reference
639                  * var obj = tinymce.resolve('a.b.c.d');
640                  */
641                 resolve : function(n, o) {
642                         var i, l;
643
644                         o = o || win;
645
646                         n = n.split('.');
647                         for (i = 0, l = n.length; i < l; i++) {
648                                 o = o[n[i]];
649
650                                 if (!o)
651                                         break;
652                         }
653
654                         return o;
655                 },
656
657                 /**
658                  * Adds an unload handler to the document. This handler will be executed when the document gets unloaded.
659                  * This method is useful for dealing with browser memory leaks where it might be vital to remove DOM references etc.
660                  *
661                  * @method addUnload
662                  * @param {function} f Function to execute before the document gets unloaded.
663                  * @param {Object} s Optional scope to execute the function in.
664                  * @return {function} Returns the specified unload handler function.
665                  * @example
666                  * // Fixes a leak with a DOM element that was palces in the someObject
667                  * tinymce.addUnload(function() {
668                  *     // Null DOM element to reduce IE memory leak
669                  *     someObject.someElement = null;
670                  * });
671                  */
672                 addUnload : function(f, s) {
673                         var t = this;
674
675                         f = {func : f, scope : s || this};
676
677                         if (!t.unloads) {
678                                 function unload() {
679                                         var li = t.unloads, o, n;
680
681                                         if (li) {
682                                                 // Call unload handlers
683                                                 for (n in li) {
684                                                         o = li[n];
685
686                                                         if (o && o.func)
687                                                                 o.func.call(o.scope, 1); // Send in one arg to distinct unload and user destroy
688                                                 }
689
690                                                 // Detach unload function
691                                                 if (win.detachEvent) {
692                                                         win.detachEvent('onbeforeunload', fakeUnload);
693                                                         win.detachEvent('onunload', unload);
694                                                 } else if (win.removeEventListener)
695                                                         win.removeEventListener('unload', unload, false);
696
697                                                 // Destroy references
698                                                 t.unloads = o = li = w = unload = 0;
699
700                                                 // Run garbarge collector on IE
701                                                 if (win.CollectGarbage)
702                                                         CollectGarbage();
703                                         }
704                                 };
705
706                                 function fakeUnload() {
707                                         var d = document;
708
709                                         // Is there things still loading, then do some magic
710                                         if (d.readyState == 'interactive') {
711                                                 function stop() {
712                                                         // Prevent memory leak
713                                                         d.detachEvent('onstop', stop);
714
715                                                         // Call unload handler
716                                                         if (unload)
717                                                                 unload();
718
719                                                         d = 0;
720                                                 };
721
722                                                 // Fire unload when the currently loading page is stopped
723                                                 if (d)
724                                                         d.attachEvent('onstop', stop);
725
726                                                 // Remove onstop listener after a while to prevent the unload function
727                                                 // to execute if the user presses cancel in an onbeforeunload
728                                                 // confirm dialog and then presses the browser stop button
729                                                 win.setTimeout(function() {
730                                                         if (d)
731                                                                 d.detachEvent('onstop', stop);
732                                                 }, 0);
733                                         }
734                                 };
735
736                                 // Attach unload handler
737                                 if (win.attachEvent) {
738                                         win.attachEvent('onunload', unload);
739                                         win.attachEvent('onbeforeunload', fakeUnload);
740                                 } else if (win.addEventListener)
741                                         win.addEventListener('unload', unload, false);
742
743                                 // Setup initial unload handler array
744                                 t.unloads = [f];
745                         } else
746                                 t.unloads.push(f);
747
748                         return f;
749                 },
750
751                 /**
752                  * Removes the specified function form the unload handler list.
753                  *
754                  * @method removeUnload
755                  * @param {function} f Function to remove from unload handler list.
756                  * @return {function} Removed function name or null if it wasn't found.
757                  */
758                 removeUnload : function(f) {
759                         var u = this.unloads, r = null;
760
761                         tinymce.each(u, function(o, i) {
762                                 if (o && o.func == f) {
763                                         u.splice(i, 1);
764                                         r = f;
765                                         return false;
766                                 }
767                         });
768
769                         return r;
770                 },
771
772                 /**
773                  * Splits a string but removes the whitespace before and after each value.
774                  *
775                  * @method explode
776                  * @param {string} s String to split.
777                  * @param {string} d Delimiter to split by.
778                  * @example
779                  * // Split a string into an array with a,b,c
780                  * var arr = tinymce.explode('a, b,   c');
781                  */
782                 explode : function(s, d) {
783                         return s ? tinymce.map(s.split(d || ','), tinymce.trim) : s;
784                 },
785
786                 _addVer : function(u) {
787                         var v;
788
789                         if (!this.query)
790                                 return u;
791
792                         v = (u.indexOf('?') == -1 ? '?' : '&') + this.query;
793
794                         if (u.indexOf('#') == -1)
795                                 return u + v;
796
797                         return u.replace('#', v + '#');
798                 },
799
800                 // Fix function for IE 9 where regexps isn't working correctly
801                 // Todo: remove me once MS fixes the bug
802                 _replace : function(find, replace, str) {
803                         // On IE9 we have to fake $x replacement
804                         if (isRegExpBroken) {
805                                 return str.replace(find, function() {
806                                         var val = replace, args = arguments, i;
807
808                                         for (i = 0; i < args.length - 2; i++) {
809                                                 if (args[i] === undefined) {
810                                                         val = val.replace(new RegExp('\\$' + i, 'g'), '');
811                                                 } else {
812                                                         val = val.replace(new RegExp('\\$' + i, 'g'), args[i]);
813                                                 }
814                                         }
815
816                                         return val;
817                                 });
818                         }
819
820                         return str.replace(find, replace);
821                 }
822
823                 /**#@-*/
824         };
825
826         // Initialize the API
827         tinymce._init();
828
829         // Expose tinymce namespace to the global namespace (window)
830         win.tinymce = win.tinyMCE = tinymce;
831
832         // Describe the different namespaces
833
834         /**
835          * Root level namespace this contains classes directly releated to the TinyMCE editor.
836          *
837          * @namespace tinymce
838          */
839
840         /**
841          * Contains classes for handling the browsers DOM.
842          *
843          * @namespace tinymce.dom
844          */
845
846         /**
847          * Contains html parser and serializer logic.
848          *
849          * @namespace tinymce.html
850          */
851
852         /**
853          * Contains the different UI types such as buttons, listboxes etc.
854          *
855          * @namespace tinymce.ui
856          */
857
858         /**
859          * Contains various utility classes such as json parser, cookies etc.
860          *
861          * @namespace tinymce.util
862          */
863
864         /**
865          * Contains plugin classes.
866          *
867          * @namespace tinymce.plugins
868          */
869 })(window);