jam-cloud/web/app/assets/javascripts/feed.js

449 lines
14 KiB
JavaScript

(function(context,$) {
"use strict";
context.JK = context.JK || {};
context.JK.FeedScreen = function(app) {
var logger = context.JK.logger;
var rest = new context.JK.Rest();
var ui = new context.JK.UIHelper(JK.app);
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: $('<div class="infinite-scroll-loader">Loading ...</div>'),
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 toggleUserProfile() {
var userId = $(this).attr('user-id');
window.location = '/client#/profile/' + userId;
return false;
}
function toggleBandProfile() {
var bandId = $(this).attr('band-id');
if (bandId == null) {
var userId = $(this).attr('user-id');
window.location = '/client#/profile/' + userId;
}
else {
window.location = '/client#/bandProfile/' + bandId;
}
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);
$('.avatar-tiny', $feedItem).click(toggleUserProfile);
$('.musician-name', $feedItem).click(toggleUserProfile);
$('.artist', $feedItem).click(toggleBandProfile);
if (!feed.session_removed_at)
{
$('.btn-share', $feedItem).click(function() {
ui.launchShareDialog(feed.id, 'session');
});
}
else {
$('.btn-share', $feedItem).hide();
}
$('.btn-comment', $feedItem).click(function() {
ui.launchCommentDialog(feed.id, 'session');
});
$('.btn-like', $feedItem).click(function() {
ui.addSessionLike(feed.id, JK.currentUserId, $('.likes', $feedItem), $('.btn-like', $feedItem))
});
// 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);
$('.btn-share', $feedItem).click(function() {
ui.launchShareDialog(options.candidate_claimed_recording.id, 'recording');
});
$('.btn-comment', $feedItem).click(function() {
ui.launchCommentDialog(feed.id, 'recording');
});
$('.btn-like', $feedItem).click(function() {
ui.addRecordingLike(feed.id, options.candidate_claimed_recording.id, JK.currentUserId, $('.likes', $feedItem), $('.btn-like', $feedItem));
});
// 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);