diff options
Diffstat (limited to 'web/nms-public.gathering.org/js/nms-map.js')
-rw-r--r-- | web/nms-public.gathering.org/js/nms-map.js | 580 |
1 files changed, 580 insertions, 0 deletions
diff --git a/web/nms-public.gathering.org/js/nms-map.js b/web/nms-public.gathering.org/js/nms-map.js new file mode 100644 index 0000000..ada6886 --- /dev/null +++ b/web/nms-public.gathering.org/js/nms-map.js @@ -0,0 +1,580 @@ +"use strict"; + +/* WORK + * IN + * PROGRESS + * + * Interface: + * + * nmsMap.init() - start things up + * nmsMap.setSwitchColor(switch,color) + * nmsMap.setSwitchInfo(switch,info) + * nmsMap.setSwitchHighlight(switch,true/false) + * nmsMap.enableHighlights() + * nmsMap.disableHighlights() + */ + + +var nmsMap = nmsMap || { + _moveInProgress: false, + stats: { + colorChange:0, + colorSame:0, + earlyDrawAll:0, + nowDups:0, + nows:0, + resizeEvents:0, + switchInfoSame:0, + switchInfoUpdate:0, + highlightChange:0 + }, + contexts: ["bg","link","blur","switch","text","textInfo","top","input","hidden"], + _info: {}, + _settings: { + fontLineFactor: 2, + textMargin: 3, + xMargin: 10, + yMargin: 20, + fontSize: 15, + fontFace: "sans-serif" + }, + scale: 1, + _init: true, + _orig: { width:1920, height:1032 }, + _canvas: { + get width() { return nmsMap.scale * nmsMap._orig.width; }, + get height() { return nmsMap.scale * nmsMap._orig.height; } + }, + + _color: { }, + _linknets: {} , + _highlight: { }, + _highlightActive: false, + _c: {} +}; + +nmsMap._loadEvent = function(e) { + nmsMap._init = false; + nmsMap._drawAllSwitches(); +}; + +nmsMap.init = function() { + this._initContexts(); + this._init = true; + nmsData.addHandler("switches","nmsMap",function(){nmsMap._resizeEvent();}); + window.addEventListener('resize',nmsMap._resizeEvent,true); + window.addEventListener('load',nmsMap._loadEvent,true); +}; + +nmsMap.setSwitchColor = function(sw, color) { + if (this._color[sw] != color) { + this._color[sw] = color; + this._drawSwitch(sw); + this.stats.colorChange++; + } else { + this.stats.colorSame++; + } +}; + + +nmsMap.setSwitchHighlight = function(sw, highlight) { + if( highlight ) + highlight = true; + if ( this._highlight[sw] != highlight ) { + this.stats.highlightChange++; + this._highlight[sw] = highlight; + } + this._drawSwitch(sw); +}; + + +nmsMap.enableHighlights = function() { + this._highlightActive = true; +}; + + +nmsMap.disableHighlights = function() { + this._highlightActive = false; + this._drawAllSwitches(); +}; + + +nmsMap.reset = function() { + for (var sw in this._color) { + nmsMap.setSwitchColor(sw, undefined); + } + for (var sw in this._info) { + nmsMap.setSwitchInfo(sw, undefined); + } +}; + +nmsMap.setSwitchInfo = function(sw,info) { + if (this._info[sw] != info) { + this._info[sw] = info; + this._drawSwitchInfo(sw); + this.stats.switchInfoUpdate++; + } else { + this.stats.switchInfoSame++; + } +}; + +nmsMap._initContext = function(name) { + this._c[name] = {}; + this._c[name].c = document.getElementById(name + "Canvas"); + this._c[name].ctx = this._c[name].c.getContext('2d'); +}; + +nmsMap._initContexts = function() { + for (var context in this.contexts) { + this._initContext(this.contexts[context]); + } +}; + +nmsMap._resizeEvent = function() { + var width = window.innerWidth - nmsMap._c.bg.c.offsetLeft; + var height = window.innerHeight - nmsMap._c.bg.c.offsetTop; + + var xScale = (width / (nmsMap._orig.width + nmsMap._settings.xMargin)); + var yScale = (height / (nmsMap._orig.height + nmsMap._settings.yMargin)); + + if (xScale > yScale) { + nmsMap.scale = yScale; + } else { + nmsMap.scale = xScale; + } + for (var a in nmsMap._c) { + /* + * Resizing this to a too small size breaks gradients on smaller screens. + */ + if (a == 'hidden' && a != 'blur') + continue; + nmsMap._c[a].c.height = nmsMap._canvas.height; + nmsMap._c[a].c.width = nmsMap._canvas.width; + if(a == 'bg') { + nmsMap._drawBG(); + } + } + if (nmsMap._init != true) { + nmsMap._blurDrawn = false; + nmsMap._drawBG(); + nmsMap._drawAllSwitches(); + nmsMap._drawAllLinknets(); + nmsMap.drawNow(); + nmsMap.stats.resizeEvents++; + } +}; + +/* + * Draw current time-window + * + * FIXME: The math here is just wild approximation and guesswork because + * I'm lazy. + * + * FIXME: 2: Should really just use _drawText() instead somehow. Font size + * being an issue. + */ +nmsMap.drawNow = function () +{ + var now = nmsData.now; + if (nmsMap._lastNow == now) { + nmsMap.stats.nowDups++; + return; + } + nmsMap.stats.nows++; + + var ctx = nmsMap._c.top.ctx; + ctx.save(); + ctx.scale(this.scale, this.scale); + ctx.font = (2 * this._settings.fontSize) + "px " + this._settings.fontFace; + ctx.clearRect(0,0,800,100); + ctx.fillStyle = "white"; + ctx.strokeStyle = "black"; + ctx.lineWidth = nms.fontLineFactor; + ctx.strokeText(now, this._settings.textMargin, 25); + ctx.fillText(now, this._settings.textMargin, 25); + ctx.restore(); +}; + +nmsMap.setNightMode = function(toggle) { + if (this._nightmode == toggle) + return; + this._nightmode = toggle; + if (this._init == true) { + return; + } + if (!toggle) + this._c.blur.c.style.display = "none"; + else { + this._drawAllBlur(); + this._c.blur.c.style.display = ""; + } + nmsMap._drawBG(); +}; + +nmsMap._drawBG = function() { + var imageObj = document.getElementById('source'); + this._c.bg.ctx.drawImage(imageObj, 0, 0, nmsMap._canvas.width, nmsMap._canvas.height); + if(this._nightmode) + nmsMap._invertBG(); +}; + +nmsMap._invertBG = function() { + var imageData = this._c.bg.ctx.getImageData(0, 0, nmsMap._canvas.width, nmsMap._canvas.height); + var data = imageData.data; + + for(var i = 0; i < data.length; i += 4) { + data[i] = 255 - data[i]; + data[i + 1] = 255 - data[i + 1]; + data[i + 2] = 255 - data[i + 2]; + } + this._c.bg.ctx.putImageData(imageData, 0, 0); +}; + +nmsMap._getBox = function(sw) { + var box = nmsData.switches.switches[sw]['placement']; + box.x = parseInt(box.x); + box.y = parseInt(box.y); + box.width = parseInt(box.width); + box.height = parseInt(box.height); + return box; +}; + +nmsMap._drawSwitchBlur = function(sw) +{ + if (nmsData.switches == undefined || nmsData.switches.switches == undefined) + return; + var box = this._getBox(sw); + this._c.blur.ctx.save(); + this._c.blur.ctx.fillStyle = "red"; + this._c.blur.ctx.shadowBlur = 30; + this._c.blur.ctx.shadowColor = "white"; + this._c.blur.ctx.scale(this.scale, this.scale); // FIXME <- fix what?! + this._c.blur.ctx.fillRect(box['x'],box['y'],box['width'],box['height']); + this._c.blur.ctx.restore(); +}; + +nmsMap._drawSwitch = function(sw) +{ + // XXX: If a handler sets a color before switches are loaded... The + // color will get set fine so this isn't a problem. + if (nmsData.switches == undefined || nmsData.switches.switches == undefined) + return; + var box = this._getBox(sw); + var color = nmsMap._color[sw]; + if(this._highlightActive) { + if(nmsMap._highlight[sw]) { + color = green; + } else { + color = white; + } + } + if (color == undefined) { + color = blue; + } + this._c.switch.ctx.fillStyle = color; + this._drawBox(this._c.switch.ctx, box['x'],box['y'],box['width'],box['height']); + this._c.switch.ctx.shadowBlur = 0; + this._drawText(this._c.text.ctx, sw,box); + + if(this._info[sw]) + this._drawSwitchInfo(sw); +}; + +nmsMap._drawSwitchInfo = function(sw) { + var box = this._getBox(sw); + if (this._info[sw] == undefined) { + this._clearBox(this._c.textInfo.ctx, box); + } else { + this._drawText(this._c.textInfo.ctx, this._info[sw], box, "right"); + } +}; + +nmsMap._clearBox = function(ctx,box) { + ctx.save(); + ctx.scale(this.scale,this.scale); + ctx.clearRect(box['x'], box['y'], box['width'], box['height']); + ctx.restore(); +}; + +nmsMap._drawText = function(ctx, text, box, align) { + var rotate = false; + + if ((box['width'] + 10 )< box['height']) + rotate = true; + + this._clearBox(ctx,box); + ctx.save(); + ctx.scale(this.scale, this.scale); + ctx.font = "bold " + this._settings.fontSize + "px " + this._settings.fontFace; + ctx.lineWidth = nmsMap._settings.fontLineFactor; + ctx.fillStyle = "white"; + ctx.strokeStyle = "black"; + ctx.translate(box.x + this._settings.textMargin, box.y + box.height - this._settings.textMargin); + + if (rotate) { + ctx.translate(box.width - this._settings.textMargin * 2,0); + ctx.rotate(Math.PI * 3/2); + } + + if (align == "right") { + ctx.textAlign = "right"; + /* + * Margin*2 is to compensate for the margin above. + */ + if (rotate) + ctx.translate(box.height - this._settings.textMargin*2,0); + else + ctx.translate(box.width - this._settings.textMargin*2,0); + } + + ctx.strokeText(text, 0, 0); + ctx.fillText(text, 0, 0); + ctx.restore(); +}; + +nmsMap._setLinknetColor = function(l, color1, color2) +{ + var oldcolor1; + var oldcolor2; + try { + oldcolor1 = nmsMap._linknets[l].sysname1; + oldcolor2 = nmsMap._linknets[l].sysname2; + if (oldcolor1 == color1 && oldcolor2 == color2) { + return ; + } + } catch (e) {} + nmsMap._linknets[l] = {}; + nmsMap._linknets[l].sysname1 = color1; + nmsMap._linknets[l].sysname2 = color2; + nmsMap._drawLinknet(l) +} + +nmsMap._drawLinknet = function(l) { + try { + var color1 = blue; + var color2 = blue; + try { + color1 = nmsMap._linknets[l].sysname1; + color2 = nmsMap._linknets[l].sysname2; + } catch(e) { } + nmsMap._connectSwitches(nmsData.switches.linknets[l].sysname1, nmsData.switches.linknets[l].sysname2, color1, color2); + } catch(e) { } +} + +nmsMap._drawAllLinknets = function() { + for (var l in nmsData.switches.linknets) { + nmsMap._drawLinknet(l); + } +} +nmsMap._drawAllSwitches = function() { + if (nmsData.switches == undefined) { + this.stats.earlyDrawAll++; + return; + } + for (var sw in nmsData.switches.switches) { + this._drawSwitch(sw); + } + if (this._nightmode) + this._drawAllBlur(); +}; + +nmsMap._drawAllBlur = function() { + if (nmsMap._blurDrawn == true) + return; + nmsMap._blurDrawn = true; + for (var sw in nmsData.switches.switches) { + nmsMap._drawSwitchBlur(sw); + } +}; + +nmsMap._drawBox = function(ctx, x, y, boxw, boxh) { + ctx.save(); + ctx.scale(this.scale, this.scale); // FIXME <- what?! + ctx.fillRect(x,y, boxw, boxh); + ctx.lineWidth = 1; + ctx.strokeStyle = "#000000"; + ctx.strokeRect(x,y, boxw, boxh); + ctx.restore(); +}; + +nmsMap._connectSwitches = function(sw1, sw2, color1, color2) { + nmsMap._connectBoxes(this._getBox(sw1), this._getBox(sw2), + color1, color2); +}; + +/* + * Draw a line between two boxes, with a gradient going from color1 to + * color2. + */ +nmsMap._connectBoxes = function(box1, box2,color1, color2) { + var ctx = nmsMap._c.link.ctx; + if (color1 == undefined) + color1 = blue; + if (color2 == undefined) + color2 = blue; + var x0 = Math.floor(box1.x + box1.width/2); + var y0 = Math.floor(box1.y + box1.height/2); + var x1 = Math.floor(box2.x + box2.width/2); + var y1 = Math.floor(box2.y + box2.height/2); + ctx.save(); + ctx.scale(nmsMap.scale, nmsMap.scale); + var gradient = ctx.createLinearGradient(x1,y1,x0,y0); + gradient.addColorStop(0, color1); + gradient.addColorStop(1, color2); + ctx.strokeStyle = gradient; + ctx.beginPath(); + ctx.moveTo(x0,y0); + ctx.lineTo(x1,y1); + ctx.lineWidth = 5; + ctx.stroke(); + ctx.closePath(); + ctx.restore(); +}; + +nmsMap.moveSet = function(toggle) { + nmsMap._moveInProgress = toggle; + if (!toggle) + nmsMap._moveStopListen(); +}; + +/* + * onclick handler for the canvas. + * + * Currently just shows info for a switch. + */ +nmsMap.canvasClick = function(e) +{ + var sw = findSwitch(e.pageX - e.target.offsetLeft, e.pageY - e.target.offsetTop); + if (sw != undefined) { + if (nmsMap._moveInProgress) { + nmsMap._moveStart(sw, e); + } else { + nmsInfoBox.click(sw); + } + } else { + nmsInfoBox.hide(); + } +}; + +nmsMap._clearOld = function(box) { + if (box) { + nmsMap._c.top.ctx.save(); + nmsMap._c.top.ctx.fillStyle = "#000000"; + nmsMap._c.top.ctx.scale(nmsMap.scale, nmsMap.scale); // FIXME + nmsMap._c.top.ctx.clearRect(box['x'] - 5, box['y'] - 5, box['width'] + 10, box['height'] + 10); + nmsMap._c.top.ctx.restore(); + } +}; + +nmsMap._moveMove = function(e) { + nmsMap._moveX = (e.pageX - e.target.offsetLeft) / nmsMap.scale; + nmsMap._moveY = (e.pageY - e.target.offsetTop) / nmsMap.scale; + var diffx = nmsMap._moveX - nmsMap._moveXstart; + var diffy = nmsMap._moveY - nmsMap._moveYstart; + var box = {}; + nmsMap._clearOld(nmsMap._moveOldBox); + box['x'] = nmsMap._moveBox['x'] + diffx; + box['y'] = nmsMap._moveBox['y'] + diffy; + box['height'] = nmsMap._moveBox['height']; + box['width'] = nmsMap._moveBox['width']; + nmsMap._moveOldBox = box; + nmsMap._c.top.ctx.save(); + nmsMap._c.top.ctx.fillStyle = "red"; + nmsMap._drawBox(nmsMap._c.top.ctx, box['x'], box['y'], box['width'], box['height']); + nmsMap._c.top.ctx.restore(); +}; + +nmsMap._moveSubmit = function() { + var data = { + sysname: nmsMap._moving, + placement: nmsMap._moveOldBox + }; + var myData = JSON.stringify([data]); + $.ajax({ + type: "POST", + url: "/api/write/switch-update", + dataType: "text", + data:myData, + success: function (data, textStatus, jqXHR) { + nmsData.invalidate("switches"); + } + }); +}; + +nmsMap._moveStopListen = function() { + nmsMap._c.input.c.removeEventListener('mousemove',nmsMap._moveMove, true); + nmsMap._c.input.c.removeEventListener('mouseup',nmsMap._moveDone, true); +}; + +nmsMap._moveDone = function(e) { + nmsMap._moveStopListen(); + if(nmsMap._moveOldBox == false) { + return; + } + nmsMap._moveSubmit(); + nmsMap._clearOld(nmsMap._moveOldBox); +}; + +nmsMap._moveStart = function(sw, e) +{ + nmsMap._moving = sw; + nmsMap._moveOldBox = false; + nmsMap._moveXstart = (e.pageX - e.target.offsetLeft) / nmsMap.scale; + nmsMap._moveYstart = (e.pageY - e.target.offsetTop) / nmsMap.scale; + nmsMap._moveBox = nmsData.switches.switches[sw].placement; + nmsMap._c.input.c.addEventListener('mousemove',nmsMap._moveMove,true); + nmsMap._c.input.c.addEventListener('mouseup',nmsMap._moveDone,true); +}; + + +/* + * STUFF NOT YET INTEGRATED, BUT MOVED AWAY FROM nms.js TO TIDY. + * + * Consider this a TODO list. + */ + +/* + * Draw a linknet with index i. + * + * XXX: Might have to change the index here to match backend + */ +function drawLinknet(i) +{ + var c1 = nms.linknet_color[i] && nms.linknet_color[i].c1 ? nms.linknet_color[i].c1 : blue; + var c2 = nms.linknet_color[i] && nms.linknet_color[i].c2 ? nms.linknet_color[i].c2 : blue; + if (nmsData.switches.switches[nmsData.switches.linknets[i].sysname1] && nmsData.switches.switches[nmsData.switches.linknets[i].sysname2]) { + connectSwitches(nmsData.switches.linknets[i].sysname1,nmsData.switches.linknets[i].sysname2, c1, c2); + } +} + +/* + * Draw all linknets + */ +function drawLinknets() +{ + if (nmsData.switches && nmsData.switches.linknets) { + for (var i in nmsData.switches.linknets) { + drawLinknet(i); + } + } +} + +/* + * Change both colors of a linknet. + * + * XXX: Probably have to change this to better match the backend data + */ +function setLinknetColors(i,c1,c2) +{ + if (!nms.linknet_color[i] || + nms.linknet_color[i].c1 != c1 || + nms.linknet_color[i].c2 != c2) { + if (!nms.linknet_color[i]) + nms.linknet_color[i] = {}; + nms.linknet_color[i]['c1'] = c1; + nms.linknet_color[i]['c2'] = c2; + drawLinknet(i); + } +} + + |