summaryrefslogtreecommitdiff
path: root/web/js
diff options
context:
space:
mode:
authorDevaev Maxim <[email protected]>2018-12-15 04:29:40 +0300
committerDevaev Maxim <[email protected]>2018-12-15 04:29:40 +0300
commit3c33bd37190772a783369894e209bcfe0858177a (patch)
treee095f08f37371a3182f6ced0b280c4bcaa06983b /web/js
parent3445766a50eab16a96d969397a6fe0422f7cfcd2 (diff)
own auth
Diffstat (limited to 'web/js')
-rw-r--r--web/js/bb.js33
-rw-r--r--web/js/index/main.js65
-rw-r--r--web/js/kvm/atx.js43
-rw-r--r--web/js/kvm/hid.js198
-rw-r--r--web/js/kvm/keyboard.js190
-rw-r--r--web/js/kvm/main.js16
-rw-r--r--web/js/kvm/mouse.js160
-rw-r--r--web/js/kvm/msd.js193
-rw-r--r--web/js/kvm/session.js143
-rw-r--r--web/js/kvm/stream.js221
-rw-r--r--web/js/tools.js133
-rw-r--r--web/js/wm.js387
12 files changed, 0 insertions, 1782 deletions
diff --git a/web/js/bb.js b/web/js/bb.js
deleted file mode 100644
index 565a3ab4..00000000
--- a/web/js/bb.js
+++ /dev/null
@@ -1,33 +0,0 @@
-function checkBrowser() {
- if (
- !window.navigator
- || window.navigator.userAgent.indexOf("MSIE ") > 0
- || window.navigator.userAgent.indexOf("Trident/") > 0
- || window.navigator.userAgent.indexOf("Edge/") > 0
- ) {
- var el_modal = document.createElement("div");
- el_modal.className = "modal";
- el_modal.style.visibility = "visible";
- el_modal.innerHTML = `
- <div class="modal-window">
- <div class="modal-content">
- Hello. You are using an incompatible or legacy browser.<br>
- Please use one of the following browsers:
- <hr>
- <ul>
- <li><a target="_blank" href="https://google.com/chrome">Google Chrome</a> <sup><i>recommended</i></sup></li>
- <li><a target="_blank" href="https://chromium.org/Home">Chromium</a> <sup><i>recommended</i></sup></li>
- <li><a target="_blank" href="https://mozilla.org/firefox">Mozilla Firefox</a></li>
- <li><a target="_blank" href="https://apple.com/safari">Apple Safari</a></li>
- <li><a target="_blank" href="https://opera.com">Opera</a></li>
- <li><a target="_blank" href="https://vivaldi.com">Vivaldi</a></li>
- </ul>
- </div>
- </div>
- `;
- document.body.appendChild(el_modal);
- return false;
- } else {
- return true;
- }
-}
diff --git a/web/js/index/main.js b/web/js/index/main.js
deleted file mode 100644
index 8f5c74a6..00000000
--- a/web/js/index/main.js
+++ /dev/null
@@ -1,65 +0,0 @@
-function main() {
- if (checkBrowser()) {
- __setAppText();
- __loadKvmdInfo();
- }
-}
-
-function __setAppText() {
- $("app-text").innerHTML = `
- <span class="code-comment"># On Linux using Chromium/Chrome via any terminal:<br>
- $</span> \`which chromium 2>/dev/null || which chrome 2>/dev/null\` --app="${window.location.href}"<br>
- <br>
- <span class="code-comment"># On MacOS using Terminal application:<br>
- $</span> /Applications/Google&bsol; Chrome.app/Contents/MacOS/Google&bsol; Chrome --app="${window.location.href}"<br>
- <br>
- <span class="code-comment"># On Windows via cmd.exe:<br>
- C:&bsol;&gt;</span> start chrome --app="${window.location.href}"
- `;
-}
-
-function __loadKvmdInfo() {
- var http = tools.makeRequest("GET", "/kvmd/info", function() {
- if (http.readyState === 4) {
- if (http.status === 200) {
- var info = JSON.parse(http.responseText).result;
-
- var apps = Object.values(info.extras).sort(function(a, b) {
- if (a["place"] < b["place"]) {
- return -1;
- } else if (a["place"] > b["place"]) {
- return 1;
- } else {
- return 0;
- }
- });
-
- $("apps-box").innerHTML = "<ul id=\"apps\"></ul>";
- apps.forEach(function(app) {
- $("apps").innerHTML += `
- <li>
- <div class="app">
- <a href="${app.path}">
- <div>
- <img class="svg-gray" src="${app.icon}">
- ${app.name}
- </div>
- </a>
- </div>
- </li>
- `;
- });
-
- if (info.meta && info.meta.server && info.meta.server.host) {
- $("kvmd-meta-server-host").innerHTML = info.meta.server.host;
- document.title = "Pi-KVM Index: " + info.meta.server.host;
- } else {
- $("kvmd-meta-server-host").innerHTML = "";
- document.title = "Pi-KVM Index";
- }
- } else {
- setTimeout(__loadKvmdInfo, 1000);
- }
- }
- });
-}
diff --git a/web/js/kvm/atx.js b/web/js/kvm/atx.js
deleted file mode 100644
index ed5f045e..00000000
--- a/web/js/kvm/atx.js
+++ /dev/null
@@ -1,43 +0,0 @@
-function Atx() {
- var self = this;
-
- /********************************************************************************/
-
- var __init__ = function() {
- $("atx-power-led").title = "Power Led";
- $("atx-hdd-led").title = "Disk Activity Led";
-
- tools.setOnClick($("atx-power-button"), () => __clickButton("power", "Are you sure to click the power button?"));
- tools.setOnClick($("atx-power-button-long"), () => __clickButton("power_long", "Are you sure to perform the long press of the power button?"));
- tools.setOnClick($("atx-reset-button"), () => __clickButton("reset", "Are you sure to reboot the server?"));
- };
-
- /********************************************************************************/
-
- self.setState = function(state) {
- $("atx-power-led").className = ((state && state.leds.power) ? "led-green" : "led-gray");
- $("atx-hdd-led").className = ((state && state.leds.hdd) ? "led-red" : "led-gray");
-
- wm.switchDisabled($("atx-power-button"), (!state || state.busy));
- wm.switchDisabled($("atx-power-button-long"), (!state || state.busy));
- wm.switchDisabled($("atx-reset-button"), (!state || state.busy));
- };
-
- var __clickButton = function(button, confirm_msg) {
- wm.confirm(confirm_msg).then(function(ok) {
- if (ok) {
- var http = tools.makeRequest("POST", "/kvmd/atx/click?button=" + button, function() {
- if (http.readyState === 4) {
- if (http.status === 409) {
- wm.error("Performing another ATX operation for other client.<br>Please try again later");
- } else if (http.status !== 200) {
- wm.error("Click error:<br>", http.responseText);
- }
- }
- });
- }
- });
- };
-
- __init__();
-}
diff --git a/web/js/kvm/hid.js b/web/js/kvm/hid.js
deleted file mode 100644
index 49d659ab..00000000
--- a/web/js/kvm/hid.js
+++ /dev/null
@@ -1,198 +0,0 @@
-function Hid() {
- var self = this;
-
- /********************************************************************************/
-
- var __ws = null;
-
- var __chars_to_codes = {};
- var __codes_delay = 50;
-
- var __keyboard = new Keyboard();
- var __mouse = new Mouse();
-
- var __init__ = function() {
- var __hidden_attr = null;
- var __visibility_change_attr = null;
-
- if (typeof document.hidden !== "undefined") {
- __hidden_attr = "hidden";
- __visibility_change_attr = "visibilitychange";
- } else if (typeof document.webkitHidden !== "undefined") {
- __hidden_attr = "webkitHidden";
- __visibility_change_attr = "webkitvisibilitychange";
- } else if (typeof document.mozHidden !== "undefined") {
- __hidden_attr = "mozHidden";
- __visibility_change_attr = "mozvisibilitychange";
- }
-
- if (__visibility_change_attr) {
- document.addEventListener(
- __visibility_change_attr,
- function() {
- if (document[__hidden_attr]) {
- __releaseAll();
- }
- },
- false
- );
- }
-
- window.addEventListener("pagehide", __releaseAll);
- window.addEventListener("blur", __releaseAll);
-
- __chars_to_codes = __buildCharsToCodes();
-
- tools.setOnClick($("hid-pak-button"), __clickPasteAsKeysButton);
- tools.setOnClick($("hid-reset-button"), __clickResetButton);
-
- Array.prototype.forEach.call(document.querySelectorAll("[data-shortcut]"), function(el_shortcut) {
- tools.setOnClick(el_shortcut, () => __emitShortcut(el_shortcut.getAttribute("data-shortcut").split(" ")));
- });
- };
-
- /********************************************************************************/
-
- self.setSocket = function(ws) {
- wm.switchDisabled($("hid-pak-text"), !ws);
- wm.switchDisabled($("hid-pak-button"), !ws);
- wm.switchDisabled($("hid-reset-button"), !ws);
- __ws = ws;
- __keyboard.setSocket(ws);
- __mouse.setSocket(ws);
- };
-
- var __releaseAll = function() {
- __keyboard.releaseAll();
- };
-
- var __emitShortcut = function(codes) {
- return new Promise(function(resolve) {
- tools.debug("HID: emitting keys:", codes);
-
- var raw_events = [];
- [[codes, true], [codes.slice().reverse(), false]].forEach(function(op) {
- var [op_codes, state] = op;
- op_codes.forEach(function(code) {
- raw_events.push({code: code, state: state});
- });
- });
-
- var index = 0;
- var iterate = () => setTimeout(function() {
- __keyboard.fireEvent(raw_events[index].code, raw_events[index].state);
- ++index;
- if (index < raw_events.length) {
- iterate();
- } else {
- resolve(null);
- }
- }, __codes_delay);
- iterate();
- });
- };
-
- var __buildCharsToCodes = function() {
- var chars_to_codes = {
- "\n": ["Enter"],
- "\t": ["Tab"],
- " ": ["Space"],
- "`": ["Backquote"], "~": ["ShiftLeft", "Backquote"],
- "\\": ["Backslash"], "|": ["ShiftLeft", "Backslash"],
- "[": ["BracketLeft"], "{": ["ShiftLeft", "BracketLeft"],
- "]": ["BracketLeft"], "}": ["ShiftLeft", "BracketRight"],
- ",": ["Comma"], "<": ["ShiftLeft", "Comma"],
- ".": ["Period"], ">": ["ShiftLeft", "Period"],
- "1": ["Digit1"], "!": ["ShiftLeft", "Digit1"],
- "2": ["Digit2"], "@": ["ShiftLeft", "Digit2"],
- "3": ["Digit3"], "#": ["ShiftLeft", "Digit3"],
- "4": ["Digit4"], "$": ["ShiftLeft", "Digit4"],
- "5": ["Digit5"], "%": ["ShiftLeft", "Digit5"],
- "6": ["Digit6"], "^": ["ShiftLeft", "Digit6"],
- "7": ["Digit7"], "&": ["ShiftLeft", "Digit7"],
- "8": ["Digit8"], "*": ["ShiftLeft", "Digit8"],
- "9": ["Digit9"], "(": ["ShiftLeft", "Digit9"],
- "0": ["Digit0"], ")": ["ShiftLeft", "Digit0"],
- "-": ["Minus"], "_": ["ShiftLeft", "Minus"],
- "'": ["Quote"], "\"": ["ShiftLeft", "Quote"],
- ";": ["Semicolon"], ":": ["ShiftLeft", "Semicolon"],
- "/": ["Slash"], "?": ["ShiftLeft", "Slash"],
- "=": ["Equal"], "+": ["ShiftLeft", "Equal"],
- };
-
- for (var ch = "a".charCodeAt(0); ch <= "z".charCodeAt(0); ++ch) {
- var low = String.fromCharCode(ch);
- var up = low.toUpperCase();
- var code = "Key" + up;
- chars_to_codes[low] = [code];
- chars_to_codes[up] = ["ShiftLeft", code];
- }
-
- return chars_to_codes;
- };
-
- var __clickPasteAsKeysButton = function() {
- var text = $("hid-pak-text").value.replace(/[^\x00-\x7F]/g, ""); // eslint-disable-line no-control-regex
- if (text) {
- var clipboard_codes = [];
- var codes_count = 0;
- [...text].forEach(function(ch) {
- var codes = __chars_to_codes[ch];
- if (codes) {
- codes_count += codes.length;
- clipboard_codes.push(codes);
- }
- });
- var time = __codes_delay * codes_count * 2 / 1000;
-
- var confirm_msg = `
- You are going to automatically type ${codes_count} characters from the system clipboard.
- It will take ${time} seconds.<br>
- <br>
- Are you sure you want to continue?
- `;
-
- wm.confirm(confirm_msg).then(function(ok) {
- if (ok) {
- wm.switchDisabled($("hid-pak-text"), true);
- wm.switchDisabled($("hid-pak-button"), true);
- $("hid-pak-led").className = "led-yellow-rotating-fast";
- $("hid-pak-led").title = "Autotyping...";
-
- tools.debug("HID: paste-as-keys:", text);
-
- var index = 0;
- var iterate = function() {
- __emitShortcut(clipboard_codes[index]).then(function() {
- ++index;
- if (index < clipboard_codes.length && __ws) {
- iterate();
- } else {
- $("hid-pak-text").value = "";
- wm.switchDisabled($("hid-pak-text"), false);
- wm.switchDisabled($("hid-pak-button"), false);
- $("hid-pak-led").className = "led-gray";
- $("hid-pak-led").title = "";
- }
- });
- };
- iterate();
- } else {
- $("hid-pak-text").value = "";
- }
- });
- }
- };
-
- var __clickResetButton = function() {
- var http = tools.makeRequest("POST", "/kvmd/hid/reset", function() {
- if (http.readyState === 4) {
- if (http.status !== 200) {
- wm.error("HID reset error:<br>", http.responseText);
- }
- }
- });
- };
-
- __init__();
-}
diff --git a/web/js/kvm/keyboard.js b/web/js/kvm/keyboard.js
deleted file mode 100644
index 3c821406..00000000
--- a/web/js/kvm/keyboard.js
+++ /dev/null
@@ -1,190 +0,0 @@
-function Keyboard() {
- var self = this;
-
- /********************************************************************************/
-
- var __ws = null;
-
- var __keys = [].slice.call(document.querySelectorAll("div#keyboard-desktop div.keyboard-block div.keyboard-row div.key"));
- var __modifiers = [].slice.call(document.querySelectorAll("div#keyboard-desktop div.keyboard-block div.keyboard-row div.modifier"));
-
- var __init__ = function() {
- $("hid-keyboard-led").title = "Keyboard free";
-
- $("keyboard-window").onkeydown = (event) => __keyboardHandler(event, true);
- $("keyboard-window").onkeyup = (event) => __keyboardHandler(event, false);
- $("keyboard-window").onfocus = __updateLeds;
- $("keyboard-window").onblur = __updateLeds;
-
- $("stream-window").onkeydown = (event) => __keyboardHandler(event, true);
- $("stream-window").onkeyup = (event) => __keyboardHandler(event, false);
- $("stream-window").onfocus = __updateLeds;
- $("stream-window").onblur = __updateLeds;
-
- window.addEventListener("focusin", __updateLeds);
- window.addEventListener("focusout", __updateLeds);
-
- Array.prototype.forEach.call($$("key"), function(el_key) {
- tools.setOnDown(el_key, () => __clickHandler(el_key, true));
- tools.setOnUp(el_key, () => __clickHandler(el_key, false));
- el_key.onmouseout = function() {
- if (__isPressed(el_key)) {
- __clickHandler(el_key, false);
- }
- };
- });
-
- Array.prototype.forEach.call($$("modifier"), function(el_key) {
- tools.setOnDown(el_key, () => __toggleModifierHandler(el_key));
- });
-
- if (tools.browser.is_mac) {
- tools.info("Keyboard: enabled Mac-CMD-Hook");
- }
- };
-
- /********************************************************************************/
-
- self.setSocket = function(ws) {
- if (ws !== __ws) {
- self.releaseAll();
- __ws = ws;
- }
- __updateLeds();
- };
-
- self.releaseAll = function() {
- __keys.concat(__modifiers).forEach(function(el_key) {
- if (__isActive(el_key)) {
- self.fireEvent(el_key.getAttribute("data-key"), false);
- }
- });
- };
-
- self.fireEvent = function(code, state) {
- __keyboardHandler({code: code}, state);
- };
-
- var __updateLeds = function() {
- tools.debug("Keyboard: update leds");
- if (
- __ws && (
- $("stream-window").classList.contains("window-active")
- || $("keyboard-window").classList.contains("window-active")
- )
- ) {
- $("hid-keyboard-led").className = "led-green";
- $("hid-keyboard-led").title = "Keyboard captured";
- } else {
- $("hid-keyboard-led").className = "led-gray";
- $("hid-keyboard-led").title = "Keyboard free";
- }
- };
-
- var __keyboardHandler = function(event, state) {
- if (event.preventDefault) {
- event.preventDefault();
- }
- var el_key = document.querySelector(`[data-key='${event.code}']`);
- if (el_key && !event.repeat) {
- __commonHandler(el_key, state, "pressed");
- if (tools.browser.is_mac) {
- // https://bugs.chromium.org/p/chromium/issues/detail?id=28089
- // https://bugzilla.mozilla.org/show_bug.cgi?id=1299553
- if ((event.code === "MetaLeft" || event.code === "MetaRight") && !state) {
- __keys.forEach(function(el_key) {
- if (__isActive(el_key)) {
- self.fireEvent(el_key.getAttribute("data-key"), false);
- }
- });
- }
- }
- __unholdModifiers();
- }
- };
-
- var __clickHandler = function(el_key, state) {
- __commonHandler(el_key, state, "pressed");
- __unholdModifiers();
- };
-
- var __toggleModifierHandler = function(el_key) {
- __commonHandler(el_key, !__isActive(el_key), "holded");
- };
-
- var __unholdModifiers = function() {
- __modifiers.forEach(function(el_key) {
- if (__isHolded(el_key)) {
- __deactivate(el_key);
- __sendKey(el_key, false);
- }
- });
- };
-
- var __commonHandler = function(el_key, state, cls) {
- if (state && !__isActive(el_key)) {
- __deactivate(el_key);
- __activate(el_key, cls);
- __sendKey(el_key, true);
- } else {
- __deactivate(el_key);
- __sendKey(el_key, false);
- }
- };
-
- var __isPressed = function(el_key) {
- var is_pressed = false;
- Array.prototype.forEach.call(__resolveKeys(el_key), function(el_key) {
- is_pressed = (is_pressed || el_key.classList.contains("pressed"));
- });
- return is_pressed;
- };
-
- var __isHolded = function(el_key) {
- var is_holded = false;
- Array.prototype.forEach.call(__resolveKeys(el_key), function(el_key) {
- is_holded = (is_holded || el_key.classList.contains("holded"));
- });
- return is_holded;
- };
-
- var __isActive = function(el_key) {
- var is_active = false;
- Array.prototype.forEach.call(__resolveKeys(el_key), function(el_key) {
- is_active = (is_active || el_key.classList.contains("pressed") || el_key.classList.contains("holded"));
- });
- return is_active;
- };
-
- var __activate = function(el_key, cls) {
- Array.prototype.forEach.call(__resolveKeys(el_key), function(el_key) {
- el_key.classList.add(cls);
- });
- };
-
- var __deactivate = function(el_key) {
- Array.prototype.forEach.call(__resolveKeys(el_key), function(el_key) {
- el_key.classList.remove("pressed");
- el_key.classList.remove("holded");
- });
- };
-
- var __resolveKeys = function(el_key) {
- var code = el_key.getAttribute("data-key");
- return document.querySelectorAll(`[data-key='${code}']`);
- };
-
- var __sendKey = function(el_key, state) {
- var code = el_key.getAttribute("data-key");
- tools.debug("Keyboard: key", (state ? "pressed:" : "released:"), code);
- if (__ws) {
- __ws.send(JSON.stringify({
- event_type: "key",
- key: code,
- state: state,
- }));
- }
- };
-
- __init__();
-}
diff --git a/web/js/kvm/main.js b/web/js/kvm/main.js
deleted file mode 100644
index 5c6d775a..00000000
--- a/web/js/kvm/main.js
+++ /dev/null
@@ -1,16 +0,0 @@
-var wm;
-
-function main() {
- if (checkBrowser()) {
- wm = new WindowManager();
-
- tools.setOnClick($("show-about-button"), () => wm.showWindow($("about-window")));
- tools.setOnClick($("show-keyboard-button"), () => wm.showWindow($("keyboard-window")));
- tools.setOnClick($("show-stream-button"), () => wm.showWindow($("stream-window")));
- tools.setOnClick($("open-log-button"), () => window.open("/kvmd/log?seek=3600&follow=1", "_blank"));
-
- wm.showWindow($("stream-window"));
-
- new Session();
- }
-}
diff --git a/web/js/kvm/mouse.js b/web/js/kvm/mouse.js
deleted file mode 100644
index 58e46d15..00000000
--- a/web/js/kvm/mouse.js
+++ /dev/null
@@ -1,160 +0,0 @@
-function Mouse() {
- var self = this;
-
- /********************************************************************************/
-
- var __ws = null;
-
- var __current_pos = {x: 0, y:0};
- var __sent_pos = {x: 0, y:0};
- var __wheel_delta = {x: 0, y: 0};
-
- var __stream_hovered = false;
-
- var __init__ = function() {
- $("hid-mouse-led").title = "Mouse free";
-
- $("stream-box").onmouseenter = __hoverStream;
- $("stream-box").onmouseleave = __leaveStream;
- $("stream-box").onmousedown = (event) => __buttonHandler(event, true);
- $("stream-box").onmouseup = (event) => __buttonHandler(event, false);
- $("stream-box").oncontextmenu = (event) => event.preventDefault();
- $("stream-box").onmousemove = __moveHandler;
- $("stream-box").onwheel = __wheelHandler;
- $("stream-box").ontouchstart = (event) => __touchMoveHandler(event);
-
- Array.prototype.forEach.call(document.querySelectorAll("[data-mouse-button]"), function(el_button) {
- var button = el_button.getAttribute("data-mouse-button");
- tools.setOnDown(el_button, () => __sendButton(button, true));
- tools.setOnUp(el_button, () => __sendButton(button, false));
- });
-
- setInterval(__sendMove, 100);
- };
-
- /********************************************************************************/
-
- self.setSocket = function(ws) {
- __ws = ws;
- if (ws) {
- $("stream-box").classList.add("stream-box-mouse-enabled");
- } else {
- $("stream-box").classList.remove("stream-box-mouse-enabled");
- }
- __updateLeds();
- };
-
- var __hoverStream = function() {
- __stream_hovered = true;
- __updateLeds();
- };
-
- var __leaveStream = function() {
- __stream_hovered = false;
- __updateLeds();
- };
-
- var __updateLeds = function() {
- if (__ws && (__stream_hovered || tools.browser.is_ios)) {
- // Mouse is always available on iOS via touchscreen
- $("hid-mouse-led").className = "led-green";
- $("hid-mouse-led").title = "Mouse tracked";
- } else {
- $("hid-mouse-led").className = "led-gray";
- $("hid-mouse-led").title = "Mouse free";
- }
- };
-
- var __buttonHandler = function(event, state) {
- // https://www.w3schools.com/jsref/event_button.asp
- event.preventDefault();
- switch (event.button) {
- case 0: __sendButton("left", state); break;
- case 2: __sendButton("right", state); break;
- }
- };
-
- var __touchMoveHandler = function(event) {
- event.preventDefault();
- if (event.touches[0].target && event.touches[0].target.getBoundingClientRect) {
- var rect = event.touches[0].target.getBoundingClientRect();
- __current_pos = {
- x: Math.round(event.touches[0].clientX - rect.left),
- y: Math.round(event.touches[0].clientY - rect.top),
- };
- __sendMove();
- }
- };
-
- var __moveHandler = function(event) {
- var rect = event.target.getBoundingClientRect();
- __current_pos = {
- x: Math.round(event.clientX - rect.left),
- y: Math.round(event.clientY - rect.top),
- };
- };
-
-
- var __sendButton = function(button, state) {
- tools.debug("Mouse: button", (state ? "pressed:" : "released:"), button);
- __sendMove();
- if (__ws) {
- __ws.send(JSON.stringify({
- event_type: "mouse_button",
- button: button,
- state: state,
- }));
- }
- };
-
- var __sendMove = function() {
- var pos = __current_pos;
- if (pos.x !== __sent_pos.x || pos.y !== __sent_pos.y) {
- var el_stream_image = $("stream-image");
- var to = {
- x: __translate(pos.x, 0, el_stream_image.clientWidth, -32768, 32767),
- y: __translate(pos.y, 0, el_stream_image.clientHeight, -32768, 32767),
- };
-
- tools.debug("Mouse: moved:", to);
- if (__ws) {
- __ws.send(JSON.stringify({
- event_type: "mouse_move",
- to: to,
- }));
- }
- __sent_pos = pos;
- }
- };
-
- var __translate = function(x, a, b, c, d) {
- return Math.round((x - a) / (b - a) * (d - c) + c);
- };
-
- var __wheelHandler = function(event) {
- // https://learn.javascript.ru/mousewheel
- if (event.preventDefault) {
- event.preventDefault();
- }
-
- var delta = {x: 0, y: 0};
-
- __wheel_delta.y += event.deltaY;
- if (Math.abs(__wheel_delta.y) >= 100) {
- delta.y = __wheel_delta.y / Math.abs(__wheel_delta.y) * (-5);
- __wheel_delta.y = 0;
- }
-
- if (delta.y) {
- tools.debug("Mouse: scrolled:", delta);
- if (__ws) {
- __ws.send(JSON.stringify({
- event_type: "mouse_wheel",
- delta: delta,
- }));
- }
- }
- };
-
- __init__();
-}
diff --git a/web/js/kvm/msd.js b/web/js/kvm/msd.js
deleted file mode 100644
index c23de99d..00000000
--- a/web/js/kvm/msd.js
+++ /dev/null
@@ -1,193 +0,0 @@
-function Msd() {
- var self = this;
-
- /********************************************************************************/
-
- var __state = null;
- var __upload_http = null;
- var __image_file = null;
-
- var __init__ = function() {
- $("msd-led").title = "Unknown state";
-
- $("msd-select-new-image-file").onchange = __selectNewImageFile;
- tools.setOnClick($("msd-select-new-image-button"), () => $("msd-select-new-image-file").click());
-
- tools.setOnClick($("msd-upload-new-image-button"), __clickUploadNewImageButton);
- tools.setOnClick($("msd-abort-uploading-button"), __clickAbortUploadingButton);
-
- tools.setOnClick($("msd-switch-to-kvm-button"), () => __clickSwitchButton("kvm"));
- tools.setOnClick($("msd-switch-to-server-button"), () => __clickSwitchButton("server"));
-
- tools.setOnClick($("msd-reset-button"), __clickResetButton);
- };
-
- /********************************************************************************/
-
- self.setState = function(state) {
- __state = state;
- __applyState();
- };
-
- var __clickUploadNewImageButton = function() {
- var form_data = new FormData();
- form_data.append("image_name", __image_file.name);
- form_data.append("image_data", __image_file);
-
- __upload_http = new XMLHttpRequest();
- __upload_http.open("POST", "/kvmd/msd/write", true);
- __upload_http.upload.timeout = 5000;
- __upload_http.onreadystatechange = __uploadStateChange;
- __upload_http.upload.onprogress = __uploadProgress;
- __upload_http.send(form_data);
- };
-
- var __clickAbortUploadingButton = function() {
- __upload_http.onreadystatechange = null;
- __upload_http.upload.onprogress = null;
- __upload_http.abort();
- __upload_http = null;
- $("msd-progress").setAttribute("data-label", "Aborted");
- $("msd-progress-value").style.width = "0%";
- };
-
- var __clickSwitchButton = function(to) {
- var http = tools.makeRequest("POST", "/kvmd/msd/connect?to=" + to, function() {
- if (http.readyState === 4) {
- if (http.status !== 200) {
- wm.error("Switch error:<br>", http.responseText);
- }
- }
- __applyState();
- });
- __applyState();
- wm.switchDisabled($(`msd-switch-to-${to}-button`), true);
- };
-
- var __selectNewImageFile = function() {
- var el_input = $("msd-select-new-image-file");
- var image_file = (el_input.files.length ? el_input.files[0] : null);
- if (image_file && image_file.size > __state.info.size) {
- wm.error("New image is too big for your Mass Storage Device.<br>Maximum:", __formatSize(__state.info.size));
- el_input.value = "";
- image_file = null;
- }
- __image_file = image_file;
- __applyState();
- };
-
- var __clickResetButton = function() {
- var http = tools.makeRequest("POST", "/kvmd/msd/reset", function() {
- if (http.readyState === 4) {
- if (http.status !== 200) {
- wm.error("MSD reset error:<br>", http.responseText);
- }
- }
- __applyState();
- });
- __applyState();
- };
-
- var __applyState = function() {
- if (__state) {
- if (__state.connected_to === "server") {
- $("msd-another-another-user-uploads").style.display = "none";
- $("msd-led").className = "led-green";
- $("msd-status").innerHTML = $("msd-led").title = "Connected to Server";
- } else if (__state.busy) {
- if (!__upload_http) {
- $("msd-another-another-user-uploads").style.display = "block";
- }
- $("msd-led").className = "led-yellow-rotating-fast";
- $("msd-status").innerHTML = $("msd-led").title = "Uploading new image";
- } else {
- $("msd-another-another-user-uploads").style.display = "none";
- $("msd-led").className = "led-gray";
- if (__state.in_operate) {
- $("msd-status").innerHTML = $("msd-led").title = "Connected to KVM";
- } else {
- $("msd-status").innerHTML = $("msd-led").title = "Unavailable";
- }
- }
-
- $("msd-not-in-operate").style.display = (__state.in_operate ? "none" : "block");
- $("msd-current-image-broken").style.display = (
- __state.in_operate && __state.info.image &&
- !__state.info.image.complete && !__state.busy ? "block" : "none"
- );
-
- $("msd-current-image-name").innerHTML = (__state.in_operate && __state.info.image ? __state.info.image.name : "None");
- $("msd-current-image-size").innerHTML = (__state.in_operate && __state.info.image ? __formatSize(__state.info.image.size) : "None");
- $("msd-storage-size").innerHTML = (__state.in_operate ? __formatSize(__state.info.size) : "Unavailable");
-
- wm.switchDisabled($("msd-switch-to-kvm-button"), (!__state.in_operate || __state.connected_to === "kvm" || __state.busy));
- wm.switchDisabled($("msd-switch-to-server-button"), (!__state.in_operate || __state.connected_to === "server" || __state.busy));
- wm.switchDisabled($("msd-select-new-image-button"), (!__state.in_operate || __state.connected_to !== "kvm" || __state.busy || __upload_http));
- wm.switchDisabled($("msd-upload-new-image-button"), (!__state.in_operate || __state.connected_to !== "kvm" || __state.busy || !__image_file));
- wm.switchDisabled($("msd-abort-uploading-button"), (!__state.in_operate || !__upload_http));
- wm.switchDisabled($("msd-reset-button"), (!__state.in_operate || __upload_http));
-
- $("msd-new-image").style.display = (__image_file ? "block" : "none");
- $("msd-progress").setAttribute("data-label", "Waiting for upload ...");
- $("msd-progress-value").style.width = "0%";
- $("msd-new-image-name").innerHTML = (__image_file ? __image_file.name : "");
- $("msd-new-image-size").innerHTML = (__image_file ? __formatSize(__image_file.size) : "");
-
- } else {
- $("msd-another-another-user-uploads").style.display = "none";
- $("msd-led").className = "led-gray";
- $("msd-status").innerHTML = "";
- $("msd-led").title = "";
- $("msd-not-in-operate").style.display = "none";
- $("msd-current-image-broken").style.display = "none";
- $("msd-current-image-name").innerHTML = "";
- $("msd-current-image-size").innerHTML = "";
- $("msd-storage-size").innerHTML = "";
-
- wm.switchDisabled($("msd-switch-to-kvm-button"), true);
- wm.switchDisabled($("msd-switch-to-server-button"), true);
- wm.switchDisabled($("msd-select-new-image-button"), true);
- wm.switchDisabled($("msd-upload-new-image-button"), true);
- wm.switchDisabled($("msd-abort-uploading-button"), true);
- wm.switchDisabled($("msd-reset-button"), true);
-
- $("msd-select-new-image-file").value = "";
- $("msd-new-image").style.display = "none";
- $("msd-progress").setAttribute("data-label", "");
- $("msd-progress-value").style.width = "0%";
- $("msd-new-image-name").innerHTML = "";
- $("msd-new-image-size").innerHTML = "";
- }
- };
-
- var __formatSize = function(size) {
- if (size > 0) {
- var index = Math.floor( Math.log(size) / Math.log(1024) );
- return (size / Math.pow(1024, index)).toFixed(2) * 1 + " " + ["B", "kB", "MB", "GB", "TB"][index];
- } else {
- return 0;
- }
- };
-
- var __uploadStateChange = function() {
- if (__upload_http.readyState === 4) {
- if (__upload_http.status !== 200) {
- wm.error("Can't upload image to the Mass Storage Device:<br>", __upload_http.responseText);
- }
- $("msd-select-new-image-file").value = "";
- __image_file = null;
- __upload_http = null;
- __applyState();
- }
- };
-
- var __uploadProgress = function(event) {
- if(event.lengthComputable) {
- var percent = Math.round((event.loaded * 100) / event.total);
- $("msd-progress").setAttribute("data-label", percent + "%");
- $("msd-progress-value").style.width = percent + "%";
- }
- };
-
- __init__();
-}
diff --git a/web/js/kvm/session.js b/web/js/kvm/session.js
deleted file mode 100644
index e3e74160..00000000
--- a/web/js/kvm/session.js
+++ /dev/null
@@ -1,143 +0,0 @@
-function Session() {
- // var self = this;
-
- /********************************************************************************/
-
- var __ws = null;
-
- var __ping_timer = null;
- var __missed_heartbeats = 0;
-
- var __hid = new Hid();
- var __atx = new Atx();
- var __msd = new Msd();
- var __streamer = new Streamer();
-
- var __init__ = function() {
- $("link-led").title = "Not connected yet...";
- __startPoller();
- };
-
- /********************************************************************************/
-
- var __setKvmdInfo = function(state) {
- if (state.meta) {
- var text = JSON.stringify(state.meta, undefined, 4).replace(/ /g, "&nbsp;").replace(/\n/g, "<br>");
- $("about-meta").innerHTML = `
- <span class="code-comment">// The Pi-KVM metadata.<br>
- // You can get this json using handle <a target="_blank" href="/kvmd/info">/kvmd/info</a>.<br>
- // In the standard configuration this data<br>
- // is specified in the file /etc/kvmd/meta.yaml.</span><br>
- <br>
- ${text}
- `;
- if (state.meta.server && state.meta.server.host) {
- $("kvmd-meta-server-host").innerHTML = "Server: " + state.meta.server.host;
- document.title = "Pi-KVM Session: " + state.meta.server.host;
- } else {
- $("kvmd-meta-server-host").innerHTML = "";
- document.title = "Pi-KVM Session";
- }
- }
-
- $("about-version-kvmd").innerHTML = state.version.kvmd;
- $("about-version-streamer").innerHTML = `${state.version.streamer} (${state.streamer})`;
- };
-
- var __startPoller = function() {
- $("link-led").className = "led-yellow";
- $("link-led").title = "Connecting...";
-
- var http = tools.makeRequest("GET", "/ws_auth", function() {
- if (http.readyState === 4) {
- if (http.status === 200) {
- var proto = (location.protocol === "https:" ? "wss" : "ws");
- __ws = new WebSocket(`${proto}://${location.host}/kvmd/ws`);
- __ws.onopen = __wsOpenHandler;
- __ws.onmessage = __wsMessageHandler;
- __ws.onerror = __wsErrorHandler;
- __ws.onclose = __wsCloseHandler;
- } else {
- __wsCloseHandler(null);
- }
- }
- });
- };
-
- var __wsOpenHandler = function(event) {
- tools.debug("Session: socket opened:", event);
- $("link-led").className = "led-green";
- $("link-led").title = "Connected";
- __hid.setSocket(__ws);
- __missed_heartbeats = 0;
- __ping_timer = setInterval(__pingServer, 1000);
- };
-
- var __wsMessageHandler = function(event) {
- // tools.debug("Session: received socket data:", event.data);
- event = JSON.parse(event.data);
- if (event.msg_type === "pong") {
- __missed_heartbeats = 0;
- } else if (event.msg_type === "event") {
- if (event.msg.event === "info_state") {
- __setKvmdInfo(event.msg.event_attrs);
- } else if (event.msg.event === "atx_state") {
- __atx.setState(event.msg.event_attrs);
- } else if (event.msg.event === "msd_state") {
- __msd.setState(event.msg.event_attrs);
- } else if (event.msg.event === "streamer_state") {
- __streamer.setState(event.msg.event_attrs);
- }
- }
- };
-
- var __wsErrorHandler = function(event) {
- tools.error("Session: socket error:", event);
- if (__ws) {
- __ws.onclose = null;
- __ws.close();
- __wsCloseHandler(null);
- }
- };
-
- var __wsCloseHandler = function(event) {
- tools.debug("Session: socket closed:", event);
-
- $("link-led").className = "led-gray";
-
- if (__ping_timer) {
- clearInterval(__ping_timer);
- __ping_timer = null;
- }
-
- __hid.setSocket(null);
- __atx.setState(null);
- __msd.setState(null);
- __streamer.setState(null);
- __ws = null;
-
- setTimeout(function() {
- $("link-led").className = "led-yellow";
- setTimeout(__startPoller, 500);
- }, 500);
- };
-
- var __pingServer = function() {
- try {
- __missed_heartbeats += 1;
- if (__missed_heartbeats >= 5) {
- throw new Error("Too many missed heartbeats");
- }
- __ws.send(JSON.stringify({"event_type": "ping"}));
- } catch (err) {
- tools.error("Session: ping error:", err.message);
- if (__ws) {
- __ws.onclose = null;
- __ws.close();
- __wsCloseHandler(null);
- }
- }
- };
-
- __init__();
-}
diff --git a/web/js/kvm/stream.js b/web/js/kvm/stream.js
deleted file mode 100644
index 01ded5bc..00000000
--- a/web/js/kvm/stream.js
+++ /dev/null
@@ -1,221 +0,0 @@
-function Streamer() {
- var self = this;
-
- /********************************************************************************/
-
- var __resolution = {width: 640, height: 480};
- var __size_factor = 1;
- var __client_key = tools.makeId();
- var __client_id = "";
- var __client_fps = -1;
- var __prev = false;
-
- var __init__ = function() {
- $("stream-led").title = "Stream inactive";
-
- $("stream-quality-slider").min = 5;
- $("stream-quality-slider").max = 100;
- $("stream-quality-slider").step = 5;
- $("stream-quality-slider").value = 80;
- tools.setOnUpSlider($("stream-quality-slider"), 1000, __updateQualityValue, (value) => __sendParam("quality", value));
-
- $("stream-desired-fps-slider").min = 0;
- $("stream-desired-fps-slider").max = 30;
- $("stream-desired-fps-slider").step = 1;
- $("stream-desired-fps-slider").value = 0;
- tools.setOnUpSlider($("stream-desired-fps-slider"), 1000, __updateDesiredFpsValue, (value) => __sendParam("desired_fps", value));
-
- $("stream-size-slider").min = 20;
- $("stream-size-slider").max = 200;
- $("stream-size-slider").step = 5;
- $("stream-size-slider").value = 100;
- $("stream-size-slider").oninput = () => __resize();
- $("stream-size-slider").onchange = () => __resize();
-
- tools.setOnClick($("stream-screenshot-button"), __clickScreenshotButton);
- tools.setOnClick($("stream-reset-button"), __clickResetButton);
- };
-
- /********************************************************************************/
-
- self.setState = function(state) {
- if (state && state.state) {
- var source = state.state.source;
- var stream = state.state.stream;
-
- if (!__prev) {
- $("stream-quality-slider").activated = false;
- $("stream-desired-fps-slider").activated = false;
- }
-
- if (!$("stream-quality-slider").activated) {
- wm.switchDisabled($("stream-quality-slider"), false);
- if ($("stream-quality-slider").value !== source.quality) {
- $("stream-quality-slider").value = source.quality;
- __updateQualityValue(source.quality);
- }
- }
-
- if (!$("stream-desired-fps-slider").activated) {
- wm.switchDisabled($("stream-desired-fps-slider"), false);
- if ($("stream-desired-fps-slider").value !== source.desired_fps) {
- $("stream-desired-fps-slider").value = source.desired_fps;
- __updateDesiredFpsValue(source.desired_fps);
- }
- }
-
- if (__resolution.width !== source.resolution.width || __resolution.height !== source.resolution.height) {
- __resolution = source.resolution;
- if ($("stream-auto-resize-checkbox").checked) {
- __adjustSizeFactor();
- } else {
- __applySizeFactor();
- }
- }
-
- var stream_client = tools.getCookie("stream_client");
- if (!__client_id && stream_client && stream_client.startsWith(__client_key + "/")) {
- tools.info("Stream: found acceptable stream_client cookie:", stream_client);
- __client_id = stream_client.slice(stream_client.indexOf("/") + 1);
- }
-
- if (stream.clients_stat.hasOwnProperty(__client_id)) {
- __client_fps = stream.clients_stat[__client_id].fps;
- } else {
- __clearState();
- }
-
- if (!__prev) {
- var path = "/streamer/stream?key=" + __client_key;
- if (tools.browser.is_chrome || tools.browser.is_blink) {
- // uStreamer fix for Blink https://bugs.chromium.org/p/chromium/issues/detail?id=527446
- tools.info("Stream: using advance_headers=1 to fix Blink MJPG bugs");
- path += "&advance_headers=1";
- } else if (tools.browser.is_safari || tools.browser.is_ios) {
- // uStreamer fix for WebKit
- tools.info("Stream: using dual_final_frames=1 to fix WebKit MJPG bugs");
- path += "&dual_final_frames=1";
- }
- $("stream-image").src = path;
- $("stream-image").className = "stream-image-active";
- $("stream-box").classList.remove("stream-box-inactive");
- $("stream-led").className = "led-green";
- $("stream-led").title = "Stream is active";
- wm.switchDisabled($("stream-screenshot-button"), false);
- wm.switchDisabled($("stream-reset-button"), false);
- tools.info("Stream: acquired");
- __prev = true;
- }
-
- __updateStreamHeader(true);
-
- } else {
- __clearState();
- }
- };
-
- var __clearState = function() {
- tools.info("Stream: refreshing ...");
-
- $("stream-image").className = "stream-image-inactive";
- $("stream-box").classList.add("stream-box-inactive");
- $("stream-led").className = "led-gray";
- $("stream-led").title = "Stream inactive";
- wm.switchDisabled($("stream-screenshot-button"), true);
- wm.switchDisabled($("stream-reset-button"), true);
- wm.switchDisabled($("stream-quality-slider"), true);
- wm.switchDisabled($("stream-desired-fps-slider"), true);
-
- __client_key = tools.makeId();
- __client_id = "";
- __client_fps = -1;
- __prev = false;
- __updateStreamHeader(false);
- };
-
- var __updateQualityValue = function(value) {
- $("stream-quality-value").innerHTML = value + "%";
- };
-
- var __updateDesiredFpsValue = function(value) {
- $("stream-desired-fps-value").innerHTML = (value === 0 ? "Unlimited" : value);
- };
-
- var __updateStreamHeader = function(online) {
- var el_grab = document.querySelector("#stream-window-header .window-grab");
- var el_info = $("stream-info");
- if (online) {
- var fps_suffix = (__client_fps >= 0 ? ` / ${__client_fps} fps` : "");
- el_grab.innerHTML = el_info.innerHTML = `Stream &ndash; ${__resolution.width}x${__resolution.height}${fps_suffix}`;
- } else {
- el_grab.innerHTML = el_info.innerHTML = "Stream &ndash; offline";
- }
- };
-
- var __clickScreenshotButton = function() {
- var el_a = document.createElement("a");
- el_a.href = "/streamer/snapshot";
- el_a.target = "_blank";
- document.body.appendChild(el_a);
- el_a.click();
- setTimeout(() => document.body.removeChild(el_a), 0);
- };
-
- var __clickResetButton = function() {
- var http = tools.makeRequest("POST", "/kvmd/streamer/reset", function() {
- if (http.readyState === 4) {
- if (http.status !== 200) {
- wm.error("Can't reset stream:<br>", http.responseText);
- }
- }
- });
- };
-
- var __sendParam = function(name, value) {
- var http = tools.makeRequest("POST", `/kvmd/streamer/set_params?${name}=${value}`, function() {
- if (http.readyState === 4) {
- if (http.status !== 200) {
- wm.error("Can't configure stream:<br>", http.responseText);
- }
- }
- });
- };
-
- var __resize = function(center=false) {
- var size = $("stream-size-slider").value;
- $("stream-size-value").innerHTML = size + "%";
- __size_factor = size / 100;
- __applySizeFactor(center);
- };
-
- var __adjustSizeFactor = function() {
- var el_window = $("stream-window");
- var el_slider = $("stream-size-slider");
- var view = wm.getViewGeometry();
-
- for (var size = 100; size >= el_slider.min; size -= el_slider.step) {
- tools.info("Stream: adjusting size:", size);
- $("stream-size-slider").value = size;
- __resize(true);
-
- var rect = el_window.getBoundingClientRect();
- if (
- rect.bottom <= view.bottom
- && rect.top >= view.top
- && rect.left >= view.left
- && rect.right <= view.right
- ) {
- break;
- }
- }
- };
-
- var __applySizeFactor = function(center=false) {
- var el_stream_image = $("stream-image");
- el_stream_image.style.width = __resolution.width * __size_factor + "px";
- el_stream_image.style.height = __resolution.height * __size_factor + "px";
- wm.showWindow($("stream-window"), false, center);
- };
-
- __init__();
-}
diff --git a/web/js/tools.js b/web/js/tools.js
deleted file mode 100644
index 81970ef8..00000000
--- a/web/js/tools.js
+++ /dev/null
@@ -1,133 +0,0 @@
-var tools = new function() {
- var __debug = (new URL(window.location.href)).searchParams.get("debug");
-
- this.makeRequest = function(method, url, callback, timeout=null) {
- var http = new XMLHttpRequest();
- http.open(method, url, true);
- http.onreadystatechange = callback;
- http.timeout = (timeout ? timeout : 5000);
- http.send();
- return http;
- };
-
- this.makeId = function() {
- var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
- var id = "";
- for (var count = 0; count < 16; ++count) {
- id += chars.charAt(Math.floor(Math.random() * chars.length));
- }
- return id;
- };
-
- this.getCookie = function(name) {
- var matches = document.cookie.match(new RegExp(
- "(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, "\\$1") + "=([^;]*)" // eslint-disable-line no-useless-escape
- ));
- return (matches ? decodeURIComponent(matches[1]) : "");
- };
-
- this.setOnClick = function(el, callback) {
- el.onclick = el.ontouchend = function(event) {
- event.preventDefault();
- callback();
- };
- };
- this.setOnDown = function(el, callback) {
- el.onmousedown = el.ontouchstart = function(event) {
- event.preventDefault();
- callback();
- };
- };
- this.setOnUp = function(el, callback) {
- el.onmouseup = el.ontouchend = function(event) {
- event.preventDefault();
- callback();
- };
- };
-
- this.setOnUpSlider = function(el, delay, display_callback, execute_callback) {
- el.execution_timer = null;
- el.activated = false;
-
- var clear_timer = function() {
- if (el.execution_timer) {
- clearTimeout(el.execution_timer);
- el.execution_timer = null;
- }
- };
-
- el.oninput = el.onchange = () => display_callback(el.value);
-
- el.onmousedown = el.ontouchstart = function() {
- clear_timer();
- el.activated = true;
- };
-
- el.onmouseup = el.ontouchend = function(event) {
- event.preventDefault();
- clear_timer();
- el.execution_timer = setTimeout(function() {
- execute_callback(el.value);
- }, delay);
- };
- };
-
- this.debug = function(...args) {
- if (__debug) {
- console.log("LOG/DEBUG", ...args); // eslint-disable-line no-console
- }
- };
- this.info = (...args) => console.log("LOG/INFO", ...args); // eslint-disable-line no-console
- this.error = (...args) => console.error("LOG/ERROR", ...args); // eslint-disable-line no-console
-
- this.browser = new function() {
- // https://stackoverflow.com/questions/9847580/how-to-detect-safari-chrome-ie-firefox-and-opera-browser/9851769
-
- // Opera 8.0+
- var is_opera = (
- (!!window.opr && !!opr.addons) // eslint-disable-line no-undef
- || !!window.opera
- || (navigator.userAgent.indexOf(" OPR/") >= 0)
- );
-
- // Firefox 1.0+
- var is_firefox = (typeof InstallTrigger !== "undefined");
-
- // Safari 3.0+ "[object HTMLElementConstructor]"
- var is_safari = (/constructor/i.test(window.HTMLElement) || (function (p) {
- return p.toString() === "[object SafariRemoteNotification]";
- })(!window["safari"] || (typeof safari !== "undefined" && safari.pushNotification))); // eslint-disable-line no-undef
-
- // Chrome 1+
- var is_chrome = (!!window.chrome && !!window.chrome.webstore);
-
- // Blink engine detection
- var is_blink = ((is_chrome || is_opera) && !!window.CSS);
-
- // iOS browsers
- // https://stackoverflow.com/questions/9038625/detect-if-device-is-ios
- var is_ios = (!!navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform));
-
- // Any browser on Mac
- var is_mac = ((
- window.navigator.oscpu
- || window.navigator.platform
- || window.navigator.appVersion
- || "Unknown"
- ).indexOf("Mac") !== -1);
-
- return {
- "is_opera": is_opera,
- "is_firefox": is_firefox,
- "is_safari": is_safari,
- "is_chrome": is_chrome,
- "is_blink": is_blink,
- "is_ios": is_ios,
- "is_mac": is_mac,
- };
- };
- this.info("Browser:", this.browser);
-};
-
-var $ = (id) => document.getElementById(id);
-var $$ = (cls) => document.getElementsByClassName(cls);
diff --git a/web/js/wm.js b/web/js/wm.js
deleted file mode 100644
index c292ece7..00000000
--- a/web/js/wm.js
+++ /dev/null
@@ -1,387 +0,0 @@
-function WindowManager() {
- var self = this;
-
- /********************************************************************************/
-
- var __top_z_index = 0;
- var __windows = [];
- var __menu_items = [];
-
- var __init__ = function() {
- Array.prototype.forEach.call(document.querySelectorAll("button"), function(el_button) {
- // XXX: Workaround for iOS Safari:
- // https://stackoverflow.com/questions/3885018/active-pseudo-class-doesnt-work-in-mobile-safari
- el_button.ontouchstart = function() {};
- });
-
- Array.prototype.forEach.call($$("menu-item"), function(el_item) {
- el_item.parentElement.querySelector(".menu-item-content").setAttribute("tabindex", "-1");
- tools.setOnDown(el_item, () => __toggleMenu(el_item));
- __menu_items.push(el_item);
- });
-
- Array.prototype.forEach.call($$("window"), function(el_window) {
- el_window.setAttribute("tabindex", "-1");
- __makeWindowMovable(el_window);
- __windows.push(el_window);
-
- var el_button = el_window.querySelector(".window-header .window-button-close");
- if (el_button) {
- tools.setOnClick(el_button, function() {
- el_window.style.visibility = "hidden";
- __activateLastWindow(el_window);
- });
- }
- });
-
- window.onmouseup = __globalMouseButtonHandler;
- window.ontouchend = __globalMouseButtonHandler;
-
- window.addEventListener("focusin", __focusIn);
- window.addEventListener("focusout", __focusOut);
-
- window.addEventListener("resize", () => __organizeWindowsOnResize(false));
- window.addEventListener("orientationchange", () => __organizeWindowsOnResize(true));
- };
-
- /********************************************************************************/
-
- self.error = (...args) => __modalDialog("Error", args.join(" "), true, false);
- self.confirm = (...args) => __modalDialog("Question", args.join(" "), true, true);
-
- var __modalDialog = function(header, text, ok, cancel) {
- var el_modal = document.createElement("div");
- el_modal.className = "modal";
- el_modal.style.visibility = "visible";
-
- var el_window = document.createElement("div");
- el_window.className = "modal-window";
- el_window.setAttribute("tabindex", "-1");
- el_modal.appendChild(el_window);
-
- var el_header = document.createElement("div");
- el_header.className = "modal-header";
- el_header.innerHTML = header;
- el_window.appendChild(el_header);
-
- var el_content = document.createElement("div");
- el_content.className = "modal-content";
- el_content.innerHTML = text;
- el_window.appendChild(el_content);
-
- var promise = null;
- if (ok || cancel) {
- promise = new Promise(function(resolve) {
- var el_buttons = document.createElement("div");
- el_buttons.className = "modal-buttons";
- el_window.appendChild(el_buttons);
-
- function close(retval) {
- el_window.style.visibility = "hidden";
- el_modal.outerHTML = "";
- var index = __windows.indexOf(el_modal);
- if (index !== -1) {
- __windows.splice(index, 1);
- }
- __activateLastWindow(el_modal);
- resolve(retval);
- }
-
- if (cancel) {
- var el_cancel_button = document.createElement("button");
- el_cancel_button.innerHTML = "Cancel";
- tools.setOnClick(el_cancel_button, () => close(false));
- el_buttons.appendChild(el_cancel_button);
- }
- if (ok) {
- var el_ok_button = document.createElement("button");
- el_ok_button.innerHTML = "OK";
- tools.setOnClick(el_ok_button, () => close(true));
- el_buttons.appendChild(el_ok_button);
- }
- if (ok && cancel) {
- el_ok_button.className = "row50";
- el_cancel_button.className = "row50";
- }
-
- el_window.onkeyup = function(event) {
- event.preventDefault();
- if (ok && event.code === "Enter") {
- el_ok_button.click();
- } else if (cancel && event.code === "Escape") {
- el_cancel_button.click();
- }
- };
- });
- }
-
- __windows.push(el_modal);
- document.body.appendChild(el_modal);
- __activateWindow(el_modal);
-
- return promise;
- };
-
- self.switchDisabled = function(el, disabled) {
- if (disabled && document.activeElement === el) {
- var el_to_focus = (
- el.closest(".modal-window")
- || el.closest(".window")
- || el.closest(".menu-item-content")
- );
- if (el_to_focus) {
- el_to_focus.focus();
- }
- }
- el.disabled = disabled;
- };
-
- self.showWindow = function(el_window, activate=true, center=false) {
- if (!__isWindowOnPage(el_window) || el_window.hasAttribute("data-centered") || center) {
- var view = self.getViewGeometry();
- var rect = el_window.getBoundingClientRect();
-
- el_window.style.top = Math.max($("menu").clientHeight, Math.round((view.bottom - rect.height) / 2)) + "px";
- el_window.style.left = Math.round((view.right - rect.width) / 2) + "px";
- el_window.setAttribute("data-centered", "");
- }
-
- el_window.style.visibility = "visible";
- if (activate) {
- __activateWindow(el_window);
- }
- };
-
- self.getViewGeometry = function() {
- return {
- top: $("menu").clientHeight,
- bottom: Math.max(document.documentElement.clientHeight, window.innerHeight || 0),
- left: 0,
- right: Math.max(document.documentElement.clientWidth, window.innerWidth || 0),
- };
- };
-
- var __isWindowOnPage = function(el_window) {
- var view = self.getViewGeometry();
- var rect = el_window.getBoundingClientRect();
-
- return (
- (rect.bottom - el_window.clientHeight / 1.5) <= view.bottom
- && rect.top >= view.top
- && (rect.left + el_window.clientWidth / 1.5) >= view.left
- && (rect.right - el_window.clientWidth / 1.5) <= view.right
- );
- };
-
- var __toggleMenu = function(el_a) {
- var all_hidden = true;
-
- __menu_items.forEach(function(el_item) {
- var el_menu = el_item.parentElement.querySelector(".menu-item-content");
- if (el_item === el_a && window.getComputedStyle(el_menu, null).visibility === "hidden") {
- el_item.classList.add("menu-item-selected");
- el_menu.style.visibility = "visible";
- el_menu.focus();
- all_hidden &= false;
- } else {
- el_item.classList.remove("menu-item-selected");
- el_menu.style.visibility = "hidden";
- }
- });
-
- if (all_hidden) {
- document.onkeyup = null;
- __activateLastWindow();
- } else {
- document.onkeyup = function(event) {
- if (event.code === "Escape") {
- event.preventDefault();
- __closeAllMenues();
- __activateLastWindow();
- }
- };
- }
- };
-
- var __closeAllMenues = function() {
- document.onkeyup = null;
- __menu_items.forEach(function(el_item) {
- var el_menu = el_item.parentElement.querySelector(".menu-item-content");
- el_item.classList.remove("menu-item-selected");
- el_menu.style.visibility = "hidden";
- });
- };
-
- var __focusIn = function(event) {
- var el_parent;
- if ((el_parent = event.target.closest(".modal-window")) !== null) {
- el_parent.classList.add("window-active");
- } else if ((el_parent = event.target.closest(".window")) !== null) {
- el_parent.classList.add("window-active");
- } else if ((el_parent = event.target.closest(".menu-item-content")) !== null) {
- el_parent.classList.add("menu-item-content-active");
- }
- tools.debug("Focus in:", el_parent);
- };
-
- var __focusOut = function(event) {
- var el_parent;
- if ((el_parent = event.target.closest(".modal-window")) !== null) {
- el_parent.classList.remove("window-active");
- } else if ((el_parent = event.target.closest(".window")) !== null) {
- el_parent.classList.remove("window-active");
- } else if ((el_parent = event.target.closest(".menu-item-content")) !== null) {
- el_parent.classList.remove("menu-item-content-active");
- }
- tools.debug("Focus out:", el_parent);
- };
-
- var __globalMouseButtonHandler = function(event) {
- if (!event.target.matches(".menu-item")) {
- for (var el_item = event.target; el_item && el_item !== document; el_item = el_item.parentNode) {
- if (el_item.hasAttribute("data-force-hide-menu")) {
- break;
- } else if (el_item.hasAttribute("data-dont-hide-menu")) {
- return;
- }
- }
- __closeAllMenues();
- __activateLastWindow();
- }
- };
-
- var __organizeWindowsOnResize = function(orientation) {
- var view = self.getViewGeometry();
-
- Array.prototype.forEach.call($$("window"), function(el_window) {
- if (el_window.style.visibility === "visible" && (orientation || el_window.hasAttribute("data-centered"))) {
- var rect = el_window.getBoundingClientRect();
-
- el_window.style.top = Math.max($("menu").clientHeight, Math.round((view.bottom - rect.height) / 2)) + "px";
- el_window.style.left = Math.round((view.right - rect.width) / 2) + "px";
- el_window.setAttribute("data-centered", "");
- }
- });
- };
-
- var __activateLastWindow = function(el_except_window=null) {
- var el_last_window = null;
-
- if (document.activeElement) {
- el_last_window = (document.activeElement.closest(".modal-window") || document.activeElement.closest(".window"));
- }
-
- if (!el_last_window || el_last_window === el_except_window) {
- var max_z_index = 0;
-
- __windows.forEach(function(el_window) {
- var z_index = parseInt(window.getComputedStyle(el_window, null).zIndex) || 0;
- var visibility = window.getComputedStyle(el_window, null).visibility;
-
- if (max_z_index < z_index && visibility !== "hidden" && el_window !== el_except_window) {
- el_last_window = el_window;
- max_z_index = z_index;
- }
- });
- }
-
- if (el_last_window) {
- tools.debug("Activating last window:", el_last_window);
- __activateWindow(el_last_window);
- }
- };
-
- var __activateWindow = function(el_window) {
- if (window.getComputedStyle(el_window, null).visibility !== "hidden") {
- var el_to_focus;
- var el_window_contains_focus;
-
- if (el_window.className === "modal") {
- el_to_focus = el_window.querySelector(".modal-window");
- el_window_contains_focus = (document.activeElement && document.activeElement.closest(".modal-window"));
- } else { // .window
- el_to_focus = el_window;
- el_window_contains_focus = (document.activeElement && document.activeElement.closest(".window"));
- }
-
- if (el_window.className !== "modal" && parseInt(el_window.style.zIndex) !== __top_z_index) {
- __top_z_index += 1;
- el_window.style.zIndex = __top_z_index;
- tools.debug("UI: activated window:", el_window);
- }
-
- if (el_window !== el_window_contains_focus) {
- el_to_focus.focus();
- tools.debug("UI: focused window:", el_window);
- }
- }
- };
-
- var __makeWindowMovable = function(el_window) {
- var el_header = el_window.querySelector(".window-header");
- var el_grab = el_window.querySelector(".window-header .window-grab");
-
- var prev_pos = {x: 0, y: 0};
-
- function startMoving(event) {
- __closeAllMenues();
- __activateWindow(el_window);
- event = (event || window.event);
- event.preventDefault();
-
- if (!event.touches || event.touches.length === 1) {
- el_header.classList.add("window-header-grabbed");
-
- prev_pos = getEventPosition(event);
-
- document.onmousemove = doMoving;
- document.onmouseup = stopMoving;
-
- document.ontouchmove = doMoving;
- document.ontouchend = stopMoving;
- }
- }
-
- function doMoving(event) {
- el_window.removeAttribute("data-centered");
-
- event = (event || window.event);
- event.preventDefault();
-
- var event_pos = getEventPosition(event);
- var x = prev_pos.x - event_pos.x;
- var y = prev_pos.y - event_pos.y;
-
- el_window.style.top = (el_window.offsetTop - y) + "px";
- el_window.style.left = (el_window.offsetLeft - x) + "px";
-
- prev_pos = event_pos;
- }
-
- function stopMoving() {
- el_header.classList.remove("window-header-grabbed");
-
- document.onmousemove = null;
- document.onmouseup = null;
-
- document.ontouchmove = null;
- document.ontouchend = null;
- }
-
- function getEventPosition(event) {
- if (event.touches) {
- return {x: event.touches[0].clientX, y: event.touches[0].clientY};
- } else {
- return {x: event.clientX, y: event.clientY};
- }
- }
-
- el_window.setAttribute("data-centered", "");
- el_window.onclick = el_window.ontouchend = () => __activateWindow(el_window);
-
- el_grab.onmousedown = startMoving;
- el_grab.ontouchstart = startMoving;
- };
-
- __init__();
-}