181 lines
4.9 KiB
JavaScript
181 lines
4.9 KiB
JavaScript
/*
|
|
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.scriptLoader} object, used to load scripts
|
|
* asynchronously.
|
|
*/
|
|
|
|
/**
|
|
* Load scripts asynchronously.
|
|
* @namespace
|
|
* @example
|
|
*/
|
|
CKEDITOR.scriptLoader = (function()
|
|
{
|
|
var uniqueScripts = {},
|
|
waitingList = {};
|
|
|
|
return /** @lends CKEDITOR.scriptLoader */ {
|
|
/**
|
|
* Loads one or more external script checking if not already loaded
|
|
* previously by this function.
|
|
* @param {String|Array} scriptUrl One or more URLs pointing to the
|
|
* scripts to be loaded.
|
|
* @param {Function} [callback] A function to be called when the script
|
|
* is loaded and executed. If a string is passed to "scriptUrl", a
|
|
* boolean parameter is passed to the callback, indicating the
|
|
* success of the load. If an array is passed instead, two array
|
|
* parameters are passed to the callback; the first contains the
|
|
* URLs that have been properly loaded, and the second the failed
|
|
* ones.
|
|
* @param {Object} [scope] The scope ("this" reference) to be used for
|
|
* the callback call. Default to {@link CKEDITOR}.
|
|
* @param {Boolean} [showBusy] Changes the cursor of the document while
|
|
+ * the script is loaded.
|
|
* @example
|
|
* CKEDITOR.scriptLoader.load( '/myscript.js' );
|
|
* @example
|
|
* CKEDITOR.scriptLoader.load( '/myscript.js', function( success )
|
|
* {
|
|
* // Alerts "true" if the script has been properly loaded.
|
|
* // HTTP error 404 should return "false".
|
|
* alert( success );
|
|
* });
|
|
* @example
|
|
* CKEDITOR.scriptLoader.load( [ '/myscript1.js', '/myscript2.js' ], function( completed, failed )
|
|
* {
|
|
* alert( 'Number of scripts loaded: ' + completed.length );
|
|
* alert( 'Number of failures: ' + failed.length );
|
|
* });
|
|
*/
|
|
load : function( scriptUrl, callback, scope, showBusy )
|
|
{
|
|
var isString = ( typeof scriptUrl == 'string' );
|
|
|
|
if ( isString )
|
|
scriptUrl = [ scriptUrl ];
|
|
|
|
if ( !scope )
|
|
scope = CKEDITOR;
|
|
|
|
var scriptCount = scriptUrl.length,
|
|
completed = [],
|
|
failed = [];
|
|
|
|
var doCallback = function( success )
|
|
{
|
|
if ( callback )
|
|
{
|
|
if ( isString )
|
|
callback.call( scope, success );
|
|
else
|
|
callback.call( scope, completed, failed );
|
|
}
|
|
};
|
|
|
|
if ( scriptCount === 0 )
|
|
{
|
|
doCallback( true );
|
|
return;
|
|
}
|
|
|
|
var checkLoaded = function( url, success )
|
|
{
|
|
( success ? completed : failed ).push( url );
|
|
|
|
if ( --scriptCount <= 0 )
|
|
{
|
|
showBusy && CKEDITOR.document.getDocumentElement().removeStyle( 'cursor' );
|
|
doCallback( success );
|
|
}
|
|
};
|
|
|
|
var onLoad = function( url, success )
|
|
{
|
|
// Mark this script as loaded.
|
|
uniqueScripts[ url ] = 1;
|
|
|
|
// Get the list of callback checks waiting for this file.
|
|
var waitingInfo = waitingList[ url ];
|
|
delete waitingList[ url ];
|
|
|
|
// Check all callbacks waiting for this file.
|
|
for ( var i = 0 ; i < waitingInfo.length ; i++ )
|
|
waitingInfo[ i ]( url, success );
|
|
};
|
|
|
|
var loadScript = function( url )
|
|
{
|
|
if ( uniqueScripts[ url ] )
|
|
{
|
|
checkLoaded( url, true );
|
|
return;
|
|
}
|
|
|
|
var waitingInfo = waitingList[ url ] || ( waitingList[ url ] = [] );
|
|
waitingInfo.push( checkLoaded );
|
|
|
|
// Load it only for the first request.
|
|
if ( waitingInfo.length > 1 )
|
|
return;
|
|
|
|
// Create the <script> element.
|
|
var script = new CKEDITOR.dom.element( 'script' );
|
|
script.setAttributes( {
|
|
type : 'text/javascript',
|
|
src : url } );
|
|
|
|
if ( callback )
|
|
{
|
|
if ( CKEDITOR.env.ie )
|
|
{
|
|
// FIXME: For IE, we are not able to return false on error (like 404).
|
|
|
|
/** @ignore */
|
|
script.$.onreadystatechange = function ()
|
|
{
|
|
if ( script.$.readyState == 'loaded' || script.$.readyState == 'complete' )
|
|
{
|
|
script.$.onreadystatechange = null;
|
|
onLoad( url, true );
|
|
}
|
|
};
|
|
}
|
|
else
|
|
{
|
|
/** @ignore */
|
|
script.$.onload = function()
|
|
{
|
|
// Some browsers, such as Safari, may call the onLoad function
|
|
// immediately. Which will break the loading sequence. (#3661)
|
|
setTimeout( function() { onLoad( url, true ); }, 0 );
|
|
};
|
|
|
|
// FIXME: Opera and Safari will not fire onerror.
|
|
|
|
/** @ignore */
|
|
script.$.onerror = function()
|
|
{
|
|
onLoad( url, false );
|
|
};
|
|
}
|
|
}
|
|
|
|
// Append it to <head>.
|
|
script.appendTo( CKEDITOR.document.getHead() );
|
|
|
|
CKEDITOR.fire( 'download', url ); // @Packager.RemoveLine
|
|
};
|
|
|
|
showBusy && CKEDITOR.document.getDocumentElement().setStyle( 'cursor', 'wait' );
|
|
for ( var i = 0 ; i < scriptCount ; i++ )
|
|
{
|
|
loadScript( scriptUrl[ i ] );
|
|
}
|
|
}
|
|
};
|
|
})();
|