function fileUpload() {
    var form = $form[0];

    if ($(':input[name=submit],:input[id=submit]', form).length) {
      // if there is an input with a name or id of 'submit' then we won't be
      // able to invoke the submit fn on the form (at least not x-browser)
      alert('Error: Form elements must not have name or id of "submit".');
      return;
    }
    
    var s = $.extend(true, {}, $.ajaxSettings, options);
    s.context = s.context || s;
    var id = 'jqFormIO' + (new Date().getTime()), fn = '_'+id;
    window[fn] = function() {
      var f = $io.data('form-plugin-onload');
      if (f) {
        f();
        window[fn] = undefined;
        try { delete window[fn]; } catch(e){}
      }
    }
    var $io = $('<iframe id="' + id + '" name="' + id + '" src="'+ s.iframeSrc +'" onload="window[\'_\'+this.id]()" />');
    var io = $io[0];

    $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });

    var xhr = { // mock object
      aborted: 0,
      responseText: null,
      responseXML: null,
      status: 0,
      statusText: 'n/a',
      getAllResponseHeaders: function() {},
      getResponseHeader: function() {},
      setRequestHeader: function() {},
      abort: function() {
        this.aborted = 1;
        $io.attr('src', s.iframeSrc); // abort op in progress
      }
    };

    var g = s.global;
    // trigger ajax global events so that activity/block indicators work like normal
    if (g && ! $.active++) {
      $.event.trigger("ajaxStart");
    }
    if (g) {
      $.event.trigger("ajaxSend", [xhr, s]);
    }

    if (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) {
      if (s.global) { 
        $.active--;
      }
      return;
    }
    if (xhr.aborted) {
      return;
    }

    var cbInvoked = false;
    var timedOut = 0;

    // add submitting element to data if we know it
    var sub = form.clk;
    if (sub) {
      var n = sub.name;
      if (n && !sub.disabled) {
        s.extraData = s.extraData || {};
        s.extraData[n] = sub.value;
        if (sub.type == "image") {
          s.extraData[n+'.x'] = form.clk_x;
          s.extraData[n+'.y'] = form.clk_y;
        }
      }
    }

    // take a breath so that pending repaints get some cpu time before the upload starts
    function doSubmit() {
      // make sure form attrs are set
      var t = $form.attr('target'), a = $form.attr('action');

      // update form attrs in IE friendly way
      form.setAttribute('target',id);
      if (form.getAttribute('method') != 'POST') {
        form.setAttribute('method', 'POST');
      }
      if (form.getAttribute('action') != s.url) {
        form.setAttribute('action', s.url);
      }

      // ie borks in some cases when setting encoding
      if (! s.skipEncodingOverride) {
        $form.attr({
          encoding: 'multipart/form-data',
          enctype:  'multipart/form-data'
        });
      }

      // support timout
      if (s.timeout) {
        setTimeout(function() { timedOut = true; cb(); }, s.timeout);
      }

      // add "extra" data to form if provided in options
      var extraInputs = [];
      try {
        if (s.extraData) {
          for (var n in s.extraData) {
            extraInputs.push(
              $('<input type="hidden" name="'+n+'" value="'+s.extraData[n]+'" />')
                .appendTo(form)[0]);
          }
        }

        // add iframe to doc and submit the form
        $io.appendTo('body');
        $io.data('form-plugin-onload', cb);
        form.submit();
      }
      finally {
        // reset attrs and remove "extra" input elements
        form.setAttribute('action',a);
        if(t) {
          form.setAttribute('target', t);
        } else {
          $form.removeAttr('target');
        }
        $(extraInputs).remove();
      }
    }

    if (s.forceSync) {
      doSubmit();
    }
    else {
      setTimeout(doSubmit, 10); // this lets dom updates render
    }
  
    var data, doc, domCheckCount = 50;

    function cb() {
      if (cbInvoked) {
        return;
      }

      $io.removeData('form-plugin-onload');
      
      var ok = true;
      try {
        if (timedOut) {
          throw 'timeout';
        }
        // extract the server response from the iframe
        doc = io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document;
        
        var isXml = s.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc);
        log('isXml='+isXml);
        if (!isXml && window.opera && (doc.body == null || doc.body.innerHTML == '')) {
          if (--domCheckCount) {
            // in some browsers (Opera) the iframe DOM is not always traversable when
            // the onload callback fires, so we loop a bit to accommodate
            log('requeing onLoad callback, DOM not available');
            setTimeout(cb, 250);
            return;
          }
          // let this fall through because server response could be an empty document
          //log('Could not access iframe DOM after mutiple tries.');
          //throw 'DOMException: not available';
        }

        //log('response detected');
        cbInvoked = true;
        xhr.responseText = doc.documentElement ? doc.documentElement.innerHTML : null; 
        xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
        xhr.getResponseHeader = function(header){
          var headers = {'content-type': s.dataType};
          return headers[header];
        };

        var scr = /(json|script)/.test(s.dataType);
        if (scr || s.textarea) {
          // see if user embedded response in textarea
          var ta = doc.getElementsByTagName('textarea')[0];
          if (ta) {
            xhr.responseText = ta.value;
          }
          else if (scr) {
            // account for browsers injecting pre around json response
            var pre = doc.getElementsByTagName('pre')[0];
            if (pre) {
              xhr.responseText = pre.innerHTML;
            }
          }        
        }
        else if (s.dataType == 'xml' && !xhr.responseXML && xhr.responseText != null) {
          xhr.responseXML = toXml(xhr.responseText);
        }
        data = $.httpData(xhr, s.dataType);
      }
      catch(e){
        log('error caught:',e);
        ok = false;
        xhr.error = e;
        $.handleError(s, xhr, 'error', e);
      }

      // ordering of these callbacks/triggers is odd, but that's how $.ajax does it
      if (ok) {
        s.success.call(s.context, data, 'success', xhr);
        if (g) {
          $.event.trigger("ajaxSuccess", [xhr, s]);
        }
      }
      if (g) {
        $.event.trigger("ajaxComplete", [xhr, s]);
      }
      if (g && ! --$.active) {
        $.event.trigger("ajaxStop");
      }
      if (s.complete) {
        s.complete.call(s.context, xhr, ok ? 'success' : 'error');
      }

      // clean up
      setTimeout(function() {
        $io.removeData('form-plugin-onload');
        $io.remove();
        xhr.responseXML = null;
      }, 100);
    }

    function toXml(s, doc) {
      if (window.ActiveXObject) {
        doc = new ActiveXObject('Microsoft.XMLDOM');
        doc.async = 'false';
        doc.loadXML(s);
      }
      else {
        doc = (new DOMParser()).parseFromString(s, 'text/xml');
      }
      return (doc && doc.documentElement && doc.documentElement.tagName != 'parsererror') ? doc : null;
    }
  }
