views:

1387

answers:

4

Is it possible to submit a form inside an iframe without affecting the browser's history?

I've implemented sending a cross domain POST request. It uses Javascript to create and submit a form inside an iframe. It works, but each request adds an item to the browser's history.

Anyone know a way around this? I've tried creating the iframe with both innerHTML and createElement. I've seen no difference so far.

PS - I would love to use XMLHtttpRequest ("Ajax"), but it doesn't support sending data across domains. And I would love to use GET instead of post, but I need to send more than 2k of data.

Here's one version of my code. I've tried many variations and have searched all over, butI can't seem to find a solution that doesn't affect the browser's history. I believe it's not possible -- can anyone confirm that?

<html>

<head>
  <script type="text/javascript">
    function submit(params) {

      var div = document.createElement('div');
      div.innerHTML = '<iframe height="50" width="50"></iframe>';
      document.body.appendChild(div);

      var iframe = div.firstChild;
      var iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
      iframeDocument.open();
      iframeDocument.close();

      var form = iframeDocument.createElement('form');
      iframeDocument.body.appendChild(form);
      form.setAttribute('action', 'http://some-other-domain.com/submit-here');
      form.setAttribute('method', 'POST');

      for (param in params) {
        var field = iframeDocument.createElement('input');
        field.setAttribute('type', 'hidden');
        field.setAttribute('name', param);
        field.setAttribute('value', params[param]);
        form.appendChild(field);
      }
      form.submit();
    }

    window.onload = function() {
      document.getElementById('button').onclick = function() {
        submit({
          'x' : 'Some Value',
          'y' : 'Another Value',
          'z' : new Date().getTime()
        });
      }
    }
  </script>
</head>

<body>
  <h1>Example of using Javascript to POST across domains...</h1>
  <input id="button" type="button" value="click to send">
</body>

</html>
+3  A: 

You should use an AJAX POST.

Usually only the GET method is used while creating Ajax apps. But there are several occasions when POST is necessary when creating a ajax request. This could be for several reasons. For example, POST request are considered more secure than GET request as creating a POST request is relatively harder than creating a GET request.

AJAX calls aren't stored into the browsing history.

voyager
Useful links, you should follow them, but not really that much description.
Robert Massaioli
@Shhnap: it was a bit of tough love. Anyway, added the relevant info that Brian needs.
voyager
Ajax POST doesn't work across domains. The page will be hosted on one domain and will send data to another. Additionally, the data is larger than 2k, so GET won't work.
Brian
A: 

As made in the comments, the solution to this problem is in making an AJAX request from your server instead of trying to submit the page normally. W3schools has a really good introduction to AJAX that you can find here: http://www.w3schools.com/Ajax/Default.Asp

Essentially, AJAX uses javascript to send a request to the server and displays the response and because it happens using Pure javascript then the page does not reload and history is not affected at all. Which sounds like exactly what you want.

Edit: AJAX can not post data.

I actually think it can; or at least there are some workarounds that let you post data. See here:

http://www.captain.at/howto-ajax-form-post-request.php

That seems to do it in a rather straightforward manner. See the code at the bottom of the page. Specifically:

http_request.onreadystatechange = alertContents;
http_request.open('POST', url, true);
http_request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http_request.setRequestHeader("Content-length", parameters.length);
http_request.setRequestHeader("Connection", "close");
http_request.send(parameters);
Robert Massaioli
XMLHttpRequest supports POST, but it doesn't support sending data across domains.
Brian
A: 

If your server can run code, you could probably do an ajax query to a "proxy" page on your server, that would then itself run the request on the remote server and return the results to your page.

David Thibault
I don't run the host domain. I run the domain to which I need to send data. The host page will include my code as a third-party script. Thank you though.
Brian
I see. A quick search seems to indicate it's possible to do using a flash proxy (see http://blog.monstuff.com/archives/000280.html). If you don't want to go down this route, I'm not sure if it's possible.
David Thibault
Flash is a little heavy-weight, but that's a good idea. I'll definitely consider that.
Brian
Actually, the weight of flash isn't the issue. The reason I can't use it that it doesn't work on the iPhone.
Brian
+1  A: 

Does it work to use JS to add an IFRAME whose src is hosted at your site (the domain to which the third-party-hosted script needs to send data?) This IFRAME could include the needed Javascript to make an XMLHttpRequest to your/its domain. And as for getting the actual data to this IFRAME from the third-party-site - try: http://softwareas.com/cross-domain-communication-with-iframes . It's a pretty clever solution involving changing fragment identifiers (#something) at the end of the IFRAME URL, which you can then read via JS within the IFRAME.

Also a guess, but if you tack this past SO solution to a similar history problem (using location.replace) on to the above this hopefully should let you do the anchor-changing part without disrupting the history stack.

Ben
Very interesting! It will take me some time to investigate, but this could be what I was looking for. Thanks!
Brian
It completely worked, and I'm now able to use Ajax within the iframe.
Brian
Glad to hear it! Thanks for reporting back here, I can see quite likely needing to use this approach myself in the near future.
Ben
I may have spoken too soon. Safari doesn't record the iframe history, but other browsers do. Still working this out.http://www.tagneto.org/blogcode/xframe/ui.html
Brian
The final solution was to 1) insert an iframe hosted on my domain 2) use the window.name hack to send data from the host page (on a different domain) to the iframe and 3) send an Ajax POST request to the server on my domain.
Brian