implement post url in IFrame - javascript

How can I make a POST request to some URL (see my code below) in Javascript ?
My code so far doesn't work and I actually need to put it into an iFrame (having its with and height set to 0) to prevent the main page to reload.
$(document).ready(function(){
$("button").click(function(){
$.post(
"http://control.msg91.com/api/sendotp.php?otp_length=4&authkey=xxx&message=Your OTP is ##OTP##&sender=OTPSMS&mobile=xxx&otp_expiry=2"
, function(data){
alert(data);
});
});
});

If you want to use an iframe, then do not use XMLHttpRequest (NB $.post is a jQuery that wraps around XMLHttpRequest).
Create a <form>. Set its action to the URL. It's method to POST and its target to the ID of the <iframe>.
Put the data in that form. Then submit it.
If you want to do this entirely with JavaScript, then you can create the form using DOM and with entirely hidden inputs so that nothing shows up in the existing page. Ensure that you append the form to the document as some browsers will not let you submit forms that aren't part of the document.
That said, since you want an iframe with no dimensions, it seems odd to want to use an iframe at all.
You might be trying to work around CORS limitations, but you should be able to use the code you are using to make a request successfully. You just won't be able to tell if it was successful or not (because the restrictions are on reading the response). If you used an iframe, you would have the same limitations.
If you want to suppress the error message that is shown in the console, you could use fetch with mode: "no-cors". You still wouldn't be able to read the response though.

Make sure you are not hitting an issue with CORS. Unless the resource you are hitting allows exceptions to the cross-origin policy, you will not be able to access it if your webpage is not located on control.msg91.com.

Related

Sending cross-origin iFrame content over postMessage fails

First of all, I know that the topic of accessing iFrame Elements cross-domain is a tricky topic and I might be going with this nowhere.
I have a Google Forms embedded in my app that I need to set up in a way to tell me when a user has submitted his/her response. I already tried lots of things but the most optimistic way that could work would be just to read the HTML of the iFrame when the last page has been loaded saying that the response was submitted.
Therefore, I was looking for solutions on how to simply read any kind of snippet of the iFrame's content and I came across this comment in another thread:
https://stackoverflow.com/a/32265508/3856569
I'm trying reading the content of the iFrame as suggested in the comment and sending it to the parent windows via postMessage like so:
$(document).ready(function() {
document.getElementById("googleForm").addEventListener("load",
function() {
var message = document.getElementById("googleForm");
parent.postMessage(JSON.parse(JSON.stringify(message)), '*')
});
})
and the parent-window reads the message like so:
function receiveMessageGoogleForm (event) {
console.log(event)
}
//Listen for message events
window.addEventListener("message", receiveMessageGoogleForm, false);
However, the data property of the event object upon receiving the message seems to be empty.
Is this another inbuilt mechanism to avoid reading any kind of a cross-origin iFrame or am I missing something here?
Forget about postMessage for a moment.
var message = document.getElementById("googleForm");
var result = JSON.parse(JSON.stringify(message));
console.log(result);
<div id="googleForm">content</div>
If you pass a DOM element into JSON.stringify then you get a (JSON representation of an) empty object out.
DOM elements don't have any properties that will be automatically processed by JSON.stringify.
If you want to get data from a form, then you need to actually read the data from the form (e.g. get the input elements and read their value properties).
If you want to extract data from the DOM of a Google Form or if you want to send a postMessage from a Google Form then you need to write the JavaScript which does that in the HTML document containing the form.
You can't pull it across domains.
The page with the Google Form has access to the data and can push it across domains with post message.
Nothing you can do will let you just help yourself to that data.
It's private between the owner of the browser and the owner of the website and one of them needs to take explicit action if it is to be shared with anyone else (e.g. someone who has wrapped that website in an iframe).

Use JSONP to load an html page

