// UI Definition var GuacamoleUI = { "display" : document.getElementById("display"), "menu" : document.getElementById("menu"), "menuControl" : document.getElementById("menuControl"), "logo" : document.getElementById("status-logo"), "state" : document.getElementById("state"), "buttons": { "showClipboard": document.getElementById("showClipboard"), "showKeyboard" : document.getElementById("showKeyboard"), "ctrlAltDelete": document.getElementById("ctrlAltDelete"), "reconnect" : document.getElementById("reconnect"), "logout" : document.getElementById("logout") }, "containers": { "error" : document.getElementById("errorDialog"), "clipboard": document.getElementById("clipboardDiv"), "keyboard" : document.getElementById("keyboardContainer") }, "error" : document.getElementById("errorText"), "clipboard" : document.getElementById("clipboard") }; // Constant UI initialization and behavior (function() { var menu_shaded = false; var shade_interval = null; var show_interval = null; // Cache error image (might not be available when error occurs) var guacErrorImage = new Image(); guacErrorImage.src = "images/noguacamole-logo-24.png"; GuacamoleUI.showError = function(error) { GuacamoleUI.menu.className = "error"; GuacamoleUI.display.className += " guac-error"; GuacamoleUI.logo.src = guacErrorImage.src; GuacamoleUI.error.textContent = error; GuacamoleUI.containers.error.style.visibility = "visible"; }; GuacamoleUI.shadeMenu = function() { if (!menu_shaded) { var step = Math.floor(GuacamoleUI.menu.offsetHeight / 10) + 1; var offset = 0; menu_shaded = true; window.clearInterval(show_interval); shade_interval = window.setInterval(function() { offset -= step; GuacamoleUI.menu.style.top = offset + "px"; if (offset <= -GuacamoleUI.menu.offsetHeight) { window.clearInterval(shade_interval); GuacamoleUI.menu.style.visiblity = "hidden"; } }, 30); } }; GuacamoleUI.showMenu = function() { if (menu_shaded) { var step = Math.floor(GuacamoleUI.menu.offsetHeight / 5) + 1; var offset = -GuacamoleUI.menu.offsetHeight; menu_shaded = false; GuacamoleUI.menu.style.visiblity = ""; window.clearInterval(shade_interval); show_interval = window.setInterval(function() { offset += step; if (offset >= 0) { offset = 0; window.clearInterval(show_interval); } GuacamoleUI.menu.style.top = offset + "px"; }, 30); } }; // Show/Hide clipboard GuacamoleUI.buttons.showClipboard.onclick = function() { var displayed = GuacamoleUI.containers.clipboard.style.display; if (displayed != "block") { GuacamoleUI.containers.clipboard.style.display = "block"; GuacamoleUI.buttons.showClipboard.innerHTML = "Hide Clipboard"; } else { GuacamoleUI.containers.clipboard.style.display = "none"; GuacamoleUI.buttons.showClipboard.innerHTML = "Show Clipboard"; GuacamoleUI.clipboard.onchange(); } }; // Show/Hide keyboard GuacamoleUI.buttons.showKeyboard.onclick = function() { var displayed = GuacamoleUI.containers.keyboard.style.display; if (displayed != "block") { GuacamoleUI.containers.keyboard.style.display = "block"; GuacamoleUI.buttons.showKeyboard.textContent = "Hide Keyboard"; } else { GuacamoleUI.containers.keyboard.style.display = "none"; GuacamoleUI.buttons.showKeyboard.textContent = "Show Keyboard"; } }; // Logout GuacamoleUI.buttons.logout.onclick = function() { window.location.href = "logout"; }; // Timeouts for detecting if users wants menu to open or close var detectMenuOpenTimeout = null; var detectMenuCloseTimeout = null; // Clear detection timeouts function resetMenuDetect() { if (detectMenuOpenTimeout != null) { window.clearTimeout(detectMenuOpenTimeout); detectMenuOpenTimeout = null; } if (detectMenuCloseTimeout != null) { window.clearTimeout(detectMenuCloseTimeout); detectMenuCloseTimeout = null; } } // Initiate detection of menu open action. If not canceled through some // user event, menu will open. function startMenuOpenDetect() { // Clear detection state resetMenuDetect(); // Wait and then show menu detectMenuOpenTimeout = window.setTimeout(function() { GuacamoleUI.showMenu(); detectMenuOpenTimeout = null; }, 325); } // Initiate detection of menu close action. If not canceled through some // user event, menu will close. function startMenuCloseDetect() { // Clear detection state resetMenuDetect(); // Wait and then shade menu detectMenuCloseTimeout = window.setTimeout(function() { GuacamoleUI.shadeMenu(); detectMenuCloseTimeout = null; }, 500); } // Show menu if mouseover any part of menu GuacamoleUI.menu.addEventListener('mouseover', GuacamoleUI.showMenu, true); // Stop detecting menu state change intents if mouse is over menu GuacamoleUI.menu.addEventListener('mouseover', resetMenuDetect, true); // When mouse hovers over top of screen, start detection of intent to open menu GuacamoleUI.menuControl.addEventListener('mousemove', startMenuOpenDetect, true); // When mouse enters display, start detection of intent to close menu GuacamoleUI.display.addEventListener('mouseover', startMenuCloseDetect, true); // Show menu if mouse leaves document document.addEventListener('mouseout', function(e) { // Get parent of the element the mouse pointer is leaving if (!e) e = window.event; var target = e.relatedTarget || e.toElement; // Ensure target is not document nor child of document var targetParent = target; while (targetParent != null) { if (targetParent == document) return; targetParent = targetParent.parentNode; } // Start detection of intent to open menu startMenuOpenDetect(); }, true); // Reconnect button GuacamoleUI.buttons.reconnect.onclick = function() { window.location.reload(); }; // On-screen keyboard GuacamoleUI.keyboard = new Guacamole.OnScreenKeyboard("layouts/en-us-qwerty.xml"); GuacamoleUI.containers.keyboard.appendChild(GuacamoleUI.keyboard); })(); // Tie UI events / behavior to a specific Guacamole client GuacamoleUI.attach = function(guac) { // Mouse var mouse = new Guacamole.Mouse(GuacamoleUI.display); mouse.onmousedown = mouse.onmouseup = mouse.onmousemove = function(mouseState) { guac.sendMouseState(mouseState); }; // Keyboard var keyboard = new Guacamole.Keyboard(document); function disableKeyboard() { keyboard.onkeydown = null; keyboard.onkeyup = null; } function enableKeyboard() { keyboard.onkeydown = function (keysym) { guac.sendKeyEvent(1, keysym); }; keyboard.onkeyup = function (keysym) { guac.sendKeyEvent(0, keysym); }; } // Enable keyboard by default enableKeyboard(); // Handle client state change guac.onstatechange = function(clientState) { switch (clientState) { // Idle case 0: GuacamoleUI.state.textContent = "Idle." break; // Connecting case 1: GuacamoleUI.state.textContent = "Connecting..."; break; // Connected + waiting case 2: GuacamoleUI.state.textContent = "Connected, waiting for first update..."; break; // Connected case 3: GuacamoleUI.display.className = GuacamoleUI.display.className.replace(/guac-loading/, ''); GuacamoleUI.menu.className = "connected"; GuacamoleUI.state.textContent = "Connected."; GuacamoleUI.shadeMenu(); break; // Disconnecting case 4: GuacamoleUI.state.textContent = "Disconnecting..."; break; // Disconnected case 5: GuacamoleUI.state.textContent = "Disconnected."; break; // Unknown status code default: GuacamoleUI.state.textContent = "Unknown"; } }; // Name instruction handler guac.onname = function(name) { document.title = name; }; // Error handler guac.onerror = function(error) { // Disconnect, if connected guac.disconnect(); // Display error message GuacamoleUI.showError(error); // Show error by desaturating display var layers = guac.getLayers(); for (var i=0; i