- /**
- * The FileHTML5 class provides a wrapper for a file pointer in an HTML5 The File wrapper
- * also implements the mechanics for uploading a file and tracking its progress.
- * @module file-html5
- */
-
- /**
- * The class provides a wrapper for a file pointer.
- * @class FileHTML5
- * @extends Base
- * @constructor
- * @param {Object} config Configuration object.
- */
- var Lang = Y.Lang,
- Bind = Y.bind,
- Win = Y.config.win;
- var FileHTML5 = function(o) {
-
- var file = null;
- if (FileHTML5.isValidFile(o)) {
- file = o;
- }
- else if (FileHTML5.isValidFile(o.file)) {
- file = o.file;
- }
- else {
- file = false;
- }
- FileHTML5.superclass.constructor.apply(this, arguments);
-
- if (file && FileHTML5.canUpload()) {
- if (!this.get("file")) {
- this._set("file", file);
- }
- if (!this.get("name")) {
- this._set("name", file.name || file.fileName);
- }
- if (this.get("size") != (file.size || file.fileSize)) {
- this._set("size", file.size || file.fileSize);
- }
- if (!this.get("type")) {
- this._set("type", file.type);
- }
- if (file.hasOwnProperty("lastModifiedDate") && !this.get("dateModified")) {
- this._set("dateModified", file.lastModifiedDate);
- }
- }
- };
- Y.extend(FileHTML5, Y.Base, {
- /**
- * Construction logic executed during FileHTML5 instantiation.
- *
- * @method initializer
- * @protected
- */
- initializer : function (cfg) {
- if (!this.get("id")) {
- this._set("id", Y.guid("file"));
- }
- },
- /**
- * Handler of events dispatched by the XMLHTTPRequest.
- *
- * @method _uploadEventHandler
- * @param {Event} event The event object received from the XMLHTTPRequest.
- * @protected
- */
- _uploadEventHandler: function (event) {
- var xhr = this.get("xhr");
- switch (event.type) {
- case "progress":
- /**
- * Signals that progress has been made on the upload of this file.
- *
- * @event uploadprogress
- * @param event {Event} The event object for the `uploadprogress` with the
- * following payload:
- * <dl>
- * <dt>originEvent</dt>
- * <dd>The original event fired by the XMLHttpRequest instance.</dd>
- * <dt>bytesLoaded</dt>
- * <dd>The number of bytes of the file that has been uploaded.</dd>
- * <dt>bytesTotal</dt>
- * <dd>The total number of bytes in the file (the file size)</dd>
- * <dt>percentLoaded</dt>
- * <dd>The fraction of the file that has been uploaded, out of 100.</dd>
- * </dl>
- */
- this.fire("uploadprogress", {originEvent: event,
- bytesLoaded: event.loaded,
- bytesTotal: this.get("size"),
- percentLoaded: Math.min(100, Math.round(10000*event.loaded/this.get("size"))/100)
- });
- this._set("bytesUploaded", event.loaded);
- break;
- case "load":
- /**
- * Signals that this file's upload has completed and data has been received from the server.
- *
- * @event uploadcomplete
- * @param event {Event} The event object for the `uploadcomplete` with the
- * following payload:
- * <dl>
- * <dt>originEvent</dt>
- * <dd>The original event fired by the XMLHttpRequest instance.</dd>
- * <dt>data</dt>
- * <dd>The data returned by the server.</dd>
- * </dl>
- */
- if (xhr.status >= 200 && xhr.status <= 299) {
- this.fire("uploadcomplete", {originEvent: event,
- data: event.target.responseText});
- var xhrupload = xhr.upload,
- boundEventHandler = this.get("boundEventHandler");
-
- xhrupload.removeEventListener ("progress", boundEventHandler);
- xhrupload.removeEventListener ("error", boundEventHandler);
- xhrupload.removeEventListener ("abort", boundEventHandler);
- xhr.removeEventListener ("load", boundEventHandler);
- xhr.removeEventListener ("error", boundEventHandler);
- xhr.removeEventListener ("readystatechange", boundEventHandler);
-
- this._set("xhr", null);
- }
- else {
- this.fire("uploaderror", {originEvent: event,
- status: xhr.status,
- statusText: xhr.statusText,
- source: "http"});
- }
- break;
- case "error":
- /**
- * Signals that this file's upload has encountered an error.
- *
- * @event uploaderror
- * @param event {Event} The event object for the `uploaderror` with the
- * following payload:
- * <dl>
- * <dt>originEvent</dt>
- * <dd>The original event fired by the XMLHttpRequest instance.</dd>
- * <dt>status</dt>
- * <dd>The status code reported by the XMLHttpRequest. If it's an HTTP error,
- then this corresponds to the HTTP status code received by the uploader.</dd>
- * <dt>statusText</dt>
- * <dd>The text of the error event reported by the XMLHttpRequest instance</dd>
- * <dt>source</dt>
- * <dd>Either "http" (if it's an HTTP error), or "io" (if it's a network transmission
- * error.)</dd>
- *
- * </dl>
- */
- this.fire("uploaderror", {originEvent: event,
- status: xhr.status,
- statusText: xhr.statusText,
- source: "io"});
- break;
- case "abort":
- /**
- * Signals that this file's upload has been cancelled.
- *
- * @event uploadcancel
- * @param event {Event} The event object for the `uploadcancel` with the
- * following payload:
- * <dl>
- * <dt>originEvent</dt>
- * <dd>The original event fired by the XMLHttpRequest instance.</dd>
- * </dl>
- */
- this.fire("uploadcancel", {originEvent: event});
- break;
- case "readystatechange":
- /**
- * Signals that XMLHttpRequest has fired a readystatechange event.
- *
- * @event readystatechange
- * @param event {Event} The event object for the `readystatechange` with the
- * following payload:
- * <dl>
- * <dt>readyState</dt>
- * <dd>The readyState code reported by the XMLHttpRequest instance.</dd>
- * <dt>originEvent</dt>
- * <dd>The original event fired by the XMLHttpRequest instance.</dd>
- * </dl>
- */
- this.fire("readystatechange", {readyState: event.target.readyState,
- originEvent: event});
- break;
- }
- },
- /**
- * Starts the upload of a specific file.
- *
- * @method startUpload
- * @param url {String} The URL to upload the file to.
- * @param parameters {Object} (optional) A set of key-value pairs to send as variables along with the file upload HTTP request.
- * @param fileFieldName {String} (optional) The name of the POST variable that should contain the uploaded file ('Filedata' by default)
- */
- startUpload: function(url, parameters, fileFieldName) {
-
- this._set("bytesUploaded", 0);
-
- this._set("xhr", new XMLHttpRequest());
- this._set("boundEventHandler", Bind(this._uploadEventHandler, this));
-
- var uploadData = new FormData(),
- fileField = fileFieldName || "Filedata",
- xhr = this.get("xhr"),
- xhrupload = this.get("xhr").upload,
- boundEventHandler = this.get("boundEventHandler");
- Y.each(parameters, function (value, key) {uploadData.append(key, value);});
- uploadData.append(fileField, this.get("file"));
- xhr.addEventListener ("loadstart", boundEventHandler, false);
- xhrupload.addEventListener ("progress", boundEventHandler, false);
- xhr.addEventListener ("load", boundEventHandler, false);
- xhr.addEventListener ("error", boundEventHandler, false);
- xhrupload.addEventListener ("error", boundEventHandler, false);
- xhrupload.addEventListener ("abort", boundEventHandler, false);
- xhr.addEventListener ("abort", boundEventHandler, false);
- xhr.addEventListener ("loadend", boundEventHandler, false);
- xhr.addEventListener ("readystatechange", boundEventHandler, false);
- xhr.open("POST", url, true);
- xhr.withCredentials = this.get("xhrWithCredentials");
- Y.each(this.get("xhrHeaders"), function (value, key) {
- xhr.setRequestHeader(key, value);
- });
- xhr.send(uploadData);
-
- /**
- * Signals that this file's upload has started.
- *
- * @event uploadstart
- * @param event {Event} The event object for the `uploadstart` with the
- * following payload:
- * <dl>
- * <dt>xhr</dt>
- * <dd>The XMLHttpRequest instance handling the file upload.</dd>
- * </dl>
- */
- this.fire("uploadstart", {xhr: xhr});
- },
- /**
- * Cancels the upload of a specific file, if currently in progress.
- *
- * @method cancelUpload
- */
- cancelUpload: function () {
- this.get('xhr').abort();
- }
- }, {
- /**
- * The identity of the class.
- *
- * @property NAME
- * @type String
- * @default 'file'
- * @readOnly
- * @protected
- * @static
- */
- NAME: 'file',
- /**
- * The type of transport.
- *
- * @property TYPE
- * @type String
- * @default 'html5'
- * @readOnly
- * @protected
- * @static
- */
- TYPE: 'html5',
- /**
- * Static property used to define the default attribute configuration of
- * the File.
- *
- * @property ATTRS
- * @type {Object}
- * @protected
- * @static
- */
- ATTRS: {
- /**
- * A String containing the unique id of the file wrapped by the FileFlash instance.
- * The id is supplied by the Flash player uploader.
- *
- * @attribute id
- * @type {String}
- * @initOnly
- */
- id: {
- writeOnce: "initOnly",
- value: null
- },
- /**
- * The size of the file wrapped by FileHTML5. This value is supplied by the instance of File().
- *
- * @attribute size
- * @type {Number}
- * @initOnly
- */
- size: {
- writeOnce: "initOnly",
- value: 0
- },
- /**
- * The name of the file wrapped by FileHTML5. This value is supplied by the instance of File().
- *
- * @attribute name
- * @type {String}
- * @initOnly
- */
- name: {
- writeOnce: "initOnly",
- value: null
- },
- /**
- * The date that the file wrapped by FileHTML5 was created on. This value is supplied by the instance of File().
- *
- * @attribute dateCreated
- * @type {Date}
- * @initOnly
- * @default null
- */
- dateCreated: {
- writeOnce: "initOnly",
- value: null
- },
- /**
- * The date that the file wrapped by FileHTML5 was last modified on. This value is supplied by the instance of File().
- *
- * @attribute dateModified
- * @type {Date}
- * @initOnly
- */
- dateModified: {
- writeOnce: "initOnly",
- value: null
- },
- /**
- * The number of bytes of the file that has been uploaded to the server. This value is
- * non-zero only while a file is being uploaded.
- *
- * @attribute bytesUploaded
- * @type {Date}
- * @readOnly
- */
- bytesUploaded: {
- readOnly: true,
- value: 0
- },
- /**
- * The type of the file wrapped by FileHTML. This value is provided by the instance of File()
- *
- * @attribute type
- * @type {String}
- * @initOnly
- */
- type: {
- writeOnce: "initOnly",
- value: null
- },
- /**
- * The pointer to the instance of File() wrapped by FileHTML5.
- *
- * @attribute file
- * @type {File}
- * @initOnly
- */
- file: {
- writeOnce: "initOnly",
- value: null
- },
- /**
- * The pointer to the instance of XMLHttpRequest used by FileHTML5 to upload the file.
- *
- * @attribute xhr
- * @type {XMLHttpRequest}
- * @initOnly
- */
- xhr: {
- readOnly: true,
- value: null
- },
- /**
- * The dictionary of headers that should be set on the XMLHttpRequest object before
- * sending it.
- *
- * @attribute xhrHeaders
- * @type {Object}
- * @initOnly
- */
- xhrHeaders: {
- value: {}
- },
- /**
- * A Boolean indicating whether the XMLHttpRequest should be sent with user credentials.
- * This does not affect same-site requests.
- *
- * @attribute xhrWithCredentials
- * @type {Boolean}
- * @initOnly
- */
- xhrWithCredentials: {
- value: true
- },
- /**
- * The bound event handler used to handle events from XMLHttpRequest.
- *
- * @attribute boundEventHandler
- * @type {Function}
- * @initOnly
- */
- boundEventHandler: {
- readOnly: true,
- value: null
- }
- },
- /**
- * Checks whether a specific native file instance is valid
- *
- * @method isValidFile
- * @param file {File} A native File() instance.
- * @static
- */
- isValidFile: function (file) {
- return (Win && Win.File && file instanceof File);
- },
- /**
- * Checks whether the browser has a native upload capability
- * via XMLHttpRequest Level 2.
- *
- * @method canUpload
- * @static
- */
- canUpload: function () {
- return (Win && Win.FormData && Win.XMLHttpRequest);
- }
- });
- Y.FileHTML5 = FileHTML5;
-