(function(context,$) { "use strict"; context.JK = context.JK || {}; context.JK.FeedScreen = function(app) { var logger = context.JK.logger; var rest = context.JK.Rest(); var currentQuery = null; var currentPage = 0; var LIMIT = 20; var $screen = null; var $next = null; var $scroller = null; var $content = null; var $noMoreFeeds = null; var $refresh = null; var $sortFeedBy = null; var $includeDate = null; var $includeType = null; var next = null; function defaultQuery() { var query = { limit:LIMIT, page:currentPage}; if(next) { query.since = next; } return query; } function buildQuery() { currentQuery = defaultQuery(); // specify search criteria based on form currentQuery.sort = $sortFeedBy.val(); currentQuery.time_range = $includeDate.val(); currentQuery.type = $includeType.val(); return currentQuery; } function beforeShow(data) { } function afterShow(data) { refresh(); } function clearResults() { currentPage = 0; $content.empty(); // TODO: do we need to delete audio elements? $noMoreFeeds.hide(); next = null; } function handleFeedResponse(response) { next = response.next; renderFeeds(response); if(response.next == null) { // if we less results than asked for, end searching $scroller.infinitescroll('pause'); logger.debug("end of feeds") if(currentPage > 0) { $noMoreFeeds.show(); // there are bugs with infinitescroll not removing the 'loading'. // it's most noticeable at the end of the list, so whack all such entries $('.infinite-scroll-loader').remove(); } } else { currentPage++; buildQuery(); registerInfiniteScroll(); } } function refresh() { clearResults(); currentQuery = buildQuery(); rest.getFeeds(currentQuery) .done(function(response) { handleFeedResponse(response); }) .fail(function(jqXHR) { app.notifyServerError(jqXHR, 'Feed Unavailable') }) } function registerInfiniteScroll() { $scroller.infinitescroll({ behavior: 'local', navSelector: '#feedScreen .btn-next-pager', nextSelector: '#feedScreen .btn-next-pager', binder: $scroller, dataType: 'json', appendCallback: false, prefill: false, bufferPx:100, loading: { msg: $('
Loading ...
'), img: '/assets/shared/spinner.gif' }, path: function(page) { return '/api/feeds?' + $.param(buildQuery()); } },function(json, opts) { handleFeedResponse(json); }); $scroller.infinitescroll('resume'); } function toggleSessionDetails() { var $detailsLink = $(this); var $feedItem = $detailsLink.closest('.feed-entry'); var $musicians = $feedItem.find('.musician-detail'); var $description = $feedItem.find('.description'); var toggledOpen = $detailsLink.data('toggledOpen'); if(toggledOpen) { $feedItem.css('height', $feedItem.height() + 'px') $feedItem.animate({'height': $feedItem.data('original-max-height')}).promise().done(function() { $feedItem.css('height', 'auto').css('max-height', $feedItem.data('original-max-height')); $musicians.hide(); $description.css('height', $description.data('original-height')); $description.dotdotdot(); }); } else { $description.trigger('destroy.dot'); $description.data('original-height', $description.css('height')).css('height', 'auto'); $musicians.show(); $feedItem.animate({'max-height': '1000px'}); } toggledOpen = !toggledOpen; $detailsLink.data('toggledOpen', toggledOpen); return false; } function startSessionPlay($feedItem) { var img = $('.play-icon', $feedItem); var $controls = $feedItem.find('.session-controls'); img.attr('src', '/assets/content/icon_pausebutton.png'); $controls.trigger('play.listenBroadcast'); $feedItem.data('playing', true); } function stopSessionPlay($feedItem) { var img = $('.play-icon', $feedItem); var $controls = $feedItem.find('.session-controls'); img.attr('src', '/assets/content/icon_playbutton.png'); $controls.trigger('pause.listenBroadcast'); $feedItem.data('playing', false); } function toggleSessionPlay() { var $playLink = $(this); var $feedItem = $playLink.closest('.feed-entry'); var $status = $feedItem.find('.session-status') var playing = $feedItem.data('playing'); if(playing) { $status.text('SESSION IN PROGRESS'); stopSessionPlay($feedItem); } else { startSessionPlay($feedItem); } return false; } function stateChangeSession(e, data) { var $controls = data.element; var $feedItem = $controls.closest('.feed-entry'); var $status = $feedItem.find('.session-status'); if(data.displayText) $status.text(data.displayText); if(data.isEnd) stopSessionPlay(); if(data.isSessionOver) { $controls.removeClass('inprogress').addClass('ended') } } function startRecordingPlay($feedItem) { var img = $('.play-icon', $feedItem); var $controls = $feedItem.find('.recording-controls'); img.attr('src', '/assets/content/icon_pausebutton.png'); $controls.trigger('play.listenRecording'); $feedItem.data('playing', true); } function stopRecordingPlay($feedItem) { var img = $('.play-icon', $feedItem); var $controls = $feedItem.find('.recording-controls'); img.attr('src', '/assets/content/icon_playbutton.png'); $controls.trigger('pause.listenRecording'); $feedItem.data('playing', false); } function toggleRecordingPlay() { var $playLink = $(this); var $feedItem = $playLink.closest('.feed-entry'); var playing = $feedItem.data('playing'); if(playing) { stopRecordingPlay($feedItem); } else { startRecordingPlay($feedItem); } return false; } function stateChangeRecording(e, data) { var $controls = data.element; var $feedItem = $controls.closest('.feed-entry'); var $sliderBar = $('.recording-position', $feedItem); var $statusBar = $('.recording-status', $feedItem); var $currentTime = $('.recording-current', $feedItem); var $status = $('.status-text', $feedItem); var $playButton = $('.play-button', $feedItem); if(data.isEnd) stopRecordingPlay($feedItem); if(data.isError) { $sliderBar.hide(); $playButton.hide(); $currentTime.hide(); $statusBar.show(); $status.text(data.displayText); } } function toggleRecordingDetails() { var $detailsLink = $(this); var $feedItem = $detailsLink.closest('.feed-entry'); var $musicians = $feedItem.find('.musician-detail'); var $description = $feedItem.find('.description'); var $name = $feedItem.find('.name'); var toggledOpen = $detailsLink.data('toggledOpen'); if(toggledOpen) { $feedItem.css('height', $feedItem.height() + 'px') $feedItem.animate({'height': $feedItem.data('original-max-height')}).promise().done(function() { $feedItem.css('height', 'auto').css('max-height', $feedItem.data('original-max-height')); $musicians.hide(); $description.css('height', $description.data('original-height')); $description.dotdotdot(); $name.css('height', $name.data('original-height')); $name.dotdotdot(); }); } else { $description.trigger('destroy.dot'); $description.data('original-height', $description.css('height')).css('height', 'auto'); $name.trigger('destroy.dot'); $name.data('original-height', $name.css('height')).css('height', 'auto'); $musicians.show(); $feedItem.animate({'max-height': '1000px'}); } toggledOpen = !toggledOpen; $detailsLink.data('toggledOpen', toggledOpen); return false; } function renderFeeds(feeds) { $.each(feeds.entries, function(i, feed) { if(feed.type == 'music_session_history') { var options = { feed_item: feed, status_class: feed['is_over?'] ? 'ended' : 'inprogress', mount_class: feed['has_mount?'] ? 'has-mount' : 'no-mount' } var $feedItem = $(context._.template($('#template-feed-music-session').html(), options, {variable: 'data'})); var $controls = $feedItem.find('.session-controls'); // do everything we can before we attach the item to the page $('.timeago', $feedItem).timeago(); context.JK.prettyPrintElements($('.duration', $feedItem).show()); context.JK.setInstrumentAssetPath($('.instrument-icon', $feedItem)); $('.details', $feedItem).click(toggleSessionDetails); $('.details-arrow', $feedItem).click(toggleSessionDetails); $('.play-button', $feedItem).click(toggleSessionPlay); // put the feed item on the page renderFeed($feedItem); // these routines need the item to have height to work (must be after renderFeed) $controls.listenBroadcast(); $controls.bind('statechange.listenBroadcast', stateChangeSession); $('.dotdotdot', $feedItem).dotdotdot(); $feedItem.data('original-max-height', $feedItem.css('height')); context.JK.bindHoverEvents($feedItem); } else if(feed.type == 'recording') { if(feed.claimed_recordings.length == 0) { logger.error("a recording in the feed should always have one claimed_recording") return; } var options = { feed_item: feed, candidate_claimed_recording: feed.claimed_recordings[0], mix_class: feed['has_mix?'] ? 'has-mix' : 'no-mix', } var $feedItem = $(context._.template($('#template-feed-recording').html(), options, {variable: 'data'})); var $controls = $feedItem.find('.recording-controls'); $('.timeago', $feedItem).timeago(); context.JK.prettyPrintElements($('.duration', $feedItem)); context.JK.setInstrumentAssetPath($('.instrument-icon', $feedItem)); $('.details', $feedItem).click(toggleRecordingDetails); $('.details-arrow', $feedItem).click(toggleRecordingDetails); $('.play-button', $feedItem).click(toggleRecordingPlay); // put the feed item on the page renderFeed($feedItem); // these routines need the item to have height to work (must be after renderFeed) $controls.listenRecording({recordingId: feed.id, claimedRecordingId: options.candidate_claimed_recording.id, sliderSelector:'.recording-slider', sliderBarSelector: '.recording-playback', currentTimeSelector:'.recording-current'}); $controls.bind('statechange.listenRecording', stateChangeRecording); $('.dotdotdot', $feedItem).dotdotdot(); $feedItem.data('original-max-height', $feedItem.css('height')); context.JK.bindHoverEvents($feedItem); } else { logger.warn("skipping feed type: " + feed.type); } }) } function renderFeed(feed) { $content.append(feed); } function search() { logger.debug("Searching for feeds..."); refresh(); return false; } function events() { $refresh.on("click", search); $sortFeedBy.on('change', search); $includeDate.on('change', search); $includeType.on('change', search); } function initialize() { var screenBindings = { 'beforeShow': beforeShow, 'afterShow': afterShow }; app.bindScreen('feed', screenBindings); $screen = $('[layout-id="feed"]'); $scroller = $screen.find('.content-body-scroller'); $content = $screen.find('.feed-content'); $noMoreFeeds = $('#end-of-feeds-list'); $refresh = $screen.find('#btn-refresh-feed'); $sortFeedBy = $screen.find('#feed_order_by'); $includeDate = $screen.find('#feed_date'); $includeType = $screen.find('#feed_show'); // set default search criteria $sortFeedBy.val('date') $includeDate.val('month') $includeType.val('all') events(); } this.initialize = initialize; return this; } })(window,jQuery);