1 /*
  2 Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
  3 For licensing, see LICENSE.html or http://ckeditor.com/license
  4 */
  5
  6 /**
  7  * @fileOverview Defines the {@link CKEDITOR.tools} object, which contains
  8  *		utility functions.
  9  */
 10
 11 /**
 12  * Utility functions.
 13  * @namespace
 14  * @example
 15  */
 16 CKEDITOR.tools =
 17 {
 18 	/**
 19 	 * Copy the properties from one object to another. By default, properties
 20 	 * already present in the target object <strong>are not</strong> overwritten.
 21 	 * @param {Object} target The object to be extended.
 22 	 * @param {Object} source[,souce(n)] The objects from which copy
 23 	 *		properties. Any number of objects can be passed to this function.
 24 	 * @param {Boolean} [overwrite] Indicates that properties already present
 25 	 *		in the target object must be overwritten. This must be the last
 26 	 *		parameter in the function call.
 27 	 * @returns {Object} the extended object (target).
 28 	 * @example
 29 	 * // Create the sample object.
 30 	 * var myObject =
 31 	 * {
 32 	 *     prop1 : true
 33 	 * };
 34 	 *
 35 	 * // Extend the above object with two properties.
 36 	 * CKEDITOR.tools.extend( myObject,
 37 	 *     {
 38 	 *         prop2 : true,
 39 	 *         prop3 : true
 40 	 *     } );
 41 	 *
 42 	 * // Alert "prop1", "prop2" and "prop3".
 43 	 * for ( var p in myObject )
 44 	 *     alert( p );
 45 	 */
 46 	extend : function( target )
 47 	{
 48 		var argsLength = arguments.length,
 49 			overwrite = arguments[ argsLength - 1 ];
 50
 51 		if ( typeof overwrite == 'boolean' )
 52 			argsLength--;
 53 		else
 54 			overwrite = false;
 55
 56 		for ( var i = 1 ; i < argsLength ; i++ )
 57 		{
 58 			var source = arguments[ i ];
 59
 60 			for ( var propertyName in source )
 61 			{
 62 				if ( overwrite || target[ propertyName ] == undefined )
 63 					target[ propertyName ] = source[ propertyName ];
 64 			}
 65 		}
 66
 67 		return target;
 68 	},
 69
 70 	/**
 71 	 * Creates an object which is an instance of a class which prototype is a
 72 	 * predefined object. All properties defined in the source object are
 73 	 * automatically inherited by the resulting object, including future
 74 	 * changes to it.
 75 	 * @param {Object} source The source object to be used as the prototype for
 76 	 *		the final object.
 77 	 * @returns {Object} The resulting copy.
 78 	 */
 79 	prototypedCopy : function( source )
 80 	{
 81 		var copy = function()
 82 		{};
 83 		copy.prototype = source;
 84 		return new copy();
 85 	},
 86
 87 	/**
 88 	 * Checks if an object is an Array.
 89 	 * @param {Object} object The object to be checked.
 90 	 * @type Boolean
 91 	 * @returns <i>true</i> if the object is an Array, otherwise <i>false</i>.
 92 	 * @example
 93 	 * alert( CKEDITOR.tools.isArray( [] ) );      // "true"
 94 	 * alert( CKEDITOR.tools.isArray( 'Test' ) );  // "false"
 95 	 */
 96 	isArray : function( object )
 97 	{
 98 		return ( !!object && object instanceof Array );
 99 	},
100
101 	/**
102 	 * Transforms a CSS property name to its relative DOM style name.
103 	 * @param {String} cssName The CSS property name.
104 	 * @returns {String} The transformed name.
105 	 * @example
106 	 * alert( CKEDITOR.tools.cssStyleToDomStyle( 'background-color' ) );  // "backgroundColor"
107 	 * alert( CKEDITOR.tools.cssStyleToDomStyle( 'float' ) );             // "cssFloat"
108 	 */
109 	cssStyleToDomStyle : function( cssName )
110 	{
111 		if ( cssName == 'float' )
112 			return 'cssFloat';
113 		else
114 		{
115 			return cssName.replace( /-./g, function( match )
116 				{
117 					return match.substr( 1 ).toUpperCase();
118 				});
119 		}
120 	},
121
122 	/**
123 	 * Replace special HTML characters in a string with their relative HTML
124 	 * entity values.
125 	 * @param {String} text The string to be encoded.
126 	 * @returns {String} The encode string.
127 	 * @example
128 	 * alert( CKEDITOR.tools.htmlEncode( 'A > B & C < D' ) );  // "A &gt; B &amp; C &lt; D"
129 	 */
130 	htmlEncode : function( text )
131 	{
132 		var standard = function( text )
133 		{
134 			var span = new CKEDITOR.dom.element( 'span' );
135 			span.setText( text );
136 			return span.getHtml();
137 		};
138
139 		this.htmlEncode = ( standard( '>' ) == '>' ) ?
140 			function( text )
141 			{
142 				// WebKit does't encode the ">" character, which makes sense, but
143 				// it's different than other browsers.
144 				return standard( text ).replace( />/g, '>' );
145 			} :
146 			standard;
147
148 		return this.htmlEncode( text );
149 	},
150
151 	/**
152 	 * Gets a unique number for this CKEDITOR execution session. It returns
153 	 * progressive numbers starting at 1.
154 	 * @function
155 	 * @returns {Number} A unique number.
156 	 * @example
157 	 * alert( CKEDITOR.tools.<b>getNextNumber()</b> );  // "1" (e.g.)
158 	 * alert( CKEDITOR.tools.<b>getNextNumber()</b> );  // "2"
159 	 */
160 	getNextNumber : (function()
161 	{
162 		var last = 0;
163 		return function()
164 		{
165 			return ++last;
166 		};
167 	})(),
168
169 	/**
170 	 * Creates a function override.
171 	 * @param {Function} originalFunction The function to be overridden.
172 	 * @param {Function} functionBuilder A function that returns the new
173 	 *		function. The original function reference will be passed to this
174 	 *		function.
175 	 * @returns {Function} The new function.
176 	 * @example
177 	 * var example =
178 	 * {
179 	 *     myFunction : function( name )
180 	 *     {
181 	 *         alert( 'Name: ' + name );
182 	 *     }
183 	 * };
184 	 *
185 	 * example.myFunction = CKEDITOR.tools.override( example.myFunction, function( myFunctionOriginal )
186 	 *     {
187 	 *         return function( name )
188 	 *             {
189 	 *                 alert( 'Override Name: ' + name );
190 	 *                 myFunctionOriginal.call( this, name );
191 	 *             };
192 	 *     });
193 	 */
194 	override : function( originalFunction, functionBuilder )
195 	{
196 		return functionBuilder( originalFunction );
197 	},
198
199 	/**
200 	 * Executes a function after specified delay.
201 	 * @param {Function} func The function to be executed.
202 	 * @param {Number} [milliseconds] The amount of time (millisecods) to wait
203 	 *		to fire the function execution. Defaults to zero.
204 	 * @param {Object} [scope] The object to hold the function execution scope
205 	 *		(the "this" object). By default the "window" object.
206 	 * @param {Object|Array} [args] A single object, or an array of objects, to
207 	 *		pass as arguments to the function.
208 	 * @param {Object} [ownerWindow] The window that will be used to set the
209 	 *		timeout. By default the current "window".
210 	 * @returns {Object} A value that can be used to cancel the function execution.
211 	 * @example
212 	 * CKEDITOR.tools.<b>setTimeout(
213 	 *     function()
214 	 *     {
215 	 *         alert( 'Executed after 2 seconds' );
216 	 *     },
217 	 *     2000 )</b>;
218 	 */
219 	setTimeout : function( func, milliseconds, scope, args, ownerWindow )
220 	{
221 		if ( !ownerWindow )
222 			ownerWindow = window;
223
224 		if ( !scope )
225 			scope = ownerWindow;
226
227 		return ownerWindow.setTimeout(
228 			function()
229 			{
230 				if ( args )
231 					func.apply( scope, [].concat( args ) ) ;
232 				else
233 					func.apply( scope ) ;
234 			},
235 			milliseconds || 0 );
236 	},
237
238 	/**
239 	 * Remove spaces from the start and the end of a string. The following
240 	 * characters are removed: space, tab, line break, line feed.
241 	 * @function
242 	 * @param {String} str The text from which remove the spaces.
243 	 * @returns {String} The modified string without the boundary spaces.
244 	 * @example
245 	 * alert( CKEDITOR.tools.trim( '  example ' );  // "example"
246 	 */
247 	trim : (function()
248 	{
249 		// We are not using \s because we don't want "non-breaking spaces" to be caught.
250 		var trimRegex = /(?:^[ \t\n\r]+)|(?:[ \t\n\r]+$)/g;
251 		return function( str )
252 		{
253 			return str.replace( trimRegex, '' ) ;
254 		};
255 	})(),
256
257 	/**
258 	 * Remove spaces from the start (left) of a string. The following
259 	 * characters are removed: space, tab, line break, line feed.
260 	 * @function
261 	 * @param {String} str The text from which remove the spaces.
262 	 * @returns {String} The modified string excluding the removed spaces.
263 	 * @example
264 	 * alert( CKEDITOR.tools.ltrim( '  example ' );  // "example "
265 	 */
266 	ltrim : (function()
267 	{
268 		// We are not using \s because we don't want "non-breaking spaces" to be caught.
269 		var trimRegex = /^[ \t\n\r]+/g;
270 		return function( str )
271 		{
272 			return str.replace( trimRegex, '' ) ;
273 		};
274 	})(),
275
276 	/**
277 	 * Remove spaces from the end (right) of a string. The following
278 	 * characters are removed: space, tab, line break, line feed.
279 	 * @function
280 	 * @param {String} str The text from which remove the spaces.
281 	 * @returns {String} The modified string excluding the removed spaces.
282 	 * @example
283 	 * alert( CKEDITOR.tools.ltrim( '  example ' );  // "  example"
284 	 */
285 	rtrim : (function()
286 	{
287 		// We are not using \s because we don't want "non-breaking spaces" to be caught.
288 		var trimRegex = /[ \t\n\r]+$/g;
289 		return function( str )
290 		{
291 			return str.replace( trimRegex, '' ) ;
292 		};
293 	})(),
294
295 	/**
296 	 * Returns the index of an element in an array.
297 	 * @param {Array} array The array to be searched.
298 	 * @param {Object} entry The element to be found.
299 	 * @returns {Number} The (zero based) index of the first entry that matches
300 	 *		the entry, or -1 if not found.
301 	 * @example
302 	 * var letters = [ 'a', 'b', 'c' ];
303 	 * alert( CKEDITOR.tools.indexOf( letters, 'b' ) );  "1"
304 	 */
305 	indexOf : function( array, entry )
306 	{
307 		for ( var i = 0, len = array.length ; i < len ; i++ )
308 		{
309 			if ( array[ i ] == entry )
310 				return i;
311 		}
312 		return -1;
313 	}
314 };
315
316 // PACKAGER_RENAME( CKEDITOR.tools )
317