initial commit
[namibia] / public / scripts / ckeditor / _source / core / scriptloader.js
1 /*
2 Copyright (c) 2003-2011, 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                 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} [showBusy] Changes the cursor of the document while
37 +                *              the script is 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, showBusy )
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                                 {
91                                         showBusy && CKEDITOR.document.getDocumentElement().removeStyle( 'cursor' );
92                                         doCallback( success );
93                                 }
94                         };
95
96                         var onLoad = function( url, success )
97                         {
98                                 // Mark this script as loaded.
99                                 uniqueScripts[ url ] = 1;
100
101                                 // Get the list of callback checks waiting for this file.
102                                 var waitingInfo = waitingList[ url ];
103                                 delete waitingList[ url ];
104
105                                 // Check all callbacks waiting for this file.
106                                 for ( var i = 0 ; i < waitingInfo.length ; i++ )
107                                         waitingInfo[ i ]( url, success );
108                         };
109
110                         var loadScript = function( url )
111                         {
112                                 if ( uniqueScripts[ url ] )
113                                 {
114                                         checkLoaded( url, true );
115                                         return;
116                                 }
117
118                                 var waitingInfo = waitingList[ url ] || ( waitingList[ url ] = [] );
119                                 waitingInfo.push( checkLoaded );
120
121                                 // Load it only for the first request.
122                                 if ( waitingInfo.length > 1 )
123                                         return;
124
125                                 // Create the <script> element.
126                                 var script = new CKEDITOR.dom.element( 'script' );
127                                 script.setAttributes( {
128                                         type : 'text/javascript',
129                                         src : url } );
130
131                                 if ( callback )
132                                 {
133                                         if ( CKEDITOR.env.ie )
134                                         {
135                                                 // FIXME: For IE, we are not able to return false on error (like 404).
136
137                                                 /** @ignore */
138                                                 script.$.onreadystatechange = function ()
139                                                 {
140                                                         if ( script.$.readyState == 'loaded' || script.$.readyState == 'complete' )
141                                                         {
142                                                                 script.$.onreadystatechange = null;
143                                                                 onLoad( url, true );
144                                                         }
145                                                 };
146                                         }
147                                         else
148                                         {
149                                                 /** @ignore */
150                                                 script.$.onload = function()
151                                                 {
152                                                         // Some browsers, such as Safari, may call the onLoad function
153                                                         // immediately. Which will break the loading sequence. (#3661)
154                                                         setTimeout( function() { onLoad( url, true ); }, 0 );
155                                                 };
156
157                                                 // FIXME: Opera and Safari will not fire onerror.
158
159                                                 /** @ignore */
160                                                 script.$.onerror = function()
161                                                 {
162                                                         onLoad( url, false );
163                                                 };
164                                         }
165                                 }
166
167                                 // Append it to <head>.
168                                 script.appendTo( CKEDITOR.document.getHead() );
169
170                                 CKEDITOR.fire( 'download', url );               // @Packager.RemoveLine
171                         };
172
173                         showBusy && CKEDITOR.document.getDocumentElement().setStyle( 'cursor', 'wait' );
174                         for ( var i = 0 ; i < scriptCount ; i++ )
175                         {
176                                 loadScript( scriptUrl[ i ] );
177                         }
178                 }
179         };
180 })();