Last active
August 29, 2015 14:01
-
-
Save dopa/29e88b385545cb01ffdb to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*jshint forin:true, noarg:true, noempty:true, eqeqeq:true, bitwise:true, strict:true, undef:true, unused:true, curly:true, browser:true, devel:true, jquery:true, indent:4, maxerr:50, laxcomma:true, indent:false, unused: false */ | |
/*global Pusher:false, Handlebars:false, Modernizr:false, store:false, performance:false */ | |
;(function($, doc, win){ | |
"use strict"; | |
var $app, appEnvironment, realtime_templates = {}; | |
var pusherIsConnected=false; | |
var $pings, pingInterval; | |
var meetingId, meetingChannelName, meetingChannel; | |
var sessionChannel, boundSessionChannelEventId=-1; | |
var $attendee, isSignedIn=false, attendeeId, attendeeChannelName, attendeeChannel; | |
function init() { | |
$app = $('#app'); | |
$pings = $('#pings'); | |
$app.data('pings',[]); | |
appEnvironment = $app.data('appenvironment'); | |
meetingId = $app.data('meetingid'); | |
meetingChannelName = 'meeting_'+meetingId; | |
$attendee = $('#attendee'); | |
if( $attendee.length ) { | |
isSignedIn = true; | |
attendeeId = $attendee.data('attendeeid'); | |
attendeeChannelName = meetingChannelName + '_attendee_' + attendeeId; | |
var teamId = $attendee.data('teamid'); | |
if( typeof teamId !== 'undefined' && teamId.toString().length > 0 && parseInt(teamId,10) > 0 ) { | |
if ( Modernizr.localstorage ){ | |
store.set('meeting_'+meetingId+'_teamId',teamId); | |
} | |
} | |
} | |
if( $('.initPush').length ) { | |
if ( !$app.length ) { return; } | |
var pusherKey = $app.data('pusherkey'); | |
if( typeof pusherKey === 'undefined' || typeof Pusher === 'undefined' ) { return; } | |
win.pusher = new Pusher(pusherKey); | |
} | |
listen(); | |
connect(); | |
if ( window.performance ) { // disable ping feature if not supported on device | |
connect(); | |
} else { | |
hidePingButton(); | |
} | |
} | |
// TEMP ----> Pusher Debugging to Console | |
// if( $('#app').data('appenvironment') === "development" && typeof Pusher !== 'undefined' ) { | |
// Pusher.log = function(message) { | |
// if (window.console && window.console.log) window.console.log(message); | |
// }; | |
// } | |
function printConnectingIn(ms) { | |
if( appEnvironment === "development" ) { | |
console.log("Connecting in",Math.abs(ms),"ms."); | |
} | |
} | |
function connect() { | |
var timerId, $indicator = $(".indicator-connection"); | |
win.pusher.connection.bind('connecting_in', function(delay) { | |
clearInterval(timerId); | |
if( $indicator.length ) { | |
$indicator.attr('class','indicator-connection isDisconnected'); | |
} | |
timerId = setInterval(function() { | |
delay = delay - 1000; | |
printConnectingIn(delay); | |
}, 1000); | |
}); | |
win.pusher.connection.bind('connected', function() { | |
clearInterval(timerId); | |
if( !pusherIsConnected ) { | |
$indicator.attr('class', "indicator-connection isConnected"); | |
$app.trigger('pusherConnected'); | |
} | |
pusherIsConnected = true; | |
}); | |
win.pusher.connection.bind('disconnected', function() { | |
$indicator.attr("class", "indicator-connection isDisconnected"); | |
}); | |
win.pusher.connection.bind('failed', function() { | |
$indicator.attr("class", "indicator-connection isDisconnected"); | |
}); | |
win.pusher.connection.bind('unavailable', function() { | |
$indicator.attr("class", "indicator-connection isDisconnected"); | |
}); | |
} | |
function listen() { | |
$app.on('pusherConnected', function(){ | |
var channelsBound = $app.data('channelsbound'); | |
if( typeof channelsBound === 'undefined' ) { | |
bindMeetingChannelEvents(); | |
if( isSignedIn ) { | |
bindAttendeeChannelEvents(); | |
} | |
bindSessionChannelEvents(null, 0); // listen for event-wide new posts, etc. | |
// session channel events must be bound here even for safety, | |
// even if history is going to pull in new session | |
$app.data('channelsbound', true); //.trigger('bindChannels'); | |
$app.data('isloading', false); | |
} | |
}); | |
$app.on('bindSessionChannelEvents', bindSessionChannelEvents); | |
$app.on('click','.x-ping', initiatePing); | |
$app.on('pong', receivePong); | |
} | |
function bindMeetingChannelEvents() { | |
meetingChannel = win.pusher.subscribe(meetingChannelName); | |
meetingChannel.bind('announcement', function(data){ | |
$app.trigger('displayAnnouncement', data); | |
}); | |
// right now this is used for realtime leaderboards in leaderboards.js | |
// this can be a points update for any attendee at this meeting | |
// not just the current_attendee | |
meetingChannel.bind('points_updated', function(data){ | |
$app.trigger('pointsUpdated', data); | |
}); | |
meetingChannel.bind('event_points_updated', function(data){ | |
$app.trigger('eventPointsUpdated', data); | |
}); | |
meetingChannel.bind('attendee_joined_meeting', function(data){ | |
$app.trigger('attendee_joined_meeting',[data]); | |
}); | |
meetingChannel.bind('attendee_joined_event', function(data){ | |
$app.trigger('attendee_joined_event',[data]); | |
}); | |
meetingChannel.bind('photo_created', function(data){ | |
$app.trigger('appendPhoto', data); | |
}); | |
meetingChannel.bind('photo_removed', function(data){ | |
$app.trigger('removePhoto', data); | |
}); | |
meetingChannel.bind('photo_reposted', function(data){ | |
$app.trigger('displayNewPhotoRepostCount', data); | |
}); | |
meetingChannel.bind('remove_question_from_projection', function(j){ | |
$app.trigger('questionRemovedFromProduction',[j]); | |
}); | |
meetingChannel.bind('survey_deployed', function(data){ | |
$app.trigger('deploySurvey',[data]); | |
}); | |
meetingChannel.bind('survey_cleared', function(data){ | |
$app.trigger('clearSurvey',[data]); | |
}); | |
meetingChannel.bind('icebreaker_deployed', function(data){ | |
$app.trigger('deployIcebreaker',[data]); | |
}); | |
meetingChannel.bind('icebreaker_cleared', function(data){ | |
$app.trigger('clearIcebreaker',[data]); | |
}); | |
} | |
function bindAttendeeChannelEvents() { | |
attendeeChannel = win.pusher.subscribe(attendeeChannelName); | |
attendeeChannel.bind('points_earned', function(data){ | |
$app.trigger('bumpPoints',[data]); | |
}); | |
attendeeChannel.bind('badge_earned', function(data){ | |
$app.trigger('displayNewBadge',[data]); | |
}); | |
attendeeChannel.bind('mission_completed', function(data){ | |
$app.trigger('displayNewMission',[data]); | |
}); | |
attendeeChannel.bind('prize_won', function(data){ | |
$app.trigger('displayNewPrize',[data]); | |
}); | |
attendeeChannel.bind('pong', function(jres){ | |
$app.trigger('pong', jres); | |
}); | |
} | |
function bindSessionChannelEvents(e,eventId) { | |
// 3 possibilities: no channel bound, same channel, or new channel being bound | |
if( boundSessionChannelEventId === -1 ) { | |
// do nothing | |
} else if( boundSessionChannelEventId === eventId ) { | |
return; | |
} else { // new session - need to unbind old one | |
var oldSessionChannelName = getSessionChannelName(boundSessionChannelEventId); | |
win.pusher.unsubscribe(oldSessionChannelName); | |
} | |
var sessionChannelName = getSessionChannelName(eventId); | |
boundSessionChannelEventId = eventId; | |
sessionChannel = win.pusher.subscribe(sessionChannelName); | |
sessionChannel.bind('post_created', function(data) { | |
if( !$app.data('isloading') ) { // isotope can't take new messages while loading, so have to ignore | |
$app.trigger('postCreated', data); | |
} | |
}); | |
sessionChannel.bind('question_created', function(j){ | |
var q = j.question; | |
$app.trigger('update_stat',[{selector: '#sesh .questions-total', subselector: ".fig"},{count: q.event_questions_count}]); | |
}); | |
// this only happens when questions are removed | |
sessionChannel.bind('question_count_updated', function(j){ | |
$app.trigger('update_stat',[{selector: '#sesh .questions-total', subselector: ".fig", onlyIncrement: false},{count: j.count}]); | |
}); | |
sessionChannel.bind('checkin_count_updated', function(j) { | |
$app.trigger('update_stat',[{selector: '.'+ j.context +'-'+ j.id +' .counter-checkins'},{count: j.count}]); | |
}); | |
sessionChannel.bind('message_count_updated', function(j) { | |
$app.trigger('update_stat',[{selector: '.'+ j.context +'-'+ j.id +' .counter-messages'},{count: j.count}]); | |
win.setLedgerCount('event_total_messages', parseInt(j.count, 10)); | |
}); | |
sessionChannel.bind('repost_count_updated', function(j) { | |
$app.trigger('update_stat',[{selector: '.'+ j.context +'-'+ j.id +' .counter-remessages'},{count: j.count_parent}]); | |
}); | |
sessionChannel.bind('author_repost_count_updated', function(j){ | |
$app.trigger('authorRepostCountUpdated', j); | |
}); | |
sessionChannel.bind('event_photo_count_updated', function(j) { | |
$app.trigger('update_stat',[{selector: '.'+ j.context +'-'+ j.id +' .photos-total', subselector: ".fig"},{count: j.count_parent}]); | |
}); | |
sessionChannel.bind('message_action', function(data){ | |
$app.trigger('completeMessageAction', [data]); | |
}); | |
sessionChannel.bind('rating_updated', function(data){ | |
$app.trigger('updateRating', [data]); | |
}); | |
} | |
function getSessionChannelName(eventId) { | |
return meetingChannelName + "_session_" + eventId; | |
} | |
// PING | |
function initiatePing(e){ | |
e.preventDefault(); | |
var $btn = $(this); | |
if( $btn.hasClass('isPinging') ) { | |
stopPinging(); | |
$btn.text('Start Pinging'); | |
} else { | |
startPinging(); | |
$btn.text('Stop Pinging'); | |
} | |
$btn.toggleClass('isPinging'); | |
} | |
function startPinging() { | |
$app.data('pinging',true); | |
pingInterval = setInterval(sendPing,1000); | |
} | |
function stopPinging() { | |
clearInterval(pingInterval); | |
} | |
function sendPing() { | |
var templates = lazyCompileTemplates(); // must be first | |
var sent = performance.now(); | |
var id = parseInt(sent,10); | |
var ping = { | |
id: id, | |
sent_at: (new Date()).toTimeString().substring(0,8), | |
sent: sent, | |
rcvd_at: null, | |
rcvd_json: null, | |
rcvd_push: null, | |
elapsed_json: null, | |
elapsed_push: null | |
}; | |
var html = templates.ping.call(this, ping); | |
$pings.prepend(html); | |
var jqxhr = $.ajax({ | |
url: '/send_ping', | |
type: 'GET', | |
dataType: 'json', | |
data: { id: id } | |
}).fail(function(result){ | |
var $ping = $pings.find('.ping-'+id); | |
$ping.find('.elapsed_json').toggleClass('hasError',true).text('ERROR'); | |
}).done(function(result){ | |
ping.rcvd_json = performance.now(); | |
var $ping = $pings.find('.ping-'+id); | |
ping.elapsed_json = ping.rcvd_json - sent; | |
ping.elapsed_json_friendly = parseInt(ping.elapsed_json, 10) + " ms"; | |
$ping.find('.elapsed_json').toggleClass('hasError',false).text(ping.elapsed_json_friendly); | |
}); | |
} | |
function receivePong(e,id){ | |
var $ping = $pings.find('.ping-'+id); | |
var sent = parseFloat( $ping.data('sent') ); | |
var elapsed_push = performance.now() - sent; | |
var elapsed_push_friendly = parseInt(elapsed_push, 10) + " ms"; | |
$ping.find('.elapsed_push').text(elapsed_push_friendly); | |
} | |
function hidePingButton(){ | |
$('.x-ping').hide(); | |
$('.not-supported').show(); | |
} | |
function lazyCompileTemplates() { // don't run on init | |
if( !realtime_templates.hasOwnProperty('compiled') ) { | |
//game_templates.activity_items = Handlebars.compile( $('#activity-items-template').html() ); | |
realtime_templates.ping = Handlebars.compile( $('#ping-template').html() ); | |
} | |
return realtime_templates; | |
} | |
$(function(){ | |
init(); | |
}); | |
})(jQuery, document, window); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment