summaryrefslogtreecommitdiff
path: root/public/js/mv/connect.js
diff options
context:
space:
mode:
Diffstat (limited to 'public/js/mv/connect.js')
-rw-r--r--public/js/mv/connect.js193
1 files changed, 157 insertions, 36 deletions
diff --git a/public/js/mv/connect.js b/public/js/mv/connect.js
index 0fee5e7..564690d 100644
--- a/public/js/mv/connect.js
+++ b/public/js/mv/connect.js
@@ -1,7 +1,9 @@
"use strict";
var mv = function(mv) {
- mv.socket = {
- connect: connect
+ mv.connect = {
+ connect: connect,
+ join: join,
+ part: part
};
/* If we're updating due to something we received, then don't broadcast back. */
var netrendering = false;
@@ -19,12 +21,17 @@ var mv = function(mv) {
socket.on("disconnect", function() { console.log("DISCONNECT", arguments); });
d3.select("#connect-status").style("display", "block");
socket.emit('login');
+ /* Tell the server our starting filters */
+ socket.emit("filter", { filters: mv.charter.filters() });
/*
* Protocol:
* selflogin -> id (I)
* login -> id (I), nick (S)
* nickset -> id (I), nick (S)
- * users -> { id -> {nick (S), filters ({dim (S) -> filter (*)}) } }
+ * join -> id (I), channel (I)
+ * part -> id (I)
+ * filterset -> id (I), filters ({dim (S) -> filter (*)})
+ * users -> { id -> { nick (S), channel (I), filters ({dim (S) -> filter (*)}) } }
* logout -> id (I)
*/
socket.on('selflogin', function(d) {
@@ -48,9 +55,20 @@ var mv = function(mv) {
users[d.id].nick = d.nick;
updateUsersStatus();
});
+ socket.on('join', function(d) {
+ users[d.id].channel = d.channel;
+ updateUsersStatus();
+ });
+ socket.on('part', function(d) {
+ delete users[d.id].channel;
+ updateUsersStatus();
+ });
socket.on('filterset', function(d) {
/* Someone changed their filter */
- users[d.id].filters = d.filters;
+ /* Ignore server sourced (ID: 0) changes */
+ if (d.id) {
+ users[d.id].filters = d.filters;
+ }
/* Use the variable netrendering to denote that we're rendering due to a change received from the network. */
netrendering = true;
setOwnFilters(d.filters);
@@ -83,6 +101,13 @@ var mv = function(mv) {
var key;
/* Check for keys in the filters to apply which are not in our charts. */
for (key in filters) {
+ if (key == "date") {
+ /*
+ * Special case! FIXME: Find a more elegant way to handle this
+ */
+ filters[key][0] = new Date(filters[key][0]);
+ filters[key][1] = new Date(filters[key][1]);
+ }
if (!(key in mv.charts))
continue;
var filter = mv.charts[key].filter();
@@ -115,49 +140,145 @@ var mv = function(mv) {
dc.redrawAll();
}
}
+ function join(channel) {
+ if (channel != null) {
+ socket.emit("join", channel);
+ } else {
+ socket.emit("join");
+ }
+ }
+ function part() {
+ socket.emit("part");
+ }
function updateUsersStatus() {
/* Convert the user list to a form suitable for a d3 selection */
- var data = [];
- for (var uid in users) { users[uid].id = uid; data.push(users[uid]); }
- /* Data join */
- var userlist = usersStatus.selectAll(".user")
- .data(data, function(d) { return d.id; });
- /* Enter */
- userlist
- .enter().append("li").attr("class", "user")
+ var groups = [];
+ /* Track the groupless people separately. They should come at the end. */
+ var unchannelled = [];
+ var channelById = {};
+ var channelNames = [];
+ for (var uid in users) {
+ users[uid].id = uid;
+ if ("channel" in users[uid]) {
+ if (!(users[uid].channel in channelById)) {
+ groups.push(channelById[users[uid].channel] = []);
+ channelNames.push(users[uid].channel);
+ }
+ channelById[users[uid].channel].push(users[uid]);
+ } else {
+ unchannelled.push(users[uid]);
+ }
+ }
+ console.log("Channels:", groups, "Users without channels:", unchannelled);
+ groups.push(unchannelled);
+ var createpart = usersStatus.select(".createpart");
+ /* Link to part a channel we're in, or create a channel if we're not in one */
+ if (createpart.empty()) {
+ createpart = usersStatus.append("a")
+ .attr("class", "createpart")
+ ;
+ }
+ if ("channel" in users[id]) {
+ createpart
+ .attr("href", "javascript:mv.connect.part();")
+ .text("Part channel")
+ ;
+ } else {
+ createpart
+ .attr("href", "javascript:mv.connect.join();")
+ .text("Create channel")
+ ;
+ }
+ /* List of groups, with unchanneled users at the end */
+ var grouplist = usersStatus.selectAll(".group")
+ .data(groups, function(d, i) { return channelNames[i]; })
+ ;
+ grouplist
+ .enter().append("div").attr("class", "group")
;
/* Update */
- userlist
- .each(function(d,i) {
- var elm = d3.select(this);
- console.log("Userlist para appending", d,i);
- var name = elm.select(".name");
- var nick = d.nick == null ? "Anonymous User " + d.id : d.nick;
- if (d.id == id) {
- /* This is us! We can edit our name. */
- if (name.empty()) {
- console.log("Found our entry. id:", id, "datum", d);
- name = elm.append("input").attr("class", "name")
- .attr("type", "text")
- .attr("placeholder", "Enter name here")
- .on("change", function () {
- /* A d3 select must be dereferenced twice to access the DOM entity */
- socket.emit("nick", { nick: name[0][0].value });
- })
+ grouplist
+ .each(function(d, i) {
+ var group = d3.select(this);
+ var ul = group.select("ul");
+ if (ul.empty()) {
+ ul = group.append("ul");
+ }
+ /*
+ * Hacky way to check if these are the users without a channel.
+ * Feel free to FIXME!
+ */
+ if (i != groups.length - 1) {
+ console.log("Group is a channel", i, groups.length);
+ group
+ .attr("class", "group channel")
+ ;
+ var join = group.select(".join");
+ if (join.empty()) {
+ join = group.append("a")
+ .attr("class", "join")
+ .attr("href", "javascript:mv.connect.join(" + channelNames[i] + ");")
+ .text("Join channel")
;
}
- name.attr("value", nick);
+ if (users[id].channel == channelNames[i]) {
+ /* We're in this channel */
+ join.style("display", "none");
+ } else {
+ join.style("display", "inline");
+ }
} else {
- /* This is someone else. We can't edit their name. */
- if (name.empty()) {
- name = elm.append("p").attr("class", "name");
+ console.log("Group is not a channel", i, groups.length);
+ var join = group.select(".join");
+ group
+ .attr("class", "group")
+ ;
+ if (join.empty()) {
+ join.remove();
}
- name.text(nick);
}
+ /* Update the list of users in this group */
+ var userlist = ul.selectAll(".user")
+ .data(d, function(d) { return d.id; })
+ ;
+ userlist
+ .enter().append("li").attr("class", "user")
+ ;
+ userlist
+ .each(function(d,i) {
+ var elm = d3.select(this);
+ console.log("Userlist para appending", d,i);
+ var name = elm.select(".name");
+ var nick = d.nick == null ? "Anonymous User " + d.id : d.nick;
+ if (d.id == id) {
+ /* This is us! We can edit our name. */
+ if (name.empty()) {
+ console.log("Found our entry. id:", id, "datum", d);
+ name = elm.append("input").attr("class", "name")
+ .attr("type", "text")
+ .attr("placeholder", "Enter name here")
+ .on("change", function () {
+ /* A d3 select must be dereferenced twice to access the DOM entity */
+ socket.emit("nick", { nick: name[0][0].value });
+ })
+ ;
+ }
+ name.attr("value", nick);
+ } else {
+ /* This is someone else. We can't edit their name. */
+ if (name.empty()) {
+ name = elm.append("p").attr("class", "name");
+ }
+ name.text(nick);
+ }
+ })
+ ;
+ userlist
+ .exit().remove()
+ ;
})
;
- /* Remove */
- userlist
+ grouplist
.exit().remove()
;
}