Config
Table of Contents

Class

O.FormUploader

A class suitable for uploading FormData objects. The concrete class may be O.XHR if it supports the XMLHttpRequest Level 2 spec, or O.FormUploader-IFrameTransport if not. Either way, the interface is identical so you can ignore the underlying implementation.

/*global window, document */

"use strict";

( function ( NS ) {

var hidden = {
 position: 'absolute',
 top: -1000,
 left: -1000
};

Constructor

O.FormUploader( io )

Parameters

ioObject An object containing any combination of the methods 'uploadProgress', 'loading', 'success' and 'failure', to be called by the FormUploader instance as these events occur.

Class

O.FormUploader-IFrameTransport

An IO-compatible class that submits form data to a hidden iframe, allowing background file uploading.

NS.FormUploader = window.FormData ? NS.XHR : NS.Class({

Property

O.FormUploader-IFrameTransport#io

  • Object

Reference to object on which callbacks are made.

io: null,

Constructor

O.FormUploader-IFrameTransport( io )

Parameters

ioObject An object containing any combination of the methods 'uploadProgress', 'loading', 'success' and 'failure', to be called by the FormUploader instance as these events occur.
init: function ( io ) {
   this._isSuccess = false;
   this._isRunning = false;
   this._response = '';
   this.io = io || null;
 },

Private Property

O.FormUploader-IFrameTransport#_isSuccess

  • Boolean
  • private

Was the request successful?

Private Property

O.FormUploader-IFrameTransport#_isRunning

  • Boolean
  • private

Is there a request in progress?

Method

O.FormUploader-IFrameTransport#isRunning()

Determines whether a request is currently in progress.

Returns

Boolean Is there a request in progress?

isRunning: function () {
   return this._isRunning;
 },

Private Property

O.FormUploader-IFrameTransport#_response

  • String
  • private

The response text.

Method

O.FormUploader-IFrameTransport#getResponse()

Returns

String The full text of the response to the request.

getResponse: function () {
   return this._response;
 },

Method

O.FormUploader-IFrameTransport#getResponseType()

Returns

String Always "application/json".

getResponseType: function () {
   return 'application/json';
 },

Method

O.FormUploader-IFrameTransport#getStatus()

Returns the HTTP status code representing the status of the request.

Returns

Number The HTTP status code.

getStatus: function () {
   return this._isRunning ? 0 : this._isSuccess ? 200 : 400;
 },

Method

O.FormUploader-IFrameTransport#send( method, url, data )

If a request is currently active, it is first aborted. A new request is then made to the server, using the parameters supplied.

Parameters

methodString This is ignored; the method is always POST.
urlString The URL to which the request is to be made.
dataFormData The data to send in the body of the request.

Returns

O.FormUploader-IFrameTransport Returns self.

send: function ( method, url, data ) {
   if ( !( data instanceof window.FormData ) ) {
     throw new Error( 'IFrameTransport only sends FormData objects' );
   }
   if ( this._isRunning ) {
     this.abort();
   }

   this._isRunning = true;
   this._isSuccess = false;
   this._response = '';

   var that = this,
     body = document.body,
     transactionId = this._transactionId = 'upload' + Date.now(),
     frameName = 'frame-' + transactionId,
     iframe = this._iframe = NS.Element.create( 'iframe', {
       id: frameName,
       name: frameName,
       styles: hidden
     }),
     form = this._form = data.form;

   url += ( url.contains( '?' ) ? '&' : '?' ) +
     'callback=top.' + transactionId;
   form.action = this._targetUrl = url;
   form.target = frameName;

   iframe.addEventListener( 'load', this._loadfn = function () {
     that._formFrameDidLoad();
   }, false );

   window[ transactionId ] = function ( data ) {
     var status = 200,
       responseType = 'application/json',
       response = JSON.stringify( data ),
       io = that.io;
     that._response = response;
     that._isSuccess = true;
     if ( io ) {
       io.set( 'uploadProgress', 100 )
          .set( 'progress', 100 )
          .set( 'status', status )
          .set( 'responseType', responseType )
          .set( 'response', response )
          .fire( 'io:success', {
         status: status,
         headers: {},
         type: responseType,
         data: response
          });
       io.fire( 'io:end' );
     }
   }.invokeInRunLoop();

   body.appendChild( iframe );
   body.appendChild( form );
   form.submit();

   return this;
 },

Private Method

O.FormUploader-IFrameTransport#_formFrameDidLoad()

Callback for when the iframe to which the form was submitted has loaded.

_formFrameDidLoad: function () {
   // First load event is fired as soon as the frame is appended to the
   // DOM. Ignore this one; we're only interested in what happens after the
   // full page has loaded.
   var iframeHref, io;
   // May throw a security error in old IE/Opera.
   try  {
     iframeHref = this._iframe.contentWindow.location.href;
   } catch ( error ) {}
   if ( iframeHref === 'about:blank' ) {
     return;
   }
   this._isRunning = false;
   if ( !this._isSuccess ) {
     io = this.io;
     io.set( 'uploadProgress', 100 )
         .set( 'progress', 100 )
         .set( 'status', 400 )
         .fire( 'io:failure', {
        status: 400,
        headers: {},
        type: '',
        data: ''
         });
     io.fire( 'io:end' );
   }
   this._complete();
 }.invokeInRunLoop(),

Method

O.FormUploader-IFrameTransport#abort()

Aborts the currently active request. No further callbacks will be made for that request. If there is no active request, calling this method has no effect.

Returns

O.FormUploader-IFrameTransport Returns self.

abort: function () {
   if ( this._isRunning ) {
     this._isRunning = false;
     this._complete();
     this.io.fire( 'io:abort' );
     this.io.fire( 'io:end' );
   }
   return this;
 },

Private Method

O.FormUploader-IFrameTransport#_complete()

Removes event listeners and releases references to objects associated with the request.

_complete: function () {
   var body = document.body;
   body.removeChild( this._form );
   body.removeChild( this._iframe );
   this._iframe.removeEventListener( 'load', this._loadfn, false );
   window[ this._transactionId ] = null;
   this._iframe = this._form = this._loadfn = null;
 }
});

Class

FormData

Implementation of the FormData object for browsers that don't natively support it. Slightly different from spec in that you can call append() with a form element as the value; this is to support browsers that do not implement the File API and therefore cannot supply a File object as the value.

if ( !window.FormData ) {
 window.FormData = NS.Class({
   init: function () {
     this.form = NS.Element.create( 'form', {
       method: 'post',
       enctype: 'multipart/form-data',
       styles: hidden
     });
   },
   append: function ( name, value ) {
     if ( typeof value === 'string' ) {
       this.form.appendChild( NS.Element.create( 'input', {
         type: 'hidden',
         name: name,
         value: value
       }) );
     } else {
       var file = value.file;
       if ( file.nodeType ) {
         file.name = name;
         this.form.appendChild( file );
       }
     }
   }
 });
 window.FormData.isFake = true;
}

}( O ) );
Animation
Application
Core
DataStore
DOM
DragDrop
Foundation
IO
Localisation
Selection
Parser
TimeZones
Storage
Touch
CollectionViews
UA
ContainerViews
ControlViews
PanelViews
View