28

I've read the other same origin policy topics here on SO, but I haven't seen any solutions related to the local file system.

I have a web app (In a loose sense of the word) that must be local served. I am trying to load a large amount of data in after the user has loaded the page, depending on what they are doing on the webpage. In Firefox 3.5 and IE8 I am able to use jQuery's AJAX() and GetScript() methods to do this, but in Chrome this fails due to the Same Origin Policy.

XMLHttpRequest cannot load file://test/testdir/test.js. Origin null is not allowed by Access-Control-Allow-Origin.

This happens when I do something simple like

$.getScript("test.js");

This functions perfectly well in IE & Firefox.

After reading a bunch about this, I decided to try writing directly into the head of the document. In the console in Chrome I typed the following:

var head = document.getElementsByTagName("head")[0];  
var script =document.createElement('script');   
script.id = 'uploadScript';  
script.type = 'text/javascript';  
script.src = "upload.js";   
head.appendChild(script);

This works fine when pasted in the console- the <script...test.js</script> element is added to the head, evaluated, and content loaded into the DOM.

I thought this was successful, until I put this code into a function call. The same exact code, when called from a function, adds the element to the but does not evaluate the JavaScript file. I can not figure out why. If I use Chrome's console to stop execution in the method that it is adding the element to the and run the above code, it does not evaluate it. However, if I unpause the execution and run the exact same code (pasting it in the console window) it works. I'm at a loss to explain this. Has anyone dealt with this before?

I've read up on the following SO posts, but they are not describing the problem that I have:

Ways to circumvent the same-origin policy
XMLHttpRequest Origin null is not allowed Access-Control-Allow-Origin for file:/// to file:/// (Serverless)
Cross-site XMLHttpRequest

Again, my last resort is to load all the data at the webpage's load- This can cause up to a 10 second delay in loading the webpage that is unnecessary for 90% of the app's users.

Thanks for any suggestions/alternatives!!!

Community
  • 1
  • 1
user210099
  • 1,199
  • 3
  • 14
  • 24

3 Answers3

4

I think I've figured it out.

All I really needed to do was add a callback into my <script> tag. Final code:

I have an element named next... So, in the $("#next").click() function I have the following code. This only gets executed if they click "next".

//remove old dynamically written script tag-    
       var old = document.getElementById('uploadScript');  
   if (old != null) {  
     old.parentNode.removeChild(old);  
     delete old;  
   } 

   var head = document.getElementsByTagName("head")[0];  
   script = document.createElement('script');  
   script.id = 'uploadScript';  
   script.type = 'text/javascript';  
   script.src = 'test/' + scope_dir + '/js/list.js';  
   script.onload = refresh_page;    
   head.appendChild(script);  


function refresh_page(){  
   //perform action with data loaded from the .js file.  
}  

This seems to work, and allows Chrome to dynamically load .js files on the local file system while circumventing the access-control-allow-origin policy I ran into while trying to use jQuery functions.

Yi Jiang
  • 49,435
  • 16
  • 136
  • 136
user210099
  • 1,199
  • 3
  • 14
  • 24
2

Ok, done a lot of fiddling and wasted a lot of time. But I got it figured. The solution in my last answer works fine for Chrome, and for Mozilla. But it does not work for blessed IE, because IE will not fire the onload event: it thinks it has dealt with all the onloads in this file and you can't get it to do another one. However, IE is quite happy to load the file up using the JQuery getScript function (which Chrome will not permit because of the ccess-control-allow-origin policy) -- you will need the JQuery libraries for this to work. So here is what I ended up with:

function getMyText(){
    var url='mylocalfile.js';
    if (jQuery.support.scriptEval) { 
        var old = document.getElementById('uploadScript');  
        if (old != null) {  
             old.parentNode.removeChild(old);  
             delete old;  
            } 
        var head = document.getElementsByTagName("head")[0]; 
        var script = document.createElement('script');
        script.id = 'uploadScript';
        script.type = 'text/javascript';
        script.onload = refresh_page; 
        script.src = url; 
        head.appendChild(script);  
    } else {
       $.getScript(url,function(){
            refresh_page();
      });
     }
}

function refresh_page() {
    alert(mytext);
}

In all this, mylocaltext.js defines all my html as the content of a variable, mytext. Ugly, but it works. jQuery.support.scriptEval is true for intelligent browsers that fire onload events if the DOM changes. IE does not, so that sends it to .getScript; Chrome and others do, so that sends them the other way. Anyway this works on local files.

peter
  • 195
  • 1
  • 1
  • 10
  • Not so fast, folks. This works fine when you are loading just one file at a time. It does NOT work in IE if you are trying to load several files one after another -- that is, you run into synchrony problem depending on your server. Seems OK on a local host, but on a remote server there are unpredictable time lags, and the only way about is really to avoid doing this if you are loading multiple files in IE 7, at least. Nuisance. – peter Feb 03 '11 at 17:55
1

Interesting, but how can I use the same technique to load in a whole HTML file? Similar problem to yours -- I have hundreds of HTML files which I want to include within a web page, depending on what the user wants to see. It seems I can use this technique to load in a whole HTML page, something like:

script.id = 'uploadScript';
script.type = 'text/html';
script.src = url; 
script.onload = refresh_page; 
head.appendChild(script);  

ie, tell it load in HTML. I can see from the console that it is loading it into the page, and I get a message 'Resource interpreted as script but transferred with MIME type text/html'. But I cannot figure out any way to get at the HTML loaded in and held within the script

Yi Jiang
  • 49,435
  • 16
  • 136
  • 136
peter
  • 195
  • 1
  • 1
  • 10
  • Peter, I think you might run into trouble trying to load a HTML page into a – user210099 Jan 25 '11 at 00:28
  • yep, figured that. I can make the content of each html file (or at least the body element) the parameter of a javascript function as explained in http://www.c-point.com/javascript_tutorial/Editor/ajax_tutorial.htm, load the file wrapped in the function, and then have the parameter with all that data passed to the innerHTML of the element I want to populate. Which seems a quite horrid way to do it. ALternatively one might try XMLHttpRequest but I imagine this will hit exactly the same access-control-allow-origin problem. So only way I think is by pretending my html is actually a parameter. – peter Jan 25 '11 at 01:18
  • Sure enough, yes: XMLHttpRequest gives me exactly the same error. And the browsers really don't like getting such a horrendous parameter for a javascript function. Nuisance. It is not a huge amount of data, but it is irritating. – peter Jan 25 '11 at 02:05
  • me again. ok, it does work! have to do this: the source file puts the whole html into a javascript variable, var mytext=" etc etc". Fiddly, you have to make sure there are no " inside the html, and it all has to be on just one line. But if you do that, then all you need to do is say document.getElementById('mydiv').innerHTML=mytext and it all works. In Chrome, Mozilla. don't know about IE. but it should work ok. – peter Jan 25 '11 at 02:20