From 1d894d309c7a186a37f2c8c0ab3c0bdb1c827130 Mon Sep 17 00:00:00 2001 From: Nirvana Tikku Date: Fri, 2 Dec 2016 12:27:27 -0500 Subject: [PATCH] Use spaces instead of tabs and fix JSHint issues --- src/tubeplayer.js | 1182 ++++++++++++++++++------------------- test/tubeplayer_test.js | 1228 +++++++++++++++++++-------------------- 2 files changed, 1205 insertions(+), 1205 deletions(-) diff --git a/src/tubeplayer.js b/src/tubeplayer.js index 9089f17..1fe60eb 100644 --- a/src/tubeplayer.js +++ b/src/tubeplayer.js @@ -1,621 +1,621 @@ (function($) { - 'use strict'; - // - // namespace - var TUBEPLAYER = ".tubeplayer", - TUBEPLAYER_CLASS = "jquery-youtube-tubeplayer", - OPTS = "opts" + TUBEPLAYER; + 'use strict'; + // + // namespace + var TUBEPLAYER = ".tubeplayer", + TUBEPLAYER_CLASS = "jquery-youtube-tubeplayer", + OPTS = "opts" + TUBEPLAYER; - // - // TubePlayer package - var TP = { - inited: false, // tubeplayer inited flag - for destroy/re-init - ytplayers: {}, // all the instances that exist - inits: [], // local init functions for multiple iframe players - iframeScriptInited: false, // no need to import the iframe script multiple times - State: { - 'UNSTARTED': -1, - 'ENDED': 0, - 'PLAYING': 1, - 'PAUSED': 2, - 'BUFFERING': 3, - 'CUED': 5 - }, - Error: { - 'BAD_INIT': 0, - 'INVALID_PARAM': 2, - 'NOT_FOUND': 100, - 'NOT_EMBEDDABLE': 101, - 'CANT_PLAY': 150 - } - }; + // + // TubePlayer package + var TP = { + inited: false, // tubeplayer inited flag - for destroy/re-init + ytplayers: {}, // all the instances that exist + inits: [], // local init functions for multiple iframe players + iframeScriptInited: false, // no need to import the iframe script multiple times + State: { + 'UNSTARTED': -1, + 'ENDED': 0, + 'PLAYING': 1, + 'PAUSED': 2, + 'BUFFERING': 3, + 'CUED': 5 + }, + Error: { + 'BAD_INIT': 0, + 'INVALID_PARAM': 2, + 'NOT_FOUND': 100, + 'NOT_EMBEDDABLE': 101, + 'CANT_PLAY': 150 + } + }; - // - // public facing defaults - $.tubeplayer = { - TubePlayer: TP // reference to the internal TubePlayer object. primarily exposed for testing. - }; + // + // public facing defaults + $.tubeplayer = { + TubePlayer: TP // reference to the internal TubePlayer object. primarily exposed for testing. + }; - /** - * These are all the events that are bound to the YouTube Player - * the events can be overridden as they are public. - * - * There are several functions that serve as wrappers to be utilized - * internally - stateChange, onError, qualityChange, rateChange. - * Change them at your own risk. - */ - $.tubeplayer.defaults = { - afterReady: function() {}, // args: $player - stateChange: function(player) { - var _ret = this.onPlayer; - return function(state) { - var _player = $('#'+player).parent(); - if (typeof(state) === "object") { - state = state.data; - } - switch (state) { - case TP.State.UNSTARTED: - return _ret.unstarted[player].call(_player); - case TP.State.ENDED: - return _ret.ended[player].call(_player); - case TP.State.PLAYING: - return _ret.playing[player].call(_player); - case TP.State.PAUSED: - return _ret.paused[player].call(_player); - case TP.State.BUFFERING: - return _ret.buffering[player].call(_player); - case TP.State.CUED: - return _ret.cued[player].call(_player); - default: - return null; - } - }; - }, - onError: function(player) { - var _ret = this.onErr; - return function(errorCode) { - var _player = $('#'+player).parent(); - if (typeof(errorCode) === "object") { - errorCode = errorCode.data; - } - switch (errorCode) { - case TP.Error.BAD_INIT: - case TP.Error.INVALID_PARAM: - case TP.Error.CANT_PLAY: - return _ret.invalidParameter[player].call(_player); - case TP.Error.NOT_FOUND: - return _ret.notFound[player].call(_player); - case TP.Error.NOT_EMBEDDABLE: - return _ret.notEmbeddable[player].call(_player); - default: - return _ret.defaultError[player].call(_player); - } - }; - }, - qualityChange: function(player) { - var _this = this; - return function(suggested) { - var _player = $('#'+player).parent(); - if (typeof(suggested) === "object") { - suggested = suggested.data; - } - return _this.onQualityChange[player].call(_player, suggested); - }; - }, - rateChange: function(player){ - var _this = this; - return function(suggested) { - var _player = $('#'+player).parent(); - if (typeof(suggested) === "object") { - suggested = suggested.data; - } - return _this.onRateChange[player].call(_player, suggested); - }; - }, - onQualityChange: {}, - onRateChange: {}, - onPlayer: { - unstarted: {}, - ended: {}, - playing: {}, - paused: {}, - buffering: {}, - cued: {} - }, - onErr: { - defaultError: {}, - notFound: {}, - notEmbeddable: {}, - invalidParameter: {} - } - }; + /** + * These are all the events that are bound to the YouTube Player + * the events can be overridden as they are public. + * + * There are several functions that serve as wrappers to be utilized + * internally - stateChange, onError, qualityChange, rateChange. + * Change them at your own risk. + */ + $.tubeplayer.defaults = { + afterReady: function() {}, // args: $player + stateChange: function(player) { + var _ret = this.onPlayer; + return function(state) { + var _player = $('#'+player).parent(); + if (typeof(state) === "object") { + state = state.data; + } + switch (state) { + case TP.State.UNSTARTED: + return _ret.unstarted[player].call(_player); + case TP.State.ENDED: + return _ret.ended[player].call(_player); + case TP.State.PLAYING: + return _ret.playing[player].call(_player); + case TP.State.PAUSED: + return _ret.paused[player].call(_player); + case TP.State.BUFFERING: + return _ret.buffering[player].call(_player); + case TP.State.CUED: + return _ret.cued[player].call(_player); + default: + return null; + } + }; + }, + onError: function(player) { + var _ret = this.onErr; + return function(errorCode) { + var _player = $('#'+player).parent(); + if (typeof(errorCode) === "object") { + errorCode = errorCode.data; + } + switch (errorCode) { + case TP.Error.BAD_INIT: + case TP.Error.INVALID_PARAM: + case TP.Error.CANT_PLAY: + return _ret.invalidParameter[player].call(_player); + case TP.Error.NOT_FOUND: + return _ret.notFound[player].call(_player); + case TP.Error.NOT_EMBEDDABLE: + return _ret.notEmbeddable[player].call(_player); + default: + return _ret.defaultError[player].call(_player); + } + }; + }, + qualityChange: function(player) { + var _this = this; + return function(suggested) { + var _player = $('#'+player).parent(); + if (typeof(suggested) === "object") { + suggested = suggested.data; + } + return _this.onQualityChange[player].call(_player, suggested); + }; + }, + rateChange: function(player){ + var _this = this; + return function(suggested) { + var _player = $('#'+player).parent(); + if (typeof(suggested) === "object") { + suggested = suggested.data; + } + return _this.onRateChange[player].call(_player, suggested); + }; + }, + onQualityChange: {}, + onRateChange: {}, + onPlayer: { + unstarted: {}, + ended: {}, + playing: {}, + paused: {}, + buffering: {}, + cued: {} + }, + onErr: { + defaultError: {}, + notFound: {}, + notEmbeddable: {}, + invalidParameter: {} + } + }; - /** - * These are the internal defaults for the TubePlayer - * plugin to work without providing any parameters. They - * are merged with the users options. - */ - var defaults = { + /** + * These are the internal defaults for the TubePlayer + * plugin to work without providing any parameters. They + * are merged with the users options. + */ + var defaults = { - // public facing - width: 480, - height: 270, - allowFullScreen: "true", - initialVideo: "DkoeNLuMbcI", - start: 0, - preferredQuality: "default", - controls: 1, - showRelated: false, - playsinline: false, - annotations: true, - autoPlay: false, - loop: 0, - color: 'red', // 'red' or 'white' - showinfo: false, - modestbranding: true, - protocol: window.location.protocol == "https:" ? "https" : "http", // set to 'https' for compatibility on SSL-enabled pages - allowScriptAccess: "always", - playerID: "tubeplayer-player-container", + // public facing + width: 480, + height: 270, + allowFullScreen: "true", + initialVideo: "DkoeNLuMbcI", + start: 0, + preferredQuality: "default", + controls: 1, + showRelated: false, + playsinline: false, + annotations: true, + autoPlay: false, + loop: 0, + color: 'red', // 'red' or 'white' + showinfo: false, + modestbranding: true, + protocol: window.location.protocol == "https:" ? "https" : "http", // set to 'https' for compatibility on SSL-enabled pages + allowScriptAccess: "always", + playerID: "tubeplayer-player-container", - // functions called when events are triggered by using the tubeplayer interface - onPlay: function() {}, // arg: id - onPause: function() {}, - onStop: function() {}, - onSeek: function() {}, // arg: time - onMute: function() {}, - onUnMute: function() {}, + // functions called when events are triggered by using the tubeplayer interface + onPlay: function() {}, // arg: id + onPause: function() {}, + onStop: function() {}, + onSeek: function() {}, // arg: time + onMute: function() {}, + onUnMute: function() {}, - // functions called when events are triggered from the youtube player itself - onPlayerUnstarted: function() {}, - onPlayerEnded: function() {}, - onPlayerPlaying: function() {}, - onPlayerPaused: function() {}, - onPlayerBuffering: function() {}, - onPlayerCued: function() {}, - onQualityChange: function() {}, - onRateChange: function() {}, + // functions called when events are triggered from the youtube player itself + onPlayerUnstarted: function() {}, + onPlayerEnded: function() {}, + onPlayerPlaying: function() {}, + onPlayerPaused: function() {}, + onPlayerBuffering: function() {}, + onPlayerCued: function() {}, + onQualityChange: function() {}, + onRateChange: function() {}, - // functions called when errors are thrown from the youtube player - onError: function() {}, - onErrorNotFound: function() {}, - onErrorNotEmbeddable: function() {}, - onErrorInvalidParameter: function() {} + // functions called when errors are thrown from the youtube player + onError: function() {}, + onErrorNotFound: function() {}, + onErrorNotEmbeddable: function() {}, + onErrorInvalidParameter: function() {} - }; + }; - /** - * The TubePlayer plugin bound to the jQuery object's prototype. - * This method acts as an interface to instantiate a TubePlayer, - * as well as invoke events that are attached - typically getters/setters - */ - $.fn.tubeplayer = function(input, xtra) { - var $this = $(this); - var type = typeof input; - if (arguments.length === 0 || type === "object") { - return $this.each(function() { - $this = $(this); - // check if the current element is an iframe and if so replace it with a div - // Mihai Ionut Vilcu - 26/Oct/2013 - if($this.prop('tagName') == "IFRAME") { - // make sure we have a valid YT url - var regExp = /^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#\&\?]*).*/; - var match = $this.attr('src').match(regExp); - if (match&&match[7].length==11) { // we have the id - var settings = {initialVideo : match[7]}, - class_name = $this.attr('class'), - ids = $this.attr('id'); - // check for extra settings - if($this.attr('width')) { - settings.width = $this.attr('width'); - } - if($this.attr('height')) { - settings.height = $this.attr('height'); - } - if($this.attr('allowfullscreen') != undefined) { - settings.allowFullScreen = "true"; - } - else { - settings.allowFullScreen = false; - } - var newDiv = $("
").attr({ - 'class' : class_name ? class_name : '', - 'id' : ids ? ids : '', - }); - $this.replaceWith(newDiv); - var new_input = $.extend({}, defaults, settings, input); - TP.init(newDiv, new_input); - } - } else { - TP.init($(this), input); - } - }); - } else if (type === "string") { - return $this.triggerHandler(input + TUBEPLAYER, (typeof xtra !== 'undefined' ? xtra : null)); - } - }; + /** + * The TubePlayer plugin bound to the jQuery object's prototype. + * This method acts as an interface to instantiate a TubePlayer, + * as well as invoke events that are attached - typically getters/setters + */ + $.fn.tubeplayer = function(input, xtra) { + var $this = $(this); + var type = typeof input; + if (arguments.length === 0 || type === "object") { + return $this.each(function() { + $this = $(this); + // check if the current element is an iframe and if so replace it with a div + // Mihai Ionut Vilcu - 26/Oct/2013 + if($this.prop('tagName') == "IFRAME") { + // make sure we have a valid YT url + var regExp = /^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#\&\?]*).*/; + var match = $this.attr('src').match(regExp); + if (match&&match[7].length==11) { // we have the id + var settings = {initialVideo : match[7]}, + class_name = $this.attr('class'), + ids = $this.attr('id'); + // check for extra settings + if($this.attr('width')) { + settings.width = $this.attr('width'); + } + if($this.attr('height')) { + settings.height = $this.attr('height'); + } + if($this.attr('allowfullscreen') !== undefined) { + settings.allowFullScreen = "true"; + } + else { + settings.allowFullScreen = false; + } + var newDiv = $("
").attr({ + 'class' : class_name ? class_name : '', + 'id' : ids ? ids : '' + }); + $this.replaceWith(newDiv); + var new_input = $.extend({}, defaults, settings, input); + TP.init(newDiv, new_input); + } + } else { + TP.init($(this), input); + } + }); + } else if (type === "string") { + return $this.triggerHandler(input + TUBEPLAYER, (typeof xtra !== 'undefined' ? xtra : null)); + } + }; - /** - * This method is the base method for all the events - * that are bound to the TubePlayer. - */ - var wrap_fn = function(fn) { - return function(evt, param) { - var p = TP.getPkg(evt); - if (p.ytplayer) { - var ret = fn(evt, param, p); - if (typeof(ret) === "undefined") { - ret = p.$player; - } - return ret; - } - return p.$player; - }; - }; + /** + * This method is the base method for all the events + * that are bound to the TubePlayer. + */ + var wrap_fn = function(fn) { + return function(evt, param) { + var p = TP.getPkg(evt); + if (p.ytplayer) { + var ret = fn(evt, param, p); + if (typeof(ret) === "undefined") { + ret = p.$player; + } + return ret; + } + return p.$player; + }; + }; - /** - * Public method to get all the player instances - */ - $.tubeplayer.getPlayers = function() { - return TP.ytplayers; - }; + /** + * Public method to get all the player instances + */ + $.tubeplayer.getPlayers = function() { + return TP.ytplayers; + }; - /** - * Initialize a YouTube player; - * - * First check to see if TubePlayer has been init'd - * if it has then return, otherwise: - * > add the tubeplayer class (used to denote a player) - * > provide local data access to the options and store it - * > initialize the default events on the jQuery instance - * > create the container for the player - * > initialize the player (iframe/HTML5 based) - * - * @param $player - the instance being created on - * @param opts - the user's options - */ - TP.init = function($player, opts) { - if ($player.hasClass(TUBEPLAYER_CLASS)) { - return $player; - } - var o = $.extend({}, defaults, opts); - o.playerID += "-" + guid(); - $player.addClass(TUBEPLAYER_CLASS).data(OPTS, o); - for (var event in PlayerEvents){ - $player.bind(event + TUBEPLAYER, $player, PlayerEvents[event]); - } - // initialize the default event methods - TP.initDefaults($.tubeplayer.defaults, o); - // insert the player container - $("
").attr("id", o.playerID).appendTo($player); - // append the player into the container - TP.initPlayer($player, o); - return $player; - }; + /** + * Initialize a YouTube player; + * + * First check to see if TubePlayer has been init'd + * if it has then return, otherwise: + * > add the tubeplayer class (used to denote a player) + * > provide local data access to the options and store it + * > initialize the default events on the jQuery instance + * > create the container for the player + * > initialize the player (iframe/HTML5 based) + * + * @param $player - the instance being created on + * @param opts - the user's options + */ + TP.init = function($player, opts) { + if ($player.hasClass(TUBEPLAYER_CLASS)) { + return $player; + } + var o = $.extend({}, defaults, opts); + o.playerID += "-" + guid(); + $player.addClass(TUBEPLAYER_CLASS).data(OPTS, o); + for (var event in PlayerEvents){ + $player.bind(event + TUBEPLAYER, $player, PlayerEvents[event]); + } + // initialize the default event methods + TP.initDefaults($.tubeplayer.defaults, o); + // insert the player container + $("
").attr("id", o.playerID).appendTo($player); + // append the player into the container + TP.initPlayer($player, o); + return $player; + }; - /** - * Every method needs these items - */ - TP.getPkg = function(evt) { - var $player = evt.data; - var opts = $player.data(OPTS); - var ytplayer = TP.ytplayers[opts.playerID]; - return { - $player: $player, - opts: opts, - ytplayer: ytplayer - }; - }; + /** + * Every method needs these items + */ + TP.getPkg = function(evt) { + var $player = evt.data; + var opts = $player.data(OPTS); + var ytplayer = TP.ytplayers[opts.playerID]; + return { + $player: $player, + opts: opts, + ytplayer: ytplayer + }; + }; - /** - * This method handles the player init. Since - * onYouTubePlayerReady is called when the script - * has been evaluated, we want all the instances - * to get init'd. For this we have a init queue. - * If the script has been init'd, we automatically - * pop the method off the queue and init the player. - */ - TP.iframeReady = function(o) { - TP.inits.push(function() { - new YT.Player(o.playerID, { - videoId: o.initialVideo, - width: o.width, - height: o.height, - playerVars: { - 'autoplay': (o.autoPlay ? 1 : 0), - 'controls': (o.controls ? o.controls : 0), - 'loop': (o.loop ? 1 : 0), - 'playlist': (o.playlist ? o.playlist : 0), - 'rel': (o.showRelated ? 1 : 0), - 'fs': (o.allowFullScreen ? 1 : 0), - 'showinfo': (o.showinfo ? 1 : 0), - 'modestbranding': (o.modestbranding ? 1 : 0), - 'iv_load_policy': (o.annotations ? 1 : 3), - 'start': o.start, - 'color': o.color, - 'playsinline': o.playsinline, - 'origin': window.location.origin - }, - events: { - 'onReady': function(evt) { - TP.ytplayers[o.playerID] = evt.target; - var $player = $(evt.target.getIframe()).parents("." + TUBEPLAYER_CLASS); - $.tubeplayer.defaults.afterReady($player); - }, - 'onPlaybackQualityChange': $.tubeplayer.defaults.qualityChange(o.playerID), - 'onPlaybackRateChange': $.tubeplayer.defaults.rateChange(o.playerID), - 'onStateChange': $.tubeplayer.defaults.stateChange(o.playerID), - 'onError': $.tubeplayer.defaults.onError(o.playerID) - } - }); - }); + /** + * This method handles the player init. Since + * onYouTubePlayerReady is called when the script + * has been evaluated, we want all the instances + * to get init'd. For this we have a init queue. + * If the script has been init'd, we automatically + * pop the method off the queue and init the player. + */ + TP.iframeReady = function(o) { + TP.inits.push(function() { + new YT.Player(o.playerID, { + videoId: o.initialVideo, + width: o.width, + height: o.height, + playerVars: { + 'autoplay': (o.autoPlay ? 1 : 0), + 'controls': (o.controls ? o.controls : 0), + 'loop': (o.loop ? 1 : 0), + 'playlist': (o.playlist ? o.playlist : 0), + 'rel': (o.showRelated ? 1 : 0), + 'fs': (o.allowFullScreen ? 1 : 0), + 'showinfo': (o.showinfo ? 1 : 0), + 'modestbranding': (o.modestbranding ? 1 : 0), + 'iv_load_policy': (o.annotations ? 1 : 3), + 'start': o.start, + 'color': o.color, + 'playsinline': o.playsinline, + 'origin': window.location.origin + }, + events: { + 'onReady': function(evt) { + TP.ytplayers[o.playerID] = evt.target; + var $player = $(evt.target.getIframe()).parents("." + TUBEPLAYER_CLASS); + $.tubeplayer.defaults.afterReady($player); + }, + 'onPlaybackQualityChange': $.tubeplayer.defaults.qualityChange(o.playerID), + 'onPlaybackRateChange': $.tubeplayer.defaults.rateChange(o.playerID), + 'onStateChange': $.tubeplayer.defaults.stateChange(o.playerID), + 'onError': $.tubeplayer.defaults.onError(o.playerID) + } + }); + }); - // stacked init method - if (TP.inits.length >= 1 && !TP.inited) { - return function() { - for (var i = 0; i < TP.inits.length; i++) { - TP.inits[i](); - } - TP.inited = true; - }; - } + // stacked init method + if (TP.inits.length >= 1 && !TP.inited) { + return function() { + for (var i = 0; i < TP.inits.length; i++) { + TP.inits[i](); + } + TP.inited = true; + }; + } - // if we've inited already, just call the init fn - if (TP.inited) { - (TP.inits.pop())(); - } - return window.onYouTubePlayerAPIReady; - }; + // if we've inited already, just call the init fn + if (TP.inited) { + (TP.inits.pop())(); + } + return window.onYouTubePlayerAPIReady; + }; - /** - * @param d - the defaults - * @param o - the options w/ methods to attach - */ - TP.initDefaults = function(d, o) { + /** + * @param d - the defaults + * @param o - the options w/ methods to attach + */ + TP.initDefaults = function(d, o) { - var ID = o.playerID; + var ID = o.playerID; - // default onPlayer events - var dp = d.onPlayer; - dp.unstarted[ID] = o.onPlayerUnstarted; - dp.ended[ID] = o.onPlayerEnded; - dp.playing[ID] = o.onPlayerPlaying; - dp.paused[ID] = o.onPlayerPaused; - dp.buffering[ID] = o.onPlayerBuffering; - dp.cued[ID] = o.onPlayerCued; + // default onPlayer events + var dp = d.onPlayer; + dp.unstarted[ID] = o.onPlayerUnstarted; + dp.ended[ID] = o.onPlayerEnded; + dp.playing[ID] = o.onPlayerPlaying; + dp.paused[ID] = o.onPlayerPaused; + dp.buffering[ID] = o.onPlayerBuffering; + dp.cued[ID] = o.onPlayerCued; - // default onQualityChange - d.onQualityChange[ID] = o.onQualityChange; - d.onRateChange[ID] = o.onRateChange; + // default onQualityChange + d.onQualityChange[ID] = o.onQualityChange; + d.onRateChange[ID] = o.onRateChange; - // default onError events - var de = d.onErr; - de.defaultError[ID] = o.onError; - de.notFound[ID] = o.onErrorNotFound; - de.notEmbeddable[ID] = o.onErrorNotEmbeddable; - de.invalidParameter[ID] = o.onErrorInvalidParameter; + // default onError events + var de = d.onErr; + de.defaultError[ID] = o.onError; + de.notFound[ID] = o.onErrorNotFound; + de.notEmbeddable[ID] = o.onErrorNotEmbeddable; + de.invalidParameter[ID] = o.onErrorInvalidParameter; - }; + }; - /** - * Init the iframe player - * @param $player - the player that the tubeplayer binds to - * @param o - the init options - */ - TP.initPlayer = function($player, o) { - if (!TP.iframeScriptInited) { - // write the api script tag - var tag = document.createElement('script'); - tag.src = o.protocol + "://www.youtube.com/iframe_api"; - var firstScriptTag = document.getElementsByTagName('script')[0]; - firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); - TP.iframeScriptInited = true; - } - // init the iframe player - window.onYouTubePlayerAPIReady = TP.iframeReady(o); - }; + /** + * Init the iframe player + * @param $player - the player that the tubeplayer binds to + * @param o - the init options + */ + TP.initPlayer = function($player, o) { + if (!TP.iframeScriptInited) { + // write the api script tag + var tag = document.createElement('script'); + tag.src = o.protocol + "://www.youtube.com/iframe_api"; + var firstScriptTag = document.getElementsByTagName('script')[0]; + firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); + TP.iframeScriptInited = true; + } + // init the iframe player + window.onYouTubePlayerAPIReady = TP.iframeReady(o); + }; - // fmt: youtube.com/watch?x=[anything]&v=[desired-token]& - TP.getVideoIDFromURL = function(sURL) { - sURL = sURL || ""; // make sure it's a string; sometimes the YT player API returns undefined, and then indexOf() below will fail - var qryParamsStart = sURL.indexOf("?"); - var qryParams = sURL.substring(qryParamsStart, sURL.length); - var videoStart = qryParams.indexOf("v="); - if (videoStart > -1) { - var videoEnd = qryParams.indexOf("&", videoStart); - if (videoEnd === -1) { - videoEnd = qryParams.length; - } - return qryParams.substring(videoStart + "v=".length, videoEnd); - } - return ""; - }; + // fmt: youtube.com/watch?x=[anything]&v=[desired-token]& + TP.getVideoIDFromURL = function(sURL) { + sURL = sURL || ""; // make sure it's a string; sometimes the YT player API returns undefined, and then indexOf() below will fail + var qryParamsStart = sURL.indexOf("?"); + var qryParams = sURL.substring(qryParamsStart, sURL.length); + var videoStart = qryParams.indexOf("v="); + if (videoStart > -1) { + var videoEnd = qryParams.indexOf("&", videoStart); + if (videoEnd === -1) { + videoEnd = qryParams.length; + } + return qryParams.substring(videoStart + "v=".length, videoEnd); + } + return ""; + }; - /** - * All the events that are bound to a TubePlayer instance - */ - var PlayerEvents = { - opts: wrap_fn(function(evt,param,p){ - return p.opts; - }), - cue: wrap_fn(function(evt, param, p) { - p.ytplayer.cueVideoById(param, 0, p.opts.preferredQuality); - }), - cuePlaylist: wrap_fn(function(evt, param, p){ - p.ytplayer.cuePlaylist(param.playlist, - param.index || 0, - param.startSeconds || 0, - p.opts.preferredQuality); - }), - play: wrap_fn(function(evt, param, p) { - var videoId, startTime; - if (typeof(param) === 'object') { - videoId = param.id; - startTime = param.time; - } - else if (typeof param !== 'undefined') { - videoId = param; - startTime = 0; - } - if(videoId){ - p.ytplayer.loadVideoById({ - videoId: videoId, - startSeconds: startTime, - suggestedQuality: p.opts.preferredQuality - }); - } - else { - p.ytplayer.playVideo(); - } - p.opts.onPlay(param); - }), - playPlaylist: wrap_fn(function(evt, param, p){ - var playlist, playlistIndex, startTime; - if (typeof(param) === 'object') { - var isArray = param.length !== undefined; - playlist = isArray ? param : param.playlist; - startTime = isArray ? 0 : (param.time || 0); - playlistIndex = isArray ? 0 : (param.index || 0); - } - else if (typeof param !== 'undefined') { - playlist = param; - startTime = 0; - playlistIndex = 0; - } - if(playlist){ - p.ytplayer.loadPlaylist(playlist, playlistIndex, - startTime, - p.opts.preferredQuality); - p.opts.onPlay(param); - } - }), - next: wrap_fn(function(evt, param, p){ - p.ytplayer.nextVideo(); - }), - previous: wrap_fn(function(evt, param, p){ - p.ytplayer.previousVideo(); - }), - playVideoAt: wrap_fn(function(evt, param, p){ - p.ytplayer.playVideoAt(param); - }), - pause: wrap_fn(function(evt, param, p) { - p.ytplayer.pauseVideo(); - p.opts.onPause(p); - }), - stop: wrap_fn(function(evt, param, p) { - p.ytplayer.stopVideo(); - p.opts.onStop(p); - }), - seek: wrap_fn(function(evt, param, p) { - if (/:/.test(param)) { - var parts = param.split(":").reverse(); - param = 0; - for (var i = 0; i < parts.length; i++) { - param += Math.pow(60, i) * (parts[i] | 0); - } - } - p.ytplayer.seekTo(param, true); - p.opts.onSeek(param); - }), - mute: wrap_fn(function(evt, param, p) { - p.$player.attr("data-prev-mute-volume", p.ytplayer.getVolume()); - p.ytplayer.mute(); - p.opts.onMute(p); - }), - unmute: wrap_fn(function(evt, param, p) { - p.ytplayer.unMute(); - p.ytplayer.setVolume((p.$player.attr("data-prev-mute-volume") || 50)); - p.opts.onUnMute(); - }), - isMuted: wrap_fn(function(evt, param, p) { - return p.ytplayer.isMuted(); - }), - volume: wrap_fn(function(evt, param, p) { - if (typeof param !== 'undefined') { - p.ytplayer.setVolume(param); - p.$player.attr("data-prev-mute-volume", p.ytplayer.getVolume()); - } else { - return p.ytplayer.getVolume(); - } - }), - quality: wrap_fn(function(evt, param, p) { - // param = ['small', 'medium', 'large', 'hd720', 'hd1080', 'highres', 'default'] - if (typeof param !== 'undefined') { - p.ytplayer.setPlaybackQuality(param); - } - else { - return p.ytplayer.getPlaybackQuality(); - } - }), - playbackRate: wrap_fn(function(evt, param, p){ - if(typeof param !== "undefined") { - p.ytplayer.setPlaybackRate(param); - } - else { - return p.ytplayer.getPlaybackRate(); - } - }), - data: wrap_fn(function(evt, param, p) { - var ret = {}; - var P = p.ytplayer; - ret.videoLoadedFraction = P.getVideoLoadedFraction(); - ret.bytesLoaded = P.getVideoBytesLoaded(); // deprecated - ret.bytesTotal = P.getVideoBytesTotal(); // deprecated - ret.startBytes = P.getVideoStartBytes(); // deprecated - ret.state = P.getPlayerState(); - ret.currentTime = P.getCurrentTime(); - ret.duration = P.getDuration(); - ret.videoURL = P.getVideoUrl(); - ret.playlist = { - videoIDs: P.getPlaylist(), - currentIndex: P.getPlaylistIndex() - }; - ret.videoEmbedCode = P.getVideoEmbedCode(); - ret.videoID = TP.getVideoIDFromURL(ret.videoURL); - ret.availableQualityLevels = P.getAvailableQualityLevels(); - ret.availablePlaybackRates = P.getAvailablePlaybackRates(); - return ret; - }), - videoId: wrap_fn(function(evt, param, p) { - return TP.getVideoIDFromURL(p.ytplayer.getVideoUrl()); - }), - size: wrap_fn(function(evt, param, p) { - if (typeof param !== 'undefined' && param.width && param.height) { - p.ytplayer.setSize(param.width, param.height); - $(p.ytplayer).css(param); - } - }), - destroy: wrap_fn(function(evt, param, p) { - p.$player.removeClass(TUBEPLAYER_CLASS).data(OPTS, null).unbind(TUBEPLAYER).html(""); - delete TP.ytplayers[p.opts.playerID]; - // cleanup callback handler references.. - var d = $.tubeplayer.defaults; - var events = ['unstarted', 'ended', 'playing', 'paused', 'buffering', 'cued']; - $.each(events, function(i, event) { - delete d.onPlayer[event][p.opts.playerID]; - }); - events = ['defaultError', 'notFound', 'notEmbeddable', 'invalidParameter']; - $.each(events, function(i, event) { - delete d.onErr[event][p.opts.playerID]; - }); - delete d.onQualityChange[p.opts.playerID]; - delete d.onRateChange[p.opts.playerID]; - if ('destroy' in p.ytplayer) { - p.ytplayer.destroy(); - } - $(p.ytplayer).remove(); - return null; - }), - player: wrap_fn(function(evt, param, p) { - return p.ytplayer; - }) - }; + /** + * All the events that are bound to a TubePlayer instance + */ + var PlayerEvents = { + opts: wrap_fn(function(evt,param,p){ + return p.opts; + }), + cue: wrap_fn(function(evt, param, p) { + p.ytplayer.cueVideoById(param, 0, p.opts.preferredQuality); + }), + cuePlaylist: wrap_fn(function(evt, param, p){ + p.ytplayer.cuePlaylist(param.playlist, + param.index || 0, + param.startSeconds || 0, + p.opts.preferredQuality); + }), + play: wrap_fn(function(evt, param, p) { + var videoId, startTime; + if (typeof(param) === 'object') { + videoId = param.id; + startTime = param.time; + } + else if (typeof param !== 'undefined') { + videoId = param; + startTime = 0; + } + if(videoId){ + p.ytplayer.loadVideoById({ + videoId: videoId, + startSeconds: startTime, + suggestedQuality: p.opts.preferredQuality + }); + } + else { + p.ytplayer.playVideo(); + } + p.opts.onPlay(param); + }), + playPlaylist: wrap_fn(function(evt, param, p){ + var playlist, playlistIndex, startTime; + if (typeof(param) === 'object') { + var isArray = param.length !== undefined; + playlist = isArray ? param : param.playlist; + startTime = isArray ? 0 : (param.time || 0); + playlistIndex = isArray ? 0 : (param.index || 0); + } + else if (typeof param !== 'undefined') { + playlist = param; + startTime = 0; + playlistIndex = 0; + } + if(playlist){ + p.ytplayer.loadPlaylist(playlist, playlistIndex, + startTime, + p.opts.preferredQuality); + p.opts.onPlay(param); + } + }), + next: wrap_fn(function(evt, param, p){ + p.ytplayer.nextVideo(); + }), + previous: wrap_fn(function(evt, param, p){ + p.ytplayer.previousVideo(); + }), + playVideoAt: wrap_fn(function(evt, param, p){ + p.ytplayer.playVideoAt(param); + }), + pause: wrap_fn(function(evt, param, p) { + p.ytplayer.pauseVideo(); + p.opts.onPause(p); + }), + stop: wrap_fn(function(evt, param, p) { + p.ytplayer.stopVideo(); + p.opts.onStop(p); + }), + seek: wrap_fn(function(evt, param, p) { + if (/:/.test(param)) { + var parts = param.split(":").reverse(); + param = 0; + for (var i = 0; i < parts.length; i++) { + param += Math.pow(60, i) * (parts[i] | 0); + } + } + p.ytplayer.seekTo(param, true); + p.opts.onSeek(param); + }), + mute: wrap_fn(function(evt, param, p) { + p.$player.attr("data-prev-mute-volume", p.ytplayer.getVolume()); + p.ytplayer.mute(); + p.opts.onMute(p); + }), + unmute: wrap_fn(function(evt, param, p) { + p.ytplayer.unMute(); + p.ytplayer.setVolume((p.$player.attr("data-prev-mute-volume") || 50)); + p.opts.onUnMute(); + }), + isMuted: wrap_fn(function(evt, param, p) { + return p.ytplayer.isMuted(); + }), + volume: wrap_fn(function(evt, param, p) { + if (typeof param !== 'undefined') { + p.ytplayer.setVolume(param); + p.$player.attr("data-prev-mute-volume", p.ytplayer.getVolume()); + } else { + return p.ytplayer.getVolume(); + } + }), + quality: wrap_fn(function(evt, param, p) { + // param = ['small', 'medium', 'large', 'hd720', 'hd1080', 'highres', 'default'] + if (typeof param !== 'undefined') { + p.ytplayer.setPlaybackQuality(param); + } + else { + return p.ytplayer.getPlaybackQuality(); + } + }), + playbackRate: wrap_fn(function(evt, param, p){ + if(typeof param !== "undefined") { + p.ytplayer.setPlaybackRate(param); + } + else { + return p.ytplayer.getPlaybackRate(); + } + }), + data: wrap_fn(function(evt, param, p) { + var ret = {}; + var P = p.ytplayer; + ret.videoLoadedFraction = P.getVideoLoadedFraction(); + ret.bytesLoaded = P.getVideoBytesLoaded(); // deprecated + ret.bytesTotal = P.getVideoBytesTotal(); // deprecated + ret.startBytes = P.getVideoStartBytes(); // deprecated + ret.state = P.getPlayerState(); + ret.currentTime = P.getCurrentTime(); + ret.duration = P.getDuration(); + ret.videoURL = P.getVideoUrl(); + ret.playlist = { + videoIDs: P.getPlaylist(), + currentIndex: P.getPlaylistIndex() + }; + ret.videoEmbedCode = P.getVideoEmbedCode(); + ret.videoID = TP.getVideoIDFromURL(ret.videoURL); + ret.availableQualityLevels = P.getAvailableQualityLevels(); + ret.availablePlaybackRates = P.getAvailablePlaybackRates(); + return ret; + }), + videoId: wrap_fn(function(evt, param, p) { + return TP.getVideoIDFromURL(p.ytplayer.getVideoUrl()); + }), + size: wrap_fn(function(evt, param, p) { + if (typeof param !== 'undefined' && param.width && param.height) { + p.ytplayer.setSize(param.width, param.height); + $(p.ytplayer).css(param); + } + }), + destroy: wrap_fn(function(evt, param, p) { + p.$player.removeClass(TUBEPLAYER_CLASS).data(OPTS, null).unbind(TUBEPLAYER).html(""); + delete TP.ytplayers[p.opts.playerID]; + // cleanup callback handler references.. + var d = $.tubeplayer.defaults; + var events = ['unstarted', 'ended', 'playing', 'paused', 'buffering', 'cued']; + $.each(events, function(i, event) { + delete d.onPlayer[event][p.opts.playerID]; + }); + events = ['defaultError', 'notFound', 'notEmbeddable', 'invalidParameter']; + $.each(events, function(i, event) { + delete d.onErr[event][p.opts.playerID]; + }); + delete d.onQualityChange[p.opts.playerID]; + delete d.onRateChange[p.opts.playerID]; + if ('destroy' in p.ytplayer) { + p.ytplayer.destroy(); + } + $(p.ytplayer).remove(); + return null; + }), + player: wrap_fn(function(evt, param, p) { + return p.ytplayer; + }) + }; - // used in case of multiple players - function guid() { - return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { - var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); - return v.toString(16); - }); - } + // used in case of multiple players + function guid() { + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { + var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); + return v.toString(16); + }); + } })(jQuery); diff --git a/test/tubeplayer_test.js b/test/tubeplayer_test.js index 1a815fa..b1a0687 100644 --- a/test/tubeplayer_test.js +++ b/test/tubeplayer_test.js @@ -1,616 +1,616 @@ (function($) { - - var DEFAULT_VOLUME = 50; - - /** - * T E S T - * I N F R A S T R U C T U R E - */ - module('Basic', { - setup: function() { - this.$player = $('.youtube-player'); - }, - teardown: function(){ - this.$player.tubeplayer("volume", DEFAULT_VOLUME); - this.$player.tubeplayer('destroy'); - } - }); - - test('General Checkup', function() { - - expect(5); - - ok($.fn.tubeplayer, 'exists in jQuery namespace'); - ok($.tubeplayer.defaults, 'plugin defaults exists'); - ok($.tubeplayer.TubePlayer, "the tubeplayer object"); - equal(Object.keys($.tubeplayer.TubePlayer.ytplayers).length, 0, "no players yet"); - ok(this.$player, 'player node exists'); - - }); - - asyncTest('Creation and Ensure data and state is intact', function() { - - expect(15); - - $.tubeplayer.defaults.afterReady = function($player) { - - var data = $player.tubeplayer('data'); - equal(data.state === $.tubeplayer.TubePlayer.State.UNSTARTED || data.state === $.tubeplayer.TubePlayer.State.CUED, true, 'is uninitialized/cued upon creation'); - equal(data.videoURL.indexOf(data.videoID) > -1, true, 'videoID exists in videoURL'); - - var opts = $player.tubeplayer('opts'); - equal(opts.annotations, true, "annotations"); - equal(opts.autoPlay, false, "autoPlay"); - equal(opts.color, "red", "color"); - equal(opts.height, "400px", "height"); - equal(opts.loop, false, "loop"); - equal(opts.modestbranding, true, "modestbranding"); - equal(opts.preferredQuality, "default", "preferredQuality"); - equal(opts.protocol, "http", "protocol"); - equal(opts.controls, 1, "showControls"); - equal(opts.showRelated, false, "showRelated"); - equal(opts.showinfo, false, "showinfo"); - equal(opts.start, 0, "start"); - - $player.tubeplayer('destroy'); - start(); - - }; - - ok(this.$player.tubeplayer({ - width: '300px', - height: '400px' - }), 'recreated w/ (300,400)'); - - }); - - asyncTest('Player creation and control', function() { - - expect(4); - - $.tubeplayer.defaults.afterReady = function($player) { - var data = $player.tubeplayer('data'); - equal(data.state === $.tubeplayer.TubePlayer.State.UNSTARTED || data.state === $.tubeplayer.TubePlayer.State.CUED, true, 'is uninitialized upon creation'); - equal($player.tubeplayer('isMuted'), false, 'player should not be muted'); - start(); - }; - - strictEqual(this.$player.tubeplayer()[0], this.$player[0], 'same node at the end of the initialization'); - ok(this.$player.tubeplayer('destroy'), 'destroyed the player'); - - }); - - /** - * T E S T - * E V E N T S & - * C A L L B A C K S - */ - module('Events', { - setup: function() { - $(".youtube-player").remove(); - this.$player = $('
'); - $("body").append(this.$player); - }, - teardown: function() { - $(".youtube-player").tubeplayer('destroy'); - this.$player.remove(); - } - }); - - /** - * C U E V I D E O - * - * Notes: If client is participating in HTML5 trial, onPlayerCued does not seem to get called. - */ - asyncTest('tubeplayer(\'cue\') -> onPlayerCued', function(){ - - expect(3); - - $.tubeplayer.defaults.afterReady = function($player) { - $player.tubeplayer('cue', '7iEDYB7pY7U'); - }; - - ok(this.$player.tubeplayer({ - onPlayerCued: function() { - equal(this.tubeplayer('data').videoID, '7iEDYB7pY7U', 'video id is the cueued id'); - equal(this.tubeplayer('data').state, 5, 'is currently cued'); - start(); - } - }), 'created, now play'); - - }); - - /** - * P L A Y - */ - asyncTest('tubeplayer(\'play\') -> onPlay, onPlayerPlaying', function() { - - expect(3); - - $.tubeplayer.defaults.afterReady = function($player) { - $player.tubeplayer('play'); - }; - - var self = this; - - ok(this.$player.tubeplayer({ - onPlay: function() { - var data = self.$player.tubeplayer('data'); - equal(data.state === $.tubeplayer.TubePlayer.State.UNSTARTED || data.state === $.tubeplayer.TubePlayer.State.CUED, true, 'play was triggered, currently unstarted'); - }, - onPlayerPlaying: function() { - equal(this.tubeplayer('data').state, 1, 'is currently playing'); - start(); - } - }), 'created, now play'); - - }); - - /** - * P L A Y O P T I O N S - */ - asyncTest("tubeplayer('play','VqPo5vueSSA') -> onPlayerPlaying", function(){ - - expect(4); - - var originalVideoID = "2Jvju2ceNSE"; - var newVideoID = "VqPo5vueSSA"; - - $.tubeplayer.defaults.afterReady = function($player) { - equal($player.tubeplayer('data').videoID, originalVideoID, "ensure videoID is set to initial video"); - $player.tubeplayer('play',newVideoID); - // equal($player.tubeplayer("data").) - }; - - ok(this.$player.tubeplayer({ - initialVideo: originalVideoID, - onPlayerPlaying: function(){ - ok(true); - equal(this.tubeplayer("data").videoID, newVideoID, "ensure videoID is the new videoID"); - start(); - } - }), 'created'); - - }); - - /** - * P A U S E - */ - asyncTest('tubeplayer(\'pause\') -> onPause, onPlayerPaused', function() { - - expect(4); - - $.tubeplayer.defaults.afterReady = function($player) { - $player.tubeplayer('play'); - }; - - var self = this; - - ok(this.$player.tubeplayer({ - onPlay: function() { - var data = self.$player.tubeplayer('data'); - equal(data.state === $.tubeplayer.TubePlayer.State.UNSTARTED || data.state === $.tubeplayer.TubePlayer.State.CUED, true, 'play was triggered, currently unstarted'); - }, - onPlayerPlaying: function() { - this.tubeplayer('pause'); - }, - onPause: function() { - equal(self.$player.tubeplayer('data').state, 1, 'pause was triggered, currently playing'); - }, - onPlayerPaused: function() { - equal(this.tubeplayer('data').state, 2, 'is currently paused'); - start(); - } - }), 'created, now play then pause'); - - }); - - /** - * V O L U M E - */ - asyncTest('tubeplayer(\'mute\'), tubeplayer(\'unmute\') -> onStop', function() { - - expect(8); - - $.tubeplayer.defaults.afterReady = function($player) { - $player.tubeplayer('play'); - }; - - var self = this; - - ok(this.$player.tubeplayer({ - onPlay: function() { - var data = self.$player.tubeplayer('data'); - equal(data.state === $.tubeplayer.TubePlayer.State.UNSTARTED || data.state === $.tubeplayer.TubePlayer.State.CUED, true, 'play was triggered, currently unstarted'); - }, - onPlayerPlaying: function() { - - var vol = self.$player.tubeplayer('volume'); - - equal(self.$player.tubeplayer('isMuted'), false, "isn't muted yet"); - - self.$player.tubeplayer('mute'); - - setTimeout(function() { - - equal(self.$player.tubeplayer('isMuted'), true, "should be muted now"); - equal(self.$player.tubeplayer('volume'), vol, "volume should remain, though muted"); - - self.$player.tubeplayer('unmute'); - - setTimeout(function() { - - equal(self.$player.tubeplayer('isMuted'), false, 'should be unmuted'); - equal(self.$player.tubeplayer('volume'), vol, 'volume back to what it was before'); - - self.$player.tubeplayer('stop'); - - }, 50); - - }, 50); - - }, - onStop: function() { - equal(self.$player.tubeplayer('data').state, 1, 'stop was triggered while playing'); - start(); - } - }), 'created, now play then pause'); - - }); - - /** - * S E E K - */ - asyncTest("tubeplayer('seek') -> onSeek", function(){ - - expect(4); - - $.tubeplayer.defaults.afterReady = function($player) { - equal($player.tubeplayer('data').currentTime, 0, 'current time = 0'); - $player.tubeplayer("play"); - }; - - var hasSeeked = false; - - ok(this.$player.tubeplayer({ - width:500, - height:300, - onSeek:function(){ - ok(true); - }, - onPlayerPlaying: function(){ - if(!hasSeeked){ - hasSeeked = true; - this.tubeplayer('seek',100); - } else { - equal(Math.abs(this.tubeplayer('data').currentTime - 100) < 1, true, "seeked to ~100s in"); - start(); - } - } - }), 'created'); - - }); - - /** - * P L A Y E R E N D E D - */ - asyncTest('tubeplayer(\'seek\',[end]) -> onPlayerEnded', function(){ - - expect(2); - - $.tubeplayer.defaults.afterReady = function($player) { - $player.tubeplayer('play'); - }; - - var hasSeeked = false; - - ok(this.$player.tubeplayer({ - initialVideo:'7iEDYB7pY7U', - onPlayerPlaying: function(){ - if(hasSeeked) return; - hasSeeked = true; - this.tubeplayer('seek', this.tubeplayer('data').duration - 2); - }, - onPlayerEnded: function() { - equal(this.tubeplayer('data').state, 0, 'is currently ended'); - start(); - } - }), 'created, now play and skip to end of video'); - - }); - - /** - * S I Z E - */ - asyncTest("tubeplayer('size',{width:400,height:300})", function(){ - - expect(3); - - $.tubeplayer.defaults.afterReady = function($player) { - $player.tubeplayer('size',{ width: 400, height: 300 }); - equal($player.find("iframe").css('width'), "400px", 'same width as just assigned'); - equal($player.find("iframe").css('height'), "300px", 'same height as just assigned'); - start(); - }; - - ok(this.$player.tubeplayer({width:800,height:600}), 'created'); - - }); - - /** - * Q U A L I T Y - */ - asyncTest("tubeplayer('quality') -> onQualityChange", function(){ - - // a change cannot be guaranteed, so this test isn't perfect - - expect(3); - - var QUALITY_TO_SET = "small"; - - $.tubeplayer.defaults.afterReady = function($player) { - equal($player.tubeplayer('quality'), 'unknown', 'Quality is unknown at start'); - $player.tubeplayer("play"); - }; - - ok(this.$player.tubeplayer({ - width:300, - height:200, - preferredQuality: QUALITY_TO_SET, - onPlayerPlaying: function(){ - this.tubeplayer('quality', 'large'); - start(); - }, - onQualityChange: function(){ - notEqual(this.tubeplayer('quality'), QUALITY_TO_SET, 'validate that the quality was set appropriately'); - } - }), 'created'); - - }); - - - /** - * P L A Y B A C K R A T E - */ - asyncTest("tubeplayer('playbackRate'), tubeplayer('data').availablePlaybackRates",function(){ - - expect(5); - - $.tubeplayer.defaults.afterReady = function($player){ - equal($player.tubeplayer('videoId'), "JtbDDqU3dVI", "variable playback rate video set properly"); - $player.tubeplayer('play'); // video has to enable variable playback rate - }; - - ok(this.$player.tubeplayer({ - width: 300, - height: 200, - initialVideo: "JtbDDqU3dVI", - onPlayerPlaying: function(){ - - deepEqual(this.tubeplayer('data').availablePlaybackRates, [ 0.25, 0.5, 1, 1.25, 1.5, 2 ], "available playback rates are consistent"); - - var currentRate = this.tubeplayer('playbackRate'); - equal(currentRate, 1, "player should be at 1x normally"); - - this.tubeplayer('playbackRate', 2); - - var me = this; - setTimeout(function(){ - equal(me.tubeplayer('playbackRate'), 2, "rate was updated to 2x appropriately"); - start(); - },50); - - } - }), 'created'); - - }); - - /** - * D A T A I N T A C T - */ - asyncTest("tubeplayer('data') -> returns defined keys", function(){ - - var expectedKeys = [ - "availablePlaybackRates", - "videoLoadedFraction", - "bytesLoaded", - "bytesTotal", - "startBytes", - "state", - "currentTime", - "duration", - "videoURL", - "videoEmbedCode", - "videoID", - "playlist", - "availableQualityLevels", - "availablePlaybackRates" - ]; - - expect(expectedKeys.length); - - $.tubeplayer.defaults.afterReady = function($player){ - var data = $player.tubeplayer('data'); - for(var key in data){ - equal(expectedKeys.indexOf(key) > -1, true, key + " exists"); - } - start(); - }; - - ok(this.$player.tubeplayer(),"created"); - - }); - - /** - * B A D I N I T S I Z E - * Note: Seems to work with iframe API - */ - // asyncTest("bad init w/ {10,10} (onErrorNotEmbeddable)", function(){ - - // expect(2); - - // $.tubeplayer.defaults.afterReady = function($player) { - // $player.tubeplayer('play'); - // }; - - // ok(this.$player.tubeplayer({ - // autoplay: true, - // width:10, - // height:10, - // onErrorNotEmbeddable: function(){ - // ok(true); - // start(); - // } - // }), 'created'); - - // }); - - /** - * B A D I N I T V I D E O I D - */ - asyncTest("bad init w/ no videoID (onErrorInvalidParameter)", function(){ - - expect(2); - - $.tubeplayer.defaults.afterReady = function($player) { - $player.tubeplayer('play', 'bogus id'); - }; - - ok(this.$player.tubeplayer({ - autoplay: true, - width:200, - height:200, - onErrorInvalidParameter: function(){ - ok(true, "error invalid param has been triggered"); - start(); - } - }), 'created'); - - }); - - /** - * G E T P L A Y E R S - */ - asyncTest("create one, $.tubeplayer.getPlayers() === 1", function(){ - - var players = $.tubeplayer.getPlayers(); - equal(Object.keys(players).length, 0, "no players yet"); - - $.tubeplayer.defaults.afterReady = function(){ - equal(Object.keys($.tubeplayer.getPlayers()).length,1,"one player exists"); - start(); - }; - - ok(this.$player.tubeplayer(), "created"); - - }); - - /** - * M U L T I P L E - * P L A Y E R S - */ - module('Multiple', { - setup: function() { - $(".youtube-player").remove(); - this.$players = $('
'); - $("body").append(this.$players); - }, - teardown: function() { - this.$players.each(function(){ - $(this).tubeplayer('destroy'); - }); - this.$players.remove(); - } - }); - - /** - * C R E A T E - */ - asyncTest("create three, $.tubeplayer.getPlayers() === 3", function(){ - - expect(5); - - var players = $.tubeplayer.getPlayers(); - equal(Object.keys(players).length, 0, "no players yet"); - - var i = 1; - - $.tubeplayer.defaults.afterReady = function(){ - equal(Object.keys($.tubeplayer.getPlayers()).length, i, i + " < # player(s) exist"); - if(i === 3) { // one-based - start(); - } else { - i++; - } - }; - - ok(this.$players.tubeplayer(), "created"); - - }); - - /** - * P L A Y 3 V I D E O S - */ - asyncTest("create three players, tubeplayer('play') 3 unique IDs", function(){ - - expect(7); - - var players = $.tubeplayer.getPlayers(); - equal(Object.keys(players).length, 0, "no players yet"); - - var self = this; - function continueTesting(){ - - var $p1 = $(self.$players[0]); - equal($p1.tubeplayer('data').state, $.tubeplayer.TubePlayer.State.PLAYING, 'is playing'); - $p1.tubeplayer('pause'); - - var $p2 = $(self.$players[1]); - equal($p2.tubeplayer('data').state, $.tubeplayer.TubePlayer.State.CUED, 'is cued'); - // $p2.tubeplayer('pause'); - // equal($p2.tubeplayer('data').state, $.tubeplayer.TubePlayer.State.PAUSED, 'is paused'); - - var $p3 = $(self.$players[2]); - equal($p3.tubeplayer('data').state, $.tubeplayer.TubePlayer.State.CUED, 'is cued'); - // $p3.tubeplayer('pause'); - // equal($p3.tubeplayer('data').state, $.tubeplayer.TubePlayer.State.PAUSED, 'is paused'); - - start(); - - } - - var i = 0, k = 0; // counters used during callback to denote diff. players - - var videoids = ["2Jvju2ceNSE", "VqPo5vueSSA", "yv_iE1pV8gM", "6JM22R_sYs8"]; - - $.tubeplayer.defaults.afterReady = function($player){ - if(i === 0 ){ - $player.tubeplayer("play", videoids[i]); - } else { - $player.tubeplayer("cue", videoids[i]); - } - if(i === 2) { - equal(Object.keys($.tubeplayer.getPlayers()).length, 3, "3 players"); - } - i++; - }; - - ok(this.$players.tubeplayer({ - onPlayerPlaying:function(){ - ok(true, "player started playing"); - continueTesting(); - }, - onPlayerPaused: function(){ - ok(true, "player was paused"); - if(k === 2){ - // start(); - } - k++; - } - }), "created"); - - }); - - QUnit.start(); - + + var DEFAULT_VOLUME = 50; + + /** + * T E S T + * I N F R A S T R U C T U R E + */ + module('Basic', { + setup: function() { + this.$player = $('.youtube-player'); + }, + teardown: function(){ + this.$player.tubeplayer("volume", DEFAULT_VOLUME); + this.$player.tubeplayer('destroy'); + } + }); + + test('General Checkup', function() { + + expect(5); + + ok($.fn.tubeplayer, 'exists in jQuery namespace'); + ok($.tubeplayer.defaults, 'plugin defaults exists'); + ok($.tubeplayer.TubePlayer, "the tubeplayer object"); + equal(Object.keys($.tubeplayer.TubePlayer.ytplayers).length, 0, "no players yet"); + ok(this.$player, 'player node exists'); + + }); + + asyncTest('Creation and Ensure data and state is intact', function() { + + expect(15); + + $.tubeplayer.defaults.afterReady = function($player) { + + var data = $player.tubeplayer('data'); + equal(data.state === $.tubeplayer.TubePlayer.State.UNSTARTED || data.state === $.tubeplayer.TubePlayer.State.CUED, true, 'is uninitialized/cued upon creation'); + equal(data.videoURL.indexOf(data.videoID) > -1, true, 'videoID exists in videoURL'); + + var opts = $player.tubeplayer('opts'); + equal(opts.annotations, true, "annotations"); + equal(opts.autoPlay, false, "autoPlay"); + equal(opts.color, "red", "color"); + equal(opts.height, "400px", "height"); + equal(opts.loop, false, "loop"); + equal(opts.modestbranding, true, "modestbranding"); + equal(opts.preferredQuality, "default", "preferredQuality"); + equal(opts.protocol, "http", "protocol"); + equal(opts.controls, 1, "showControls"); + equal(opts.showRelated, false, "showRelated"); + equal(opts.showinfo, false, "showinfo"); + equal(opts.start, 0, "start"); + + $player.tubeplayer('destroy'); + start(); + + }; + + ok(this.$player.tubeplayer({ + width: '300px', + height: '400px' + }), 'recreated w/ (300,400)'); + + }); + + asyncTest('Player creation and control', function() { + + expect(4); + + $.tubeplayer.defaults.afterReady = function($player) { + var data = $player.tubeplayer('data'); + equal(data.state === $.tubeplayer.TubePlayer.State.UNSTARTED || data.state === $.tubeplayer.TubePlayer.State.CUED, true, 'is uninitialized upon creation'); + equal($player.tubeplayer('isMuted'), false, 'player should not be muted'); + start(); + }; + + strictEqual(this.$player.tubeplayer()[0], this.$player[0], 'same node at the end of the initialization'); + ok(this.$player.tubeplayer('destroy'), 'destroyed the player'); + + }); + + /** + * T E S T + * E V E N T S & + * C A L L B A C K S + */ + module('Events', { + setup: function() { + $(".youtube-player").remove(); + this.$player = $('
'); + $("body").append(this.$player); + }, + teardown: function() { + $(".youtube-player").tubeplayer('destroy'); + this.$player.remove(); + } + }); + + /** + * C U E V I D E O + * + * Notes: If client is participating in HTML5 trial, onPlayerCued does not seem to get called. + */ + asyncTest('tubeplayer(\'cue\') -> onPlayerCued', function(){ + + expect(3); + + $.tubeplayer.defaults.afterReady = function($player) { + $player.tubeplayer('cue', '7iEDYB7pY7U'); + }; + + ok(this.$player.tubeplayer({ + onPlayerCued: function() { + equal(this.tubeplayer('data').videoID, '7iEDYB7pY7U', 'video id is the cueued id'); + equal(this.tubeplayer('data').state, 5, 'is currently cued'); + start(); + } + }), 'created, now play'); + + }); + + /** + * P L A Y + */ + asyncTest('tubeplayer(\'play\') -> onPlay, onPlayerPlaying', function() { + + expect(3); + + $.tubeplayer.defaults.afterReady = function($player) { + $player.tubeplayer('play'); + }; + + var self = this; + + ok(this.$player.tubeplayer({ + onPlay: function() { + var data = self.$player.tubeplayer('data'); + equal(data.state === $.tubeplayer.TubePlayer.State.UNSTARTED || data.state === $.tubeplayer.TubePlayer.State.CUED, true, 'play was triggered, currently unstarted'); + }, + onPlayerPlaying: function() { + equal(this.tubeplayer('data').state, 1, 'is currently playing'); + start(); + } + }), 'created, now play'); + + }); + + /** + * P L A Y O P T I O N S + */ + asyncTest("tubeplayer('play','VqPo5vueSSA') -> onPlayerPlaying", function(){ + + expect(4); + + var originalVideoID = "2Jvju2ceNSE"; + var newVideoID = "VqPo5vueSSA"; + + $.tubeplayer.defaults.afterReady = function($player) { + equal($player.tubeplayer('data').videoID, originalVideoID, "ensure videoID is set to initial video"); + $player.tubeplayer('play',newVideoID); + // equal($player.tubeplayer("data").) + }; + + ok(this.$player.tubeplayer({ + initialVideo: originalVideoID, + onPlayerPlaying: function(){ + ok(true); + equal(this.tubeplayer("data").videoID, newVideoID, "ensure videoID is the new videoID"); + start(); + } + }), 'created'); + + }); + + /** + * P A U S E + */ + asyncTest('tubeplayer(\'pause\') -> onPause, onPlayerPaused', function() { + + expect(4); + + $.tubeplayer.defaults.afterReady = function($player) { + $player.tubeplayer('play'); + }; + + var self = this; + + ok(this.$player.tubeplayer({ + onPlay: function() { + var data = self.$player.tubeplayer('data'); + equal(data.state === $.tubeplayer.TubePlayer.State.UNSTARTED || data.state === $.tubeplayer.TubePlayer.State.CUED, true, 'play was triggered, currently unstarted'); + }, + onPlayerPlaying: function() { + this.tubeplayer('pause'); + }, + onPause: function() { + equal(self.$player.tubeplayer('data').state, 1, 'pause was triggered, currently playing'); + }, + onPlayerPaused: function() { + equal(this.tubeplayer('data').state, 2, 'is currently paused'); + start(); + } + }), 'created, now play then pause'); + + }); + + /** + * V O L U M E + */ + asyncTest('tubeplayer(\'mute\'), tubeplayer(\'unmute\') -> onStop', function() { + + expect(8); + + $.tubeplayer.defaults.afterReady = function($player) { + $player.tubeplayer('play'); + }; + + var self = this; + + ok(this.$player.tubeplayer({ + onPlay: function() { + var data = self.$player.tubeplayer('data'); + equal(data.state === $.tubeplayer.TubePlayer.State.UNSTARTED || data.state === $.tubeplayer.TubePlayer.State.CUED, true, 'play was triggered, currently unstarted'); + }, + onPlayerPlaying: function() { + + var vol = self.$player.tubeplayer('volume'); + + equal(self.$player.tubeplayer('isMuted'), false, "isn't muted yet"); + + self.$player.tubeplayer('mute'); + + setTimeout(function() { + + equal(self.$player.tubeplayer('isMuted'), true, "should be muted now"); + equal(self.$player.tubeplayer('volume'), vol, "volume should remain, though muted"); + + self.$player.tubeplayer('unmute'); + + setTimeout(function() { + + equal(self.$player.tubeplayer('isMuted'), false, 'should be unmuted'); + equal(self.$player.tubeplayer('volume'), vol, 'volume back to what it was before'); + + self.$player.tubeplayer('stop'); + + }, 50); + + }, 50); + + }, + onStop: function() { + equal(self.$player.tubeplayer('data').state, 1, 'stop was triggered while playing'); + start(); + } + }), 'created, now play then pause'); + + }); + + /** + * S E E K + */ + asyncTest("tubeplayer('seek') -> onSeek", function(){ + + expect(4); + + $.tubeplayer.defaults.afterReady = function($player) { + equal($player.tubeplayer('data').currentTime, 0, 'current time = 0'); + $player.tubeplayer("play"); + }; + + var hasSeeked = false; + + ok(this.$player.tubeplayer({ + width:500, + height:300, + onSeek:function(){ + ok(true); + }, + onPlayerPlaying: function(){ + if(!hasSeeked){ + hasSeeked = true; + this.tubeplayer('seek',100); + } else { + equal(Math.abs(this.tubeplayer('data').currentTime - 100) < 1, true, "seeked to ~100s in"); + start(); + } + } + }), 'created'); + + }); + + /** + * P L A Y E R E N D E D + */ + asyncTest('tubeplayer(\'seek\',[end]) -> onPlayerEnded', function(){ + + expect(2); + + $.tubeplayer.defaults.afterReady = function($player) { + $player.tubeplayer('play'); + }; + + var hasSeeked = false; + + ok(this.$player.tubeplayer({ + initialVideo:'7iEDYB7pY7U', + onPlayerPlaying: function(){ + if(hasSeeked) return; + hasSeeked = true; + this.tubeplayer('seek', this.tubeplayer('data').duration - 2); + }, + onPlayerEnded: function() { + equal(this.tubeplayer('data').state, 0, 'is currently ended'); + start(); + } + }), 'created, now play and skip to end of video'); + + }); + + /** + * S I Z E + */ + asyncTest("tubeplayer('size',{width:400,height:300})", function(){ + + expect(3); + + $.tubeplayer.defaults.afterReady = function($player) { + $player.tubeplayer('size',{ width: 400, height: 300 }); + equal($player.find("iframe").css('width'), "400px", 'same width as just assigned'); + equal($player.find("iframe").css('height'), "300px", 'same height as just assigned'); + start(); + }; + + ok(this.$player.tubeplayer({width:800,height:600}), 'created'); + + }); + + /** + * Q U A L I T Y + */ + asyncTest("tubeplayer('quality') -> onQualityChange", function(){ + + // a change cannot be guaranteed, so this test isn't perfect + + expect(3); + + var QUALITY_TO_SET = "small"; + + $.tubeplayer.defaults.afterReady = function($player) { + equal($player.tubeplayer('quality'), 'unknown', 'Quality is unknown at start'); + $player.tubeplayer("play"); + }; + + ok(this.$player.tubeplayer({ + width:300, + height:200, + preferredQuality: QUALITY_TO_SET, + onPlayerPlaying: function(){ + this.tubeplayer('quality', 'large'); + start(); + }, + onQualityChange: function(){ + notEqual(this.tubeplayer('quality'), QUALITY_TO_SET, 'validate that the quality was set appropriately'); + } + }), 'created'); + + }); + + + /** + * P L A Y B A C K R A T E + */ + asyncTest("tubeplayer('playbackRate'), tubeplayer('data').availablePlaybackRates",function(){ + + expect(5); + + $.tubeplayer.defaults.afterReady = function($player){ + equal($player.tubeplayer('videoId'), "JtbDDqU3dVI", "variable playback rate video set properly"); + $player.tubeplayer('play'); // video has to enable variable playback rate + }; + + ok(this.$player.tubeplayer({ + width: 300, + height: 200, + initialVideo: "JtbDDqU3dVI", + onPlayerPlaying: function(){ + + deepEqual(this.tubeplayer('data').availablePlaybackRates, [ 0.25, 0.5, 1, 1.25, 1.5, 2 ], "available playback rates are consistent"); + + var currentRate = this.tubeplayer('playbackRate'); + equal(currentRate, 1, "player should be at 1x normally"); + + this.tubeplayer('playbackRate', 2); + + var me = this; + setTimeout(function(){ + equal(me.tubeplayer('playbackRate'), 2, "rate was updated to 2x appropriately"); + start(); + },50); + + } + }), 'created'); + + }); + + /** + * D A T A I N T A C T + */ + asyncTest("tubeplayer('data') -> returns defined keys", function(){ + + var expectedKeys = [ + "availablePlaybackRates", + "videoLoadedFraction", + "bytesLoaded", + "bytesTotal", + "startBytes", + "state", + "currentTime", + "duration", + "videoURL", + "videoEmbedCode", + "videoID", + "playlist", + "availableQualityLevels", + "availablePlaybackRates" + ]; + + expect(expectedKeys.length); + + $.tubeplayer.defaults.afterReady = function($player){ + var data = $player.tubeplayer('data'); + for(var key in data){ + equal(expectedKeys.indexOf(key) > -1, true, key + " exists"); + } + start(); + }; + + ok(this.$player.tubeplayer(),"created"); + + }); + + /** + * B A D I N I T S I Z E + * Note: Seems to work with iframe API + */ + // asyncTest("bad init w/ {10,10} (onErrorNotEmbeddable)", function(){ + + // expect(2); + + // $.tubeplayer.defaults.afterReady = function($player) { + // $player.tubeplayer('play'); + // }; + + // ok(this.$player.tubeplayer({ + // autoplay: true, + // width:10, + // height:10, + // onErrorNotEmbeddable: function(){ + // ok(true); + // start(); + // } + // }), 'created'); + + // }); + + /** + * B A D I N I T V I D E O I D + */ + asyncTest("bad init w/ no videoID (onErrorInvalidParameter)", function(){ + + expect(2); + + $.tubeplayer.defaults.afterReady = function($player) { + $player.tubeplayer('play', 'bogus id'); + }; + + ok(this.$player.tubeplayer({ + autoplay: true, + width:200, + height:200, + onErrorInvalidParameter: function(){ + ok(true, "error invalid param has been triggered"); + start(); + } + }), 'created'); + + }); + + /** + * G E T P L A Y E R S + */ + asyncTest("create one, $.tubeplayer.getPlayers() === 1", function(){ + + var players = $.tubeplayer.getPlayers(); + equal(Object.keys(players).length, 0, "no players yet"); + + $.tubeplayer.defaults.afterReady = function(){ + equal(Object.keys($.tubeplayer.getPlayers()).length,1,"one player exists"); + start(); + }; + + ok(this.$player.tubeplayer(), "created"); + + }); + + /** + * M U L T I P L E + * P L A Y E R S + */ + module('Multiple', { + setup: function() { + $(".youtube-player").remove(); + this.$players = $('
'); + $("body").append(this.$players); + }, + teardown: function() { + this.$players.each(function(){ + $(this).tubeplayer('destroy'); + }); + this.$players.remove(); + } + }); + + /** + * C R E A T E + */ + asyncTest("create three, $.tubeplayer.getPlayers() === 3", function(){ + + expect(5); + + var players = $.tubeplayer.getPlayers(); + equal(Object.keys(players).length, 0, "no players yet"); + + var i = 1; + + $.tubeplayer.defaults.afterReady = function(){ + equal(Object.keys($.tubeplayer.getPlayers()).length, i, i + " < # player(s) exist"); + if(i === 3) { // one-based + start(); + } else { + i++; + } + }; + + ok(this.$players.tubeplayer(), "created"); + + }); + + /** + * P L A Y 3 V I D E O S + */ + asyncTest("create three players, tubeplayer('play') 3 unique IDs", function(){ + + expect(7); + + var players = $.tubeplayer.getPlayers(); + equal(Object.keys(players).length, 0, "no players yet"); + + var self = this; + function continueTesting(){ + + var $p1 = $(self.$players[0]); + equal($p1.tubeplayer('data').state, $.tubeplayer.TubePlayer.State.PLAYING, 'is playing'); + $p1.tubeplayer('pause'); + + var $p2 = $(self.$players[1]); + equal($p2.tubeplayer('data').state, $.tubeplayer.TubePlayer.State.CUED, 'is cued'); + // $p2.tubeplayer('pause'); + // equal($p2.tubeplayer('data').state, $.tubeplayer.TubePlayer.State.PAUSED, 'is paused'); + + var $p3 = $(self.$players[2]); + equal($p3.tubeplayer('data').state, $.tubeplayer.TubePlayer.State.CUED, 'is cued'); + // $p3.tubeplayer('pause'); + // equal($p3.tubeplayer('data').state, $.tubeplayer.TubePlayer.State.PAUSED, 'is paused'); + + start(); + + } + + var i = 0, k = 0; // counters used during callback to denote diff. players + + var videoids = ["2Jvju2ceNSE", "VqPo5vueSSA", "yv_iE1pV8gM", "6JM22R_sYs8"]; + + $.tubeplayer.defaults.afterReady = function($player){ + if(i === 0 ){ + $player.tubeplayer("play", videoids[i]); + } else { + $player.tubeplayer("cue", videoids[i]); + } + if(i === 2) { + equal(Object.keys($.tubeplayer.getPlayers()).length, 3, "3 players"); + } + i++; + }; + + ok(this.$players.tubeplayer({ + onPlayerPlaying:function(){ + ok(true, "player started playing"); + continueTesting(); + }, + onPlayerPaused: function(){ + ok(true, "player was paused"); + if(k === 2){ + // start(); + } + k++; + } + }), "created"); + + }); + + QUnit.start(); + }(jQuery));