mirror of
https://github.com/tsl0922/ttyd.git
synced 2025-12-22 11:54:19 +01:00
Move to xterm.js for CJK and IME support (#22)
This commit is contained in:
109
html/js/app.js
Normal file
109
html/js/app.js
Normal file
@@ -0,0 +1,109 @@
|
||||
(function() {
|
||||
var terminalContainer = document.getElementById('terminal-container'),
|
||||
httpsEnabled = window.location.protocol == "https:",
|
||||
url = (httpsEnabled ? 'wss://' : 'ws://') + window.location.host + window.location.pathname + 'ws',
|
||||
protocols = ["tty"],
|
||||
autoReconnect = -1,
|
||||
term, pingTimer;
|
||||
|
||||
var openWs = function() {
|
||||
var ws = new WebSocket(url, protocols);
|
||||
|
||||
ws.onopen = function(event) {
|
||||
if (typeof tty_auth_token !== 'undefined') {
|
||||
ws.send(JSON.stringify({AuthToken: tty_auth_token}));
|
||||
}
|
||||
pingTimer = setInterval(sendPing, 30 * 1000, ws);
|
||||
|
||||
if (typeof term !== 'undefined') {
|
||||
term.destroy();
|
||||
}
|
||||
|
||||
term = new Terminal();
|
||||
|
||||
term.on('resize', function (size) {
|
||||
if (ws.readyState === WebSocket.OPEN) {
|
||||
ws.send("2" + JSON.stringify({columns: size.cols, rows: size.rows}));
|
||||
}
|
||||
setTimeout(function() {
|
||||
term.showOverlay(size.cols + 'x' + size.rows);
|
||||
}, 500);
|
||||
});
|
||||
term.on("data", function(data) {
|
||||
if (ws.readyState === WebSocket.OPEN) {
|
||||
ws.send("0" + data);
|
||||
}
|
||||
});
|
||||
window.onresize = function(event) {
|
||||
term.fit();
|
||||
};
|
||||
|
||||
while (terminalContainer.firstChild) {
|
||||
terminalContainer.removeChild(terminalContainer.firstChild);
|
||||
}
|
||||
|
||||
term.open(terminalContainer);
|
||||
term.fit();
|
||||
term.focus();
|
||||
};
|
||||
|
||||
ws.onmessage = function(event) {
|
||||
var data = event.data.slice(1);
|
||||
switch(event.data[0]) {
|
||||
case '0':
|
||||
term.write(decodeURIComponent(escape(window.atob(data))));
|
||||
break;
|
||||
case '1': // pong
|
||||
break;
|
||||
case '2':
|
||||
document.title = data;
|
||||
break;
|
||||
case '3':
|
||||
var preferences = JSON.parse(data);
|
||||
Object.keys(preferences).forEach(function(key) {
|
||||
console.log("Setting " + key + ": " + preferences[key]);
|
||||
term.setOption(key, preferences[key]);
|
||||
});
|
||||
break;
|
||||
case '4':
|
||||
autoReconnect = JSON.parse(data);
|
||||
console.log("Enabling reconnect: " + autoReconnect + " seconds")
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
ws.onclose = function(event) {
|
||||
if (term) {
|
||||
term.off('data');
|
||||
term.off('resize');
|
||||
term.showOverlay("Connection Closed", null);
|
||||
}
|
||||
clearInterval(pingTimer);
|
||||
if (autoReconnect > 0) {
|
||||
setTimeout(openWs, autoReconnect * 1000);
|
||||
}
|
||||
};
|
||||
|
||||
ws.onerror = function(event) {
|
||||
var errorNode = document.createElement('div');
|
||||
errorNode.style.cssText = [
|
||||
"color: red",
|
||||
"background-color: white",
|
||||
"font-size: x-large",
|
||||
"opacity: 0.75",
|
||||
"text-align: center",
|
||||
"margin: 1em",
|
||||
"padding: 0.2em",
|
||||
"border: 0.1em dotted #ccc"
|
||||
].join(";");
|
||||
errorNode.textContent = "Websocket handshake failed!";
|
||||
terminalContainer.insertBefore(errorNode, terminalContainer.firstChild);
|
||||
};
|
||||
};
|
||||
|
||||
var sendPing = function(ws) {
|
||||
ws.send("1");
|
||||
};
|
||||
|
||||
openWs();
|
||||
})()
|
||||
56
html/js/overlay/overlay.js
Normal file
56
html/js/overlay/overlay.js
Normal file
@@ -0,0 +1,56 @@
|
||||
// ported from hterm.Terminal.prototype.showOverlay
|
||||
Terminal.prototype.showOverlay = function(msg, timeout) {
|
||||
if (!this.overlayNode_) {
|
||||
if (!this.element)
|
||||
return;
|
||||
this.overlayNode_ = document.createElement('div');
|
||||
this.overlayNode_.style.cssText = (
|
||||
'border-radius: 15px;' +
|
||||
'font-size: xx-large;' +
|
||||
'opacity: 0.75;' +
|
||||
'padding: 0.2em 0.5em 0.2em 0.5em;' +
|
||||
'position: absolute;' +
|
||||
'-webkit-user-select: none;' +
|
||||
'-webkit-transition: opacity 180ms ease-in;' +
|
||||
'-moz-user-select: none;' +
|
||||
'-moz-transition: opacity 180ms ease-in;');
|
||||
|
||||
this.overlayNode_.addEventListener('mousedown', function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}, true);
|
||||
}
|
||||
this.overlayNode_.style.color = "#101010";
|
||||
this.overlayNode_.style.backgroundColor = "#f0f0f0";
|
||||
|
||||
this.overlayNode_.textContent = msg;
|
||||
this.overlayNode_.style.opacity = '0.75';
|
||||
|
||||
if (!this.overlayNode_.parentNode)
|
||||
this.element.appendChild(this.overlayNode_);
|
||||
|
||||
var divSize = this.element.getBoundingClientRect();
|
||||
var overlaySize = this.overlayNode_.getBoundingClientRect();
|
||||
|
||||
this.overlayNode_.style.top =
|
||||
(divSize.height - overlaySize.height) / 2 + 'px';
|
||||
this.overlayNode_.style.left = (divSize.width - overlaySize.width) / 2 + 'px';
|
||||
|
||||
var self = this;
|
||||
|
||||
if (this.overlayTimeout_)
|
||||
clearTimeout(this.overlayTimeout_);
|
||||
|
||||
if (timeout === null)
|
||||
return;
|
||||
|
||||
this.overlayTimeout_ = setTimeout(function() {
|
||||
self.overlayNode_.style.opacity = '0';
|
||||
self.overlayTimeout_ = setTimeout(function() {
|
||||
if (self.overlayNode_.parentNode)
|
||||
self.overlayNode_.parentNode.removeChild(self.overlayNode_);
|
||||
self.overlayTimeout_ = null;
|
||||
self.overlayNode_.style.opacity = '0.75';
|
||||
}, 200);
|
||||
}, timeout || 1500);
|
||||
};
|
||||
Reference in New Issue
Block a user