371 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			HTML
		
	
	
	
			
		
		
	
	
			371 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			HTML
		
	
	
	
<!DOCTYPE html>
 | 
						|
<html>
 | 
						|
<head>
 | 
						|
	<meta charset="UTF-8">
 | 
						|
	<style data-theme="core" type="text/css">
 | 
						|
		:root {
 | 
						|
			--keyMargin: 1px;
 | 
						|
			--keyWidth: calc(45px + var(--keyMargin) * 2);
 | 
						|
		}
 | 
						|
 | 
						|
		html, body {
 | 
						|
			margin: 0; padding: 0;
 | 
						|
			color: black;
 | 
						|
			user-select: none;
 | 
						|
			font-size: 25px;
 | 
						|
		}
 | 
						|
 | 
						|
		.keyHolder {
 | 
						|
			margin: 5px;
 | 
						|
			display: inline-block;
 | 
						|
		}
 | 
						|
 | 
						|
		.key, .noShow {
 | 
						|
			display: inline-block;
 | 
						|
			box-sizing: border-box;
 | 
						|
			border: 1px solid black;
 | 
						|
			border-radius: 4px;
 | 
						|
			background: rgba(255, 255, 255, .7);
 | 
						|
			text-align: center;
 | 
						|
			cursor: pointer;
 | 
						|
			padding-top: 10px;
 | 
						|
			vertical-align: middle;
 | 
						|
 | 
						|
			margin: var(--keyMargin);
 | 
						|
			width: calc(var(--keyWidth) - var(--keyMargin) * 2);
 | 
						|
			height: calc(var(--keyWidth) - var(--keyMargin) * 2);
 | 
						|
		}
 | 
						|
 | 
						|
		.noShow {
 | 
						|
			border: none;
 | 
						|
			background: transparent !important;
 | 
						|
			cursor: inherit;
 | 
						|
		}
 | 
						|
 | 
						|
		.key:hover {
 | 
						|
			background: #EEE;
 | 
						|
		}
 | 
						|
 | 
						|
		.key.pressed, .key[data-pressed=true] {
 | 
						|
			background: #555;
 | 
						|
		}
 | 
						|
 | 
						|
		.key.s1x1_25 { width: calc(var(--keyWidth) * 1.25 - var(--keyMargin) * 2); }
 | 
						|
		.key.s1x1_5 { width: calc(var(--keyWidth) * 1.5 - var(--keyMargin) * 2); }
 | 
						|
		.key.s1x2 { width: calc(var(--keyWidth) * 2 - var(--keyMargin) * 2); }
 | 
						|
		.key.s1x1_75 { width: calc(var(--keyWidth) * 1.75 - var(--keyMargin) * 2); }
 | 
						|
		.key.s1x2_25 { width: calc(var(--keyWidth) * 2.25 - var(--keyMargin) * 2); }
 | 
						|
		.key.s1x2_75 { width: calc(var(--keyWidth) * 2.75 - var(--keyMargin) * 2); }
 | 
						|
		.key.s1x3_75 { width: calc(var(--keyWidth) * 3.75 - var(--keyMargin) * 2); }
 | 
						|
		.key.s1x4_75 { width: calc(var(--keyWidth) * 4.75 - var(--keyMargin) * 2); }
 | 
						|
		.key.s1x6_5 { width: calc(var(--keyWidth) * 6.5 - var(--keyMargin) * 2); }
 | 
						|
 | 
						|
		.key.s2x1 {
 | 
						|
			height: calc(var(--keyWidth) * 2 - var(--keyMargin) * 2);
 | 
						|
			float: right;
 | 
						|
			padding-top: 32px;
 | 
						|
		}
 | 
						|
 | 
						|
		.smallText {
 | 
						|
			font-size: 50%;
 | 
						|
			padding-top: 15px;
 | 
						|
		}
 | 
						|
	</style>
 | 
						|
	<style data-theme="0" type="text/css">
 | 
						|
		.key {
 | 
						|
			border-radius: 6px;
 | 
						|
		}
 | 
						|
	</style>
 | 
						|
	<style data-theme="1" type="text/css">
 | 
						|
		body {
 | 
						|
			text-transform: uppercase;
 | 
						|
			color: white;
 | 
						|
			font-size: 20px;
 | 
						|
			font-family: monospace;
 | 
						|
		}
 | 
						|
		.key {
 | 
						|
			border-color: white;
 | 
						|
			background: rgba(0, 0, 0, .6);
 | 
						|
			padding-top: 10px;
 | 
						|
			border-radius: 0;
 | 
						|
		}
 | 
						|
		.key:hover {
 | 
						|
			background: #333;
 | 
						|
		}
 | 
						|
		.key.pressed, .key[data-pressed=true] {
 | 
						|
			background: #CCC;
 | 
						|
			position: relative;
 | 
						|
			top: 1px; left: 1px;
 | 
						|
 | 
						|
		}
 | 
						|
		.smallText {
 | 
						|
			padding-top: 16px;
 | 
						|
		}
 | 
						|
		.s2x1 { padding-top: 32px; }
 | 
						|
		.s2x1.kpEnter { padding-top: 62px; }
 | 
						|
	</style>
 | 
						|
	<style data-theme="2" type="text/css">
 | 
						|
		:root {
 | 
						|
			--keyMargin: 1px;
 | 
						|
			--keyWidth: calc(46px + var(--keyMargin) * 2);
 | 
						|
		}
 | 
						|
		body {
 | 
						|
			font-family: sans-serif;
 | 
						|
		}
 | 
						|
		.keyHolder {
 | 
						|
			background: white;
 | 
						|
			margin: 1px;
 | 
						|
			padding: 4px;
 | 
						|
			border-radius: 7px;
 | 
						|
		}
 | 
						|
		.key {
 | 
						|
			padding-top: 9px;
 | 
						|
			border-color: #777;
 | 
						|
		}
 | 
						|
		.key:hover {
 | 
						|
			background: #FFFAE2;
 | 
						|
		}
 | 
						|
		.key.pressed, .key[data-pressed=true] {
 | 
						|
			background: rgba(146, 190, 255, 1);
 | 
						|
			position: relative;
 | 
						|
			top: 1px; left: 1px;
 | 
						|
		}
 | 
						|
		.smallText {
 | 
						|
			padding-top: 16px;
 | 
						|
		}
 | 
						|
	</style>
 | 
						|
	<style data-theme="3" type="text/css">
 | 
						|
		:root {
 | 
						|
			--keyMargin: 2px;
 | 
						|
			--keyWidth: calc(43px + var(--keyMargin) * 2);
 | 
						|
		}
 | 
						|
		body {
 | 
						|
			/*text-transform: uppercase;*/
 | 
						|
			color: #FFF;
 | 
						|
			font-size: 20px;
 | 
						|
			font-family: monospace;
 | 
						|
		}
 | 
						|
		.key {
 | 
						|
			border-color: #0F0;
 | 
						|
			background: rgba(0, 0, 0, 1);
 | 
						|
			padding-top: 10px;
 | 
						|
			box-shadow: 0 0 10px #0F0;
 | 
						|
		}
 | 
						|
		.key:hover {
 | 
						|
			background: #000;
 | 
						|
 | 
						|
			border-width: 2px;
 | 
						|
 | 
						|
		}
 | 
						|
		.key.pressed, .key[data-pressed=true] {
 | 
						|
			background: #0F0;
 | 
						|
			color: black;
 | 
						|
		}
 | 
						|
		.smallText {
 | 
						|
			padding-top: 16px;
 | 
						|
		}
 | 
						|
		.s2x1 { padding-top: 32px; }
 | 
						|
	</style>
 | 
						|
 | 
						|
