"
+ );
+ $("#tabscontent").append("");
+
+ tabs = $(".tabscontent").tabbedContent({ loop: true }).data("api");
+ // switch to tab...
+ $("a")
+ .filter(function () {
+ return $(this).attr("href") === "#click-to-switch";
+ })
+ .on("click", function (e) {
+ var tab = prompt("Tab to switch to (number or id)?");
+ if (!tabs.switchTab(tab)) {
+ alert("That tab does not exist :\\");
+ }
+ e.preventDefault();
+ });
+ }
+ break;
+
+ case UI_OPTION:
+ if (data.parentControl) {
+ var parent = $("#select" + data.parentControl);
+ parent.append(
+ ""
+ );
+ }
+ break;
+
+ case UI_MIN:
+ if (data.parentControl) {
+ //Is it applied to a slider?
+ if ($('#sl' + data.parentControl).length) {
+ $('#sl' + data.parentControl).attr("min", data.value);
+ } else if ($('#num' + data.parentControl).length) {
+ //Or a number
+ $('#num' + data.parentControl).attr("min", data.value);
+ }
+ }
+ break;
+
+ case UI_MAX:
+ if (data.parentControl) {
+ //Is it applied to a slider?
+ if ($('#sl' + data.parentControl).length) {
+ $('#sl' + data.parentControl).attr("max", data.value);
+ } else if ($('#text' + data.parentControl).length) {
+ //Is it a text element
+ $('#text' + data.parentControl).attr("maxlength", data.value);
+ } else if ($('#num' + data.parentControl).length) {
+ //Or a number
+ $('#num' + data.parentControl).attr("max", data.value);
+ }
+ }
+ break;
+
+ case UI_STEP:
+ if (data.parentControl) {
+ var parent = $("#id" + data.parentControl + " input");
+ if (parent.size()) {
+ parent.attr("step", data.value);
+ }
+ }
+ break;
+
+ case UI_GRAPH:
+ if (data.visible) {
+ addToHTML(data);
+ graphData[data.id] = restoreGraphData(data.id);
+ renderGraphSvg(graphData[data.id], "graph" + data.id);
+ }
+ break;
+ case ADD_GRAPH_POINT:
+ var ts = Math.round(new Date().getTime() / 1000);
+ graphData[data.id].push({ x: ts, y: data.value });
+ saveGraphData();
+ renderGraphSvg(graphData[data.id], "graph" + data.id);
+ break;
+ case CLEAR_GRAPH:
+ graphData[data.id] = [];
+ saveGraphData();
+ renderGraphSvg(graphData[data.id], "graph" + data.id);
+ break;
+
+ case UI_ACCEL:
+ if (hasAccel) break;
+ hasAccel = true;
+ if (data.visible) {
+ addToHTML(data);
+ requestOrientationPermission();
+ }
+ break;
+
+ /*
+ * Update messages change the value/style of a component without adding new HTML
+ */
+ case UPDATE_LABEL:
+ $("#l" + data.id).html(data.value);
+ if (data.hasOwnProperty('elementStyle')) {
+ $("#l" + data.id).attr("style", data.elementStyle);
+ }
+ break;
+
+ case UPDATE_SWITCHER:
+ switcher(data.id, data.value == "0" ? 0 : 1);
+ if (data.hasOwnProperty('elementStyle')) {
+ $("#sl" + data.id).attr("style", data.elementStyle);
+ }
+ break;
+
+ case UPDATE_SLIDER:
+ $("#sl" + data.id).attr("value", data.value)
+ slider_move($("#sl" + data.id).parent().parent(), data.value, "100", false);
+ if (data.hasOwnProperty('elementStyle')) {
+ $("#sl" + data.id).attr("style", data.elementStyle);
+ }
+ break;
+
+ case UPDATE_NUMBER:
+ $("#num" + data.id).val(data.value);
+ if (data.hasOwnProperty('elementStyle')) {
+ $("#num" + data.id).attr("style", data.elementStyle);
+ }
+ break;
+
+ case UPDATE_TEXT_INPUT:
+ $("#text" + data.id).val(data.value);
+ if (data.hasOwnProperty('elementStyle')) {
+ $("#text" + data.id).attr("style", data.elementStyle);
+ }
+ if (data.hasOwnProperty('inputType')) {
+ $("#text" + data.id).attr("type", data.inputType);
+ }
+ break;
+
+ case UPDATE_SELECT:
+ $("#select" + data.id).val(data.value);
+ if (data.hasOwnProperty('elementStyle')) {
+ $("#select" + data.id).attr("style", data.elementStyle);
+ }
+ break;
+
+ case UPDATE_BUTTON:
+ $("#btn" + data.id).val(data.value);
+ $("#btn" + data.id).text(data.value);
+ if (data.hasOwnProperty('elementStyle')) {
+ $("#btn" + data.id).attr("style", data.elementStyle);
+ }
+ break;
+
+ case UPDATE_PAD:
+ case UPDATE_CPAD:
+ break;
+ case UPDATE_GAUGE:
+ $("#gauge" + data.id).val(data.value);
+ if (data.hasOwnProperty('elementStyle')) {
+ $("#gauge" + data.id).attr("style", data.elementStyle);
+ }
+ break;
+ case UPDATE_ACCEL:
+ break;
+
+ case UPDATE_TIME:
+ var rv = new Date().toISOString();
+ websock.send("time:" + rv + ":" + data.id);
+ break;
+
+ default:
+ console.error("Unknown type or event");
+ break;
+ }
+
+ if (data.type >= UI_TITEL && data.type < UPDATE_OFFSET) {
+ //A UI element was just added to the DOM
+ processEnabled(data);
+ }
+
+ if (data.type >= UPDATE_OFFSET && data.type < UI_INITIAL_GUI) {
+ //An "update" message was just recieved and processed
+ var element = $("#id" + data.id);
+
+ if (data.hasOwnProperty('panelStyle')) {
+ $("#id" + data.id).attr("style", data.panelStyle);
+ }
+
+ if (data.hasOwnProperty('visible')) {
+ if (data['visible'])
+ $("#id" + data.id).show();
+ else
+ $("#id" + data.id).hide();
+ }
+
+ if (data.type == UPDATE_SLIDER) {
+ element.removeClass(
+ "slider-turquoise slider-emerald slider-peterriver slider-wetasphalt slider-sunflower slider-carrot slider-alizarin"
+ );
+ element.addClass("slider-" + colorClass(data.color));
+ } else {
+ element.removeClass(
+ "turquoise emerald peterriver wetasphalt sunflower carrot alizarin"
+ );
+ element.addClass(colorClass(data.color));
+ }
+
+ processEnabled(data);
+ }
+
+ $(".range-slider__range").each(function () {
+ $(this)[0].value = $(this).attr("value");
+ $(this).next().html($(this).attr("value"));
+ });
+ };
+
+ websock.onmessage = handleEvent;
}
function sliderchange(number) {
- var val = $("#sl" + number).val();
- websock.send("slvalue:" + val + ":" + number);
+ var val = $("#sl" + number).val();
+ websock.send("slvalue:" + val + ":" + number);
- $(".range-slider__range").each(function(){
- $(this).attr("value", $(this)[0].value);
- });
+ $(".range-slider__range").each(function () {
+ $(this).attr("value", $(this)[0].value);
+ });
}
function numberchange(number) {
- var val = $("#num" + number).val();
- websock.send("nvalue:" + val + ":" + number);
+ var val = $("#num" + number).val();
+ websock.send("nvalue:" + val + ":" + number);
}
function textchange(number) {
- var val = $("#text" + number).val();
- websock.send("tvalue:" + val + ":" + number);
+ var val = $("#text" + number).val();
+ websock.send("tvalue:" + val + ":" + number);
}
function tabclick(number) {
- var val = $("#tab" + number).val();
- websock.send("tabvalue:" + val + ":" + number);
+ var val = $("#tab" + number).val();
+ websock.send("tabvalue:" + val + ":" + number);
}
function selectchange(number) {
- var val = $("#select" + number).val();
- websock.send("svalue:" + val + ":" + number);
+ var val = $("#select" + number).val();
+ websock.send("svalue:" + val + ":" + number);
}
function buttonclick(number, isdown) {
- if (isdown) websock.send("bdown:" + number);
- else websock.send("bup:" + number);
+ if (isdown) websock.send("bdown:" + number);
+ else websock.send("bup:" + number);
}
function padclick(type, number, isdown) {
- if($("#id" + number + " nav").hasClass("disabled")) {
- return;
- }
- switch (type) {
- case CENTER:
- if (isdown) websock.send("pcdown:" + number);
- else websock.send("pcup:" + number);
- break;
- case UP:
- if (isdown) websock.send("pfdown:" + number);
- else websock.send("pfup:" + number);
- break;
- case DOWN:
- if (isdown) websock.send("pbdown:" + number);
- else websock.send("pbup:" + number);
- break;
- case LEFT:
- if (isdown) websock.send("pldown:" + number);
- else websock.send("plup:" + number);
- break;
- case RIGHT:
- if (isdown) websock.send("prdown:" + number);
- else websock.send("prup:" + number);
- break;
- }
+ if ($("#id" + number + " nav").hasClass("disabled")) {
+ return;
+ }
+ switch (type) {
+ case CENTER:
+ if (isdown) websock.send("pcdown:" + number);
+ else websock.send("pcup:" + number);
+ break;
+ case UP:
+ if (isdown) websock.send("pfdown:" + number);
+ else websock.send("pfup:" + number);
+ break;
+ case DOWN:
+ if (isdown) websock.send("pbdown:" + number);
+ else websock.send("pbup:" + number);
+ break;
+ case LEFT:
+ if (isdown) websock.send("pldown:" + number);
+ else websock.send("plup:" + number);
+ break;
+ case RIGHT:
+ if (isdown) websock.send("prdown:" + number);
+ else websock.send("prup:" + number);
+ break;
+ }
}
function switcher(number, state) {
- if (state == null) {
- if (!$("#sl" + number).hasClass("checked")) {
- websock.send("sactive:" + number);
- $("#sl" + number).addClass("checked");
- } else {
- websock.send("sinactive:" + number);
- $("#sl" + number).removeClass("checked");
+ if (state == null) {
+ if (!$("#sl" + number).hasClass("checked")) {
+ websock.send("sactive:" + number);
+ $("#sl" + number).addClass("checked");
+ } else {
+ websock.send("sinactive:" + number);
+ $("#sl" + number).removeClass("checked");
+ }
+ } else if (state == 1) {
+ $("#sl" + number).addClass("checked");
+ $("#sl" + number).prop("checked", true);
+ } else if (state == 0) {
+ $("#sl" + number).removeClass("checked");
+ $("#sl" + number).prop("checked", false);
}
- } else if (state == 1) {
- $("#sl" + number).addClass("checked");
- $("#sl" + number).prop("checked", true);
- } else if (state == 0) {
- $("#sl" + number).removeClass("checked");
- $("#sl" + number).prop("checked", false);
- }
}
var rangeSlider = function (isDiscrete) {
- var range = $(".range-slider__range");
- var slidercb = function() {
- sliderchange($(this).attr("id").replace(/^\D+/g, ""));
- };
+ var range = $(".range-slider__range");
+ var slidercb = function () {
+ sliderchange($(this).attr("id").replace(/^\D+/g, ""));
+ };
- range.on({input: function() {
- $(this).next().html(this.value)}
- });
+ range.on({
+ input: function () {
+ $(this).next().html(this.value)
+ }
+ });
- range.each(function() {
- $(this).next().html(this.value);
- if($(this).attr("callbackSet") != "true") {
- if (!isDiscrete) {
- $(this).on({input: slidercb}); //input fires when dragging
- } else {
- $(this).on({change: slidercb}); //change fires only once released
- }
- $(this).attr("callbackSet", "true");
- }
- });
+ range.each(function () {
+ $(this).next().html(this.value);
+ if ($(this).attr("callbackSet") != "true") {
+ if (!isDiscrete) {
+ $(this).on({ input: slidercb }); //input fires when dragging
+ } else {
+ $(this).on({ change: slidercb }); //change fires only once released
+ }
+ $(this).attr("callbackSet", "true");
+ }
+ });
};
-var addToHTML = function(data) {
- panelStyle = data.hasOwnProperty('panelStyle') ? " style='" + data.panelStyle + "' " : "";
- panelwide = data.hasOwnProperty('wide') ? "wide" : "";
+var addToHTML = function (data) {
+ panelStyle = data.hasOwnProperty('panelStyle') ? " style='" + data.panelStyle + "' " : "";
+ panelwide = data.hasOwnProperty('wide') ? "wide" : "";
- if(!data.hasOwnProperty('parentControl') || $("#tab" + data.parentControl).length > 0) {
- //We add the control with its own panel
- var parent = data.hasOwnProperty('parentControl') ?
- $("#tab" + data.parentControl) :
- $("#row");
+ if (!data.hasOwnProperty('parentControl') || $("#tab" + data.parentControl).length > 0) {
+ //We add the control with its own panel
+ var parent = data.hasOwnProperty('parentControl') ?
+ $("#tab" + data.parentControl) :
+ $("#row");
- var html = "";
- switch(data.type) {
- case UI_LABEL:
- case UI_BUTTON:
- case UI_SWITCHER:
- case UI_CPAD:
- case UI_PAD:
- case UI_SLIDER:
- case UI_NUMBER:
- case UI_TEXT_INPUT:
- case UI_SELECT:
- case UI_GRAPH:
- case UI_GAUGE:
- case UI_ACCEL:
- html = "
" + data.label + "
" +
- elementHTML(data) +
- "
";
- break;
- case UI_SEPARATOR:
- html = "
" +
- "
" + data.label + "
";
- break;
- case UI_TIME:
- //Invisible element
- break;
+ var html = "";
+ switch (data.type) {
+ case UI_LABEL:
+ case UI_BUTTON:
+ case UI_SWITCHER:
+ case UI_CPAD:
+ case UI_PAD:
+ case UI_SLIDER:
+ case UI_NUMBER:
+ case UI_TEXT_INPUT:
+ case UI_SELECT:
+ case UI_GRAPH:
+ case UI_GAUGE:
+ case UI_ACCEL:
+ html = "
" + data.label + "
" +
+ elementHTML(data) +
+ "
";
+ break;
+ case UI_SEPARATOR:
+ html = "
" +
+ "
" + data.label + "
";
+ break;
+ case UI_TIME:
+ //Invisible element
+ break;
+ }
+
+ parent.append(html);
+
+ } else {
+ //We are adding to an existing panel so we only need the HTML for the element
+ var parent = $("#id" + data.parentControl);
+ parent.append(elementHTML(data));
}
-
- parent.append(html);
-
- } else {
- //We are adding to an existing panel so we only need the HTML for the element
- var parent = $("#id" + data.parentControl);
- parent.append(elementHTML(data));
- }
}
-var elementHTML = function(data) {
- var id = data.id
- var elementStyle = data.hasOwnProperty('elementStyle') ? " style='" + data.elementStyle + "' " : "";
- var inputType = data.hasOwnProperty('inputType') ? " type='" + data.inputType + "' " : "";
- switch(data.type) {
- case UI_LABEL:
- return "" + data.value + "";
- case UI_BUTTON:
- return "";
- case UI_SWITCHER:
- return "";
- case UI_CPAD:
- case UI_PAD:
- return "";
- case UI_SLIDER:
- return "
" +
- "" +
- data.value + "
";
- case UI_NUMBER:
- return "";
- case UI_TEXT_INPUT:
- return "";
- case UI_SELECT:
- return "";
- case UI_GRAPH:
- return "";
- case UI_GAUGE:
- return "WILL BE A GAUGE ";
- case UI_ACCEL:
- return "ACCEL // Not implemented fully!
";
- default:
- return "";
- }
+var elementHTML = function (data) {
+ var id = data.id
+ var elementStyle = data.hasOwnProperty('elementStyle') ? " style='" + data.elementStyle + "' " : "";
+ var inputType = data.hasOwnProperty('inputType') ? " type='" + data.inputType + "' " : "";
+ switch (data.type) {
+ case UI_LABEL:
+ return "" + data.value + "";
+ case UI_BUTTON:
+ return "";
+ case UI_SWITCHER:
+ return "";
+ case UI_CPAD:
+ case UI_PAD:
+ return "";
+ case UI_SLIDER:
+ return "
" +
+ "" +
+ data.value + "
";
+ case UI_NUMBER:
+ return "";
+ case UI_TEXT_INPUT:
+ return "";
+ case UI_SELECT:
+ return "";
+ case UI_GRAPH:
+ return "";
+ case UI_GAUGE:
+ return "WILL BE A GAUGE ";
+ case UI_ACCEL:
+ return "ACCEL // Not implemented fully!
";
+ default:
+ return "";
+ }
}
-var processEnabled = function(data) {
- //Handle the enabling and disabling of controls
- //Most controls can be disabled through the use of $("#").prop("disabled", true) and CSS will style it accordingly
- //The switcher and pads also require the addition of the "disabled" class
- switch(data.type) {
- case UI_SWITCHER:
- case UPDATE_SWITCHER:
- if(data.enabled) {
- $("#sl" + data.id).removeClass('disabled');
- $("#s" + data.id).prop("disabled", false);
- } else {
- $("#sl" + data.id).addClass('disabled');
- $("#s" + data.id).prop("disabled", true);
- }
- break;
-
- case UI_SLIDER:
- case UPDATE_SLIDER:
- $("#sl" + data.id).prop("disabled", !data.enabled);
- break;
+var processEnabled = function (data) {
+ //Handle the enabling and disabling of controls
+ //Most controls can be disabled through the use of $("#").prop("disabled", true) and CSS will style it accordingly
+ //The switcher and pads also require the addition of the "disabled" class
+ switch (data.type) {
+ case UI_SWITCHER:
+ case UPDATE_SWITCHER:
+ if (data.enabled) {
+ $("#sl" + data.id).removeClass('disabled');
+ $("#s" + data.id).prop("disabled", false);
+ } else {
+ $("#sl" + data.id).addClass('disabled');
+ $("#s" + data.id).prop("disabled", true);
+ }
+ break;
- case UI_NUMBER:
- case UPDATE_NUMBER:
- $("#num" + data.id).prop("disabled", !data.enabled);
- break;
+ case UI_SLIDER:
+ case UPDATE_SLIDER:
+ $("#sl" + data.id).prop("disabled", !data.enabled);
+ break;
- case UI_TEXT_INPUT:
- case UPDATE_TEXT_INPUT:
- $("#text" + data.id).prop("disabled", !data.enabled);
- break;
-
- case UI_SELECT:
- case UPDATE_SELECT:
- $("#select" + data.id).prop("disabled", !data.enabled);
- break;
+ case UI_NUMBER:
+ case UPDATE_NUMBER:
+ $("#num" + data.id).prop("disabled", !data.enabled);
+ break;
- case UI_BUTTON:
- case UPDATE_BUTTON:
- $("#btn" + data.id).prop("disabled", !data.enabled);
- break;
+ case UI_TEXT_INPUT:
+ case UPDATE_TEXT_INPUT:
+ $("#text" + data.id).prop("disabled", !data.enabled);
+ break;
- case UI_PAD:
- case UI_CPAD:
- case UPDATE_PAD:
- case UPDATE_CPAD:
- if(data.enabled) {
- $("#id" + data.id + " nav").removeClass('disabled');
- } else {
- $("#id" + data.id + " nav").addClass('disabled');
- }
- break;
- }
+ case UI_SELECT:
+ case UPDATE_SELECT:
+ $("#select" + data.id).prop("disabled", !data.enabled);
+ break;
+
+ case UI_BUTTON:
+ case UPDATE_BUTTON:
+ $("#btn" + data.id).prop("disabled", !data.enabled);
+ break;
+
+ case UI_PAD:
+ case UI_CPAD:
+ case UPDATE_PAD:
+ case UPDATE_CPAD:
+ if (data.enabled) {
+ $("#id" + data.id + " nav").removeClass('disabled');
+ } else {
+ $("#id" + data.id + " nav").addClass('disabled');
+ }
+ break;
+ }
}
diff --git a/data/js/controls.min.js b/data/js/controls.min.js
index e18bcce..b387a49 100644
--- a/data/js/controls.min.js
+++ b/data/js/controls.min.js
@@ -1,16 +1,15 @@
const UI_INITIAL_GUI=200;const UI_RELOAD=201;const UPDATE_OFFSET=100;const UI_EXTEND_GUI=210;const UI_TITEL=0;const UI_PAD=1;const UPDATE_PAD=101;const UI_CPAD=2;const UPDATE_CPAD=102;const UI_BUTTON=3;const UPDATE_BUTTON=103;const UI_LABEL=4;const UPDATE_LABEL=104;const UI_SWITCHER=5;const UPDATE_SWITCHER=105;const UI_SLIDER=6;const UPDATE_SLIDER=106;const UI_NUMBER=7;const UPDATE_NUMBER=107;const UI_TEXT_INPUT=8;const UPDATE_TEXT_INPUT=108;const UI_GRAPH=9;const ADD_GRAPH_POINT=10;const CLEAR_GRAPH=109;const UI_TAB=11;const UPDATE_TAB=111;const UI_SELECT=12;const UPDATE_SELECT=112;const UI_OPTION=13;const UPDATE_OPTION=113;const UI_MIN=14;const UPDATE_MIN=114;const UI_MAX=15;const UPDATE_MAX=115;const UI_STEP=16;const UPDATE_STEP=116;const UI_GAUGE=17;const UPDATE_GAUGE=117;const UI_ACCEL=18;const UPDATE_ACCEL=118;const UI_SEPARATOR=19;const UPDATE_SEPARATOR=119;const UI_TIME=20;const UPDATE_TIME=120;const UP=0;const DOWN=1;const LEFT=2;const RIGHT=3;const CENTER=4;const C_TURQUOISE=0;const C_EMERALD=1;const C_PETERRIVER=2;const C_WETASPHALT=3;const C_SUNFLOWER=4;const C_CARROT=5;const C_ALIZARIN=6;const C_DARK=7;const C_NONE=255;var graphData=new Array();var hasAccel=false;var sliderContinuous=false;function colorClass(colorId){colorId=Number(colorId);switch(colorId){case C_TURQUOISE:return"turquoise";case C_EMERALD:return"emerald";case C_PETERRIVER:return"peterriver";case C_WETASPHALT:return"wetasphalt";case C_SUNFLOWER:return"sunflower";case C_CARROT:return"carrot";case C_ALIZARIN:return"alizarin";case C_DARK:case C_NONE:return"dark";default:return"";}}
-var websock;var websockConnected=false;function requestOrientationPermission(){}
+var websock;var websockConnected=false;var WebSocketTimer=null;function requestOrientationPermission(){}
function saveGraphData(){localStorage.setItem("espuigraphs",JSON.stringify(graphData));}
function restoreGraphData(id){var savedData=localStorage.getItem("espuigraphs",graphData);if(savedData!=null){savedData=JSON.parse(savedData);return savedData[id];}
return[];}
-function restart(){$(document).add("*").off();$("#row").html("");websock.close();start();}
-function conStatusError(){websockConnected=false;$("#conStatus").removeClass("color-green");$("#conStatus").addClass("color-red");$("#conStatus").html("Error / No Connection ↻");$("#conStatus").off();$("#conStatus").on({click:restart,});}
+function restart(){$(document).add("*").off();$("#row").html("");conStatusError();start();}
+function conStatusError(){if(true===websockConnected){websockConnected=false;websock.close();$("#conStatus").removeClass("color-green");$("#conStatus").addClass("color-red");$("#conStatus").html("Error / No Connection ↻");$("#conStatus").off();$("#conStatus").on({click:restart,});}}
function handleVisibilityChange(){if(!websockConnected&&!document.hidden){restart();}}
function start(){document.addEventListener("visibilitychange",handleVisibilityChange,false);if(window.location.port!=""||window.location.port!=80||window.location.port!=443){websock=new WebSocket("ws://"+window.location.hostname+":"+window.location.port+"/ws");}else{websock=new WebSocket("ws://"+window.location.hostname+"/ws");}
-websock.onopen=function(evt){console.log("websock open");$("#conStatus").addClass("color-green");$("#conStatus").text("Connected");websockConnected=true;};websock.onclose=function(evt){console.log("websock close");conStatusError();};websock.onerror=function(evt){console.log("websock Error");console.log(evt);conStatusError();};var handleEvent=function(evt){console.log(evt);try
-{var data=JSON.parse(evt.data);}
-catch(Event)
-{console.error(Event);websock.send("uiok:"+0);return;}
+if(null===WebSocketTimer){WebSocketTimer=setInterval(function(){if(websock.readyState===3){restart();}},5000);}
+websock.onopen=function(evt){console.log("websock open");$("#conStatus").addClass("color-green");$("#conStatus").text("Connected");websockConnected=true;};websock.onclose=function(evt){console.log("websock close");conStatusError();};websock.onerror=function(evt){console.log("websock Error");console.log(evt);restart();};var handleEvent=function(evt){console.log(evt);try{var data=JSON.parse(evt.data);}
+catch(Event){console.error(Event);websock.send("uiok:"+0);return;}
var e=document.body;var center="";switch(data.type){case UI_INITIAL_GUI:$("#row").html("");$("#tabsnav").html("");$("#tabscontent").html("");if(data.sliderContinuous){sliderContinuous=data.sliderContinuous;}
data.controls.forEach(element=>{var fauxEvent={data:JSON.stringify(element),};handleEvent(fauxEvent);});if(data.totalcontrols>(data.controls.length-1)){websock.send("uiok:"+(data.controls.length-1));}
break;case UI_EXTEND_GUI:data.controls.forEach(element=>{var fauxEvent={data:JSON.stringify(element),};handleEvent(fauxEvent);});if(data.totalcontrols>data.startindex+(data.controls.length-1)){websock.send("uiok:"+(data.startindex+(data.controls.length-1)));}
diff --git a/data/js/graph.min.js b/data/js/graph.min.js
index b113ea1..7d11b2d 100644
--- a/data/js/graph.min.js
+++ b/data/js/graph.min.js
@@ -1,15 +1,15 @@
-function lineGraph(parent,xAccessor,yAccessor){const width=620;const height=420;const gutter=40;const pixelsPerTick=30;function numericTransformer(dataMin,dataMax,pxMin,pxMax){var dataDiff=dataMax-dataMin,pxDiff=pxMax-pxMin,dataRatio=pxDiff/dataDiff,coordRatio=dataDiff/pxDiff;return{toCoord:function(data){return(data-dataMin)*dataRatio+pxMin;},toData:function(coord){return(coord-pxMin)*coordRatio+dataMin;}};}
-function axisRenderer(orientation,transform){var axisGroup=document.createElementNS("http://www.w3.org/2000/svg","g");var axisPath=document.createElementNS("http://www.w3.org/2000/svg","path");axisGroup.setAttribute("class",orientation+"-axis");var xMin=gutter;var xMax=width-gutter;var yMin=height-gutter;var yMax=gutter;if(orientation==="x"){axisPath.setAttribute("d","M "+xMin+" "+yMin+" L "+xMax+" "+yMin);for(var i=xMin;i<=xMax;i++){if((i-xMin)%pixelsPerTick===0&&i!==xMin){var text=document.createElementNS("http://www.w3.org/2000/svg","text");text.innerHTML=Math.floor(transform(i));text.setAttribute("x",i);text.setAttribute("y",yMin);text.setAttribute("dy","1em");axisGroup.appendChild(text);}}}else{axisPath.setAttribute("d","M "+xMin+" "+yMin+" L "+xMin+" "+yMax);for(var i=yMax;i<=yMin;i++){if((i-yMin)%pixelsPerTick===0&&i!==yMin){var tickGroup=document.createElementNS("http://www.w3.org/2000/svg","g");var gridLine=document.createElementNS("http://www.w3.org/2000/svg","path");text=document.createElementNS("http://www.w3.org/2000/svg","text");text.innerHTML=Math.floor(transform(i));text.setAttribute("x",xMin);text.setAttribute("y",i);text.setAttribute("dx","-.5em");text.setAttribute("dy",".3em");gridLine.setAttribute("d","M "+xMin+" "+i+" L "+xMax+" "+i);tickGroup.appendChild(gridLine);tickGroup.appendChild(text);axisGroup.appendChild(tickGroup);}}}
-axisGroup.appendChild(axisPath);parent.appendChild(axisGroup);}
-function lineRenderer(xAccessor,yAccessor,xTransform,yTransform){var line=document.createElementNS("http://www.w3.org/2000/svg","path");xAccessor.reset();yAccessor.reset();if(!xAccessor.hasNext()||!yAccessor.hasNext()){return;}
-var pathString="M "+xTransform(xAccessor.next())+" "+yTransform(yAccessor.next());while(xAccessor.hasNext()&&yAccessor.hasNext()){pathString+=" L "+
-xTransform(xAccessor.next())+
-" "+
-yTransform(yAccessor.next());}
-line.setAttribute("class","series");line.setAttribute("d",pathString);parent.appendChild(line);}
-function pointRenderer(xAccessor,yAccessor,xTransform,yTransform){var pointGroup=document.createElementNS("http://www.w3.org/2000/svg","g");pointGroup.setAttribute("class","data-points");xAccessor.reset();yAccessor.reset();if(!xAccessor.hasNext()||!yAccessor.hasNext()){return;}
-while(xAccessor.hasNext()&&yAccessor.hasNext()){var xDataValue=xAccessor.next();var x=xTransform(xDataValue);var yDataValue=yAccessor.next();var y=yTransform(yDataValue);var circle=document.createElementNS("http://www.w3.org/2000/svg","circle");circle.setAttribute("cx",x);circle.setAttribute("cy",y);circle.setAttribute("r","4");var text=document.createElementNS("http://www.w3.org/2000/svg","text");text.innerHTML=Math.floor(xDataValue)+" / "+Math.floor(yDataValue);text.setAttribute("x",x);text.setAttribute("y",y);text.setAttribute("dx","1em");text.setAttribute("dy","-.7em");pointGroup.appendChild(circle);pointGroup.appendChild(text);}
-parent.appendChild(pointGroup);}
-xTransform=numericTransformer(xAccessor.min(),xAccessor.max(),0+gutter,width-gutter);yTransform=numericTransformer(yAccessor.min(),yAccessor.max(),height-gutter,0+gutter);axisRenderer("x",xTransform.toData);axisRenderer("y",yTransform.toData);lineRenderer(xAccessor,yAccessor,xTransform.toCoord,yTransform.toCoord);pointRenderer(xAccessor,yAccessor,xTransform.toCoord,yTransform.toCoord);}
-function renderGraphSvg(dataArray,renderId){var figure=document.getElementById(renderId);while(figure.hasChildNodes()){figure.removeChild(figure.lastChild);}
+function lineGraph(parent,xAccessor,yAccessor){const width=620;const height=420;const gutter=40;const pixelsPerTick=30;function numericTransformer(dataMin,dataMax,pxMin,pxMax){var dataDiff=dataMax-dataMin,pxDiff=pxMax-pxMin,dataRatio=pxDiff/dataDiff,coordRatio=dataDiff/pxDiff;return{toCoord:function(data){return(data-dataMin)*dataRatio+pxMin;},toData:function(coord){return(coord-pxMin)*coordRatio+dataMin;}};}
+function axisRenderer(orientation,transform){var axisGroup=document.createElementNS("http://www.w3.org/2000/svg","g");var axisPath=document.createElementNS("http://www.w3.org/2000/svg","path");axisGroup.setAttribute("class",orientation+"-axis");var xMin=gutter;var xMax=width-gutter;var yMin=height-gutter;var yMax=gutter;if(orientation==="x"){axisPath.setAttribute("d","M "+xMin+" "+yMin+" L "+xMax+" "+yMin);for(var i=xMin;i<=xMax;i++){if((i-xMin)%pixelsPerTick===0&&i!==xMin){var text=document.createElementNS("http://www.w3.org/2000/svg","text");text.innerHTML=Math.floor(transform(i));text.setAttribute("x",i);text.setAttribute("y",yMin);text.setAttribute("dy","1em");axisGroup.appendChild(text);}}}else{axisPath.setAttribute("d","M "+xMin+" "+yMin+" L "+xMin+" "+yMax);for(var i=yMax;i<=yMin;i++){if((i-yMin)%pixelsPerTick===0&&i!==yMin){var tickGroup=document.createElementNS("http://www.w3.org/2000/svg","g");var gridLine=document.createElementNS("http://www.w3.org/2000/svg","path");text=document.createElementNS("http://www.w3.org/2000/svg","text");text.innerHTML=Math.floor(transform(i));text.setAttribute("x",xMin);text.setAttribute("y",i);text.setAttribute("dx","-.5em");text.setAttribute("dy",".3em");gridLine.setAttribute("d","M "+xMin+" "+i+" L "+xMax+" "+i);tickGroup.appendChild(gridLine);tickGroup.appendChild(text);axisGroup.appendChild(tickGroup);}}}
+axisGroup.appendChild(axisPath);parent.appendChild(axisGroup);}
+function lineRenderer(xAccessor,yAccessor,xTransform,yTransform){var line=document.createElementNS("http://www.w3.org/2000/svg","path");xAccessor.reset();yAccessor.reset();if(!xAccessor.hasNext()||!yAccessor.hasNext()){return;}
+var pathString="M "+xTransform(xAccessor.next())+" "+yTransform(yAccessor.next());while(xAccessor.hasNext()&&yAccessor.hasNext()){pathString+=" L "+
+xTransform(xAccessor.next())+
+" "+
+yTransform(yAccessor.next());}
+line.setAttribute("class","series");line.setAttribute("d",pathString);parent.appendChild(line);}
+function pointRenderer(xAccessor,yAccessor,xTransform,yTransform){var pointGroup=document.createElementNS("http://www.w3.org/2000/svg","g");pointGroup.setAttribute("class","data-points");xAccessor.reset();yAccessor.reset();if(!xAccessor.hasNext()||!yAccessor.hasNext()){return;}
+while(xAccessor.hasNext()&&yAccessor.hasNext()){var xDataValue=xAccessor.next();var x=xTransform(xDataValue);var yDataValue=yAccessor.next();var y=yTransform(yDataValue);var circle=document.createElementNS("http://www.w3.org/2000/svg","circle");circle.setAttribute("cx",x);circle.setAttribute("cy",y);circle.setAttribute("r","4");var text=document.createElementNS("http://www.w3.org/2000/svg","text");text.innerHTML=Math.floor(xDataValue)+" / "+Math.floor(yDataValue);text.setAttribute("x",x);text.setAttribute("y",y);text.setAttribute("dx","1em");text.setAttribute("dy","-.7em");pointGroup.appendChild(circle);pointGroup.appendChild(text);}
+parent.appendChild(pointGroup);}
+xTransform=numericTransformer(xAccessor.min(),xAccessor.max(),0+gutter,width-gutter);yTransform=numericTransformer(yAccessor.min(),yAccessor.max(),height-gutter,0+gutter);axisRenderer("x",xTransform.toData);axisRenderer("y",yTransform.toData);lineRenderer(xAccessor,yAccessor,xTransform.toCoord,yTransform.toCoord);pointRenderer(xAccessor,yAccessor,xTransform.toCoord,yTransform.toCoord);}
+function renderGraphSvg(dataArray,renderId){var figure=document.getElementById(renderId);while(figure.hasChildNodes()){figure.removeChild(figure.lastChild);}
var svg=document.createElementNS("http://www.w3.org/2000/svg","svg");svg.setAttribute("viewBox","0 0 640 440");svg.setAttribute("preserveAspectRatio","xMidYMid meet");lineGraph(svg,(function(data,min,max){var i=0;return{hasNext:function(){return i