novnc-rails 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (31) hide show
  1. checksums.yaml +7 -0
  2. data/COPYING +0 -0
  3. data/LICENSE.txt +0 -0
  4. data/README.md +0 -0
  5. data/lib/novnc-rails.rb +8 -0
  6. data/lib/novnc-rails/version.rb +5 -0
  7. data/vendor/assets/javascripts/noVNC/Orbitron700.ttf +0 -0
  8. data/vendor/assets/javascripts/noVNC/Orbitron700.woff +0 -0
  9. data/vendor/assets/javascripts/noVNC/base.css +512 -0
  10. data/vendor/assets/javascripts/noVNC/base64.js +113 -0
  11. data/vendor/assets/javascripts/noVNC/black.css +71 -0
  12. data/vendor/assets/javascripts/noVNC/blue.css +64 -0
  13. data/vendor/assets/javascripts/noVNC/des.js +276 -0
  14. data/vendor/assets/javascripts/noVNC/display.js +751 -0
  15. data/vendor/assets/javascripts/noVNC/input.js +388 -0
  16. data/vendor/assets/javascripts/noVNC/jsunzip.js +676 -0
  17. data/vendor/assets/javascripts/noVNC/keyboard.js +543 -0
  18. data/vendor/assets/javascripts/noVNC/keysym.js +378 -0
  19. data/vendor/assets/javascripts/noVNC/keysymdef.js +15 -0
  20. data/vendor/assets/javascripts/noVNC/logo.js +1 -0
  21. data/vendor/assets/javascripts/noVNC/playback.js +102 -0
  22. data/vendor/assets/javascripts/noVNC/rfb.js +1889 -0
  23. data/vendor/assets/javascripts/noVNC/ui.js +979 -0
  24. data/vendor/assets/javascripts/noVNC/util.js +656 -0
  25. data/vendor/assets/javascripts/noVNC/web-socket-js/README.txt +109 -0
  26. data/vendor/assets/javascripts/noVNC/web-socket-js/WebSocketMain.swf +0 -0
  27. data/vendor/assets/javascripts/noVNC/web-socket-js/swfobject.js +4 -0
  28. data/vendor/assets/javascripts/noVNC/web-socket-js/web_socket.js +391 -0
  29. data/vendor/assets/javascripts/noVNC/websock.js +388 -0
  30. data/vendor/assets/javascripts/noVNC/webutil.js +239 -0
  31. metadata +86 -0
