1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2024-12-24 23:25:24 +00:00

Unified VNC/SPICE console interfaces with bootstrap

This commit is contained in:
Benjamin Renard 2016-04-18 00:25:46 +02:00
parent 2f63d35804
commit 69b955261f
3 changed files with 374 additions and 388 deletions

View file

@ -0,0 +1,127 @@
{% load i18n %}
<html>
<head>
<meta charset="utf-8">
<link rel="shortcut icon" href="{{ STATIC_URL }}img/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="{{ STATIC_URL }}css/bootstrap.min.css">
<link href="{{ STATIC_URL }}css/webvirtcloud.css" rel="stylesheet">
<style>
body {
margin: 0;
padding: 0;
background-color: #313131;
}
.navbar {
margin-bottom: 2px;
}
#main_container {
padding: 0;
width: 100%;
max-width: none;
height: 100%;
background-color:#494949;
border-bottom-right-radius: 800px 600px;
}
#main_container canvas {
padding-left: 0;
padding-right: 0;
margin-left: auto;
margin-right: auto;
display: block;
margin: auto;
}
#status {
z-index: 10000;
width: 80%;
position: absolute;
top: 5px;
left: 10%;
text-align: center;
}
</style>
{% block head %}{% endblock %}
</head>
<body>
<nav class="navbar navbar-inverse navbar-static-top" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand">{{ instance.name }}</a>
</div>
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">Send key(s) <span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li onclick='sendCtrlAltDel();'><a href='#'>Ctrl+Alt+Del</a></li>
<li class="divider"></li>
<li onclick='sendCtrlAltFN(0);'><a href='#'>Ctrl+Alt+F1</a></li>
<li onclick='sendCtrlAltFN(1);'><a href='#'>Ctrl+Alt+F2</a></li>
<li onclick='sendCtrlAltFN(2);'><a href='#'>Ctrl+Alt+F3</a></li>
<li onclick='sendCtrlAltFN(3);'><a href='#'>Ctrl+Alt+F4</a></li>
<li onclick='sendCtrlAltFN(4);'><a href='#'>Ctrl+Alt+F5</a></li>
<li onclick='sendCtrlAltFN(5);'><a href='#'>Ctrl+Alt+F6</a></li>
<li onclick='sendCtrlAltFN(6);'><a href='#'>Ctrl+Alt+F7</a></li>
<li onclick='sendCtrlAltFN(7);'><a href='#'>Ctrl+Alt+F8</a></li>
<li onclick='sendCtrlAltFN(8);'><a href='#'>Ctrl+Alt+F9</a></li>
<li onclick='sendCtrlAltFN(9);'><a href='#'>Ctrl+Alt+F10</a></li>
<li onclick='sendCtrlAltFN(10);'><a href='#'>Ctrl+Alt+F11</a></li>
<li onclick='sendCtrlAltFN(11);'><a href='#'>Ctrl+Alt+F12</a></li>
</ul>
</li>
<li onclick='fullscreen()'><a href='#'>{% trans "Fullscreen" %}</a></li>
{% block navbarmenu %}{% endblock %}
</ul>
</div>
</div>
</nav>
<div id='main_container' class="container">
{% block content %}{% endblock %}
</div>
<script src="{{ STATIC_URL }}js/jquery.js"></script>
<script src="{{ STATIC_URL }}js/bootstrap.min.js"></script>
<script>
function log_message(msg,type) {
var exist=$('#status').is('div');
status_div=$('<div id="status" class="alert alert-'+type+' role="alert"><button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>'+msg+'</div>');
if (exist) {
$('#status').remove();
$('body').prepend(status_div);
}
else {
status_div.hide();
$('body').prepend(status_div);
status_div.fadeIn(200);
}
if (type!='danger') {
status_div.delay(3000).fadeOut(200);
}
}
function log_error(msg) {
log_message(msg,'danger');
}
function log_info(msg) {
log_message(msg,'info');
}
</script>
{% block foot %}{% endblock %}
</body>
</html>

View file

