jam-cloud/app/assets/javascripts/createSession.js

369 lines
13 KiB
JavaScript

(function(context,$) {
"use strict";
context.JK = context.JK || {};
context.JK.CreateSessionScreen = function(app) {
var logger = context.JK.logger;
var realtimeMessaging = context.JK.JamServer;
var autoComplete = null;
var usernames = [];
var userids = [];
/*
Message from Seth on sequence for creating/joining sessions:
02:31:46 PM) Seth Call: sequence:
(02:31:53 PM) Seth Call: LOGIN websocket (get your client_id)
(02:32:02 PM) Seth Call: CRETAE SESSION
(02:32:09 PM) Seth Call: CREATE PARTICIPANT (pass in client_id)
(02:32:12 PM) Seth Call: that's it for client 1
(02:32:13 PM) Seth Call: client 2
(02:32:20 PM) Seth Call: LOGIN WEBSOCKET (get your client_id)
(02:32:29 PM) Seth Call: CREATE PARTICIPANT(pass in client_id for client2)
(02:32:31 PM) Seth Call: that's it
(02:32:43 PM) Seth Call: USER_JOINED_MUSIC_SESSION is an event from the server
(02:32:52 PM) Seth Call: and LOGIN_MUSIC_SESSION is deprecated/junk
*/
function beforeShow(data) {
usernames = [];
userids = [];
resetForm();
}
/**
* Reset form to initial state.
*/
function resetForm() {
var $form = $('#create-session-form');
$('textarea[name="description"]', $form).val('');
}
function afterShow(data) {
// TODO: This won't work in the long-term. We'll need to provide
// a handlers which accepts some characters and only returns users
// who are musicians who match that input string. Once we get there,
// we could just use the ajax functionality of the autocomplete plugin.
//
// But for now:
// Load the users list into our local array for autocomplete.
$.ajax({
type: "GET",
url: "/api/users"
}).done(function(response) {
$.each(response, function() {
usernames.push(this.name);
userids.push(this.id);
});
// Hook up the autocomplete.
var autoCompleteOptions = {
lookup: {suggestions:usernames, data: userids},
onSelect: addInvitation
};
if (!(autoComplete)) {
autoComplete = $('#invitations').autocomplete(autoCompleteOptions);
} else {
autoComplete.setOptions(autoCompleteOptions);
}
});
}
function addInvitation(value, data) {
var username = value;
var userid = data;
var template = $('#template-added-invitation').html(); // TODO: cache this
var inviteHtml = context.JK.fillTemplate(template, {userId: userid, userName: username});
$('#added-invitations').append(inviteHtml);
$('#invitations').select();
}
/**
* Validate the form, returning a list of errors.
*/
function validateForm() {
var errors = [];
var $form = $('#create-session-form');
// Description can't be empty
var description = $('#description').val();
if (!description) {
errors.push(['#description', "Please enter a description."]);
}
var genres = getSelectedGenres();
if (genres.length == 0) {
errors.push(['#genre-list-items', "Please select a genre."]);
}
if (genres.length > 3) {
errors.push(['#genre-list-items', "No more than 3 genres are allowed."]);
}
return (errors.length) ? errors : null;
}
function getSelectedGenres() {
var selectedGenres = [];
$('#genre-list-items :checked').each(function() {
selectedGenres.push($(this).val());
});
return selectedGenres;
}
function submitForm(evt) {
evt.preventDefault();
var formErrors = validateForm();
if (formErrors) {
app.notify({
title: "Validation Errors",
text: JSON.stringify(formErrors)
});
return false;
}
var $this = $(evt.currentTarget);
logger.debug($this.length);
var data = {};
data.client_id = app.clientId;
data.description = $('#description').val()
data.as_musician = true;
data.legal_terms = true; // this overrides the default of 'on', which isn't satisfying our concept of boolean
data.genres = getSelectedGenres();
data.musician_access = $('#musician-access option:selected').val() === "true" ? true : false;
data.approval_required = $("input[name='musician-access-option']:checked").val() === "true" ? true : false;
data.fan_access = $('#fan-access option:selected').val() === "true" ? true : false;
data.fan_chat = $("input[name='fan-chat-option']:checked").val() === "true" ? true : false;
if ($('#band-list option:selected').val() != '') {
data.band = $('#band-list option:selected').val();
}
// FIXME: Hard-code tracks for now. Needs to default to:
// 1. If no previous session data, a single stereo track with the
// top instrument in the user's profile.
// 2. Otherwise, use the tracks from the last created session.
data.tracks = [
{ instrument_id: "electric guitar", sound: "mono" },
{ instrument_id: "keyboard", sound: "mono" }
];
var jsonData = JSON.stringify(data);
var url = "/api/sessions";
$.ajax({
type: "POST",
dataType: "json",
contentType: 'application/json',
url: url,
processData:false,
data: JSON.stringify(data),
success: function(response) {
var newSessionId = response.id;
createInvitations(newSessionId, function() {
context.location = '#/session/' + newSessionId;
});
},
error: app.ajaxError
});
return false;
}
function createInvitations(sessionId, onComplete) {
var callCount = 0;
$('#added-invitations .invitation').each(function(index, invitation) {
callCount++;
var invite_id = $(invitation).attr('user-id');
var invite = {
music_session: sessionId,
receiver: invite_id
};
$.ajax({
type: "POST",
url: "/api/invitations",
data: invite
}).done(function(response) {
callCount--;
}).fail(app.ajaxError);
});
// TODO - this is the second time I've used this pattern.
// refactor to make a common utility for this.
function checker() {
if (callCount === 0) {
onComplete();
} else {
context.setTimeout(checker, 10);
}
}
checker();
}
function events() {
$('#create-session-form').submit(submitForm);
$('#added-invitations').on("click", ".invitation span", removeInvitation);
$('#genre-list-header').on("click", toggleGenreBox);
$('#genre-list-arrow').on("click", toggleGenreBox);
$('#genre-list-items input[type=checkbox]').each(function() {
$(this).on("click", updateGenreCount);
});
$('#musician-access').change(toggleMusicianAccess);
$('#fan-access').change(toggleFanAccess);
}
// Used to disable checkboxes once 3 genres are selected.
function updateGenreCount() {
var genreCount = parseInt($('#genre-count').val());
if ($(this).attr('checked')) {
genreCount++;
}
else {
genreCount--;
}
$('#genre-count').val(genreCount);
var disabled = false;
if (genreCount == 3) {
disabled = true;
}
$('#genre-list-items input[type=checkbox]').each(function() {
if (!$(this).attr('checked')) {
if (disabled) {
$(this).attr('disabled', 'disabled');
}
else {
$(this).removeAttr('disabled');
}
}
});
}
function removeInvitation(evt) {
$(evt.currentTarget).closest('.invitation').remove();
}
function toggleMusicianAccess() {
var value = $("#musician-access option:selected").val();
if (value == "false") {
$("input[name='musician-access-option']").attr('disabled', 'disabled');
$("input[name='musician-access-option']").parent().addClass("op50");
}
else {
$("input[name='musician-access-option']").removeAttr('disabled');
$("input[name='musician-access-option']").parent().removeClass("op50");
}
}
function toggleFanAccess() {
var value = $("#fan-access option:selected").val();
if (value == "false") {
$("input[name='fan-chat-option']").attr('disabled', 'disabled');
$("input[name='fan-chat-option']").parent().addClass("op50");
}
else {
$("input[name='fan-chat-option']").removeAttr('disabled');
$("input[name='fan-chat-option']").parent().removeClass("op50");
}
}
function loadGenres() {
var url = "/api/genres";
$.ajax({
type: "GET",
url: url,
async: false, // do this synchronously so the event handlers in events() can be wired up
success: genresLoaded
});
}
function genresLoaded(response) {
$.each(response, function() {
var template = $('#template-genre-option').html();
var genreOptionHtml = context.JK.fillTemplate(template, {value: this.id, label: this.description});
$('#genre-list-items').append(genreOptionHtml);
});
}
function toggleGenreBox() {
var boxHeight = $('#genre-list').css("height");
// TODO: clean this up (check class name of arrow to determine current state)
if (boxHeight == "20px") {
$('#genre-list').css({height: "auto"});
$('#genre-list-arrow').removeClass("arrow-down").addClass("arrow-up");
}
else {
$('#genre-list').css({height: "20px"});
$('#genre-list-arrow').removeClass("arrow-up").addClass("arrow-down");
}
}
function loadBands() {
var url = "/api/users/" + context.JK.currentUserId + "/bands";
$.ajax({
type: "GET",
url: url,
success: bandsLoaded
});
}
function bandsLoaded(response) {
$.each(response, function() {
var template = $('#template-band-option').html();
var bandOptionHtml = context.JK.fillTemplate(template, {value: this.id, label: this.name});
$('#band-list').append(bandOptionHtml);
});
}
function loadFriends() {
var url = "/api/users/" + context.JK.currentUserId + "/friends";
$.ajax({
type: "GET",
url: url,
success: friendsLoaded
});
}
function friendsLoaded(response) {
$.each(response, function() {
$('#hdn-friends').append();
$('#band-list').append(bandOptionHtml);
});
}
function enterText(div,v) {
cv = $(dcreateSessioniv).value;
if (cv != v && v != '' && cv != '') {
$(div).value = cv;
}
else {
$(div).value = v;
}
}
function initialize() {
loadGenres();
events();
loadBands();
var screenBindings = { 'afterShow': afterShow, 'beforeShow': beforeShow };
app.bindScreen('createSession', screenBindings);
}
// Expose publics
this.initialize = initialize;
this.resetForm = resetForm;
this.submitForm = submitForm;
this.validateForm = validateForm;
this.loadGenres = loadGenres;
this.loadBands = loadBands;
this.loadFriends = loadFriends;
return this;
};
})(window,jQuery);