function fileUpload() {
    var form = $form[0];

    if ($(':input[name=submit],:input[id=submit]', form).length) {
      
      
      alert('Error: Form elements must not have name or id of "submit".');
      return;
    }
    
    var s = $.extend(true, {}, $.ajaxSettings, options);
    s.context = s.context || s;
    var id = 'jqFormIO' + (new Date().getTime()), fn = '_'+id;
    window[fn] = function() {
      var f = $io.data('form-plugin-onload');
      if (f) {
        f();
        window[fn] = undefined;
        try { delete window[fn]; } catch(e){}
      }
    }
    var $io = $('<iframe id="' + id + '" name="' + id + '" src="'+ s.iframeSrc +'" onload="window[\'_\'+this.id]()" />');
    var io = $io[0];

    $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });

    var xhr = { 
      aborted: 0,
      responseText: null,
      responseXML: null,
      status: 0,
      statusText: 'n/a',
      getAllResponseHeaders: function() {},
      getResponseHeader: function() {},
      setRequestHeader: function() {},
      abort: function() {
        this.aborted = 1;
        $io.attr('src', s.iframeSrc); 
      }
    };

    var g = s.global;
    
    if (g && ! $.active++) {
      $.event.trigger("ajaxStart");
    }
    if (g) {
      $.event.trigger("ajaxSend", [xhr, s]);
    }

    if (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) {
      if (s.global) { 
        $.active--;
      }
      return;
    }
    if (xhr.aborted) {
      return;
    }

    var cbInvoked = false;
    var timedOut = 0;

    
    var sub = form.clk;
    if (sub) {
      var n = sub.name;
      if (n && !sub.disabled) {
        s.extraData = s.extraData || {};
        s.extraData[n] = sub.value;
        if (sub.type == "image") {
          s.extraData[n+'.x'] = form.clk_x;
          s.extraData[n+'.y'] = form.clk_y;
        }
      }
    }

    
    function doSubmit() {
      
      var t = $form.attr('target'), a = $form.attr('action');

      
      form.setAttribute('target',id);
      if (form.getAttribute('method') != 'POST') {
        form.setAttribute('method', 'POST');
      }
      if (form.getAttribute('action') != s.url) {
        form.setAttribute('action', s.url);
      }

      
      if (! s.skipEncodingOverride) {
        $form.attr({
          encoding: 'multipart/form-data',
          enctype:  'multipart/form-data'
        });
      }

      
      if (s.timeout) {
        setTimeout(function() { timedOut = true; cb(); }, s.timeout);
      }

      
      var extraInputs = [];
      try {
        if (s.extraData) {
          for (var n in s.extraData) {
            extraInputs.push(
              $('<input type="hidden" name="'+n+'" value="'+s.extraData[n]+'" />')
                .appendTo(form)[0]);
          }
        }

        
        $io.appendTo('body');
        $io.data('form-plugin-onload', cb);
        form.submit();
      }
      finally {
        
        form.setAttribute('action',a);
        if(t) {
          form.setAttribute('target', t);
        } else {
          $form.removeAttr('target');
        }
        $(extraInputs).remove();
      }
    }

    if (s.forceSync) {
      doSubmit();
    }
    else {
      setTimeout(doSubmit, 10); 
    }
  
    var data, doc, domCheckCount = 50;

    function cb() {
      if (cbInvoked) {
        return;
      }

      $io.removeData('form-plugin-onload');
      
      var ok = true;
      try {
        if (timedOut) {
          throw 'timeout';
        }
        
        doc = io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document;
        
        var isXml = s.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc);
        log('isXml='+isXml);
        if (!isXml && window.opera && (doc.body == null || doc.body.innerHTML == '')) {
          if (--domCheckCount) {
            
            
            log('requeing onLoad callback, DOM not available');
            setTimeout(cb, 250);
            return;
          }
          
          
          
        }

        
        cbInvoked = true;
        xhr.responseText = doc.documentElement ? doc.documentElement.innerHTML : null; 
        xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
        xhr.getResponseHeader = function(header){
          var headers = {'content-type': s.dataType};
          return headers[header];
        };

        var scr = /(json|script)/.test(s.dataType);
        if (scr || s.textarea) {
          
          var ta = doc.getElementsByTagName('textarea')[0];
          if (ta) {
            xhr.responseText = ta.value;
          }
          else if (scr) {
            
            var pre = doc.getElementsByTagName('pre')[0];
            if (pre) {
              xhr.responseText = pre.innerHTML;
            }
          }        
        }
        else if (s.dataType == 'xml' && !xhr.responseXML && xhr.responseText != null) {
          xhr.responseXML = toXml(xhr.responseText);
        }
        data = $.httpData(xhr, s.dataType);
      }
      catch(e){
        log('error caught:',e);
        ok = false;
        xhr.error = e;
        $.handleError(s, xhr, 'error', e);
      }

      
      if (ok) {
        s.success.call(s.context, data, 'success', xhr);
        if (g) {
          $.event.trigger("ajaxSuccess", [xhr, s]);
        }
      }
      if (g) {
        $.event.trigger("ajaxComplete", [xhr, s]);
      }
      if (g && ! --$.active) {
        $.event.trigger("ajaxStop");
      }
      if (s.complete) {
        s.complete.call(s.context, xhr, ok ? 'success' : 'error');
      }

      
      setTimeout(function() {
        $io.removeData('form-plugin-onload');
        $io.remove();
        xhr.responseXML = null;
      }, 100);
    }

    function toXml(s, doc) {
      if (window.ActiveXObject) {
        doc = new ActiveXObject('Microsoft.XMLDOM');
        doc.async = 'false';
        doc.loadXML(s);
      }
      else {
        doc = (new DOMParser()).parseFromString(s, 'text/xml');
      }
      return (doc && doc.documentElement && doc.documentElement.tagName != 'parsererror') ? doc : null;
    }
  }
