From 2bc7906400406a8f4a3270c22bb8c82669d69dc0 Mon Sep 17 00:00:00 2001 From: Sean Creeley Date: Wed, 11 Dec 2013 16:14:47 -0500 Subject: [PATCH] Adds a Receiver and fixes a few things to bring it closer to the Spec --- Gruntfile.js | 7 +- README.rst | 4 +- package.json | 2 +- src/core.js | 27 ++++--- src/keeper.js | 28 +++---- src/player.js | 100 ++++++++++++++----------- src/receiver.js | 191 +++++++++++++++++++++++++++++++++++++++++++++++ test/iframe.html | 1 + test/mock.js | 138 ++++++++++++++++------------------ test/test.js | 18 +++-- 10 files changed, 365 insertions(+), 151 deletions(-) create mode 100644 src/receiver.js diff --git a/Gruntfile.js b/Gruntfile.js index 1d58a22..e51a09e 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -55,11 +55,14 @@ module.exports = function(grunt) { ' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */\n' }, local: { - src: ['src/core.js', 'src/keeper.js', 'src/player.js'], + src: ['src/core.js', 'src/keeper.js', 'src/player.js', 'src/receiver.js'], dest: 'dist/player.js' }, release: { - src: ['src/intro.js', 'src/core.js', 'src/keeper.js', 'src/player.js', 'src/outro.js'], + src: [ + 'src/intro.js', 'src/core.js', 'src/keeper.js', + 'src/player.js', 'src/receiver.js', 'src/outro.js' + ], dest: 'dist/player-<%= pkg.version %>.js' } }, diff --git a/README.rst b/README.rst index 81c3e82..256a730 100644 --- a/README.rst +++ b/README.rst @@ -36,9 +36,9 @@ player object. However, the player will internally queue messages until ready is called. :: - var player = Player('iframe'); + var player = new playerjs.Player('iframe'); - player.on(Player.Events.PLAY, function( + player.on(playerjs.Events.PLAY, function( console.log('play'); )); diff --git a/package.json b/package.json index 41409db..7fbd8fe 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "title": "Player.js", "name": "Player.js", - "version": "0.0.2", + "version": "0.0.3", "homepage": "http://github.com/embedly/player.js", "author": { "name": "Embedly" diff --git a/src/core.js b/src/core.js index a6cd835..399f3cf 100644 --- a/src/core.js +++ b/src/core.js @@ -1,12 +1,12 @@ -var playjs = {}; +var playerjs = {}; -playjs.DEBUG = false; -playjs.POST_MESSAGE = !!window.postMessage; +playerjs.DEBUG = false; +playerjs.POST_MESSAGE = !!window.postMessage; /* * Utils. */ -playjs.origin = function(url){ +playerjs.origin = function(url){ // Grab the origin of a URL if (url.substr(0, 2) === '//'){ url = window.location.protocol + url; @@ -15,7 +15,7 @@ playjs.origin = function(url){ return url.split('/').slice(0,3).join('/'); }; -playjs.addEvent = function(elem, type, eventHandle) { +playerjs.addEvent = function(elem, type, eventHandle) { if (!elem) { return; } if ( elem.addEventListener ) { elem.addEventListener( type, eventHandle, false ); @@ -28,19 +28,24 @@ playjs.addEvent = function(elem, type, eventHandle) { // usage: log('inside coolFunc',this,arguments); // http://paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/ -playjs.log = function(){ - playjs.log.history = playjs.log.history || []; // store logs to an array for reference - playjs.log.history.push(arguments); - if(window.console && playjs.DEBUG){ +playerjs.log = function(){ + playerjs.log.history = playerjs.log.history || []; // store logs to an array for reference + playerjs.log.history.push(arguments); + if(window.console && playerjs.DEBUG){ window.console.log( Array.prototype.slice.call(arguments) ); } }; // isFunctions -playjs.isString = function (obj) { +playerjs.isString = function (obj) { return Object.prototype.toString.call(obj) === '[object String]'; }; -playjs.isNone = function(obj){ +playerjs.isObject = function(obj){ + return Object.prototype.toString.call(obj) === "[object Object]"; +}; + + +playerjs.isNone = function(obj){ return (obj === null || obj === undefined); }; \ No newline at end of file diff --git a/src/keeper.js b/src/keeper.js index de82b5e..c399e0d 100644 --- a/src/keeper.js +++ b/src/keeper.js @@ -1,17 +1,17 @@ -/*globals playjs:true*/ +/*globals playerjs:true*/ /* * Keeper is just a method for keeping track of all the callbacks. */ -playjs.Keeper = function(){ +playerjs.Keeper = function(){ this.init(); }; -playjs.Keeper.prototype.init = function(){ +playerjs.Keeper.prototype.init = function(){ this.data = {}; }; -playjs.Keeper.prototype.getUUID = function(){ +playerjs.Keeper.prototype.getUUID = function(){ // Create a random id. #http://stackoverflow.com/a/2117523/564191 return 'listener-xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function(c) { var r = Math.random()*16|0, v = c === 'x' ? r : (r&0x3|0x8); @@ -19,12 +19,12 @@ playjs.Keeper.prototype.getUUID = function(){ }); }; -playjs.Keeper.prototype.has = function(event, id){ +playerjs.Keeper.prototype.has = function(event, id){ if (!this.data.hasOwnProperty(event)){ return false; } - if (playjs.isNone(id)){ + if (playerjs.isNone(id)){ return true; } @@ -40,7 +40,7 @@ playjs.Keeper.prototype.has = function(event, id){ return false; }; -playjs.Keeper.prototype.add = function(id, event, cb, ctx, one){ +playerjs.Keeper.prototype.add = function(id, event, cb, ctx, one){ var d = { id: id, event: event, @@ -56,7 +56,7 @@ playjs.Keeper.prototype.add = function(id, event, cb, ctx, one){ } }; -playjs.Keeper.prototype.execute = function(event, id, data){ +playerjs.Keeper.prototype.execute = function(event, id, data){ if (!this.has(event, id)){ return false; } @@ -67,7 +67,7 @@ playjs.Keeper.prototype.execute = function(event, id, data){ for (var i=0; i< this.data[event].length; i++){ var d = this.data[event][i]; - if (!playjs.isNone(id) && d.id !== id){ + if (!playerjs.isNone(id) && d.id !== id){ continue; } @@ -96,15 +96,15 @@ playjs.Keeper.prototype.execute = function(event, id, data){ } }; -playjs.Keeper.prototype.on = function(id, event, cb, ctx){ +playerjs.Keeper.prototype.on = function(id, event, cb, ctx){ this.add(id, event, cb, ctx, false); }; -playjs.Keeper.prototype.one = function(id, event, cb, ctx){ +playerjs.Keeper.prototype.one = function(id, event, cb, ctx){ this.add(id, event, cb, ctx, true); }; -playjs.Keeper.prototype.off = function(event, cb){ +playerjs.Keeper.prototype.off = function(event, cb){ // We should probably restructure so this is a bit less of a pain. var listeners = []; @@ -118,9 +118,9 @@ playjs.Keeper.prototype.off = function(event, cb){ for (var i=0; i< this.data[event].length; i++){ var data = this.data[event][i]; // If we only keep if there was a CB and the CB is there. - if (!playjs.isNone(cb) && data.cb !== cb) { + if (!playerjs.isNone(cb) && data.cb !== cb) { keep.push(data); - } else if (!playjs.isNone(data.id)) { + } else if (!playerjs.isNone(data.id)) { listeners.push(data.id); } } diff --git a/src/player.js b/src/player.js index ea2715f..2fc2561 100644 --- a/src/player.js +++ b/src/player.js @@ -1,15 +1,15 @@ -/*globals playjs:true*/ +/*globals playerjs:true*/ /* * Player.js is a javascript library for interacting with iframes via * postMessage that use an Open Player Spec * */ -playjs.Player = function(elem, options){ +playerjs.Player = function(elem, options){ this.init(elem, options); }; -playjs.Player.EVENTS = { +playerjs.EVENTS = { PLAY: 'play', PAUSE: 'pause', ENDED: 'ended', @@ -19,36 +19,55 @@ playjs.Player.EVENTS = { ERROR: 'error' // Not implemented yet. }; -playjs.Player.prototype.init = function(elem, options){ - - if (playjs.isString(elem)){ +playerjs.METHODS = [ + 'play', + 'pause', + 'getPaused', + 'mute', + 'unmute', + 'getMuted', + 'setVolume', + 'getVolume', + 'getDuration', + 'setCurrentTime', + 'getCurrentTime', + 'setLoop', + 'getLoop', + 'removeEventListener', + 'addEventListener' +]; + + +playerjs.Player.prototype.init = function(elem, options){ + + if (playerjs.isString(elem)){ elem = document.getElementById(elem); } this.elem = elem; // Figure out the origin of where we are sending messages. - this.origin = playjs.origin(elem.src); + this.origin = playerjs.origin(elem.src); // Event handling. - this.keeper = new playjs.Keeper(); + this.keeper = new playerjs.Keeper(); // Queuing before ready. this.isReady = false; this.queue = []; - if (playjs.POST_MESSAGE){ + if (playerjs.POST_MESSAGE){ // Set up the reciever. var self = this; - playjs.addEvent(window, 'message', function(e){ + playerjs.addEvent(window, 'message', function(e){ self.receive(e); }); } else { - playjs.log('Post Message is not Available.'); + playerjs.log('Post Message is not Available.'); } }; -playjs.Player.prototype.send = function(data, callback, ctx){ +playerjs.Player.prototype.send = function(data, callback, ctx){ // We are expecting a response. if (callback) { // Create a UUID @@ -61,19 +80,19 @@ playjs.Player.prototype.send = function(data, callback, ctx){ this.keeper.one(id, data.method, callback, ctx); } - if (!this.isReady && data.event !== 'ready'){ - playjs.log('Player.queue', data); + if (!this.isReady && data.value !== 'ready'){ + playerjs.log('Player.queue', data); this.queue.push(data); return false; } - playjs.log('Player.send', data, this.origin); + playerjs.log('Player.send', data, this.origin); this.elem.contentWindow.postMessage(JSON.stringify(data), this.origin); return true; }; -playjs.Player.prototype.receive = function(e){ - playjs.log('Player.receive', e); +playerjs.Player.prototype.receive = function(e){ + playerjs.log('Player.receive', e); if (e.origin !== this.origin){ return false; @@ -98,7 +117,7 @@ playjs.Player.prototype.receive = function(e){ }; -playjs.Player.prototype.ready = function(){ +playerjs.Player.prototype.ready = function(){ if (this.isReady === true){ return false; @@ -111,7 +130,7 @@ playjs.Player.prototype.ready = function(){ for (var i=0; i 0) { for (var i in listeners){ this.send({ method: 'removeEventListener', - event: event, + value: event, listener: listeners[i] }); return true; @@ -159,90 +178,85 @@ playjs.Player.prototype.off = function(event, callback){ return false; }; -playjs.Player.prototype.play = function(){ +playerjs.Player.prototype.play = function(){ this.send({ method: 'play' }); }; -playjs.Player.prototype.pause = function(){ +playerjs.Player.prototype.pause = function(){ this.send({ method: 'pause' }); }; -playjs.Player.prototype.getPaused = function(callback, ctx){ +playerjs.Player.prototype.getPaused = function(callback, ctx){ this.send({ method: 'getPaused' }, callback, ctx); }; -playjs.Player.prototype.mute = function(){ +playerjs.Player.prototype.mute = function(){ this.send({ method: 'mute' }); }; -playjs.Player.prototype.unmute = function(){ +playerjs.Player.prototype.unmute = function(){ this.send({ method: 'unmute' }); }; -playjs.Player.prototype.getMuted = function(callback, ctx){ +playerjs.Player.prototype.getMuted = function(callback, ctx){ this.send({ method: 'getMuted' }, callback, ctx); }; -playjs.Player.prototype.getVolume = function(callback, ctx){ +playerjs.Player.prototype.getVolume = function(callback, ctx){ this.send({ method: 'getVolume' }, callback, ctx); }; -playjs.Player.prototype.setVolume = function(value){ +playerjs.Player.prototype.setVolume = function(value){ this.send({ method: 'setVolume', value: value }); }; -playjs.Player.prototype.getDuration = function(callback, ctx){ +playerjs.Player.prototype.getDuration = function(callback, ctx){ this.send({ method: 'getDuration' }, callback, ctx); }; -playjs.Player.prototype.setCurrentTime = function(value){ +playerjs.Player.prototype.setCurrentTime = function(value){ this.send({ method: 'setCurrentTime', value: value }); }; -playjs.Player.prototype.getCurrentTime = function(callback, ctx){ +playerjs.Player.prototype.getCurrentTime = function(callback, ctx){ this.send({ method: 'getCurrentTime' }, callback, ctx); }; -playjs.Player.prototype.setLoop = function(value){ +playerjs.Player.prototype.setLoop = function(value){ this.send({ method: 'getLoop', value: value }); }; -playjs.Player.prototype.getLoop = function(callback, ctx){ +playerjs.Player.prototype.getLoop = function(callback, ctx){ this.send({ method: 'getLoop' }, callback, ctx); }; - - -//Set the global player. -window.Player = function(elem, options){ - return new playjs.Player(elem, options); -}; +window.playerjs = playerjs; diff --git a/src/receiver.js b/src/receiver.js new file mode 100644 index 0000000..fa4b956 --- /dev/null +++ b/src/receiver.js @@ -0,0 +1,191 @@ +/*globals playerjs:true*/ +/* +* Does all the wiring up for the backend. +* +* var receiver = new playerjs.Receiver(); +* receiver.on('play', function(){ video.play() }); +* receiver.on('getDuration', function(callback){ callback(video.duration) }); +* receiver.emit('timeupdate', {}); +*/ + +playerjs.Receiver = function(){ + this.init(); +}; + +playerjs.Receiver.prototype.init = function(){ + var self = this; + + // Deal with the ready crap. + this.isReady = false; + + // Bind the window message. + this.origin = playerjs.origin(document.referrer); + + //Create a holder for all the methods. + this.methods = {}; + + // Deals with the adding and removing of event listeners. + this.eventListeners = {}; + + // We can't send any messages. + this.reject = !(window.self !== window.top && playerjs.POST_MESSAGE); + + // We aren't in an iframe, don't listen. + if (!this.reject){ + playerjs.addEvent(window, 'message', function(e){ + self.receive(e); + }); + } +}; + +playerjs.Receiver.prototype.receive = function(e){ + // Only want to listen to events that came from our origin. + if (e.origin !== this.origin){ + return false; + } + + // Browsers that support postMessage also support JSON. + var data = {}; + if (playerjs.isObject(e.data)){ + data = e.data; + } else { + try { + data = window.JSON.parse(e.data); + } catch (err){ + playerjs.log('JSON Parse Error', err); + } + } + + playerjs.log('Receiver.receive', e, data); + + // Nothing for us to do. + if (!data.method){ + return false; + } + + // Make sure we have a valid method. + if (playerjs.METHODS.indexOf(data.method) === -1){ + this.emit('error', { + code: 2, + msg: 'Invalid Method "'+data.method+'"' + }); + return false; + } + + // See if we added a listener + var listener = !playerjs.isNone(data.listener) ? data.listener : null; + + // Add Event Listener. + if (data.method === 'addEventListener') { + if (this.eventListeners.hasOwnProperty(data.value)) { + //If the listener is the same, i.e. null only add it once. + if (this.eventListeners[data.value].indexOf(listener) > -1){ + this.eventListeners[data.value].push(listener); + } + } else { + this.eventListeners[data.value] = [listener]; + } + + if (data.value === 'ready' && this.isReady){ + this.ready(); + } + } + // Remove the event listener. + else if (data.method === 'removeEventListener') { + if (this.eventListeners.hasOwnProperty(data.value)) { + var index = this.eventListeners[data.value].indexOf(listener); + + // if we find the element, remove it. + if (index > -1){ + this.eventListeners[data.value].splice(index, 1); + } + + if (this.eventListeners[data.value].length === 0){ + delete this.eventListeners[data.value]; + } + } + } + // Go get it. + else { + this.get(data.method, data.value, listener); + } +}; + +playerjs.Receiver.prototype.get = function(method, value, listener){ + var self = this; + + // Now lets do it. + if (!this.methods.hasOwnProperty(method)){ + this.emit('error', { + code: 3, + msg: 'Method Not Supported"'+method+'"' + }); + return false; + } + + var func = this.methods[method]; + + if (method.substr(0,3) === 'get') { + var callback = function(val){ + self.send(method, val, listener); + }; + func.call(this, callback); + } else { + func.call(this, value); + } +}; + +playerjs.Receiver.prototype.on = function(event, callback){ + this.methods[event] = callback; +}; + +playerjs.Receiver.prototype.send = function(event, value, listener){ + + playerjs.log('Receiver.send', event, value, listener); + + if (this.reject){ + // We are not in a frame, or we don't support POST_MESSAGE + playerjs.log('Receiver.send.reject', event, value, listener); + return false; + } + var data = { + event: event + }; + + if (!playerjs.isNone(value)){ + data.value = value; + } + + if (!playerjs.isNone(listener)){ + data.listener = listener; + } + + var msg = JSON.stringify(data); + window.parent.postMessage(msg, this.origin === "" ? '*' : this.origin); +}; + +playerjs.Receiver.prototype.emit = function(event, value){ + + if (!this.eventListeners.hasOwnProperty(event)){ + return false; + } + + playerjs.log('Instance.emit', event, value, this.eventListeners[event]); + + for (var i=0; i < this.eventListeners[event].length; i++){ + var listener = this.eventListeners[event][i]; + this.send(event, value, listener); + } +}; + + +playerjs.Receiver.prototype.ready = function(){ + playerjs.log('Receiver.ready'); + this.isReady = true; + this.emit('ready', { + src: window.location.toString() + }); +}; + + + diff --git a/test/iframe.html b/test/iframe.html index 7c2f078..203ee5f 100644 --- a/test/iframe.html +++ b/test/iframe.html @@ -5,6 +5,7 @@

Mock IFrame

+ \ No newline at end of file diff --git a/test/mock.js b/test/mock.js index 6fc66c4..1b665ae 100644 --- a/test/mock.js +++ b/test/mock.js @@ -1,87 +1,79 @@ -// We need to create a mock iframe for testing proposes. +/*globals playerjs:true*/ -var eventListeners = {}; +//playerjs.DEBUG = true; +var receiver = new playerjs.Receiver(); +receiver.ready(); -var addEvent = function(elem, type, eventHandle) { - if (!elem) { return; } - if ( elem.addEventListener ) { - elem.addEventListener( type, eventHandle, false ); - } else if ( elem.attachEvent ) { - elem.attachEvent( "on" + type, eventHandle ); - } else { - elem["on"+type]=eventHandle; +var video = { + duration: 20, + currentTime: 0, + interval: null, + timeupdate: function(){}, + volume: 100, + mute: false, + playing: false, + play: function(){ + video.interval = setInterval(function(){ + video.currentTime += 0.25; + video.timeupdate({ + seconds: video.currentTime, + duration: video.duration + }); + }, 250); + video.playing = true; + }, + pause: function(){ + clearInterval(video.interval); + video.playing = false; } }; -var send = function(data, listener){ - if (listener) { - data.listener = listener; - } +receiver.on('play', function(){ + var self = this; + video.play(); + this.emit('play'); + video.timeupdate = function(data){ + self.emit('timeupdate', data); + }; +}); - window.parent.postMessage(JSON.stringify(data), '*'); -}; +receiver.on('pause', function(){ + video.pause(); + this.emit('pause'); +}); -var emit = function(event, data){ - if (!eventListeners.hasOwnProperty(event)){ - return false; - } +receiver.on('getPaused', function(callback){ + callback(!video.playing); +}); - var listeners = eventListeners[event]; - for(var i = 0; i< listeners.length; i++){ - var l = listeners[i]; - var d = { - event: event - }; - if (l.listener){ - d.listener = l.listener; - } - if (data){ - d.data = l.data; - } - send(d); - } -}; +receiver.on('getCurrentTime', function(callback){ + callback(video.currentTime); +}); -addEvent(window, 'message', function(e){ - var data = JSON.parse(e.data); +receiver.on('setCurrentTime', function(value){ + video.currentTime = value; +}); - if (data.method === 'addEventListener'){ - if (eventListeners.hasOwnProperty(data.event)){ - eventListeners[data.event].push(data); - } else { - eventListeners[data.event] = [data]; - } - } +receiver.on('getDuration', function(callback){ + callback(video.duration); +}); - switch (data.method) { - case 'play': - emit('play'); - emit('playProgress', {seconds: 20, duration:100}); - break; - case 'pause': - emit('pause'); break; - case 'paused': - send({ - event: 'paused', - value: true - }, data.listener); break; - case 'getDuration': - send({ - event: 'getDuration', - value: 100 - }, data.listener); break; - case 'getVolume': - send({ - event: 'getVolume', - value: 90 - }, data.listener); break; - case 'getCurrentTime': - send({ - event: 'getCurrentTime', - value: 10.1 - }, data.listener); break; - } +receiver.on('getVolume', function(callback){ + callback(video.volume); }); +receiver.on('setVolume', function(value){ + video.volume = value; +}); + +receiver.on('mute', function(){ + video.mute = true; +}); + +receiver.on('unmute', function(){ + video.mute = false; +}); -send({method:'isReady', event:'ready'}); \ No newline at end of file +receiver.on('getMuted', function(callback){ + callback(video.mute); +}); \ No newline at end of file diff --git a/test/test.js b/test/test.js index c94f058..1e52c5c 100644 --- a/test/test.js +++ b/test/test.js @@ -1,10 +1,12 @@ -/*globals asyncTest:true, ok:true, start:true, Player:true*/ +/*globals asyncTest:true, ok:true, start:true, playerjs:true*/ var FRAMES = [ 'src=http%3A%2F%2Fdistilleryvesper8-8.ak.instagram.com%2Fdc7cdbb2418811e3a4fc22000a1fc7c7_101.mp4&src_secure=1&url=http%3A%2F%2Finstagram.com%2Fp%2FgGZegnh9Sg%2F&image=http%3A%2F%2Fdistilleryimage8.ak.instagram.com%2Fdc7cdbb2418811e3a4fc22000a1fc7c7_8.jpg&type=video%2Fmp4&schema=instagram', - 'src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FKYZIj0Nmdps&src_secure=1&url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DKYZIj0Nmdps&image=http%3A%2F%2Fi1.ytimg.com%2Fvi%2FKYZIj0Nmdps%2Fhqdefault.jpg&key=internal&type=text%2Fhtml&schema=youtube', +'src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FKYZIj0Nmdps&src_secure=1&url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DKYZIj0Nmdps&image=http%3A%2F%2Fi1.ytimg.com%2Fvi%2FKYZIj0Nmdps%2Fhqdefault.jpg&key=internal&type=text%2Fhtml&schema=youtube', 'src=https%3A%2F%2Fplayer.vimeo.com%2Fvideo%2F18150336&src_secure=1&url=http%3A%2F%2Fvimeo.com%2F18150336&image=http%3A%2F%2Fb.vimeocdn.com%2Fts%2F117%2F311%2F117311910_1280.jpg&type=text%2Fhtml&schema=vimeo', - 'src=https%3A%2F%2Fw.soundcloud.com%2Fplayer%2F%3Furl%3Dhttp%253A%252F%252Fapi.soundcloud.com%252Ftracks%252F120478577%26auto_play%3Dfalse%26show_artwork%3Dtrue%26origin%3Dtwitter&src_secure=1&url=http%3A%2F%2Fsoundcloud.com%2Fkettelmusic%2Fhon&image=http%3A%2F%2Fi1.sndcdn.com%2Fartworks-000062945914-gt5axz-t500x500.jpg%3F3eddc42&type=text%2Fhtml&schema=soundcloud' + 'src=https%3A%2F%2Fw.soundcloud.com%2Fplayer%2F%3Furl%3Dhttp%253A%252F%252Fapi.soundcloud.com%252Ftracks%252F120478577%26auto_play%3Dfalse%26show_artwork%3Dtrue%26origin%3Dtwitter&src_secure=1&url=http%3A%2F%2Fsoundcloud.com%2Fkettelmusic%2Fhon&image=http%3A%2F%2Fi1.sndcdn.com%2Fartworks-000062945914-gt5axz-t500x500.jpg%3F3eddc42&type=text%2Fhtml&schema=soundcloud', + 'http://localhost.com:8003/test/iframe.html' + ]; @@ -142,7 +144,7 @@ var loadPlayers = function() { if (count === FRAMES.length){ var iframes = document.getElementsByTagName('iframe'); for (var d=0; d