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