/* Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.html or http://ckeditor.com/license */ /** * @fileOverview Defines the {@link CKEDITOR.skins} object, which is used to * manage skins loading. */ /** * Manages skins loading. * @namespace * @example */ CKEDITOR.skins = (function() { // Holds the list of loaded skins. var loaded = {}, paths = {}; var loadPart = function( editor, skinName, part, callback ) { // Get the skin definition. var skinDefinition = loaded[ skinName ]; if ( !editor.skin ) { editor.skin = skinDefinition; // Trigger init function if any. if ( skinDefinition.init ) skinDefinition.init( editor ); } var appendSkinPath = function( fileNames ) { for ( var n = 0 ; n < fileNames.length ; n++ ) { fileNames[ n ] = CKEDITOR.getUrl( paths[ skinName ] + fileNames[ n ] ); } }; function fixCSSTextRelativePath( cssStyleText, baseUrl ) { return cssStyleText.replace( /url\s*\(([\s'"]*)(.*?)([\s"']*)\)/g, function( match, opener, path, closer ) { if ( /^\/|^\w?:/.test( path ) ) return match; else return 'url(' + baseUrl + opener + path + closer + ')'; } ); } // Get the part definition. part = skinDefinition[ part ]; var partIsLoaded = !part || !!part._isLoaded; // Call the callback immediately if already loaded. if ( partIsLoaded ) callback && callback(); else { // Put the callback in a queue. var pending = part._pending || ( part._pending = [] ); pending.push( callback ); // We may have more than one skin part load request. Just the first // one must do the loading job. if ( pending.length > 1 ) return; // Check whether the "css" and "js" properties have been defined // for that part. var cssIsLoaded = !part.css || !part.css.length, jsIsLoaded = !part.js || !part.js.length; // This is the function that will trigger the callback calls on // load. var checkIsLoaded = function() { if ( cssIsLoaded && jsIsLoaded ) { // Mark the part as loaded. part._isLoaded = 1; // Call all pending callbacks. for ( var i = 0 ; i < pending.length ; i++ ) { if ( pending[ i ] ) pending[ i ](); } } }; // Load the "css" pieces. if ( !cssIsLoaded ) { var cssPart = part.css; if ( CKEDITOR.tools.isArray( cssPart ) ) { appendSkinPath( cssPart ); for ( var c = 0 ; c < cssPart.length ; c++ ) CKEDITOR.document.appendStyleSheet( cssPart[ c ] ); } else { cssPart = fixCSSTextRelativePath( cssPart, CKEDITOR.getUrl( paths[ skinName ] ) ); // Processing Inline CSS part. CKEDITOR.document.appendStyleText( cssPart ); } part.css = cssPart; cssIsLoaded = 1; } // Load the "js" pieces. if ( !jsIsLoaded ) { appendSkinPath( part.js ); CKEDITOR.scriptLoader.load( part.js, function() { jsIsLoaded = 1; checkIsLoaded(); }); } // We may have nothing to load, so check it immediately. checkIsLoaded(); } }; return /** @lends CKEDITOR.skins */ { /** * Registers a skin definition. * @param {String} skinName The skin name. * @param {Object} skinDefinition The skin definition. * @example */ add : function( skinName, skinDefinition ) { loaded[ skinName ] = skinDefinition; skinDefinition.skinPath = paths[ skinName ] || ( paths[ skinName ] = CKEDITOR.getUrl( '_source/' + // @Packager.RemoveLine 'skins/' + skinName + '/' ) ); }, /** * Loads a skin part. Skins are defined in parts, which are basically * separated CSS files. This function is mainly used by the core code and * should not have much use out of it. * @param {String} skinName The name of the skin to be loaded. * @param {String} skinPart The skin part to be loaded. Common skin parts * are "editor" and "dialog". * @param {Function} [callback] A function to be called once the skin * part files are loaded. * @example */ load : function( editor, skinPart, callback ) { var skinName = editor.skinName, skinPath = editor.skinPath; if ( loaded[ skinName ] ) loadPart( editor, skinName, skinPart, callback ); else { paths[ skinName ] = skinPath; CKEDITOR.scriptLoader.load( CKEDITOR.getUrl( skinPath + 'skin.js' ), function() { loadPart( editor, skinName, skinPart, callback ); }); } } }; })();