aboutsummaryrefslogtreecommitdiffstats
path: root/web/nms.gathering.org/nms2/js
diff options
context:
space:
mode:
Diffstat (limited to 'web/nms.gathering.org/nms2/js')
-rw-r--r--web/nms.gathering.org/nms2/js/nms.js339
1 files changed, 263 insertions, 76 deletions
diff --git a/web/nms.gathering.org/nms2/js/nms.js b/web/nms.gathering.org/nms2/js/nms.js
index 2cfd4fb..97c0dc1 100644
--- a/web/nms.gathering.org/nms2/js/nms.js
+++ b/web/nms.gathering.org/nms2/js/nms.js
@@ -4,33 +4,120 @@ var nms = {
switches_then:undefined, // 2 minutes old
speed:0, // Current aggregated speed
full_speed:false, // Set to 'true' to include ALL interfaces
- ping_data:undefined,
+ ping_data:undefined, // JSON data for ping history.
drawn:false, // Set to 'true' when switches are drawn
- switch_showing:"",
- nightMode:false,
- nightBlur:{},
- switch_color:{},
- linknet_color:{},
- textDrawn:{},
- drawText:true,
- now:false,
- fontSize:14,
+ switch_showing:"", // Which switch we are displaying (if any).
+ nightMode:false,
+ /*
+ * Switch-specific variables. These are currently separate from
+ * "switches_now" because switches_now is reset every time we get
+ * new data.
+ */
+ nightBlur:{}, // Have we blurred this switch or not?
+ switch_color:{}, // Color for switch
+ linknet_color:{}, // color for linknet
+ textDrawn:{}, // Have we drawn text for this switch?
+ now:false, // Date we are looking at (false for current date).
+ fontSize:14, // This is scaled too, but 14 seems to make sense.
fontFace:"Arial Black",
- did_update:false // Set to 'true' after we've done some basic updating
+ outstandingAjaxRequests:0,
+ ajaxOverflow:0,
+ /*
+ * Set to 'true' after we've done some basic updating. Used to
+ * bootstrap the map quickly as soon as we have enough data, then
+ * ignored.
+ */
+ did_update:false,
+ /*
+ * Various setInterval() handlers.
+ */
+ handlers: {
+ replay:false,
+ ports:false,
+ info:false,
+ ping:false,
+ map:false,
+ speed:false
+ }
};
+
+/*
+ * Returns a handler object.
+ *
+ * This might seem a bit much for 'setInterval()' etc, but it's really more
+ * about self-documentation and predictable ways of configuring timers.
+ */
+function nmsTimer(handler, interval, name, description) {
+ this.handler = handler;
+ this.handle = false;
+ this.interval = parseInt(interval);
+ this.name = name;
+ this.description = description;
+ this.start = function() {
+ if (this.handle) {
+ this.stop();
+ }
+ this.handle = setInterval(this.handler,this.interval);
+ };
+ this.stop = function() {
+ if (this.handle)
+ clearInterval(this.handle);
+ this.handle = false;
+ };
+
+ this.setInterval = function(interval) {
+ var started = this.handle == false ? false : true;
+ this.stop();
+ this.interval = parseInt(interval);
+ if (started)
+ this.start();
+ };
+}
+
+/*
+ * Drawing primitives.
+ *
+ * This contains both canvas and context for drawing layers. It's on a
+ * top-level namespace to reduce SLIGHTLY the ridiculously long names
+ * (e.g.: dr.bg.ctx.drawImage() is long enough....).
+ *
+ * Only initialized once (for now).
+ */
var dr = {};
+/*
+ * Original scale. This is just used to define the coordinate system.
+ * 1920x1032 was chosen for tg15 by coincidence: We scaled the underlying
+ * map down to "full hd" and these are the bounds we got. There's no
+ * particular reason this couldn't change, except it means re-aligning all
+ * switches.
+ */
var orig = {
width:1920,
height:1032
};
+/*
+ * Canvas dimensions, and scale factor.
+ *
+ * We could derive scale factor from canvas.width / orig.width, but it's
+ * used so frequently that this makes much more sense.
+ *
+ * Width and height are rarely used.
+ */
var canvas = {
width:0,
height:0,
scale:1
};
+
+/*
+ * Various margins at the sides.
+ *
+ * Not really used much, except for "text", which is really more of a
+ * padding than margin...
+ */
var margin = {
x:10,
y:20,
@@ -41,30 +128,7 @@ var tgStart = stringToEpoch('2015-04-01T09:00:00');
var tgEnd = stringToEpoch('2015-04-05T12:00:00');
var replayTime = 0;
var replayIncrement = 30 * 60;
-var replayHandler = false;
-
-function initDrawing() {
- dr['bg'] = {};
- dr['bg']['c'] = document.getElementById("bgCanvas");
- dr['bg']['ctx'] = dr['bg']['c'].getContext('2d');
- dr['link'] = {};
- dr['link']['c'] = document.getElementById("linkCanvas");
- dr['link']['ctx'] = dr['link']['c'].getContext('2d');
- dr['blur'] = {};
- dr['blur']['c'] = document.getElementById("blurCanvas");
- dr['blur']['ctx'] = dr['blur']['c'].getContext('2d');
- dr['switch'] = {};
- dr['switch']['c'] = document.getElementById("switchCanvas");
- dr['switch']['ctx'] = dr['switch']['c'].getContext('2d');
- dr['text'] = {};
- dr['text']['c'] = document.getElementById("textCanvas");
- dr['text']['ctx'] = dr['text']['c'].getContext('2d');
- dr['top'] = {};
- dr['top']['c'] = document.getElementById("topCanvas");
- dr['top']['ctx'] = dr['top']['c'].getContext('2d');
-}
-initDrawing();
/*
* Handlers. "updater" is run periodically when the handler is active, and
* "init" is run once when it's activated.
@@ -100,6 +164,32 @@ var handler_disco = {
name:"Disco fever"
};
+/*
+ * Convenience-function to populate the 'dr' structure.
+ *
+ * Only run once.
+ */
+function initDrawing() {
+ dr['bg'] = {};
+ dr['bg']['c'] = document.getElementById("bgCanvas");
+ dr['bg']['ctx'] = dr['bg']['c'].getContext('2d');
+ dr['link'] = {};
+ dr['link']['c'] = document.getElementById("linkCanvas");
+ dr['link']['ctx'] = dr['link']['c'].getContext('2d');
+ dr['blur'] = {};
+ dr['blur']['c'] = document.getElementById("blurCanvas");
+ dr['blur']['ctx'] = dr['blur']['c'].getContext('2d');
+ dr['switch'] = {};
+ dr['switch']['c'] = document.getElementById("switchCanvas");
+ dr['switch']['ctx'] = dr['switch']['c'].getContext('2d');
+ dr['text'] = {};
+ dr['text']['c'] = document.getElementById("textCanvas");
+ dr['text']['ctx'] = dr['text']['c'].getContext('2d');
+ dr['top'] = {};
+ dr['top']['c'] = document.getElementById("topCanvas");
+ dr['top']['ctx'] = dr['top']['c'].getContext('2d');
+}
+
function byteCount(bytes) {
var units = ['', 'K', 'M', 'G', 'T', 'P'];
i = 0;
@@ -148,7 +238,7 @@ function epochToString(t)
function timeReplay()
{
if (replayTime >= tgEnd) {
- clearInterval(replayHandler);
+ nms.handlers.replay.stop();
return;
}
replayTime = parseInt(replayTime) + parseInt(replayIncrement);
@@ -157,12 +247,11 @@ function timeReplay()
}
function startReplay() {
- if (replayHandler)
- clearInterval(replayHandler);
+ nms.handlers.replay.stop();
resetColors();
replayTime = tgStart;
timeReplay();
- replayHandler = setInterval(timeReplay,1000);
+ nms.handlers.replay.start();;
}
function changeNow() {
@@ -565,7 +654,7 @@ function pingInit()
*/
function updateMap()
{
- if (nms.updater != undefined) {
+ if (nms.updater != undefined && nms.switches_now && nms.switches_then) {
nms.updater();
}
}
@@ -611,6 +700,11 @@ function initialUpdate()
function updatePing()
{
var now = nms.now ? ("?now=" + nms.now) : "";
+ if (nms.outstandingAjaxRequests > 5) {
+ nms.ajaxOverflow++;
+ return;
+ }
+ nms.outstandingAjaxRequests++;
$.ajax({
type: "GET",
url: "/ping-json2.pl" + now,
@@ -618,6 +712,9 @@ function updatePing()
success: function (data, textStatus, jqXHR) {
nms.ping_data = JSON.parse(data);
initialUpdate();
+ },
+ complete: function(jqXHR, textStatus) {
+ nms.outstandingAjaxRequests--;
}
});
}
@@ -628,6 +725,11 @@ function updatePing()
function updatePorts()
{
var now = "";
+ if (nms.outstandingAjaxRequests > 5) {
+ nms.ajaxOverflow++;
+ return;
+ }
+ nms.outstandingAjaxRequests++;
if (nms.now != false)
now = "?now=" + nms.now;
$.ajax({
@@ -639,11 +741,15 @@ function updatePorts()
nms.switches_now = switchdata;
parseIntPlacements();
initialUpdate();
+ },
+ complete: function(jqXHR, textStatus) {
+ nms.outstandingAjaxRequests--;
}
});
now="";
if (nms.now != false)
now = "&now=" + nms.now;
+ nms.outstandingAjaxRequests++;
$.ajax({
type: "GET",
url: "/port-state.pl?time=5m" + now,
@@ -652,6 +758,9 @@ function updatePorts()
var switchdata = JSON.parse(data);
nms.switches_then = switchdata;
initialUpdate();
+ },
+ complete: function(jqXHR, textStatus) {
+ nms.outstandingAjaxRequests--;
}
})
}
@@ -818,6 +927,9 @@ function drawSwitches()
nms.drawn = true;
}
+/*
+ * Draw current time-window
+ */
function drawNow()
{
if (nms.now != false) {
@@ -836,6 +948,9 @@ function drawNow()
/*
* Draw foreground/scene.
*
+ * FIXME: Review this! This was made before linknets and switches were
+ * split apart.
+ *
* This is used so linknets are drawn before switches. If a switch is all
* that has changed, we just need to re-draw that, but linknets require
* scene-redrawing.
@@ -873,7 +988,7 @@ function setScale()
* Returns true if the coordinates (x,y) is inside the box defined by
* box.{x,y,w.h} (e.g.: placement of a switch).
*/
-function isin(box, x, y)
+function isIn(box, x, y)
{
if ((x >= box.x) && (x <= (box.x + box.width)) && (y >= box.y) && (y <= (box.y + box.height))) {
return true;
@@ -891,7 +1006,7 @@ function findSwitch(x,y) {
y = parseInt(parseInt(y) / canvas.scale);
for (var v in nms.switches_now.switches) {
- if(isin(nms.switches_now.switches[v]['placement'],x,y)) {
+ if(isIn(nms.switches_now.switches[v]['placement'],x,y)) {
return v;
}
}
@@ -920,19 +1035,6 @@ function getRandomColor()
}
/*
- * Helper functions for the front-end testing.
- */
-function hideBorder()
-{
- c.style.border = "";
-}
-
-function showBorder()
-{
- c.style.border = "1px solid #000000";
-}
-
-/*
* Event handler for the front-end drag bar to change scale
*/
function scaleChange()
@@ -943,23 +1045,6 @@ function scaleChange()
}
/*
- * Draw a "cross hair" at/around (x,y).
- *
- * Used for testing.
- */
-function crossHair(x,y)
-{
- ctx.fillStyle = "yellow";
- ctx.fillRect(x,y,-100,10);
- ctx.fillStyle = "red";
- ctx.fillRect(x,y,100,10);
- ctx.fillStyle = "blue";
- ctx.fillRect(x,y,10,-100);
- ctx.fillStyle = "green";
- ctx.fillRect(x,y,10,100);
-}
-
-/*
* Called when a switch is clicked
*/
function switchClick(sw)
@@ -989,6 +1074,7 @@ function discoInit()
setLegend(3,"green", "3");
setLegend(2,"white","4");
}
+
/*
* Resets the colors of linknets and switches.
*
@@ -1010,7 +1096,9 @@ function resetColors()
}
/*
- * onclick handler for the canvas
+ * onclick handler for the canvas.
+ *
+ * Currently just shows info for a switch.
*/
function canvasClick(e)
{
@@ -1054,6 +1142,12 @@ function drawBG()
}
}
+/*
+ * Set night mode to whatever 'toggle' is.
+ *
+ * XXX: setScale() is a bit of a hack, but it really is the same stuff we
+ * need to do: Redraw "everything" (not really).
+ */
function setNightMode(toggle) {
nms.nightMode = toggle;
var body = document.getElementById("body");
@@ -1169,8 +1263,101 @@ function connectSwitches(insw1, insw2,color1, color2) {
dr.link.ctx.moveTo(0,0);
}
-function debugIt(e)
-{
- console.log("Debug triggered");
- console.log(e);
+
+function initNMS() {
+ var url;
+ initDrawing();
+ updatePorts();
+ updatePing();
+ window.addEventListener('resize',resizeEvent,true);
+ document.addEventListener('load',resizeEvent,true);
+
+ nms.handlers.ports = new nmsTimer(updatePorts, 1000, "Port updater", "AJAX request to update port data (traffic, etc)");
+ nms.handlers.ports.start();
+
+ nms.handlers.info = new nmsTimer(updateInfo, 5000, "Info updater", "Updates info-box about client speed (fast - no backend requests)");
+ nms.handlers.info.start();
+
+ nms.handlers.ping = new nmsTimer(updatePing, 1000, "Ping updater", "AJAX request to update ping data");
+ nms.handlers.ping.start();
+
+ nms.handlers.map = new nmsTimer(updateMap, 1000, "Map handler", "Updates the map using the chosen map handler (ping, uplink, traffic, etc)");
+ nms.handlers.map.start();
+
+ nms.handlers.speed = new nmsTimer(updateSpeed, 3000, "Speed updater", "Recompute total speed (no backend requests)");
+ nms.handlers.speed.start();
+
+ nms.handlers.replay = new nmsTimer(timeReplay, 1000, "Time machine", "Handler used to change time");
+
+ url = document.URL;
+ if (/#ping/.exec(url)) {
+ setUpdater(handler_ping);
+ }else if (/#uplink/.exec(url)) {
+ setUpdater(handler_uplinks);
+ } else if (/#temp/.exec(url)) {
+ setUpdater(handler_temp);
+ } else if (/#traffic/.exec(url)) {
+ setUpdater(handler_traffic);
+ } else if (/#disco/.exec(url)) {
+ setUpdater(handler_disco);
+ } else {
+ setUpdater(handler_ping);
+ }
+ if (/nightMode/.exec(url)) {
+ toggleNightMode();
+ }
+}
+
+function showTimerDebug() {
+ var tableTop = document.getElementById('timerTableTop');
+ var table = document.getElementById('timerTable');
+ var tr, td1, td2;
+ if (table)
+ tableTop.removeChild(table);
+ table = document.createElement("table");
+ table.id = "timerTable";
+ table.style.zIndex = 100;
+ table.className = "table";
+ table.classList.add("table");
+ table.classList.add("table-default");
+ table.border = "1";
+ tr = document.createElement("tr");
+ td = document.createElement("th");
+ td.innerHTML = "Handler";
+ tr.appendChild(td);
+ td = document.createElement("th");
+ td.innerHTML = "Interval (ms)";
+ tr.appendChild(td);
+ td = document.createElement("th");
+ td.innerHTML = "Name";
+ tr.appendChild(td);
+ td = document.createElement("th");
+ td.innerHTML = "Description";
+ tr.appendChild(td);
+ table.appendChild(tr);
+ for (var v in nms.handlers) {
+ tr = document.createElement("tr");
+ td = document.createElement("td");
+ td.innerHTML = nms.handlers[v].handle;
+ tr.appendChild(td);
+ td = document.createElement("td");
+ td.innerHTML = "<input type=\"text\" id='handlerValue" + v + "' value='" + nms.handlers[v].interval + "'>";
+ td.innerHTML += "<button type=\"button\" class=\"btn btn-default\" onclick=\"nms.handlers['" + v + "'].setInterval(document.getElementById('handlerValue" + v + "').value);\">Apply</button>";
+ tr.appendChild(td);
+ td = document.createElement("td");
+ td.innerHTML = nms.handlers[v].name;
+ tr.appendChild(td);
+ td = document.createElement("td");
+ td.innerHTML = nms.handlers[v].description;
+ tr.appendChild(td);
+ table.appendChild(tr);
+ }
+ tableTop.appendChild(table);
+ document.getElementById('debugTimers').style.display = 'block';
+}
+
+function debugHandlers() {
+ for (var v in nms.handlers) {
+ console.log(nms.handlers[v]);
+ }
}