I'm trying to load an external page using JSONP, but the page is an HTML page, I just want to grab the contents of it using ajax.
EDIT: The reason why I'm doing this is because I want to pass all the user information ex: headers, ip, agent, when loading the page rather than my servers.
Is this doable? Right now, I can get the page, but jsonp attempts to parse the json, returning an error: Uncaught SyntaxError: Unexpected token <
Sample code:
$.post('http://example.com',function(data){
$('.results').html(data);
},'jsonp');
I've set up a jsfiddle for people to test with:
http://jsfiddle.net/8A63A/1/
http://en.wikipedia.org/wiki/JSONP#Script_element_injection
Making a JSONP call (in other words, to employ this usage pattern),
requires a script element. Therefore, for each new JSONP request, the
browser must add (or reuse) a new element—in other words,
inject the element—into the HTML DOM, with the desired value for the
"src" attribute. This element is then evaluated, the src URL is
retrieved, and the response JSON is evaluated.
Now look at your error:
Uncaught SyntaxError: Unexpected token <
< is the first character of any html tag, probably this is the start of <DOCTYPE, in this case, which is, of course, invalid JavaScript.
And NO, you can't use JSONP for fetching html data.
I have done what you want but in my case I have control of the server side code that returns the HTML.
So, what I did was wrapped the HTML code in one of the Json properties of the returned object and used it at client side, something like:
callback({"page": "<html>...</html>"})
The Syntax error you are facing it's because the library you're using expects json but the response is HTML, just that.
I've got three words for you: Same Origin Policy
Unless the remote URL actually supports proper JSONP requests, you won't be able to do what you're trying to. And that's a good thing.
Edit: You could of course try to proxy the request through your server …
If you really just want to employ the client to snag an HTML file, I suggest using flyJSONP - which uses YQL.. or use jankyPOST which uses some sweet techniques:
jankyPOST creates a hidden iframe and stuffs it with a form (iframe[0].contentWindow.document.body.form.name).
Then it uses HTML5 (watch legacy browsers!) webMessaging API to post to the other iframe and sets iframe's form elements' vals to what u specified.
Submits form to remote server...done.
Or you could just use PHP curl, parse it, echo it, so on.
IDK if what exactly ur using it for but I hope this helps.
ALSO...
I'm pretty sure you can JSONP anything that is an output from server code. I did this with ClientLogin by just JSONPing their keyGen page and successfully consoleLogged the text even though it was b/w tags. I had some other errors on that but point is that I scraped that output.
Currently, I'm trying to do what you are so I'll post back if successful.
I don't think this is possible. JSONP requires that the response is rendered properly.
If you want another solution, what about loading the url in an iframe and trying to talk through the iframe. I'm not 100% positive it will work, but it's worth a shot.
First, call the AJAX URL manually and see of the resulting HTML makes sense.
Second, you need to close your DIV in your fiddle example.

Performing JS methods on a URL submitted by the user?

I haven't found an answer to this, and since I'm pretty new to JS, I don't know if it's even possible.
I have a regular HTML form, where the only field is a user types in a URL (any URL) and clicks submit.
The URL will "be sent" to JS code that stores this URL in some variable, I guess. Basically, I need to be able to call getElementsByTagName() on any URL submitted by the user.
My point is to count up the number of times a URL contains a specified element, which I do know how to do :)
How do I interpret a URL submitted through a form by someone and then take that URL and be able to perform methods (such as getElementsById) on it? I want to return the count of the number of elements to the user.
Any ideas? Can this all be done in JS? Is this possible?
When you say "URL," I assume you are talking about the actual webpage and not the url string. In other words, you want to load the entire DOM into a javascript variable and then parse it with getElementsByTagName(), etc. Javascript cannot load this webpage due to the Same Origin Policy, unless users can only submit pages that are on the same domain as your site. If that was the case, you could use a frame. Otherwise, JS can't do it without Jsonp, which isn't going to work in this case.
However, all is not lost. You can have your JS make an asynchronous request (ajax) to your own server. Your server scripting language /can/ get the entire DOM of the webpage (e.g. PHP can do this with cURL). Then it can send the entire string back to JS as xml that can be parsed. Good luck.
You can't really do that from the client (the web browser) with nothing but Javascript, because security rules will prevent your page from fetching and examining content from a different domain. You'll need to send the URL to a server and have it do the work.

Retrieving response from remote server after uploading a file in iframe

