NOBUG: Fixed file access permissions
[moodle.git] / lib / yuilib / 3.13.0 / file-html5 / file-html5-debug.js
blob9e06199f6cf1bf83fd072d595010721af8e922bc
1 /*
2 YUI 3.13.0 (build 508226d)
3 Copyright 2013 Yahoo! Inc. All rights reserved.
4 Licensed under the BSD License.
5 http://yuilibrary.com/license/
6 */
8 YUI.add('file-html5', function (Y, NAME) {
10     /**
11      * The FileHTML5 class provides a wrapper for a file pointer in an HTML5 The File wrapper
12      * also implements the mechanics for uploading a file and tracking its progress.
13      * @module file-html5
14      */
16     /**
17      * The class provides a wrapper for a file pointer.
18      * @class FileHTML5
19      * @extends Base
20      * @constructor
21      * @param {Object} config Configuration object.
22      */
23     var Lang = Y.Lang,
24         Bind = Y.bind,
25         Win = Y.config.win;
27     var FileHTML5 = function(o) {
29         var file = null;
31         if (FileHTML5.isValidFile(o)) {
32             file = o;
33         }
34         else if (FileHTML5.isValidFile(o.file)) {
35             file = o.file;
36         }
37         else {
38             file = false;
39         }
41         FileHTML5.superclass.constructor.apply(this, arguments);
43         if (file && FileHTML5.canUpload()) {
44            if (!this.get("file")) {
45                this._set("file", file);
46            }
48            if (!this.get("name")) {
49            this._set("name", file.name || file.fileName);
50            }
52            if (this.get("size") != (file.size || file.fileSize)) {
53            this._set("size", file.size || file.fileSize);
54            }
56            if (!this.get("type")) {
57            this._set("type", file.type);
58            }
60            if (file.hasOwnProperty("lastModifiedDate") && !this.get("dateModified")) {
61                this._set("dateModified", file.lastModifiedDate);
62            }
63         }
64     };
67     Y.extend(FileHTML5, Y.Base, {
69        /**
70         * Construction logic executed during FileHTML5 instantiation.
71         *
72         * @method initializer
73         * @protected
74         */
75         initializer : function (cfg) {
76             if (!this.get("id")) {
77                 this._set("id", Y.guid("file"));
78             }
79         },
81        /**
82         * Handler of events dispatched by the XMLHTTPRequest.
83         *
84         * @method _uploadEventHandler
85         * @param {Event} event The event object received from the XMLHTTPRequest.
86         * @protected
87         */
88         _uploadEventHandler: function (event) {
89             var xhr = this.get("xhr");
91             switch (event.type) {
92                 case "progress":
93                   /**
94                    * Signals that progress has been made on the upload of this file.
95                    *
96                    * @event uploadprogress
97                    * @param event {Event} The event object for the `uploadprogress` with the
98                    *                      following payload:
99                    *  <dl>
100                    *      <dt>originEvent</dt>
101                    *          <dd>The original event fired by the XMLHttpRequest instance.</dd>
102                    *      <dt>bytesLoaded</dt>
103                    *          <dd>The number of bytes of the file that has been uploaded.</dd>
104                    *      <dt>bytesTotal</dt>
105                    *          <dd>The total number of bytes in the file (the file size)</dd>
106                    *      <dt>percentLoaded</dt>
107                    *          <dd>The fraction of the file that has been uploaded, out of 100.</dd>
108                    *  </dl>
109                    */
110                    this.fire("uploadprogress", {originEvent: event,
111                                                bytesLoaded: event.loaded,
112                                                bytesTotal: this.get("size"),
113                                                percentLoaded: Math.min(100, Math.round(10000*event.loaded/this.get("size"))/100)
114                                                });
115                    this._set("bytesUploaded", event.loaded);
116                    break;
118                 case "load":
119                   /**
120                    * Signals that this file's upload has completed and data has been received from the server.
121                    *
122                    * @event uploadcomplete
123                    * @param event {Event} The event object for the `uploadcomplete` with the
124                    *                      following payload:
125                    *  <dl>
126                    *      <dt>originEvent</dt>
127                    *          <dd>The original event fired by the XMLHttpRequest instance.</dd>
128                    *      <dt>data</dt>
129                    *          <dd>The data returned by the server.</dd>
130                    *  </dl>
131                    */
133                    if (xhr.status >= 200 && xhr.status <= 299) {
134                         this.fire("uploadcomplete", {originEvent: event,
135                                                      data: event.target.responseText});
136                         var xhrupload = xhr.upload,
137                             boundEventHandler = this.get("boundEventHandler");
139                         xhrupload.removeEventListener ("progress", boundEventHandler);
140                         xhrupload.removeEventListener ("error", boundEventHandler);
141                         xhrupload.removeEventListener ("abort", boundEventHandler);
142                         xhr.removeEventListener ("load", boundEventHandler);
143                         xhr.removeEventListener ("error", boundEventHandler);
144                         xhr.removeEventListener ("readystatechange", boundEventHandler);
146                         this._set("xhr", null);
147                    }
148                    else {
149                         this.fire("uploaderror", {originEvent: event,
150                                                   status: xhr.status,
151                                                   statusText: xhr.statusText,
152                                                   source: "http"});
153                    }
154                    break;
156                 case "error":
157                   /**
158                    * Signals that this file's upload has encountered an error.
159                    *
160                    * @event uploaderror
161                    * @param event {Event} The event object for the `uploaderror` with the
162                    *                      following payload:
163                    *  <dl>
164                    *      <dt>originEvent</dt>
165                    *          <dd>The original event fired by the XMLHttpRequest instance.</dd>
166                    *      <dt>status</dt>
167                    *          <dd>The status code reported by the XMLHttpRequest. If it's an HTTP error,
168                                   then this corresponds to the HTTP status code received by the uploader.</dd>
169                    *      <dt>statusText</dt>
170                    *          <dd>The text of the error event reported by the XMLHttpRequest instance</dd>
171                    *      <dt>source</dt>
172                    *          <dd>Either "http" (if it's an HTTP error), or "io" (if it's a network transmission
173                    *              error.)</dd>
174                    *
175                    *  </dl>
176                    */
177                    this.fire("uploaderror", {originEvent: event,
178                                                   status: xhr.status,
179                                                   statusText: xhr.statusText,
180                                                   source: "io"});
181                    break;
183                 case "abort":
185                   /**
186                    * Signals that this file's upload has been cancelled.
187                    *
188                    * @event uploadcancel
189                    * @param event {Event} The event object for the `uploadcancel` with the
190                    *                      following payload:
191                    *  <dl>
192                    *      <dt>originEvent</dt>
193                    *          <dd>The original event fired by the XMLHttpRequest instance.</dd>
194                    *  </dl>
195                    */
196                    this.fire("uploadcancel", {originEvent: event});
197                    break;
199                 case "readystatechange":
201                   /**
202                    * Signals that XMLHttpRequest has fired a readystatechange event.
203                    *
204                    * @event readystatechange
205                    * @param event {Event} The event object for the `readystatechange` with the
206                    *                      following payload:
207                    *  <dl>
208                    *      <dt>readyState</dt>
209                    *          <dd>The readyState code reported by the XMLHttpRequest instance.</dd>
210                    *      <dt>originEvent</dt>
211                    *          <dd>The original event fired by the XMLHttpRequest instance.</dd>
212                    *  </dl>
213                    */
214                    this.fire("readystatechange", {readyState: event.target.readyState,
215                                                   originEvent: event});
216                    break;
217             }
218         },
220        /**
221         * Starts the upload of a specific file.
222         *
223         * @method startUpload
224         * @param url {String} The URL to upload the file to.
225         * @param parameters {Object} (optional) A set of key-value pairs to send as variables along with the file upload HTTP request.
226         * @param fileFieldName {String} (optional) The name of the POST variable that should contain the uploaded file ('Filedata' by default)
227         */
228         startUpload: function(url, parameters, fileFieldName) {
230             this._set("bytesUploaded", 0);
232             this._set("xhr", new XMLHttpRequest());
233             this._set("boundEventHandler", Bind(this._uploadEventHandler, this));
235             var uploadData = new FormData(),
236                 fileField = fileFieldName || "Filedata",
237                 xhr = this.get("xhr"),
238                 xhrupload = this.get("xhr").upload,
239                 boundEventHandler = this.get("boundEventHandler");
241             Y.each(parameters, function (value, key) {uploadData.append(key, value);});
242             uploadData.append(fileField, this.get("file"));
247             xhr.addEventListener ("loadstart", boundEventHandler, false);
248             xhrupload.addEventListener ("progress", boundEventHandler, false);
249             xhr.addEventListener ("load", boundEventHandler, false);
250             xhr.addEventListener ("error", boundEventHandler, false);
251             xhrupload.addEventListener ("error", boundEventHandler, false);
252             xhrupload.addEventListener ("abort", boundEventHandler, false);
253             xhr.addEventListener ("abort", boundEventHandler, false);
254             xhr.addEventListener ("loadend", boundEventHandler, false);
255             xhr.addEventListener ("readystatechange", boundEventHandler, false);
257             xhr.open("POST", url, true);
259             xhr.withCredentials = this.get("xhrWithCredentials");
261             Y.each(this.get("xhrHeaders"), function (value, key) {
262                  xhr.setRequestHeader(key, value);
263             });
265             xhr.send(uploadData);
267             /**
268              * Signals that this file's upload has started.
269              *
270              * @event uploadstart
271              * @param event {Event} The event object for the `uploadstart` with the
272              *                      following payload:
273              *  <dl>
274              *      <dt>xhr</dt>
275              *          <dd>The XMLHttpRequest instance handling the file upload.</dd>
276              *  </dl>
277              */
278              this.fire("uploadstart", {xhr: xhr});
280         },
282        /**
283         * Cancels the upload of a specific file, if currently in progress.
284         *
285         * @method cancelUpload
286         */
287         cancelUpload: function () {
288             var xhr = this.get('xhr');
289             if (xhr) {
290                 xhr.abort();
291             }
292         }
295     }, {
297        /**
298         * The identity of the class.
299         *
300         * @property NAME
301         * @type String
302         * @default 'file'
303         * @readOnly
304         * @protected
305         * @static
306         */
307         NAME: 'file',
309        /**
310         * The type of transport.
311         *
312         * @property TYPE
313         * @type String
314         * @default 'html5'
315         * @readOnly
316         * @protected
317         * @static
318         */
319         TYPE: 'html5',
321        /**
322         * Static property used to define the default attribute configuration of
323         * the File.
324         *
325         * @property ATTRS
326         * @type {Object}
327         * @protected
328         * @static
329         */
330         ATTRS: {
332        /**
333         * A String containing the unique id of the file wrapped by the FileFlash instance.
334         * The id is supplied by the Flash player uploader.
335         *
336         * @attribute id
337         * @type {String}
338         * @initOnly
339         */
340         id: {
341             writeOnce: "initOnly",
342             value: null
343         },
345        /**
346         * The size of the file wrapped by FileHTML5. This value is supplied by the instance of File().
347         *
348         * @attribute size
349         * @type {Number}
350         * @initOnly
351         */
352         size: {
353             writeOnce: "initOnly",
354             value: 0
355         },
357        /**
358         * The name of the file wrapped by FileHTML5. This value is supplied by the instance of File().
359         *
360         * @attribute name
361         * @type {String}
362         * @initOnly
363         */
364         name: {
365             writeOnce: "initOnly",
366             value: null
367         },
369        /**
370         * The date that the file wrapped by FileHTML5 was created on. This value is supplied by the instance of File().
371         *
372         * @attribute dateCreated
373         * @type {Date}
374         * @initOnly
375         * @default null
376         */
377         dateCreated: {
378             writeOnce: "initOnly",
379             value: null
380         },
382        /**
383         * The date that the file wrapped by FileHTML5 was last modified on. This value is supplied by the instance of File().
384         *
385         * @attribute dateModified
386         * @type {Date}
387         * @initOnly
388         */
389         dateModified: {
390             writeOnce: "initOnly",
391             value: null
392         },
394        /**
395         * The number of bytes of the file that has been uploaded to the server. This value is
396         * non-zero only while a file is being uploaded.
397         *
398         * @attribute bytesUploaded
399         * @type {Date}
400         * @readOnly
401         */
402         bytesUploaded: {
403             readOnly: true,
404             value: 0
405         },
407        /**
408         * The type of the file wrapped by FileHTML. This value is provided by the instance of File()
409         *
410         * @attribute type
411         * @type {String}
412         * @initOnly
413         */
414         type: {
415             writeOnce: "initOnly",
416             value: null
417         },
419        /**
420         * The pointer to the instance of File() wrapped by FileHTML5.
421         *
422         * @attribute file
423         * @type {File}
424         * @initOnly
425         */
426         file: {
427             writeOnce: "initOnly",
428             value: null
429         },
431        /**
432         * The pointer to the instance of XMLHttpRequest used by FileHTML5 to upload the file.
433         *
434         * @attribute xhr
435         * @type {XMLHttpRequest}
436         * @initOnly
437         */
438         xhr: {
439             readOnly: true,
440             value: null
441         },
443        /**
444         * The dictionary of headers that should be set on the XMLHttpRequest object before
445         * sending it.
446         *
447         * @attribute xhrHeaders
448         * @type {Object}
449         * @initOnly
450         */
451         xhrHeaders: {
452             value: {}
453         },
455        /**
456         * A Boolean indicating whether the XMLHttpRequest should be sent with user credentials.
457         * This does not affect same-site requests.
458         *
459         * @attribute xhrWithCredentials
460         * @type {Boolean}
461         * @initOnly
462         */
463         xhrWithCredentials: {
464             value: true
465         },
467        /**
468         * The bound event handler used to handle events from XMLHttpRequest.
469         *
470         * @attribute boundEventHandler
471         * @type {Function}
472         * @initOnly
473         */
474         boundEventHandler: {
475             readOnly: true,
476             value: null
477         }
478         },
480        /**
481         * Checks whether a specific native file instance is valid
482         *
483         * @method isValidFile
484         * @param file {File} A native File() instance.
485         * @static
486         */
487         isValidFile: function (file) {
488             return (Win && Win.File && file instanceof File);
489         },
491        /**
492         * Checks whether the browser has a native upload capability
493         * via XMLHttpRequest Level 2.
494         *
495         * @method canUpload
496         * @static
497         */
498         canUpload: function () {
499             return (Win && Win.FormData && Win.XMLHttpRequest);
500         }
501     });
503     Y.FileHTML5 = FileHTML5;
506 }, '3.13.0', {"requires": ["base"]});