I'm developing a JavaScript API service. Main html page looks like this:
<html>
<head>
<script type="text/javascript" src="scripts/logic.js"></script>
<script type="text/javascript" src="scripts/jquery-1..."></script>
<script type="text/javascript" src="http://mydomain/api/main.js"></script>
</head>
...
</html>
In the main.js script I load another script from mydomain. I'm doing it by adding script tag ([script.. src="http://mydomain/api/getsomedata.js?callback_id=3434&someparams=..."]). Loaded script imediatly calls API callback function: MyApi.processCallback(...). Everything works ok.
But when I'm trying to load another mydomain script from local file (logic.js), I recive very strange situation: all script global objects are undefined. There is no MyApi object or jQuery $ object which were visible during previous call. So I can't call MyApi callback function.
Perhaps it is because of security restrictions. Anti-XSS, or something similar. I tried to add a X-XSS-Protection header, like in all Google JavaScript APIs. But it did not help.
I don't use IFRAMES.
The problem can be solved exactly, since many cross-site JavaScript API's are working (Google Maps API, etc.) on the same idea.
What is happening in your script?
If you are doing Ajax calls back to the domain, your script will fail with a Same Origin security error. If you need to do communication with your server from another domain, than you need to use JSONP to do it. If you are working with only modern day browser you can get away with CORS.
Related
at first: sorry for my bad english...
also im new in js, css, html, jquery, phonegap etc.
Cross domain should not be a problem because PhoneGap is a file base (file:///) where such restriction doesn't apply, right?
i know, that i need to whitelist the server in my config.xml like here
http://docs.build.phonegap.com/en_US/configuring_access_elements.md.html#Access%20Elements
but what is the best way to do it? A simple httprequest? A Plugin? ajax ?(I've haerd that ajax isnt good at file:/// requests).... i shall not
use
a proxy
JSONP
CORS (Cross-origin ressource sharing)
here you can see how the html code from the server will look like:
<html>
<head>
<title>Memorycards</title>
<link rel="stylesheet" href="/stylesheets/style.css">
</head>
<body>
<h1>Memorycards</h1>
<p>here are all Memorycards
<li>memory1</li>
<li>memory2</li>
</p>new Memorycard <br>
</body>
</html>
i want to put the names (memory1, memory2) in a list and the links (link1, link2) into another list.
Hope you guys can help me!
Something I've done in the past in ASP.NET is wrap all external json/xml requests with a local resource (like a proxy). It makes the connection and simply returns the result which then you can use any javascript based application and bypass using jsonp.
Javascript <-> Local App <-> Remote Resource
For example, lets say you need to access the results on http://remotehost.com/app.php. What you can do is write a local application that gets deployed with your javascript (let's call it remoteapp.php) that simply calls this resource and echos the response. You then simply call remoteapp.php via your javascript using a simple ajax GET and you have the results of http://remotehost.com/app.php.
Given your limitations of not being able to use CORS and probably not wanting to rely on another application for XSS (corsproxy.com) this seems like your best bet.
I'm developing a small application with HTML, CSS, Javascript, JQuery and JQTouch.
This is a LOCAL application. I've an index.html with some div's. When I click on a link in this file, I want to load HTML code of page1.html (same folder) and insert into a div of index.html the tag that I want of page1.html.
Example: Inject the content of (page1.html) into (index.html).
I try: http://api.jquery.com/load/
$('#loadContent').load('page1.html #test');
And the content of loadContent doesn't change. I include JQuery script into index.html...
I try http://api.jquery.com/html/ too, but I think it connect to the server.
Any idea? Thanks!
Make sure you're calling it after loadContent has been created. The following will run your load code when the document is ready to be written to.
$(function() {
$('#loadContent').load('page1.html #test');
});
Or you could run a local server. If you have python you can go to your directory with the files and run python -m SimpleHTTPServer for python 2.7 or python -m http.server for python 3.x
Most browsers will, by default, block this on a local file system as a security precaution. Have you tried it on a remote server?
I dont know much on jQuery. But still, you can do this, by loading the page1.html to a hidden iframe, then get the document.body.innerHTML of this page, and then append that node to the div you need. Its only HTML DOM in JavaScript.
But performance base, loading an iframe is always a costly one. This would do your job. However there may be many solutions in jQuery or other libraries, Sorry i don't know much on it.
It sounds like the problem is that the jQuery library isn't loading when you're running on localhost, or the AJAX request is failing for the same reason. This is due to protection built into the browser to prevent cross-site scripting.
See this "additional note" from the documentation for load:
Due to browser security restrictions, most "Ajax" requests are subject to the same origin policy; the request can not successfully retrieve data from a different domain, subdomain, or protocol.
If you use any AJAX, you'll have to run this on a local web server. In which case you should just run this page from your local webserver rather than from the filesystem. Then you won't need any workarounds.
If you're on Windows, you could use UniServer.
If you aren't going to use any AJAX whatsoever (aren't using load), then you could write your code so that it falls back to a local version of jQuery if the remote version didn't load.
Here's an example of how, grabbed from this page:
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
<script>!window.jQuery && document.write('<script src="/Scripts/lib/jquery/jquery-1.4.4.min.js"></script>'))</script>
<script src="//ajax.aspnetcdn.com/ajax/jquery.validate/1.7/jquery.validate.min.js"></script>
<script>!window.jQuery.validator && document.write('<script src="/Scripts/lib/jquery/jquery.validate.min.js"></script>')</script>
<script src="//ajax.aspnetcdn.com/ajax/mvc/3.0/jquery.validate.unobtrusive.min.js"></script>
<script>!window.jQuery.validator.unobtrusive && document.write('<script src="/Scripts/lib/jquery/jquery.validate.unobtrusive.min.js"></script>')</script>
I have javascript file, located on one domain, e.g:
http://mydomain.com/script.js
Some pages (from other domains) include my javascript using SCRIPT tag. They can include it via http or https
<script src="http://mydomain.com/script.js"></script>
or
<script src="https://mydomain.com/script.js"></script>
Also they can include my script using 3rdparty iframes, e.g:
<iframe src="http://3rdparty.com/frame.php">
where http://3rdparty.com/frame.php outputs
<script src="http://mydomain.com/script.js"></script>
or
<script src="https://mydomain.com/script.js"></script>
I can edit only static javascript file script.js on mydomain.com.
How I can detect what protocol used to load my javascript (https://mydomain.com/script.js or http://mydomain.com/script.js)?
You can use a protocol relative URL:
<script src="//mydomain.com/script.js"></script>
You can use this:
document.location.protocol + "//mydomain.com/script.js"
I do not believe that you have any ability to identify within the code how it has been loaded. The best suggestion I can come up with is to have the http and https point to different locations ( i.e. be different sites ) and have something within the code that indicates which one is being picked up.
var protocol='http'
or
var protocol='https'
It does mean maintaining two files, and two sites though.
ETA: I thought James Wiseman had the answer, but of course that will only return the protocol of the PAGE, not the SCRIPT. If you know these are related, that would work ( often the https is loaded on https pages and vv ). But it is not definitive.
It is a good solution if you can be confident that the protocol on hte page is the same as on the script.
So I'm totally new to this, but jsonp seemed so simple, I'm just trying to make a web app using dashcode. I need to put twitter json data on a page of my web app. This is what I tried.
I put this code in index.html
<script src="http://twitter.com/users/USERNAME.json?callback=handleResponse"/>
Then I created a javascript file
function handleResponse(responseJson){
alert(responseJson.status.text);
}
When I put the javascript file as the datasource I get an error saying it is not valid JSON or XML. As I said I am new to this, so I might be doing it completely wrong.
You code works, at least in Chrome, with one small tweak - see http://jsfiddle.net/nrabinowitz/jJTQn/1/
<script type="text/javascript">
function handleResponse(responseJson){
alert(responseJson.status.text);
}
</script>
<script type="text/javascript"
src="http://twitter.com/users/Pogue.json?callback=handleResponse"></script>
The small tweak is closing the script tag properly (script tags can't be self-closing, for reasons I'm apparently too lazy to Google). Wouldn't hurt to throw type="text/javascript" in there too.
You need to make sure the handleResponse function is defined before the external jsonp call.
(Also your script tag is invalid)
<script>
function handleResponse(responseJson){
alert(responseJson.status.text);
}
</script>
<script src="http://twitter.com/users/USERNAME.json?callback=handleResponse"></script>
Click on “Widget Attributes” in the left-hand source pane. Under “Network / Disk Access”, make sure that “Allow Network Access” is checked. Without this checked your widget won’t be able to make any AJAX requests.
Previously, Google's Friend Connect required users to upload a couple of files to their websites to enable cross domain communication and Facebook Connect still requires you to upload a single file to enabled it.
Now, Friend Connect doesn't require any file upload... I was wondering how they were able to accomplish this.
Reference:
http://www.techcrunch.com/2009/10/02/easy-does-it-google-friend-connect-one-ups-facebook-connects-install-wizard/
There are multiple methods of communicating between documents on different domains, amongst these HTML5 postMessage, NIX, FIM(hash/fragment), frameElement and by using the window.name property.
These are available on different browsers and in different versions, but collectively they allow you to do reliable XDM (cross domain messaging).
One project that have done this earlier is Apache Shindig, which probably pioneered quite a few of these, and more recently, the project easyXDM has come, unifying all of these approaches with a common API, making it easy to create complex applications using XDM and RPC.
You can read in depth about the various methods of transporting the data in this article at Script Junkie.
Now, to answer your question directly, earlier on it was quite common to believe that there was only postMessage, the FIM (Fragment Identifier Messaging) available, and for the latter to work efficiently, one often had to upload a special file to your domain. As more methods have been discovered, this has by many been deprecated as a technique, and hence; no more need for the file.
Just for the record; I'm the author of both the Script Junkie article, and the easyXDM library (that is what Twitter, Disqus and quite a few more are using by the way).
<edit>It's difficult to remember/verify now, but I believe my answer here was probably incorrect. Sean Kinsey's answer above should be the definitive answer to this question. If you're reading this, please upvote his answer and ignore mine.</edit>
The Google Friend Connect widget works like most ads/gadgets do, using a copy/pasted snippet of HTML to reference a JavaScript include on the host's server which then creates an iframe containing the desired content. By opening the iframe with your site ID in the URL, Google's server is able to generate the appropriate HTML document to represent a Friend Connect gadget for your particular site/settings.
There isn't any cross-site communication happening beyond that initial step of creating an iframe with the appropriate URL target. Everything inside the gadget's dynamically generated iframe is more like the user visited a separate page on Google's server, but what would have been displayed is then embedded/isolated in a block on your page instead.
I'm not sure how it works in this particular instance but cross-domain messaging can be accomplished either by the postMessage() API or by changing the hash part of the URL and monitoring that.
The hash change method works because both the enclosing and the enclosed pages have access to the enclosed page's URL.
Of course, hopefully the postMessage() API call becomes more standard over time.
JSON allows cross-domain javascript.
Due to browser security restrictions,
most "Ajax" requests are subject to
the same origin policy; the request
can not successfully retrieve data
from a different domain, subdomain,
or protocol.
Script and JSONP
requests are not subject to the same
origin policy restrictions.
There is no other method than using the somewindow.postMessage(); for communication between cross-domain iframes.
Before somewindow.postMessage() you had to upload file in order to ensure that you can establish communication between iframes.
example:
<html>
<!-- this is main domain www.example.com -->
<head>
</head>
<body>
<iframe src="http://www.exampleotherdomain.com/">
<script>
function sendMsg(a) {
var f = document.createElement('iframe'),
k = document.getElementById('ifr');
f.setAttribute('src', 'http://www.example.com/xdreciver.html#myValueisSent');
k.appendChild(f);
k.removeChild(f);
}
</script>
<div id="ifr"></div>
</iframe>
</body>
</html>
now the http://www.example.com/xdreciver.html html content :
<html>
<!-- this is http://www.example.com/xdreciver.html -->
<head>
<script>
function getMsg() {
return window.location.hash;
}
</script>
</head>
<body onload="var msg = getMsg(); alert(msg);">
</body>
</html>
As for using the .postMessage(); its enough to use top.postMessage('my message to other domain document, which is also the main document', 'http://www.theotherdomain.com');