      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.skins} object, which is used to
      8  *		manage skins loading.
      9  */
     10
     11 /**
     12  * Manages skins loading.
     13  * @namespace
     14  * @example
     15  */
     16 CKEDITOR.skins = (function()
     17 {
     18 	// Holds the list of loaded skins.
     19 	var loaded = {};
     20 	var preloaded = {};
     21 	var paths = {};
     22
     23 	var loadedPart = function( skinName, part, callback )
     24 	{
     25 		// Get the skin definition.
     26 		var skinDefinition = loaded[ skinName ];
     27
     28 		var appendSkinPath = function( fileNames )
     29 		{
     30 			for ( var n = 0 ; n < fileNames.length ; n++ )
     31 			{
     32 				fileNames[ n ] = CKEDITOR.getUrl( paths[ skinName ] + fileNames[ n ] );
     33 			}
     34 		};
     35
     36 		// Check if we need to preload images from it.
     37 		if ( !preloaded[ skinName ] )
     38 		{
     39 			var preload = skinDefinition.preload;
     40 			if ( preload && preload.length > 0 )
     41 			{
     42 				appendSkinPath( preload );
     43 				CKEDITOR.imageCacher.load( preload, function()
     44 					{
     45 						preloaded[ skinName ] = 1;
     46 						loadedPart( skinName, part, callback );
     47 					} );
     48 				return;
     49 			}
     50
     51 			// Mark it as preloaded.
     52 			preloaded[ skinName ] = 1;
     53 		}
     54
     55 		// Get the part definition.
     56 		part = skinDefinition[ part ];
     57 		var partIsLoaded = !part || !!part._isLoaded;
     58
     59 		// Call the callback immediately if already loaded.
     60 		if ( partIsLoaded )
     61 			callback && callback();
     62 		else
     63 		{
     64 			// Put the callback in a queue.
     65 			var pending = part._pending || ( part._pending = [] );
     66 			pending.push( callback );
     67
     68 			// We may have more than one skin part load request. Just the first
     69 			// one must do the loading job.
     70 			if ( pending.length > 1 )
     71 				return;
     72
     73 			// Check whether the "css" and "js" properties have been defined
     74 			// for that part.
     75 			var cssIsLoaded = !part.css || !part.css.length;
     76 			var jsIsLoaded = !part.js || !part.js.length;
     77
     78 			// This is the function that will trigger the callback calls on
     79 			// load.
     80 			var checkIsLoaded = function()
     81 			{
     82 				if ( cssIsLoaded && jsIsLoaded )
     83 				{
     84 					// Mark the part as loaded.
     85 					part._isLoaded = 1;
     86
     87 					// Call all pending callbacks.
     88 					for ( var i = 0 ; i < pending.length ; i++ )
     89 					{
     90 						if ( pending[ i ] )
     91 							pending[ i ]();
     92 					}
     93 				}
     94 			};
     95
     96 			// Load the "css" pieces.
     97 			if ( !cssIsLoaded )
     98 			{
     99 				appendSkinPath( part.css );
    100
    101 				for ( var c = 0 ; c < part.css.length ; c++ )
    102 					CKEDITOR.document.appendStyleSheet( part.css[ c ] );
    103
    104 				cssIsLoaded = 1;
    105 			}
    106
    107 			// Load the "js" pieces.
    108 			if ( !jsIsLoaded )
    109 			{
    110 				appendSkinPath( part.js );
    111 				CKEDITOR.scriptLoader.load( part.js, function()
    112 					{
    113 						jsIsLoaded = 1;
    114 						checkIsLoaded();
    115 					});
    116 			}
    117
    118 			// We may have nothing to load, so check it immediately.
    119 			checkIsLoaded();
    120 		}
    121 	};
    122
    123 	return /** @lends CKEDITOR.skins */ {
    124
    125 		/**
    126 		 * Registers a skin definition.
    127 		 * @param {String} skinName The skin name.
    128 		 * @param {Object} skinDefinition The skin definition.
    129 		 * @example
    130 		 */
    131 		add : function( skinName, skinDefinition )
    132 		{
    133 			loaded[ skinName ] = skinDefinition;
    134
    135 			skinDefinition.skinPath = paths[ skinName ]
    136 				|| ( paths[ skinName ] =
    137 						CKEDITOR.getUrl(
    139 							'skins/' + skinName + '/' ) );
    140 		},
    141
    142 		/**
    143 		 * Loads a skin part. Skins are defined in parts, which are basically
    144 		 * separated CSS files. This function is mainly used by the core code and
    145 		 * should not have much use out of it.
    146 		 * @param {String} skinName The name of the skin to be loaded.
    147 		 * @param {String} skinPart The skin part to be loaded. Common skin parts
    148 		 *		are "editor" and "dialog".
    149 		 * @param {Function} [callback] A function to be called once the skin
    150 		 *		part files are loaded.
    151 		 * @example
    152 		 */
    153 		load : function( editor, skinPart, callback )
    154 		{
    155 			var skinName = editor.skinName,
    156 				skinPath = editor.skinPath;
    157
    158 			if ( loaded[ skinName ] )
    159 			{
    160 				loadedPart( skinName, skinPart, callback );
    161
    162 				// Get the skin definition.
    163 				var skinDefinition = loaded[ skinName ];
    164
    165 				// Trigger init function if any.
    166 				if ( skinDefinition.init )
    167 					skinDefinition.init( editor );
    168 			}
    169 			else
    170 			{
    171 				paths[ skinName ] = skinPath;
    172 				CKEDITOR.scriptLoader.load( skinPath + 'skin.js', function()
    173 						{
    174 							loadedPart( skinName, skinPart, callback );
    175
    176 							// Get the skin definition.
    177 							var skinDefinition = loaded[ skinName ];
    178
    179 							// Trigger init function if any.
    180 							if ( skinDefinition.init )
    181 								skinDefinition.init( editor );
    182 						});
    183 			}
    184 		}
    185 	};
    186 })();
    187