1364 lines
42 KiB
JavaScript
1364 lines
42 KiB
JavaScript
/**
|
|
* Common utility functions.
|
|
*/
|
|
(function (context, $) {
|
|
|
|
"use strict";
|
|
context.JK = context.JK || {};
|
|
var logger = context.JK.logger;
|
|
var AUDIO_DEVICE_BEHAVIOR = context.JK.AUDIO_DEVICE_BEHAVIOR;
|
|
|
|
var ALERT_NAMES = context.JK.ALERT_NAMES;
|
|
var ALERT_TYPES = context.JK.ALERT_TYPES;
|
|
var EVENTS = context.JK.EVENTS;
|
|
|
|
var days = new Array("Sun", "Mon", "Tue",
|
|
"Wed", "Thu", "Fri", "Sat");
|
|
|
|
var months = new Array("January", "February", "March",
|
|
"April", "May", "June", "July", "August", "September",
|
|
"October", "November", "December");
|
|
|
|
var os = null;
|
|
|
|
context.JK.getGenreList = function() {
|
|
return context.JK.Rest().getGenres();
|
|
}
|
|
|
|
context.JK.stringToBool = function (s) {
|
|
switch (s.toLowerCase()) {
|
|
case "true":
|
|
case "yes":
|
|
case "1":
|
|
return true;
|
|
case "false":
|
|
case "no":
|
|
case "0":
|
|
case null:
|
|
return false;
|
|
default:
|
|
return Boolean(s);
|
|
}
|
|
};
|
|
|
|
// http://stackoverflow.com/a/8809472/834644
|
|
context.JK.generateUUID = function () {
|
|
var d = new Date().getTime();
|
|
var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
|
var r = (d + Math.random() * 16) % 16 | 0;
|
|
d = Math.floor(d / 16);
|
|
return (c == 'x' ? r : (r & 0x7 | 0x8)).toString(16);
|
|
});
|
|
return uuid;
|
|
};
|
|
|
|
// Build up two maps of images, for each instrument id.
|
|
// This map is a simple base map of instrument id to the basic image name.
|
|
// Below, a loop goes through this and builds two size-specific maps.
|
|
// In the future, we should test Whether having a single larger image
|
|
// available, and allowing the browser to resize offers better quality.
|
|
var icon_map_base = {
|
|
"accordion": "accordion",
|
|
"acoustic guitar": "acoustic_guitar",
|
|
"banjo": "banjo",
|
|
"bass guitar": "bass_guitar",
|
|
"cello": "cello",
|
|
"clarinet": "clarinet",
|
|
"computer": "computer",
|
|
"_default": "default",
|
|
"drums": "drums",
|
|
"electric guitar": "electric_guitar",
|
|
"euphonium": "euphonium",
|
|
"flute": "flute",
|
|
"french horn": "french_horn",
|
|
"harmonica": "harmonica",
|
|
"keyboard": "keyboard",
|
|
"mandolin": "mandolin",
|
|
"oboe": "oboe",
|
|
"other": "other",
|
|
"piano": "piano",
|
|
"saxophone": "saxophone",
|
|
"trombone": "trombone",
|
|
"trumpet": "trumpet",
|
|
"tuba": "tuba",
|
|
"ukulele": "ukulele",
|
|
"upright bass": "upright_bass",
|
|
"viola": "viola",
|
|
"violin": "violin",
|
|
"voice": "voice"
|
|
};
|
|
|
|
var instrumentIconMap24 = {};
|
|
var instrumentIconMap45 = {};
|
|
var instrumentIconMap256 = {};
|
|
var notSpecifiedText = "Not specified";
|
|
|
|
$.each(icon_map_base, function (instrumentId, icon) {
|
|
instrumentIconMap24[instrumentId] = {asset: "/assets/content/icon_instrument_" + icon + "24.png", name: instrumentId};
|
|
instrumentIconMap45[instrumentId] = {asset: "/assets/content/icon_instrument_" + icon + "45.png", name: instrumentId};
|
|
instrumentIconMap256[instrumentId] = {asset: "/assets/content/icon_instrument_" + icon + "256.png", name: instrumentId};
|
|
});
|
|
|
|
context.JK.helpBubbleFunctionHelper = function(originalFunc) {
|
|
var helpText = originalFunc.apply(this);
|
|
var holder = $('<div class="hover-bubble help-bubble"></div>');
|
|
holder.append(helpText);
|
|
return holder;
|
|
}
|
|
/**
|
|
* Associates a help bubble on hover (by default) with the specified $element, using jquery.bt.js (BeautyTips)
|
|
* @param $element The element that should show the help when hovered
|
|
* @param templateName the name of the help template (without the '#template-help' prefix). Add to _help.html.slim
|
|
* @param data (optional) data for your template, if applicable
|
|
* @param options (optional) You can override the default BeautyTips options: https://github.com/dillon-sellars/BeautyTips
|
|
*/
|
|
context.JK.helpBubble = function ($element, templateName, data, options) {
|
|
if (!data) {
|
|
data = {};
|
|
}
|
|
if(!options) {
|
|
options = {};
|
|
}
|
|
|
|
$element.on('remove', function() {
|
|
$element.btOff(); // if the element goes away for some reason, get rid of the bubble too
|
|
})
|
|
|
|
var holder = null;
|
|
if (context._.isFunction(templateName)) {
|
|
holder = function wrapper() {
|
|
return context.JK.helpBubbleFunctionHelper.apply(this, [templateName]);
|
|
}
|
|
}
|
|
else {
|
|
try {
|
|
var $template = $('#template-help-' + templateName)
|
|
if ($template.length == 0) {
|
|
var helpText = templateName;
|
|
}
|
|
else {
|
|
var helpText = context._.template($template.html(), data, { variable: 'data' });
|
|
}
|
|
}
|
|
catch(e) {
|
|
var helpText = templateName;
|
|
}
|
|
|
|
holder = $('<div class="hover-bubble help-bubble"></div>');
|
|
holder = holder.append(helpText).html()
|
|
}
|
|
|
|
context.JK.hoverBubble($element, holder, options);
|
|
}
|
|
|
|
/**
|
|
* Meant to show a little bubble to confirm something happened, in a way less obtrusive than a app.notify
|
|
* @param $element The element that should show the help when hovered
|
|
* @param templateName the name of the help template (without the '#template-help' prefix). Add to _help.html.slim
|
|
* @param data (optional) data for your template, if applicable
|
|
* @param options (optional) You can override the default BeautyTips options: https://github.com/dillon-sellars/BeautyTips
|
|
*/
|
|
context.JK.ackBubble = function($element, templateName, data, options) {
|
|
if(!options) options = {};
|
|
options.spikeGirth = 0;
|
|
options.spikeLength = 0;
|
|
options.shrinkToFit = true
|
|
options.duration = 3000
|
|
options.cornerRadius = 5
|
|
|
|
return context.JK.prodBubble($element, templateName, data, options);
|
|
}
|
|
/**
|
|
* Associates a help bubble immediately with the specified $element, using jquery.bt.js (BeautyTips)
|
|
* By 'prod' it means to literally prod the user, to make them aware of something important because they did something else
|
|
*
|
|
* This will open a bubble immediately and show it for 4 seconds,
|
|
* if you call it again before the 4 second timer is up, it will renew the 4 second timer.
|
|
* @param $element The element that should show the help when hovered
|
|
* @param templateName the name of the help template (without the '#template-help' prefix). Add to _help.html.slim
|
|
* @param data (optional) data for your template, if applicable
|
|
* @param options (optional) You can override the default BeautyTips options: https://github.com/dillon-sellars/BeautyTips
|
|
*/
|
|
context.JK.prodBubble = function($element, templateName, data, options) {
|
|
if(!options) options = {};
|
|
options['trigger'] = 'none';
|
|
options['clickAnywhereToClose'] = false
|
|
if(!options['duration']) options['duration'] = 6000;
|
|
|
|
var existingTimer = $element.data("prodTimer");
|
|
if(existingTimer) {
|
|
clearTimeout(existingTimer);
|
|
$element.btOn();
|
|
}
|
|
else {
|
|
context.JK.helpBubble($element, templateName, data, options);
|
|
$element.btOn();
|
|
}
|
|
$element.data("prodTimer", setTimeout(function() {
|
|
$element.data("prodTimer", null);
|
|
$element.btOff();
|
|
}, options['duration']));
|
|
|
|
$element.on('remove', function() {
|
|
var timer = $element.data('prodTimer')
|
|
if(timer) {
|
|
clearTimeout(timer);
|
|
$element.data("prodTimer", null);
|
|
$element.btOff();
|
|
}
|
|
})
|
|
return $element;
|
|
}
|
|
/**
|
|
* Associates a bubble on hover (by default) with the specified $element, using jquery.bt.js (BeautyTips)
|
|
* @param $element The element that should show the bubble when hovered
|
|
* @param text the text or jquery element that should be shown as contents of the bubble
|
|
* @param options (optional) You can override the default BeautyTips options: https://github.com/dillon-sellars/BeautyTips
|
|
*/
|
|
context.JK.hoverBubble = function ($element, text, options) {
|
|
if (!text) {
|
|
logger.error("hoverBubble: no text to attach to $element %o", $element);
|
|
return;
|
|
}
|
|
|
|
$element.on('remove', function() {
|
|
$element.btOff();
|
|
})
|
|
|
|
if ($element instanceof jQuery) {
|
|
if ($element.length == 0) {
|
|
logger.error("hoverBubble: no element specified with text %o", text);
|
|
return;
|
|
}
|
|
}
|
|
|
|
var defaultOpts = {
|
|
fill: '#333',
|
|
strokeStyle: '#ED3618',
|
|
spikeLength: 10,
|
|
spikeGirth: 10,
|
|
padding: 8,
|
|
cornerRadius: 0,
|
|
cssStyles: {
|
|
fontSize: '11px',
|
|
color: '#cccccc',
|
|
whiteSpace: 'normal'
|
|
}
|
|
};
|
|
|
|
if (options) {
|
|
options = $.extend(false, defaultOpts, options);
|
|
}
|
|
else {
|
|
options = defaultOpts;
|
|
}
|
|
|
|
if(typeof text != 'string') {
|
|
options.contentSelector = text;
|
|
$element.bt(options);
|
|
}
|
|
else {
|
|
$element.bt(text, options);
|
|
}
|
|
|
|
}
|
|
|
|
context.JK.bindProfileClickEvents = function($parent, dialogsToClose) {
|
|
if (!$parent) {
|
|
$parent = $('body');
|
|
}
|
|
|
|
function closeDialogs() {
|
|
if (dialogsToClose) {
|
|
$.each(dialogsToClose, function(index, val) {
|
|
JK.app.layout.closeDialog(val);
|
|
});
|
|
}
|
|
}
|
|
|
|
$("[profileaction='band']", $parent).unbind('click');
|
|
$("[profileaction='band']", $parent).click(function(evt) {
|
|
closeDialogs();
|
|
window.location = "/client#/bandProfile/" + $(this).attr('band-id');
|
|
});
|
|
|
|
$("[profileaction='musician']", $parent).unbind('click');
|
|
$("[profileaction='musician']", $parent).click(function(evt) {
|
|
closeDialogs();
|
|
window.location = "/client#/profile/" + $(this).attr('user-id');
|
|
});
|
|
}
|
|
|
|
context.JK.bindInstrumentHover = function($parent, options) {
|
|
context._.each($parent.find("[hoveraction='instrument']"), function(element) {
|
|
var $element = $(element);
|
|
|
|
var instrumentId = $element.attr('data-instrument-id');
|
|
|
|
if(instrumentId) {
|
|
if (instrumentId === "null") {
|
|
instrumentId = "not specified";
|
|
}
|
|
context.JK.hoverBubble($element, instrumentId, options);
|
|
}
|
|
else {
|
|
logger.warn("no instrument-id on hoveraction=instrument element")
|
|
}
|
|
});
|
|
}
|
|
|
|
context.JK.calculateHoverPosition = function(mouseX, mouseY, hoverWidth, hoverHeight, $hoverElement) {
|
|
var mouseLeft = mouseX < (window.innerWidth / 2);
|
|
var mouseTop = mouseY < (window.innerHeight / 2);
|
|
|
|
var hoverElementX = $hoverElement.offset().left;
|
|
var hoverElementY = $hoverElement.offset().top;
|
|
var hoverElementWidth = $hoverElement.width();
|
|
var hoverElementHeight = $hoverElement.height();
|
|
|
|
var css = {};
|
|
if (mouseLeft) {
|
|
css.left = hoverElementX + hoverElementWidth + 5 + 'px';
|
|
}
|
|
else {
|
|
css.left = hoverElementX - hoverWidth - 5 + 'px';
|
|
}
|
|
if (mouseTop) {
|
|
css.top = hoverElementY + 'px';
|
|
}
|
|
else {
|
|
css.top = hoverElementY - hoverHeight + 'px';
|
|
}
|
|
|
|
return css;
|
|
}
|
|
|
|
context.JK.bindHoverEvents = function ($parent) {
|
|
var timeout = 300;
|
|
var fadeoutValue = 100;
|
|
var sensitivity = 3;
|
|
var interval = 500;
|
|
|
|
if (!$parent) {
|
|
$parent = $('body');
|
|
}
|
|
|
|
function showBubble(bubble, $hoverElement) {
|
|
$hoverElement.attr("bubble-id", bubble.id);
|
|
bubble.showBubble($hoverElement)
|
|
.done(function() {
|
|
|
|
$(bubble.id()).hover(
|
|
function () {
|
|
$(this).data('hovering', true)
|
|
// do nothing when entering the bubble
|
|
},
|
|
function () {
|
|
$(this).data('hovering', false).fadeOut(100);
|
|
}
|
|
);
|
|
|
|
})
|
|
}
|
|
|
|
function hideBubble($hoverElement) {
|
|
|
|
var bubbleSelector = $hoverElement.attr("bubble-id");
|
|
|
|
// first check to see if the user isn't hovering over the hover bubble
|
|
if (!$(bubbleSelector).data('hovering')) {
|
|
$(bubbleSelector).fadeOut(fadeoutValue);
|
|
}
|
|
}
|
|
|
|
// MUSICIAN
|
|
$("[hoveraction='musician']", $parent).hoverIntent({
|
|
over: function(e) {
|
|
var bubble = new JK.MusicianHoverBubble($(this).attr('user-id'), e.pageX, e.pageY);
|
|
|
|
showBubble(bubble, $(this));
|
|
|
|
|
|
},
|
|
out: function () { // this registers for leaving the hoverable element
|
|
hideBubble($(this));
|
|
},
|
|
sensitivity: sensitivity,
|
|
interval: interval,
|
|
timeout: timeout
|
|
});
|
|
|
|
// FAN
|
|
$("[hoveraction='fan']", $parent).hoverIntent({
|
|
over: function(e) {
|
|
var bubble = new JK.FanHoverBubble($(this).attr('user-id'), e.pageX, e.pageY);
|
|
showBubble(bubble, $(this));
|
|
},
|
|
out: function () { // this registers for leaving the hoverable element
|
|
hideBubble($(this));
|
|
},
|
|
sensitivity: sensitivity,
|
|
interval: interval,
|
|
timeout: timeout
|
|
});
|
|
|
|
// BAND
|
|
$("[hoveraction='band']", $parent).hoverIntent({
|
|
over: function(e) {
|
|
var bubble = new JK.BandHoverBubble($(this).attr('band-id'), e.pageX, e.pageY);
|
|
showBubble(bubble, $(this));
|
|
},
|
|
out: function () { // this registers for leaving the hoverable element
|
|
hideBubble($(this));
|
|
},
|
|
sensitivity: sensitivity,
|
|
interval: interval,
|
|
timeout: timeout
|
|
});
|
|
|
|
// SESSION
|
|
$("[hoveraction='session']", $parent).hoverIntent({
|
|
over: function(e) {
|
|
var bubble = new JK.SessionHoverBubble($(this).attr('session-id'), e.pageX, e.pageY);
|
|
showBubble(bubble, $(this));
|
|
},
|
|
out: function () { // this registers for leaving the hoverable element
|
|
hideBubble($(this));
|
|
},
|
|
sensitivity: sensitivity,
|
|
interval: interval,
|
|
timeout: timeout
|
|
});
|
|
|
|
// RECORDING
|
|
$("[hoveraction='recording']", $parent).hoverIntent({
|
|
over: function(e) {
|
|
var bubble = new JK.RecordingHoverBubble($(this).attr('recording-id'), e.pageX, e.pageY);
|
|
showBubble(bubble, $(this));
|
|
},
|
|
out: function () { // this registers for leaving the hoverable element
|
|
hideBubble($(this));
|
|
},
|
|
sensitivity: sensitivity,
|
|
interval: interval,
|
|
timeout: timeout
|
|
});
|
|
}
|
|
|
|
context.JK.fetchUserNetworkOrServerFailure = function () {
|
|
JK.app.notify({
|
|
title: "Unable to communicate with server",
|
|
text: "Please try again later",
|
|
icon_url: "/assets/content/icon_alert_big.png"
|
|
});
|
|
}
|
|
|
|
context.JK.entityNotFound = function (type) {
|
|
JK.app.notify({
|
|
title: type + " Deleted",
|
|
text: "The " + type + " no longer exists.",
|
|
icon_url: "/assets/content/icon_alert_big.png"
|
|
});
|
|
}
|
|
|
|
// http://stackoverflow.com/questions/4878756/javascript-how-to-capitalize-first-letter-of-each-word-like-a-2-word-city
|
|
context.JK.toTitleCase = function(str) {
|
|
return str.replace(/\w\S*/g, function(txt){
|
|
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
|
|
});
|
|
}
|
|
|
|
|
|
// Uber-simple templating
|
|
// var template = "Hey {name}";
|
|
// var vals = { name: "Jon" };
|
|
// _fillTemplate(template, vals);
|
|
// --> "Hey Jon"
|
|
//
|
|
// use context._.template for something more powerful
|
|
context.JK.fillTemplate = function (template, vals) {
|
|
if (template == null) throw 'null template in fillTemplate'
|
|
for (var val in vals)
|
|
template = template.replace(new RegExp('{' + val + '}', 'g'), vals[val]);
|
|
return template;
|
|
};
|
|
|
|
context.JK.resolveAvatarUrl = function (photo_url) {
|
|
return photo_url ? photo_url : "/assets/shared/avatar_generic.png";
|
|
};
|
|
|
|
context.JK.resolveBandAvatarUrl = function (photo_url) {
|
|
return photo_url ? photo_url : "/assets/shared/avatar_generic_band.png";
|
|
};
|
|
|
|
context.JK.getInstrumentIconMap24 = function () {
|
|
return instrumentIconMap24;
|
|
};
|
|
|
|
context.JK.getInstrumentIconMap45 = function () {
|
|
return instrumentIconMap45;
|
|
};
|
|
|
|
context.JK.getInstrumentIconMap256 = function () {
|
|
return instrumentIconMap256;
|
|
};
|
|
|
|
context.JK.getInstrumentIcon24 = function (instrument) {
|
|
if (instrument in instrumentIconMap24) {
|
|
return instrumentIconMap24[instrument].asset;
|
|
}
|
|
|
|
return instrumentIconMap24["_default"].asset;
|
|
};
|
|
|
|
context.JK.getInstrumentIcon45 = function (instrument) {
|
|
if (instrument in instrumentIconMap45) {
|
|
return instrumentIconMap45[instrument].asset;
|
|
}
|
|
|
|
return instrumentIconMap45["_default"].asset;
|
|
};
|
|
|
|
context.JK.getInstrumentIcon256 = function (instrument) {
|
|
if (instrument in instrumentIconMap256) {
|
|
return instrumentIconMap256[instrument].asset;
|
|
}
|
|
|
|
return instrumentIconMap256["_default"].asset;
|
|
};
|
|
|
|
context.JK.getInstrumentId = function(instrumentId) {
|
|
return instrumentId ? instrumentId : notSpecifiedText;
|
|
}
|
|
|
|
// meant to pass in a bunch of images with an instrument-id attribute on them.
|
|
|
|
context.JK.setInstrumentAssetPath = function ($elements) {
|
|
$.each($elements, function (index, item) {
|
|
var $element = $(this);
|
|
if (!$element.is('img')) {
|
|
throw "expected to receive an <img> in setInstrumentAssetPath"
|
|
}
|
|
|
|
var instrument = $element.attr('instrument-id');
|
|
|
|
$element.attr('src', context.JK.getInstrumentIcon24(instrument))
|
|
})
|
|
}
|
|
|
|
// creates an array with entries like [{ id: "drums", description: "Drums"}, ]
|
|
context.JK.listInstruments = function () {
|
|
var instrumentArray = [];
|
|
$.each(context.JK.server_to_client_instrument_map, function (key, val) {
|
|
instrumentArray.push({"id": context.JK.server_to_client_instrument_map[key].client_id, "description": key});
|
|
});
|
|
return instrumentArray;
|
|
}
|
|
|
|
context.JK.showErrorDialog = function (app, msg, title) {
|
|
app.layout.showDialog('error-dialog');
|
|
$('#error-msg', 'div[layout-id="error-dialog"]').html(msg);
|
|
$('#error-summary', 'div[layout-id="error-dialog"]').html(title);
|
|
}
|
|
|
|
// TODO: figure out how to handle this in layout.js for layered popups
|
|
context.JK.showOverlay = function () {
|
|
$('.dialog-overlay').show();
|
|
}
|
|
|
|
context.JK.hideOverlay = function () {
|
|
$('.dialog-overlay').hide();
|
|
}
|
|
|
|
// usage: context.JK.onBackendEvent(ALERT_NAMES.SOME_EVENT)
|
|
context.JK.onBackendEvent = function(type, namespace, callback) {
|
|
var alertData = ALERT_TYPES[type];
|
|
if(!alertData) {throw "onBackendEvent: unknown alert type " + type};
|
|
logger.debug("onBackendEvent: " + alertData.name + '.' + namespace)
|
|
$(document).on(alertData.name + '.' + namespace, callback);
|
|
}
|
|
|
|
context.JK.offBackendEvent = function(type, namespace, callback) {
|
|
var alertData = ALERT_TYPES[type];
|
|
if(!alertData) {throw "offBackendEvent: unknown alert type " + type};
|
|
logger.debug("offBackendEvent: " + alertData.name + '.' + namespace, alertData)
|
|
$(document).off(alertData.name + '.' + namespace);
|
|
}
|
|
|
|
/*
|
|
* Loads a listbox or dropdown with the values in input_array, setting the option value
|
|
* to the id_field and the option text to text_field. It will preselect the option with
|
|
* value equal to selected_id.
|
|
*/
|
|
context.JK.loadOptions = function (templateHtml, listbox_id, input_array, id_field, text_field, selected_id) {
|
|
$.each(input_array, function (index, val) {
|
|
var isSelected = "";
|
|
if (val[id_field] === selected_id) {
|
|
isSelected = "selected";
|
|
}
|
|
var html = context.JK.fillTemplate(templateHtml, {
|
|
value: val[id_field],
|
|
label: val[text_field],
|
|
selected: isSelected
|
|
});
|
|
|
|
listbox_id.append(html);
|
|
});
|
|
}
|
|
|
|
context.JK.trimString = function (str) {
|
|
return str.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
|
|
};
|
|
|
|
context.JK.padString = function (str, max) {
|
|
var retVal = '' + str;
|
|
while (retVal.length < max) {
|
|
retVal = '0' + retVal;
|
|
}
|
|
|
|
return retVal;
|
|
}
|
|
|
|
context.JK.formatDateTime = function (dateString) {
|
|
var date = dateString instanceof Date ? dateString : new Date(dateString);
|
|
return context.JK.padString(date.getMonth() + 1, 2) + "/" + context.JK.padString(date.getDate(), 2) + "/" + date.getFullYear() + " - " + date.toLocaleTimeString();
|
|
}
|
|
|
|
// returns Fri May 20, 2013
|
|
context.JK.formatDate = function (dateString, suppressDay) {
|
|
var date = new Date(dateString);
|
|
return (suppressDay ? '' : (days[date.getDay()] + ' ')) + months[date.getMonth()] + ' ' + context.JK.padString(date.getDate(), 2) + ', ' + date.getFullYear();
|
|
}
|
|
|
|
|
|
context.JK.formatDateYYYYMMDD = function(dateString) {
|
|
var date = new Date(dateString);
|
|
return date.getFullYear() + '-' + context.JK.padString((date.getMonth() + 1).toString(), 2) + '-' + context.JK.padString(date.getDate(), 2);
|
|
}
|
|
|
|
context.JK.formatTime = function (dateString) {
|
|
var date = new Date(dateString);
|
|
return date.toLocaleTimeString();
|
|
}
|
|
|
|
context.JK.formatUtcTime = function(date, change) {
|
|
if (change) {
|
|
date.setMinutes(Math.ceil(date.getMinutes() / 30) * 30);
|
|
}
|
|
var h12h = date.getHours();
|
|
var m12h = date.getMinutes();
|
|
var ampm;
|
|
if (h12h >= 0 && h12h < 12) {
|
|
if (h12h === 0) {
|
|
h12h = 12; // 0 becomes 12
|
|
}
|
|
ampm = "AM";
|
|
}
|
|
else {
|
|
if (h12h > 12) {
|
|
h12h -= 12; // 13-23 becomes 1-11
|
|
}
|
|
ampm = "PM";
|
|
}
|
|
var timeString = ("00" + h12h).slice(-2) + ":" + ("00" + m12h).slice(-2) + " " + ampm;
|
|
|
|
return timeString;
|
|
}
|
|
|
|
context.JK.prettyPrintElements = function ($elements) {
|
|
$.each($elements, function (index, item) {
|
|
var $item = $(item);
|
|
$item.text(context.JK.prettyPrintSeconds(parseInt($item.attr('duration'))))
|
|
});
|
|
}
|
|
|
|
context.JK.prettyPrintSeconds = function (seconds) {
|
|
// from: http://stackoverflow.com/questions/3733227/javascript-seconds-to-minutes-and-seconds
|
|
|
|
// Minutes and seconds
|
|
var mins = ~~(seconds / 60);
|
|
var secs = seconds % 60;
|
|
|
|
// Hours, minutes and seconds
|
|
var hrs = ~~(seconds / 3600);
|
|
var mins = ~~((seconds % 3600) / 60);
|
|
var secs = seconds % 60;
|
|
|
|
// Output like "1:01" or "4:03:59" or "123:03:59"
|
|
var ret = "";
|
|
|
|
if (hrs > 0)
|
|
ret += "" + hrs + ":" + (mins < 10 ? "0" : "");
|
|
|
|
ret += "" + mins + ":" + (secs < 10 ? "0" : "");
|
|
ret += "" + secs;
|
|
return ret;
|
|
}
|
|
|
|
context.JK.alertSupportedNeeded = function(additionalContext) {
|
|
var $item = context.JK.Banner.showAlert(additionalContext + '<br/><br/>Please <a href="http://jamkazam.desk.com" rel="external">contact support</a>.');
|
|
context.JK.popExternalLinks($item);
|
|
return $item;
|
|
}
|
|
|
|
// returns:
|
|
// * Win32
|
|
// * MacOSX
|
|
// * Unix
|
|
context.JK.GetOSAsString = function() {
|
|
if(!os) {
|
|
if(context.jamClient.IsNativeClient()) {
|
|
os = context.jamClient.GetOSAsString();
|
|
}
|
|
else {
|
|
os = context.JK.detectOS();
|
|
}
|
|
}
|
|
return os;
|
|
}
|
|
|
|
context.JK.search = function (query, app, callback) {
|
|
//logger.debug("search: "+ query)
|
|
$.ajax({
|
|
type: "GET",
|
|
dataType: "json",
|
|
contentType: 'application/json',
|
|
url: "/api/search?query=" + query,
|
|
processData: false,
|
|
success: function (response) {
|
|
callback(response);
|
|
},
|
|
error: app.ajaxError
|
|
});
|
|
};
|
|
|
|
/*
|
|
* Get the length of a dictionary
|
|
*/
|
|
context.JK.dlen = function (d) {
|
|
var count = 0;
|
|
for (var i in d) {
|
|
if (d.hasOwnProperty(i)) {
|
|
count++;
|
|
}
|
|
}
|
|
return count;
|
|
};
|
|
|
|
/*
|
|
* Get the keys of a dictionary as an array (same as Object.keys, but works in all browsers)
|
|
*/
|
|
context.JK.dkeys = function (d) {
|
|
var keys = []
|
|
for (var i in d) {
|
|
if (d.hasOwnProperty(i)) {
|
|
keys.push(i);
|
|
}
|
|
}
|
|
return keys;
|
|
};
|
|
|
|
/**
|
|
* Finds the first error associated with the field.
|
|
* @param fieldName the name of the field
|
|
* @param errors_data response from a 422 response in ajax
|
|
* @returns null if no error for the field name, or the 1st error associated with that field
|
|
*/
|
|
context.JK.get_first_error = function (fieldName, errors_data) {
|
|
var errors = errors_data["errors"];
|
|
if (errors == null) return null;
|
|
|
|
if (errors[fieldName] && errors[fieldName].length > 0) {
|
|
return errors[fieldName][0]
|
|
}
|
|
else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns a ul with an li per field name.
|
|
* @param fieldName the name of the field
|
|
* @param errors_data error data return by a 422 ajax response
|
|
* @returns null if no error for the field name; otherwise a ul/li
|
|
*/
|
|
context.JK.format_errors = function (fieldName, errors_data) {
|
|
var errors = errors_data["errors"];
|
|
if (errors == null) return null;
|
|
|
|
var field_errors = errors[fieldName];
|
|
if (field_errors == null) {
|
|
return null;
|
|
}
|
|
|
|
var ul = $('<ul class="error-text"></ul>');
|
|
|
|
$.each(field_errors, function (index, item) {
|
|
ul.append(context.JK.fillTemplate("<li>{message}</li>", {message: item}))
|
|
})
|
|
|
|
return ul;
|
|
}
|
|
|
|
context.JK.format_all_errors = function (errors_data) {
|
|
var errors = errors_data["errors"];
|
|
if (errors == null) return $('<ul class="error-text"><li>unknown error</li></ul>');
|
|
|
|
var ul = $('<ul class="error-text"></ul>');
|
|
|
|
$.each(errors, function (fieldName, field_errors) {
|
|
|
|
$.each(field_errors, function (index, item) {
|
|
ul.append(context.JK.fillTemplate("<li>{field} {message}</li>", {field: fieldName, message: item}))
|
|
});
|
|
});
|
|
|
|
return ul;
|
|
}
|
|
|
|
|
|
/**
|
|
* Way to verify that a number of parallel tasks have all completed.
|
|
* Provide a function to evaluate completion, and a callback to
|
|
* invoke when that function evaluates to true.
|
|
* NOTE: this does not pause execution, it simply ensures that
|
|
* when the test function evaluates to true, the callback will
|
|
* be invoked.
|
|
*/
|
|
context.JK.joinCalls = function (completionTestFunction, callback, interval) {
|
|
function doneYet() {
|
|
if (completionTestFunction()) {
|
|
callback();
|
|
} else {
|
|
context.setTimeout(doneYet, interval);
|
|
}
|
|
}
|
|
|
|
doneYet();
|
|
};
|
|
|
|
context.JK.initJamClient = function(app) {
|
|
// If no jamClient (when not running in native client)
|
|
// create a fake one.
|
|
if (!(window.jamClient)) {
|
|
var p2pMessageFactory = new JK.FakeJamClientMessages();
|
|
window.jamClient = new JK.FakeJamClient(app, p2pMessageFactory);
|
|
window.jamClient.SetFakeRecordingImpl(new JK.FakeJamClientRecordings(app, jamClient, p2pMessageFactory));
|
|
}
|
|
else if(false) { // set to true to time long running bridge calls
|
|
var originalJamClient = window.jamClient;
|
|
var interceptedJamClient = {};
|
|
$.each(Object.keys(originalJamClient), function(i, key) {
|
|
if(key.indexOf('(') > -1) {
|
|
// this is a method. time it
|
|
var jsKey = key.substring(0, key.indexOf('('))
|
|
console.log("replacing " + jsKey)
|
|
interceptedJamClient[jsKey] = function() {
|
|
var original = originalJamClient[key]
|
|
var start = new Date();
|
|
if(key == "FTUEGetDevices()") {
|
|
var returnVal = eval('originalJamClient.FTUEGetDevices(' + arguments[0] + ')');
|
|
}
|
|
else {
|
|
var returnVal = original.apply(originalJamClient, arguments);
|
|
}
|
|
var time = new Date().getTime() - start.getTime();
|
|
if(time >= 0) { // if 0, you'll see ALL bridge calls. If you set it to a higher value, you'll only see calls that are beyond that threshold
|
|
console.error(time + "ms jamClient." + jsKey + ' returns=', returnVal);
|
|
}
|
|
|
|
return returnVal;
|
|
}
|
|
}
|
|
else {
|
|
// we need to intercept properties... but how?
|
|
}
|
|
});
|
|
|
|
|
|
window.jamClient = interceptedJamClient;
|
|
}
|
|
|
|
}
|
|
|
|
// pass in 'arguments' in a fail callback of a $.ajax
|
|
context.JK.isNetworkError = function(failArgs) {
|
|
if(failArgs.length != 3) throw "expected 3 arguments from .fail of $ajax in isNetworkError"
|
|
var xhr = failArgs[0];
|
|
|
|
return xhr.status == 0;
|
|
}
|
|
|
|
context.JK.clientType = function () {
|
|
if (context.jamClient) {
|
|
return context.jamClient.IsNativeClient() ? 'client' : 'browser';
|
|
}
|
|
return 'browser';
|
|
}
|
|
/**
|
|
* Returns 'MacOSX' if the os appears to be macintosh,
|
|
* 'Win32' if the os appears to be windows,
|
|
* 'Unix' if the OS appears to be linux,
|
|
* and null if unknown
|
|
* @returns {*}
|
|
*/
|
|
context.JK.detectOS = function () {
|
|
if (!navigator.platform) {
|
|
return null;
|
|
}
|
|
|
|
if (navigator.platform.toLowerCase().indexOf('mac') !== -1) {
|
|
return "MacOSX";
|
|
}
|
|
if (navigator.platform.toLowerCase().indexOf('win') !== -1) {
|
|
return "Win32"
|
|
}
|
|
if (navigator.platform.toLowerCase().indexOf('linux') !== -1) {
|
|
return "Unix"
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
context.JK.makeAbsolute = function(path) {
|
|
return window.location.protocol + '//' + window.location.host + path;
|
|
}
|
|
|
|
context.JK.popExternalLinks = function ($parent) {
|
|
|
|
function popOpenBrowser (evt) {
|
|
|
|
if (!context.jamClient) {
|
|
return;
|
|
}
|
|
|
|
evt.preventDefault();
|
|
var href = $(this).attr("href");
|
|
|
|
if (href) {
|
|
// make absolute if not already
|
|
if (href.indexOf('http') != 0 && href.indexOf('mailto') != 0) {
|
|
href = window.location.protocol + '//' + window.location.host + href;
|
|
}
|
|
|
|
context.jamClient.OpenSystemBrowser(href);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
if(!$parent) $parent = $('body');
|
|
// Allow any a link with a rel="external" attribute to launch
|
|
// the link in the default browser, using jamClient:
|
|
$parent.on('click', 'a[rel="external"]', popOpenBrowser);
|
|
}
|
|
|
|
context.JK.popExternalLink = function (href) {
|
|
if (!context.jamClient) {
|
|
return;
|
|
}
|
|
|
|
if (href) {
|
|
// make absolute if not already
|
|
if (href.indexOf('http') != 0 && href.indexOf('mailto') != 0) {
|
|
href = window.location.protocol + '//' + window.location.host + href;
|
|
}
|
|
|
|
context.jamClient.OpenSystemBrowser(href);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
context.JK.checkbox = function ($checkbox) {
|
|
return $checkbox.iCheck({
|
|
checkboxClass: 'icheckbox_minimal',
|
|
radioClass: 'iradio_minimal',
|
|
inheritClass: true
|
|
});
|
|
}
|
|
|
|
context.JK.dropdown = function ($select) {
|
|
|
|
$select.each(function (index) {
|
|
var $item = $(this);
|
|
|
|
if ($item.data('easydropdown-select')) {
|
|
// if this has already been initialized, re-init it so it picks up any new <options>
|
|
$item.easyDropDown('destroy')
|
|
}
|
|
$item.easyDropDown({nativeTouch: !(context.jamClient && context.jamClient.IsNativeClient()) && gon.global.env != "test", cutOff: 7});
|
|
})
|
|
}
|
|
|
|
|
|
context.JK.flash = function(msg, options) {
|
|
options = options || {}
|
|
|
|
var $flash = $(context._.template($('#template-flash-notice').html(), {}, { variable: 'data' }));
|
|
$flash.find('.flash-content').html(msg);
|
|
$('body').prepend($flash)
|
|
if(options.hide) {
|
|
// slide down (take 1 sec to do it), sit for 5, then leave over 1 second
|
|
setTimeout(function() {$flash.slideUp(1000, 'swing') }, options.hide * 1000)
|
|
}
|
|
}
|
|
|
|
context.JK.hasFlash = function () {
|
|
var hasFlash = false;
|
|
|
|
if (!context.jamClient || !context.jamClient.IsNativeClient()) {
|
|
try {
|
|
var fo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash');
|
|
if (fo) hasFlash = true;
|
|
} catch (e) {
|
|
if (navigator.mimeTypes ["application/x-shockwave-flash"] != undefined) hasFlash = true;
|
|
}
|
|
}
|
|
|
|
return hasFlash;
|
|
}
|
|
|
|
context.JK.getNameOfFile = function(filename) {
|
|
|
|
var index = filename.lastIndexOf('/');
|
|
if(index == -1) {
|
|
index = filename.lastIndexOf('\\');
|
|
}
|
|
return index == -1 ? filename : filename.substring(index + 1, filename.length)
|
|
}
|
|
|
|
context.JK.hasOneConfiguredDevice = function () {
|
|
var result = context.jamClient.FTUEGetGoodConfigurationList();
|
|
logger.debug("hasOneConfiguredDevice: ", result);
|
|
return result.length > 0;
|
|
};
|
|
|
|
context.JK.getGoodAudioConfigs = function () {
|
|
var result = context.jamClient.FTUEGetGoodAudioConfigurations();
|
|
logger.debug("goodAudioConfigs=%o", result);
|
|
return result;
|
|
};
|
|
|
|
context.JK.getGoodConfigMap = function () {
|
|
var goodConfigMap = [];
|
|
var goodConfigs = context.JK.getGoodAudioConfigs();
|
|
$.each(goodConfigs, function (index, profileKey) {
|
|
var friendlyName = context.jamClient.FTUEGetConfigurationDevice(profileKey);
|
|
goodConfigMap.push({key: profileKey, name: friendlyName});
|
|
});
|
|
|
|
return goodConfigMap;
|
|
}
|
|
|
|
context.JK.getBadAudioConfigs = function () {
|
|
var badAudioConfigs = [];
|
|
var allAudioConfigs = context.jamClient.FTUEGetAllAudioConfigurations();
|
|
var goodAudioConfigs = context.JK.getGoodAudioConfigs();
|
|
|
|
for (var i = 0; i < allAudioConfigs.length; i++) {
|
|
if ($.inArray(allAudioConfigs[i], goodAudioConfigs) === -1) {
|
|
badAudioConfigs.push(allAudioConfigs[i]);
|
|
}
|
|
}
|
|
logger.debug("badAudioConfigs=%o", badAudioConfigs);
|
|
return badAudioConfigs;
|
|
};
|
|
|
|
context.JK.getBadConfigMap = function () {
|
|
var badConfigMap = [];
|
|
var badConfigs = context.JK.getBadAudioConfigs();
|
|
$.each(badConfigs, function (index, profileKey) {
|
|
var friendlyName = context.jamClient.FTUEGetConfigurationDevice(profileKey);
|
|
badConfigMap.push({key: profileKey, name: friendlyName});
|
|
});
|
|
|
|
return badConfigMap;
|
|
}
|
|
|
|
context.JK.getFirstGoodDevice = function (preferredDeviceId) {
|
|
var badConfigs = context.JK.getBadAudioConfigs();
|
|
|
|
function getGoodDevice() {
|
|
var goodConfigs = context.JK.getGoodAudioConfigs();
|
|
if (goodConfigs && goodConfigs.length > 0) {
|
|
deviceId = goodConfigs[0];
|
|
}
|
|
else {
|
|
deviceId = null;
|
|
}
|
|
return deviceId;
|
|
}
|
|
|
|
var deviceId = null;
|
|
|
|
if (preferredDeviceId) {
|
|
|
|
// if the preferred device is not in the list of invalid configs, use it
|
|
if ($.inArray(preferredDeviceId, badConfigs) === -1) {
|
|
deviceId = preferredDeviceId;
|
|
}
|
|
else {
|
|
deviceId = getGoodDevice();
|
|
}
|
|
}
|
|
else {
|
|
deviceId = getGoodDevice();
|
|
}
|
|
return deviceId;
|
|
}
|
|
|
|
// returns /client#/home for http://www.jamkazam.com/client#/home
|
|
context.JK.locationPath = function () {
|
|
var bits = context.location.href.split('/');
|
|
return '/' + bits.slice(3).join('/');
|
|
}
|
|
|
|
context.JK.nowUTC = function () {
|
|
var d = new Date();
|
|
return new Date(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds());
|
|
}
|
|
|
|
context.JK.guardAgainstBrowser = function(app, args) {
|
|
if(!gon.isNativeClient) {
|
|
logger.debug("guarding against normal browser on screen that requires native client")
|
|
app.layout.showDialog('launch-app-dialog', args)
|
|
.one(EVENTS.DIALOG_CLOSED, function() {
|
|
if(args && args.goHome) {
|
|
window.location = '/client#/home';
|
|
}
|
|
})
|
|
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
context.JK.createSession = function(app, data) {
|
|
|
|
// auto pick an 'other' instrument
|
|
var otherId = context.JK.server_to_client_instrument_map.Other.server_id; // get server ID
|
|
var otherInstrumentInfo = context.JK.instrument_id_to_instrument[otherId]; // get display name
|
|
var beginnerLevel = 1; // default to beginner
|
|
var instruments = [ {id: otherId, name: otherInstrumentInfo.display, level: beginnerLevel} ];
|
|
$.each(instruments, function(index, instrument) {
|
|
var slot = {};
|
|
slot.instrument_id = instrument.id;
|
|
slot.proficiency_level = instrument.level;
|
|
slot.approve = true;
|
|
data.rsvp_slots.push(slot);
|
|
});
|
|
|
|
data.isUnstructuredRsvp = true;
|
|
|
|
return rest.createScheduledSession(data)
|
|
}
|
|
|
|
context.JK.privateSessionSettings = function(createSessionSettings) {
|
|
createSessionSettings.genresValues = ['Pop'];
|
|
createSessionSettings.genres = ['pop'];
|
|
createSessionSettings.timezone = 'Central Time (US & Canada),America/Chicago'
|
|
createSessionSettings.name = "Private Test Session";
|
|
createSessionSettings.description = "Private session set up just to test things out in the session interface by myself.";
|
|
createSessionSettings.notations = [];
|
|
createSessionSettings.language = 'eng'
|
|
createSessionSettings.legal_policy = 'Standard';
|
|
createSessionSettings.musician_access = false
|
|
createSessionSettings.fan_access = false
|
|
createSessionSettings.fan_chat = false
|
|
createSessionSettings.approval_required = false
|
|
createSessionSettings.legal_terms = true
|
|
createSessionSettings.recurring_mode = 'once';
|
|
createSessionSettings.start = new Date().toDateString() + ' ' + context.JK.formatUtcTime(new Date(), false);
|
|
createSessionSettings.duration = "60";
|
|
createSessionSettings.open_rsvps = false
|
|
createSessionSettings.rsvp_slots = [];
|
|
}
|
|
/*
|
|
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
|
|
* Digest Algorithm, as defined in RFC 1321.
|
|
* Copyright (C) Paul Johnston 1999 - 2000.
|
|
* Updated by Greg Holt 2000 - 2001.
|
|
* See http://pajhome.org.uk/site/legal.html for details.
|
|
*/
|
|
|
|
/*
|
|
* Convert a 32-bit number to a hex string with ls-byte first
|
|
*/
|
|
var hex_chr = "0123456789abcdef";
|
|
|
|
function rhex(num) {
|
|
var str, j;
|
|
str = "";
|
|
for (j = 0; j <= 3; j++) {
|
|
str += hex_chr.charAt((num >> (j * 8 + 4)) & 0x0F) +
|
|
hex_chr.charAt((num >> (j * 8)) & 0x0F);
|
|
}
|
|
return str;
|
|
}
|
|
|
|
/*
|
|
* Convert a string to a sequence of 16-word blocks, stored as an array.
|
|
* Append padding bits and the length, as described in the MD5 standard.
|
|
*/
|
|
function str2blks_MD5(str) {
|
|
var nblk, blks, i;
|
|
nblk = ((str.length + 8) >> 6) + 1;
|
|
blks = new Array(nblk * 16);
|
|
for (i = 0; i < nblk * 16; i++) blks[i] = 0;
|
|
for (i = 0; i < str.length; i++)
|
|
blks[i >> 2] |= str.charCodeAt(i) << ((i % 4) * 8);
|
|
blks[i >> 2] |= 0x80 << ((i % 4) * 8);
|
|
blks[nblk * 16 - 2] = str.length * 8;
|
|
return blks;
|
|
}
|
|
|
|
/*
|
|
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
|
|
* to work around bugs in some JS interpreters.
|
|
*/
|
|
function add(x, y) {
|
|
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
|
|
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
|
|
return (msw << 16) | (lsw & 0xFFFF);
|
|
}
|
|
|
|
/*
|
|
* Bitwise rotate a 32-bit number to the left
|
|
*/
|
|
function rol(num, cnt) {
|
|
return (num << cnt) | (num >>> (32 - cnt));
|
|
}
|
|
|
|
/*
|
|
* These functions implement the basic operation for each round of the
|
|
* algorithm.
|
|
*/
|
|
function cmn(q, a, b, x, s, t) {
|
|
return add(rol(add(add(a, q), add(x, t)), s), b);
|
|
}
|
|
|
|
function ff(a, b, c, d, x, s, t) {
|
|
return cmn((b & c) | ((~b) & d), a, b, x, s, t);
|
|
}
|
|
|
|
function gg(a, b, c, d, x, s, t) {
|
|
return cmn((b & d) | (c & (~d)), a, b, x, s, t);
|
|
}
|
|
|
|
function hh(a, b, c, d, x, s, t) {
|
|
return cmn(b ^ c ^ d, a, b, x, s, t);
|
|
}
|
|
|
|
function ii(a, b, c, d, x, s, t) {
|
|
return cmn(c ^ (b | (~d)), a, b, x, s, t);
|
|
}
|
|
|
|
/*
|
|
* Take a string and return the hex representation of its MD5.
|
|
*/
|
|
context.JK.calcMD5 = function (str) {
|
|
var x, a, b, c, d, i,
|
|
olda, oldb, oldc, oldd;
|
|
x = str2blks_MD5(str);
|
|
a = 1732584193;
|
|
b = -271733879;
|
|
c = -1732584194;
|
|
d = 271733878;
|
|
|
|
for (i = 0; i < x.length; i += 16) {
|
|
olda = a;
|
|
oldb = b;
|
|
oldc = c;
|
|
oldd = d;
|
|
|
|
a = ff(a, b, c, d, x[i + 0], 7, -680876936);
|
|
d = ff(d, a, b, c, x[i + 1], 12, -389564586);
|
|
c = ff(c, d, a, b, x[i + 2], 17, 606105819);
|
|
b = ff(b, c, d, a, x[i + 3], 22, -1044525330);
|
|
a = ff(a, b, c, d, x[i + 4], 7, -176418897);
|
|
d = ff(d, a, b, c, x[i + 5], 12, 1200080426);
|
|
c = ff(c, d, a, b, x[i + 6], 17, -1473231341);
|
|
b = ff(b, c, d, a, x[i + 7], 22, -45705983);
|
|
a = ff(a, b, c, d, x[i + 8], 7, 1770035416);
|
|
d = ff(d, a, b, c, x[i + 9], 12, -1958414417);
|
|
c = ff(c, d, a, b, x[i + 10], 17, -42063);
|
|
b = ff(b, c, d, a, x[i + 11], 22, -1990404162);
|
|
a = ff(a, b, c, d, x[i + 12], 7, 1804603682);
|
|
d = ff(d, a, b, c, x[i + 13], 12, -40341101);
|
|
c = ff(c, d, a, b, x[i + 14], 17, -1502002290);
|
|
b = ff(b, c, d, a, x[i + 15], 22, 1236535329);
|
|
|
|
a = gg(a, b, c, d, x[i + 1], 5, -165796510);
|
|
d = gg(d, a, b, c, x[i + 6], 9, -1069501632);
|
|
c = gg(c, d, a, b, x[i + 11], 14, 643717713);
|
|
b = gg(b, c, d, a, x[i + 0], 20, -373897302);
|
|
a = gg(a, b, c, d, x[i + 5], 5, -701558691);
|
|
d = gg(d, a, b, c, x[i + 10], 9, 38016083);
|
|
c = gg(c, d, a, b, x[i + 15], 14, -660478335);
|
|
b = gg(b, c, d, a, x[i + 4], 20, -405537848);
|
|
a = gg(a, b, c, d, x[i + 9], 5, 568446438);
|
|
d = gg(d, a, b, c, x[i + 14], 9, -1019803690);
|
|
c = gg(c, d, a, b, x[i + 3], 14, -187363961);
|
|
b = gg(b, c, d, a, x[i + 8], 20, 1163531501);
|
|
a = gg(a, b, c, d, x[i + 13], 5, -1444681467);
|
|
d = gg(d, a, b, c, x[i + 2], 9, -51403784);
|
|
c = gg(c, d, a, b, x[i + 7], 14, 1735328473);
|
|
b = gg(b, c, d, a, x[i + 12], 20, -1926607734);
|
|
|
|
a = hh(a, b, c, d, x[i + 5], 4, -378558);
|
|
d = hh(d, a, b, c, x[i + 8], 11, -2022574463);
|
|
c = hh(c, d, a, b, x[i + 11], 16, 1839030562);
|
|
b = hh(b, c, d, a, x[i + 14], 23, -35309556);
|
|
a = hh(a, b, c, d, x[i + 1], 4, -1530992060);
|
|
d = hh(d, a, b, c, x[i + 4], 11, 1272893353);
|
|
c = hh(c, d, a, b, x[i + 7], 16, -155497632);
|
|
b = hh(b, c, d, a, x[i + 10], 23, -1094730640);
|
|
a = hh(a, b, c, d, x[i + 13], 4, 681279174);
|
|
d = hh(d, a, b, c, x[i + 0], 11, -358537222);
|
|
c = hh(c, d, a, b, x[i + 3], 16, -722521979);
|
|
b = hh(b, c, d, a, x[i + 6], 23, 76029189);
|
|
a = hh(a, b, c, d, x[i + 9], 4, -640364487);
|
|
d = hh(d, a, b, c, x[i + 12], 11, -421815835);
|
|
c = hh(c, d, a, b, x[i + 15], 16, 530742520);
|
|
b = hh(b, c, d, a, x[i + 2], 23, -995338651);
|
|
|
|
a = ii(a, b, c, d, x[i + 0], 6, -198630844);
|
|
d = ii(d, a, b, c, x[i + 7], 10, 1126891415);
|
|
c = ii(c, d, a, b, x[i + 14], 15, -1416354905);
|
|
b = ii(b, c, d, a, x[i + 5], 21, -57434055);
|
|
a = ii(a, b, c, d, x[i + 12], 6, 1700485571);
|
|
d = ii(d, a, b, c, x[i + 3], 10, -1894986606);
|
|
c = ii(c, d, a, b, x[i + 10], 15, -1051523);
|
|
b = ii(b, c, d, a, x[i + 1], 21, -2054922799);
|
|
a = ii(a, b, c, d, x[i + 8], 6, 1873313359);
|
|
d = ii(d, a, b, c, x[i + 15], 10, -30611744);
|
|
c = ii(c, d, a, b, x[i + 6], 15, -1560198380);
|
|
b = ii(b, c, d, a, x[i + 13], 21, 1309151649);
|
|
a = ii(a, b, c, d, x[i + 4], 6, -145523070);
|
|
d = ii(d, a, b, c, x[i + 11], 10, -1120210379);
|
|
c = ii(c, d, a, b, x[i + 2], 15, 718787259);
|
|
b = ii(b, c, d, a, x[i + 9], 21, -343485551);
|
|
|
|
a = add(a, olda);
|
|
b = add(b, oldb);
|
|
c = add(c, oldc);
|
|
d = add(d, oldd);
|
|
}
|
|
return rhex(a) + rhex(b) + rhex(c) + rhex(d);
|
|
};
|
|
|
|
/** validates that no changes are being made to tracks while recording */
|
|
context.JK.verifyNotRecordingForTrackChange = function (app) {
|
|
if (context.JK.CurrentSessionModel.recordingModel.isRecording()) {
|
|
app.notify({
|
|
title: "Currently Recording",
|
|
text: "Tracks cannot be modified while recording.",
|
|
icon_url: "/assets/content/icon_alert_big.png"});
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
})(window, jQuery); |