function fileUpload ( ) { var form = $form [ 0 ] ; if ( $ ( ':input[name=submit],:input[id=submit]' , form ) . length ) { // if there is an input with a name or id of 'submit' then we won't be // able to invoke the submit fn on the form (at least not x-browser) alert ( 'Error: Form elements must not have name or id of "submit".' ) ; return ; } var s = $ . extend ( true , { } , $ . ajaxSettings , options ) ; s . context = s . context || s ; var id = 'jqFormIO' + ( new Date ( ) . getTime ( ) ) , fn = '_' + id ; window [ fn ] = function ( ) { var f = $io . data ( 'form-plugin-onload' ) ; if ( f ) { f ( ) ; window [ fn ] = undefined ; try { delete window [ fn ] ; } catch ( e ) { } } } var $io = $ ( '<iframe id="' + id + '" name="' + id + '" src="' + s . iframeSrc + '" onload="window[\'_\'+this.id]()" />' ) ; var io = $io [ 0 ] ; $io . css ( { position : 'absolute' , top : '-1000px' , left : '-1000px' } ) ; var xhr = { // mock object aborted : 0 , responseText : null , responseXML : null , status : 0 , statusText : 'n/a' , getAllResponseHeaders : function ( ) { } , getResponseHeader : function ( ) { } , setRequestHeader : function ( ) { } , abort : function ( ) { this . aborted = 1 ; $io . attr ( 'src' , s . iframeSrc ) ; // abort op in progress } } ; var g = s . global ; // trigger ajax global events so that activity/block indicators work like normal if ( g && ! $ . active ++ ) { $ . event . trigger ( "ajaxStart" ) ; } if ( g ) { $ . event . trigger ( "ajaxSend" , [ xhr , s ] ) ; } if ( s . beforeSend && s . beforeSend . call ( s . context , xhr , s ) === false ) { if ( s . global ) { $ . active -- ; } return ; } if ( xhr . aborted ) { return ; } var cbInvoked = false ; var timedOut = 0 ; // add submitting element to data if we know it var sub = form . clk ; if ( sub ) { var n = sub . name ; if ( n && ! sub . disabled ) { s . extraData = s . extraData || { } ; s . extraData [ n ] = sub . value ; if ( sub . type == "image" ) { s . extraData [ n + '.x' ] = form . clk_x ; s . extraData [ n + '.y' ] = form . clk_y ; } } } // take a breath so that pending repaints get some cpu time before the upload starts function doSubmit ( ) { // make sure form attrs are set var t = $form . attr ( 'target' ) , a = $form . attr ( 'action' ) ; // update form attrs in IE friendly way form . setAttribute ( 'target' , id ) ; if ( form . getAttribute ( 'method' ) != 'POST' ) { form . setAttribute ( 'method' , 'POST' ) ; } if ( form . getAttribute ( 'action' ) != s . url ) { form . setAttribute ( 'action' , s . url ) ; } // ie borks in some cases when setting encoding if ( ! s . skipEncodingOverride ) { $form . attr ( { encoding : 'multipart/form-data' , enctype : 'multipart/form-data' } ) ; } // support timout if ( s . timeout ) { setTimeout ( function ( ) { timedOut = true ; cb ( ) ; } , s . timeout ) ; } // add "extra" data to form if provided in options var extraInputs = [ ] ; try { if ( s . extraData ) { for ( var n in s . extraData ) { extraInputs . push ( $ ( '<input type="hidden" name="' + n + '" value="' + s . extraData [ n ] + '" />' ) . appendTo ( form ) [ 0 ] ) ; } } // add iframe to doc and submit the form $io . appendTo ( 'body' ) ; $io . data ( 'form-plugin-onload' , cb ) ; form . submit ( ) ; } finally { // reset attrs and remove "extra" input elements form . setAttribute ( 'action' , a ) ; if ( t ) { form . setAttribute ( 'target' , t ) ; } else { $form . removeAttr ( 'target' ) ; } $ ( extraInputs ) . remove ( ) ; } } if ( s . forceSync ) { doSubmit ( ) ; } else { setTimeout ( doSubmit , 10 ) ; // this lets dom updates render } var data , doc , domCheckCount = 50 ; function cb ( ) { if ( cbInvoked ) { return ; } $io . removeData ( 'form-plugin-onload' ) ; var ok = true ; try { if ( timedOut ) { throw 'timeout' ; } // extract the server response from the iframe doc = io . contentWindow ? io . contentWindow . document : io . contentDocument ? io . contentDocument : io . document ; var isXml = s . dataType == 'xml' || doc . XMLDocument || $ . isXMLDoc ( doc ) ; log ( 'isXml=' + isXml ) ; if ( ! isXml && window . opera && ( doc . body == null || doc . body . innerHTML == '' ) ) { if ( -- domCheckCount ) { // in some browsers (Opera) the iframe DOM is not always traversable when // the onload callback fires, so we loop a bit to accommodate log ( 'requeing onLoad callback, DOM not available' ) ; setTimeout ( cb , 250 ) ; return ; } // let this fall through because server response could be an empty document //log('Could not access iframe DOM after mutiple tries.'); //throw 'DOMException: not available'; } //log('response detected'); cbInvoked = true ; xhr . responseText = doc . documentElement ? doc . documentElement . innerHTML : null ; xhr . responseXML = doc . XMLDocument ? doc . XMLDocument : doc ; xhr . getResponseHeader = function ( header ) { var headers = { 'content-type' : s . dataType } ; return headers [ header ] ; } ; var scr = / (json|script) / . test ( s . dataType ) ; if ( scr || s . textarea ) { // see if user embedded response in textarea var ta = doc . getElementsByTagName ( 'textarea' ) [ 0 ] ; if ( ta ) { xhr . responseText = ta . value ; } else if ( scr ) { // account for browsers injecting pre around json response var pre = doc . getElementsByTagName ( 'pre' ) [ 0 ] ; if ( pre ) { xhr . responseText = pre . innerHTML ; } } } else if ( s . dataType == 'xml' && ! xhr . responseXML && xhr . responseText != null ) { xhr . responseXML = toXml ( xhr . responseText ) ; } data = $ . httpData ( xhr , s . dataType ) ; } catch ( e ) { log ( 'error caught:' , e ) ; ok = false ; xhr . error = e ; $ . handleError ( s , xhr , 'error' , e ) ; } // ordering of these callbacks/triggers is odd, but that's how $.ajax does it if ( ok ) { s . success . call ( s . context , data , 'success' , xhr ) ; if ( g ) { $ . event . trigger ( "ajaxSuccess" , [ xhr , s ] ) ; } } if ( g ) { $ . event . trigger ( "ajaxComplete" , [ xhr , s ] ) ; } if ( g && ! -- $ . active ) { $ . event . trigger ( "ajaxStop" ) ; } if ( s . complete ) { s . complete . call ( s . context , xhr , ok ? 'success' : 'error' ) ; } // clean up setTimeout ( function ( ) { $io . removeData ( 'form-plugin-onload' ) ; $io . remove ( ) ; xhr . responseXML = null ; } , 100 ) ; } function toXml ( s , doc ) { if ( window . ActiveXObject ) { doc = new ActiveXObject ( 'Microsoft.XMLDOM' ) ; doc . async = 'false' ; doc . loadXML ( s ) ; } else { doc = ( new DOMParser ( ) ) . parseFromString ( s , 'text/xml' ) ; } return ( doc && doc . documentElement && doc . documentElement . tagName != 'parsererror' ) ? doc : null ; } }
private function for handling file uploads (hat tip to YAHOO!)
private function for handling file uploads ( hat tip to YAHOO! )