</head>
 | 
						|
<body>
 | 
						|
	<div id="mainKeys" class="keyHolder"></div>
 | 
						|
	<div id="navKeys" class="keyHolder"></div>
 | 
						|
	<div id="numberKeys" class="keyHolder"></div>
 | 
						|
 | 
						|
	<script type="application/javascript">
 | 
						|
		//API funcs:
 | 
						|
		function textTyped(text) { console.log(`Typed: ${text} (u0x${text.charCodeAt(0).toString(16)})`)};
 | 
						|
		function commandEntered(action, shiftPressed) { console.log(`Command: ${action} Shift: ${shiftPressed}`)};
 | 
						|
 | 
						|
 | 
						|
 | 
						|
		function capsLockPressed() {
 | 
						|
			shiftOn = capsLockOn = !capsLockOn;
 | 
						|
			setShifted(shiftOn);
 | 
						|
		}
 | 
						|
 | 
						|
		function shiftPressed() {
 | 
						|
			capsLockOn = false;
 | 
						|
			shiftOn = !shiftOn;
 | 
						|
			setShifted(shiftOn);
 | 
						|
		}
 | 
						|
 | 
						|
		var allKeys = [];
 | 
						|
		var shiftOn = false;
 | 
						|
		var capsLockOn = false;
 | 
						|
 | 
						|
		function generateKeys(element, keys) {
 | 
						|
			var parent = document.getElementById(element);
 | 
						|
 | 
						|
			for (var i = 0; i < keys.length; i++) {
 | 
						|
				for (var j = 0; j < keys[i].length; j++) {
 | 
						|
					var keyInfo = keys[i][j];
 | 
						|
 | 
						|
					if (typeof keyInfo == "string") {
 | 
						|
						keyInfo = {
 | 
						|
							text: keyInfo[0],
 | 
						|
							upperText: keyInfo[1] || keyInfo[0].toUpperCase(),
 | 
						|
						};
 | 
						|
					}
 | 
						|
					keyInfo.label = keyInfo.label || keyInfo.text || '';
 | 
						|
					keyInfo.upperLabel = keyInfo.upperText ? keyInfo.upperText : keyInfo.label;
 | 
						|
					keyInfo.size = keyInfo.size || "1x1";
 | 
						|
					keyInfo.smallText = keyInfo.smallText === undefined ? keyInfo.label.length > 1 : keyInfo.smallText;
 | 
						|
 | 
						|
					allKeys.push(keyInfo);
 | 
						|
 | 
						|
					var keyEl = document.createElement("span");
 | 
						|
					keyEl.className = `${keyInfo.noShow ? "noShow" : "key"} s${keyInfo.size} ${keyInfo.smallText ? "smallText" : ""}`;
 | 
						|
					keyEl.setAttribute("data-keyId", allKeys.length - 1);
 | 
						|
					keyEl.textContent = keyInfo.label;
 | 
						|
					parent.appendChild(keyEl);
 | 
						|
					if (keyInfo.title) keyEl.title = keyInfo.title;
 | 
						|
 | 
						|
					keyInfo.el = keyEl;
 | 
						|
					keyInfo.baseClass = keyEl.className;
 | 
						|
				}
 | 
						|
 | 
						|
				var br = document.createElement("br");
 | 
						|
				parent.appendChild(br);
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		function setShifted(shifted) {
 | 
						|
			for (var i = 0; i < allKeys.length; i++) {
 | 
						|
				allKeys[i].el.textContent = shifted ? allKeys[i].upperLabel || allKeys[i].label : allKeys[i].label;
 | 
						|
				if (allKeys[i].isPressed) {
 | 
						|
					allKeys[i].el.setAttribute("data-pressed", allKeys[i].isPressed());
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		addEventListener("mousedown", ev => {
 | 
						|
			var keyId = ev.target.getAttribute("data-keyId");
 | 
						|
			if (keyId === null) return;
 | 
						|
 | 
						|
			var keyInfo = allKeys[keyId];
 | 
						|
 | 
						|
			var press = () => {
 | 
						|
				ev.preventDefault();
 | 
						|
				ev.target.className += " pressed";
 | 
						|
				setTimeout(() => ev.target.className = keyInfo.baseClass, 50);
 | 
						|
			};
 | 
						|
 | 
						|
			if (keyInfo.action) {
 | 
						|
				keyInfo.action();
 | 
						|
				press();
 | 
						|
				return;
 | 
						|
			}
 | 
						|
 | 
						|
			if (keyInfo.command) {
 | 
						|
				commandEntered(keyInfo.command, shiftOn);
 | 
						|
				press();
 | 
						|
				return;
 | 
						|
			}
 | 
						|
 | 
						|
			if (keyInfo.text) {
 | 
						|
				var text = shiftOn ? keyInfo.upperText || keyInfo.text : keyInfo.text;
 | 
						|
 | 
						|
				textTyped(text);
 | 
						|
				press();
 | 
						|
 | 
						|
				if (shiftOn && !capsLockOn) {
 | 
						|
					shiftOn = false;
 | 
						|
					setShifted(shiftOn);
 | 
						|
				}
 | 
						|
				return;
 | 
						|
			}
 | 
						|
 | 
						|
		}, true);
 | 
						|
 | 
						|
		var currentScheme = 0;
 | 
						|
		function cycleColorScheme() {
 | 
						|
			currentScheme = (currentScheme + 1) % 4;
 | 
						|
			setColorScheme(currentScheme);
 | 
						|
		}
 | 
						|
 | 
						|
		function setColorScheme(index) {
 | 
						|
			for (var el of document.getElementsByTagName("style")) {
 | 
						|
				if (el.getAttribute("data-theme") == "core") continue;
 | 
						|
				if (el.getAttribute("data-theme") == index) el.disabled = false;
 | 
						|
				else el.disabled = true;
 | 
						|
			}
 | 
						|
			currentScheme = +index;
 | 
						|
			localStorage.colorScheme = index;
 | 
						|
		}
 | 
						|
 | 
						|
		setColorScheme(localStorage.colorScheme == undefined ? 2 : localStorage.colorScheme);
 | 
						|
 | 
						|
 | 
						|
		var mainKeys = [
 | 
						|
			["`~", "1!", "2@", "3#", "4$", "5%", "6^", "7&", "8*", "9(", "0)", "-_", "=+", {label: "←", command: "backspace", size: "1x2"}],
 | 
						|
			[
 | 
						|
				{label: "Tab", text: "\t", size: "1x1_5", smallText: false},
 | 
						|
				"q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "[{", "]}",
 | 
						|
				{text: "\\", upperText: "|", size: "1x1_5"},
 | 
						|
			], [
 | 
						|
				{label: "Caps\nLock", size: "1x1_75 capsLock", action: capsLockPressed, isPressed: () => capsLockOn},
 | 
						|
				"a", "s", "d", "f", "g", "h", "j", "k", "l", ";:", "'\"",
 | 
						|
				{label: "↵", text: "\n", size: "1x2_25"},
 | 
						|
			], [
 | 
						|
				{label: "Shift", action: shiftPressed, size: "1x2_25", isPressed: () => shiftOn, smallText: false},
 | 
						|
				"z", "x", "c", "v", "b", "n", "m", ",<", ".>", "/?",
 | 
						|
				{label: "Shift", action: shiftPressed, size: "1x2_75", isPressed: () => shiftOn, smallText: false},
 | 
						|
			],
 | 
						|
			[
 | 
						|
				// {label: "", size: "1x3_75", noShow: true},
 | 
						|
 | 
						|
				{label: "Sel All", size: "1x1_25", command: "selectAll"},
 | 
						|
				{label: "↶", size: "1x1_25", command: "undo", title: "Undo"},
 | 
						|
				{label: "↷", size: "1x1_25", command: "redo", title: "Redo"},
 | 
						|
 | 
						|
				// {label: "Cut", size: "1x1_25", command: "cut"},
 | 
						|
				// {label: "Copy", size: "1x1_25", command: "copy"},
 | 
						|
				// {label: "Paste", size: "1x1_25", command: "paste"},
 | 
						|
 | 
						|
				{label: "", size: "1x6_5", text: " "},//space
 | 
						|
 | 
						|
				// {label: "Select All", size: "1x1_75", command: "selectAll"},
 | 
						|
				// {label: "↶", size: "1x1_5", command: "undo", title: "Undo"},
 | 
						|
				// {label: "↷", size: "1x1_5", command: "redo", title: "Redo"},
 | 
						|
 | 
						|
				{label: "Cut", size: "1x1_5", command: "cut"},
 | 
						|
				{label: "Copy", size: "1x1_75", command: "copy"},
 | 
						|
				{label: "Paste", size: "1x1_5", command: "paste"},
 | 
						|
 | 
						|
				// {label: "", size: "1x4_75", noShow: true},
 | 
						|
			]
 | 
						|
		];
 | 
						|
 | 
						|
		var navKeys = [
 | 
						|
			[{label: "Insert", command: "insert"}, {label: "Home", command: "home"}, {label: "PgUp", command: "pageUp"}],
 | 
						|
			[{label: "Delete", command: "delete"}, {label: "End", command: "end"}, {label: "PgDn", command: "pageDown"}],
 | 
						|
			[{noShow: true}],
 | 
						|
			[
 | 
						|
				{label: "⇤", command: "wordLeft", title: "Move one word left"},
 | 
						|
				{label: "↑", command: "up"},
 | 
						|
				{label: "⇥", command: "wordRight", title: "Move one word right"}
 | 
						|
			],
 | 
						|
			[{label: "←", command: "left"}, {label: "↓", command: "down"}, {label: "→", command: "right"}],
 | 
						|
		];
 | 
						|
 | 
						|
		var numberKeys = [
 | 
						|
			[
 | 
						|
				// {noShow: true},
 | 
						|
				{label: "✩", smallText: true, action: cycleColorScheme},
 | 
						|
				"/", "*", "-",
 | 
						|
			],
 | 
						|
			["7", "8", "9", {text: "+", size: "2x1"}],
 | 
						|
			["4", "5", "6"],
 | 
						|
			["1", "2", "3", {label: "↵", text: "\n", size: "2x1 kpEnter"}],
 | 
						|
			[{text: "0", size: "1x2"}, "."],
 | 
						|
		];
 | 
						|
 | 
						|
		generateKeys("mainKeys", mainKeys);
 | 
						|
		generateKeys("navKeys", navKeys);
 | 
						|
		generateKeys("numberKeys", numberKeys);
 | 
						|
 | 
						|
	</script>
 | 
						|
</body>
 | 
						|
</html> |