(function (context, $) { "use strict"; context.JK = context.JK || {}; context.JK.Feed = function (app) { var logger = context.JK.logger; var rest = new context.JK.Rest(); var EVENTS = context.JK.EVENTS; var ui = new context.JK.UIHelper(JK.app); var recordingUtils = context.JK.RecordingUtils; var userId = null; var bandId = null; var currentFeedPage = 0; var feedBatchSize = 20; var $screen = null; var $scroller = null; var $content = null; var $noMoreFeeds = null; var $refresh = null; var $sortFeedBy = null; var $includeDate = null; var nextPage = 1; var $includeType = null; var didLoadAllFeeds = false, isLoading = false; var $templateRecordingDiscardedSoon = null; var defaults; function defaultQuery() { var query = { limit: feedBatchSize }; if(nextPage) { query.next_page = nextPage; } if(userId) { query.user = userId; } if(bandId) { query.band = bandId; } return query; } function buildQuery() { var currentQuery = defaultQuery(); // specify search criteria based on form currentQuery.sort = $sortFeedBy.length == 0 ? defaults.sort : $sortFeedBy.val(); currentQuery.time_range = $includeDate.length == 0 ? defaults.time_range : $includeDate.val(); currentQuery.type = $includeType.length == 0 ? defaults.type : $includeType.val(); return currentQuery; } function clearResults() { didLoadAllFeeds = false; currentFeedPage = 0; $content.empty(); // TODO: do we need to delete audio elements? $noMoreFeeds.hide(); nextPage = 1; } function handleFeedResponse(response) { nextPage = response.next_page; renderFeeds(response); if(nextPage == null) { didLoadAllFeeds = true; // if we got less results than asked for, end searching logger.debug("end of feeds") if(currentFeedPage == 0 && response.entries.length == 0) { $content.append("
This user has no history.
") ; } if(currentFeedPage > 0) { $noMoreFeeds.show(); } } else { currentFeedPage++; } } function setUser(_userId) { userId = _userId; } function setBand(_bandId) { bandId = _bandId; } function refresh() { clearResults(); populate(); } function setLoading(yn) { isLoading = yn; if (yn) { $('#'+screenID()+'-loading-feeds').show(); } else { $('#'+screenID()+'-loading-feeds').hide(); } } function populate() { if (isLoading || didLoadAllFeeds) return; setLoading(true); rest.getFeeds(buildQuery()) .done(function(response) { handleFeedResponse(response); setLoading(false); }) .fail(function(jqXHR) { setLoading(false); app.notifyServerError(jqXHR, 'Feed Unavailable') }); } 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($feedItem); 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 isOwner() { return userId == context.JK.currentUserId; } function screenID() { return $screen.attr('id'); } function obtainCandidate(recording) { if(isOwner()) { var candidate = null; context._.each(recording.claimed_recordings, function(claimedRecording) { if(claimedRecording.user_id == context.JK.currentUserId) { candidate = claimedRecording; return false; } }) if(!candidate) throw "unable to find candidate claimed recording, yet we can see this recording. server error..." return candidate; } else { return recording.claimed_recordings[0]; } } function toggleOpen($feedItem, $name, $description, $musicians) { $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'}); } function toggleClose($feedItem, $name, $description, $musicians, immediate) { $feedItem.css('height', $feedItem.height() + 'px') $feedItem.animate({'height': $feedItem.data('original-max-height')}, immediate ? 0 : 400).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(); }); } 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) { toggleClose($feedItem, $name, $description, $musicians) } else { toggleOpen($feedItem, $name, $description, $musicians) } toggledOpen = !toggledOpen; $detailsLink.data('toggledOpen', toggledOpen); return false; } function updateRecordingName($feedEntry, name) { $feedEntry.find('.name-text').text(name); } function updateRecordingDescription($feedEntry, description) { $feedEntry.find('.description').text(description); } function updateIsPublic($feedEntry, isPublic) { var $isPrivate = $feedEntry.find('.is_private') if(isPublic) { $isPrivate.removeClass('enabled') } else { if(!isOwner()) { $feedEntry.find('.play-button').hide(); // still show play button if private && isOwner() } $isPrivate.addClass('enabled') } } function updateComments($feedEntry, comments) { $feedEntry.find('.comments').html(comments) } function updatePlays($feedEntry, plays) { $feedEntry.find('.plays').html(plays); } function updateLikes($feedEntry, likes) { $feedEntry.find('.likes').html(likes); } function updateStats($feedEntry) { if($feedEntry.is('.recording-entry')) { var id = $feedEntry.attr('data-claimed-recording-id'); rest.getClaimedRecording(id) .done(function(claimedRecording) { updateComments($feedEntry, claimedRecording.recording.comment_count); updateLikes($feedEntry, claimedRecording.recording.like_count); updatePlays($feedEntry, claimedRecording.recording.play_count); }) .fail(app.ajaxError) } else { var id = $feedEntry.attr('data-music-session'); rest.getSessionHistory(id) .done(function(music_session) { updateComments($feedEntry, music_session.comment_count); updateLikes($feedEntry, music_session.like_count); updatePlays($feedEntry, music_session.play_count); }) .fail(app.ajaxError) } } function updateGenre($feedEntry, genre) { $feedEntry.find('.genre').text(context.JK.GenreSelectorHelper.getNameForId(genre)); } function renderFeeds(feeds) { $.each(feeds.entries, function(i, feed) { if(feed.type == 'music_session') { 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); 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() { var result = ui.launchCommentDialog({ session_id: feed.id, entity_type: 'session' }).one(EVENTS.DIALOG_CLOSED, function() { updateStats($feedItem); }) }); $('.btn-like', $feedItem).click(function() { ui.addSessionLike(feed.id, JK.currentUserId, $('.likes', $feedItem), $('.btn-like', $feedItem)) }); // should we show the select checkbox? if(!defaults.show_checkbox) { $feedItem.find('.select-box').hide(); } // 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); context.JK.bindProfileClickEvents($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; } // pump some useful data about mixing into the feed item feed.mix_info = recordingUtils.createMixInfo({state: feed.mix_state}) var options = { feed_item: feed, candidate_claimed_recording: obtainCandidate(feed), 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'); var $titleText = $feedItem.find('.title .title-text'); // if this item will be discarded, tack on a * to the RECORDING NAME var discardTime = feed['when_will_be_discarded?']; if(discardTime) { context.JK.helpBubble($titleText, 'recording-discarded-soon', {discardTime: discardTime}, {}); $titleText.text($titleText.text() + '*'); } $controls.data('mix-state', feed.mix_info) // for recordingUtils helper methods $controls.data('server-info', feed.mix) // for recordingUtils helper methods $controls.data('view-context', 'feed') // tack on video if available if(feed.external_video_id) { var $videoWrapper = $feedItem.find('.video-wrapper') var $videoContainer = $feedItem.find('.video-container') if(gon.isNativeClient) { var $embed = $('' + '' + '') $videoContainer.append($embed).addClass('no-embed') $videoWrapper.removeClass('hidden') $embed.click(function() { context.JK.popExternalLink($(this).attr('href')) return false; }) } else { var $embed = $('