A bit of UI work

This commit is contained in:
Neale Pickett 2020-04-20 22:12:30 -06:00
parent 0677d7171c
commit 7ba5ee836e
3 changed files with 245 additions and 155 deletions

View File

@ -2,82 +2,107 @@
<html>
<head>
<title>Vail</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Material Design Lite -->
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
<link rel="stylesheet" href="https://code.getmdl.io/1.3.0/material.teal-purple.min.css">
<script defer src="https://code.getmdl.io/1.3.0/material.min.js"></script>
<!-- Vail stuff -->
<script src="vail.js"></script>
<link rel="stylesheet" href="vail.css">
</head>
<body>
<div>
<div class="mdl-layout mdl-js-layout">
<header class="mdl-layout__header mdl-layout__header--scroll">
<div class="mdl-layout__header-row">
<!-- Title -->
<span class="mdl-layout-title">Vail</span>
<!-- Add spacer, to align navigation to the right -->
<div class="mdl-layout-spacer"></div>
<!-- Navigation -->
<nav class="mdl-navigation">
<a class="mdl-navigation__link" href="">Link</a>
<a class="mdl-navigation__link" href="">Link</a>
<a class="mdl-navigation__link" href="">Link</a>
<a class="mdl-navigation__link" href="">Link</a>
</nav>
</div>
</header>
<div class="mdl-layout__drawer">
<span class="mdl-layout-title">Title</span>
<nav class="mdl-navigation">
<a class="mdl-navigation__link" href="">Link</a>
<a class="mdl-navigation__link" href="">Link</a>
<a class="mdl-navigation__link" href="">Link</a>
<a class="mdl-navigation__link" href="">Link</a>
</nav>
</div>
<main class="mdl-layout__content">
<div class="flex">
<div class="mdl-card mdl-shadow--4dp">
<div class="mdl-card__title">
<h2 class="mdl-card__title-text">
Code Tree
</h2>
</div>
<div class="mdl-card__supporting-text">
<img src="code-tree.png">
</div>
</div>
<div>
<table>
<div class="mdl-card mdl-shadow--4dp">
<div class="mdl-card__title">
<h2 class="mdl-card__title-text">
Input
</h2>
</div>
<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
<div class="mdl-tabs__tab-bar">
<a href="#iambic" class="mdl-tabs__tab is-active">Iambic</a>
<a href="#straight" class="mdl-tabs__tab">Straight Key</a>
</div>
<div class="mdl-tabs__panel is-active" id="iambic">
<table style="width: 100%; text-align: center;">
<tr>
<th>Dot</th>
<td><code>,</code>, <code>w</code>, left mouse button</td>
<td>
<button class="key mdl-button mdl-js-button mdl-button--raised mdl-button--colored">
dit
</button>
</td>
<td>
<button class="key mdl-button mdl-js-button mdl-button--raised mdl-button--colored">
dah
</button>
</td>
</tr>
<tr>
<th>Dash</th>
<td><code>.</code>, <code>v</code>, right mouse button</td>
<td>
<code>.</code> or <code></code>
</td>
<td>
<code>/</code> or <code>z</code>
</td>
</tr>
</table>
</div>
<div>
<pre>
a : .-
b : -...
c : -.-.
d : -..
e : .
f : ..-.
g : --.
h : ....
i : ..
j : .---
k : -.-
l : .-..
m : --
n : -.
o : ---
p : .--.
q : --.-
r : .-.
s : ...
t : -
u : ..-
v : ...-
w : .--
x : -..-
y : -.--
z : --..
0 : -----
1 : .----
2 : ..---
3 : ...--
4 : ....-
5 : .....
6 : -....
7 : --...
8 : ---..
9 : ----.
. : .-.-.-
, : --..--
: : ---...
? : ..--..
' : .----.
- : -....-
/ : -..-.
" : .-..-.
@ : .--.-.
= : -...-
! : -.-.--
</pre>
<div class="mdl-tabs__panel" id="straight">
<button class="key mdl-button mdl-js-button mdl-button--raised mdl-button--colored">
Key
</button>
</div>
</div>
</div>
<div>
<h1>Vail</h1>
<div class="mdl-card mdl-shadow--4dp">
<div class="mdl-card__title">
<h2 class="mdl-card__title-text">
Vail
</h2>
</div>
<div class="mdl-card__supporting-text">
<p>
This is a CW repeater,
named after Alfred Vail,
@ -98,10 +123,15 @@ z : --..
let me know and I'll come up with something for you.
</p>
</div>
</div>
<div>
<h2>Why does this exist?</h2>
<div class="mdl-card mdl-shadow--4dp">
<div class="mdl-card__title">
<h2 class="mdl-card__title-text">
Why Does This Exist?
</h2>
</div>
<div class="mdl-card__supporting-text">
<p>
I need a place to practice CW with actual human beings,
and I want it to be as close as possible to what I'd experience on a radio.
@ -109,14 +139,20 @@ z : --..
Nothing else like this exists on the Internet, as far as I can tell.
</p>
<h2>Who made it?</h2>
<h3>Who made it?</h3>
<p>
<a href="mailto:neale@woozle.org">Neale Pickett</a> kd7oqi
</p>
<h2>Future plans</h2>
</div>
</div>
<div class="mdl-card mdl-shadow--4dp">
<div class="mdl-card__title">
<h3 class="mdl-card__title-text">Future plans</h3>
</div>
<div class="mdl-card__supporting_text">
<ul>
<li>Move to a more permanent URL</li>
<li>Make this page less ugly</li>
@ -128,12 +164,16 @@ z : --..
</ul>
<h2>How can I help?</h2>
<h3>How can I help?</h3>
<ul>
<li>Improve the <a href="https://github.com/nealey/vail/">source code</a></li>
<li><a href="mailto:neale@woozle.org">Email me</a> and let me know you're using it</li>
</ul>
</div>
</div>
</div>
</main>
</div>
</body>
</html>

