vail

Internet morse code repeater
git clone https://git.woozle.org/neale/vail.git

vail / static
WrathPak  ·  2025-06-09

index.html

  1<!DOCTYPE html>
  2<html>
  3	<head>
  4		<title>Vail</title>
  5		<meta charset="utf-8">
  6		<meta name="viewport" content="width=device-width, initial-scale=1">
  7
  8		<meta property="og:url" content="https://vail.woozle.org/">
  9		<meta property="og:type" content="website">
 10		<meta property="og:title" content="Vail: Internet Morse Code">
 11		<meta property="og:description" content="Send and recieve with just a computer or smartphone">
 12		<meta property="og:image" content="https://vail.woozle.org/key.jpg">
 13		<!-- Image from https://www.flickr.com/photos/nationalmuseumofamericanhistory/14448709921
 14			-- Used with permission (CC-BY-NC) -->
 15
 16		<!-- Bulma CSS -->
 17		<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.3/css/bulma.min.css">
 18		<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@mdi/font@6.5.95/css/materialdesignicons.min.css">
 19
 20		<!-- Vail stuff -->
 21		<link rel="manifest" href="manifest.json">
 22		<link rel="icon" href="assets/vail.png" data-rx="assets/vail-rx.png" sizes="256x256" type="image/png">
 23		<link rel="icon" href="assets/vail.svg" data-rx="assets/vail-rx.svg" sizes="any" type="image/svg+xml">
 24		<script type="module" src="scripts/vail.mjs"></script>
 25		<script type="module" src="scripts/ui.mjs"></script>
 26		<link rel="stylesheet" href="vail.css">
 27		<link rel="stylesheet" href="dark.css">
 28	</head>
 29	<body>
 30		<nav class="navbar is-dark">
 31			<div class="navbar-brand">
 32				<a class="navbar-item">
 33					<img class="" src="assets/vail.svg" alt="">
 34					<div class="block">Vail</div>
 35				</a>
 36			</div>
 37			<div class="navbar-menu">
 38				<div class="navbar-end">
 39					<a class="navbar-item" href="https://discord.gg/GBzj8cBat7" target="_blank" title="Text/voice chat on Discord"><i class="mdi mdi-discord"></i></a>
 40					<a class="navbar-item" href="https://github.com/nealey/vail/wiki" target="_blank" title="Vail Wiki">Help</a>
 41				</div>
 42			</div>
 43		</nav>
 44
 45		<div class="modal is-active init">
 46			<div class="modal-content">
 47				<div class="notification is-info">
 48						<h1 class="title has-text-centered">
 49							Loading...
 50						</h1>
 51						<p>
 52							If you can read this,
 53							it could mean
 54							your browser has disabled JavaScript,
 55							a browser extension is interfering with JavaScript,
 56							or your browser is too old to run Vail.
 57						</p>
 58						<p>
 59							Please post a screen shot in a new
 60							<a href="https://github.com/nealey/vail/discussions">Vail Discussions</a>
 61							thread,
 62							or in our
 63							<a href="https://discord.gg/GBzj8cBat7">Discord instance</a>,
 64							so we can help you out!
 65						</p>
 66						<ul>
 67							<li>Starting JavaScript application...</li>
 68						</ul>
 69					</div>
 70				</div>
 71			</div>
 72		</div>
 73
 74		<section class="section">
 75			<div class="columns is-multiline">
 76				<div class="column">
 77					<div class="box" id="transciever">
 78						<div class="level">
 79							<div class="level-left">
 80								<div class="level-item">
 81									<h1 class="title" data-i18n="heading.repeater">Repeater</h1>
 82								</div>
 83							</div>
 84							<div class="level-right">
 85								<div class="level-item">
 86									<!-- This appears as a little light that turns on when someone's sending -->
 87									<span class="tag recv-lamp">
 88										<output class="has-text-info" id="note"></output>
 89										<i class="mdi mdi-volume-off muted"></i>
 90									</span>
 91								</div>
 92							</div>
 93						</div>
 94
 95						<div class="block is-flex">
 96							<input class="input" type="text" id="repeater" list="repeater-list">
 97							<datalist id="repeater-list"></datalist>
 98							<div class="dropdown is-right is-hoverable">
 99								<div class="dropdown-trigger">
