ESPTerm - ESP8266 terminal emulator. Branches: [master] patches, [work] next release
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
espterm-firmware/html_orig/script.js

271 lines
5.7 KiB

//region Libs / utils
/*
* DOM selector
*
* Usage:
* $('div');
* $('#name');
* $('.name');
*
*
* Copyright (C) 2011 Jed Schmidt <http://jed.is> - WTFPL
* More: https://gist.github.com/991057
*
*/
var $ = function(
a, // take a simple selector like "name", "#name", or ".name", and
b // an optional context, and
){
a = a.match(/^(\W)?(.*)/); // split the selector into name and symbol.
return( // return an element or list, from within the scope of
b // the passed context
|| document // or document,
)[
"getElement" + ( // obtained by the appropriate method calculated by
a[1]
? a[1] == "#"
? "ById" // the node by ID,
: "sByClassName" // the nodes by class name, or
: "sByTagName" // the nodes by tag name,
)
](
a[2] // called with the name.
)
};
/*
* Create DOM element
*
* Usage:
* var el = m('<h1>Hello</h1>');
* document.body.appendChild(el);
*
*
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
* Version 2, December 2004
*
* Copyright (C) 2011 Jed Schmidt <http://jed.is> - WTFPL
* More: https://gist.github.com/966233
*
*/
var m = function(
a, // an HTML string
b, // placeholder
c // placeholder
){
b = document; // get the document,
c = b.createElement("p"); // create a container element,
c.innerHTML = a; // write the HTML to it, and
a = b.createDocumentFragment(); // create a fragment.
while ( // while
b = c.firstChild // the container element has a first child
) a.appendChild(b); // append the child to the fragment,
return a // and then return the fragment.
};
//endregion
//
// Terminal class
//
(function () {
function make(e) {return document.createElement(e)}
var W = 26, H = 10; //26, 10
var cursor = {a: false, x: 0, y: 0, suppress: false, hidden: false};
var screen = [];
/** Colors table */
var CLR = [// dark gray #2E3436
// 0 black, 1 red, 2 green, 3 yellow
// 4 blue, 5 mag, 6 cyan, 7 white
'#111213','#CC0000','#4E9A06','#C4A000',
'#3465A4','#75507B','#06989A','#D3D7CF',
// BRIGHT
// 8 black, 9 red, 10 green, 11 yellow
// 12 blue, 13 mag, 14 cyan, 15 white
'#555753','#EF2929','#8AE234','#FCE94F',
'#729FCF','#AD7FA8','#34E2E2','#EEEEEC'
];
/** Clear screen */
function cls() {
screen.forEach(function(cell, i) {
cell.t = ' ';
cell.fg = 7;
cell.bg = 0;
blit(cell);
});
}
/** Set text and color at XY */
function cellAt(y, x) {
return screen[y*W+x];
}
/** Get cell under cursor */
function cursorCell() {
return cellAt(cursor.y, cursor.x);
}
/** Enable or disable cursor visibility */
function cursorEnable(enable) {
cursor.hidden = !enable;
cursor.a &= enable;
blit(cursorCell(), cursor.a);
}
/** Safely move cursor */
function cursorSet(y, x) {
// Hide and prevent from showing up during the move
cursor.suppress = true;
blit(cursorCell(), false);
cursor.x = x;
cursor.y = y;
// Show again
cursor.suppress = false;
blit(cursorCell(), cursor.a);
}
/** Update cell on display. inv = invert (for cursor) */
function blit(cell, inv) {
var e = cell.e, fg, bg;
// Colors
fg = inv ? cell.bg : cell.fg;
bg = inv ? cell.fg : cell.bg;
// Update
e.innerText = (cell.t+' ')[0];
e.style.color = colorHex(fg);
e.style.backgroundColor = colorHex(bg);
e.style.fontWeight = fg > 7 ? 'bold' : 'normal';
}
/** Show entire screen */
function blitAll() {
screen.forEach(function(cell, i) {
/* Invert if under cursor & cursor active */
var inv = cursor.a && (i == cursor.y*W+cursor.x);
blit(cell, inv);
});
}
/** Load screen content from a 'binary' sequence */
function load(seq) {
if (seq.length != W*H*3) throw "Bad data format.";
// primitive format with 3 chars per cell: letter, fg [hex], bg [hex]
for (var i = 0; i < W * H; i++) {
var cell = screen[i];
cell.t = seq[i*3];
cell.fg = parseInt(seq[i*3+1], 16);
cell.bg = parseInt(seq[i*3+2], 16);
}
blitAll();
}
/** Parse color */
function colorHex(c) {
var c = parseInt(c);
if (c < 0 || c > 15) c = 0;
return CLR[c];
}
/** Init the terminal */
function init() {
/* Build screen & show */
var e, scr = $('#screen');
for(var i = 0; i < W*H; i++) {
e = make('span');
/* End of line */
if ((i > 0) && (i % W == 0)) {
scr.appendChild(make('br'));
}
/* The cell */
scr.appendChild(e);
var cell = {t: ' ', fg: 7, bg: 0, e: e};
screen.push(cell);
blit(cell);
}
/* Cursor blinking */
setInterval(function() {
cursor.a = !cursor.a;
if (cursor.hidden) {
cursor.a = false;
}
if (!cursor.suppress) {
blit(cursorCell(), cursor.a);
}
}, 500);
}
// publish
window.Term = {
init: init,
load: load,
setCursor: cursorSet,
enableCursor: cursorEnable,
clear: cls,
};
})();
//
// Connection class
//
(function() {
var wsUri = "ws://"+window.location.host+"/ws/update.cgi";
var ws;
function onOpen(evt) {
console.log("CONNECTED");
}
function onClose(evt) {
console.error("SOCKET CLOSED");
}
function onMessage(evt) {
console.log("Message received!", evt.data);
// TODO process
}
function onError(evt) {
console.error(evt.data);
}
function doSend(message) {
ws.send(message);
}
function init() {
ws = new WebSocket(wsUri);
ws.onopen = onOpen;
ws.onclose = onClose
ws.onmessage = onMessage;
ws.onerror = onError;
console.log("Opening socket.");
}
window.Conn = {
ws: null,
init: init,
};
})();
function init() {
Term.init();
Conn.init();
}