View File

@ -1,8 +1,13 @@
body {
background-color: #ccc;
font-family: sans-serif;
.flex {
display: flex;
flex-wrap: wrap;
align-items: flex-start;
justify-content: space-around;
}
.key {
width: 100%;
height: 6em;
}
code {

View File

@ -1,46 +1,89 @@
var ac = new AudioContext()
var gain = ac.createGain()
gain.connect(ac.destination)
gain.gain.value = 0.1
// jshint asi:true
var short = 80
var long = 200
var audioFreq = 660
var audioFreqMe = audioFreq * 6 / 5 // I think this works out to a minor third
var myosc
var ac = new AudioContext()
var mygain = ac.createGain()
mygain.connect(ac.destination)
mygain.gain.value = 0
var myosc = ac.createOscillator()
myosc.connect(mygain)
myosc.frequency.value = audioFreqMe
myosc.start()
var theirgain = ac.createGain()
theirgain.connect(ac.destination)
theirgain.gain.value = 0
var theirosc = ac.createOscillator()
theirosc.connect(theirgain)
theirosc.frequency.value = audioFreq
theirosc.start()
var repeatInterval
function message(event) {
let now = ac.currentTime
let duration = Number(event.data) || 0
duration = Math.min(duration, long)
let osc = ac.createOscillator()
osc.connect(gain)
osc.frequency.value = audioFreq
osc.start(ac.currentTime)
osc.stop(ac.currentTime + (duration * 0.001))
if (now === 0) {
// Audio Context hasn't started, we can't make sound yet
return
}
theirgain.gain.linearRampToValueAtTime(0.1, now + 0.01)
mygain.gain.setValueAtTime(0.1, now + duration/1000)
theirgain.gain.linearRampToValueAtTime(0.0, now + 0.01 + duration/1000)
}
function send(duration) {
let now = ac.currentTime
window.socket.send(duration)
if (now === 0) {
return
}
mygain.gain.linearRampToValueAtTime(0.1, now + 0.01)
mygain.gain.setValueAtTime(0.1, now + duration/1000)
mygain.gain.linearRampToValueAtTime(0.0, now + 0.01 + duration/1000)
}
function key(event) {
let duration = 0
if ((event.button === 0) || (event.key == ",") || (event.key == "w")) {
duration = short
}
if ((event.button === 2) || (event.key == ".") || (event.key == "v")) {
duration = long
}
// You don't get to hold the key down yet, sorry
if ((event.repeat) || (duration === 0)) {
ac.resume()
if (event.repeat) {
// Ignore key repeats generated by the OS, we do this ourselves
return
}
window.socket.send(duration)
if ((event.button === 0) || (event.code == "Period") || (event.key == "Shift")) {
duration = short
}
if ((event.button === 2) || (event.code == "Slash") || (event.code == "KeyZ")) {
duration = long
}
if (duration === 0) {
return
}
myosc = ac.createOscillator()
myosc.connect(gain)
myosc.frequency.value = audioFreqMe
myosc.start(ac.currentTime)
myosc.stop(ac.currentTime + duration * 0.001)
if (repeatInterval) {
clearInterval(repeatInterval)
}
if (event.type.endsWith("down")) {
send(duration)
repeatInterval = setInterval(() => {send(duration)}, duration + short)
}
}
function canWeJustNot(event) {
@ -58,7 +101,9 @@ function init() {
// disable RMB context menu
document.addEventListener("contextmenu", e => canWeJustNot(e))
document.addEventListener("mousedown", e => key(e))
document.addEventListener("mouseup", e => key(e))
document.addEventListener("keydown", e => key(e))
document.addEventListener("keyup", e => key(e))
}