100									<button class="button" aria-haspopup="true" aria-controls="stock-repeaters">
101										<span class="icon is-small">
102											<i class="mdi mdi-chevron-down" aria-hidden="true"></i>
103										</span>
104									</button>
105								</div>
106								<div class="dropdown-menu" id="stock-repeaters" role="menu">
107									<div class="dropdown-content">
108										<a class="dropdown-item" data-value="">General</a>
109										<a class="dropdown-item" data-value="1">Channel 1</a>
110										<a class="dropdown-item" data-value="2">Channel 2</a>
111										<a class="dropdown-item" data-value="3">Channel 3</a>
112										<hr class="dropdown-divider">
113										<a class="dropdown-item" data-value="Null">Null (no transmit)</a>
114										<a class="dropdown-item">Echo</a>
115										<a class="dropdown-item">Fortunes</a>
116										<a class="dropdown-item">Fortunes: Pauses ×2</a>
117										<a class="dropdown-item">Fortunes: Pauses ×4</a>
118										<a class="dropdown-item">Fortunes: Pauses ×8</a>
119									</div>
120								</div>
121							</div>
122						</div>
123
124
125						<div class="block">
126							<div class="" id="charts">
127								<canvas class="chart" id="rxChart" data-color="orange"></canvas>
128								<canvas class="chart" id="txChart" data-color="teal"></canvas>
129								<canvas class="chart" id="key0Chart" data-color="olive"></canvas>
130								<canvas class="chart" id="key1Chart" data-color="purple"></canvas>
131							</div>
132						</div>
133
134						<div class="block">
135							<table class="wide">
136								<tr>
137									<td>
138										<button class="button key is-primary" data-key="0" title="right click for Key">
139											Key
140										</button>
141										<div class="shortcuts">
142											<kbd title="keyboard button">.</kbd>
143											<kbd title="keyboard button">x</kbd>
144											<i class="mdi mdi-gamepad-circle-left" title="Gamepad Left Button"></i>
145										</div>
146									</td>
147									<td>
148										<button class="button key is-primary" data-key="1" title="right click for Key">
149											Key
150										</button>
151										<div class="shortcuts">
152											<kbd title="keyboard button">/</kbd>
153											<kbd title="keyboard button">z</kbd>
154											<i class="mdi mdi-gamepad-circle-up" title="Gamepad Top Button"></i>
155										</div>
156									</td>
157								</tr>
158							</table>
159						</div>
160
161						<div>
162							<div class="field is-horizontal">
163								<div class="field-label">
164									<label class="label" data-i18n="heading.mode">Mode</label>
165								</div>
166								<div class="field-body">
167									<div class="field">
168										<div class="control">
169											<div class="select">
170												<select id="keyer-mode">
171													<option value="cootie" data-i18n="keyer.cootie">Straight Key / Cootie</option>
172													<option value="bug" data-i18n="keyer.bug">Bug</option>
173													<option value="elbug" data-i18n="keyer.elbug">ElBug</option>
174													<option value="singledot" data-i18n="keyer.singledot">Single Dot</option>
175													<option value="ultimatic" data-i18n="keyer.ultimatic">Ultimatic</option>
176													<option value="iambic" data-i18n="keyer.iambic">Iambic (Plain)</option>
177													<option value="iambica" data-i18n="keyer.iambica">Iambic A</option>
178													<option value="iambicb" data-i18n="keyer.iambicb">Iambic B</option>
179													<option value="keyahead" data-i18n="keyer.keyahead">Keyahead</option>
180												</select>
181											</div>
182										</div>
183									</div>
184								</div>
185							</div>
186
187							<div class="field is-horizontal">
188								<div class="field-label">
189									<label class="label">
190										<output for="keyer-rate"></output>&nbsp;<span data-i18n="label.wpm">WPM</span>
191										/
192										<span data-fill="keyer-ms"></span><span data-i18n="label:ms">ms</span>
193									</label>
194								</div>
195								<div class="field-body">
196									<div class="field">
197										<div class="control">
198											<input
199												id="keyer-rate"
200												type="range"
201												min="5"
202												max="50"
203												step="1"
204												value="12">
205										</div>
206									</div>
207								</div>
208							</div>
209						</div>
210
211					</div>
212				</div>
213
214				<div class="column">
215					<div class="box">
216						<h2 class="title" data-i18n="heading.notes" data-i18n="heading.notes"></h2>
217						<textarea class="textarea" data-i18n-placeholder="description.notes" id="notes"></textarea>
218						<nav class="breadcrumb has-bullet-separator">
219							<ul>
220								<li><a href="https://discord.gg/GBzj8cBat7" target="_blank" data-i18n-title="title.discord"><i class="mdi mdi-discord"></i></a></li>
221								<li><a href="https://github.com/nealey/vail/wiki" target="_blank" data-i18n-title="title.wiki">Help</a></li>
222							</ul>
223						</nav>
224					</div>
225				</div>
226
227				<div class="column">
228					<div class="box">
229						<h2 class="title" data-i18n="heading.knobs">Knobs</h2>
230						<div class="block">
231							<div class="control">
232								<button id="reset" class="button" data-i18n="label.reset">
233									Reset
234								</button>
235							</div>
236							<div data-i18n="description.reset">
237								Reset all Vail preferences to default.
238							</div>
239						</div>
240
241
242						<div class="field is-horizontal">
243							<div class="field-label">
244								<label class="label">
245									<span data-i18n="label.rx-delay">rx delay</span>:
246									<output for="rx-delay"></output>s
247								</label>
248							</div>
249							<div class="field-body">
250								<div class="field">
251									<div class="control">
252										<input
253											id="rx-delay"
254											type="range"
255											min="0"
256											max="10"
257											value="4"
258											step="0.1"
259											list="rx-delays">
260										<datalist id="rx-delays">
261											<option value="0"></option>
262											<option value="1"></option>
263											<option value="2" label="2s"></option>
264											<option value="3"></option>
265											<option value="4" label="4s"></option>
266											<option value="5"></option>
267											<option value="6" label="6s"></option>
268											<option value="7"></option>
269											<option value="8" label="8s"></option>
270											<option value="9"></option>
271											<option value="10"></option>
272										</datalist>
273									</div>
274								</div>
275							</div>
276						</div>
277
278						<div class="field is-horizontal">
279							<div class="field-label">
280								<label class="label">
281									<span data-i18n="label.gain">volume</span>:
282									<output for="masterGain"></output>%
283									<i class="mdi mdi-volume-off muted"></i>
284								</label>
285							</div>
286							<div class="field-body">
287								<div class="field">
288									<div class="control">
289										<input
290											id="masterGain"
291											type="range"
292											min="0"
293											max="100"
294											value="100"
295											step="1">
296									</div>
297								</div>
298							</div>
299						</div>
300		
301						<div class="field is-horizontal">
302							<div class="field-label">
303								<label class="label">
304									<span data-i18n="label.tx-tone">tx tone</span>:
305									<output for="tx-tone" data-transform="note"></output>
306									<output for="tx-tone" data-transform="freq"></output>Hz
307								</label>
308							</div>
309							<div class="field-body">
310								<div class="field">
311									<div class="control">
312										<input
313											id="tx-tone"
314											type="range"
315											min="0"
316											max="127"
317											value="72"
318											step="1"
319											list="tones">
320									</div>
321								</div>
322							</div>
323						</div>
324
325						<div class="field is-horizontal">
326							<div class="field-label">
327								<label class="label">
328									<span data-i18n="label.rx-tone">rx tone</span>:
329									<output for="rx-tone" data-transform="note"></output>
330									<output for="rx-tone" data-transform="freq"></output>Hz
331								</label>
332							</div>
333							<div class="field-body">
334								<div class="field">
335									<div class="control">
336										<input
337											id="rx-tone"
338											type="range"
339											min="0"
340											max="127"
341											value="69"
342											step="1"
343											list="tones">
344									</div>
345								</div>
346							</div>
347						</div>
348
349						<datalist id="tones">
350							<option value="0" label="C-1"></option>
351							<option value="12" label="C0"></option>
352							<option value="24" label="C1"></option>
353							<option value="36" label="C2"></option>
354							<option value="48" label="C3"></option>
355							<option value="60" label="C4"></option>
356							<option value="72" label="C5"></option>
357							<option value="84" label="C6"></option>
358							<option value="96" label="C7"></option>
359							<option value="108" label="C8"></option>
360							<option value="120" label="C9"></option>
361						</datalist>
362
363						<p>
364							<label class="checkbox">
365								<input type="checkbox" id="telegraph-buzzer">
366								<span data-i18n="label.telegraph-sounds">Telegraph sounds</span>
367							</label>
368						</p>
369
370						<div class="field is-horizontal">
371							<div class="field-label">
372								<label class="label">
373									<span data-i18n="label.gain">noise</span>:
374									<output for="noiseGain"></output>%
375									<i class="mdi mdi-volume-off muted"></i>
376								</label>
377							</div>
378							<div class="field-body">
379								<div class="field">
380									<div class="control">
381										<input
382											id="noiseGain"
383											type="range"
384											min="0"
385											max="100"
386											value="0"
387											step="1">
388									</div>
389								</div>
390							</div>
391						</div>
392
393					</div>
394				</div>
395			</div>
396		</section>
397
398		<div class="columns is-centered bottom">
399			<div class="column is-half" id="errors"></div>
400		</div>
401	</body>
402</html>
403<!-- vim: set noet ts=2 sw=2 : -->