[2000] | 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.scriptLoader} object, used to load scripts
|
---|
| 8 | * asynchronously.
|
---|
| 9 | */
|
---|
| 10 |
|
---|
| 11 | /**
|
---|
| 12 | * Load scripts asynchronously.
|
---|
| 13 | * @namespace
|
---|
| 14 | * @example
|
---|
| 15 | */
|
---|
| 16 | CKEDITOR.scriptLoader = (function()
|
---|
| 17 | {
|
---|
| 18 | var uniqueScripts = {};
|
---|
| 19 | var waitingList = {};
|
---|
| 20 |
|
---|
| 21 | return /** @lends CKEDITOR.scriptLoader */ {
|
---|
| 22 | /**
|
---|
| 23 | * Loads one or more external script checking if not already loaded
|
---|
| 24 | * previously by this function.
|
---|
| 25 | * @param {String|Array} scriptUrl One or more URLs pointing to the
|
---|
| 26 | * scripts to be loaded.
|
---|
| 27 | * @param {Function} [callback] A function to be called when the script
|
---|
| 28 | * is loaded and executed. If a string is passed to "scriptUrl", a
|
---|
| 29 | * boolean parameter is passed to the callback, indicating the
|
---|
| 30 | * success of the load. If an array is passed instead, two array
|
---|
| 31 | * parameters are passed to the callback; the first contains the
|
---|
| 32 | * URLs that have been properly loaded, and the second the failed
|
---|
| 33 | * ones.
|
---|
| 34 | * @param {Object} [scope] The scope ("this" reference) to be used for
|
---|
| 35 | * the callback call. Default to {@link CKEDITOR}.
|
---|
| 36 | * @param {Boolean} [noCheck] Indicates that the script must be loaded
|
---|
| 37 | * anyway, not checking if it has already loaded.
|
---|
| 38 | * @example
|
---|
| 39 | * CKEDITOR.scriptLoader.load( '/myscript.js' );
|
---|
| 40 | * @example
|
---|
| 41 | * CKEDITOR.scriptLoader.load( '/myscript.js', function( success )
|
---|
| 42 | * {
|
---|
| 43 | * // Alerts "true" if the script has been properly loaded.
|
---|
| 44 | * // HTTP error 404 should return "false".
|
---|
| 45 | * alert( success );
|
---|
| 46 | * });
|
---|
| 47 | * @example
|
---|
| 48 | * CKEDITOR.scriptLoader.load( [ '/myscript1.js', '/myscript2.js' ], function( completed, failed )
|
---|
| 49 | * {
|
---|
| 50 | * alert( 'Number of scripts loaded: ' + completed.length );
|
---|
| 51 | * alert( 'Number of failures: ' + failed.length );
|
---|
| 52 | * });
|
---|
| 53 | */
|
---|
| 54 | load : function( scriptUrl, callback, scope, noCheck )
|
---|
| 55 | {
|
---|
| 56 | var isString = ( typeof scriptUrl == 'string' );
|
---|
| 57 |
|
---|
| 58 | if ( isString )
|
---|
| 59 | scriptUrl = [ scriptUrl ];
|
---|
| 60 |
|
---|
| 61 | if ( !scope )
|
---|
| 62 | scope = CKEDITOR;
|
---|
| 63 |
|
---|
| 64 | var scriptCount = scriptUrl.length,
|
---|
| 65 | completed = [],
|
---|
| 66 | failed = [];
|
---|
| 67 |
|
---|
| 68 | var doCallback = function( success )
|
---|
| 69 | {
|
---|
| 70 | if ( callback )
|
---|
| 71 | {
|
---|
| 72 | if ( isString )
|
---|
| 73 | callback.call( scope, success );
|
---|
| 74 | else
|
---|
| 75 | callback.call( scope, completed, failed );
|
---|
| 76 | }
|
---|
| 77 | };
|
---|
| 78 |
|
---|
| 79 | if ( scriptCount === 0 )
|
---|
| 80 | {
|
---|
| 81 | doCallback( true );
|
---|
| 82 | return;
|
---|
| 83 | }
|
---|
| 84 |
|
---|
| 85 | var checkLoaded = function( url, success )
|
---|
| 86 | {
|
---|
| 87 | ( success ? completed : failed ).push( url );
|
---|
| 88 |
|
---|
| 89 | if ( --scriptCount <= 0 )
|
---|
| 90 | doCallback( success );
|
---|
| 91 | };
|
---|
| 92 |
|
---|
| 93 | var onLoad = function( url, success )
|
---|
| 94 | {
|
---|
| 95 | // Mark this script as loaded.
|
---|
| 96 | uniqueScripts[ url ] = 1;
|
---|
| 97 |
|
---|
| 98 | // Get the list of callback checks waiting for this file.
|
---|
| 99 | var waitingInfo = waitingList[ url ];
|
---|
| 100 | delete waitingList[ url ];
|
---|
| 101 |
|
---|
| 102 | // Check all callbacks waiting for this file.
|
---|
| 103 | for ( var i = 0 ; i < waitingInfo.length ; i++ )
|
---|
| 104 | waitingInfo[ i ]( url, success );
|
---|
| 105 | };
|
---|
| 106 |
|
---|
| 107 | var loadScript = function( url )
|
---|
| 108 | {
|
---|
| 109 | if ( noCheck !== true && uniqueScripts[ url ] )
|
---|
| 110 | {
|
---|
| 111 | checkLoaded( url, true );
|
---|
| 112 | return;
|
---|
| 113 | }
|
---|
| 114 |
|
---|
| 115 | var waitingInfo = waitingList[ url ] || ( waitingList[ url ] = [] );
|
---|
| 116 | waitingInfo.push( checkLoaded );
|
---|
| 117 |
|
---|
| 118 | // Load it only for the first request.
|
---|
| 119 | if ( waitingInfo.length > 1 )
|
---|
| 120 | return;
|
---|
| 121 |
|
---|
| 122 | // Create the <script> element.
|
---|
| 123 | var script = new CKEDITOR.dom.element( 'script' );
|
---|
| 124 | script.setAttributes( {
|
---|
| 125 | type : 'text/javascript',
|
---|
| 126 | src : url } );
|
---|
| 127 |
|
---|
| 128 | if ( callback )
|
---|
| 129 | {
|
---|
| 130 | if ( CKEDITOR.env.ie )
|
---|
| 131 | {
|
---|
| 132 | // FIXME: For IE, we are not able to return false on error (like 404).
|
---|
| 133 |
|
---|
| 134 | /** @ignore */
|
---|
| 135 | script.$.onreadystatechange = function ()
|
---|
| 136 | {
|
---|
| 137 | if ( script.$.readyState == 'loaded' || script.$.readyState == 'complete' )
|
---|
| 138 | {
|
---|
| 139 | script.$.onreadystatechange = null;
|
---|
| 140 | onLoad( url, true );
|
---|
| 141 | }
|
---|
| 142 | };
|
---|
| 143 | }
|
---|
| 144 | else
|
---|
| 145 | {
|
---|
| 146 | /** @ignore */
|
---|
| 147 | script.$.onload = function()
|
---|
| 148 | {
|
---|
| 149 | // Some browsers, such as Safari, may call the onLoad function
|
---|
| 150 | // immediately. Which will break the loading sequence. (#3661)
|
---|
| 151 | setTimeout( function() { onLoad( url, true ); }, 0 );
|
---|
| 152 | };
|
---|
| 153 |
|
---|
| 154 | // FIXME: Opera and Safari will not fire onerror.
|
---|
| 155 |
|
---|
| 156 | /** @ignore */
|
---|
| 157 | script.$.onerror = function()
|
---|
| 158 | {
|
---|
| 159 | onLoad( url, false );
|
---|
| 160 | };
|
---|
| 161 | }
|
---|
| 162 | }
|
---|
| 163 |
|
---|
| 164 | // Append it to <head>.
|
---|
| 165 | script.appendTo( CKEDITOR.document.getHead() );
|
---|
| 166 |
|
---|
| 167 | CKEDITOR.fire( 'download', url ); // @Packager.RemoveLine
|
---|
| 168 | };
|
---|
| 169 |
|
---|
| 170 | for ( var i = 0 ; i < scriptCount ; i++ )
|
---|
| 171 | {
|
---|
| 172 | loadScript( scriptUrl[ i ] );
|
---|
| 173 | }
|
---|
| 174 | },
|
---|
| 175 |
|
---|
| 176 | /**
|
---|
| 177 | * Executes a JavaScript code into the current document.
|
---|
| 178 | * @param {String} code The code to be executed.
|
---|
| 179 | * @example
|
---|
| 180 | * CKEDITOR.scriptLoader.loadCode( 'var x = 10;' );
|
---|
| 181 | * alert( x ); // "10"
|
---|
| 182 | */
|
---|
| 183 | loadCode : function( code )
|
---|
| 184 | {
|
---|
| 185 | // Create the <script> element.
|
---|
| 186 | var script = new CKEDITOR.dom.element( 'script' );
|
---|
| 187 | script.setAttribute( 'type', 'text/javascript' );
|
---|
| 188 | script.appendText( code );
|
---|
| 189 |
|
---|
| 190 | // Append it to <head>.
|
---|
| 191 | script.appendTo( CKEDITOR.document.getHead() );
|
---|
| 192 | }
|
---|
| 193 | };
|
---|
| 194 | })();
|
---|