// This file is renamed to toolbar_player.js in the podomatic project ( function ($) { App.Toolbar.Player = { currentEpisode: null, currentPodcast: null, compact: null, initialize: function () { this.initializeUI(); PodoPreviewPlayer.default_options.trigger_callback = this.triggerCallback; }, triggerCallback: function (episode_list, episode, podcast) { if (App.Toolbar.Player.isVideo(episode)) { App.Overlays.Video.playEpisode(episode); } else if (episode_list) { App.Toolbar.Player.playEpisodeList(episode_list, episode); } else { App.Toolbar.Player.playEpisode(episode, podcast); } }, playEpisode: function (episode, podcast, compact) { // if it's audio, update the player. if it's video, launch the video player if (this.isVideo(episode)) { App.Overlays.Video.playEpisode(episode, compact); } else { App.Toolbar.Player.playEpisodeInternal(episode, podcast, compact); } }, playEpisodeList: function (episode_list, episode) { if (!episode_list) throw "No episode list provided"; this.stopOtherPlayers(); // Extract attributes from models episode_list = episode_list.models || episode_list; if (episode_list[0].attributes) { // Do we have to map it? episode_list = $.map(episode_list, function (epi) { return epi.attributes || epi; }); } if (typeof episode == 'number') { var episodeIndex = episode; episode = episode_list[episodeIndex]; } else { var episodeIndex = episode_list.indexOf(episode); } // Don't reload if (this.currentEpisode && this.currentEpisode.episode_guid == episode.episode_guid && this.currentEpisodeList && this.currentEpisodeList.collection_guid == episodeList.collection_guid) return; this.currentEpisodeList = episode_list; this.playSingleEpisodeFromList(episodeIndex); }, episodeListChanged: function() { if (this.currentEpisodeList) { var last = this.currentEpisodeIndex >= this.currentEpisodeList.length - 1; this.player().enableNextButton( !last ); } }, stop: function () { if (this._player) this._player.pause(); }, playSingleEpisodeFromList: function (episodeIndex) { if (!this.currentEpisodeList) throw "No episode list defined"; if (episodeIndex < 0) return; if (episodeIndex >= this.currentEpisodeList.length) return; var episode = this.currentEpisodeList[episodeIndex]; var podcast = null; this.currentEpisodeIndex = episodeIndex; this.currentEpisode = episode; this.currentPodcast = podcast; var prev_button = episodeIndex > 0; var next_button = episodeIndex < this.currentEpisodeList.length - 1; var player = this.player(); player.loadEpisode({ episode: episode, podcast: podcast, start_playing: true, prev_button: prev_button, next_button: next_button }); this.loadEpisodeDetails(episode); this.updatePlayerUI(episode); this.showPlayer(); this.markEpisodePlayed(episode); }, listenWithEpisode: function (episode, podcast, offset) { alert('This code still needs to be written'); }, isVideo: function (episode) { return (episode.media_type == 'video' && !episode.chapter_count); }, playEpisodeInternal: function (episode, podcast, compact) { console.log("playEpisode id is " + episode.episode_guid); this.stopOtherPlayers(); // Don't reload if (this.currentEpisode && this.currentEpisode.episode_guid == episode.episode_guid) return; this.currentEpisode = episode; this.currentPodcast = podcast; this.currentEpisodeList = undefined; this.currentEpisodeIndex = undefined; var player = this.player(); player.loadEpisode({ episode: episode, podcast: podcast, start_playing: true, prev_button: false, next_button: false }); this.loadEpisodeDetails(episode); this.updatePlayerUI(episode); this.closeAllPanels(); this.showPlayer(compact); this.markEpisodePlayed(episode); }, loadEpisodeDetails: function (episode) { var that = this; //#@todo get real waveform data //var url = '/episodes/' + episode.episode_guid + '?podcast=true&waveform=true&chapters=true'; var url = '/episodes/' + episode.episode_guid + '?podcast=true&chapters=true'; //#@todo change this to a backbone query App.API.get(url).success(function (data) { if (data.status != 'success') { console.log('Episode Load Failed', data); return; } var player = that.player(); that.currentEpisode = data.episode; that.currentPodcast = data.podcast; data.episode.user_episode = data.episode.user_episode || data.user_episode; data.podcast.user_podcast = data.podcast.user_podcast || data.episode.user_podcast || data.user_podcast; player.updateEpisode({ episode: data.episode, podcast: data.podcast, chapters: data.chapters, waveform: data.waveform || that.randomWaveform() }); that.updatePlayerUI(data.episode); }) }, updatePlayerUI: function (episode) { if (episode.downloadable) { var downloadUrl = App.Sharing.downloadUrl(episode); $("#player_panel .download_btn").removeClass('disabled').attr("href", downloadUrl); } else { $("#player_panel .download_btn").addClass('disabled').attr("href", ''); } App.Auth.loggedIn(function () { // update the follow button if the user is logged in var flw = new App.Views.FollowButton({ $container: $('#player_panel .follow_button_wrap'), model: episode }); flw.render(); //#@todo //// update the currently playing episode for listenwith //var lwe = new App.Views.ListenWithEpisode({ // $container: $('#player_panel #lw_right'), // model: episode //}); //lwe.render(); }); }, markEpisodePlayed: function(episode) { // Delay to keep the network and UI free for other calls (audio buffering, animation) setTimeout( function() { var url = '/episodes/' + episode.episode_guid + '/played'; App.API.post(url); App.Channels.MyProfile.resetHistory(); }, 1000); }, showPlayer: function (compact) { $('.player_maxi_flash, .player_controls_right img, .player_controls_right div').css({"visibility": "visible"}); if (compact===undefined) compact = this.compact; if (compact) this.contract(); else this.expand(); }, contract: function () { var $btn = $('#expand_player'); var $panel = $('#player_panel'); this.closeAllPanels(); $btn.attr("src", $btn.attr("src").replace("up", "down")); $btn.removeClass('expanded').addClass('contracted'); App.$frame.add($panel).removeClass('player_expanded').addClass('player_contracted'); this.player().setControlMode('title'); this.compact = true; }, expand: function () { var $btn = $('#expand_player'); var $panel = $('#player_panel'); $btn.attr("src", $btn.attr('src').replace("down", "up")); $btn.removeClass('contracted').addClass('expanded'); App.$frame.add($panel).removeClass('player_contracted').addClass('player_expanded'); this.player().setControlMode('progress'); this.compact = false; }, player: function () { if (!this._player) { var that = this; var options = { // Callback function for when the "next" button was clicked on the player on_next_clicked: function () { that.playSingleEpisodeFromList(that.currentEpisodeIndex + 1); }, // Callback function for when the "previous" button was clicked on the player on_prev_clicked: function () { that.playSingleEpisodeFromList(that.currentEpisodeIndex - 1); }, on_play_clicked: function () { that.stopOtherPlayers(); }, on_share_clicked: function (timestamp) { //#@todo console.log('share clicked at', timestamp); }, on_media_ended: function () { if (that.currentEpisodeList) that.playSingleEpisodeFromList(that.currentEpisodeIndex + 1); } }; this._player = new PodoToolbarPlayer($('.homebase_player'), options); } return this._player; }, stopOtherPlayers: function () { PodoPreviewPlayer.stopAllPlayers(); App.Overlays.Video.stop(); }, initializeUI: function () { var player = this; this.enableForLoggedIn(false); this.initializePlayer(); App.Auth.loggedIn(function () { player.enableForLoggedIn(true); player.initializePanels(); }); }, initializePlayer: function () { $('#player_panel').on("click", "#expand_player", function () { if (($(this).hasClass('expanded'))) App.Toolbar.Player.contract(); else App.Toolbar.Player.expand(); }); $('#player_panel .share_btn, .homebase_btn.share_btn').click(function (e) { if ($(e.currentTarget).hasClass('disabled')) return; App.Overlays.Share.episode(e.currentTarget, App.Toolbar.Player.currentEpisode, App.Toolbar.Player.currentPodcast, true); }); $('#player_panel .add_to_playlist_btn, .homebase_btn.add_to_playlist_btn:not(.inactive)').click(function (e) { App.Overlays.Share.add_to_playlist_menu(e.currentTarget, App.Toolbar.Player.currentEpisode); }); $("#thumbnail_metadata_wrap").on({ mouseenter: function () { App.Toolbar.Player.inMeta = true; }, mouseleave: function () { App.Toolbar.Player.inMeta = false; setTimeout(function () { if (!App.Toolbar.Player.inMeta && !App.Toolbar.Player.inThumb) { $(".playbtn").remove(); $("#thumbnail_metadata_wrap").hide(); } }, 100); } }); //$('#player_panel').on('click', '.back_to_playlists', 'click', function() { // $("#playlists_panel .panel_thumbnails_wrap.sub_list, .back_to_playlists").hide(); // $("#playlists_panel .panel_thumbnails_wrap:not('.sub_list')").fadeIn(); //}); }, enableForLoggedIn: function(loggedIn) { $('#player_panel #history_tab').toggle(loggedIn); $('#player_panel .add_to_playlist_btn').toggleClass('disabled', ! loggedIn); }, initializePanels: function () { //#@todo there is a lot that can be refactored here and in initializePanel // PLAYER PANEL TABS JS: $(".player_maxi_tab").click(function (e) { e.preventDefault(); e.stopImmediatePropagation(); App.Toolbar.Player.panelClosing = true; var $current_tab = $(this); var current_panel = $current_tab.attr('panel'); var current_tab_id = $current_tab.attr("id"); $(".player_maxi_tab").each(function () { if ($(this).attr("id") != current_tab_id) { var imgsrc = $(this).find("img").attr("src"); $(this).find("img").attr("src", imgsrc.replace("over", "up")); } }); if ($current_tab.hasClass('active')) App.Toolbar.Player.closePanel(current_panel); else App.Toolbar.Player.openPanel(current_panel); }); }, closePanel: function (which_panel) { App.Toolbar.Player.panelClosing = true; var $panel = $('#' + which_panel+'_panel'); var $thumbnails = $panel.find('.panel_thumbnails_wrap'); var width = $thumbnails.innerWidth(); $thumbnails.animate({ right: -width }, 500, function () { $(".player_maxi_tab").removeClass("active"); $panel.hide(); App.Toolbar.Player.panelClosing = false; }); }, closeAllPanels: function() { this.closePanel('history'); }, initializePanel: function (which_panel) { // Panel Close Button $(which_panel + " img.close_white").on("click", function () { var thispanel = '#' + $(this).closest('.player_tab_panel').attr("id"); App.Toolbar.Player.closePanel(thispanel); }); //Panel Gear Button $(which_panel + " img.gear_icon").on({ mouseenter: function () { var $this = $(this); var src = $this.attr("src").replace('_off', '_over'); $this.addClass("hover").attr("src", src); }, mouseleave: function () { var $this = $(this); var thispanel = "#" + $this.attr("panel") + "_gear_panel"; if ($(thispanel).css("display") == "none") { var src = $this.attr("src").replace('_over', '_off'); $this.removeClass("hover").attr("src", src); } }, click: function () { var $menu = $("#" + $(this).attr("panel") + "_gear_panel"); if ($menu.is(":visible")) { $menu.hide(); } else { App.Util.setOffset($menu, this); $menu.show(); } } }); var $wrap = $(which_panel + " .panel_thumbnails_wrap"); $wrap.width( $wrap.find('.panel_thumbnail').length * 58.5 ); $(which_panel + ".player_tab_panel .panel_thumbnail").on({ mouseenter: function () { $(".playbtn").remove(); $("#thumbnail_metadata_wrap").hide(); App.Toolbar.Player.inThumb = true; if (!App.Toolbar.Player.panelClosing) { $('
').insertBefore($(this).find("img")); if ($(this).find(".media_metadata").length) { $("#thumbnail_metadata").html(""); $("#thumbnail_metadata").html($(this).find(".media_metadata").html()); App.Util.setOffset($("#thumbnail_metadata_wrap"), this, true).show(); } } }, mouseleave: function () { App.Toolbar.Player.inThumb = false; setTimeout(function () { if (!App.Toolbar.Player.inMeta && !App.Toolbar.Player.inThumb && !App.Toolbar.Player.panelClosing) { $(".playbtn").remove(); $("#thumbnail_metadata_wrap").hide(); } }, 100); } }); $(which_panel + " .scrollbar_grabber").draggable( { axis: "x", containment: "parent", drag: function (event, ui) { var percentscrolled = parseInt($(this).position().left) / (parseInt($(this).parent().outerWidth()) - 102); $(this).parent().parent().find(".panel_thumbnails").css({ "margin-left": 0 - (percentscrolled * $(this).parent().parent().attr("maxleft")) + "px" }); } } ); }, //#@todo remove this and the dependent vies/css //createPlaylistsPanel: function() { // App.Channels.Playlists.playlistsData(function (playlists) { // // if (playlists.length) { // var view = new App.Views.PlaylistsAccordion({ // $container: $('#playlists_panel'), // model: playlists // }); // view.render(); // App.Toolbar.Player.initializePanel('#playlists_panel'); // // } else { // var empty_img = ""; // var message = 'You have no playlists'; // $("#history_panel").addClass("empty").html(empty_img + message); // // } // // }); //}, // //createFollowingPanel: function() { // // App.Channels.Following.followingData(function (following) { // // if (following.length) { // // var view = new App.Views.FollowingAccordion({ // $container: $('#following_panel'), // model: following // }); // view.render(); // App.Toolbar.Player.initializePanel('#following_panel'); // // } else { // var empty_img = ""; // var message = 'You are not following anyone'; // $("#history_panel").addClass("empty").html(empty_img + message); // // } // // }); // //}, openPanel: function (which_panel) { var $panel = $('#' + which_panel + '_panel'); $('#' + which_panel + '_tab').addClass("active"); var view = new App.Views.PanelSpinner({ $container: $panel.empty() }); view.render(); var $wrap = $panel.find(".panel_thumbnails_wrap"); $wrap.width( 58 ); this.expandPanel($panel); this['load_' + which_panel](function () { App.Toolbar.Player.expandPanel($panel); }); }, expandPanel: function($panel) { var $thumbnails = $panel.find('.panel_thumbnails_wrap'); var width = $thumbnails.innerWidth(); $thumbnails.width(width); $panel.width( Math.min(936, width) ); $panel.show(); $thumbnails.css('right', -width); $thumbnails.animate( {right:0}, 500, function() { App.Toolbar.Player.panelClosing = false; }); }, load_history: function (callback) { App.Channels.MyProfile.historyData(function (history) { var episodes = history.episodes || history.models[0].get("episodes"); if (episodes.length) { // history is loaded, now send it to the toolbar var view = new App.Views.HistoryAccordion({ $container: $('#history_panel').empty(), model: history.models ? history.models[0] : history }); view.render(); App.Toolbar.Player.initializePanel('#history_panel'); $("#history_panel").removeClass("empty"); } else { var message = 'You have no history'; var $el = $('