Styling/integration refactoring.
- Instead of onload override, move to RFB.load function that takes a parameter for the target DOM ID. This allows the user to have their own onload function. - Add "VNC_" prefix to all element ID names. Only create DOM elements if they don't already exist on the page, otherwise use the existing elements. - Move all styling to separate stylesheet. - Use list model for control styling.
This commit is contained in:
parent
3a2fafac9b
commit
ded9dfae10
19
README.md
19
README.md
|
@ -78,3 +78,22 @@ Usage
|
||||||
password that the vnc server is using (if any). Hit the Connect
|
password that the vnc server is using (if any). Hit the Connect
|
||||||
button and enjoy!
|
button and enjoy!
|
||||||
|
|
||||||
|
|
||||||
|
Integration
|
||||||
|
-----------
|
||||||
|
|
||||||
|
The client is designed to be easily integrated with existing web
|
||||||
|
structure and style.
|
||||||
|
|
||||||
|
At a minimum you must include the script and call the RFB.load()
|
||||||
|
function which takes a parameter that is the ID of the DOM element to
|
||||||
|
fill. For example:
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id='vnc'>Loading</div>
|
||||||
|
</body>
|
||||||
|
<script src='vnc.js'></script>
|
||||||
|
<script> windows.onload = RFB.load('vnc'); </script>
|
||||||
|
|
||||||
|
|
||||||
|
The file include/plain.css has a list of stylable elements.
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
#VNC_controls {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
#VNC_controls ul {
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
#VNC_controls li {
|
||||||
|
float: left;
|
||||||
|
margin-right: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#VNC_host {
|
||||||
|
width: 100;
|
||||||
|
}
|
||||||
|
#VNC_port {
|
||||||
|
width: 50;
|
||||||
|
}
|
||||||
|
#VNC_password {
|
||||||
|
width: 80;
|
||||||
|
}
|
||||||
|
#VNC_encrypt {
|
||||||
|
}
|
||||||
|
#VNC_connect_button {
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#VNC_status {
|
||||||
|
margin-top: 15px;
|
||||||
|
text-align: center;
|
||||||
|
background: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do not set width/height for VNC_screen or VNC_canvas or incorrect
|
||||||
|
* scaling will occur. Canvas resizes to remote VNC settings */
|
||||||
|
#VNC_screen {
|
||||||
|
text-align: center;
|
||||||
|
display: table;
|
||||||
|
}
|
||||||
|
#VNC_canvas {
|
||||||
|
background: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
#VNC_clipboard_clear_button {
|
||||||
|
}
|
||||||
|
#VNC_clipboard_text {
|
||||||
|
font-size: 9;
|
||||||
|
}
|
||||||
|
|
7
vnc.html
7
vnc.html
|
@ -2,11 +2,16 @@
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<title>VNC Client</title>
|
<title>VNC Client</title>
|
||||||
<script src="vnc.js"></script>
|
<link rel="stylesheet" href="include/plain.css">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id='vnc'>Loading</div>
|
<div id='vnc'>Loading</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
<script src="vnc.js"></script>
|
||||||
|
<script>
|
||||||
|
window.onload = RFB.load('vnc');
|
||||||
|
</script>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
179
vnc.js
179
vnc.js
|
@ -1,10 +1,9 @@
|
||||||
/*
|
/*
|
||||||
* HTML5 VNC client. To use, include this script and define a div with
|
* HTML5 VNC client
|
||||||
* id of 'vnc'. For example:
|
*
|
||||||
* <html><body>
|
* Licensed under AGPL-3 (see LICENSE.AGPL-3)
|
||||||
* <script src='vnc.js'></script>
|
*
|
||||||
* <div id='vnc'>Loading</div>
|
* See README.md for usage and integration instructions.
|
||||||
* </body></html>
|
|
||||||
*
|
*
|
||||||
* This script defines the following globals:
|
* This script defines the following globals:
|
||||||
* VNC_scripts, VNC_native_ws, FBU, RFB,
|
* VNC_scripts, VNC_native_ws, FBU, RFB,
|
||||||
|
@ -38,66 +37,6 @@ if (window.WebSocket) {
|
||||||
}
|
}
|
||||||
document.write(VNC_scripts);
|
document.write(VNC_scripts);
|
||||||
|
|
||||||
/*
|
|
||||||
* Load the controls
|
|
||||||
*/
|
|
||||||
window.onload = function () {
|
|
||||||
console.log("onload");
|
|
||||||
|
|
||||||
/* Populate the 'vnc' div */
|
|
||||||
var html = "";
|
|
||||||
html += '<div id="controls">';
|
|
||||||
html += 'Host: <input id="host" style="width:100"> ';
|
|
||||||
html += 'Port: <input id="port" style="width:50"> ';
|
|
||||||
html += 'Password: <input id="password" type="password" style="width:80"> ';
|
|
||||||
html += 'Encrypt: <input id="encrypt" type="checkbox"> ';
|
|
||||||
html += '<input id="connectButton" type="button" value="Loading"';
|
|
||||||
html += 'style="width:100px" disabled> ';
|
|
||||||
html += '</div>';
|
|
||||||
html += '<br>';
|
|
||||||
html += '<div id="status">Loading</div>';
|
|
||||||
html += '<canvas id="canvas" width="640" height="20"';
|
|
||||||
html += ' style="border-style: dotted; border-width: 1px;">';
|
|
||||||
html += ' Canvas not supported.';
|
|
||||||
html += '</canvas>';
|
|
||||||
html += '<br><br>';
|
|
||||||
html += 'VNC Clipboard:';
|
|
||||||
html += '<input id="clearButton" type="button" value="Clear"';
|
|
||||||
html += ' onclick="RFB.clipboardClear();"><br>';
|
|
||||||
html += '<textarea id="clipboard" style="font-size:9;" cols=80 rows=5';
|
|
||||||
html += ' onchange="RFB.clipboardPasteFrom();"';
|
|
||||||
html += ' onfocus="RFB.clipboardFocus=true;"';
|
|
||||||
html += ' onblur="RFB.clipboardFocus=false;"></textarea>';
|
|
||||||
$('vnc').innerHTML = html;
|
|
||||||
|
|
||||||
/* Load web-socket-js if no builtin WebSocket support */
|
|
||||||
if (VNC_native_ws) {
|
|
||||||
console.log("Using native WebSockets");
|
|
||||||
RFB.updateState('disconnected', 'Disconnected');
|
|
||||||
} else {
|
|
||||||
console.log("Using web-socket-js flash bridge");
|
|
||||||
if ((! Browser.Plugins.Flash) ||
|
|
||||||
(Browser.Plugins.Flash.version < 9)) {
|
|
||||||
RFB.updateState('failed', "WebSockets or Adobe Flash is required");
|
|
||||||
} else if (location.href.substr(0, 7) == "file://") {
|
|
||||||
RFB.updateState('failed', "'file://' URL is incompatible with Adobe Flash");
|
|
||||||
} else {
|
|
||||||
WebSocket.__swfLocation = "include/web-socket-js/WebSocketMain.swf";
|
|
||||||
RFB.use_seq = true;
|
|
||||||
RFB.updateState('disconnected', 'Disconnected');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Populate the controls if defaults are provided in the URL */
|
|
||||||
if (RFB.state == 'disconnected') {
|
|
||||||
var url = document.location.href;
|
|
||||||
$('host').value = (url.match(/host=([^&#]*)/) || ['',''])[1];
|
|
||||||
$('port').value = (url.match(/port=([^&#]*)/) || ['',''])[1];
|
|
||||||
$('password').value = (url.match(/password=([^&#]*)/) || ['',''])[1];
|
|
||||||
$('encrypt').checked = (url.match(/encrypt=([^&#]*)/) || ['',''])[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make arrays quack
|
* Make arrays quack
|
||||||
*/
|
*/
|
||||||
|
@ -372,7 +311,7 @@ init_msg: function () {
|
||||||
var name_length = RQ.shift32();
|
var name_length = RQ.shift32();
|
||||||
RFB.fb_name = RQ.shiftStr(name_length);
|
RFB.fb_name = RQ.shiftStr(name_length);
|
||||||
|
|
||||||
Canvas.init('canvas', RFB.fb_width, RFB.fb_height,
|
Canvas.init('VNC_canvas', RFB.fb_width, RFB.fb_height,
|
||||||
RFB.keyDown, RFB.keyUp,
|
RFB.keyDown, RFB.keyUp,
|
||||||
RFB.mouseDown, RFB.mouseUp, RFB.mouseMove);
|
RFB.mouseDown, RFB.mouseUp, RFB.mouseMove);
|
||||||
|
|
||||||
|
@ -801,7 +740,7 @@ clientCutText: function (text) {
|
||||||
arr.push8(0); // padding
|
arr.push8(0); // padding
|
||||||
arr.push32(text.length);
|
arr.push32(text.length);
|
||||||
arr.pushStr(text);
|
arr.pushStr(text);
|
||||||
console.log("<< clientCutText");
|
console.log("<< clientCutText:" + arr);
|
||||||
return arr;
|
return arr;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1003,26 +942,26 @@ mouseMove: function(e) {
|
||||||
|
|
||||||
clipboardCopyTo: function (text) {
|
clipboardCopyTo: function (text) {
|
||||||
console.log(">> clipboardCopyTo: " + text.substr(0,40) + "...");
|
console.log(">> clipboardCopyTo: " + text.substr(0,40) + "...");
|
||||||
$('clipboard').value = text;
|
$('VNC_clipboard_text').value = text;
|
||||||
console.log("<< clipboardCopyTo");
|
console.log("<< clipboardCopyTo");
|
||||||
},
|
},
|
||||||
|
|
||||||
clipboardPasteFrom: function () {
|
clipboardPasteFrom: function () {
|
||||||
if (RFB.state != "normal") return;
|
if (RFB.state != "normal") return;
|
||||||
var text = $('clipboard').value;
|
var text = $('VNC_clipboard_text').value;
|
||||||
console.log(">> clipboardPasteFrom: " + text.substr(0,40) + "...");
|
console.log(">> clipboardPasteFrom: " + text.substr(0,40) + "...");
|
||||||
RFB.send_array(RFB.clientCutText(text));
|
RFB.send_array(RFB.clientCutText(text));
|
||||||
console.log("<< clipboardPasteFrom");
|
console.log("<< clipboardPasteFrom");
|
||||||
},
|
},
|
||||||
|
|
||||||
clipboardClear: function () {
|
clipboardClear: function () {
|
||||||
$('clipboard').value = '';
|
$('VNC_clipboard_text').value = '';
|
||||||
RFB.clipboardPasteFrom();
|
RFB.clipboardPasteFrom();
|
||||||
},
|
},
|
||||||
|
|
||||||
updateState: function(state, statusMsg) {
|
updateState: function(state, statusMsg) {
|
||||||
var s = $('status');
|
var s = $('VNC_status');
|
||||||
var c = $('connectButton');
|
var c = $('VNC_connect_button');
|
||||||
var func = function(msg) { console.log(msg) };
|
var func = function(msg) { console.log(msg) };
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case 'failed':
|
case 'failed':
|
||||||
|
@ -1134,10 +1073,10 @@ init_vars: function () {
|
||||||
|
|
||||||
connect: function () {
|
connect: function () {
|
||||||
console.log(">> connect");
|
console.log(">> connect");
|
||||||
RFB.host = $('host').value;
|
RFB.host = $('VNC_host').value;
|
||||||
RFB.port = $('port').value;
|
RFB.port = $('VNC_port').value;
|
||||||
RFB.password = $('password').value;
|
RFB.password = $('VNC_password').value;
|
||||||
if ($('encrypt').checked) {
|
if ($('VNC_encrypt').checked) {
|
||||||
RFB.scheme = "wss://";
|
RFB.scheme = "wss://";
|
||||||
} else {
|
} else {
|
||||||
RFB.scheme = "ws://";
|
RFB.scheme = "ws://";
|
||||||
|
@ -1180,4 +1119,90 @@ disconnect: function () {
|
||||||
console.log("<< disconnect");
|
console.log("<< disconnect");
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Load the controls
|
||||||
|
*/
|
||||||
|
load: function (target) {
|
||||||
|
console.log(">> RFB.load");
|
||||||
|
|
||||||
|
if (!target) { target = 'vnc' };
|
||||||
|
|
||||||
|
/* Populate the 'vnc' div */
|
||||||
|
var html = "";
|
||||||
|
if ($('VNC_controls') === null) {
|
||||||
|
html += '<div id="VNC_controls">';
|
||||||
|
html += ' <ul>';
|
||||||
|
html += ' <li>Host: <input id="VNC_host"></li>';
|
||||||
|
html += ' <li>Port: <input id="VNC_port"></li>';
|
||||||
|
html += ' <li>Password: <input id="VNC_password" type="password"></li>';
|
||||||
|
html += ' <li>Encrypt: <input id="VNC_encrypt" type="checkbox"></li>';
|
||||||
|
html += ' <li><input id="VNC_connect_button" type="button"';
|
||||||
|
html += ' value="Loading" disabled></li>';
|
||||||
|
html += ' </ul>';
|
||||||
|
html += '</div>';
|
||||||
|
}
|
||||||
|
if ($('VNC_screen') === null) {
|
||||||
|
html += '<div id="VNC_screen">';
|
||||||
|
html += '</div>';
|
||||||
|
}
|
||||||
|
if ($('VNC_clipboard') === null) {
|
||||||
|
html += '<br><br>';
|
||||||
|
html += '<div id="VNC_clipboard">';
|
||||||
|
html += ' VNC Clipboard:';
|
||||||
|
html += ' <input id="VNC_clipboard_clear_button" type="button" value="Clear">';
|
||||||
|
html += ' <br>';
|
||||||
|
html += ' <textarea id="VNC_clipboard_text" cols=80 rows=5>';
|
||||||
|
html += ' </textarea>';
|
||||||
|
html += '</div>';
|
||||||
|
}
|
||||||
|
$(target).innerHTML = html;
|
||||||
|
|
||||||
|
html = "";
|
||||||
|
if ($('VNC_status') === null) {
|
||||||
|
html += '<div id="VNC_status">Loading</div>';
|
||||||
|
}
|
||||||
|
if ($('VNC_canvas') === null) {
|
||||||
|
html += '<canvas id="VNC_canvas" width="640px" height="20px">';
|
||||||
|
html += ' Canvas not supported.';
|
||||||
|
html += '</canvas>';
|
||||||
|
}
|
||||||
|
$('VNC_screen').innerHTML += html;
|
||||||
|
|
||||||
|
/* Add handlers */
|
||||||
|
$('VNC_clipboard_clear_button').onclick = RFB.clipboardClear;
|
||||||
|
var clipt = $('VNC_clipboard_text')
|
||||||
|
clipt.onchange = RFB.clipboardPasteFrom;
|
||||||
|
clipt.onfocus = function () { RFB.clipboardFocus = true; };
|
||||||
|
clipt.onblur = function () { RFB.clipboardFocus = false; };
|
||||||
|
|
||||||
|
/* Load web-socket-js if no builtin WebSocket support */
|
||||||
|
if (VNC_native_ws) {
|
||||||
|
console.log("Using native WebSockets");
|
||||||
|
RFB.updateState('disconnected', 'Disconnected');
|
||||||
|
} else {
|
||||||
|
console.log("Using web-socket-js flash bridge");
|
||||||
|
if ((! Browser.Plugins.Flash) ||
|
||||||
|
(Browser.Plugins.Flash.version < 9)) {
|
||||||
|
RFB.updateState('failed', "WebSockets or Adobe Flash is required");
|
||||||
|
} else if (location.href.substr(0, 7) == "file://") {
|
||||||
|
RFB.updateState('failed', "'file://' URL is incompatible with Adobe Flash");
|
||||||
|
} else {
|
||||||
|
WebSocket.__swfLocation = "include/web-socket-js/WebSocketMain.swf";
|
||||||
|
RFB.use_seq = true;
|
||||||
|
RFB.updateState('disconnected', 'Disconnected');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Populate the controls if defaults are provided in the URL */
|
||||||
|
if (RFB.state == 'disconnected') {
|
||||||
|
var url = document.location.href;
|
||||||
|
$('VNC_host').value = (url.match(/host=([^&#]*)/) || ['',''])[1];
|
||||||
|
$('VNC_port').value = (url.match(/port=([^&#]*)/) || ['',''])[1];
|
||||||
|
$('VNC_password').value = (url.match(/password=([^&#]*)/) || ['',''])[1];
|
||||||
|
$('VNC_encrypt').checked = (url.match(/encrypt=([^&#]*)/) || ['',''])[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("<< RFB.load");
|
||||||
|
}
|
||||||
|
|
||||||
}; /* End of RFB */
|
}; /* End of RFB */
|
||||||
|
|
Loading…
Reference in New Issue