Post data to JsonP
It is not possible to do an asynchronous POST
to a service on another domain, due to the (quite sensible) limitation of the same origin policy. JSON-P only works because you're allowed to insert <script>
tags into the DOM, and they can point anywhere.
You can, of course, make a page on another domain the action of a regular form POST.
Edit: There are some interesting hacks out there if you're willing to go to a lot of effort inserting hidden <iframe>
s and mucking about with their properties.
If you need to send a lot of data cross-domain. I usually create a service that you can call in two steps:
First the client do a FORM submit (post allowed cross domain). The service stores the input in the session on the server (using the GUID as key). (the client creates a GUID and send's it as a part of the input)
Then the client do a normal script-inject (JSONP) as a parameter you use the same GUID as you used in the FORM post. The service processes the input from the session and returns the data in the normal JSONP-fashion. After this the session is destroyed.
This of course relies on that you write the server-backend.
I know this is serious necromancy, but I thought I'd post my implementation of JSONP POST using jQuery, which I'm successfully using for my JS widget (this is used for customer registration and login):
Basically, I'm using an IFrame approach, as suggested in the accepted answer. What I'm doing differently is after sending the request, I'm watchin, if the form can be reached in the iframe, using a timer. When the form cannot be reached, it means the request has returned. Then, I'm using a normal JSONP request to query for the status of the operation.
I hope that someone finds it useful. Tested in >=IE8, Chrome, FireFox and Safari.
function JSONPPostForm(form, postUrl, queryStatusUrl, queryStatusSuccessFunc, queryStatusData)
{
var tmpDiv = $('<div style="display: none;"></div>');
form.parent().append(tmpDiv);
var clonedForm = cloneForm(form);
var iframe = createIFrameWithContent(tmpDiv, clonedForm);
if (postUrl)
clonedForm.attr('action', postUrl);
var postToken = 'JSONPPOST_' + (new Date).getTime();
clonedForm.attr('id', postToken);
clonedForm.append('<input name="JSONPPOSTToken" value="'+postToken+'">');
clonedForm.attr('id', postToken );
clonedForm.submit();
var timerId;
var watchIFrameRedirectHelper = function()
{
if (watchIFrameRedirect(iframe, postToken ))
{
clearInterval(timerId);
tmpDiv.remove();
$.ajax({
url: queryStatusUrl,
data: queryStatusData,
dataType: "jsonp",
type: "GET",
success: queryStatusSuccessFunc
});
}
}
if (queryStatusUrl && queryStatusSuccessFunc)
timerId = setInterval(watchIFrameRedirectHelper, 200);
}
function createIFrameWithContent(parent, content)
{
var iframe = $('<iframe></iframe>');
parent.append(iframe);
if (!iframe.contents().find('body').length)
{
//For certain IE versions that do not create document content...
var doc = iframe.contents().get()[0];
doc.open();
doc.close();
}
iframe.contents().find('body').append(content);
return iframe;
}
function watchIFrameRedirect(iframe, formId)
{
try
{
if (iframe.contents().find('form[id="' + formId + '"]').length)
return false;
else
return true;
}
catch (err)
{
return true;
}
return false;
}
//This one clones only form, without other HTML markup
function cloneForm(form)
{
var clonedForm = $('<form></form>');
//Copy form attributes
$.each(form.get()[0].attributes, function(i, attr)
{
clonedForm.attr(attr.name, attr.value);
});
form.find('input, select, textarea').each(function()
{
clonedForm.append($(this).clone());
});
return clonedForm;
}
Well generally JSONP is implemented by adding a <script>
tag to the calling document, such that the URL of the JSONP service is the "src". The browser fetches script source with an HTTP GET transaction.
Now, if your JSONP service is in the same domain as your calling page, then you could probably cobble something together with a simple $.ajax()
call. If it's not in the same domain, then I'm not sure how it'd be possible.