4 * Copyright, Moxiecode Systems AB
5 * Released under LGPL License.
7 * License: http://www.tinymce.com/license
8 * Contributing: http://www.tinymce.com/contributing
12 * This class contains various utlity functions. These are also exposed
13 * directly on the tinymce namespace.
15 * @class tinymce.util.Tools
17 define("tinymce/util/Tools", [], function() {
19 * Removes whitespace from the beginning and end of a string.
22 * @param {String} s String to remove whitespace from.
23 * @return {String} New string with removed whitespace.
25 var whiteSpaceRegExp = /^\s*|\s*$/g;
26 var trim = function(str) {
27 return (str === null || str === undefined) ? '' : ("" + str).replace(whiteSpaceRegExp, '');
31 * Returns true/false if the object is an array or not.
34 * @param {Object} obj Object to check.
35 * @return {boolean} true/false state if the object is an array or not.
37 var isArray = Array.isArray || function(obj) {
38 return Object.prototype.toString.call(obj) === "[object Array]";
42 * Checks if a object is of a specific type for example an array.
45 * @param {Object} o Object to check type of.
46 * @param {string} t Optional type to check for.
47 * @return {Boolean} true/false if the object is of the specified type.
51 return o !== undefined;
54 if (t == 'array' && isArray(o)) {
58 return typeof(o) == t;
62 * Converts the specified object into a real JavaScript array.
65 * @param {Object} obj Object to convert into array.
66 * @return {Array} Array object based in input.
68 function toArray(obj) {
71 for (i = 0, l = obj.length; i < l; i++) {
79 * Makes a name/object map out of an array with names.
82 * @param {Array/String} items Items to make map out of.
83 * @param {String} delim Optional delimiter to split string by.
84 * @param {Object} map Optional map to add items to.
85 * @return {Object} Name/value map of items.
87 function makeMap(items, delim, map) {
93 if (typeof(items) == "string") {
94 items = items.split(delim);
108 * Performs an iteration of all items in a collection such as an object or array. This method will execure the
109 * callback function for each item in the collection, if the callback returns false the iteration will terminate.
110 * The callback has the following format: cb(value, key_or_index).
113 * @param {Object} o Collection to iterate.
114 * @param {function} cb Callback function to execute for each item.
115 * @param {Object} s Optional scope to execute the callback in.
117 * // Iterate an array
118 * tinymce.each([1,2,3], function(v, i) {
119 * console.debug("Value: " + v + ", Index: " + i);
122 * // Iterate an object
123 * tinymce.each({a: 1, b: 2, c: 3], function(v, k) {
124 * console.debug("Value: " + v + ", Key: " + k);
127 function each(o, cb, s) {
136 if (o.length !== undefined) {
137 // Indexed arrays, needed for Safari
138 for (n=0, l = o.length; n < l; n++) {
139 if (cb.call(s, o[n], n, o) === false) {
146 if (o.hasOwnProperty(n)) {
147 if (cb.call(s, o[n], n, o) === false) {
158 * Creates a new array by the return value of each iteration function call. This enables you to convert
159 * one array list into another.
162 * @param {Array} a Array of items to iterate.
163 * @param {function} f Function to call for each item. It's return value will be the new value.
164 * @return {Array} Array with new values based on function return values.
169 each(a, function(v) {
177 * Filters out items from the input array by calling the specified function for each item.
178 * If the function returns false the item will be excluded if it returns true it will be included.
181 * @param {Array} a Array of items to loop though.
182 * @param {function} f Function to call for each item. Include/exclude depends on it's return value.
183 * @return {Array} New array with values imported and filtered based in input.
185 * // Filter out some items, this will return an array with 4 and 5
186 * var items = tinymce.grep([1,2,3,4,5], function(v) {return v > 3;});
188 function grep(a, f) {
191 each(a, function(v) {
201 * Creates a class, subclass or static singleton.
202 * More details on this method can be found in the Wiki.
205 * @param {String} s Class name, inheritage and prefix.
206 * @param {Object} p Collection of methods to add to the class.
207 * @param {Object} root Optional root object defaults to the global window object.
209 * // Creates a basic class
210 * tinymce.create('tinymce.somepackage.SomeClass', {
211 * SomeClass: function() {
212 * // Class constructor
215 * method: function() {
220 * // Creates a basic subclass class
221 * tinymce.create('tinymce.somepackage.SomeSubClass:tinymce.somepackage.SomeClass', {
222 * SomeSubClass: function() {
223 * // Class constructor
224 * this.parent(); // Call parent constructor
227 * method: function() {
229 * this.parent(); // Call parent method
233 * staticMethod: function() {
239 * // Creates a singleton/static class
240 * tinymce.create('static tinymce.somepackage.SomeSingletonClass', {
241 * method: function() {
246 function create(s, p, root) {
247 var t = this, sp, ns, cn, scn, c, de = 0;
249 // Parse : <prefix> <class>:<super class>
250 s = /^((static) )?([\w.]+)(:([\w.]+))?/.exec(s);
251 cn = s[3].match(/(^|\.)(\w+)$/i)[2]; // Class name
253 // Create namespace for new class
254 ns = t.createNS(s[3].replace(/\.\w+$/, ''), root);
256 // Class already exists
261 // Make pure static class
262 if (s[2] == 'static') {
266 this.onCreate(s[2], s[3], ns[cn]);
272 // Create default constructor
274 p[cn] = function() {};
278 // Add constructor and methods
280 t.extend(ns[cn].prototype, p);
284 sp = t.resolve(s[5]).prototype;
285 scn = s[5].match(/\.(\w+)$/i)[1]; // Class name
287 // Extend constructor
290 // Add passthrough constructor
291 ns[cn] = function() {
292 return sp[scn].apply(this, arguments);
295 // Add inherit constructor
296 ns[cn] = function() {
297 this.parent = sp[scn];
298 return c.apply(this, arguments);
301 ns[cn].prototype[cn] = ns[cn];
304 t.each(sp, function(f, n) {
305 ns[cn].prototype[n] = sp[n];
308 // Add overridden methods
309 t.each(p, function(f, n) {
310 // Extend methods if needed
312 ns[cn].prototype[n] = function() {
314 return f.apply(this, arguments);
318 ns[cn].prototype[n] = f;
324 // Add static methods
326 t.each(p['static'], function(f, n) {
332 * Returns the index of a value in an array, this method will return -1 if the item wasn't found.
335 * @param {Array} a Array/Object to search for value in.
336 * @param {Object} v Value to check for inside the array.
337 * @return {Number/String} Index of item inside the array inside an object. Or -1 if it wasn't found.
339 * // Get index of value in array this will alert 1 since 2 is at that index
340 * alert(tinymce.inArray([1,2,3], 2));
342 function inArray(a, v) {
346 for (i = 0, l = a.length; i < l; i++) {
356 function extend(obj, ext) {
357 var i, l, name, args = arguments, value;
359 for (i = 1, l = args.length; i < l; i++) {
362 if (ext.hasOwnProperty(name)) {
365 if (value !== undefined) {
376 * Executed the specified function for each item in a object tree.
379 * @param {Object} o Object tree to walk though.
380 * @param {function} f Function to call for each item.
381 * @param {String} n Optional name of collection inside the objects to walk for example childNodes.
382 * @param {String} s Optional scope to execute the function in.
384 function walk(o, f, n, s) {
392 each(o, function(o, i) {
393 if (f.call(s, o, i, n) === false) {
403 * Creates a namespace on a specific object.
406 * @param {String} n Namespace to create for example a.b.c.d.
407 * @param {Object} o Optional object to add namespace to, defaults to window.
408 * @return {Object} New namespace object the last item in path.
410 * // Create some namespace
411 * tinymce.createNS('tinymce.somepackage.subpackage');
414 * var tinymce.somepackage.subpackage.SomeSingleton = {
415 * method: function() {
420 function createNS(n, o) {
426 for (i=0; i<n.length; i++) {
440 * Resolves a string and returns the object from a specific structure.
443 * @param {String} n Path to resolve for example a.b.c.d.
444 * @param {Object} o Optional object to search though, defaults to window.
445 * @return {Object} Last object in path or null if it couldn't be resolved.
447 * // Resolve a path into an object reference
448 * var obj = tinymce.resolve('a.b.c.d');
450 function resolve(n, o) {
456 for (i = 0, l = n.length; i < l; i++) {
468 * Splits a string but removes the whitespace before and after each value.
471 * @param {string} s String to split.
472 * @param {string} d Delimiter to split by.
474 * // Split a string into an array with a,b,c
475 * var arr = tinymce.explode('a, b, c');
477 function explode(s, d) {
478 if (!s || is(s, 'array')) {
482 return map(s.split(d || ','), trim);