UNPKG

5.76 kBJavaScriptView Raw
1/**
2 * @author mrdoob / http://mrdoob.com/
3 */
4
5import { Cache } from './Cache.js';
6import { DefaultLoadingManager } from './LoadingManager.js';
7
8var loading = {};
9
10function FileLoader( manager ) {
11
12 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
13
14}
15
16Object.assign( FileLoader.prototype, {
17
18 load: function ( url, onLoad, onProgress, onError ) {
19
20 if ( url === undefined ) url = '';
21
22 if ( this.path !== undefined ) url = this.path + url;
23
24 url = this.manager.resolveURL( url );
25
26 var scope = this;
27
28 var cached = Cache.get( url );
29
30 if ( cached !== undefined ) {
31
32 scope.manager.itemStart( url );
33
34 setTimeout( function () {
35
36 if ( onLoad ) onLoad( cached );
37
38 scope.manager.itemEnd( url );
39
40 }, 0 );
41
42 return cached;
43
44 }
45
46 // Check if request is duplicate
47
48 if ( loading[ url ] !== undefined ) {
49
50 loading[ url ].push( {
51
52 onLoad: onLoad,
53 onProgress: onProgress,
54 onError: onError
55
56 } );
57
58 return;
59
60 }
61
62 // Check for data: URI
63 var dataUriRegex = /^data:(.*?)(;base64)?,(.*)$/;
64 var dataUriRegexResult = url.match( dataUriRegex );
65
66 // Safari can not handle Data URIs through XMLHttpRequest so process manually
67 if ( dataUriRegexResult ) {
68
69 var mimeType = dataUriRegexResult[ 1 ];
70 var isBase64 = !! dataUriRegexResult[ 2 ];
71 var data = dataUriRegexResult[ 3 ];
72
73 data = window.decodeURIComponent( data );
74
75 if ( isBase64 ) data = window.atob( data );
76
77 try {
78
79 var response;
80 var responseType = ( this.responseType || '' ).toLowerCase();
81
82 switch ( responseType ) {
83
84 case 'arraybuffer':
85 case 'blob':
86
87 var view = new Uint8Array( data.length );
88
89 for ( var i = 0; i < data.length; i ++ ) {
90
91 view[ i ] = data.charCodeAt( i );
92
93 }
94
95 if ( responseType === 'blob' ) {
96
97 response = new Blob( [ view.buffer ], { type: mimeType } );
98
99 } else {
100
101 response = view.buffer;
102
103 }
104
105 break;
106
107 case 'document':
108
109 var parser = new DOMParser();
110 response = parser.parseFromString( data, mimeType );
111
112 break;
113
114 case 'json':
115
116 response = JSON.parse( data );
117
118 break;
119
120 default: // 'text' or other
121
122 response = data;
123
124 break;
125
126 }
127
128 // Wait for next browser tick like standard XMLHttpRequest event dispatching does
129 window.setTimeout( function () {
130
131 if ( onLoad ) onLoad( response );
132
133 scope.manager.itemEnd( url );
134
135 }, 0 );
136
137 } catch ( error ) {
138
139 // Wait for next browser tick like standard XMLHttpRequest event dispatching does
140 window.setTimeout( function () {
141
142 if ( onError ) onError( error );
143
144 scope.manager.itemEnd( url );
145 scope.manager.itemError( url );
146
147 }, 0 );
148
149 }
150
151 } else {
152
153 // Initialise array for duplicate requests
154
155 loading[ url ] = [];
156
157 loading[ url ].push( {
158
159 onLoad: onLoad,
160 onProgress: onProgress,
161 onError: onError
162
163 } );
164
165 var request = new XMLHttpRequest();
166
167 request.open( 'GET', url, true );
168
169 request.addEventListener( 'load', function ( event ) {
170
171 var response = this.response;
172
173 Cache.add( url, response );
174
175 var callbacks = loading[ url ];
176
177 delete loading[ url ];
178
179 if ( this.status === 200 ) {
180
181 for ( var i = 0, il = callbacks.length; i < il; i ++ ) {
182
183 var callback = callbacks[ i ];
184 if ( callback.onLoad ) callback.onLoad( response );
185
186 }
187
188 scope.manager.itemEnd( url );
189
190 } else if ( this.status === 0 ) {
191
192 // Some browsers return HTTP Status 0 when using non-http protocol
193 // e.g. 'file://' or 'data://'. Handle as success.
194
195 console.warn( 'THREE.FileLoader: HTTP Status 0 received.' );
196
197 for ( var i = 0, il = callbacks.length; i < il; i ++ ) {
198
199 var callback = callbacks[ i ];
200 if ( callback.onLoad ) callback.onLoad( response );
201
202 }
203
204 scope.manager.itemEnd( url );
205
206 } else {
207
208 for ( var i = 0, il = callbacks.length; i < il; i ++ ) {
209
210 var callback = callbacks[ i ];
211 if ( callback.onError ) callback.onError( event );
212
213 }
214
215 scope.manager.itemEnd( url );
216 scope.manager.itemError( url );
217
218 }
219
220 }, false );
221
222 request.addEventListener( 'progress', function ( event ) {
223
224 var callbacks = loading[ url ];
225
226 for ( var i = 0, il = callbacks.length; i < il; i ++ ) {
227
228 var callback = callbacks[ i ];
229 if ( callback.onProgress ) callback.onProgress( event );
230
231 }
232
233 }, false );
234
235 request.addEventListener( 'error', function ( event ) {
236
237 var callbacks = loading[ url ];
238
239 delete loading[ url ];
240
241 for ( var i = 0, il = callbacks.length; i < il; i ++ ) {
242
243 var callback = callbacks[ i ];
244 if ( callback.onError ) callback.onError( event );
245
246 }
247
248 scope.manager.itemEnd( url );
249 scope.manager.itemError( url );
250
251 }, false );
252
253 if ( this.responseType !== undefined ) request.responseType = this.responseType;
254 if ( this.withCredentials !== undefined ) request.withCredentials = this.withCredentials;
255
256 if ( request.overrideMimeType ) request.overrideMimeType( this.mimeType !== undefined ? this.mimeType : 'text/plain' );
257
258 for ( var header in this.requestHeader ) {
259
260 request.setRequestHeader( header, this.requestHeader[ header ] );
261
262 }
263
264 request.send( null );
265
266 }
267
268 scope.manager.itemStart( url );
269
270 return request;
271
272 },
273
274 setPath: function ( value ) {
275
276 this.path = value;
277 return this;
278
279 },
280
281 setResponseType: function ( value ) {
282
283 this.responseType = value;
284 return this;
285
286 },
287
288 setWithCredentials: function ( value ) {
289
290 this.withCredentials = value;
291 return this;
292
293 },
294
295 setMimeType: function ( value ) {
296
297 this.mimeType = value;
298 return this;
299
300 },
301
302 setRequestHeader: function ( value ) {
303
304 this.requestHeader = value;
305 return this;
306
307 }
308
309} );
310
311
312export { FileLoader };