Did I mentioned that the side where the form belongs was on a different domain then the target of the form (an action attribute)? I thought it would be really easy, even if it wasn't only a pure HTML form because of a unacceptable redirection to the other side. Just a few lines of jQuery and I've got a nice asynchronous form that will add any provided e-mail address. It would be easy if only not the cross domain policy about which I forgot. An AJAX request didn't sound optimistic at the time.

How about $getJSON()? Nope, it had to be a POST method.

I had to quit with a simple AJAX form, there was no way it could work. Next I've tried something little more complex an AJAX form calling a PHP script located on the same domain, which with a use of a cURL extension should create exactly the same POST request as a real HTML form, send it to the target and get a response. It's a popular method to walk around the cross domain JavaScript's limitations and it's called proxy. In theory it looks well, but for a some reason it failed. I had the same values, post arrays looked exactly the same, even the cookies were identical and all I got was an application error.

Here it's my proxy script.

    $ch = curl_init();

    $data = array('email' => 'email@test.com', 
                             'subscription_type' => 'E', 
                             'id' => '6', 
                             'extra_ar' => '');

    curl_setopt($ch, CURLOPT_URL, 'http://www.domain2.com);

    curl_setopt($ch, CURLOPT_USERAGENT, 
    "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:7.0.1) Gecko/20100101 Firefox/7.0.1");
    $strCookie = 'zenid=2ff8666d6c5f92054a5e0d9f10206bc0; path=/';
    curl_setopt($ch, CURLOPT_COOKIE, $strCookie );
    curl_setopt($ch, CURLOPT_HTTPHEADER, 
                array("Content-Type: application/x-www-form-urlencoded"));
    curl_setopt($ch, CURLOPT_POST, TRUE);
    curl_setopt($ch, CURLOPT_HTTPGET, FALSE);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);

    curl_exec($ch);

It was time for plan C. Iframe + content manipulation. As usual it sounds easy and as always it almost is.

  1. Putting a HTML document located on the same server as a parent document of iframe into iframe went smoothly.

  2. Attaching an event handler to a submit button in the loaded form turn out not to be obvious.

First try.

	$('iframe form').bind(funtion(){

		submit: function(){		
	
			console.log('Success!');

		}

	});

Not working.

A little research on Stackoverflow and I've a similar problem and a few answers, a quick look on the jQuery's documentation and a working example at http://api.jquery.com/contents/.

	$('iframe') .contents().find('form').bind(function(){

		submit: function(){			

			console.log('Success!');

		}

	});

It's not working. Instead of DOM element tree I'm getting an empty jQuery object.

More reading, more answers. Looks similar but I had to give it a try. Unfortunately it wasn't the solution for my problem either. Still getting a blank document.

A snippet from Stackoverflow below:

        $(document.getElementById('IFrameId').contentWindow.document).keydown( 

            function(){

                 alert('Key down!'); 

            }

        );

More and more reading and finally I understood what was the problem. Document in iframe wasn't ready at the time of executing the event attach. I found an answer on Stackoferwlow and made my script based on it:


    var url = 'http://localdomain.com';

    //creating an iframe
    $('.iframewrap').
    append('');

    //caching jQuery object
    var iframe = $('#frameid');

    //styling and setting url
    iframe.css({'border': 'none', 'overflow': 'hidden'});
    iframe.attr('src', url);

    //making sure iframe's content is ready
    iframe.load(function(){

        callback(this);

    });          
       

    function callback(frame){
       
       //pay attention to the way of creating 
       //selector's context $('#frameid').contents()!

       $('#sendnewsletter', $('#frameid').contents()).bind({
       
             submit: function(){
                    
                    //hiding a page loaded after submission...
                    $('#frameid').fadeOut('slow', function(){
                            
                           //...and showing our gratitude  
                           $('#postsendmsg')
                                .html('Thanks for subscribing!');

                    });
                    
             }
             
       });
       
    }

It cost me a couple of hour but now I'm satisfied with how it looks and works, and what's the most important I really learned a lot.

Recapitulating: if you want to do a cross domain AJAX request you can:

  1. Make a get request and get a JSONP answer.

  2. Make a proxy server side script which will make a request instead of JavaScript.

  3. You can use an iframe and manipulate it's structure when you are sure the hole document is loaded.

Of course there is more solutions based on YQL and Flash. I haven't tested them yet so I'm just giving a sort note about theirs existence.