diff --git a/WebPanel/WebPanel1/index.html b/WebPanel/WebPanel1/index.html
new file mode 100644
index 00000000..a6ebb489
--- /dev/null
+++ b/WebPanel/WebPanel1/index.html
@@ -0,0 +1,342 @@
+
+
+
+
+ A320 MCDU
+
+
+
+
+
+
+
+
+
+
+
+
+
|
+ |
+
|
+
+
+ — |
+ — |
+
+
+ — |
+ — |
+
+
+ — |
+ — |
+
+
+ — |
+ — |
+
+
+ — |
+ — |
+
+
+ — |
+ — |
+
+
+
|
+
|
+
+
+
+
+
+
+ AIR PORT |
+ |
+
+
+ ← |
+ ↑ |
+
+
+ → |
+ ↓ |
+
+
+
+
+
+
\ No newline at end of file
diff --git a/WebPanel/WebPanel1/screenshot.jpg b/WebPanel/WebPanel1/screenshot.jpg
new file mode 100644
index 00000000..a1cce228
Binary files /dev/null and b/WebPanel/WebPanel1/screenshot.jpg differ
diff --git a/WebPanel/WebPanel2/css/mcdu.css b/WebPanel/WebPanel2/css/mcdu.css
new file mode 100644
index 00000000..cb35fcb4
--- /dev/null
+++ b/WebPanel/WebPanel2/css/mcdu.css
@@ -0,0 +1,281 @@
+* {
+ -webkit-touch-callout: none;
+ -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
+ -webkit-text-size-adjust: none;
+ text-size-adjust: none;
+ -webkit-user-select: none;
+ user-select: none;
+}
+
+html, body {
+ overscroll-behavior-y: none;
+ position: fixed;
+ overflow: hidden;
+}
+
+body {
+ width: calc(100vw - 2px);
+ height: calc(100vh - 2px);
+ margin-left: 1px;
+ overflow: hidden;
+ background-color: #000;
+}
+
+.mcdu {
+ width: 100vw;
+ height: calc(100vw / .6);
+ max-height: 100vh;
+ max-width: calc(100vh * .6);
+ position: absolute;
+ margin: auto;
+ top: 0;
+ left: 0;
+ right: 0;
+}
+
+.mcdu_case {
+ display: block;
+ width: 100%;
+ height: auto;
+}
+
+.mcdu-glass {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ z-index: -1;
+ overflow: hidden;
+}
+
+.mcdu-glass--dust {
+ display: none;
+ position: absolute;
+ top: 6%;
+ left: 13%;
+ width: 73.5%;
+ opacity: 0.5;
+ transform: scale(1, -1);
+ filter: blur(0.1vh);
+}
+
+[data-used-universe="1"] .mcdu-glass--dust {
+ display: inline-block;
+}
+
+.screen-img,
+.screen-glow {
+ position: absolute;
+ top: 7.5%;
+ left: 13.4%;
+ width: 72.8%;
+}
+
+.screen-glow {
+ display: none;
+}
+
+[data-used-universe="1"] .screen-glow {
+ display: inline-block;
+ filter: brightness(50) blur(0.2vh);
+ opacity: 0.15;
+}
+
+
+.mcdu-fg {
+ position: absolute;
+ top: 0.3%;
+ left: 0;
+ width: 100%;
+ height: 100%;
+}
+
+[data-button] {
+ position: absolute;
+ cursor: pointer;
+}
+
+[data-showbuttons="1"] [data-button] {
+ background-color: red;
+ opacity: 0.5;
+}
+
+.glassbutton {
+ top: 6%;
+ left: 13%;
+ width: 73.5%;
+ height: 40%
+}
+
+.skbutton {
+ width: 7.7%;
+ height: 3.3%;
+ border-radius: 0.2vh;
+}
+
+.menubutton {
+ width: 9.8%;
+ height: 4%;
+ border-radius: 0.2vh;
+}
+
+.numberbutton {
+ width: 7.5%;
+ padding-bottom: 7.5%;
+ border-radius: 50%;
+}
+
+.alphabutton {
+ width: 7.4%;
+ padding-bottom: 7.4%;
+ border-radius: 0.2vh;
+}
+
+.skbuttons-left .skbutton {
+ left: 1.6%;
+}
+
+.skbuttons-right .skbutton {
+ right: 2.1%;
+}
+
+.sk-1 {
+ top: 12.3%;
+}
+
+.sk-2 {
+ top: 17.34%;
+}
+
+.sk-3 {
+ top: 22.4%;
+}
+
+.sk-4 {
+ top: 27.4%;
+}
+
+.sk-5 {
+ top: 32.5%;
+}
+
+.sk-6 {
+ top: 37.6%;
+}
+
+.menu-row1 .menubutton {
+ top: 48.2%;
+}
+
+.menu-row2 .menubutton {
+ top: 53.04%;
+}
+
+.menu-row3 .menubutton {
+ top: 57.9%;
+}
+
+.menu-row4 .menubutton {
+ top: 62.8%;
+}
+
+.menu-row5 .menubutton {
+ top: 67.6%;
+}
+
+.menu-col1 {
+ left: 11.3%;
+}
+
+.menu-col2 {
+ left: 23.2%;
+}
+
+.menu-col3 {
+ left: 35.1%;
+}
+
+.menu-col4 {
+ left: 47%;
+}
+
+.menu-col5 {
+ left: 59%;
+}
+
+.menu-col6 {
+ left: 70.95%;
+}
+
+.number-row1 .numberbutton {
+ top: 73.9%;
+}
+
+.number-row2 .numberbutton {
+ top: 79.6%;
+}
+
+.number-row3 .numberbutton {
+ top: 85.3%;
+}
+
+.number-row4 .numberbutton {
+ top: 91%;
+}
+
+.number-col1 {
+ left: 11.5%;
+}
+
+.number-col2 {
+ left: 21.1%;
+}
+
+.number-col3 {
+ left: 30.6%;
+}
+
+.alphabutton-row1 .alphabutton {
+ top: 59.5%;
+}
+
+.alphabutton-row2 .alphabutton {
+ top: 65.8%;
+}
+
+.alphabutton-row3 .alphabutton {
+ top: 72.1%;
+}
+
+.alphabutton-row4 .alphabutton {
+ top: 78.4%;
+}
+
+.alphabutton-row5 .alphabutton {
+ top: 84.8%;
+}
+
+.alphabutton-row6 .alphabutton {
+ top: 91.1%;
+}
+
+.alphabutton-col1 {
+ left: 40.6%;
+}
+
+.alphabutton-col2 {
+ left: 50.7%;
+}
+
+.alphabutton-col3 {
+ left: 60.7%;
+}
+
+.alphabutton-col4 {
+ left: 70.7%;
+}
+
+.alphabutton-col5 {
+ left: 80.7%;
+}
diff --git a/WebPanel/WebPanel2/img/dust2.png b/WebPanel/WebPanel2/img/dust2.png
new file mode 100644
index 00000000..1312976c
Binary files /dev/null and b/WebPanel/WebPanel2/img/dust2.png differ
diff --git a/WebPanel/WebPanel2/img/mcdu-bg.png b/WebPanel/WebPanel2/img/mcdu-bg.png
new file mode 100644
index 00000000..9401284f
Binary files /dev/null and b/WebPanel/WebPanel2/img/mcdu-bg.png differ
diff --git a/WebPanel/WebPanel2/img/screenshot.jpg b/WebPanel/WebPanel2/img/screenshot.jpg
new file mode 100644
index 00000000..369e24c2
Binary files /dev/null and b/WebPanel/WebPanel2/img/screenshot.jpg differ
diff --git a/WebPanel/WebPanel2/index.html b/WebPanel/WebPanel2/index.html
new file mode 100644
index 00000000..c3214b3a
--- /dev/null
+++ b/WebPanel/WebPanel2/index.html
@@ -0,0 +1,146 @@
+
+
+
+ A320 MCDU
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WebPanel/WebPanel2/js/mcdu.js b/WebPanel/WebPanel2/js/mcdu.js
new file mode 100644
index 00000000..11944742
--- /dev/null
+++ b/WebPanel/WebPanel2/js/mcdu.js
@@ -0,0 +1,185 @@
+const MCDU = (function () {
+ const screenImageBaseUrl = '/screenshot?canvasindex=10&type=jpg';
+ const refreshInterval = 2000;
+
+ const body = document.body;
+ let currentCacheBust = 0;
+ let lastSentText = '';
+
+ init();
+
+ return {
+ toggleUsedUniverse
+ }
+
+////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////
+
+ function init()
+ {
+ body.dataset.lastTouch = 0;
+ body.addEventListener('touchstart', preventZoomAction, { passive: false });
+
+ registerButtons();
+ registerKeyboardInput();
+ setInterval(refreshScreen, refreshInterval);
+ refreshScreen();
+ }
+
+ function refreshScreen() {
+ loadScreenImage(screenImageBaseUrl)
+ .then(setScreenSrc)
+ .catch(setScreenSrc);
+ }
+
+ function setScreenSrc(url) {
+ url = typeof url === 'string' ? url : '';
+ showScreenImageLoadState(url !== '');
+ document.querySelectorAll('[data-element="lcdimage"]').forEach((imageElement) => {
+ imageElement.src = url;
+ });
+ }
+
+ function loadScreenImage(baseUrl) {
+ currentCacheBust = new Date().getTime();
+ return new Promise((resolve, reject) => {
+ const url = baseUrl + '?cacheBust=' + currentCacheBust;
+ const img = new Image;
+
+ img.addEventListener('error', reject);
+
+ img.addEventListener('load', (event) => {
+ showScreenImageLoadState(true);
+ resolve(url);
+ });
+ img.src = url;
+ });
+ }
+
+ function showScreenImageLoadState(isOK) {
+ if (!isOK) {
+ console.log('fail');
+ }
+ }
+
+ function toggleUsedUniverse() {
+ body.setAttribute('data-used-universe', body.getAttribute('data-used-universe') === '1' ? '0' : '1');
+ }
+
+ function registerButtons() {
+ document.querySelectorAll('[data-button]').forEach((buttonElement) => {
+ const buttonFunction = getButtonFunction(buttonElement);
+ if (!(typeof buttonFunction === 'function')) {
+ return;
+ }
+ buttonElement.addEventListener('click', buttonFunction);
+ buttonElement.addEventListener('touchstart', preventZoomAction, true);
+ });
+ }
+
+ function registerKeyboardInput() {
+ const keyTranslation = {
+ BACKSPACE: 'CLR'
+ };
+ body.addEventListener('keyup', (event) => {
+ const key = event.key.toUpperCase();
+ if (key.match(/^[A-Z0-9/\-+.\ ]$/)) {
+ if (key === '+' || key === '-') {
+ return sendPlusMinusKey();
+ }
+ return sendButtonpress('button', key);
+ }
+
+ const translatedKey = keyTranslation[key];
+ if (translatedKey) {
+ return sendButtonpress('button', translatedKey);
+ }
+ });
+ }
+
+ function getButtonFunction(buttonElement) {
+ const buttonActions = buttonElement.getAttribute('data-button').split(':');
+ const actionKey = buttonActions[0];
+ const actionValue = buttonActions[1];
+
+ if(!actionKey) {
+ return;
+ }
+
+ if (actionKey === 'toggleUsedUniverse') {
+ return toggleUsedUniverse;
+ }
+
+ if (actionKey === 'button' && actionValue === '-') {
+ return sendPlusMinusKey;
+ }
+
+ return function () {
+ sendButtonpress(actionKey, actionValue);
+ };
+ }
+
+ function sendPlusMinusKey() {
+ if (lastSentText === '-') {
+ sendButtonpress('button', 'CLR')
+ .then(() => {
+ sendButtonpress('button', '+');
+ })
+ return;
+ }
+
+ if (lastSentText === '+') {
+ sendButtonpress('button', 'CLR')
+ .then(() => {
+ sendButtonpress('button', '-');
+ })
+ return;
+ }
+
+ sendButtonpress('button', '-');
+ }
+
+ function sendButtonpress(type, text) {
+ // console.log({ type, text });
+ let request = new XMLHttpRequest;
+ request.open("POST", "/run.cgi?value=nasal");
+ request.setRequestHeader("Content-Type", "application/json");
+ let body = JSON.stringify({
+ "name": "",
+ "children": [
+ {
+ "name": "script",
+ "index": 0,
+ "value": "mcdu." + type + "(\"" + text + "\", 0);"
+ }
+ ]
+ });
+ request.send(body);
+ return new Promise((resolve) => {
+ request.addEventListener('load', () => {
+ lastSentText = text;
+ refreshScreen();
+ resolve();
+ }, true);
+ });
+ }
+
+ //https://exceptionshub.com/disable-double-tap-zoom-option-in-browser-on-touch-devices.html
+ function preventZoomAction(event) {
+ const t2 = event.timeStamp;
+ const touchedElement = event.currentTarget;
+ const t1 = touchedElement.dataset.lastTouch || t2;
+ const dt = t2 - t1;
+ const fingers = event.touches.length;
+ touchedElement.dataset.lastTouch = t2;
+
+ if (!dt || dt > 500 || fingers > 1) {
+ // no double-tap
+ return;
+ }
+
+ event.preventDefault();
+ event.target.click();
+ }
+})();
diff --git a/WebPanel/mcdu.html b/WebPanel/mcdu.html
index a6ebb489..264131af 100644
--- a/WebPanel/mcdu.html
+++ b/WebPanel/mcdu.html
@@ -1,342 +1,116 @@
-
-
-
-
- A320 MCDU
-
-
-
-
-
-
-
-
-
-
-
-
-
|
- |
-
|
-
-
- — |
- — |
-
-
- — |
- — |
-
-
- — |
- — |
-
-
- — |
- — |
-
-
- — |
- — |
-
-
- — |
- — |
-
-
-
|
-
|
-
-
-
-
-
-
- AIR PORT |
- |
-
-
- ← |
- ↑ |
-
-
- → |
- ↓ |
-
-
-
-
-
+
+
+
+
+ A320 MCDU
+
+
+
+
+
+
+
+
+ Web MCDU
+ Please choose:
+
+
+
\ No newline at end of file