I have a form that uploads a file in an firame to a remote server. As a result at the submission url server returns json data with the result of operation, which my iframe catches.
{'result': 'true' or 'false'}
Now I'd like to retrieve this json as the callback of my iframe. I know that I need jsonp to achieve this since it's a cross-site call. Here's my function with sample code from IBM' site :
function fileUploadFunction(){
var fileUploadForm = $('#file_upload_form');
fileUploadForm.attr('action', uploadURL);
fileUploadForm.submit();
$('#upload_target').load(function () {
alert("IFrame loaded");
$.getJSON(uploadUrl+"&callback=?", function(data) {
alert("Symbol: " + data.symbol + ", Price: " + data.price);
});
});
};
But here few problems arise. First - my uploadUrl is just "http://something/" . Do I need it to support calls with $callback= suffix ?
Secondly - server gives response only as a result to file upload. So I need to get the result that is stored in my iframe and not at the specified url. How to solve this ?
Here's the link. Notice hidden iframe inside the form. Result from server shows there. :
http://ntt.vipserv.org/artifact/
EDIT
I've previously tried :
$('#upload_target').load(function () {
var ret = frames['upload_target'].document.getElementsByTagName("body")[0].innerHTML;
var data = eval("("+ret+")");
});
But it raises 'permissions denied' error.
This is easily done with easyXDM and there is actually a blog post about this exact use case here.
In essence what it does is use cross-domain messaging to relay the response to the invoking document.
Update: Here is a link for this in action, the source can be found at github, the files are prefixed 'upload_'.
Sean's easyXDM recommendation is a great option (& should probably be marked as correct), but I wanted to suggest another light-weight solution that I haven't seen anyone use.
In cases where you're posting to a hidden iframe on another domain & just need a single response back (not two-way communcation), you could pass a message from the iframe to the parent using a busted url. Here's an example:
the parent loads an iframe on different domain
the parent polls myframe.contentWindow.location.href (constantly getting Permission denied errors since the frame is on another domain)
iframe processes, then redirects to
http://parentdomain.com/pagethatdoesnotexist?{'result':'ok'}
iframe gets a 404 but now the location is available to the parent
the parent reads the message from the iframe's URL
one possible solution could be to set the name of the iframe with pure js. This name could be read from the wrapping parent page.
Looks to me that your code will request uploadURL twice: first, .submit() do a POST request to upload the file and the result is shown in the iframe as a webpage; second, .getJSON() do a GET request and the result is executed as javascript in <script>. You will realize this if you open up Firebug while testing your app.
Since two of the requests are independent, I have no idea how .getJSON() will give you any information about the file you just uploaded with .submit().
For these kind of cross-domain communication, I would suggest using postMessage; otherwise you will need to change you application workflow to do everything in the iframe after file have uploaded; e.g. do <script>alert('Submission accepted');</script> in the iframe.
What are you trying to do after a user have successfully upload a file?
dont use .html() at all.
I used
jQuery('.someElement')
and it worked for me. you can save the result in a variable and insert it in new element
e.g
var = jQuery('.someElement');
jQuery('.newElement').html(var);

Asynchronous cross-domain POST request via JavaScript?

I could just create a form and use that to do a POST request to any site, thing is the FORM method isn't asynchronous, I need to know when the page has finished loading. I tried messing around with this using an iframe with a form inside, but no success.
Any ideas?
EDIT
unfortunately I have no control over the response data, it varies from XML, json to simple text.
You can capture the onload event of an iframe. Target your form to the iframe and listen for the onload. You will not be able to access the contents of the iframe though, just the event.
Try something like this:
<iframe id='RS' name='RS' src='about:blank' onload='loaded()'></iframe>
<form action='wherever.php' target='RS' method='POST'>...</form>
script block:
var loadComplete = 0
function loaded() {
//avoid first onload
if(loadComplete==0) {
loadComplete=1
return()
}
alert("form has loaded")
}
IF you want to make cross domain requests you should either made a JSON call or use a serverside proxy. A serverside proxy is easy to set up, not sure why people avoid it so much. Set up rules in it so people can not use the proxy to request other things.
If the data returned from the cross domain post is JSON, then you can dynamically add a script tag pointing to the URI that returns the data. The browser will load that "script" which then you can access from other javascript.
YUI3's IO object offers cross-domain requests, however it does so using a small Flash control it embeds on the page.
While there is work going into secure cross-domain requests from JavaScript, at this time, you need to use a plugin like Flash or Silverlight as a bridge with which to make the request.
You can't do anything cross-domain using javascript. You'd have to use a backend language like PHP or asp or something.

Categories