Tools.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. /**
  2. * Tools.js
  3. *
  4. * Copyright, Moxiecode Systems AB
  5. * Released under LGPL License.
  6. *
  7. * License: http://www.tinymce.com/license
  8. * Contributing: http://www.tinymce.com/contributing
  9. */
  10. /**
  11. * This class contains various utlity functions. These are also exposed
  12. * directly on the tinymce namespace.
  13. *
  14. * @class tinymce.util.Tools
  15. */
  16. define("tinymce/util/Tools", [], function() {
  17. /**
  18. * Removes whitespace from the beginning and end of a string.
  19. *
  20. * @method trim
  21. * @param {String} s String to remove whitespace from.
  22. * @return {String} New string with removed whitespace.
  23. */
  24. var whiteSpaceRegExp = /^\s*|\s*$/g;
  25. function trim(str) {
  26. return (str === null || str === undefined) ? '' : ("" + str).replace(whiteSpaceRegExp, '');
  27. }
  28. /**
  29. * Returns true/false if the object is an array or not.
  30. *
  31. * @method isArray
  32. * @param {Object} obj Object to check.
  33. * @return {boolean} true/false state if the object is an array or not.
  34. */
  35. var isArray = Array.isArray || function(obj) {
  36. return Object.prototype.toString.call(obj) === "[object Array]";
  37. };
  38. /**
  39. * Checks if a object is of a specific type for example an array.
  40. *
  41. * @method is
  42. * @param {Object} o Object to check type of.
  43. * @param {string} t Optional type to check for.
  44. * @return {Boolean} true/false if the object is of the specified type.
  45. */
  46. function is(o, t) {
  47. if (!t) {
  48. return o !== undefined;
  49. }
  50. if (t == 'array' && isArray(o)) {
  51. return true;
  52. }
  53. return typeof(o) == t;
  54. }
  55. /**
  56. * Converts the specified object into a real JavaScript array.
  57. *
  58. * @method toArray
  59. * @param {Object} obj Object to convert into array.
  60. * @return {Array} Array object based in input.
  61. */
  62. function toArray(obj) {
  63. var array = [], i, l;
  64. for (i = 0, l = obj.length; i < l; i++) {
  65. array[i] = obj[i];
  66. }
  67. return array;
  68. }
  69. /**
  70. * Makes a name/object map out of an array with names.
  71. *
  72. * @method makeMap
  73. * @param {Array/String} items Items to make map out of.
  74. * @param {String} delim Optional delimiter to split string by.
  75. * @param {Object} map Optional map to add items to.
  76. * @return {Object} Name/value map of items.
  77. */
  78. function makeMap(items, delim, map) {
  79. var i;
  80. items = items || [];
  81. delim = delim || ',';
  82. if (typeof(items) == "string") {
  83. items = items.split(delim);
  84. }
  85. map = map || {};
  86. i = items.length;
  87. while (i--) {
  88. map[items[i]] = {};
  89. }
  90. return map;
  91. }
  92. /**
  93. * Performs an iteration of all items in a collection such as an object or array. This method will execure the
  94. * callback function for each item in the collection, if the callback returns false the iteration will terminate.
  95. * The callback has the following format: cb(value, key_or_index).
  96. *
  97. * @method each
  98. * @param {Object} o Collection to iterate.
  99. * @param {function} cb Callback function to execute for each item.
  100. * @param {Object} s Optional scope to execute the callback in.
  101. * @example
  102. * // Iterate an array
  103. * tinymce.each([1,2,3], function(v, i) {
  104. * console.debug("Value: " + v + ", Index: " + i);
  105. * });
  106. *
  107. * // Iterate an object
  108. * tinymce.each({a: 1, b: 2, c: 3], function(v, k) {
  109. * console.debug("Value: " + v + ", Key: " + k);
  110. * });
  111. */
  112. function each(o, cb, s) {
  113. var n, l;
  114. if (!o) {
  115. return 0;
  116. }
  117. s = s || o;
  118. if (o.length !== undefined) {
  119. // Indexed arrays, needed for Safari
  120. for (n = 0, l = o.length; n < l; n++) {
  121. if (cb.call(s, o[n], n, o) === false) {
  122. return 0;
  123. }
  124. }
  125. } else {
  126. // Hashtables
  127. for (n in o) {
  128. if (o.hasOwnProperty(n)) {
  129. if (cb.call(s, o[n], n, o) === false) {
  130. return 0;
  131. }
  132. }
  133. }
  134. }
  135. return 1;
  136. }
  137. /**
  138. * Creates a new array by the return value of each iteration function call. This enables you to convert
  139. * one array list into another.
  140. *
  141. * @method map
  142. * @param {Array} a Array of items to iterate.
  143. * @param {function} f Function to call for each item. It's return value will be the new value.
  144. * @return {Array} Array with new values based on function return values.
  145. */
  146. function map(a, f) {
  147. var o = [];
  148. each(a, function(v) {
  149. o.push(f(v));
  150. });
  151. return o;
  152. }
  153. /**
  154. * Filters out items from the input array by calling the specified function for each item.
  155. * If the function returns false the item will be excluded if it returns true it will be included.
  156. *
  157. * @method grep
  158. * @param {Array} a Array of items to loop though.
  159. * @param {function} f Function to call for each item. Include/exclude depends on it's return value.
  160. * @return {Array} New array with values imported and filtered based in input.
  161. * @example
  162. * // Filter out some items, this will return an array with 4 and 5
  163. * var items = tinymce.grep([1,2,3,4,5], function(v) {return v > 3;});
  164. */
  165. function grep(a, f) {
  166. var o = [];
  167. each(a, function(v) {
  168. if (!f || f(v)) {
  169. o.push(v);
  170. }
  171. });
  172. return o;
  173. }
  174. /**
  175. * Creates a class, subclass or static singleton.
  176. * More details on this method can be found in the Wiki.
  177. *
  178. * @method create
  179. * @param {String} s Class name, inheritage and prefix.
  180. * @param {Object} p Collection of methods to add to the class.
  181. * @param {Object} root Optional root object defaults to the global window object.
  182. * @example
  183. * // Creates a basic class
  184. * tinymce.create('tinymce.somepackage.SomeClass', {
  185. * SomeClass: function() {
  186. * // Class constructor
  187. * },
  188. *
  189. * method: function() {
  190. * // Some method
  191. * }
  192. * });
  193. *
  194. * // Creates a basic subclass class
  195. * tinymce.create('tinymce.somepackage.SomeSubClass:tinymce.somepackage.SomeClass', {
  196. * SomeSubClass: function() {
  197. * // Class constructor
  198. * this.parent(); // Call parent constructor
  199. * },
  200. *
  201. * method: function() {
  202. * // Some method
  203. * this.parent(); // Call parent method
  204. * },
  205. *
  206. * 'static': {
  207. * staticMethod: function() {
  208. * // Static method
  209. * }
  210. * }
  211. * });
  212. *
  213. * // Creates a singleton/static class
  214. * tinymce.create('static tinymce.somepackage.SomeSingletonClass', {
  215. * method: function() {
  216. * // Some method
  217. * }
  218. * });
  219. */
  220. function create(s, p, root) {
  221. var self = this, sp, ns, cn, scn, c, de = 0;
  222. // Parse : <prefix> <class>:<super class>
  223. s = /^((static) )?([\w.]+)(:([\w.]+))?/.exec(s);
  224. cn = s[3].match(/(^|\.)(\w+)$/i)[2]; // Class name
  225. // Create namespace for new class
  226. ns = self.createNS(s[3].replace(/\.\w+$/, ''), root);
  227. // Class already exists
  228. if (ns[cn]) {
  229. return;
  230. }
  231. // Make pure static class
  232. if (s[2] == 'static') {
  233. ns[cn] = p;
  234. if (this.onCreate) {
  235. this.onCreate(s[2], s[3], ns[cn]);
  236. }
  237. return;
  238. }
  239. // Create default constructor
  240. if (!p[cn]) {
  241. p[cn] = function() {};
  242. de = 1;
  243. }
  244. // Add constructor and methods
  245. ns[cn] = p[cn];
  246. self.extend(ns[cn].prototype, p);
  247. // Extend
  248. if (s[5]) {
  249. sp = self.resolve(s[5]).prototype;
  250. scn = s[5].match(/\.(\w+)$/i)[1]; // Class name
  251. // Extend constructor
  252. c = ns[cn];
  253. if (de) {
  254. // Add passthrough constructor
  255. ns[cn] = function() {
  256. return sp[scn].apply(this, arguments);
  257. };
  258. } else {
  259. // Add inherit constructor
  260. ns[cn] = function() {
  261. this.parent = sp[scn];
  262. return c.apply(this, arguments);
  263. };
  264. }
  265. ns[cn].prototype[cn] = ns[cn];
  266. // Add super methods
  267. self.each(sp, function(f, n) {
  268. ns[cn].prototype[n] = sp[n];
  269. });
  270. // Add overridden methods
  271. self.each(p, function(f, n) {
  272. // Extend methods if needed
  273. if (sp[n]) {
  274. ns[cn].prototype[n] = function() {
  275. this.parent = sp[n];
  276. return f.apply(this, arguments);
  277. };
  278. } else {
  279. if (n != cn) {
  280. ns[cn].prototype[n] = f;
  281. }
  282. }
  283. });
  284. }
  285. // Add static methods
  286. /*jshint sub:true*/
  287. self.each(p['static'], function(f, n) {
  288. ns[cn][n] = f;
  289. });
  290. }
  291. /**
  292. * Returns the index of a value in an array, this method will return -1 if the item wasn't found.
  293. *
  294. * @method inArray
  295. * @param {Array} a Array/Object to search for value in.
  296. * @param {Object} v Value to check for inside the array.
  297. * @return {Number/String} Index of item inside the array inside an object. Or -1 if it wasn't found.
  298. * @example
  299. * // Get index of value in array this will alert 1 since 2 is at that index
  300. * alert(tinymce.inArray([1,2,3], 2));
  301. */
  302. function inArray(a, v) {
  303. var i, l;
  304. if (a) {
  305. for (i = 0, l = a.length; i < l; i++) {
  306. if (a[i] === v) {
  307. return i;
  308. }
  309. }
  310. }
  311. return -1;
  312. }
  313. function extend(obj, ext) {
  314. var i, l, name, args = arguments, value;
  315. for (i = 1, l = args.length; i < l; i++) {
  316. ext = args[i];
  317. for (name in ext) {
  318. if (ext.hasOwnProperty(name)) {
  319. value = ext[name];
  320. if (value !== undefined) {
  321. obj[name] = value;
  322. }
  323. }
  324. }
  325. }
  326. return obj;
  327. }
  328. /**
  329. * Executed the specified function for each item in a object tree.
  330. *
  331. * @method walk
  332. * @param {Object} o Object tree to walk though.
  333. * @param {function} f Function to call for each item.
  334. * @param {String} n Optional name of collection inside the objects to walk for example childNodes.
  335. * @param {String} s Optional scope to execute the function in.
  336. */
  337. function walk(o, f, n, s) {
  338. s = s || this;
  339. if (o) {
  340. if (n) {
  341. o = o[n];
  342. }
  343. each(o, function(o, i) {
  344. if (f.call(s, o, i, n) === false) {
  345. return false;
  346. }
  347. walk(o, f, n, s);
  348. });
  349. }
  350. }
  351. /**
  352. * Creates a namespace on a specific object.
  353. *
  354. * @method createNS
  355. * @param {String} n Namespace to create for example a.b.c.d.
  356. * @param {Object} o Optional object to add namespace to, defaults to window.
  357. * @return {Object} New namespace object the last item in path.
  358. * @example
  359. * // Create some namespace
  360. * tinymce.createNS('tinymce.somepackage.subpackage');
  361. *
  362. * // Add a singleton
  363. * var tinymce.somepackage.subpackage.SomeSingleton = {
  364. * method: function() {
  365. * // Some method
  366. * }
  367. * };
  368. */
  369. function createNS(n, o) {
  370. var i, v;
  371. o = o || window;
  372. n = n.split('.');
  373. for (i = 0; i < n.length; i++) {
  374. v = n[i];
  375. if (!o[v]) {
  376. o[v] = {};
  377. }
  378. o = o[v];
  379. }
  380. return o;
  381. }
  382. /**
  383. * Resolves a string and returns the object from a specific structure.
  384. *
  385. * @method resolve
  386. * @param {String} n Path to resolve for example a.b.c.d.
  387. * @param {Object} o Optional object to search though, defaults to window.
  388. * @return {Object} Last object in path or null if it couldn't be resolved.
  389. * @example
  390. * // Resolve a path into an object reference
  391. * var obj = tinymce.resolve('a.b.c.d');
  392. */
  393. function resolve(n, o) {
  394. var i, l;
  395. o = o || window;
  396. n = n.split('.');
  397. for (i = 0, l = n.length; i < l; i++) {
  398. o = o[n[i]];
  399. if (!o) {
  400. break;
  401. }
  402. }
  403. return o;
  404. }
  405. /**
  406. * Splits a string but removes the whitespace before and after each value.
  407. *
  408. * @method explode
  409. * @param {string} s String to split.
  410. * @param {string} d Delimiter to split by.
  411. * @example
  412. * // Split a string into an array with a,b,c
  413. * var arr = tinymce.explode('a, b, c');
  414. */
  415. function explode(s, d) {
  416. if (!s || is(s, 'array')) {
  417. return s;
  418. }
  419. return map(s.split(d || ','), trim);
  420. }
  421. return {
  422. trim: trim,
  423. isArray: isArray,
  424. is: is,
  425. toArray: toArray,
  426. makeMap: makeMap,
  427. each: each,
  428. map: map,
  429. grep: grep,
  430. inArray: inArray,
  431. extend: extend,
  432. create: create,
  433. walk: walk,
  434. createNS: createNS,
  435. resolve: resolve,
  436. explode: explode
  437. };
  438. });