@@ -0,0 +1,979 @@
1
+ /*
2
+ * noVNC: HTML5 VNC client
3
+ * Copyright (C) 2012 Joel Martin
4
+ * Copyright (C) 2013 Samuel Mannehed for Cendio AB
5
+ * Licensed under MPL 2.0 (see LICENSE.txt)
6
+ *
7
+ * See README.md for usage and integration instructions.
8
+ */
9
+
10
+ /* jslint white: false, browser: true */
11
+ /* global window, $D, Util, WebUtil, RFB, Display */
12
+
13
+ var UI;
14
+
15
+ (function () {
16
+ "use strict";
17
+
18
+ // Load supporting scripts
19
+ window.onscriptsload = function () { UI.load(); };
20
+ window.onload = function () { UI.keyboardinputReset(); };
21
+ Util.load_scripts(["webutil.js", "base64.js", "websock.js", "des.js",
22
+ "keysymdef.js", "keyboard.js", "input.js", "display.js",
23
+ "jsunzip.js", "rfb.js", "keysym.js"]);
24
+
25
+ UI = {
26
+
27
+ rfb_state : 'loaded',
28
+ settingsOpen : false,
29
+ connSettingsOpen : false,
30
+ popupStatusOpen : false,
31
+ clipboardOpen: false,
32
+ keyboardVisible: false,
33
+ hideKeyboardTimeout: null,
34
+ lastKeyboardinput: null,
35
+ defaultKeyboardinputLen: 100,
36
+ extraKeysVisible: false,
37
+ ctrlOn: false,
38
+ altOn: false,
39
+ isTouchDevice: false,
40
+
41
+ // Setup rfb object, load settings from browser storage, then call
42
+ // UI.init to setup the UI/menus
43
+ load: function (callback) {
44
+ WebUtil.initSettings(UI.start, callback);
45
+ },
46
+
47
+ // Render default UI and initialize settings menu
48
+ start: function(callback) {
49
+ UI.isTouchDevice = 'ontouchstart' in document.documentElement;
50
+
51
+ // Stylesheet selection dropdown
52
+ var sheet = WebUtil.selectStylesheet();
53
+ var sheets = WebUtil.getStylesheets();
54
+ var i;
55
+ for (i = 0; i < sheets.length; i += 1) {
56
+ UI.addOption($D('noVNC_stylesheet'),sheets[i].title, sheets[i].title);
57
+ }
58
+
59
+ // Logging selection dropdown
60
+ var llevels = ['error', 'warn', 'info', 'debug'];
61
+ for (i = 0; i < llevels.length; i += 1) {
62
+ UI.addOption($D('noVNC_logging'),llevels[i], llevels[i]);
63
+ }
64
+
65
+ // Settings with immediate effects
66
+ UI.initSetting('logging', 'warn');
67
+ WebUtil.init_logging(UI.getSetting('logging'));
68
+
69
+ UI.initSetting('stylesheet', 'default');
70
+ WebUtil.selectStylesheet(null);
71
+ // call twice to get around webkit bug
72
+ WebUtil.selectStylesheet(UI.getSetting('stylesheet'));
73
+
74
+ // if port == 80 (or 443) then it won't be present and should be
75
+ // set manually
76
+ var port = window.location.port;
77
+ if (!port) {
78
+ if (window.location.protocol.substring(0,5) == 'https') {
79
+ port = 443;
80
+ }
81
+ else if (window.location.protocol.substring(0,4) == 'http') {
82
+ port = 80;
83
+ }
84
+ }
85
+
86
+ /* Populate the controls if defaults are provided in the URL */
87
+ UI.initSetting('host', window.location.hostname);
88
+ UI.initSetting('port', port);
89
+ UI.initSetting('password', '');
90
+ UI.initSetting('encrypt', (window.location.protocol === "https:"));
91
+ UI.initSetting('true_color', true);
92
+ UI.initSetting('cursor', !UI.isTouchDevice);
93
+ UI.initSetting('shared', true);
94
+ UI.initSetting('view_only', false);
95
+ UI.initSetting('path', 'websockify');
96
+ UI.initSetting('repeaterID', '');
97
+
98
+ UI.rfb = new RFB({'target': $D('noVNC_canvas'),
99
+ 'onUpdateState': UI.updateState,
100
+ 'onXvpInit': UI.updateXvpVisualState,
101
+ 'onClipboard': UI.clipReceive,
102
+ 'onDesktopName': UI.updateDocumentTitle});
103
+
104
+ var autoconnect = WebUtil.getQueryVar('autoconnect', false);
105
+ if (autoconnect === 'true' || autoconnect == '1') {
106
+ autoconnect = true;
107
+ UI.connect();
108
+ } else {
109
+ autoconnect = false;
110
+ }
111
+
112
+ UI.updateVisualState();
113
+
114
+ // Show mouse selector buttons on touch screen devices
115
+ if (UI.isTouchDevice) {
116
+ // Show mobile buttons
117
+ $D('noVNC_mobile_buttons').style.display = "inline";
118
+ UI.setMouseButton();
119
+ // Remove the address bar
120
+ setTimeout(function() { window.scrollTo(0, 1); }, 100);
121
+ UI.forceSetting('clip', true);
122
+ $D('noVNC_clip').disabled = true;
123
+ } else {
124
+ UI.initSetting('clip', false);
125
+ }
126
+
127
+ //iOS Safari does not support CSS position:fixed.
128
+ //This detects iOS devices and enables javascript workaround.
129
+ if ((navigator.userAgent.match(/iPhone/i)) ||
130
+ (navigator.userAgent.match(/iPod/i)) ||
131
+ (navigator.userAgent.match(/iPad/i))) {
132
+ //UI.setOnscroll();
133
+ //UI.setResize();
134
+ }
135
+ UI.setBarPosition();
136
+
137
+ $D('noVNC_host').focus();
138
+
139
+ UI.setViewClip();
140
+ Util.addEvent(window, 'resize', UI.setViewClip);
141
+
142
+ Util.addEvent(window, 'beforeunload', function () {
143
+ if (UI.rfb_state === 'normal') {
144
+ return "You are currently connected.";
145
+ }
146
+ } );
147
+
148
+ // Show description by default when hosted at for kanaka.github.com
149
+ if (location.host === "kanaka.github.io") {
150
+ // Open the description dialog
151
+ $D('noVNC_description').style.display = "block";
152
+ } else {
153
+ // Show the connect panel on first load unless autoconnecting
154
+ if (autoconnect === UI.connSettingsOpen) {
155
+ UI.toggleConnectPanel();
156
+ }
157
+ }
158
+
159
+ // Add mouse event click/focus/blur event handlers to the UI
160
+ UI.addMouseHandlers();
161
+
162
+ if (typeof callback === "function") {
163
+ callback(UI.rfb);
164
+ }
165
+ },
166
+
167
+ addMouseHandlers: function() {
168
+ // Setup interface handlers that can't be inline
169
+ $D("noVNC_view_drag_button").onclick = UI.setViewDrag;
170
+ $D("noVNC_mouse_button0").onclick = function () { UI.setMouseButton(1); };
171
+ $D("noVNC_mouse_button1").onclick = function () { UI.setMouseButton(2); };
172
+ $D("noVNC_mouse_button2").onclick = function () { UI.setMouseButton(4); };
173
+ $D("noVNC_mouse_button4").onclick = function () { UI.setMouseButton(0); };
174
+ $D("showKeyboard").onclick = UI.showKeyboard;
175
+
176
+ $D("keyboardinput").oninput = UI.keyInput;
177
+ $D("keyboardinput").onblur = UI.keyInputBlur;
178
+
179
+ $D("showExtraKeysButton").onclick = UI.showExtraKeys;
180
+ $D("toggleCtrlButton").onclick = UI.toggleCtrl;
181
+ $D("toggleAltButton").onclick = UI.toggleAlt;
182
+ $D("sendTabButton").onclick = UI.sendTab;
183
+ $D("sendEscButton").onclick = UI.sendEsc;
184
+
185
+ $D("sendCtrlAltDelButton").onclick = UI.sendCtrlAltDel;
186
+ $D("xvpShutdownButton").onclick = UI.xvpShutdown;
187
+ $D("xvpRebootButton").onclick = UI.xvpReboot;
188
+ $D("xvpResetButton").onclick = UI.xvpReset;
189
+ $D("noVNC_status").onclick = UI.togglePopupStatusPanel;
190
+ $D("noVNC_popup_status_panel").onclick = UI.togglePopupStatusPanel;
191
+ $D("xvpButton").onclick = UI.toggleXvpPanel;
192
+ $D("clipboardButton").onclick = UI.toggleClipboardPanel;
193
+ $D("settingsButton").onclick = UI.toggleSettingsPanel;
194
+ $D("connectButton").onclick = UI.toggleConnectPanel;
195
+ $D("disconnectButton").onclick = UI.disconnect;
196
+ $D("descriptionButton").onclick = UI.toggleConnectPanel;
197
+
198
+ $D("noVNC_clipboard_text").onfocus = UI.displayBlur;
199
+ $D("noVNC_clipboard_text").onblur = UI.displayFocus;
200
+ $D("noVNC_clipboard_text").onchange = UI.clipSend;
201
+ $D("noVNC_clipboard_clear_button").onclick = UI.clipClear;
202
+
203
+ $D("noVNC_settings_menu").onmouseover = UI.displayBlur;
204
+ $D("noVNC_settings_menu").onmouseover = UI.displayFocus;
205
+ $D("noVNC_apply").onclick = UI.settingsApply;
206
+
207
+ $D("noVNC_connect_button").onclick = UI.connect;
208
+ },
209
+
210
+ // Read form control compatible setting from cookie
211
+ getSetting: function(name) {
212
+ var ctrl = $D('noVNC_' + name);
213
+ var val = WebUtil.readSetting(name);
214
+ if (val !== null && ctrl.type === 'checkbox') {
215
+ if (val.toString().toLowerCase() in {'0':1, 'no':1, 'false':1}) {
216
+ val = false;
217
+ } else {
218
+ val = true;
219
+ }
220
+ }
221
+ return val;
222
+ },
223
+
224
+ // Update cookie and form control setting. If value is not set, then
225
+ // updates from control to current cookie setting.
226
+ updateSetting: function(name, value) {
227
+
228
+ // Save the cookie for this session
229
+ if (typeof value !== 'undefined') {
230
+ WebUtil.writeSetting(name, value);
231
+ }
232
+
233
+ // Update the settings control
234
+ value = UI.getSetting(name);
235
+
236
+ var ctrl = $D('noVNC_' + name);
237
+ if (ctrl.type === 'checkbox') {
238
+ ctrl.checked = value;
239
+
240
+ } else if (typeof ctrl.options !== 'undefined') {
241
+ for (var i = 0; i < ctrl.options.length; i += 1) {
242
+ if (ctrl.options[i].value === value) {
243
+ ctrl.selectedIndex = i;
244
+ break;
245
+ }
246
+ }
247
+ } else {
248
+ /*Weird IE9 error leads to 'null' appearring
249
+ in textboxes instead of ''.*/
250
+ if (value === null) {
251
+ value = "";
252
+ }
253
+ ctrl.value = value;
254
+ }
255
+ },
256
+
257
+ // Save control setting to cookie
258
+ saveSetting: function(name) {
259
+ var val, ctrl = $D('noVNC_' + name);
260
+ if (ctrl.type === 'checkbox') {
261
+ val = ctrl.checked;
262
+ } else if (typeof ctrl.options !== 'undefined') {
263
+ val = ctrl.options[ctrl.selectedIndex].value;
264
+ } else {
265
+ val = ctrl.value;
266
+ }
267
+ WebUtil.writeSetting(name, val);
268
+ //Util.Debug("Setting saved '" + name + "=" + val + "'");
269
+ return val;
270
+ },
271
+
272
+ // Initial page load read/initialization of settings
273
+ initSetting: function(name, defVal) {
274
+ // Check Query string followed by cookie
275
+ var val = WebUtil.getQueryVar(name);
276
+ if (val === null) {
277
+ val = WebUtil.readSetting(name, defVal);
278
+ }
279
+ UI.updateSetting(name, val);
280
+ return val;
281
+ },
282
+
283
+ // Force a setting to be a certain value
284
+ forceSetting: function(name, val) {
285
+ UI.updateSetting(name, val);
286
+ return val;
287
+ },
288
+
289
+
290
+ // Show the popup status panel
291
+ togglePopupStatusPanel: function() {
292
+ var psp = $D('noVNC_popup_status_panel');
293
+ if (UI.popupStatusOpen === true) {
294
+ psp.style.display = "none";
295
+ UI.popupStatusOpen = false;
296
+ } else {
297
+ psp.innerHTML = $D('noVNC_status').innerHTML;
298
+ psp.style.display = "block";
299
+ psp.style.left = window.innerWidth/2 -
300
+ parseInt(window.getComputedStyle(psp, false).width)/2 -30 + "px";
301
+ UI.popupStatusOpen = true;
302
+ }
303
+ },
304
+
305
+ // Show the XVP panel
306
+ toggleXvpPanel: function() {
307
+ // Close the description panel
308
+ $D('noVNC_description').style.display = "none";
309
+ // Close settings if open
310
+ if (UI.settingsOpen === true) {
311
+ UI.settingsApply();
312
+ UI.closeSettingsMenu();
313
+ }
314
+ // Close connection settings if open
315
+ if (UI.connSettingsOpen === true) {
316
+ UI.toggleConnectPanel();
317
+ }
318
+ // Close popup status panel if open
319
+ if (UI.popupStatusOpen === true) {
320
+ UI.togglePopupStatusPanel();
321
+ }
322
+ // Close clipboard panel if open
323
+ if (UI.clipboardOpen === true) {
324
+ UI.toggleClipboardPanel();
325
+ }
326
+ // Toggle XVP panel
327
+ if (UI.xvpOpen === true) {
328
+ $D('noVNC_xvp').style.display = "none";
329
+ $D('xvpButton').className = "noVNC_status_button";
330
+ UI.xvpOpen = false;
331
+ } else {
332
+ $D('noVNC_xvp').style.display = "block";
333
+ $D('xvpButton').className = "noVNC_status_button_selected";
334
+ UI.xvpOpen = true;
335
+ }
336
+ },
337
+
338
+ // Show the clipboard panel
339
+ toggleClipboardPanel: function() {
340
+ // Close the description panel
341
+ $D('noVNC_description').style.display = "none";
342
+ // Close settings if open
343
+ if (UI.settingsOpen === true) {
344
+ UI.settingsApply();
345
+ UI.closeSettingsMenu();
346
+ }
347
+ // Close connection settings if open
348
+ if (UI.connSettingsOpen === true) {
349
+ UI.toggleConnectPanel();
350
+ }
351
+ // Close popup status panel if open
352
+ if (UI.popupStatusOpen === true) {
353
+ UI.togglePopupStatusPanel();
354
+ }
355
+ // Close XVP panel if open
356
+ if (UI.xvpOpen === true) {
357
+ UI.toggleXvpPanel();
358
+ }
359
+ // Toggle Clipboard Panel
360
+ if (UI.clipboardOpen === true) {
361
+ $D('noVNC_clipboard').style.display = "none";
362
+ $D('clipboardButton').className = "noVNC_status_button";
363
+ UI.clipboardOpen = false;
364
+ } else {
365
+ $D('noVNC_clipboard').style.display = "block";
366
+ $D('clipboardButton').className = "noVNC_status_button_selected";
367
+ UI.clipboardOpen = true;
368
+ }
369
+ },
370
+
371
+ // Show the connection settings panel/menu
372
+ toggleConnectPanel: function() {
373
+ // Close the description panel
374
+ $D('noVNC_description').style.display = "none";
375
+ // Close connection settings if open
376
+ if (UI.settingsOpen === true) {
377
+ UI.settingsApply();
378
+ UI.closeSettingsMenu();
379
+ $D('connectButton').className = "noVNC_status_button";
380
+ }
381
+ // Close clipboard panel if open
382
+ if (UI.clipboardOpen === true) {
383
+ UI.toggleClipboardPanel();
384
+ }
385
+ // Close popup status panel if open
386
+ if (UI.popupStatusOpen === true) {
387
+ UI.togglePopupStatusPanel();
388
+ }
389
+ // Close XVP panel if open
390
+ if (UI.xvpOpen === true) {
391
+ UI.toggleXvpPanel();
392
+ }
393
+
394
+ // Toggle Connection Panel
395
+ if (UI.connSettingsOpen === true) {
396
+ $D('noVNC_controls').style.display = "none";
397
+ $D('connectButton').className = "noVNC_status_button";
398
+ UI.connSettingsOpen = false;
399
+ UI.saveSetting('host');
400
+ UI.saveSetting('port');
401
+ //UI.saveSetting('password');
402
+ } else {
403
+ $D('noVNC_controls').style.display = "block";
404
+ $D('connectButton').className = "noVNC_status_button_selected";
405
+ UI.connSettingsOpen = true;
406
+ $D('noVNC_host').focus();
407
+ }
408
+ },
409
+
410
+ // Toggle the settings menu:
411
+ // On open, settings are refreshed from saved cookies.
412
+ // On close, settings are applied
413
+ toggleSettingsPanel: function() {
414
+ // Close the description panel
415
+ $D('noVNC_description').style.display = "none";
416
+ if (UI.settingsOpen) {
417
+ UI.settingsApply();
418
+ UI.closeSettingsMenu();
419
+ } else {
420
+ UI.updateSetting('encrypt');
421
+ UI.updateSetting('true_color');
422
+ if (UI.rfb.get_display().get_cursor_uri()) {
423
+ UI.updateSetting('cursor');
424
+ } else {
425
+ UI.updateSetting('cursor', !UI.isTouchDevice);
426
+ $D('noVNC_cursor').disabled = true;
427
+ }
428
+ UI.updateSetting('clip');
429
+ UI.updateSetting('shared');
430
+ UI.updateSetting('view_only');
431
+ UI.updateSetting('path');
432
+ UI.updateSetting('repeaterID');
433
+ UI.updateSetting('stylesheet');
434
+ UI.updateSetting('logging');
435
+
436
+ UI.openSettingsMenu();
437
+ }
438
+ },
439
+
440
+ // Open menu
441
+ openSettingsMenu: function() {
442
+ // Close the description panel
443
+ $D('noVNC_description').style.display = "none";
444
+ // Close clipboard panel if open
445
+ if (UI.clipboardOpen === true) {
446
+ UI.toggleClipboardPanel();
447
+ }
448
+ // Close connection settings if open
449
+ if (UI.connSettingsOpen === true) {
450
+ UI.toggleConnectPanel();
451
+ }
452
+ // Close popup status panel if open
453
+ if (UI.popupStatusOpen === true) {
454
+ UI.togglePopupStatusPanel();
455
+ }
456
+ // Close XVP panel if open
457
+ if (UI.xvpOpen === true) {
458
+ UI.toggleXvpPanel();
459
+ }
460
+ $D('noVNC_settings').style.display = "block";
461
+ $D('settingsButton').className = "noVNC_status_button_selected";
462
+ UI.settingsOpen = true;
463
+ },
464
+
465
+ // Close menu (without applying settings)
466
+ closeSettingsMenu: function() {
467
+ $D('noVNC_settings').style.display = "none";
468
+ $D('settingsButton').className = "noVNC_status_button";
469
+ UI.settingsOpen = false;
470
+ },
471
+
472
+ // Save/apply settings when 'Apply' button is pressed
473
+ settingsApply: function() {
474
+ //Util.Debug(">> settingsApply");
475
+ UI.saveSetting('encrypt');
476
+ UI.saveSetting('true_color');
477
+ if (UI.rfb.get_display().get_cursor_uri()) {
478
+ UI.saveSetting('cursor');
479
+ }
480
+ UI.saveSetting('clip');
481
+ UI.saveSetting('shared');
482
+ UI.saveSetting('view_only');
483
+ UI.saveSetting('path');
484
+ UI.saveSetting('repeaterID');
485
+ UI.saveSetting('stylesheet');
486
+ UI.saveSetting('logging');
487
+
488
+ // Settings with immediate (non-connected related) effect
489
+ WebUtil.selectStylesheet(UI.getSetting('stylesheet'));
490
+ WebUtil.init_logging(UI.getSetting('logging'));
491
+ UI.setViewClip();
492
+ UI.setViewDrag(UI.rfb.get_viewportDrag());
493
+ //Util.Debug("<< settingsApply");
494
+ },
495
+
496
+
497
+
498
+ setPassword: function() {
499
+ UI.rfb.sendPassword($D('noVNC_password').value);
500
+ //Reset connect button.
501
+ $D('noVNC_connect_button').value = "Connect";
502
+ $D('noVNC_connect_button').onclick = UI.Connect;
503
+ //Hide connection panel.
504
+ UI.toggleConnectPanel();
505
+ return false;
506
+ },
507
+
508
+ sendCtrlAltDel: function() {
509
+ UI.rfb.sendCtrlAltDel();
510
+ },
511
+
512
+ xvpShutdown: function() {
513
+ UI.rfb.xvpShutdown();
514
+ },
515
+
516
+ xvpReboot: function() {
517
+ UI.rfb.xvpReboot();
518
+ },
519
+
520
+ xvpReset: function() {
521
+ UI.rfb.xvpReset();
522
+ },
523
+
524
+ setMouseButton: function(num) {
525
+ if (typeof num === 'undefined') {
526
+ // Disable mouse buttons
527
+ num = -1;
528
+ }
529
+ if (UI.rfb) {
530
+ UI.rfb.get_mouse().set_touchButton(num);
531
+ }
532
+
533
+ var blist = [0, 1,2,4];
534
+ for (var b = 0; b < blist.length; b++) {
535
+ var button = $D('noVNC_mouse_button' + blist[b]);
536
+ if (blist[b] === num) {
537
+ button.style.display = "";
538
+ } else {
539
+ button.style.display = "none";
540
+ }
541
+ }
542
+ },
543
+
544
+ updateState: function(rfb, state, oldstate, msg) {
545
+ UI.rfb_state = state;
546
+ var klass;
547
+ switch (state) {
548
+ case 'failed':
549
+ case 'fatal':
550
+ klass = "noVNC_status_error";
551
+ break;
552
+ case 'normal':
553
+ klass = "noVNC_status_normal";
554
+ break;
555
+ case 'disconnected':
556
+ $D('noVNC_logo').style.display = "block";
557
+ /* falls through */
558
+ case 'loaded':
559
+ klass = "noVNC_status_normal";
560
+ break;
561
+ case 'password':
562
+ UI.toggleConnectPanel();
563
+
564
+ $D('noVNC_connect_button').value = "Send Password";
565
+ $D('noVNC_connect_button').onclick = UI.setPassword;
566
+ $D('noVNC_password').focus();
567
+
568
+ klass = "noVNC_status_warn";
569
+ break;
570
+ default:
571
+ klass = "noVNC_status_warn";
572
+ break;
573
+ }
574
+
575
+ if (typeof(msg) !== 'undefined') {
576
+ $D('noVNC-control-bar').setAttribute("class", klass);
577
+ $D('noVNC_status').innerHTML = msg;
578
+ }
579
+
580
+ UI.updateVisualState();
581
+ },
582
+
583
+ // Disable/enable controls depending on connection state
584
+ updateVisualState: function() {
585
+ var connected = UI.rfb_state === 'normal' ? true : false;
586
+
587
+ //Util.Debug(">> updateVisualState");
588
+ $D('noVNC_encrypt').disabled = connected;
589
+ $D('noVNC_true_color').disabled = connected;
590
+ if (UI.rfb && UI.rfb.get_display() &&
591
+ UI.rfb.get_display().get_cursor_uri()) {
592
+ $D('noVNC_cursor').disabled = connected;
593
+ } else {
594
+ UI.updateSetting('cursor', !UI.isTouchDevice);
595
+ $D('noVNC_cursor').disabled = true;
596
+ }
597
+ $D('noVNC_shared').disabled = connected;
598
+ $D('noVNC_view_only').disabled = connected;
599
+ $D('noVNC_path').disabled = connected;
600
+ $D('noVNC_repeaterID').disabled = connected;
601
+
602
+ if (connected) {
603
+ UI.setViewClip();
604
+ UI.setMouseButton(1);
605
+ $D('clipboardButton').style.display = "inline";
606
+ $D('showKeyboard').style.display = "inline";
607
+ $D('noVNC_extra_keys').style.display = "";
608
+ $D('sendCtrlAltDelButton').style.display = "inline";
609
+ } else {
610
+ UI.setMouseButton();
611
+ $D('clipboardButton').style.display = "none";
612
+ $D('showKeyboard').style.display = "none";
613
+ $D('noVNC_extra_keys').style.display = "none";
614
+ $D('sendCtrlAltDelButton').style.display = "none";
615
+ UI.updateXvpVisualState(0);
616
+ }
617
+
618
+ // State change disables viewport dragging.
619
+ // It is enabled (toggled) by direct click on the button
620
+ UI.setViewDrag(false);
621
+
622
+ switch (UI.rfb_state) {
623
+ case 'fatal':
624
+ case 'failed':
625
+ case 'loaded':
626
+ case 'disconnected':
627
+ $D('connectButton').style.display = "";
628
+ $D('disconnectButton').style.display = "none";
629
+ break;
630
+ default:
631
+ $D('connectButton').style.display = "none";
632
+ $D('disconnectButton').style.display = "";
633
+ break;
634
+ }
635
+
636
+ //Util.Debug("<< updateVisualState");
637
+ },
638
+
639
+ // Disable/enable XVP button
640
+ updateXvpVisualState: function(ver) {
641
+ if (ver >= 1) {
642
+ $D('xvpButton').style.display = 'inline';
643
+ } else {
644
+ $D('xvpButton').style.display = 'none';
645
+ // Close XVP panel if open
646
+ if (UI.xvpOpen === true) {
647
+ UI.toggleXvpPanel();
648
+ }
649
+ }
650
+ },
651
+
652
+ // Display the desktop name in the document title
653
+ updateDocumentTitle: function(rfb, name) {
654
+ document.title = name + " - noVNC";
655
+ },
656
+
657
+ clipReceive: function(rfb, text) {
658
+ Util.Debug(">> UI.clipReceive: " + text.substr(0,40) + "...");
659
+ $D('noVNC_clipboard_text').value = text;
660
+ Util.Debug("<< UI.clipReceive");
661
+ },
662
+
663
+ connect: function() {
664
+ UI.closeSettingsMenu();
665
+ UI.toggleConnectPanel();
666
+
667
+ var host = $D('noVNC_host').value;
668
+ var port = $D('noVNC_port').value;
669
+ var password = $D('noVNC_password').value;
670
+ var path = $D('noVNC_path').value;
671
+ if ((!host) || (!port)) {
672
+ throw new Error("Must set host and port");
673
+ }
674
+
675
+ UI.rfb.set_encrypt(UI.getSetting('encrypt'));
676
+ UI.rfb.set_true_color(UI.getSetting('true_color'));
677
+ UI.rfb.set_local_cursor(UI.getSetting('cursor'));
678
+ UI.rfb.set_shared(UI.getSetting('shared'));
679
+ UI.rfb.set_view_only(UI.getSetting('view_only'));
680
+ UI.rfb.set_repeaterID(UI.getSetting('repeaterID'));
681
+
682
+ UI.rfb.connect(host, port, password, path);
683
+
684
+ //Close dialog.
685
+ setTimeout(UI.setBarPosition, 100);
686
+ $D('noVNC_logo').style.display = "none";
687
+ },
688
+
689
+ disconnect: function() {
690
+ UI.closeSettingsMenu();
691
+ UI.rfb.disconnect();
692
+
693
+ $D('noVNC_logo').style.display = "block";
694
+ UI.connSettingsOpen = false;
695
+ UI.toggleConnectPanel();
696
+ },
697
+
698
+ displayBlur: function() {
699
+ UI.rfb.get_keyboard().set_focused(false);
700
+ UI.rfb.get_mouse().set_focused(false);
701
+ },
702
+
703
+ displayFocus: function() {
704
+ UI.rfb.get_keyboard().set_focused(true);
705
+ UI.rfb.get_mouse().set_focused(true);
706
+ },
707
+
708
+ clipClear: function() {
709
+ $D('noVNC_clipboard_text').value = "";
710
+ UI.rfb.clipboardPasteFrom("");
711
+ },
712
+
713
+ clipSend: function() {
714
+ var text = $D('noVNC_clipboard_text').value;
715
+ Util.Debug(">> UI.clipSend: " + text.substr(0,40) + "...");
716
+ UI.rfb.clipboardPasteFrom(text);
717
+ Util.Debug("<< UI.clipSend");
718
+ },
719
+
720
+ // Enable/disable and configure viewport clipping
721
+ setViewClip: function(clip) {
722
+ var display;
723
+ if (UI.rfb) {
724
+ display = UI.rfb.get_display();
725
+ } else {
726
+ return;
727
+ }
728
+
729
+ var cur_clip = display.get_viewport();
730
+
731
+ if (typeof(clip) !== 'boolean') {
732
+ // Use current setting
733
+ clip = UI.getSetting('clip');
734
+ }
735
+
736
+ if (clip && !cur_clip) {
737
+ // Turn clipping on
738
+ UI.updateSetting('clip', true);
739
+ } else if (!clip && cur_clip) {
740
+ // Turn clipping off
741
+ UI.updateSetting('clip', false);
742
+ display.set_viewport(false);
743
+ $D('noVNC_canvas').style.position = 'static';
744
+ display.viewportChange();
745
+ }
746
+ if (UI.getSetting('clip')) {
747
+ // If clipping, update clipping settings
748
+ $D('noVNC_canvas').style.position = 'absolute';
749
+ var pos = Util.getPosition($D('noVNC_canvas'));
750
+ var new_w = window.innerWidth - pos.x;
751
+ var new_h = window.innerHeight - pos.y;
752
+ display.set_viewport(true);
753
+ display.viewportChange(0, 0, new_w, new_h);
754
+ }
755
+ },
756
+
757
+ // Toggle/set/unset the viewport drag/move button
758
+ setViewDrag: function(drag) {
759
+ var vmb = $D('noVNC_view_drag_button');
760
+ if (!UI.rfb) { return; }
761
+
762
+ if (UI.rfb_state === 'normal' &&
763
+ UI.rfb.get_display().get_viewport()) {
764
+ vmb.style.display = "inline";
765
+ } else {
766
+ vmb.style.display = "none";
767
+ }
768
+
769
+ if (typeof(drag) === "undefined" ||
770
+ typeof(drag) === "object") {
771
+ // If not specified, then toggle
772
+ drag = !UI.rfb.get_viewportDrag();
773
+ }
774
+ if (drag) {
775
+ vmb.className = "noVNC_status_button_selected";
776
+ UI.rfb.set_viewportDrag(true);
777
+ } else {
778
+ vmb.className = "noVNC_status_button";
779
+ UI.rfb.set_viewportDrag(false);
780
+ }
781
+ },
782
+
783
+ // On touch devices, show the OS keyboard
784
+ showKeyboard: function() {
785
+ var kbi = $D('keyboardinput');
786
+ var skb = $D('showKeyboard');
787
+ var l = kbi.value.length;
788
+ if(UI.keyboardVisible === false) {
789
+ kbi.focus();
790
+ try { kbi.setSelectionRange(l, l); } // Move the caret to the end
791
+ catch (err) {} // setSelectionRange is undefined in Google Chrome
792
+ UI.keyboardVisible = true;
793
+ skb.className = "noVNC_status_button_selected";
794
+ } else if(UI.keyboardVisible === true) {
795
+ kbi.blur();
796
+ skb.className = "noVNC_status_button";
797
+ UI.keyboardVisible = false;
798
+ }
799
+ },
800
+
801
+ keepKeyboard: function() {
802
+ clearTimeout(UI.hideKeyboardTimeout);
803
+ if(UI.keyboardVisible === true) {
804
+ $D('keyboardinput').focus();
805
+ $D('showKeyboard').className = "noVNC_status_button_selected";
806
+ } else if(UI.keyboardVisible === false) {
807
+ $D('keyboardinput').blur();
808
+ $D('showKeyboard').className = "noVNC_status_button";
809
+ }
810
+ },
811
+
812
+ keyboardinputReset: function() {
813
+ var kbi = $D('keyboardinput');
814
+ kbi.value = new Array(UI.defaultKeyboardinputLen).join("_");
815
+ UI.lastKeyboardinput = kbi.value;
816
+ },
817
+
818
+ // When normal keyboard events are left uncought, use the input events from
819
+ // the keyboardinput element instead and generate the corresponding key events.
820
+ // This code is required since some browsers on Android are inconsistent in
821
+ // sending keyCodes in the normal keyboard events when using on screen keyboards.
822
+ keyInput: function(event) {
823
+ var newValue = event.target.value;
824
+ var oldValue = UI.lastKeyboardinput;
825
+
826
+ var newLen;
827
+ try {
828
+ // Try to check caret position since whitespace at the end
829
+ // will not be considered by value.length in some browsers
830
+ newLen = Math.max(event.target.selectionStart, newValue.length);
831
+ } catch (err) {
832
+ // selectionStart is undefined in Google Chrome
833
+ newLen = newValue.length;
834
+ }
835
+ var oldLen = oldValue.length;
836
+
837
+ var backspaces;
838
+ var inputs = newLen - oldLen;
839
+ if (inputs < 0) {
840
+ backspaces = -inputs;
841
+ } else {
842
+ backspaces = 0;
843
+ }
844
+
845
+ // Compare the old string with the new to account for
846
+ // text-corrections or other input that modify existing text
847
+ var i;
848
+ for (i = 0; i < Math.min(oldLen, newLen); i++) {
849
+ if (newValue.charAt(i) != oldValue.charAt(i)) {
850
+ inputs = newLen - i;
851
+ backspaces = oldLen - i;
852
+ break;
853
+ }
854
+ }
855
+
856
+ // Send the key events
857
+ for (i = 0; i < backspaces; i++) {
858
+ UI.rfb.sendKey(XK_BackSpace);
859
+ }
860
+ for (i = newLen - inputs; i < newLen; i++) {
861
+ UI.rfb.sendKey(newValue.charCodeAt(i));
862
+ }
863
+
864
+ // Control the text content length in the keyboardinput element
865
+ if (newLen > 2 * UI.defaultKeyboardinputLen) {
866
+ UI.keyboardinputReset();
867
+ } else if (newLen < 1) {
868
+ // There always have to be some text in the keyboardinput
869
+ // element with which backspace can interact.
870
+ UI.keyboardinputReset();
871
+ // This sometimes causes the keyboard to disappear for a second
872
+ // but it is required for the android keyboard to recognize that
873
+ // text has been added to the field
874
+ event.target.blur();
875
+ // This has to be ran outside of the input handler in order to work
876
+ setTimeout(function() { UI.keepKeyboard(); }, 0);
877
+ } else {
878
+ UI.lastKeyboardinput = newValue;
879
+ }
880
+ },
881
+
882
+ keyInputBlur: function() {
883
+ $D('showKeyboard').className = "noVNC_status_button";
884
+ //Weird bug in iOS if you change keyboardVisible
885
+ //here it does not actually occur so next time
886
+ //you click keyboard icon it doesnt work.
887
+ UI.hideKeyboardTimeout = setTimeout(function() { UI.setKeyboard(); },100);
888
+ },
889
+
890
+ showExtraKeys: function() {
891
+ UI.keepKeyboard();
892
+ if(UI.extraKeysVisible === false) {
893
+ $D('toggleCtrlButton').style.display = "inline";
894
+ $D('toggleAltButton').style.display = "inline";
895
+ $D('sendTabButton').style.display = "inline";
896
+ $D('sendEscButton').style.display = "inline";
897
+ $D('showExtraKeysButton').className = "noVNC_status_button_selected";
898
+ UI.extraKeysVisible = true;
899
+ } else if(UI.extraKeysVisible === true) {
900
+ $D('toggleCtrlButton').style.display = "";
901
+ $D('toggleAltButton').style.display = "";
902
+ $D('sendTabButton').style.display = "";
903
+ $D('sendEscButton').style.display = "";
904
+ $D('showExtraKeysButton').className = "noVNC_status_button";
905
+ UI.extraKeysVisible = false;
906
+ }
907
+ },
908
+
909
+ toggleCtrl: function() {
910
+ UI.keepKeyboard();
911
+ if(UI.ctrlOn === false) {
912
+ UI.rfb.sendKey(XK_Control_L, true);
913
+ $D('toggleCtrlButton').className = "noVNC_status_button_selected";
914
+ UI.ctrlOn = true;
915
+ } else if(UI.ctrlOn === true) {
916
+ UI.rfb.sendKey(XK_Control_L, false);
917
+ $D('toggleCtrlButton').className = "noVNC_status_button";
918
+ UI.ctrlOn = false;
919
+ }
920
+ },
921
+
922
+ toggleAlt: function() {
923
+ UI.keepKeyboard();
924
+ if(UI.altOn === false) {
925
+ UI.rfb.sendKey(XK_Alt_L, true);
926
+ $D('toggleAltButton').className = "noVNC_status_button_selected";
927
+ UI.altOn = true;
928
+ } else if(UI.altOn === true) {
929
+ UI.rfb.sendKey(XK_Alt_L, false);
930
+ $D('toggleAltButton').className = "noVNC_status_button";
931
+ UI.altOn = false;
932
+ }
933
+ },
934
+
935
+ sendTab: function() {
936
+ UI.keepKeyboard();
937
+ UI.rfb.sendKey(XK_Tab);
938
+ },
939
+
940
+ sendEsc: function() {
941
+ UI.keepKeyboard();
942
+ UI.rfb.sendKey(XK_Escape);
943
+ },
944
+
945
+ setKeyboard: function() {
946
+ UI.keyboardVisible = false;
947
+ },
948
+
949
+ // iOS < Version 5 does not support position fixed. Javascript workaround:
950
+ setOnscroll: function() {
951
+ window.onscroll = function() {
952
+ UI.setBarPosition();
953
+ };
954
+ },
955
+
956
+ setResize: function () {
957
+ window.onResize = function() {
958
+ UI.setBarPosition();
959
+ };
960
+ },
961
+
962
+ //Helper to add options to dropdown.
963
+ addOption: function(selectbox, text, value) {
964
+ var optn = document.createElement("OPTION");
965
+ optn.text = text;
966
+ optn.value = value;
967
+ selectbox.options.add(optn);
968
+ },
969
+
970
+ setBarPosition: function() {
971
+ $D('noVNC-control-bar').style.top = (window.pageYOffset) + 'px';
972
+ $D('noVNC_mobile_buttons').style.left = (window.pageXOffset) + 'px';
973
+
974
+ var vncwidth = $D('noVNC_screen').style.offsetWidth;
975
+ $D('noVNC-control-bar').style.width = vncwidth + 'px';
976
+ }
977
+
978
+ };
979
+ })();