Totomobile
Totomobile

Reputation: 663

Soundcloud HTML5 API not working with Facebook JS

I'm trying to set up the SC html 5 api located here:

http://w.soundcloud.com/player/api.js

However it is throwing a "c is undefined" error (7 times) in Firebug.

After a bit of digging it seems that the these errors only show up if I am loading the Facebook JS asynchronously like this:

(function(d, s, id) {
  var js, fjs = d.getElementsByTagName(s)[0];
  if (d.getElementById(id)) return;
  js = d.createElement(s); js.id = id;
  js.src = "//connect.facebook.net/en_US/all.js#xfbml=1&appId=137624476258287";
  fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));

The api.js and the facebook.js both seem to be using function wrappers, yet FB is causing soundcloud to error out.


I've added my solution below, also this error might show up not just for Facebook, but for any application that uses HTML5 messaging, so this is a general fix for all those as well.

Upvotes: 2

Views: 1193

Answers (2)

Totomobile
Totomobile

Reputation: 663

Well I decided to dig a little deeper, and have found the solution (and the cause) of this issue.

First, I used the jsbeutifier (http://jsbeautifier.org/) to get the code in a more readable format. The error was coming from a function called D. This function was being added as a handler to the HTML5 message listener:

    window.addEventListener ? window.addEventListener("message", parseMessage, !1) : window.attachEvent("onmessage", parseMessage); 

(I have renamed D to parseMessage here)

Next, if you look in the D (parseMessage) function, we see that code attempts to parse the message without checking the origin.

The problem is, Facebook also sends messages to the "message" handler! You can see this if you print out all messages, all of the errors are actually the SC api attempting to parse Facebook messages!

The solution is to check the origin before parsing the message (as described in the Opera HTML5 dev site: http://dev.opera.com/articles/view/window-postmessage-messagechannel/)

Here is the fixed "D" function:

function D(a) {
        var b, c, d, e;

        if(a.origin == 'http://w.soundcloud.com'){
            try {
                c = JSON.parse(a.data)
            } catch (f) {
                console.log(f);
            }

            b = y(a.source);
            d = c.method;
            e = c.value;
            d === i.READY && (b ? (b.isReady = !0, C(b, k), v(k, b)) : m.push(a.source));
            if (!b || a.origin !== b.domain) return !1;
            var g = [];
            e !== undefined && g.push(e), C(b, d, g)
        }
    }

Or the whole um-ninified solution: http://jsfiddle.net/6uREk/1/

thanks T

Upvotes: 7

Oren Roth
Oren Roth

Reputation: 152

found a solution!

just load the soundcloud api asyc with delay and no error will eccour.. (weird bug BTW :/)

<script>
setTimeout(function(){

(function(d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s); js.id = id;
js.src = "http://w.soundcloud.com/player/api.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'sc'));
},2000);

(function(d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/all.js#xfbml=1&appId=137624476258287";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
</script>

Upvotes: 1

Related Questions