Archive

hidden iframe post jquery plugin with iframe

I have been pretty getting pretty excited lately about the possibilities of JSONP + JavaScript MVC possibilities, but one piece that was still missing was how to send data back to the server in a distributed server scenario where your JavaScript RIA app is getting and sending data to different servers. Of course a simple server side wrapper could solve the solution, where you post to your server which sends the data to other server.

So here is the solution: I create a hidden iframe on the fly and a form inside of it, post the data inside of it, and remove the iframe from the DOM. (this is not an original solution of course :) but I have not seen anybody wrapping this in a nice jQuery plugin)

Here is the github project link which will have the most up to date code.

Demo:

Code:

  (function ($) {

    // Element factory.
    var createElement = function (context, name, atributes) {

      // Create element.
      var element = context.createElement(name);

      // Add atributes.
      $.each(atributes, function (i, d) {
        element[d.key] = d.value;
      });
      return element;
    };

    $.fn.iForm = function (op) {
      
      // Defaults.
      var defaults = {
        start: function () { },
        sucess: function () { },
        buttonSelector: '.button',
        disabledButtonClass: 'disabled'
      };

      $.extend(defaults, op);

      return this.each(function () {

        // Local vars.
        var form = $(this),
            postUrl = form.attr('action'),
            postMethod = form.attr('method'),
            submitButton = $(defaults.buttonSelector, form);

        // Submit button click.
        submitButton.click(function () {
          
          // Do nothing if button is disabled.
          if(submitButton.hasClass(defaults.disabledButtonClass)){
            return false;
          }

          // Disable button.
          submitButton.addClass(defaults.disabledButtonClass).attr('disabled', 'disabled'); ;

          // 'On start'
          defaults.start(submitButton);

          // Create iframe.
          var iframe = $('');

          form.after(iframe);

          // Serilize form.
          var formData = form.serializeArray();

          // Local shortcuts.
          var iF = iframe[0],
              iWindow = iF.contentWindow,
              iDoc = iWindow.document,
              iBody = iDoc.body;

          // Create form.
          var iForm = createElement(iDoc, 'form',
            [
              { key: 'action', value: postUrl },
              { key: 'method', value: postMethod }
            ]);

          // Create form fields.
          $.each(formData, function (i, d) {
            var input = createElement(iDoc, 'input',
              [
                { key: 'name', value: d.name },
                { key: 'value', value: d.value }
              ]);
            iForm.appendChild(input);
          });

          // IE needs delay.
          var t = setTimeout(function () {
            // Put form into iframe page.
            iDoc.body.appendChild(iForm);
          }, 5);

          // IE needs delay.
          var t2 = setTimeout(function () {

            // Submit form.
            iForm.submit();

            // Callback.
            iF.onload = function () {

              submitButton.removeClass(defaults.disabledButtonClass).removeAttr('disabled');

              // FF needs delay.
              var t = setTimeout(function () {
                iframe.remove();
              }, 10);

              // Run callback.
              defaults.sucess(submitButton);
            };
          }, 10);
          return false;
        });
      });
    };
  } (jQuery));

Usage:

  $('form').iForm({
    start: function(button){
      //alert('loaded');
    },
    sucess: function (button) {
      //alert('loaded');
    }  
  });

Comments: