Search code examples
javascriptjquerycorsblogs

How to integrate CORS, Google Blog and JavaScript?


I have a working JavaScript on a web page that gets my blog from a blog site and displays it in a sidebar on my web page. In other words I blog in one place, but also display my blog content in another place (my web page).

The script uses Cross Origin Sharing (CORS) and looks like this:

$(
  function () {
    $.get(
     'http://www.corsproxy.com/my_name.soup.io/rss/original',
     function (data) {
      var items = data.getElementsByTagName('item');
      var thoughts = $('#activity ul');
      var count = 0;
      $(items).each(function (i, e) {
        count++;
        if (count > 10) return;
        thoughts.append('<li>'
          + e.getElementsByTagName('description')[0].textContent
          + '<small>' 
          + $.timeago( new Date(e.getElementsByTagName('pubDate')[0].textContent) )
          + '</small></li>');
     });
    }, 'xml'
   );
  }
);

I want to move my blog to Google blogging and have an account URL that looks like this: http://my_name.blogspot.com/feeds/posts/default

But I think I still need to invoke CORS so that the JavaScript on the web site can cross domains to the Google site. I have tried using the Google URL directly but the script does not get the content.

How should I change the JavaScript so that my web page running the JavaScript will display the content from the Google blog?

As an aside: using the same JavaScript, I am able to display content (the title of the commit) from my Github account on my web page. In this case I do not use CORS; the following JavaScript works as expected:

$.getScript(
  '/public/bin/jquery.timeago.js',
  function () {
    $.getScript(
      '/public/bin/jquery.github-activity.js',
      function () {
        $("#gh-activity ul").githubActivityFor("my_name", { limit: 10 });
      }
    );
  }
);

Why does the Github get work without using CORS?

Can I reconfigure the get for the Google blog to act in the same way as get for my Github account?


Solution

  • Examining the code for the githubActivityFor call, we see:

    $.get('https://api.github.com/users/' + username + '/events?callback=?', function(activity) {
        ...
    },
    "jsonp");
    

    The "jsonp" argument tells jQuery that that JSONP is being used here, and the resource should be loaded inside of <script> tag instead of fetched with Ajax. Sure enough, we we actually look at a user's activity feed from that URL template, it's a script. jQuery can therefore perform a JSONP script load in the usual way:

    • storing the callback function (i.e., the second argument) in a variable with a random, long name like jQuery35758395
    • replacing the ? in callback=? with the same value (e.g., jQuery35758395)
    • loading the script resource in a <script> tag

    The Github resource (like any traditional JSONP server-side endpoint) is set up to use value of the callback parameter in a function call in the beginning of the script (e.g., jQuery35758395({ 'some': 'data' }). When script runs, the function call is executed, and it triggers the randomly-named callback we set up before the fetch.

    Turns out Blogger supports JSONP on their server already. If you visit http://foobar.blogspot.com/feeds/posts/default?callback=foobaz you'll see the feed data wrapped inside of a function call. To take advantage of this, simply perform your $.get with a callback=? parameter:

    $.get(
         'http://my_name.blogspot.com/feeds/posts/default?callback=?',
         function (data) {
             ...
         },
         "jsonp");
    

    This will automatically do JSONP behind the scenes and correctly invoke your callback function with the XML string. Unfortunately, the string won't be parsed into a DOM structure for you already, but the jQuery function (a.k.a., $) can parse the data string for you:

    var feedDOM = $(data).get(1);
    

    The get call pulls the DOM structure out of the jQuery object, but you can also keep it in the jQuery object and use jQuery functions to examine it. Alternatively, you can supply the XML string as a context argument for a jQuery selector:

    var authorTags = $("author", data);