@ -1,333 +1,194 @@
{% extends "console-base.html" %}
{% load i18n %} {% load i18n %}
<html> {% load staticfiles %}
<head> {% block head %}
<link rel="shortcut icon" href="{{ STATIC_URL }}img/favicon.ico"> <script src="{% static "js/spice-html5/spicearraybuffer.js" %}"></script>
<script src="{{ STATIC_URL }}js/spice-html5/spicearraybuffer.js"></script> <script src="{% static "js/spice-html5/enums.js" %}"></script>
<script src="{{ STATIC_URL }}js/spice-html5/enums.js"></script> <script src="{% static "js/spice-html5/atKeynames.js" %}"></script>
<script src="{{ STATIC_URL }}js/spice-html5/atKeynames.js"></script> <script src="{% static "js/spice-html5/utils.js" %}"></script>
<script src="{{ STATIC_URL }}js/spice-html5/utils.js"></script> <script src="{% static "js/spice-html5/png.js" %}"></script>
<script src="{{ STATIC_URL }}js/spice-html5/png.js"></script> <script src="{% static "js/spice-html5/lz.js" %}"></script>
<script src="{{ STATIC_URL }}js/spice-html5/lz.js"></script> <script src="{% static "js/spice-html5/quic.js" %}"></script>
<script src="{{ STATIC_URL }}js/spice-html5/quic.js"></script> <script src="{% static "js/spice-html5/bitmap.js" %}"></script>
<script src="{{ STATIC_URL }}js/spice-html5/bitmap.js"></script> <script src="{% static "js/spice-html5/spicedataview.js" %}"></script>
<script src="{{ STATIC_URL }}js/spice-html5/spicedataview.js"></script> <script src="{% static "js/spice-html5/spicetype.js" %}"></script>
<script src="{{ STATIC_URL }}js/spice-html5/spicetype.js"></script> <script src="{% static "js/spice-html5/spicemsg.js" %}"></script>
<script src="{{ STATIC_URL }}js/spice-html5/spicemsg.js"></script> <script src="{% static "js/spice-html5/wire.js" %}"></script>
<script src="{{ STATIC_URL }}js/spice-html5/wire.js"></script> <script src="{% static "js/spice-html5/spiceconn.js" %}"></script>
<script src="{{ STATIC_URL }}js/spice-html5/spiceconn.js"></script> <script src="{% static "js/spice-html5/display.js" %}"></script>
<script src="{{ STATIC_URL }}js/spice-html5/display.js"></script> <script src="{% static "js/spice-html5/main.js" %}"></script>
<script src="{{ STATIC_URL }}js/spice-html5/main.js"></script> <script src="{% static "js/spice-html5/inputs.js" %}"></script>
<script src="{{ STATIC_URL }}js/spice-html5/inputs.js"></script> <script src="{% static "js/spice-html5/webm.js" %}"></script>
<script src="{{ STATIC_URL }}js/spice-html5/webm.js"></script> <script src="{% static "js/spice-html5/playback.js" %}"></script>
<script src="{{ STATIC_URL }}js/spice-html5/playback.js"></script> <script src="{% static "js/spice-html5/simulatecursor.js" %}"></script>
<script src="{{ STATIC_URL }}js/spice-html5/simulatecursor.js"></script> <script src="{% static "js/spice-html5/cursor.js" %}"></script>
<script src="{{ STATIC_URL }}js/spice-html5/cursor.js"></script> <script src="{% static "js/spice-html5/thirdparty/jsbn.js" %}"></script>
<script src="{{ STATIC_URL }}js/spice-html5/thirdparty/jsbn.js"></script> <script src="{% static "js/spice-html5/thirdparty/rsa.js" %}"></script>
<script src="{{ STATIC_URL }}js/spice-html5/thirdparty/rsa.js"></script> <script src="{% static "js/spice-html5/thirdparty/prng4.js" %}"></script>
<script src="{{ STATIC_URL }}js/spice-html5/thirdparty/prng4.js"></script> <script src="{% static "js/spice-html5/thirdparty/rng.js" %}"></script>
<script src="{{ STATIC_URL }}js/spice-html5/thirdparty/rng.js"></script> <script src="{% static "js/spice-html5/thirdparty/sha1.js" %}"></script>
<script src="{{ STATIC_URL }}js/spice-html5/thirdparty/sha1.js"></script> <script src="{% static "js/spice-html5/ticket.js" %}"></script>
<script src="{{ STATIC_URL }}js/spice-html5/ticket.js"></script> <script src="{% static "js/spice-html5/resize.js" %}"></script>
<script src="{{ STATIC_URL }}js/spice-html5/resize.js"></script> <script src="{% static "js/spice-html5/filexfer.js" %}"></script>
<script src="{{ STATIC_URL }}js/spice-html5/filexfer.js"></script>
<style> {% endblock %}
body {
margin: 0; {% block content %}
padding: 0; <div id='spice_container'></div>
font-family: Helvetica; {% endblock %}
background-color:#494949;
{% block foot %}
<script>
var sc;
function spice_set_cookie(name, value, days) {
var date, expires;
date = new Date();
date.setTime(date.getTime() + (days*24*60*60*1000));
expires = "; expires=" + date.toGMTString();
document.cookie = name + "=" + value + expires + "; path=/";
};
function spice_query_var(name, defvalue) {
var match = RegExp('[?&]' + name + '=([^&]*)')
.exec(window.location.search);
return match ?
decodeURIComponent(match[1].replace(/\+/g, ' '))
: defvalue;
}
function spice_error(e)
{
console.log(e);
disconnect();
if (e.message != undefined) {
log_error(e.message);
}
else {
log_error('Unknown error');
}
}
function spice_success(msg) {
log_info(msg);
}
function connect(uri,password)
{
// If a token variable is passed in, set the parameter in a cookie.
// This is used by nova-spiceproxy.
token = spice_query_var('token', null);
if (token) {
spice_set_cookie('token', token, 1)
} }
#status { if (sc) {
text-align: center; sc.stop();
width: 100%;
margin: 0;
font-size: 1em;
height: 1.6em;
padding-top: 0.3em;
background-color: #222;
} }
#spice-area { try
border-bottom-right-radius: 800px 600px; {
background-color: #313131; sc = new SpiceMainConn({uri: uri, password: password, screen_id: "spice_container",
height: 100%; onsuccess: spice_success, onerror: spice_error, onagent: agent_connected });
}
catch (e)
{
console.log(e);
log_error(e.toString());
disconnect();
} }
#spice-screen canvas { }
padding-left: 0;
padding-right: 0; function disconnect()
margin-left: auto; {
margin-right: auto; console.log(">> disconnect");
display: block; if (sc) {
sc.stop();
} }
if (window.File && window.FileReader && window.FileList && window.Blob)
#spice-menu { {
list-style-type: none; console.log(" -> Disable drag/drop transfer");
margin: 0px; var spice_xfer_area = document.getElementById('spice-xfer-area');
padding: 0px; try {
border: 0px none; document.getElementById('spice-area').removeChild(spice_xfer_area);
position: absolute; document.getElementById('spice-area').removeEventListener('dragover', handle_file_dragover, false);
top: 0px; document.getElementById('spice-area').removeEventListener('drop', handle_file_drop, false);
z-index: 100; }
catch(e) {
console.log(' -> Error disabling drag/drop transfer');
}
} }
console.log("<< disconnect");
}
#spice-menu li { function agent_connected(sc) {
width: auto; window.addEventListener('resize', handle_resize);
float: left; window.spice_connection = this;
margin: 2px;
padding: 0px; resize_helper(this);
border: 0px none;
position: relative; if (window.File && window.FileReader && window.FileList && window.Blob)
height: 18px; {
cursor: pointer; var spice_xfer_area = document.createElement("div");
padding: 0.2em; spice_xfer_area.setAttribute('id', 'spice-xfer-area');
background: #eee; document.getElementById('spice-area').addEventListener('dragover', handle_file_dragover, false);
border-radius: 3px; document.getElementById('spice-area').addEventListener('drop', handle_file_drop, false);
log_info('Drag and drop transfer enabled.');
} }
else
#spice-menu .spice-submenu { {
display: none; console.log("File API is not supported");
opacity: 0; log_info('Drag and drop transfer not supported.');
list-style-type: none;
margin: 0;
padding: 0;
border: 0;
overflow: hidden;
position: absolute;
} }
}
#spice-menu .spice-submenu li { function sendCtrlAltFN(f) {
float: none; if (sc && sc.inputs && sc.inputs.state === "ready"){
margin: 0; var keys_code=[KEY_F1,KEY_F2,KEY_F3,KEY_F4,KEY_F5,KEY_F6,KEY_F7,KEY_F8,KEY_F9,KEY_F10,KEY_F11,KEY_F12];
padding: 0;
border: 0; if (keys_code[f]==undefined) {
border-top: 1px solid white; return;
border-right: 1px solid white; }
font: normal 14px sans-serif; var key = new SpiceMsgcKeyDown();
z-index: 100; var msg = new SpiceMiniData();
white-space: nowrap;
min-width: 100px; update_modifier(true, KEY_LCtrl, sc);
padding: 0.2em; update_modifier(true, KEY_Alt, sc);
border-radius: 0;
key.code = keys_code[f];
msg.build_msg(SPICE_MSGC_INPUTS_KEY_DOWN, key);
sc.inputs.send_msg(msg);
msg.build_msg(SPICE_MSGC_INPUTS_KEY_UP, key);
sc.inputs.send_msg(msg);
if(Ctrl_state == false) update_modifier(false, KEY_LCtrl, sc);
if(Alt_state == false) update_modifier(false, KEY_Alt, sc);
} }
}
#spice-menu li:hover > .spice-submenu { function fullscreen() {
opacity: 1; var screen=document.getElementById('spice_container');
display: block; if(screen.requestFullscreen) {
margin: 2px 0 0 -2px; screen.requestFullscreen();
} else if(screen.mozRequestFullScreen) {
screen.mozRequestFullScreen();
} else if(screen.webkitRequestFullscreen) {
screen.webkitRequestFullscreen();
} else if(screen.msRequestFullscreen) {
screen.msRequestFullscreen();
} }
}
#spice-menu li:hover > .spice-submenu li { var uri;
height: auto; if (window.location.protocol === "https:") {
} uri = 'wss://{{ ws_host }}:{{ ws_port }}';
</style> } else {
</head> uri = 'ws://{{ ws_host }}:{{ ws_port }}';
<body> }
<div id="header">
<ul id='spice-menu'>
<li>Send key(s)
<ul class='spice-submenu'>
<li onclick='sendCtrlAltDel();'>Ctrl+Alt+Del</li>
<li onclick='sendCtrlAltFN(0);'>Ctrl+Alt+F1</li>
<li onclick='sendCtrlAltFN(1);'>Ctrl+Alt+F2</li>
<li onclick='sendCtrlAltFN(2);'>Ctrl+Alt+F3</li>
<li onclick='sendCtrlAltFN(3);'>Ctrl+Alt+F4</li>
<li onclick='sendCtrlAltFN(4);'>Ctrl+Alt+F5</li>
<li onclick='sendCtrlAltFN(5);'>Ctrl+Alt+F6</li>
<li onclick='sendCtrlAltFN(6);'>Ctrl+Alt+F7</li>
<li onclick='sendCtrlAltFN(7);'>Ctrl+Alt+F8</li>
<li onclick='sendCtrlAltFN(8);'>Ctrl+Alt+F9</li>
<li onclick='sendCtrlAltFN(9);'>Ctrl+Alt+F10</li>
<li onclick='sendCtrlAltFN(10);'>Ctrl+Alt+F11</li>
<li onclick='sendCtrlAltFN(11);'>Ctrl+Alt+F12</li>
</ul>
</li>
<li onclick='fullscreen()'>Fullscreen</li>
</ul>
<div id="status"></div>
</div>
<div id="spice-area">
<div id="spice-screen" class="spice-screen"></div>
</div>
<script> var password = '{{ console_passwd }}';
var sc; log_info('Connecting ...');
connect(uri,password);
function spice_set_cookie(name, value, days) { </script>
var date, expires; {% endblock %}
date = new Date();
date.setTime(date.getTime() + (days*24*60*60*1000));
expires = "; expires=" + date.toGMTString();
document.cookie = name + "=" + value + expires + "; path=/";
};
function spice_query_var(name, defvalue) {
var match = RegExp('[?&]' + name + '=([^&]*)')
.exec(window.location.search);
return match ?
decodeURIComponent(match[1].replace(/\+/g, ' '))
: defvalue;
}
var status_div=false;
function log_message(msg,color,bgcolor) {
if (!status_div) {
status_div=document.getElementById('status');
}
status_div.innerHTML=msg;
if (color) {
status_div.style.color=color;
}
if (bgcolor) {
status_div.style.backgroundColor=bgcolor;
}
}
function log_error(msg) {
log_message(msg,'#000','#f44');
}
function log_info(msg) {
log_message(msg,'#000','#eee');
}
function spice_error(e)
{
console.log(e);
disconnect();
if (e.message != undefined) {
log_error(e.message);
}
else {
log_error('Unknown error');
}
}
function spice_success(msg) {
log_info(msg);
}
function connect(uri,password)
{
// If a token variable is passed in, set the parameter in a cookie.
// This is used by nova-spiceproxy.
token = spice_query_var('token', null);
if (token) {
spice_set_cookie('token', token, 1)
}
if (sc) {
sc.stop();
}
try
{
sc = new SpiceMainConn({uri: uri, password: password, screen_id: "spice-screen",
onsuccess: spice_success, onerror: spice_error, onagent: agent_connected });
}
catch (e)
{
console.log(e);
log_error(e.toString());
disconnect();
}
}
function disconnect()
{
console.log(">> disconnect");
if (sc) {
sc.stop();
}
if (window.File && window.FileReader && window.FileList && window.Blob)
{
console.log(" -> Disable drag/drop transfer");
var spice_xfer_area = document.getElementById('spice-xfer-area');
try {
document.getElementById('spice-area').removeChild(spice_xfer_area);
document.getElementById('spice-area').removeEventListener('dragover', handle_file_dragover, false);
document.getElementById('spice-area').removeEventListener('drop', handle_file_drop, false);
}
catch(e) {
console.log(' -> Error disabling drag/drop transfer');
}
}
console.log("<< disconnect");
}
function agent_connected(sc) {
console.log('Connected');
window.addEventListener('resize', handle_resize);
window.spice_connection = this;
resize_helper(this);
if (window.File && window.FileReader && window.FileList && window.Blob)
{
var spice_xfer_area = document.createElement("div");
spice_xfer_area.setAttribute('id', 'spice-xfer-area');
document.getElementById('spice-area').addEventListener('dragover', handle_file_dragover, false);
document.getElementById('spice-area').addEventListener('drop', handle_file_drop, false);
log_info('Drag and drop transfer enabled.');
}
else
{
console.log("File API is not supported");
log_info('Drag and drop transfer not supported.');
}
log_info('Connected');
}
function sendCtrlAltFN(f) {
if (sc && sc.inputs && sc.inputs.state === "ready"){
var keys_code=[KEY_F1,KEY_F2,KEY_F3,KEY_F4,KEY_F5,KEY_F6,KEY_F7,KEY_F8,KEY_F9,KEY_F10,KEY_F11,KEY_F12];
if (keys_code[f]==undefined) {
return;
}
var key = new SpiceMsgcKeyDown();
var msg = new SpiceMiniData();
update_modifier(true, KEY_LCtrl, sc);
update_modifier(true, KEY_Alt, sc);
key.code = keys_code[f];
msg.build_msg(SPICE_MSGC_INPUTS_KEY_DOWN, key);
sc.inputs.send_msg(msg);
msg.build_msg(SPICE_MSGC_INPUTS_KEY_UP, key);
sc.inputs.send_msg(msg);
if(Ctrl_state == false) update_modifier(false, KEY_LCtrl, sc);
if(Alt_state == false) update_modifier(false, KEY_Alt, sc);
}
}
function fullscreen() {
var screen=document.getElementById('spice-screen');
if(screen.requestFullscreen) {
screen.requestFullscreen();
} else if(screen.mozRequestFullScreen) {
screen.mozRequestFullScreen();
} else if(screen.webkitRequestFullscreen) {
screen.webkitRequestFullscreen();
} else if(screen.msRequestFullscreen) {
screen.msRequestFullscreen();
}
}
var uri;
if (window.location.protocol === "https:") {
uri = 'wss://{{ ws_host }}:{{ ws_port }}';
} else {
uri = 'ws://{{ ws_host }}:{{ ws_port }}';
}
var password = '{{ console_passwd }}';
log_info('Connecting ...');
connect(uri,password);
</script>
</body>
</html>

