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