tinymce.js 21 KB

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