Hi I have built a web app and everything was working ok until I tested on IE9 with JSON files coming from another domain
Basically all of out JSON files are stored on AMAZON.
The idea on the first load is that I get a site.json file and this initializes and setups the app - but in IE9 and periodically in Safari and Chrome I am getting cross domain errors
So this is some extracts from the head of my homepage
<meta http-equiv="Access-Control-Allow-Origin" content="*"/>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.0/jquery-ui.min.js"></script>
<script type="text/javascript">
var SiteConfig, frameworkHost;
$(document).ready(function() {
var promise = $.ajax({
url: '//s3-ap-southeast-2.amazonaws.com/****/site.json',
method: 'get',
dataType: 'json'
});
$.when(promise).then(function(result) {
SiteConfig = result.data;
frameworkHost = '//s3-ap-southeast-2.amazonaws.com/**/public_html';
var requireTag = document.createElement('script');
requireTag.setAttribute('type', 'text/javascript');
requireTag.setAttribute('src', frameworkHost + '/js/require/require.js');
requireTag.setAttribute('data-main', frameworkHost + '/js/bootstrap');
document.head.appendChild(requireTag);
});
});
</script>
but the problem is as soon as the url to get site.json is not local on IE9 it fails.
Also in chrome, and safari on iphone 4s with ios 5 on occasions i get this error
XMLHttpRequest cannot load http://s3-ap-southeast-2.amazonaws.com/*. Origin It is not allowed by Access-Control-Allow-Origin
when i clear the cache this works though. It works perfectly on FF.
Can anyone help?
Thanks
if ($.browser.msie && window.XDomainRequest) {
// Use Microsoft XDR
var xdr = new XDomainRequest();
xdr.open("get", "someurl");
xdr.onload = function () {
var JSON = $.parseJSON(xdr.responseText);
if (JSON == null || typeof (JSON) == 'undefined')
{
JSON = $.parseJSON(data.firstChild.textContent);
}
processData(JSON);
};
xdr.send();
} else {
$.ajax({
type: 'GET',
url: "someurl",
processData: true,
data: {},
dataType: "json",
success: function (data) { processData(data); }
});
}
Related
I want to call sample service using Ajax. Below is the code i am using.
<script type="text/javascript">
var date1;
var time1;
var time2;
var date2
function CallService() {
date1 = new Date();
time1 = date1.getMilliseconds();
$.ajax({
url: "https://www.google.co.in",
type: "GET",
crossDomain: true,
contentType: "text/xml; charset=\"utf-8\"",
success: OnSuccess,
error: OnError
});
return false;
}
function OnSuccess(data, status) {
alert('success');
}
function OnError(request, status, error) {
alert('error');
}
$(document).ready(function () {
jQuery.support.cors = true;
});
</script>
I know that if we add header('Access-Control-Allow-Origin: *'); in server will remove the issue.
But i don't have access to the server side code so please can some one tell me how can i enable cross domain access in javascript.
Thanks in Advance.
You can use JSONP which stands for “JSON with Padding” and it is a workaround for loading data from different domains. It loads the script into the head of the DOM and thus you can access the information as if it were loaded on your own domain, thus by-passing the cross domain issue
Basic Example : http://jsfiddle.net/yvzSL/714/
Please refer "http://www.sitepoint.com/jsonp-examples/" for more examples
I know how to use jQuery well, but I don't know so much pure JavaScript.
This is my jQuery code:
$(document).ready(function() {
$.get('http://jsonip.com/', function(r){
var ip_address = r.ip;
my_function(ip_address);
});
function my_function(ip_address){
var url = "Url_to my server hosted on a different domain";
var data = {number:"1286", ip: ip_address};
$.ajax({
url: url,
type: "POST",
dataType: 'json',
crossDomain: true,
data: {data: data},
success: function (data) {console.log(JSON.stringify(data));},
error: function (xhr, error) {console.log("There was an error and data was not posted.");}});}
});
What it does: it is pasted in any website, then it picks any visitors ip address and send that as JSON to my server as variable data.
Problem: the code is working perfectly okay in some sites but not all the sites due to jQuery dependency. And I want to remove this and use pure JavaScript.
I am getting great answers but CORS is not working, there failing them. I am using different domains since the site we are sending data to is hosted on another server.
As mentioned in my commment above, you do not need the first ajax request as you can get this information from the request headers (PHP Example below) from your AJAX request.
To make sure that your website(s) have jQuery loaded you can run a check in your script and load it in dynamically. Using some code from this answer. See below for an example:
// Anonymous "self-invoking" function
(function() {
// Load the script
var script = document.createElement("SCRIPT");
script.src = 'https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js';
script.type = 'text/javascript';
document.getElementsByTagName("head")[0].appendChild(script);
// Poll for jQuery to come into existance
var checkReady = function(callback) {
if (window.jQuery) {
callback(jQuery);
}
else {
window.setTimeout(function() { checkReady(callback); }, 100);
}
};
// Start polling...
checkReady(function($) {
var url = "Url_to my server hosted on a different domain";
var data = {number:"1286", ip: ip_address};
$.ajax({
url: url,
type: "POST",
dataType: 'json',
crossDomain: true,
data: {data: data},
success: function (data) {console.log(JSON.stringify(data));},
error: function (xhr, error) {console.log("There was an error and data was not posted.");
});
});
})();
To get the IP Address from your ajax request: (PHP) Source
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
$ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
$ip = $_SERVER['REMOTE_ADDR'];
}
The annoying part is that you need to do a cross-domain POST to send your data. There's a W3C standard for this called Cross-Origin Resource Sharing (CORS). Check out this tutorial for more info.
You'll want to put this at the bottom of the page. Different browsers handle ready state change events differently, so let's just avoid them.
<script>
// Once the JSONP script loads, it will call this function with its payload.
function getip(ipJson) {
var method = 'POST';
var url = 'URL of your server';
// The XMLHTTPRequest is the standard way to do AJAX. Try to use CORS.
var xhr = new XMLHttpRequest();
if ("withCredentials" in xhr) {
// XHR for Chrome/Firefox/Opera/Safari.
xhr.open(method, url, true);
} else if (typeof XDomainRequest != "undefined") {
// XDomainRequest for IE.
xhr = new XDomainRequest();
xhr.open(method, url);
}
// Create your request body. It has to be form encoded. I'm not sure
// where you get `number` from, so I've hard-coded it.
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xhr.send('number=1286&ip=' + ipJson.ip);
}
</script>
<!-- Get the IP using JSONP so we can skip implementing that. -->
<script type="application/javascript" src="http://www.telize.com/jsonip?callback=getip"></script>
This probably only works in modern browsers, but it should work in most modern browsers.
Replace $.ready(function...) with document.addEventListener('DOMContentLoaded', function..., false).
Replace $.ajax with XMLHttpRequest:
var xhr = new XMLHttpRequest();
//var data = {number:"1286", ip: ip_address};
var data = new FormData();
data.append("number", "1286");
data.append("ip", ip_address); // As stated by Scriptable in the question comments, your server should be able to get it from the request headers.
xhr.onload = function() { console.log(JSON.stringify(this.response)); };
xhr.onerror = function() { console.log("There was an error and data was not posted.") };
xhr.open("POST", "URL to your server");
xhr.send(data);
I need to send a cross domain request using jQuery AJAX. But it is not working in IE9.
The strange thing is, it works fine when I try it in a standalone HTML file. But breaks when done in a CQ page.
The js code is below:
$.support.cors = true;
$.ajax({
cache: false,
url: "https://www.some.external.web.service",
dataType: "json",
contentType: "application/json; charset=utf-8",
type: "POST",
crossDomain: true,
data: "{"key":"value"}",
processData: false,
success: function (response) { alert("success"); },
error: function (xhr, status, error) { alert("AJAX Error:status: "+ status+ "\nerror: " + error + "\nxhr.status: " + xhr.status + "\nResponseText: \n" + xhr.responseText); }
});
I have tried using datatype as 'jsonp' but still no avail. In IE9, it never returns the 'Success' handler and always goes to the 'error' handler.
The error shown is 'Transport Error'.
The webservice is in https and my page can be either http(author) or http(publish)
I already have the $.support.cors = true; set before the ajax. What am I missing ?
I couldn't use JSONP or XDR because of the GET and text content respectively.
For this, I added an iframe in my page whose HTML resides in the client's server. So we post our data to the iframe and the iframe then posts it to the webservice. Hence the cross-domain referencing is eliminated.
We've added a 2-way origin check to confirm only authorized page posts data to and from the iframe.
<iframe style="display:none;" id='receiver' name="receiver" src="https://iframe-address-at-client-server">
</iframe>
//send data to iframe
var hiddenFrame = document.getElementById('receiver').contentWindow;
hiddenFrame.postMessage(JSON.stringify(message), 'https://client-server-url');
//The iframe receives the data using the code:
window.onload = function () {
var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
var eventer = window[eventMethod];
var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";
eventer(messageEvent, function (e) {
var origin = e.origin;
//if origin not in pre-defined list, break and return
var messageFromParent = JSON.parse(e.data);
var json = messageFromParent.data;
//send json to web service using AJAX- same origin now
//return the response back to source
e.source.postMessage(JSON.stringify(aJAXResponse), e.origin);
}, false);
}
Is there a way to add a custom http header into the request done by an <iframe> when changing the source (src) using javascript?
You can have the results of an ajax request that has custom headers be set as the content of an iframe like so:
$.ajax({
type: "GET",
url: "https://app.icontact.com/icp/a/",
contentType: "application/json",
beforeSend: function(xhr, settings){
xhr.setRequestHeader("some_custom_header", "foo");},
success: function(data){
$("#output_iframe_id").attr('src',"data:text/html;charset=utf-8," + escape(data))
}
});
This is assuming the iframe is pointing at a cross domain src. It is simpler if everything is on the same domain.
Edit: Maybe try this variation.
$.ajax({
type: "GET",
url: "https://app.icontact.com/icp/a/",
contentType: "application/json",
beforeSend: function(xhr, settings){
xhr.setRequestHeader("some_custom_header", "foo");},
success: function(data){
$("#output_iframe_id").attr('src',"/")
$("#output_iframe_id").contents().find('html').html(data);
}
});
Rather than using a data URI, or setting the contents to a string, you can use URL.createObjectURL(), and set it as the src of the iframe.
var xhr = new XMLHttpRequest();
xhr.open('GET', 'some.pdf');
xhr.onreadystatechange = handler;
xhr.responseType = 'blob';
xhr.setRequestHeader('Authorization', 'Bearer ' + token);
xhr.send();
function handler() {
if (this.readyState === this.DONE) {
if (this.status === 200) {
// this.response is a Blob, because we set responseType above
var data_url = URL.createObjectURL(this.response);
document.querySelector('#output-frame-id').src = data_url;
} else {
console.error('no pdf :(');
}
}
}
The object URLs are pretty interesting. They're of the form blob:https://your.domain/1e8def13-3817-4eab-ad8a-160923995170. You can actually open them in a new tab and see the response, and they're discarded when the context that created them is closed.
Here's a full example: https://github.com/courajs/pdf-poc
I ended up going with the approach proposed by the other answers here, that use ajax to get the html string and then directly set the contents of the iFrame.
However, I used the approach posted in this answer to actually set the contents of the iFrame, as I found it worked well cross platform with almost all devices I could dig up.
Tested - successful:
Chrome 54 (desktop) ^
Firefox 49 (desktop) ^
IE 11 (desktop) ^
IE 10 (desktop) in emulation mode ^
Safari/Chrome on iOS 8 (ipad)
Chrome on Android 6 (nexus phone)
Edge on Lumia 950 (Win 10 Phone)
^ confirmed that linked css and js in the content run correctly (others not tested)
Tested - unsuccessful:
IE 9 (desktop) in emulation mode
Safari/Chrome on iOS 7 (iPhone)
So putting them together gives something like this (Note: I havn't actually run this exact code):
$.ajax({
type: "GET",
url: "https://yourdomain.com/gethtml",
beforeSend: function(xhr) {
xhr.setRequestHeader("yourheader", "value");
},
success: function(data) {
var iframeDoc = document.querySelector('#myiframe').contentWindow.document;
iframeDoc.open('text/html', 'replace');
iframeDoc.write(data);
iframeDoc.close();
}
});
Here's an example of setting the iFrame contents in this JS Bin
Edit: Here's the html part
<iframe id="myiframe" src="about:blank"></iframe>
Edit 2:
The solution above appears to no longer be working in Firefox (50.1.0) for some unknown reason. Using the solution in this answer I've now changed to code to the example below, which also seems to be more robust:
$.ajax({
type: "GET",
url: "https://yourdomain.com/gethtml",
beforeSend: function(xhr) {
xhr.setRequestHeader("yourheader", "value");
},
success: function(data) {
var iframe = document.getElementById('myiframe');
iframe.contentWindow.contents = data;
iframe.src = 'javascript:window["contents"]';
}
});
The following code works. It is a modification of the code provided by Matthew Graves, modified to use the srcdoc attribute to solve the problem of CSS and JavaScript references not been ran. Unfortunately, it is only working in Chrome.
$.ajax({
type: "GET",
url: "https://app.icontact.com/icp/a/",
contentType: "application/json",
beforeSend: function(xhr, settings){
xhr.setRequestHeader("some_custom_header", "foo");},
success: function(data){
$("#output_iframe_id").attr('srcdoc',data)
}
});
Edit: Finally, I have resolved the issue of the scripts blocks cross-browser, by reassigning them to the iframe on document.ready function:
$(document).ready(function () {
var doc = $(document);
if (frames.length > 0) {
doc = frames[0].document;
$(doc).find('script').each(function () {
var script = document.createElement("script");
if ($(this).attr("type") != null) script.type = $(this).attr("type");
if ($(this).attr("src") != null) script.src = $(this).attr("src");
script.text = $(this).html();
$(doc).find('head')[0].appendChild(script);
$(this).remove();
});
}
});
been having trouble with this script, ive managed to get it working in ie8, works on chrome fine.
initilize: function(){
$('#my_form').submit(function(){
if ($.browser.msie && window.XDomainRequest) {
var data = $('#my_form').serialize();
xdr=new XDomainRequest();
function after_xhr_load()
{
response = $.parseJSON(xdr.responseText);
if(response.number =="incorrect format"){
$('#errors').html('error');
}
else
{
$('#errors').html('worked');
}
}
xdr.onload = after_xhr_load;
xdr.open("POST",$('#my_form').attr('action')+".json");
xdr.send(data);
} else {
$.ajax({
type: "POST",
url: $('#my_form').attr('action')+".json",
data: $('#my_form').serialize(),
dataType: "json",
complete: function(data) {
if(data.statusText =="OK"){
$('#errors').html('error');
}
if(data.statusText =="Created"){
response = $.parseJSON(data.responseText);
$('#errors').html('Here is your code:' +response.code);
}
}
});
}
return false;
});
}
I understand that ie7 does not have the XDomainRequest() object. How can I replicate this in ie7.
Thanks, in advance
You are not going to get that code to work in IE7 since is cross domain calls are not supported in that old browser. You either need to change the backend to do a JSONP call or you need to use a serverside proxy.