diff options
author | Freeyorp <TheFreeYorp@NOSPAM.G.m.a.i.l.replace> | 2013-05-14 21:08:11 +1200 |
---|---|---|
committer | Freeyorp <TheFreeYorp@NOSPAM.G.m.a.i.l.replace> | 2013-05-14 21:09:06 +1200 |
commit | 4e83d0b4c7e2b303689ac1b8df6373a987ab1944 (patch) | |
tree | 46974728f66f38112922d9d3105aa6faad481fb3 /public | |
parent | 8edde7d254089d9ae7b4745d43117b02c9d4b09d (diff) | |
download | manavis-4e83d0b4c7e2b303689ac1b8df6373a987ab1944.tar.gz manavis-4e83d0b4c7e2b303689ac1b8df6373a987ab1944.tar.bz2 manavis-4e83d0b4c7e2b303689ac1b8df6373a987ab1944.tar.xz manavis-4e83d0b4c7e2b303689ac1b8df6373a987ab1944.zip |
Add channels
Active filters will only be applied from users in the same channel.
This closes #14.
Diffstat (limited to 'public')
-rw-r--r-- | public/css/style.css | 13 | ||||
-rw-r--r-- | public/index.html | 2 | ||||
-rw-r--r-- | public/js/mv/connect.js | 193 | ||||
-rw-r--r-- | public/js/mv/main.js | 2 | ||||
-rw-r--r-- | public/js/mv/parse.js | 3 |
5 files changed, 172 insertions, 41 deletions
diff --git a/public/css/style.css b/public/css/style.css index d223226..0e1e244 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -151,9 +151,20 @@ h3 { border-left: 1px black solid; border-bottom: 1px black solid; display: none; + height: 200px; + overflow-y: scroll; } -#users-status { +#users-status .channel { + border: 1px gray solid; + margin: 0 2em; +} + +#users-status a { + margin-left: 1em; +} + +#users-status ul { padding-left: 20px; } diff --git a/public/index.html b/public/index.html index 0ab91a1..a016fb1 100644 --- a/public/index.html +++ b/public/index.html @@ -9,7 +9,7 @@ <div class="side med col3"> <div id="connect-status"> <h3>Manavis users</h3> - <ul id="users-status"></ul> + <div id="users-status"></div> </div> <div id="blvl-chart"> <h3>Character base level <a class="reset" style="display: none;" href="javascript:mv.charts.blvl.filterAll();dc.redrawAll();">clear</a></h3> 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() ; } diff --git a/public/js/mv/main.js b/public/js/mv/main.js index eb802e0..d7ebdf9 100644 --- a/public/js/mv/main.js +++ b/public/js/mv/main.js @@ -58,7 +58,7 @@ var mv = function(mv) { mv.charter.init(); console.log(document.getElementById("connect-option").checked); if (document.getElementById("connect-option").checked) { - mv.socket.connect(); + mv.connect.connect(); } }, 2000); } diff --git a/public/js/mv/parse.js b/public/js/mv/parse.js index b30a19a..2c8b916 100644 --- a/public/js/mv/parse.js +++ b/public/js/mv/parse.js @@ -218,7 +218,6 @@ var mv = function(mv) { } function parseScrubbed(scrubbedRecords) { scrubbedRecords = JSON.parse(scrubbedRecords); - console.log(scrubbedRecords, scrubbedRecords.length); /* * The work is mostly all done for us. Just scan through to see if there * are any undefined records, and update the pointer if so. @@ -236,7 +235,7 @@ var mv = function(mv) { } } /* It's simple when everything's already been done. */ - parser.records = parser.records.concat(scrubbedRecords); + mv.parser.records = mv.parser.records.concat(scrubbedRecords); } return mv; }(mv || {}); |