Show:
                                /**
                                 * 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 = o;
                            
                                    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,
                                                                              data: xhr.responseText,
                                                                              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>data</dt>
                                               *          <dd>The data returned by the server.</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,
                                                                              data: xhr.responseText,
                                                                              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 () {
                                        var xhr = this.get('xhr');
                                        if (xhr) {
                                            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;