7

Please consider this javascript:

$.ajax({
    url:'http://ichart.finance.yahoo.com/table.csv?s=GS&a=00&b=1&c=2010&d=08&e=3&f=2012&g=d&ignore=.csv',
    type:'get',
    dataType:'jsonp',
    success:function(data){
        alert(data);
    }
})

The URL returns a .csv file, but I am specifying the jsonp data type because this is a cross-domain ajax request. Without that parameter I get the "origin is not allowed" error.

Since I specify the jsonp data type, the ajax function throws an error because the .csv file is not JSON format. But in the dev console I can see that the browser DOES receive a coherent .csv file. So I know I am successfully receiving the CSV file. I think it should be possible, but I am not sure how to correctly receive this csv file to my ajax function??

Of course if I could make this URL return a correctly formatted JSON string that would be the best, but I am not sure I can do that.

Here is a fiddle where you can try it, you will have to open up the dev console to see that error: http://jsfiddle.net/92uJ4/3/

Any help is greatly appreciated.

Tim

jeffery_the_wind
  • 17,048
  • 34
  • 98
  • 160

2 Answers2

8

Unfortunately, cross-domain restrictions mean that this just isn't going to work. The system is built specifically so that you can't pull arbitrary cross-domain content with AJAX. There isn't any sort of pre-parse method to convert the non-JSONP data you're getting into actual JSONP data (because that would defeat the point of the restrictions).

You're going to have to either make a call to a local server that pulls the data from Yahoo! and sends it to your AJAX request, or find a service of some kind that will pull from an arbitrary URL and return the data as JSONP. As it happens, Yahoo! provides just such a service: YQL (Yahoo query language). See this link for more details.

To accomplish what you're wanting, use the code in this fiddle: http://jsfiddle.net/c5TeM/1/

function get_url(remote_url) {
    $.ajax({
        url: "http://query.yahooapis.com/v1/public/yql?"+
"q=select%20*%20from%20html%20where%20url%3D%22"+
encodeURIComponent(remote_url)+
"%22&format=json",
        type: 'get',
        dataType: 'jsonp',
        success: function(data) {
            alert(data.query.results.body.p);
        },
        error: function(jqXHR, textStatus, errorThrow){
            alert(jqXHR['responseText']);
        }
    })
}
Aprillion
  • 21,510
  • 5
  • 55
  • 89
Joe C.
  • 1,538
  • 11
  • 14
  • THank you for the great information. I was thinking that it was the case that this method of pulling information was not really feasible. Your solution looks great, I was looking at YQL before, I guess that is the way to do it. – jeffery_the_wind Sep 03 '12 at 23:24
  • Does this implementation save anything to the YQL database? or does it just retrieve the data for further manipulation? Thanks @JoeC – PT_C Oct 30 '14 at 16:34
  • @PT_C: As far as I know, it doesn't save anything to the YQL database. It should just be a pass-through. However, since this is a third-party, you can't guarantee that they aren't logging the information that passes through their systems, so I wouldn't use this for anything sensitive. It'd be better to implement your own server-side solution for pulling data in that case. – Joe C. Jan 08 '15 at 19:32
0

Modifying the last provided jsfiddle lead me to the following solution:
http://jsfiddle.net/9zcsxq5a/

var str_parse = function(data){
  data = data.replace(/<[/]*body[^>]*>/g,'');
  data = data.replace(/<--[\S\s]*?-->/g,'');
  data = data.replace(/[\r]+/g,'');
  data = data.replace(/<noscript[^>]*>[\S\s]*?<\/noscript>/g,'');
  data = data.replace(/<script[^>]*>[\S\s]*?<\/script>/g,'');
  data = data.replace(/<script.*\/>/,'');
  return data
}

get_url = function(URL){
  $.ajax({
    url:"http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20html%20where%20url%3D%22"+
    encodeURIComponent(URL)+"%22",
    dataType: "jsonp",
    type: 'get',
    success: function(r){
      data=r.results[0];
      data = str_parse(data);
      data = data.split(/[\n]+/);
    
    //// first line of the csv holds the colnames
      var HEADER = data[0].split(",");
      data.shift();
      
    /// create { OBJECT } structure for each row
        data = (function(){
        var o=[]; 
        data.forEach(function(E){
            o.push( (function(){ 
            var _o={}; 
            for( var i=0, s=E.split(",");i<s.length;i++ ) 
              _o[HEADER[i]]=s[i];
            return _o;
          }()) );
        });
        return o;
      }());
      
    /// THE FINAL OBJECT 
      console.log(data);
      return data;
    }
  }); 
}

$('#a').click(function() {
    get_url("http://ichart.finance.yahoo.com/table.csv?a=8&b=11&e=10&g=d&c=2005&d=2&f=2016&s=YHOO");
});

The csv is passed through, asis and will then be modified to become a json object, similar to the one (but whithout date restrictions) that you will, get when you use

http://query.yahooapis.com/v1/public/yql?q=select%20%2a%20from%20yahoo.finance.historicaldata%20where%20symbol%20in%20%28%27YHOO%27%29%20and%20startDate%20=%20%272009-09-11%27%20and%20endDate%20=%20%272010-03-10%27&diagnostics=true&env=store://datatables.org/alltableswithkeys

Community
  • 1
  • 1