View file

@ -1,48 +1,37 @@
{% extends "console-base.html" %}
{% load i18n %} {% load i18n %}
<html> {% load staticfiles %}
<head> {% block head %}
<link rel="shortcut icon" href="{{ STATIC_URL }}img/favicon.ico"> <script src="{% static "js/novnc/util.js" %}"></script>
<link rel="stylesheet" href="{{ STATIC_URL }}js/novnc/base.css" title="plain">
<!--
<script type='text/javascript'
src='http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js'></script>
-->
<script src="{{ STATIC_URL }}js/novnc/util.js"></script>
</head>
<body style="margin: 0px;">
<div id="noVNC_screen">
<div id="noVNC_status_bar" class="noVNC_status_bar" style="margin-top: 0px;">
<table border=0 width="100%">
<tr>
<td>
<div id="noVNC_status">{% trans "Loading..." %}</div>
</td>
<td width="32%" style="text-align:right;">
<div id="noVNC_buttons">
<!-- dirty fix for keyboard on iOS devices -->
<input type="button" id="showKeyboard" value="Keyboard" title="Show Keyboard"/>
<!-- Note that Google Chrome on Android doesn't respect any of these,
html attributes which attempt to disable text suggestions on the
on-screen keyboard. Let's hope Chrome implements the ime-mode
style for example -->
<!-- TODO: check if this is needed on iOS -->
<textarea id="keyboardinput" autocapitalize="off"
autocorrect="off" autocomplete="off" spellcheck="false"
mozactionhint="Enter" onsubmit="return false;"
style="ime-mode: disabled;">
</textarea>
<input type=button value="Ctrl+Alt+Del" id="sendCtrlAltDelButton"> {% endblock %}
<input type=button value="Fullscreen" id="askFullscreen">
</div> {% block navbarmenu %}
</td> <!-- dirty fix for keyboard on iOS devices -->
</tr> <li id="showKeyboard"><a href='#'>{% trans "Show Keyboad" %}</a></li>
</table> {% endblock %}
</div>
{% block content %}
<div id='noVNC_area'>
<canvas id="noVNC_canvas" width="640px" height="20px"> <canvas id="noVNC_canvas" width="640px" height="20px">
{% trans "Canvas not supported." %} {% trans "Canvas not supported." %}
</canvas> </canvas>
</div> </div>
<!-- Note that Google Chrome on Android doesn't respect any of these,
html attributes which attempt to disable text suggestions on the
on-screen keyboard. Let's hope Chrome implements the ime-mode
style for example -->
<!-- TODO: check if this is needed on iOS -->
<textarea id="keyboardinput" autocapitalize="off"
autocorrect="off" autocomplete="off" spellcheck="false"
mozactionhint="Enter" onsubmit="return false;"
style="display: none;">
</textarea>
{% endblock %}
{% block foot %}
<script> <script>
/*jslint white: false */ /*jslint white: false */
/*global window, $, Util, RFB, */ /*global window, $, Util, RFB, */
@ -60,18 +49,32 @@
var rfb; var rfb;
function passwordRequired(rfb) { function passwordRequired(rfb) {
var msg; var modal;
msg = '<form onsubmit="return setPassword();"'; modal = '<div class="modal fade">';
msg += 'role="form"'; modal += ' <div class="modal-dialog">';
msg += ' style="margin-bottom: 0px">'; modal += ' <div class="modal-content">';
msg += 'Password Required: '; modal += ' <div class="modal-header">';
msg += '<input type=password size=10 id="password_input" class="noVNC_status">'; modal += ' <h4 class="modal-title">{% trans "Password required" %}</h4>';
msg += '<\/form>'; modal += ' </div>';
$D('noVNC_status_bar').setAttribute("class", "noVNC_status_warn"); modal += ' <div class="modal-body">';
$D('noVNC_status').innerHTML = msg; modal += ' <form id="password_form" onsubmit="return setPassword();">';
modal += ' <div class="form-group">';
modal += ' <label for="password_input">Password</label>';
modal += ' <input type="password" class="form-control" id="password_input" placeholder="Password"/>';
modal += ' </div>';
modal += ' </form>';
modal += ' </div>';
modal += ' <div class="modal-footer">';
modal += ' <button type="button" class="btn btn-primary" data-dismiss="modal" onclick="return setPassword();">{% trans "OK" %}</button>';
modal += ' </div>';
modal += ' </div>';
modal += ' </div>';
modal += '</div>';
$('body').append(modal);
$('div.modal').modal();
} }
function setPassword() { function setPassword() {
rfb.sendPassword($D('password_input').value); rfb.sendPassword($('#password_input').val());
return false; return false;
} }
function sendCtrlAltDel() { function sendCtrlAltDel() {
@ -79,6 +82,19 @@
return false; return false;
} }
function sendCtrlAltFN(f) {
var keys_code=[0xFFBE,0xFFBF,0xFFC0,0xFFC1,0xFFC2,0xFFC3,0xFFC4,0xFFC5,0xFFC6,0xFFC7,0xFFC8,0xFFC9];
if (keys_code[f]==undefined) {
return;
}
rfb.sendKey(0xFFE3, 'down');
rfb.sendKey(0xFFE9, 'down');
rfb.sendKey(keys_code[f], 'down');
rfb.sendKey(keys_code[f], 'up');
rfb.sendKey(0xFFE9, 'up');
rfb.sendKey(0xFFE3, 'up');
};
// dirty fix for keyboard on iOS devices // dirty fix for keyboard on iOS devices
function showKeyboard() { function showKeyboard() {
var kbi, skb, l; var kbi, skb, l;
@ -103,48 +119,36 @@
function updateState(rfb, state, oldstate, msg) { function updateState(rfb, state, oldstate, msg) {
var s, sb, cad, af, level; var s, sb, cad, af, level;
s = $D('noVNC_status');
sb = $D('noVNC_status_bar');
cad = $D('sendCtrlAltDelButton'); cad = $D('sendCtrlAltDelButton');
af = $D('askFullscreen'); af = $D('askFullscreen');
switch (state) { switch (state) {
case 'failed': case 'failed':
level = "error"; level = "danger";
break; break;
case 'fatal': case 'fatal':
level = "error"; level = "danger";
break; break;
case 'normal': case 'normal':
level = "normal"; level = "info";
break; break;
case 'disconnected': case 'disconnected':
level = "normal"; level = "info";
break; break;
case 'loaded': case 'loaded':
level = "normal"; level = "info";
break; break;
default: default:
level = "warn"; level = "warning";
break; break;
} }
if (state === "normal") {
cad.disabled = false;
af.disabled = false;
}
else {
cad.disabled = true;
af.disabled = true;
}
if (typeof(msg) !== 'undefined') { if (typeof(msg) !== 'undefined') {
sb.setAttribute("class", "noVNC_status_" + level); log_message(msg,level);
s.innerHTML = msg;
} }
} }
function fullscreen() { function fullscreen() {
var screen=document.getElementById('noVNC_canvas'); var screen=document.getElementById('main_container');
if(screen.requestFullscreen) { if(screen.requestFullscreen) {
screen.requestFullscreen(); screen.requestFullscreen();
} else if(screen.mozRequestFullScreen) { } else if(screen.mozRequestFullScreen) {
@ -159,11 +163,6 @@
window.onscriptsload = function () { window.onscriptsload = function () {
var host, port, password, path, token; var host, port, password, path, token;
$D('sendCtrlAltDelButton').style.display = "inline";
$D('sendCtrlAltDelButton').onclick = sendCtrlAltDel;
$D('askFullscreen').style.display = "inline";
$D('askFullscreen').onclick = fullscreen;
// dirty fix for keyboard on iOS devices // dirty fix for keyboard on iOS devices
if (isTouchDevice) { if (isTouchDevice) {
$D('showKeyboard').onclick = showKeyboard; $D('showKeyboard').onclick = showKeyboard;
@ -188,7 +187,7 @@
return; return;
} }
rfb = new RFB({'target': $D('noVNC_canvas'), rfb = new RFB({'target': document.getElementById('noVNC_canvas'),
'encrypt': WebUtil.getQueryVar('encrypt', 'encrypt': WebUtil.getQueryVar('encrypt',
(window.location.protocol === "https:")), (window.location.protocol === "https:")),
'repeaterID': WebUtil.getQueryVar('repeaterID', ''), 'repeaterID': WebUtil.getQueryVar('repeaterID', ''),
@ -201,5 +200,4 @@
rfb.connect(host, port, password, path); rfb.connect(host, port, password, path);
}; };
</script> </script>
</body> {% endblock %}
</html>