Initial commit
This commit is contained in:
385
client/jsFiles/SEAWebClientCommunication.js
Normal file
385
client/jsFiles/SEAWebClientCommunication.js
Normal file
@ -0,0 +1,385 @@
|
||||
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
// % COMMUNICATION
|
||||
|
||||
var timeoutID; // We need this ID to reset the timer every 30 seconds
|
||||
|
||||
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
// Server Sent Event
|
||||
|
||||
|
||||
function buildUpdateConnection() {
|
||||
// Establishes server-sent-event-connection, which is used for all sorts of
|
||||
// updates and exists as long as the client is running.
|
||||
// Executed at programstart (see also SEAWebClientMain.js).
|
||||
|
||||
var path = "http://" + hostPort + "/update";
|
||||
if (debugCommunication) {
|
||||
console.log("%cto server (SSE): " + path,
|
||||
"color:white;background:lightblue");
|
||||
}
|
||||
|
||||
try {
|
||||
var src = new EventSource(path);
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
alertify.prompt(
|
||||
"NETWORK ERROR",
|
||||
"Failed to establish connection to data-server at the given address!"
|
||||
+ "Try to enter HOST and PORT of the data-server manually!",
|
||||
hostPort, function(evt, value) {
|
||||
hostPort = value;
|
||||
buildUpdateConnection();
|
||||
}, function() {
|
||||
})
|
||||
}
|
||||
|
||||
src.onmessage = function(e) {
|
||||
var message = JSON.parse(e.data);
|
||||
if (message) {
|
||||
handleUpdateMessage(src, message);
|
||||
}
|
||||
};
|
||||
|
||||
src.onerror = function(e) {
|
||||
console.log(e);
|
||||
console.log('EVTSRC error')
|
||||
alertify
|
||||
.prompt(
|
||||
"NETWORK ERROR",
|
||||
"Failed to establish connection to data-server at the given address!"
|
||||
+ "Try to enter HOST and PORT of the data-server manually!",
|
||||
hostPort, function(evt, value) {
|
||||
hostPort = value;
|
||||
buildUpdateConnection();
|
||||
}, function() {
|
||||
})
|
||||
src.close();
|
||||
};
|
||||
}
|
||||
|
||||
function handleUpdateMessage(src, message) {
|
||||
// Handles incoming SSE-messages depending on type of message.
|
||||
|
||||
if (debugCommunication > 1) {
|
||||
console.log("%cfrom server (SSE): " + message.type,
|
||||
"color:white;background:lightgray", message);
|
||||
}
|
||||
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
// <---------------------------------------------------------------------------------BUG!!!
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
resetTimer(src);
|
||||
switch (message.type) {
|
||||
// id-message: Confirms establishment of SSE-connection and determines
|
||||
// specific ID of the client
|
||||
case "id":
|
||||
for (var i = 0; i < swiper.length; i++) {
|
||||
swiper[i].removeAllSlides();
|
||||
}
|
||||
clientID = message.id;
|
||||
if ("device" in message) {
|
||||
if (message.device == "_inst_select") {
|
||||
clientTitle = "select instrument";
|
||||
console.log('IDselect')
|
||||
pushInitCommand("getblock?path=_inst_select&", "instrument selection");
|
||||
menuMode = true;
|
||||
sizeChange();
|
||||
} else {
|
||||
clientTitle = message.instrument + " " + message.device;
|
||||
console.log('loadBlocks')
|
||||
loadFirstBlocks();
|
||||
}
|
||||
document.title = "SEA "+clientTitle;
|
||||
} else {
|
||||
document.title = "SEA "+clientTitle + " " + message.title;
|
||||
}
|
||||
var header = document.getElementById("header");
|
||||
header.setAttribute("style", "width: auto;");
|
||||
header.innerHTML = clientTitle;
|
||||
console.log('ID', initCommands);
|
||||
nextInitCommand();
|
||||
break;
|
||||
// console-update-message: Confirms a command.
|
||||
case "command":
|
||||
var histories = document.getElementsByClassName("history");
|
||||
for (var i = 0; i < histories.length; i++) {
|
||||
var line = document.createElement('div');
|
||||
line.innerHTML = htmlEscape(message.line);
|
||||
line.style.color = "cornflowerblue";
|
||||
if (message.origin == "self") {
|
||||
line.style.fontWeight = "bold";
|
||||
}
|
||||
histories[i].appendChild(document.createElement('br'));
|
||||
histories[i].appendChild(line);
|
||||
histories[i].scrollTop = histories[i].scrollHeight;
|
||||
}
|
||||
var cmd = htmlEscape(message.line);
|
||||
if (commandHistory.indexOf(cmd) === -1) {
|
||||
commandHistory.unshift(cmd);
|
||||
}
|
||||
break;
|
||||
// console-update-message: Confirms execution of command.
|
||||
case "reply":
|
||||
var histories = document.getElementsByClassName("history");
|
||||
for (var i = 0; i < histories.length; i++) {
|
||||
var line = document.createElement('div');
|
||||
line.innerHTML = htmlEscape(message.line);
|
||||
line.style.color = "black";
|
||||
if (message.origin == "self") {
|
||||
line.style.fontWeight = "bold";
|
||||
} else if (message.origin == "async") {
|
||||
line.style.color = "green";
|
||||
if (!showAsync) continue;
|
||||
}
|
||||
histories[i].appendChild(line);
|
||||
histories[i].scrollTop = histories[i].scrollHeight;
|
||||
}
|
||||
break;
|
||||
// graph-message: Evokes redraw of graphics.
|
||||
case "graph":
|
||||
console.log("graph");
|
||||
createCharts2(message.graph);
|
||||
break;
|
||||
// redraw.message: Communicates changes requiring reset of a whole group
|
||||
case "redraw": // SHOULD BE TESTED
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
// SPECIAL CASE: is message.title = "main possible? It should evoke
|
||||
// redraw of client
|
||||
|
||||
// special meaning: s < 0: replace slides in all swiper instances
|
||||
reqJSON(-1, "http://" + hostPort + "/getblock?path=" + message.path
|
||||
+ "&id=" + clientID, successHandler, errorHandler);
|
||||
|
||||
break;
|
||||
// graph-update-message:
|
||||
case "graph-update":
|
||||
//if (getUpdatesGraphics) {
|
||||
//timeServer = message.time;
|
||||
console.log("graph-update");
|
||||
updateCharts2(message.graph);
|
||||
//}
|
||||
break;
|
||||
// update-message: Communicates change of values.
|
||||
case "update":
|
||||
if (debugCommunication > 1) {
|
||||
console.log(message);
|
||||
}
|
||||
updateValues(message, src);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function htmlEscape(str) {
|
||||
if (!str) return "";
|
||||
return str.replace(/&/g, '&').replace(/"/g, '"').replace(/'/g,
|
||||
''').replace(/</g, '<').replace(/>/g, '>');
|
||||
}
|
||||
|
||||
function resetTimer(src) {
|
||||
// Executed every time a heartbeat-message is obtained.
|
||||
// If no heartbeat-messages are obtained for a certain amount of time,
|
||||
// an error-message is thrown.
|
||||
|
||||
clearTimeout(timeoutID);
|
||||
timeoutID = setTimeout(function(src) {
|
||||
console.log("timeout");
|
||||
alertify.error("connection lost");
|
||||
if (src) {
|
||||
src.close();
|
||||
}
|
||||
}, 60000);
|
||||
}
|
||||
|
||||
function updateValues(message, src) {
|
||||
// Handles changes of parameter-values
|
||||
|
||||
for (var i = 0; i < message.updates.length; i++) {
|
||||
var component = message.updates[i];
|
||||
var value = component.value;
|
||||
var matches = document.getElementsByName(component.name);
|
||||
for (var j = 0; j < matches.length; j++) {
|
||||
var type = matches[j].getAttribute("__ctype__");
|
||||
if (type == "rdonly") {
|
||||
var text = htmlEscape(value);
|
||||
if (text) {
|
||||
matches[j].innerHTML = text;
|
||||
}
|
||||
} else if (type == "input") {
|
||||
var row = matches[j].parentNode.parentNode.parentNode;
|
||||
row.style.backgroundColor = "white";
|
||||
var oldValue = matches[j].getAttribute("oldValue")
|
||||
|| matches[j].value;
|
||||
if (value != matches[j].value && value != oldValue) {
|
||||
if (matches[j] == document.activeElement
|
||||
|| oldValue != matches[j].value) {
|
||||
row.style.backgroundColor = "orange";
|
||||
} else {
|
||||
matches[j].value = value;
|
||||
}
|
||||
}
|
||||
matches[j].setAttribute("actualValue", value);
|
||||
resizeTextfield(matches[j]);
|
||||
} else if (type == "checkbox") {
|
||||
var row = matches[j].parentNode.parentNode;
|
||||
row.style.backgroundColor = "white";
|
||||
matches[j].checked = value == 1 && value == "1";
|
||||
} else if (type == "enum") {
|
||||
matches[j].style.display = "block";
|
||||
var row = matches[j].parentNode.parentNode;
|
||||
row.style.backgroundColor = "white";
|
||||
matches[j].value = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
// XMLHttpRequest
|
||||
|
||||
function reqJSON(s, url, successHandler, errorHandler) {
|
||||
var xhr = typeof XMLHttpRequest != 'undefined' ? new XMLHttpRequest()
|
||||
: new ActiveXObject('Microsoft.XMLHTTP');
|
||||
if (debugCommunication) {
|
||||
console.log("%cto server (reqJSON): " + url,
|
||||
"color:white;background:lightgreen");
|
||||
}
|
||||
xhr.open('get', url, true);
|
||||
xhr.onreadystatechange = function() {
|
||||
// console.log(xhr)
|
||||
var status;
|
||||
var data;
|
||||
// https://xhr.spec.whatwg.org/#dom-xmlhttprequest-readystate
|
||||
if (xhr.readyState == 4) { // `DONE`
|
||||
status = xhr.status;
|
||||
if (status == 200) {
|
||||
data = JSON.parse(xhr.responseText);
|
||||
successHandler && successHandler(s, data);
|
||||
} else {
|
||||
errorHandler && errorHandler(status);
|
||||
}
|
||||
}
|
||||
};
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
function successHandler(s, message) {
|
||||
// Handles incoming XMLHttp-messages depending on type of message.
|
||||
// s: slide number or -1 for replacing slide in all slider instances
|
||||
if (debugCommunication) {
|
||||
console.log("%cfrom server (reqJSON): " + message.type,
|
||||
"color:white;background:dimgray", message);
|
||||
}
|
||||
switch (message.type) {
|
||||
// Response to a "getblock"-server-request.
|
||||
case "draw":
|
||||
if (debugCommunication) {
|
||||
console.log(message);
|
||||
}
|
||||
if (message.path == "main") {
|
||||
// Happens only initially or at device change.
|
||||
for (var sLocal = 0; sLocal < MAXBLOCK; sLocal++) {
|
||||
insertSlide(sLocal, message.title, "main", createContent(
|
||||
sLocal, message));
|
||||
}
|
||||
} else {
|
||||
if (s < 0) { // redraw: check for slides in all swiper instances
|
||||
for (var isw = 0; isw < MAXBLOCK; isw ++) {
|
||||
var slide = findSlide(isw, message.path);
|
||||
if (slide) {
|
||||
console.log("redraw", isw);
|
||||
replaceSlideContent(slide, message.title,
|
||||
createContent(isw, message));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
insertSlide(s, message.title, message.path, createContent(s,
|
||||
message));
|
||||
}
|
||||
}
|
||||
nextInitCommand();
|
||||
// Request for updates.
|
||||
if (getUpdates) {
|
||||
reqJSON(s, "http://" + hostPort + "/updateblock?path="
|
||||
+ message.path + "&id=" + clientID, successHandler,
|
||||
errorHandler);
|
||||
}
|
||||
break;
|
||||
// Response to a "update-block"-server-request.
|
||||
case "accept-block":
|
||||
break;
|
||||
// Response to a "console"-server-request.
|
||||
case "accept-console":
|
||||
// draw console, only on the first and the last swiper
|
||||
insertSlide(0, "console", "console",
|
||||
createContentConsole(sLocal));
|
||||
insertSlide(3, "console", "console",
|
||||
createContentConsole(sLocal));
|
||||
nextInitCommand();
|
||||
// send empty command in order to trigger getting history
|
||||
reqJSON(0, "http://" + hostPort + "/sendcommand?command=&id=" + clientID, successHandler,
|
||||
errorHandler);
|
||||
break;
|
||||
// Response to a "gettime"-server-request.
|
||||
case "time":
|
||||
timeRange = message.time;
|
||||
/*createGraphics();
|
||||
// By default mostleft swiper-instance shows graphics.
|
||||
swiper[0].slideTo(0);
|
||||
|
||||
// Update time-selection. (see also SEAWebClientGraphics.js)
|
||||
var select = document.getElementsByClassName("select-time")[0];
|
||||
begin = timeRange[0] - timeRange[1];
|
||||
select.value = begin;
|
||||
// Server-request for variable-list.*/
|
||||
reqJSON(0, "http://" + hostPort + "/getvars?time=" + timeRange + "&id="
|
||||
+ clientID, successHandler, errorHandler);
|
||||
break;
|
||||
// Response to a "getvars"-server-request.
|
||||
case "var_list":
|
||||
//blocks = message.blocks;
|
||||
/*var varlist = [];
|
||||
for (var i = 0; i < blocks.length; i++) {
|
||||
for (var j = 0; j < blocks[i].curves.length; j++) {
|
||||
varlist.push(blocks[i].curves[j].name);
|
||||
}
|
||||
}
|
||||
// Update graphics
|
||||
if (varlist.length > 0) {
|
||||
reqJSON(0, "http://" + hostPort + "/graph?time=" + timeRange
|
||||
+ "&variables=" + varlist + "&id=" + clientID,
|
||||
successHandler, errorHandler);
|
||||
} else {
|
||||
nextInitCommand();
|
||||
}*/
|
||||
graphs.receivedVars(message.blocks);
|
||||
nextInitCommand();
|
||||
break;
|
||||
// Response to a "graph"-server-request.
|
||||
case "graph-draw":
|
||||
// obsolete?
|
||||
if (debugCommunication) {
|
||||
console.log("graph-draw", message);
|
||||
}
|
||||
createCharts2(message.graph);
|
||||
nextInitCommand();
|
||||
// Request for updates.
|
||||
reqJSON(s, "http://" + hostPort + "/updategraph?id=" + clientID,
|
||||
successHandler, errorHandler);
|
||||
break;
|
||||
// Response to a "updategraph"-server-request.
|
||||
case "accept-graph":
|
||||
break;
|
||||
case "error":
|
||||
console.log("%cError-Message received!", "color:white;background:red");
|
||||
console.log(message);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function errorHandler(status) {
|
||||
if (debugCommunication) {
|
||||
console.log("error", status);
|
||||
}
|
||||
}
|
67
client/jsFiles/SEAWebClientConsole.js
Normal file
67
client/jsFiles/SEAWebClientConsole.js
Normal file
@ -0,0 +1,67 @@
|
||||
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
// % CONSOLE
|
||||
|
||||
var commandHistory = []; // Stores commands executed by console.
|
||||
|
||||
var histIndex = -1; // Selected element of 'commandHistory'. (-1 = "")
|
||||
|
||||
function createContentConsole(s) {
|
||||
// Creates input-textfield and texarea showing console-history.
|
||||
|
||||
var commandline = document.createElement('input');
|
||||
commandline.setAttribute("type", "text");
|
||||
commandline.setAttribute("class", "row commandline");
|
||||
|
||||
commandline.onkeydown = function (e) {
|
||||
//console.log(histIndex);
|
||||
if (e.which === 38 || e.key == "ArrowUp") {
|
||||
if (histIndex + 1 < commandHistory.length) {
|
||||
histIndex++;
|
||||
this.value = commandHistory[histIndex];
|
||||
}
|
||||
var input = this;
|
||||
window.setTimeout(
|
||||
function () {
|
||||
input.setSelectionRange(input.value.length,
|
||||
input.value.length);
|
||||
}, 0, input);
|
||||
}
|
||||
if (e.which === 40 || e.key == "ArrowDown") {
|
||||
if (histIndex >= 0) {
|
||||
histIndex--;
|
||||
if (histIndex > -1) {
|
||||
this.value = commandHistory[histIndex];
|
||||
} else {
|
||||
this.value = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
commandline.setAttribute("autocomplete", "on");
|
||||
|
||||
var wrapper = document.createElement('form');
|
||||
wrapper.setAttribute("class", "commandline-wrapper");
|
||||
|
||||
wrapper.onsubmit = function (e) {
|
||||
e.preventDefault();
|
||||
histIndex = -1;
|
||||
// Request for command.
|
||||
reqJSON(s, "http://" + hostPort + "/sendcommand?command="
|
||||
+ commandline.value + "&id=" + clientID, successHandler,
|
||||
errorHandler);
|
||||
commandline.value = "";
|
||||
};
|
||||
|
||||
wrapper.setAttribute("method", 'GET');
|
||||
wrapper.appendChild(commandline);
|
||||
|
||||
var history = document.createElement('div');
|
||||
history.setAttribute("class", "history");
|
||||
|
||||
var content = document.createElement('div');
|
||||
content.setAttribute("class", "content-console");
|
||||
content.appendChild(wrapper);
|
||||
content.appendChild(history);
|
||||
return content;
|
||||
}
|
1108
client/jsFiles/SEAWebClientGraph.js
Normal file
1108
client/jsFiles/SEAWebClientGraph.js
Normal file
File diff suppressed because it is too large
Load Diff
31
client/jsFiles/SEAWebClientGraphics.js
Normal file
31
client/jsFiles/SEAWebClientGraphics.js
Normal file
@ -0,0 +1,31 @@
|
||||
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
// % GRAPHICS
|
||||
/*
|
||||
var swiperGraphics = []; // This array contains graphics-swiper-Instances.
|
||||
var begin = -10; // Time to look back (in seconds).
|
||||
var timeServer; // Every time a graph-update-mesage is received the
|
||||
// server-timestamp is stored.
|
||||
var timeRange; // Range of time to regard (unix-time in seconds).
|
||||
var blocks; // array of graphic-blocks sorted by units. (as from var_list, but values added)
|
||||
|
||||
var MARGIN_TOP = 10;
|
||||
var MARGIN_RIGHT = 10;
|
||||
var MARGIN_BOTTOM = 20;
|
||||
var MARGIN_LEFT = 60;
|
||||
|
||||
var width;
|
||||
var height;
|
||||
var margin;
|
||||
|
||||
var scaleX;
|
||||
|
||||
zoomSelection = false;
|
||||
|
||||
|
||||
function createCharts(graph) {
|
||||
createCharts2(graph);
|
||||
return
|
||||
}
|
||||
function updateCharts(graph){
|
||||
updateCharts2(graph)
|
||||
}
|
565
client/jsFiles/SEAWebClientGroup.js
Normal file
565
client/jsFiles/SEAWebClientGroup.js
Normal file
@ -0,0 +1,565 @@
|
||||
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
// % GROUP
|
||||
|
||||
var writePermissionTimeout; // Sets writePermission to 'false, restarts by
|
||||
// user-interaction.
|
||||
|
||||
var prompt = false // True while a prompt is opened.
|
||||
|
||||
function getGroup(s, name) {
|
||||
var found = false;
|
||||
if (name == "") {
|
||||
swiper[s].slideTo(defaultSlidePos(s));
|
||||
return;
|
||||
}
|
||||
for (var i = 0; i < swiper[s].slides.length; i++) {
|
||||
var slideType = swiper[s].slides[i].getAttribute("slide-type");
|
||||
if (slideType == name) {
|
||||
found = true;
|
||||
swiper[s].slideTo(i);
|
||||
}
|
||||
}
|
||||
if (!found && name != "console" && name != "graphics") {
|
||||
// Server-request for group.
|
||||
reqJSON(s, "http://" + hostPort + "/getblock?path=" + name
|
||||
+ "&id=" + clientID, successHandler, errorHandler);
|
||||
}
|
||||
}
|
||||
|
||||
function sendCommand(s, command) {
|
||||
reqJSON(s, "http://" + hostPort + "/sendcommand?command=" + command
|
||||
+ "&id=" + clientID, successHandler, errorHandler);
|
||||
}
|
||||
|
||||
function createContent(s, message) {
|
||||
// Depending on the message received from the server the content of the
|
||||
// group
|
||||
// is created dynamically. Handles draw-message.
|
||||
|
||||
var content = document.createElement('div');
|
||||
content.setAttribute("class", "content");
|
||||
// Process components of the message
|
||||
for (var i = 0; i < message.components.length; i++) {
|
||||
var component = message.components[i];
|
||||
var name = component.name;
|
||||
var type = component.type;
|
||||
var title = name;
|
||||
if ("title" in component)
|
||||
title = component.title;
|
||||
var info = component.info;
|
||||
switch (type) {
|
||||
case "group":
|
||||
content.appendChild(createLink(s, name, title));
|
||||
break;
|
||||
case "rdonly":
|
||||
if ("link" in component) {
|
||||
content.appendChild(createReadOnlyInstrLink(s, name, title,
|
||||
component.link, info));
|
||||
} else {
|
||||
content.appendChild(createReadOnly(s, name, title, info));
|
||||
}
|
||||
break;
|
||||
case "rdlink":
|
||||
content.appendChild(createReadOnlyGroupLink(s, name, title, info));
|
||||
break;
|
||||
case "input":
|
||||
content.appendChild(createInput(s, name, title,
|
||||
info));
|
||||
break;
|
||||
case "checkbox":
|
||||
content.appendChild(createCheckbox(s, name, title,
|
||||
info));
|
||||
break;
|
||||
case "enum":
|
||||
content.appendChild(createSelection(s, name, title,
|
||||
component.enum_names, info));
|
||||
break;
|
||||
case "pushbutton":
|
||||
console.log(component);
|
||||
console.log(component.info);
|
||||
content.appendChild(createPushButton(s, name, title,
|
||||
info));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
function gotoGroups(slideNames) {
|
||||
slideNames = slideNames.split("%20");
|
||||
var l = Math.min(MAXBLOCK,slideNames.length);
|
||||
document.title = "SEA "+ clientTitle + " " + slideNames.join(" ");
|
||||
for (var s=0; s<l; s++) {
|
||||
getGroup(s, slideNames[s]);
|
||||
}
|
||||
}
|
||||
|
||||
function createLink(s, name, title) {
|
||||
// Creates row-element containing link.
|
||||
|
||||
var row = document.createElement('row');
|
||||
row.setAttribute("id", name);
|
||||
row.setAttribute("name", title);
|
||||
row.setAttribute("class", "interactive row link");
|
||||
row.setAttribute("tabindex", 0);
|
||||
|
||||
row.onclick = function () {
|
||||
var slideNames = getSlideNames();
|
||||
slideNames[s] = name;
|
||||
document.title = "SEA "+ clientTitle + " " + slideNames.join(" ");
|
||||
history.pushState({func: "gotoGroups", funarg: slideNames.join("%20")}, document.title, "#" + slideNames.join("%20"));
|
||||
getGroup(s, name);
|
||||
}
|
||||
|
||||
if (title === "console" || title === "device config") {
|
||||
row.setAttribute("class", "interactive row link link-static");
|
||||
row.innerHTML = "console";
|
||||
}
|
||||
row.innerHTML = title;
|
||||
return row;
|
||||
}
|
||||
|
||||
function createReadOnly(s, name, title, info) {
|
||||
// Creates row-element containing read-only-item.
|
||||
|
||||
var left = createTitle(title, info);
|
||||
|
||||
var right = document.createElement('span');
|
||||
right.setAttribute("class", "col-right");
|
||||
right.setAttribute("name", name);
|
||||
right.setAttribute("__ctype__", "rdonly");
|
||||
|
||||
return appendToContent(info, left, right);
|
||||
}
|
||||
|
||||
function createReadOnlyGroupLink(s, name, title, info) {
|
||||
// Creates row-element containing link AND read-only-item.
|
||||
// for secop
|
||||
|
||||
var left = createTitle(title, info);
|
||||
|
||||
left.setAttribute("id", name);
|
||||
left.setAttribute("name", title);
|
||||
left.setAttribute("class", "interactive link");
|
||||
|
||||
left.onclick = function () {
|
||||
getGroup(s, title);
|
||||
}
|
||||
|
||||
var right = document.createElement('span');
|
||||
right.setAttribute("class", "col-right");
|
||||
right.setAttribute("name", name);
|
||||
right.setAttribute("__ctype__", "rdonly");
|
||||
|
||||
return appendToContent(info, left, right);
|
||||
}
|
||||
|
||||
function createReadOnlyInstrLink(s, name, title, link, info) {
|
||||
// Creates row-element containing link AND read-only-item.
|
||||
|
||||
// var left = createTitle(title, info);
|
||||
var left = document.createElement('a');
|
||||
left.setAttribute("class", "col-left");
|
||||
left.innerHTML = title;
|
||||
|
||||
left.setAttribute("id", name);
|
||||
left.setAttribute("name", title);
|
||||
left.setAttribute("class", "interactive link");
|
||||
|
||||
var right = document.createElement('span');
|
||||
right.setAttribute("class", "col-right");
|
||||
right.setAttribute("name", name);
|
||||
right.setAttribute("__ctype__", "rdonly");
|
||||
|
||||
row = appendToContent(info, left, right);
|
||||
row.onclick = function () {
|
||||
this.style.backgroundColor = "orangered";
|
||||
left.click();
|
||||
}
|
||||
if (link.charAt(0) == ':') {
|
||||
left.href = "http://" + location.hostname + link + "/";
|
||||
} else {
|
||||
left.href = link;
|
||||
}
|
||||
|
||||
row.setAttribute("class", "row clickable");
|
||||
return row;
|
||||
}
|
||||
|
||||
function createPushButton(s, name, title, info) {
|
||||
// Creates row-element containing a push button
|
||||
|
||||
var left = createTitle(title, info);
|
||||
console.log(info);
|
||||
|
||||
left.setAttribute("id", name);
|
||||
left.setAttribute("name", title);
|
||||
|
||||
var right = document.createElement('span');
|
||||
right.setAttribute("class", "col-right clickable push-button");
|
||||
right.setAttribute("name", name);
|
||||
right.setAttribute("__ctype__", "rdonly");
|
||||
|
||||
row = appendToContent(info, left, right);
|
||||
right.onclick = function () {
|
||||
if (writePermission) {
|
||||
var row = left.parentNode;
|
||||
right.style.backgroundColor = "orangered";
|
||||
// Request for command
|
||||
sendCommand(s, name);
|
||||
} else {
|
||||
prompt = true;
|
||||
alertify.confirm("", "You are connected with <b>" + clientTitle
|
||||
+ "</b>. <br>"
|
||||
+ "Are you sure you want to modify things here?",
|
||||
function () {
|
||||
// User decided to proceed.
|
||||
writePermission = true;
|
||||
writePermissionTimeout = setTimeout(function () {
|
||||
writePermission = false;
|
||||
}, 3600000);
|
||||
var row = left.parentNode;
|
||||
row.style.backgroundColor = "orangered";
|
||||
// Request for command
|
||||
sendCommand(s, name);
|
||||
prompt = false;
|
||||
}, function () {
|
||||
// User decided to cancel
|
||||
prompt = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
row.setAttribute("class", "row");
|
||||
return row;
|
||||
}
|
||||
|
||||
function createInput(s, name, title, info) {
|
||||
// Creates row-element containing input-item.
|
||||
|
||||
if (info) {
|
||||
var infoBox = createInfo(title, info);
|
||||
}
|
||||
var left = createTitle(title, info);
|
||||
|
||||
var input = document.createElement('input');
|
||||
input.setAttribute("type", "text");
|
||||
input.setAttribute("class", "input-text");
|
||||
input.setAttribute("name", name);
|
||||
input.setAttribute("__ctype__", "input");
|
||||
input.style.width = "100px";
|
||||
|
||||
input.onkeydown = function (e) {
|
||||
if (e.which === 27 || e.key == "Escape") {
|
||||
// User decided to cancel
|
||||
input.value = input.getAttribute("oldValue");
|
||||
resizeTextfield(input);
|
||||
var row = left.parentNode;
|
||||
row.style.backgroundColor = "white";
|
||||
}
|
||||
}
|
||||
|
||||
input.onfocus = function () {
|
||||
input.setAttribute("oldValue", input.value);
|
||||
|
||||
if (isTouchDevice())
|
||||
setTimeout(function () {
|
||||
posTextfield(s, left);
|
||||
}, 1);
|
||||
}
|
||||
|
||||
input.onblur = function () {
|
||||
if (prompt) {
|
||||
return false;
|
||||
}
|
||||
var row = left.parentNode;
|
||||
var value = input.value;
|
||||
var oldValue = input.getAttribute("oldValue") || value;
|
||||
if (!input.hasAttribute("actualValue")) {
|
||||
input.setAttribute("actualValue", oldValue);
|
||||
}
|
||||
var actualValue = input.getAttribute("actualValue");
|
||||
if (value === actualValue || value === oldValue) {
|
||||
input.value = actualValue;
|
||||
// nothing to do.
|
||||
row.style.backgroundColor = "white";
|
||||
return false;
|
||||
}
|
||||
// User changed value and moved focus to other object.
|
||||
alertify.confirm("", "You changed a field without pressing the return key.<br>"
|
||||
+ "Hint: press ESC for leaving a field unchanged.<b>"
|
||||
+ "You are connected with <b>" + clientTitle + "</b>.<br>"
|
||||
+ "Are you sure you want to change the value of<br><b>"
|
||||
+ name + "</b> from <b>" + actualValue
|
||||
+ "</b> to <b>" + value + "</b>?", function () {
|
||||
// User decided to proceed.
|
||||
writePermission = true;
|
||||
writePermissionTimeout = setTimeout(function () {
|
||||
writePermission = false;
|
||||
}, 3600000);
|
||||
row.style.backgroundColor = "orangered";
|
||||
// Request for command
|
||||
sendCommand(s, name + " " + value);
|
||||
resizeTextfield(input);
|
||||
prompt = false;
|
||||
}, function () {
|
||||
// User decided to cancel
|
||||
input.value = input.getAttribute("actualValue");
|
||||
resizeTextfield(input);
|
||||
row.style.backgroundColor = "white";
|
||||
prompt = false;
|
||||
});
|
||||
}
|
||||
|
||||
var form = document.createElement('form');
|
||||
form.onsubmit = function (e) {
|
||||
e.preventDefault();
|
||||
// remove following check: sometimes we want to send a command even with an unchanged value
|
||||
//if (input.value === input.getAttribute("oldValue")) {
|
||||
// // nothing to do.
|
||||
// return false;
|
||||
//}
|
||||
if (writePermission) {
|
||||
var row = left.parentNode;
|
||||
row.style.backgroundColor = "orangered";
|
||||
// Request for command
|
||||
sendCommand(s, name + " " + input.value);
|
||||
} else {
|
||||
var value = input.value
|
||||
prompt = true;
|
||||
alertify.confirm("", "You are connected with <b>" + clientTitle
|
||||
+ "</b>. <br>"
|
||||
+ "Are you sure you want to modify things here?",
|
||||
function () {
|
||||
// User decided to proceed.
|
||||
writePermission = true;
|
||||
writePermissionTimeout = setTimeout(function () {
|
||||
writePermission = false;
|
||||
}, 3600000);
|
||||
var row = left.parentNode;
|
||||
row.style.backgroundColor = "orangered";
|
||||
// Request for command
|
||||
sendCommand(s, name + " " + value);
|
||||
resizeTextfield(input);
|
||||
prompt = false;
|
||||
}, function () {
|
||||
// User decided to cancel
|
||||
input.value = input.getAttribute("oldValue");
|
||||
resizeTextfield(input);
|
||||
prompt = false;
|
||||
});
|
||||
}
|
||||
};
|
||||
form.appendChild(input);
|
||||
|
||||
var right = document.createElement('span');
|
||||
right.setAttribute("class", "col-right");
|
||||
right.appendChild(form);
|
||||
return appendToContent(info, left, right);
|
||||
}
|
||||
|
||||
function posTextfield(s, left) {
|
||||
var content = swiper[s].slides[swiper[s].activeIndex].childNodes[1];
|
||||
var row = left.parentNode;
|
||||
content.scrollTop = row.offsetTop - 30;
|
||||
}
|
||||
|
||||
function resizeTextfield(input) {
|
||||
if (input.value.length > input.size * 12 / 20) {
|
||||
var str0 = window.getComputedStyle(input).fontSize;
|
||||
var str1 = str0.substring(0, str0.length - 2);
|
||||
if (input.value.length < 43) {
|
||||
input.style.width = input.value.length * str1 * 12 / 20 + "px";
|
||||
}
|
||||
} else {
|
||||
input.style.width = "100px";
|
||||
}
|
||||
}
|
||||
|
||||
function createCheckbox(s, name, title, info) {
|
||||
// Creates row-element containing checkbox-item
|
||||
|
||||
var left = createTitle(title, info);
|
||||
|
||||
var input = document.createElement('input');
|
||||
input.setAttribute("type", "checkbox");
|
||||
input.setAttribute("name", name);
|
||||
input.setAttribute("__ctype__", "checkbox");
|
||||
input.setAttribute("class", "parameter-checkbox");
|
||||
|
||||
input.onkeyup = function (e) {
|
||||
if (e.keyCode === 32) {
|
||||
handleCheckbox();
|
||||
}
|
||||
}
|
||||
|
||||
var label = document.createElement('label');
|
||||
label.setAttribute("for", input);
|
||||
label.setAttribute("class", "parameter-label");
|
||||
|
||||
label.onclick = function () {
|
||||
handleCheckbox();
|
||||
}
|
||||
|
||||
function handleCheckbox() {
|
||||
if (writePermission) {
|
||||
var row = left.parentNode;
|
||||
row.style.backgroundColor = "orangered";
|
||||
if (input.checked) {
|
||||
var value = "0";
|
||||
input.checked = false;
|
||||
} else {
|
||||
var value = "1";
|
||||
input.checked = true;
|
||||
}
|
||||
// Request for command
|
||||
sendCommand(s, name + " " + value);
|
||||
} else {
|
||||
alertify.confirm("", "You are connected with <b>" + clientTitle
|
||||
+ "</b>. <br>"
|
||||
+ "Are you sure you want to modify things here?",
|
||||
function () {
|
||||
// User decided to proceed.
|
||||
writePermission = true;
|
||||
writePermissionTimeout = setTimeout(function () {
|
||||
writePermission = false;
|
||||
}, 3600000);
|
||||
var row = left.parentNode;
|
||||
row.style.backgroundColor = "orangered";
|
||||
if (input.checked) {
|
||||
var value = "0";
|
||||
input.checked = false;
|
||||
} else {
|
||||
var value = "1";
|
||||
input.checked = true;
|
||||
}
|
||||
// Request for command
|
||||
sendCommand(s, name + " " + value);
|
||||
}, function () {
|
||||
// User decided to cancel
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var right = document.createElement('span');
|
||||
right.setAttribute("class", "col-right");
|
||||
right.appendChild(input);
|
||||
right.appendChild(label);
|
||||
return appendToContent(info, left, right);
|
||||
}
|
||||
|
||||
function createSelection(s, name, title, buttons, info) {
|
||||
// Creates row-element containing dropdown-selection.
|
||||
|
||||
var left = createTitle(title, info);
|
||||
|
||||
var select = document.createElement('select');
|
||||
select.setAttribute("name", name);
|
||||
select.setAttribute("__ctype__", "enum");
|
||||
select.setAttribute("class", "select-params");
|
||||
|
||||
select.onfocus = function () {
|
||||
select.setAttribute("oldIndex", select.selectedIndex);
|
||||
}
|
||||
|
||||
select.oninput = function () {
|
||||
if (writePermission && title != "device config") {
|
||||
var row = left.parentNode;
|
||||
row.style.backgroundColor = "orangered";
|
||||
// Request for command
|
||||
sendCommand(s, name + " " + this.value);
|
||||
} else {
|
||||
alertify.confirm("", "You are connected with <b>" + clientTitle
|
||||
+ "</b>. <br>"
|
||||
+ "Are you sure you want to modify things here?",
|
||||
function () {
|
||||
// User decided to proceed.
|
||||
writePermission = true;
|
||||
writePermissionTimeout = setTimeout(function () {
|
||||
writePermission = false;
|
||||
}, 3600000);
|
||||
var row = left.parentNode;
|
||||
row.style.backgroundColor = "orangered";
|
||||
// Request for command
|
||||
sendCommand(s, name + " " + select.value);
|
||||
}, function () {
|
||||
// User decided to cancel
|
||||
select.value = select.options[select
|
||||
.getAttribute("oldIndex")].value;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
for (var i = 0; i < buttons.length; i++) {
|
||||
var option = document.createElement('option');
|
||||
option.setAttribute("type", "enum");
|
||||
option.setAttribute("class", "option-params");
|
||||
option.setAttribute("value", buttons[i].value);
|
||||
option.appendChild(document.createTextNode(buttons[i].title));
|
||||
select.add(option);
|
||||
}
|
||||
select.style.display = "none";
|
||||
|
||||
var right = document.createElement('span');
|
||||
right.setAttribute("class", "col-right");
|
||||
right.appendChild(select);
|
||||
return appendToContent(info, left, right);
|
||||
}
|
||||
|
||||
function createTitle(title, info) {
|
||||
// Creates left side of row-tag containing title. Title may hold additional
|
||||
// information, which is shown, when title-tag is clicked.
|
||||
|
||||
var left = document.createElement('span');
|
||||
if (info) {
|
||||
left.setAttribute("class", "col-left event-toggle-info");
|
||||
|
||||
left.onclick = function () {
|
||||
var infoBox = left.parentNode.childNodes[0];
|
||||
if (infoBox.style.display == "none") {
|
||||
infoBox.style.display = "block";
|
||||
} else {
|
||||
infoBox.style.display = "none";
|
||||
}
|
||||
}
|
||||
|
||||
left.innerHTML = title + "<sup><b>(i)</b></sup>";
|
||||
} else {
|
||||
left.setAttribute("class", "col-left");
|
||||
left.innerHTML = title;
|
||||
}
|
||||
return left;
|
||||
}
|
||||
|
||||
function createInfo(info) {
|
||||
// Creates info-box, which isn't visible by default but can be displayed.
|
||||
|
||||
var infoBox = document.createElement('div');
|
||||
infoBox.setAttribute("class", "info-box");
|
||||
|
||||
infoBox.onclick = function () {
|
||||
infoBox.style.display = "none";
|
||||
}
|
||||
|
||||
infoBox.innerHTML = info;
|
||||
return infoBox;
|
||||
}
|
||||
|
||||
function appendToContent(info, left, right) {
|
||||
// Cretees row-tag containing infoBox (not visible by default), left side
|
||||
// (span)
|
||||
// and right side (span).
|
||||
|
||||
var row = document.createElement('div');
|
||||
row.setAttribute("class", "row");
|
||||
if (info) {
|
||||
row.appendChild(createInfo(info));
|
||||
}
|
||||
for (var i = 1; i < arguments.length; i++)
|
||||
if (arguments[i]) {
|
||||
row.appendChild(arguments[i]);
|
||||
}
|
||||
return row;
|
||||
}
|
198
client/jsFiles/SEAWebClientMain.js
Normal file
198
client/jsFiles/SEAWebClientMain.js
Normal file
@ -0,0 +1,198 @@
|
||||
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
// % INIT
|
||||
|
||||
var MAXBLOCK = 4; // max number of blocks
|
||||
|
||||
var elements = []; // grid elements
|
||||
|
||||
var swiper = []; // This array contains main-swiper-Instances.
|
||||
|
||||
var hostPort = ""; // Address and port of static html-file.
|
||||
|
||||
var clientID = ""; // ID given by server when SSE-connection is established.
|
||||
|
||||
var clientTitle = ""; // Contains name of instrument and device.
|
||||
|
||||
var getUpdates = true;
|
||||
|
||||
var getUpdatesGraphics = true;
|
||||
|
||||
var initCommands = [];
|
||||
|
||||
var loadingShown = true;
|
||||
|
||||
var writePermission = false;
|
||||
|
||||
var menuMode = false;
|
||||
|
||||
var panelOn = true;
|
||||
|
||||
var firstState = 0;
|
||||
|
||||
function Settings() {
|
||||
// get key/value pairs from search part of the URL and fill into query
|
||||
var qstr = location.search;
|
||||
console.log(qstr);
|
||||
if (qstr) {
|
||||
var a = (qstr[0] === '?' ? qstr.substr(1) : qstr).split('&');
|
||||
for (var i = 0; i < a.length; i++) {
|
||||
var b = a[i].split('=');
|
||||
key = decodeURIComponent(b[0]);
|
||||
value = decodeURIComponent(b.slice(1).join("=").replace(/\+/g, '%20'));
|
||||
this[key] = value;
|
||||
}
|
||||
}
|
||||
this.treat = function (variable, shortcut, convert, defaultValue) {
|
||||
// the third argument should be:
|
||||
// None or omitted for a string
|
||||
// to_bool for converting to boolean
|
||||
// Number for converting to a number
|
||||
if (shortcut in this) {
|
||||
value = this[shortcut];
|
||||
if (convert) {
|
||||
value = convert(value);
|
||||
}
|
||||
} else {
|
||||
value = defaultValue;
|
||||
}
|
||||
//console.log(variable, value);
|
||||
window[variable] = value;
|
||||
return this;
|
||||
}
|
||||
this.add_init = function (shortcut, command, defaultValue) {
|
||||
if (shortcut in this) {
|
||||
value = to_bool(this[shortcut]);
|
||||
console.log(shortcut, value);
|
||||
} else {
|
||||
value = defaultValue;
|
||||
console.log(shortcut, value);
|
||||
}
|
||||
if (value) {
|
||||
initCommands.push(command);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
function to_bool(string) {
|
||||
// everything else than false, 0 or an empty string is considered as true
|
||||
return !/^(false|FALSE|False|0|)$/.test(string);
|
||||
}
|
||||
|
||||
// example: localhost:5000/SEAWebClient.html?hp=ldmzolliker:5000&dc=1
|
||||
// hostPort given and debugCommunication switched on
|
||||
new Settings()
|
||||
.treat("debugCommunication", "dc", 0, 0) // 1: debug synchronous comm. 2: debug syn and asyn comm
|
||||
.treat("debugGraphics", "dg", to_bool, false)
|
||||
.treat("hostPort", "hp", 0, location.hostname + ":" + location.port)
|
||||
.treat("showMain", "sm", to_bool, true)
|
||||
.treat("showConsole", "sc", to_bool, true)
|
||||
.treat("showOverview", "so", to_bool, true)
|
||||
.treat("showGraphics", "sg", to_bool, true)
|
||||
.treat("showAsync", "sa", to_bool, false)
|
||||
|
||||
function loadFirstBlocks() {
|
||||
|
||||
if (showMain) pushInitCommand("getblock?path=main&", "main")
|
||||
if (showConsole) pushInitCommand("console?", "console")
|
||||
if (nColumns == 1) { // probably mobile phone}
|
||||
if (showGraphics) pushInitCommand("gettime?time=-1800,0&", "graphics")
|
||||
if (showOverview) pushInitCommand("getblock?path=_overview&", "overview")
|
||||
} else {
|
||||
if (showOverview) pushInitCommand("getblock?path=_overview&", "overview")
|
||||
if (showGraphics) pushInitCommand("gettime?time=-1800,0&", "graphics")
|
||||
// last is shown first
|
||||
}
|
||||
}
|
||||
|
||||
function nextInitCommand() {
|
||||
// do the next init request
|
||||
if (initCommands.length > 0) {
|
||||
next = initCommands.shift();
|
||||
cmd = next[0]
|
||||
text = next[1]
|
||||
var loadingSpan = document.getElementsByClassName("loading-span")[0];
|
||||
loadingSpan.innerHTML = loadingSpan.innerHTML + "<br>loading " + htmlEscape(text) + " ...";
|
||||
reqJSON(0, "http://" + hostPort + "/" + cmd + "id=" + clientID, successHandler, errorHandler);
|
||||
} else if (loadingShown) {
|
||||
var loadingScreen = document.getElementsByClassName("loading-div")[0];
|
||||
loadingScreen.style.display = "none";
|
||||
loadingShown = false;
|
||||
if (location.hash) { // there was a #hash part
|
||||
var slideNames = location.hash.substr(1);
|
||||
gotoGroups(slideNames);
|
||||
}
|
||||
console.log("loading finished");
|
||||
}
|
||||
}
|
||||
|
||||
function pushInitCommand(cmd, text) {
|
||||
initCommands.push([cmd, text]);
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
// Executed when loading of page is completed.
|
||||
|
||||
// Create grid-elements. (see also at
|
||||
// 'SEAWebClientResponsivity.js')
|
||||
elements = createGrid();
|
||||
// Number of shown columns 'm' and rows 'n' is determined depending on
|
||||
// available viewport-size.
|
||||
determineViewportSize();
|
||||
// Determine size of grid-elements depending on number of columns 'm' and
|
||||
// rows 'n'
|
||||
adjustGrid();
|
||||
// Create swiper-instances.
|
||||
for (var s = 0; s < MAXBLOCK; s++) {
|
||||
swiper[s] = insertSwiper(s);
|
||||
}
|
||||
var homeButton = document.getElementById("home-icon");
|
||||
homeButton.onclick = function () {
|
||||
window.location = "http://" + location.hostname + ":8800/";
|
||||
};
|
||||
buildUpdateConnection();
|
||||
if (location.hash) {
|
||||
console.log("hash in url", location.hash);
|
||||
initSlides = location.hash.substring(1);
|
||||
} else {
|
||||
initSlides = "";
|
||||
}
|
||||
// Initialisation will be continued, when SSE-connection is established
|
||||
// and id-message is obtained.
|
||||
// (see also at SEAWebClientCommunication.js)
|
||||
addEventListener("popstate", function (e) {
|
||||
if (e.state) {
|
||||
if (loadingShown) {
|
||||
if (initSlides != e.state.funarg) {
|
||||
console.log("hash mismatch", initSlides, e.state.funarg);
|
||||
initSlides = e.state.funarg;
|
||||
}
|
||||
} else {
|
||||
console.log("popstate", e.state.func, e.state.funarg);
|
||||
window[e.state.func](e.state.funarg);
|
||||
}
|
||||
} else {
|
||||
document.title = "SEA "+ clientTitle;
|
||||
for (var s=0; s<MAXBLOCK; s++) {
|
||||
swiper[s].slideTo(defaultSlidePos(s));
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
function toggleHeader() {
|
||||
// Show and hide box showing name of the current device ('see also
|
||||
// SEAWebClient.html')
|
||||
|
||||
var main_panel = document.getElementById("main-panel");
|
||||
panelOn = !panelOn;
|
||||
if (panelOn) {
|
||||
header.innerHTML = clientTitle
|
||||
/* header.setAttribute("style", "width: auto;"); */
|
||||
main_panel.setAttribute("style", "display: block;");
|
||||
} else {
|
||||
/* header.setAttribute("style", "width: 30px;"); */
|
||||
main_panel.setAttribute("style", "display: none;");
|
||||
}
|
||||
return true;
|
||||
}
|
151
client/jsFiles/SEAWebClientResponsivity.js
Normal file
151
client/jsFiles/SEAWebClientResponsivity.js
Normal file
@ -0,0 +1,151 @@
|
||||
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
// % RESPONSIVITY
|
||||
|
||||
var nColumns = 1; // Viewport is subdivided in nColumns columns.
|
||||
|
||||
var nRows = 1; // Viewport is subdivided in nRows rows.
|
||||
|
||||
var gridCountGraphics = 2; // Number of displayed graphics-swipers.
|
||||
|
||||
var MINWIDTH = 400; // Minimal width of block.
|
||||
|
||||
var MINHEIGHT = 700; // Minimal height of block.
|
||||
|
||||
function createGrid() {
|
||||
// Creates grid-elements. By default only the first one is shown
|
||||
// and
|
||||
// takes the whole viewport.
|
||||
var elements = [];
|
||||
for (var i = 0; i < 4; i++) {
|
||||
var element = document.createElement('div');
|
||||
element.setAttribute("class", "grid-element");
|
||||
document.getElementById("center").appendChild(element);
|
||||
elements.push(element);
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
|
||||
function determineViewportSize() {
|
||||
// Number of columns 'nColumns' and rows 'nRows' is determined depending on available
|
||||
// viewport-size.
|
||||
|
||||
var width = window.innerWidth || document.documentElement.clientWidth
|
||||
|| document.body.clientWidth;
|
||||
var height = window.innerHeight || document.documentElement.clientHeight
|
||||
|| document.body.clientHeight;
|
||||
nColumns = 1;
|
||||
if (width > MINWIDTH * 1.8) {
|
||||
nColumns = 2;
|
||||
}
|
||||
if (width > MINWIDTH * 2.5) {
|
||||
nColumns = 3;
|
||||
}
|
||||
if (width > MINWIDTH * 3.5) {
|
||||
nColumns = 4;
|
||||
}
|
||||
nRows = 1;
|
||||
if (height > MINHEIGHT) {
|
||||
nRows = 2;
|
||||
}
|
||||
if (menuMode) {
|
||||
nRows = 1;
|
||||
nColumns = 1;
|
||||
}
|
||||
}
|
||||
|
||||
function sizeChange() {
|
||||
determineViewportSize();
|
||||
adjustGrid();
|
||||
}
|
||||
|
||||
function adjustGrid() {
|
||||
// Determines size of grid-elements depending on number of columns 'nColumns' and
|
||||
// rows 'nRows'
|
||||
|
||||
var width = window.innerWidth || document.documentElement.clientWidth
|
||||
|| document.body.clientWidth;
|
||||
var height = window.innerHeight || document.documentElement.clientHeight
|
||||
|| document.body.clientHeight;
|
||||
|
||||
switch (nColumns) {
|
||||
case 1:
|
||||
if (menuMode) {
|
||||
leftWidth = Math.min(100, MINWIDTH / width * 100);
|
||||
style(0,leftWidth + "vw","100vh");
|
||||
style(1); // hide
|
||||
style(2); // hide
|
||||
style(3); // hide
|
||||
} else {
|
||||
style(0,"100vw","100vh");
|
||||
style(1); // hide
|
||||
style(2); // hide
|
||||
style(3); // hide
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
rightWidth = Math.min(50, MINWIDTH / width * 100);
|
||||
leftWidth = 100 - rightWidth;
|
||||
if (nRows == 1) {
|
||||
style(0,leftWidth + "vw","100vh");
|
||||
style(1,rightWidth + "vw","100vh");
|
||||
style(2); // hide
|
||||
style(3); // hide
|
||||
} else {
|
||||
style(0,leftWidth + "vw","100vh");
|
||||
style(1,rightWidth + "vw","50vh");
|
||||
style(2); // hide
|
||||
style(3,rightWidth + "vw","50vh");
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
rightWidth = MINWIDTH / width * 100;
|
||||
leftWidth = 100 - rightWidth;
|
||||
if (nRows == 1) {
|
||||
style(0,leftWidth + "vw","100vh");
|
||||
style(1,rightWidth + "vw","100vh");
|
||||
style(2); // hide
|
||||
style(3); // hide
|
||||
} else {
|
||||
style(0,leftWidth + "vw","100vh");
|
||||
style(1,rightWidth + "vw","50vh");
|
||||
style(2); // hide
|
||||
style(3,rightWidth + "vw","50vh");
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
rightWidth = MINWIDTH / width * 100;
|
||||
leftWidth = 100 - 2 * rightWidth;
|
||||
if (nRows == 1) {
|
||||
style(0,leftWidth + "vw","100vh");
|
||||
style(1,rightWidth + "vw","100vh");
|
||||
style(2); // hide
|
||||
style(3,rightWidth + "vw","100vh");
|
||||
} else {
|
||||
style(0,leftWidth + "vw","100vh");
|
||||
style(1,rightWidth + "vw","50vh");
|
||||
style(2,rightWidth + "vw","50vh");
|
||||
style(3,(2 * rightWidth) + "vw","50vh");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function style(s, width, height) {
|
||||
if (width) {
|
||||
elements[s].style.display = "inline-block";
|
||||
elements[s].style.width = width;
|
||||
} else {
|
||||
elements[s].style.display = "none";
|
||||
}
|
||||
if (height) {
|
||||
elements[s].style.height = height;
|
||||
}
|
||||
elements[s].style.float = "left";
|
||||
}
|
||||
|
||||
function isTouchDevice() {
|
||||
return !!('ontouchstart' in window)
|
||||
|| !!('msmaxtouchpoints' in window.navigator);
|
||||
};
|
42
client/jsFiles/SEAWebClientStart.js
Normal file
42
client/jsFiles/SEAWebClientStart.js
Normal file
@ -0,0 +1,42 @@
|
||||
var showSettings = false;
|
||||
|
||||
function toggleSettings() {
|
||||
// Shows and hides settings.
|
||||
|
||||
console.log("toggle settings");
|
||||
if (showSettings) {
|
||||
document.getElementsByClassName("start-settings-checkboxes")[0].style.display = "none";
|
||||
document.getElementsByClassName("start-settings-show-hide")[0].innerHTML = "show";
|
||||
showSettings = false;
|
||||
} else {
|
||||
document.getElementsByClassName("start-settings-checkboxes")[0].style.display = "inline";
|
||||
document.getElementsByClassName("start-settings-show-hide")[0].innerHTML = "hide";
|
||||
showSettings = true;
|
||||
}
|
||||
}
|
||||
|
||||
function followLink(destination) {
|
||||
// Build query string and load new page.
|
||||
|
||||
var checkboxes = document.getElementsByClassName("start-checkbox");
|
||||
var query = "";
|
||||
// Loop through settings-checkboxes.
|
||||
for (var i = 0; i < checkboxes.length; i++) {
|
||||
if (checkboxes[i].checked != checkboxes[i].defaultChecked) {
|
||||
if (query === "") {
|
||||
query = "?";
|
||||
} else {
|
||||
query += "&";
|
||||
}
|
||||
query += checkboxes[i].name + "=";
|
||||
if (checkboxes[i].checked) {
|
||||
query += "1";
|
||||
} else {
|
||||
query += "0";
|
||||
}
|
||||
}
|
||||
}
|
||||
destination += query;
|
||||
console.log(destination);
|
||||
window.location = destination;
|
||||
}
|
174
client/jsFiles/SEAWebClientSwiper.js
Normal file
174
client/jsFiles/SEAWebClientSwiper.js
Normal file
@ -0,0 +1,174 @@
|
||||
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
// % SWIPER
|
||||
|
||||
function insertSwiper(s) {
|
||||
// Create an empty swiper-instance and append the swiper-container to
|
||||
// 'grid-element' s.
|
||||
|
||||
var container = document.createElement('div');
|
||||
container.setAttribute("class", "swiper-container swiper-container-main");
|
||||
elements[s].appendChild(container);
|
||||
|
||||
var swiperwrapper = document.createElement('div');
|
||||
swiperwrapper.setAttribute("class", "swiper-wrapper swiper-wrapper-main");
|
||||
swiperwrapper.setAttribute("s", s);
|
||||
container.appendChild(swiperwrapper);
|
||||
|
||||
var paginationWrapper = document.createElement('div');
|
||||
paginationWrapper.setAttribute("class", "swiper-pagination");
|
||||
container.appendChild(paginationWrapper);
|
||||
|
||||
var buttonPrev = document.createElement("div");
|
||||
buttonPrev.setAttribute("class", "swiper-button-prev swiper-button-black");
|
||||
|
||||
var buttonNext = document.createElement("div");
|
||||
buttonNext.setAttribute("class", "swiper-button-next swiper-button-black");
|
||||
|
||||
var swiper = new Swiper(container, {
|
||||
direction : 'horizontal',
|
||||
pagination: {
|
||||
el: paginationWrapper,
|
||||
clickable: true
|
||||
},
|
||||
spaceBetween : 0,
|
||||
navigation:{
|
||||
prevEl: buttonPrev,
|
||||
nextEl: buttonNext
|
||||
}
|
||||
});
|
||||
//console.log(swiper);
|
||||
|
||||
|
||||
if (!isTouchDevice()) {
|
||||
// Add swiper-button.
|
||||
swiper.params.noSwipingClass = "swiper-slide-main";
|
||||
container.appendChild(buttonPrev);
|
||||
container.appendChild(buttonNext);
|
||||
}
|
||||
|
||||
return swiper;
|
||||
}
|
||||
|
||||
function findSlide(s, type) {
|
||||
var i;
|
||||
for (i = 0; i < swiper[s].slides.length; i++) {
|
||||
if (swiper[s].slides[i].getAttribute("slide-type") === type) {
|
||||
return swiper[s].slides[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function replaceSlideContent(slide, title, content) {
|
||||
titlewrapper = slide.childNodes[0].childNodes[0];
|
||||
titlewrapper.innerHTML = title;
|
||||
slide.replaceChild(content, slide.childNodes[1])
|
||||
}
|
||||
|
||||
function insertSlide(s, title, type, content) {
|
||||
// Inserts new group to instance s of Swiper.
|
||||
|
||||
var slide = findSlide(s, type);
|
||||
if (slide) { // slide already exists
|
||||
replaceSlideContent(slide, title, content);
|
||||
return
|
||||
}
|
||||
var panel = document.createElement('div');
|
||||
panel.setAttribute("class", "panel");
|
||||
|
||||
titlewrapper = document.createElement('span');
|
||||
titlewrapper.innerHTML = title;
|
||||
panel.appendChild(titlewrapper);
|
||||
if (type == "_overview" || type == "main") {
|
||||
//panel.appendChild(createHomeButton(s));
|
||||
} else if (type != "graphics" && type != "_inst_select" && type != "console") {
|
||||
panel.appendChild(createCloseButton(s));
|
||||
}
|
||||
|
||||
/*if (type === "graphics") {
|
||||
panel.appendChild(createUpdateButton(s));
|
||||
}*/
|
||||
|
||||
slide = document.createElement('div');
|
||||
slide.setAttribute("class", "swiper-slide swiper-slide-main");
|
||||
// Store type so it can be found easiely later.
|
||||
slide.setAttribute("slide-type", type);
|
||||
slide.appendChild(panel);
|
||||
slide.appendChild(content);
|
||||
// Graphics-slide is put at mostleft position.
|
||||
if (type == "graphics" || type == "_overview") {
|
||||
// Remove old graphics-slide.
|
||||
/* see above
|
||||
if(swiper[0].slides[0].getAttribute("slide-type") === "graphics"){
|
||||
swiper[0].removeSlide(0);
|
||||
}
|
||||
*/
|
||||
swiper[s].prependSlide(slide);
|
||||
swiper[s].slideTo(0);
|
||||
} else if (type == "console") {
|
||||
swiper[s].appendSlide(slide);
|
||||
if (s === 3) {
|
||||
// Slide mostright swiper-instance to last position (console)
|
||||
swiper[3].slideNext();
|
||||
}
|
||||
} else {
|
||||
swiper[s].appendSlide(slide);
|
||||
if (swiper[s].slides.length > 1) {
|
||||
var consoleslide = swiper[s].slides[swiper[s].slides.length - 2];
|
||||
if (consoleslide.getAttribute["slide-type"] == "console") {
|
||||
// shift Console-slide to mostright position.
|
||||
swiper[s].removeSlide(swiper[s].slides.length - 2);
|
||||
swiper[s].appendSlide(consoleslide);
|
||||
// Slide to position of new slide
|
||||
swiper[s].slideTo(swiper[s].slides.length - 2);
|
||||
} else {
|
||||
swiper[s].slideTo(swiper[s].slides.length - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function createCloseButton(s) {
|
||||
// Creates 'span'-element containing close-button.
|
||||
var wrapper = document.createElement('span');
|
||||
wrapper.onclick = function () {
|
||||
swiper[s].removeSlide(swiper[s].activeIndex);
|
||||
swiper[s].slidePrev();
|
||||
};
|
||||
var closeButton = '<svg class="interactive icon slide-close-icon" fill="#000000" height="24" viewBox="0 0 24 24" width="24"><path d="M19 6.41L17.6 5 12 10.6 6.4 5 5 6.4 10.6 12 5 17.6 6.4 19 12 13.4 17.6 19 19 17.6 13.4 12z"/><path d="M0 0h24v24H0z" fill="none"/></svg>';
|
||||
wrapper.innerHTML = closeButton;
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
function createUpdateButton(s){
|
||||
// Creates 'span'-element containing update-button (Should be removed later!)
|
||||
var button = document.createElement('span');
|
||||
button.setAttribute("class","interactive toggle-updates-graphics")
|
||||
button.onclick = function () {
|
||||
getUpdatesGraphics = ! getUpdatesGraphics;
|
||||
button.innerHTML = "updates = "+getUpdatesGraphics;
|
||||
};
|
||||
button.innerHTML = "updates: "+getUpdatesGraphics;
|
||||
return button;
|
||||
}
|
||||
|
||||
function defaultSlidePos(s) {
|
||||
return s < 3 ? 0 : swiper[s].slides.length-1;
|
||||
}
|
||||
|
||||
function getSlideNames() {
|
||||
var names = []
|
||||
for (var s=0; s<MAXBLOCK; s++) {
|
||||
var sw = swiper[s];
|
||||
var name = "";
|
||||
if (sw.activeIndex != defaultSlidePos(s)) {
|
||||
name = sw.slides[sw.activeIndex].getAttribute("slide-type");
|
||||
}
|
||||
names.push();
|
||||
}
|
||||
for (var s=MAXBLOCK-1; s>=0; s--) {
|
||||
if (names[s] != "") break;
|
||||
names.pop();
|
||||
}
|
||||
return names;
|
||||
}
|
Reference in New Issue
Block a user