Add event subscription to main app with tests. Early start on track view. Add some docs.
This commit is contained in:
parent
9205b35bc0
commit
c5a7a89413
|
|
@ -6,11 +6,17 @@
|
|||
var JamKazam = context.JK.JamKazam = function() {
|
||||
var app;
|
||||
var logger = context.JK.logger;
|
||||
var subscribers = {}; // Keys are MessageType.MESSAGE values Values are lists of functions to call
|
||||
|
||||
/**
|
||||
* Dynamically build routes from markup. Any layout="screen" will get a route corresponding to
|
||||
* his layout-id attribute. If a layout-arg attribute is present, that will be named as a data
|
||||
* section of the route.
|
||||
*/
|
||||
function routing() {
|
||||
var routes = window.RouteMap, rules, rule;
|
||||
rules = {};
|
||||
context = {};
|
||||
routingContext = {};
|
||||
$('div[layout="screen"]').each(function() {
|
||||
var target = $(this).attr('layout-id');
|
||||
var targetUrl = target;
|
||||
|
|
@ -22,14 +28,17 @@
|
|||
app.layout.changeToScreen(target, data);
|
||||
};
|
||||
rules[target] = {route: '/' + targetUrl, method: target};
|
||||
context[target] = fn;
|
||||
routingContext[target] = fn;
|
||||
});
|
||||
routes.context(context);
|
||||
routes.context(routingContext);
|
||||
for (rule in rules) if (rules.hasOwnProperty(rule)) routes.add(rules[rule]);
|
||||
$(window).bind('hashchange', routes.handler);
|
||||
$(routes.handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Some simple events for hovering on the home page. May want to move to a separate file.
|
||||
*/
|
||||
function events() {
|
||||
$('.homecard').on('mouseenter', function() {
|
||||
$(this).addClass('hover');
|
||||
|
|
@ -39,17 +48,74 @@
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a websocket message
|
||||
*/
|
||||
function handleMessage(header, payload) {
|
||||
logger.debug(header.type + ": " + JSON.stringify(payload));
|
||||
if (header.type in subscribers) {
|
||||
$.each(subscribers[header.type], function() {
|
||||
try {
|
||||
this.call();
|
||||
} catch (ex) {
|
||||
logger.warn(ex);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register for all known types, logging events as they happen, and
|
||||
* notifying subscribers (see this.subscribe) as they occur.
|
||||
*/
|
||||
function _registerMessages() {
|
||||
for (var message in context.JK.MessageType) {
|
||||
logger.debug("registering " + message);
|
||||
context.JK.JamServer.registerMessageCallback(message, handleMessage);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a function to call when a certain event type happens.
|
||||
* No checks for dupes here, so take care to not add the same handler
|
||||
* for the same event type repeatedly.
|
||||
* Event Types should be one of the values in JK.MessageType
|
||||
*/
|
||||
this.subscribe = function(eventType, handler) {
|
||||
if (!(eventType in subscribers)) {
|
||||
subscribers[eventType] = [];
|
||||
}
|
||||
subscribers[eventType].push(handler);
|
||||
};
|
||||
|
||||
/**
|
||||
* Expose event firing. Generally not to be used except by tests.
|
||||
*/
|
||||
this.fireEvent = handleMessage;
|
||||
|
||||
/**
|
||||
* Provide a handler object for events related to a particular screen
|
||||
* being shown or hidden.
|
||||
* @screen is a string corresponding to the screen's layout-id attribute
|
||||
* @handler is an object with up to four optional keys:
|
||||
* beforeHide, afterHide, beforeShow, afterShow, which should all have
|
||||
* functions as values. If there is data provided by the screen's route
|
||||
* it will be provided to these functions.
|
||||
*/
|
||||
this.bindScreen = function(screen, handler) {
|
||||
this.layout.bindScreen(screen, handler);
|
||||
};
|
||||
|
||||
/**
|
||||
* Two-phase construction. Call after construction when in non-unit-test use.
|
||||
*/
|
||||
this.initialize = function() {
|
||||
var url, hash;
|
||||
app = this;
|
||||
this.layout = new JK.Layout();
|
||||
this.layout.initialize();
|
||||
routing();
|
||||
_registerMessages();
|
||||
events();
|
||||
|
||||
hash = location.hash;
|
||||
|
|
|
|||
|
|
@ -53,14 +53,9 @@
|
|||
* Register a simple console logger for all known message types.
|
||||
*/
|
||||
this.register = function() {
|
||||
for (var message in messages) {
|
||||
logger.debug("registering " + message);
|
||||
server.registerMessageCallback(message, logMessage);
|
||||
}
|
||||
|
||||
registerLoginPinger();
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
})(window);
|
||||
})(window);
|
||||
|
|
@ -13,11 +13,39 @@
|
|||
}
|
||||
|
||||
function renderSession(sessionData) {
|
||||
$contents = $('#session-contents');
|
||||
$contents.empty();
|
||||
_renderSessionInfo(sessionData);
|
||||
// TODO: Just for testing. Should respond to events.
|
||||
var trackData = {
|
||||
clientId: 1,
|
||||
name: "Jonathon Wilson",
|
||||
part: "Keyboard",
|
||||
avatar: "https://en.gravatar.com/userimage/3198431/5ba95e655ce68d976f46dcf6f99fdde5.png",
|
||||
latency: "good",
|
||||
vu: 0.0,
|
||||
gain: 0.5,
|
||||
mute: false
|
||||
};
|
||||
_addTrack(trackData);
|
||||
// TODO - hook events to the session-tracks container, not the tracks.
|
||||
// then have the events see which track fired.
|
||||
}
|
||||
|
||||
function _renderSessionInfo(sessionData) {
|
||||
$info = $('#session-info');
|
||||
$info.empty();
|
||||
var template = $('#template-session-contents').html();
|
||||
var contents = JK.fillTemplate(template, sessionData);
|
||||
$contents.html(contents);
|
||||
$info.html(contents);
|
||||
}
|
||||
|
||||
function _addTrack(trackData) {
|
||||
var template = $('#template-session-track').html();
|
||||
var newTrack = JK.fillTemplate(template, trackData);
|
||||
$('#session-tracks').append(newTrack);
|
||||
}
|
||||
|
||||
function _userJoinedSession() {
|
||||
logger.debug(arguments);
|
||||
}
|
||||
|
||||
function deleteSession(evt) {
|
||||
|
|
@ -42,6 +70,7 @@
|
|||
'afterShow': afterShow
|
||||
};
|
||||
app.bindScreen('session', screenBindings);
|
||||
app.subscribe(JK.MessageType.USER_JOINED_MUSIC_SESSION, _userJoinedSession);
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,81 @@
|
|||
(function(context,$) {
|
||||
|
||||
context.JK = context.JK || {};
|
||||
context.JK.SessionTrack = function() {
|
||||
var logger = context.JK.logger;
|
||||
|
||||
function events() {
|
||||
$('#session-contents').on("click", '[action="delete"]', deleteSession);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set latency. val = [good,medium,bad]
|
||||
*/
|
||||
function _setLatency(val) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set VU level. val = 0.0-1.0
|
||||
*/
|
||||
function _setVolumeUnit(val) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the track's gain. val = 0.0-1.0
|
||||
* Allows external control of channel fader.
|
||||
*/
|
||||
function _setGain(val) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the track's gain from current fader. Returns 0.0-1.0
|
||||
*/
|
||||
function _getGain() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether this channel is muted. Takes a boolean where
|
||||
* true means mute, false, means unmuted.
|
||||
*/
|
||||
function _mute(muted) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the channel is currently muted.
|
||||
*/
|
||||
function _isMute() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name (typically user name)
|
||||
*/
|
||||
function _setName(name) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the part this user is performing. If part is
|
||||
* one of ENUM.FIGURE_ME_OUT then it is a recognized
|
||||
* part with an icon, otherwise it is an 'other' value
|
||||
* with a default icon.
|
||||
*/
|
||||
function _setPart(part) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the channel's avatar. Typically the user's profile
|
||||
* avatar url.
|
||||
*/
|
||||
function _setAvatar(avatar_url) {
|
||||
}
|
||||
|
||||
this.initialize = function() {
|
||||
events();
|
||||
screenBindings = {
|
||||
'afterShow': afterShow
|
||||
};
|
||||
app.bindScreen('session', screenBindings);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
})(window,jQuery);
|
||||
|
|
@ -371,6 +371,8 @@
|
|||
<p class="current">Session</p>
|
||||
</div>
|
||||
<div id="session-contents">
|
||||
<div id="session-info"></div>
|
||||
<div id="session-tracks"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -381,6 +383,19 @@
|
|||
<p><a action="delete" action-id="{id}">Delete?</a></p>
|
||||
</script>
|
||||
|
||||
<!-- Template for an individual session track -->
|
||||
<script type="text/template" id="template-session-track">
|
||||
<div class="session-track" client-id="{clientId}">
|
||||
<div class="latency {latency}">Network</div>
|
||||
<div class="vu">{vu}</div>
|
||||
<div class="gain">{gain}</div>
|
||||
<div class="mute">{mute}</div>
|
||||
<div class="name">{name}</div>
|
||||
<div class="part">{part}</div>
|
||||
<div class="avatar"><img src="{avatar}"/></div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
|
||||
<!-- Find Session Screen -->
|
||||
<div layout="screen" layout-id="findSession" class="screen secondary">
|
||||
|
|
|
|||
|
|
@ -0,0 +1,51 @@
|
|||
(function(context, $) {
|
||||
|
||||
describe("JamKazam Main Application", function() {
|
||||
var jamkazam;
|
||||
|
||||
beforeEach(function() {
|
||||
jamkazam = new context.JK.JamKazam();
|
||||
});
|
||||
|
||||
describe("Event Subscription", function() {
|
||||
|
||||
it("Subscribing to ping should call function", function() {
|
||||
var called = false;
|
||||
jamkazam.subscribe(context.JK.MessageType.PING_ACK, function() {
|
||||
called = true;
|
||||
});
|
||||
var header = {type: context.JK.MessageType.PING_ACK};
|
||||
var payload = {};
|
||||
jamkazam.fireEvent(header, payload);
|
||||
expect(called).toBeTruthy();
|
||||
|
||||
});
|
||||
|
||||
it("All subscribers should be called", function() {
|
||||
var callCount = 0;
|
||||
jamkazam.subscribe(context.JK.MessageType.PING_ACK, function() {callCount += 1;});
|
||||
jamkazam.subscribe(context.JK.MessageType.PING_ACK, function() {callCount += 2;});
|
||||
var header = {type: context.JK.MessageType.PING_ACK};
|
||||
var payload = {};
|
||||
jamkazam.fireEvent(header, payload);
|
||||
expect(callCount).toEqual(3);
|
||||
});
|
||||
|
||||
it("An error in a subscriber should be caught", function() {
|
||||
var callCount = 0;
|
||||
jamkazam.subscribe(context.JK.MessageType.PING_ACK, function() {callCount += 1;});
|
||||
jamkazam.subscribe(context.JK.MessageType.PING_ACK, function() {throw "Intentional Error";});
|
||||
jamkazam.subscribe(context.JK.MessageType.PING_ACK, function() {callCount += 1;});
|
||||
var header = {type: context.JK.MessageType.PING_ACK};
|
||||
var payload = {};
|
||||
jamkazam.fireEvent(header, payload);
|
||||
expect(callCount).toEqual(2);
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
}(window, jQuery));
|
||||
Loading…
Reference in New Issue