Add initial files
This commit is contained in:
1337
morse-code_files/International_Morse_Code.svg
Normal file
1337
morse-code_files/International_Morse_Code.svg
Normal file
File diff suppressed because it is too large
Load Diff
After Width: | Height: | Size: 27 KiB |
212
morse-code_files/Morse-code-tree.svg
Normal file
212
morse-code_files/Morse-code-tree.svg
Normal file
@ -0,0 +1,212 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg version="1.1" width="836" height="362" viewBox="0 0 836 362"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xml:space="preserve">
|
||||
<style type="text/css">
|
||||
circle, line, path{
|
||||
fill: none;
|
||||
stroke: #000;
|
||||
stroke-width: 2.5;
|
||||
}
|
||||
circle{
|
||||
stroke-width: 1.5;
|
||||
}
|
||||
text{
|
||||
font-size: 28px;
|
||||
font-family: "Bitstream Charter", Charter, serif;
|
||||
text-anchor: middle;
|
||||
}
|
||||
.arrowhead{
|
||||
fill: #000;
|
||||
stroke-width: 3.2;
|
||||
}
|
||||
.big { stroke-width: 3; font-size: 32px; }
|
||||
.dot { stroke-dasharray: 2.5, 7.5; }
|
||||
.dash { stroke-dasharray: 7.5, 7.5; }
|
||||
.thin { stroke-width: 1; }
|
||||
.grey { stroke: #808080; }
|
||||
.tiny { font-size: 20px; }
|
||||
</style>
|
||||
<circle r="18" cx="209.1975" cy="96.7551"/>
|
||||
<circle r="18" cx="626.7500" cy="96.8076"/>
|
||||
<path class="dot" d="M384.1785583,48.2296791l-157.529892,43.7463417"/>
|
||||
<path class="dash" d="M451.8214417,48.2296791l157.5299377,43.7463417"/>
|
||||
<circle r="18" cx="104.8225" cy="156.279"/>
|
||||
<circle r="18" cx="313.5725" cy="156.279"/>
|
||||
<circle r="18" cx="522.3225" cy="156.279"/>
|
||||
<circle r="18" cx="731.0725" cy="156.279"/>
|
||||
<circle r="18" cx="70.03075" cy="224.2428"/>
|
||||
<circle r="18" cx="139.614" cy="224.2428"/>
|
||||
<circle r="18" cx="278.7808" cy="224.2428"/>
|
||||
<circle r="18" cx="348.364" cy="224.2428"/>
|
||||
<circle r="18" cx="487.5308" cy="224.2428"/>
|
||||
<circle r="18" cx="557.114" cy="224.2428"/>
|
||||
<circle r="18" cx="696.2801" cy="224.2428"/>
|
||||
<circle r="18" cx="765.864" cy="224.2428"/>
|
||||
<circle r="18" cx="793.6975" cy="284.211" class="grey"/>
|
||||
<circle r="18" cx="751.9475" cy="284.211" class="grey"/>
|
||||
<circle r="18" cx="710.1975" cy="284.211"/>
|
||||
<circle r="18" cx="668.4475" cy="284.211"/>
|
||||
<circle r="18" cx="584.9475" cy="284.211"/>
|
||||
<circle r="18" cx="543.1975" cy="284.211"/>
|
||||
<circle r="18" cx="501.4475" cy="284.211"/>
|
||||
<circle r="18" cx="459.6975" cy="284.211"/>
|
||||
<circle r="18" cx="376.1975" cy="284.211"/>
|
||||
<circle r="18" cx="334.4475" cy="284.211"/>
|
||||
<circle r="18" cx="292.6975" cy="284.211" class="grey"/>
|
||||
<circle r="18" cx="250.9475" cy="284.211"/>
|
||||
<circle r="18" cx="167.4475" cy="284.211" class="grey"/>
|
||||
<circle r="18" cx="125.6975" cy="284.211"/>
|
||||
<circle r="18" cx="83.9475" cy="284.211"/>
|
||||
<circle r="18" cx="42.1975" cy="284.211"/>
|
||||
<circle r="10" cx="24.162" cy="344.255" class="thin"/>
|
||||
<circle r="10" cx="47.35625" cy="344.255" class="thin"/>
|
||||
<circle r="10" cx="70.55075" cy="344.255" class="thin grey"/>
|
||||
<circle r="10" cx="93.74525" cy="344.255" class="thin"/>
|
||||
<circle r="10" cx="116.93975" cy="344.255" class="thin grey"/>
|
||||
<circle r="10" cx="140.134" cy="344.255" class="thin grey"/>
|
||||
<circle r="10" cx="163.3285" cy="344.255" class="thin grey"/>
|
||||
<circle r="10" cx="186.523" cy="344.255" class="thin"/>
|
||||
<circle r="10" cx="232.912" cy="344.255" class="thin grey"/>
|
||||
<circle r="10" cx="256.10625" cy="344.255" class="thin grey"/>
|
||||
<circle r="10" cx="279.30075" cy="344.255" class="thin"/>
|
||||
<circle r="10" cx="302.49525" cy="344.255" class="thin grey"/>
|
||||
<circle r="10" cx="325.68975" cy="344.255" class="thin grey"/>
|
||||
<circle r="10" cx="348.884" cy="344.255" class="thin grey"/>
|
||||
<circle r="10" cx="372.0785" cy="344.255" class="thin grey"/>
|
||||
<circle r="10" cx="395.273" cy="344.255" class="thin"/>
|
||||
<circle r="10" cx="441.66175" cy="344.255" class="thin"/>
|
||||
<circle r="10" cx="464.85625" cy="344.255" class="thin"/>
|
||||
<circle r="10" cx="488.05075" cy="344.255" class="thin"/>
|
||||
<circle r="10" cx="511.24525" cy="344.255" class="thin grey"/>
|
||||
<circle r="10" cx="534.43975" cy="344.255" class="thin grey"/>
|
||||
<circle r="10" cx="557.63425" cy="344.255" class="thin grey"/>
|
||||
<circle r="10" cx="580.8285" cy="344.255" class="thin grey"/>
|
||||
<circle r="10" cx="604.023" cy="344.255" class="thin grey"/>
|
||||
<circle r="10" cx="650.412" cy="344.255" class="thin"/>
|
||||
<circle r="10" cx="673.60625" cy="344.255" class="thin grey"/>
|
||||
<circle r="10" cx="696.80075" cy="344.255" class="thin grey"/>
|
||||
<circle r="10" cx="719.99525" cy="344.255" class="thin grey"/>
|
||||
<circle r="10" cx="743.18975" cy="344.255" class="thin"/>
|
||||
<circle r="10" cx="766.384" cy="344.255" class="thin grey"/>
|
||||
<circle r="10" cx="789.5785" cy="344.255" class="thin"/>
|
||||
<circle r="10" cx="812.773" cy="344.255" class="thin"/>
|
||||
<path class="dot" d="M193.5657043,105.7522507l-73.0063782,41.6347122"/>
|
||||
<path class="dash" d="M224.9343567,105.7522507l73.0063171,41.6347122"/>
|
||||
<path class="dot" d="M611.0656738,105.7522507l-73.0063477,41.6347122"/>
|
||||
<path class="dash" d="M642.4343262,105.7522507l73.0063477,41.6347122"/>
|
||||
<path class="dash" d="M739.3528442,172.4042816l18.3359375,35.8184357"/>
|
||||
<path class="dot" d="M722.8971558,172.4042816l-18.3359985,35.8184357"/>
|
||||
<path class="dash" d="M530.6028442,172.4042816l18.3359375,35.8184357"/>
|
||||
<path class="dot" d="M514.1471558,172.4042816l-18.335968,35.8184357"/>
|
||||
<path class="dash" d="M321.8528442,172.4042816l18.335968,35.8184357"/>
|
||||
<path class="dot" d="M305.3971558,172.4042816l-18.335968,35.8184357"/>
|
||||
<path class="dash" d="M113.1028519,172.4042816l18.3359756,35.8184357"/>
|
||||
<path class="dot" d="M96.6471481,172.4042816l-18.3359604,35.8184357"/>
|
||||
<path class="dot" d="M62.4814339,240.674057l-12.629528,27.2108612"/>
|
||||
<path class="dash" d="M74.1651917,241.8845062l5.7529526,24.7899933"/>
|
||||
<path class="dot" d="M135.5848236,241.8845062l-5.7529449,24.7899933"/>
|
||||
<path class="dash" d="M147.2685852,240.674057l12.6295471,27.2108612"/>
|
||||
<path class="dot" d="M271.2314453,240.674057l-12.6295166,27.2108612"/>
|
||||
<path class="dash" d="M282.9151917,241.8845062l5.7529297,24.7899628"/>
|
||||
<path class="dot" d="M344.3348083,241.8845062l-5.7529602,24.7899933"/>
|
||||
<path class="dash" d="M356.0185852,240.674057l12.6295166,27.2108612"/>
|
||||
<path class="dot" d="M479.9814148,240.674057l-12.6295166,27.2108612"/>
|
||||
<path class="dash" d="M491.6651917,241.8845062l5.7529297,24.7899628"/>
|
||||
<path class="dot" d="M553.0847778,241.8845062l-5.7529297,24.7899628"/>
|
||||
<path class="dash" d="M564.7685547,240.674057l12.6295166,27.2108612"/>
|
||||
<path class="dot" d="M688.7314453,240.674057l-12.6295166,27.2108612"/>
|
||||
<path class="dash" d="M700.4151611,241.8845062l5.7529907,24.7899933"/>
|
||||
<path class="dot" d="M761.8348389,241.8845062l-5.7529297,24.7899628"/>
|
||||
<path class="dash" d="M773.5185547,240.674057l12.6295166,27.2108612"/>
|
||||
<path class="dash" d="M799.1239624,301.502655l10.3438721,33.1818848"/>
|
||||
<path class="dot" d="M792.34729,302.2623291l-2.4954834,32.0210571"/>
|
||||
<path class="grey dash" d="M756.1107788,301.8459167l7.6352539,32.6573486"/>
|
||||
<path class="dot" d="M749.2194214,302.1032104l-5.0289307,32.2642212"/>
|
||||
<path class="grey dash" d="M713.0306396,302.1032104l5.0289307,32.2642212"/>
|
||||
<path class="grey dot" d="M706.1392822,301.8459167l-7.6353149,32.6573486"/>
|
||||
<path class="grey dash" d="M669.90271,302.2623291l2.4954834,32.0210571"/>
|
||||
<path class="dot" d="M663.1259766,301.502655l-10.3438721,33.1818848"/>
|
||||
<path class="grey dash" d="M590.3739624,301.502655l10.3438721,33.1818848"/>
|
||||
<path class="grey dot" d="M583.59729,302.2623291l-2.4954834,32.0210571"/>
|
||||
<path class="grey dash" d="M547.3607788,301.8459167l7.6353149,32.6573486"/>
|
||||
<path class="grey dot" d="M540.4694214,302.1032104l-5.0289307,32.2642212"/>
|
||||
<path class="grey dash" d="M504.2805786,302.1032104l5.0289001,32.2642212"/>
|
||||
<path class="dot" d="M497.3892517,301.8459167l-7.6352539,32.6573486"/>
|
||||
<path class="dash" d="M461.15271,302.2623291l2.4955139,32.0210571"/>
|
||||
<path class="dot" d="M454.3760071,301.502655l-10.3439026,33.1818848"/>
|
||||
<path class="dash" d="M381.6239929,301.502655l10.3439026,33.1818848"/>
|
||||
<path class="grey dot" d="M374.84729,302.2623291l-2.4955139,32.0210571"/>
|
||||
<path class="grey dash" d="M338.6107483,301.8459167l7.6352844,32.6573486"/>
|
||||
<path class="grey dot" d="M331.7193909,302.1032104l-5.0289001,32.2641907"/>
|
||||
<path class="grey dash" d="M295.5306091,302.1032104l5.0289307,32.2642212"/>
|
||||
<path class="dot" d="M288.6392517,301.8459167l-7.6352844,32.6573486"/>
|
||||
<path class="grey dash" d="M252.40271,302.2623291l2.4955139,32.0210571"/>
|
||||
<path class="grey dot" d="M245.6260223,301.502655l-10.3438873,33.1818848"/>
|
||||
<path class="dash" d="M172.8740082,301.502655l10.3438873,33.1818848"/>
|
||||
<path class="grey dot" d="M166.0973053,302.2623291l-2.4955139,32.0210571"/>
|
||||
<path class="grey dash" d="M129.8607635,301.8459167l7.6352844,32.6573486"/>
|
||||
<path class="grey dot" d="M122.9694138,302.1032104l-5.0289078,32.2642212"/>
|
||||
<path class="dash" d="M86.7806091,302.1032104l5.0289078,32.2642212"/>
|
||||
<path class="grey dot" d="M79.8892593,301.8459167l-7.6352768,32.6573486"/>
|
||||
<path class="dash" d="M43.65271,302.2623291l2.4955025,32.0210571"/>
|
||||
<path class="dot" d="M36.8760147,301.502655l-10.3438854,33.1818848"/>
|
||||
<text x="209" y="106">E</text>
|
||||
<text x="626" y="106">T</text>
|
||||
<text x="105" y="166">I</text>
|
||||
<text x="314" y="166">A</text>
|
||||
<text x="522" y="166">N</text>
|
||||
<text x="731" y="166">M</text>
|
||||
<text x="70" y="234">S</text>
|
||||
<text x="140" y="234">U</text>
|
||||
<text x="279" y="234">R</text>
|
||||
<text x="349" y="234">W</text>
|
||||
<text x="488" y="234">D</text>
|
||||
<text x="558" y="234">K</text>
|
||||
<text x="696" y="234">G</text>
|
||||
<text x="766" y="234">O</text>
|
||||
<text x="42" y="294">H</text>
|
||||
<text x="84" y="294">V</text>
|
||||
<text x="126" y="294">F</text>
|
||||
<text x="252" y="294">L</text>
|
||||
<text x="335" y="294">P</text>
|
||||
<text x="376" y="294">J</text>
|
||||
<text x="461" y="294">B</text>
|
||||
<text x="501" y="294">X</text>
|
||||
<text x="543" y="294">C</text>
|
||||
<text x="585" y="294">Y</text>
|
||||
<text x="669" y="294">Z</text>
|
||||
<text x="710" y="292">Q</text>
|
||||
<text x="24" y="351" class="tiny">5</text>
|
||||
<text x="46" y="351" class="tiny">4</text>
|
||||
<text x="94" y="351" class="tiny">3</text>
|
||||
<text x="187" y="351" class="tiny">2</text>
|
||||
<text x="279" y="350" class="tiny">+</text>
|
||||
<text x="395" y="351" class="tiny">1</text>
|
||||
<text x="441" y="351" class="tiny">6</text>
|
||||
<text x="465" y="350" class="tiny">=</text>
|
||||
<text x="489" y="349" style="font-size: 16px">/</text>
|
||||
<text x="650" y="351" class="tiny">7</text>
|
||||
<text x="743" y="351" class="tiny">8</text>
|
||||
<text x="790" y="351" class="tiny">9</text>
|
||||
<text x="813" y="351" class="tiny">0</text>
|
||||
<g>
|
||||
<circle r="37" cx="418" cy="39" class="big"/>
|
||||
<text x="417" y="48" class="big">start</text>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<line class="dot big" style="stroke-dasharray: 3.5, 8.5" x1="102.2679901" y1="50.8910065" x2="249.2680054" y2="50.8910065"/>
|
||||
<path class="arrowhead" d="M120.2640381,50.9020538l12-12l-42,12l42,12L120.2640381,50.9020538z"/>
|
||||
</g>
|
||||
<text x="177" y="35" class="big">Dot</text>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<line class="dash big" style="stroke-dasharray: 8.55, 9.55" x1="592.7290039" y1="50.8910065" x2="727.7290039" y2="50.8910065"/>
|
||||
<path class="arrowhead" d="M715.7359619,50.9020538l-12,12l42-12l-42-12L715.7359619,50.9020538z"/>
|
||||
</g>
|
||||
<text x="657" y="35" class="big">Dash</text>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 10 KiB |
1037
morse-code_files/constants.js
Normal file
1037
morse-code_files/constants.js
Normal file
File diff suppressed because it is too large
Load Diff
4
morse-code_files/font-awesome.css
vendored
Normal file
4
morse-code_files/font-awesome.css
vendored
Normal file
File diff suppressed because one or more lines are too long
98
morse-code_files/highlight.css
Normal file
98
morse-code_files/highlight.css
Normal file
@ -0,0 +1,98 @@
|
||||
/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */
|
||||
|
||||
code {
|
||||
background: #fff;
|
||||
font-size: 13px;
|
||||
/*font-weight: 100;*/
|
||||
padding: 4px;
|
||||
border: none;
|
||||
box-shadow: inset 0 0 0 1px #E4EBF2;
|
||||
border-radius: 4px;
|
||||
overflow: scroll;
|
||||
font-family: 'Menlo', 'Monaco', Courier, monospace;
|
||||
}
|
||||
|
||||
pre code {
|
||||
font-size: 13px;
|
||||
word-wrap: break-word;
|
||||
-webkit-font-smoothing: subpixel-antialiased;
|
||||
-moz-osx-font-smoothing: auto;
|
||||
padding: 0 16px;
|
||||
display: block;
|
||||
color: #222;
|
||||
background: #fff;
|
||||
border: none;
|
||||
box-shadow: inset 0 0 0 1px #E4EBF2;
|
||||
border-radius: 4px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/* Tomorrow Comment */
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #8e908c;
|
||||
}
|
||||
|
||||
/* Tomorrow Red */
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-tag,
|
||||
.hljs-name,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class,
|
||||
.hljs-regexp,
|
||||
.hljs-deletion {
|
||||
color: #c82829;
|
||||
}
|
||||
|
||||
/* Tomorrow Orange */
|
||||
.hljs-number,
|
||||
.hljs-built_in,
|
||||
.hljs-builtin-name,
|
||||
.hljs-literal,
|
||||
.hljs-type,
|
||||
.hljs-params,
|
||||
.hljs-meta,
|
||||
.hljs-link {
|
||||
color: #f5871f;
|
||||
}
|
||||
|
||||
/* Tomorrow Yellow */
|
||||
.hljs-attribute {
|
||||
color: #eab700;
|
||||
}
|
||||
|
||||
/* Tomorrow Green */
|
||||
.hljs-string,
|
||||
.hljs-symbol,
|
||||
.hljs-bullet,
|
||||
.hljs-addition {
|
||||
color: #718c00;
|
||||
}
|
||||
|
||||
/* Tomorrow Blue */
|
||||
.hljs-title,
|
||||
.hljs-section {
|
||||
color: #4271ae;
|
||||
}
|
||||
|
||||
/* Tomorrow Purple */
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag {
|
||||
color: #8959a8;
|
||||
}
|
||||
|
||||
code.hljs {
|
||||
display: block;
|
||||
white-space: pre;
|
||||
overflow-x: auto;
|
||||
word-wrap: normal;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
3
morse-code_files/highlight.js
Normal file
3
morse-code_files/highlight.js
Normal file
File diff suppressed because one or more lines are too long
4
morse-code_files/jquery-2.js
vendored
Normal file
4
morse-code_files/jquery-2.js
vendored
Normal file
File diff suppressed because one or more lines are too long
36
morse-code_files/main.js
Normal file
36
morse-code_files/main.js
Normal file
@ -0,0 +1,36 @@
|
||||
// To make images retina, add a class "2x" to the img element
|
||||
// and add a <image-name>@2x.png image. Assumes jquery is loaded.
|
||||
|
||||
function isRetina() {
|
||||
var mediaQuery = "(-webkit-min-device-pixel-ratio: 1.5),\
|
||||
(min--moz-device-pixel-ratio: 1.5),\
|
||||
(-o-min-device-pixel-ratio: 3/2),\
|
||||
(min-resolution: 1.5dppx)";
|
||||
|
||||
if (window.devicePixelRatio > 1)
|
||||
return true;
|
||||
|
||||
if (window.matchMedia && window.matchMedia(mediaQuery).matches)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
function retina() {
|
||||
|
||||
if (!isRetina())
|
||||
return;
|
||||
|
||||
$("img.2x").map(function(i, image) {
|
||||
|
||||
var path = $(image).attr("src");
|
||||
|
||||
path = path.replace(".png", "@2x.png");
|
||||
path = path.replace(".jpg", "@2x.jpg");
|
||||
|
||||
$(image).attr("src", path);
|
||||
});
|
||||
};
|
||||
|
||||
$(document).ready(retina);
|
680
morse-code_files/morse-code.js
Normal file
680
morse-code_files/morse-code.js
Normal file
@ -0,0 +1,680 @@
|
||||
|
||||
const FREQUENCY = 440;
|
||||
|
||||
var DOT_TIME = 300;
|
||||
var DASH_TIME = DOT_TIME * 3;
|
||||
var SYMBOL_BREAK = DOT_TIME;
|
||||
var LETTER_BREAK = DOT_TIME * 3;
|
||||
var WORD_BREAK = DOT_TIME * 7;
|
||||
|
||||
|
||||
let note_context;
|
||||
let note_node;
|
||||
let gain_node;
|
||||
|
||||
let audioContextInitialized = false;
|
||||
|
||||
async function initializeAudioContext() {
|
||||
note_context = new AudioContext();
|
||||
await note_context.resume();
|
||||
note_node = note_context.createOscillator();
|
||||
gain_node = note_context.createGain();
|
||||
note_node.frequency.value = FREQUENCY.toFixed(2);
|
||||
gain_node.gain.value = 0;
|
||||
note_node.connect(gain_node);
|
||||
gain_node.connect(note_context.destination);
|
||||
note_node.start();
|
||||
audioContextInitialized = true;
|
||||
}
|
||||
|
||||
function startNotePlaying() {
|
||||
// Pass a start time of 0 so it starts ramping up immediately.
|
||||
gain_node.gain.setTargetAtTime(0.1, 0, 0.001)
|
||||
}
|
||||
|
||||
function stopNotePlaying() {
|
||||
// Pass a start time of 0 so it starts ramping down immediately.
|
||||
gain_node.gain.setTargetAtTime(0, 0, 0.001)
|
||||
}
|
||||
|
||||
|
||||
|
||||
function sleep(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
// Global strictly increasing play counter to avoid multiple replays at the same time.
|
||||
var playCounter = 0;
|
||||
|
||||
async function playDash(currentPlayCounter) {
|
||||
if (currentPlayCounter != playCounter) { return; }
|
||||
startNotePlaying();
|
||||
await sleep(DASH_TIME);
|
||||
stopNotePlaying();
|
||||
}
|
||||
|
||||
async function playDot(currentPlayCounter) {
|
||||
if (currentPlayCounter != playCounter) { return; }
|
||||
startNotePlaying();
|
||||
await sleep(DOT_TIME);
|
||||
stopNotePlaying();
|
||||
}
|
||||
|
||||
/**
|
||||
* message is something like '---'
|
||||
*/
|
||||
async function playLetter(letter, currentPlayCounter) {
|
||||
// console.log('playSentence with', playCounter, currentPlayCounter);
|
||||
if (!audioContextInitialized) {
|
||||
initializeAudioContext();
|
||||
}
|
||||
// console.log('playing', letter);
|
||||
for (let i = 0; i < letter.length; i++) {
|
||||
if (currentPlayCounter != playCounter) { return; }
|
||||
if (letter[i] == '-') {
|
||||
await playDash(currentPlayCounter);
|
||||
} else if (letter[i] == '.') {
|
||||
await playDot(currentPlayCounter);
|
||||
}
|
||||
await sleep(SYMBOL_BREAK);
|
||||
}
|
||||
}
|
||||
|
||||
// Word is an array of letters, like ['.', '.-', '-']
|
||||
async function playWord(word, currentPlayCounter) {
|
||||
// console.log('playSentence with', playCounter, currentPlayCounter);
|
||||
for (let i = 0; i < word.length; i++) {
|
||||
if (currentPlayCounter != playCounter) { return; }
|
||||
await playLetter(word[i], currentPlayCounter);
|
||||
await sleep(LETTER_BREAK);
|
||||
}
|
||||
}
|
||||
|
||||
// Sentence is an array of words.
|
||||
// Ex. "dog is good" -> [['-..', '---', '--.'], ['..', '...'], ['--.', '---', '---', '-..']]
|
||||
async function playSentence(sentence, currentPlayCounter) {
|
||||
// console.log('playSentence with', playCounter, currentPlayCounter);
|
||||
if (currentPlayCounter != playCounter) { return; }
|
||||
// Slight pause before it starts
|
||||
// console.log('playSentence with', playCounter, currentPlayCounter);
|
||||
await sleep(LETTER_BREAK);
|
||||
// console.log('playSentence with', playCounter, currentPlayCounter);
|
||||
for (let i = 0; i < sentence.length; i++) {
|
||||
if (currentPlayCounter != playCounter) { return; }
|
||||
await playWord(sentence[i], currentPlayCounter);
|
||||
await sleep(WORD_BREAK);
|
||||
}
|
||||
}
|
||||
|
||||
// asciiChar is something like 'd'
|
||||
// Assumes [a-z0-9]
|
||||
function convertAsciiCharToMorse(asciiChar) {
|
||||
return MORSE_MAP[asciiChar];
|
||||
}
|
||||
|
||||
// asciiWord is something like 'dog'
|
||||
// Assumes [a-z0-9]
|
||||
function convertAsciiWordToMorse(asciiWord) {
|
||||
return asciiWord.split('').map(convertAsciiCharToMorse);
|
||||
}
|
||||
|
||||
// asciiSentence is something like 'dog is good'
|
||||
// Assumes words are separated by spaces.
|
||||
function convertAsciiSentenceToMorse(asciiSentence) {
|
||||
let splitSentence = asciiSentence.toLowerCase().split(' ');
|
||||
return splitSentence.map(convertAsciiWordToMorse);
|
||||
}
|
||||
|
||||
function getRandomLetter() {
|
||||
const randomIndex = Math.floor(Math.random() * 26);
|
||||
return Object.keys(MORSE_MAP)[randomIndex];
|
||||
}
|
||||
|
||||
function getRandomWord() {
|
||||
const randomIndex = Math.floor(Math.random() * EASY_WORDS.length);
|
||||
return EASY_WORDS[randomIndex];
|
||||
}
|
||||
|
||||
function getRandomEasyWords() {
|
||||
const totalLength = Math.floor(Math.random() * 3) + 2;
|
||||
let finalSentence = ''
|
||||
for (let i = 0; i < totalLength; i++) {
|
||||
finalSentence += EASY_WORDS[Math.floor(Math.random() * EASY_WORDS.length)];
|
||||
if (i < totalLength - 1) {
|
||||
finalSentence += ' ';
|
||||
}
|
||||
}
|
||||
return finalSentence;
|
||||
}
|
||||
|
||||
function getRandomWords() {
|
||||
const totalLength = Math.floor(Math.random() * 4) + 2;
|
||||
let finalSentence = ''
|
||||
for (let i = 0; i < totalLength; i++) {
|
||||
finalSentence += ALL_WORDS[Math.floor(Math.random() * ALL_WORDS.length)];
|
||||
if (i < totalLength - 1) {
|
||||
finalSentence += ' ';
|
||||
}
|
||||
}
|
||||
return finalSentence;
|
||||
}
|
||||
|
||||
function updateSpeed() {
|
||||
const useFarnsworth = document.querySelector('input[name="farnsworth"]:checked').value == 'yes';
|
||||
// Get the difficulty and update the constants.
|
||||
const difficulty = document.querySelector('input[name="speed"]:checked').value
|
||||
if (useFarnsworth) {
|
||||
DOT_TIME = 60;
|
||||
DASH_TIME = DOT_TIME * 3;
|
||||
SYMBOL_BREAK = DOT_TIME;
|
||||
let letterBreakMultiplier;
|
||||
switch (difficulty) {
|
||||
case 'easy':
|
||||
letterBreakMultiplier = 24;
|
||||
break;
|
||||
case 'medium':
|
||||
letterBreakMultiplier = 12;
|
||||
break;
|
||||
case 'hard':
|
||||
letterBreakMultiplier = 6;
|
||||
break;
|
||||
default:
|
||||
letterBreakMultiplier = 3;
|
||||
break;
|
||||
}
|
||||
LETTER_BREAK = DOT_TIME * letterBreakMultiplier;
|
||||
WORD_BREAK = DOT_TIME * (letterBreakMultiplier * 2.5);
|
||||
} else {
|
||||
switch (difficulty) {
|
||||
case 'easy':
|
||||
DOT_TIME = 300;
|
||||
break;
|
||||
case 'medium':
|
||||
DOT_TIME = 200;
|
||||
break;
|
||||
case 'hard':
|
||||
DOT_TIME = 100;
|
||||
break;
|
||||
default:
|
||||
DOT_TIME = 60;
|
||||
break;
|
||||
}
|
||||
DASH_TIME = DOT_TIME * 3;
|
||||
SYMBOL_BREAK = DOT_TIME;
|
||||
LETTER_BREAK = DOT_TIME * 3;
|
||||
WORD_BREAK = DOT_TIME * 7;
|
||||
}
|
||||
}
|
||||
|
||||
function getTarget() {
|
||||
let target;
|
||||
// Get the difficulty and assign a random target.
|
||||
const difficulty = document.querySelector('input[name="difficulty"]:checked').value
|
||||
switch (difficulty) {
|
||||
case 'easy':
|
||||
target = getRandomLetter();
|
||||
break;
|
||||
case 'medium':
|
||||
target = getRandomWord();
|
||||
break;
|
||||
case 'hard':
|
||||
target = getRandomEasyWords();
|
||||
break;
|
||||
default:
|
||||
target = getRandomWords();
|
||||
break;
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
var startButton = document.getElementById('playGame');
|
||||
|
||||
class ListeningGame {
|
||||
constructor(wordInput, statusElement, submitButton, resetButton) {
|
||||
this.stopped = false;
|
||||
this.messageFound = false;
|
||||
|
||||
// DOM elements we'll interact with
|
||||
this.wordInput = wordInput;
|
||||
this.statusElement = statusElement;
|
||||
this.submitButton = submitButton;
|
||||
this.resetButton = resetButton;
|
||||
|
||||
// Bind listeners to `this`.
|
||||
this.inputListener = this.inputListener.bind(this);
|
||||
this.submit = this.submit.bind(this);
|
||||
this.resetButtonListener = this.resetButtonListener.bind(this);
|
||||
|
||||
// Initialize listeners
|
||||
this.wordInput.addEventListener('keyup', this.inputListener);
|
||||
this.submitButton.addEventListener('click', this.submit);
|
||||
this.resetButton.addEventListener('click', this.resetButtonListener);
|
||||
this.wordInput.removeAttribute('disabled');
|
||||
this.submitButton.removeAttribute('disabled');
|
||||
this.resetButton.removeAttribute('disabled');
|
||||
|
||||
this.target = '';
|
||||
}
|
||||
|
||||
startNewGame() {
|
||||
// Start listening
|
||||
if (!audioContextInitialized) {
|
||||
initializeAudioContext();
|
||||
}
|
||||
// Focus on the word input box.
|
||||
this.wordInput.focus();
|
||||
// Update speed based on difficulty.
|
||||
updateSpeed();
|
||||
// Get a new target
|
||||
this.target = getTarget();
|
||||
// console.log('target: ', this.target);
|
||||
// Reset
|
||||
this.messageFound = false;
|
||||
this.wordInput.value = '';
|
||||
this.statusElement.textContent = 'Waiting...';
|
||||
this.playTarget();
|
||||
}
|
||||
|
||||
submit(event) {
|
||||
event.preventDefault();
|
||||
if (this.messageFound) {
|
||||
// If we found it already, get a new target and play it.
|
||||
this.startNewGame();
|
||||
} else {
|
||||
const enteredWord = this.wordInput.value;
|
||||
// console.log('enteredWord: ', enteredWord, 'target: ', this.target);
|
||||
if (enteredWord.toLowerCase() == this.target) {
|
||||
// If they got the word, show message and switch event listener.
|
||||
this.statusElement.textContent = 'Correct! Press enter to play a new round.';
|
||||
this.messageFound = true;
|
||||
// Extra playCounter increase to stop any current playing.
|
||||
this.stopCurrentPlaying();
|
||||
} else {
|
||||
// If they didn't, clear the text box and let them try again.
|
||||
this.statusElement.textContent = 'Not quite! Try again.';
|
||||
this.replay();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stopCurrentPlaying() {
|
||||
// console.log('stopping current playing');
|
||||
// Also increase playCounter to stop any current playing. Wastes a count, but we have the bits to spare.
|
||||
playCounter += 1;
|
||||
}
|
||||
|
||||
async replay() {
|
||||
if (this.messageFound) {
|
||||
this.startNewGame();
|
||||
return;
|
||||
}
|
||||
// Stop the current playing, and play the target again.
|
||||
this.stopCurrentPlaying();
|
||||
this.wordInput.focus();
|
||||
this.playTarget();
|
||||
}
|
||||
|
||||
resetButtonListener(event) {
|
||||
event.preventDefault();
|
||||
this.replay();
|
||||
}
|
||||
|
||||
inputListener(event) {
|
||||
if (this.messageFound) {
|
||||
this.startNewGame();
|
||||
return;
|
||||
}
|
||||
if (event.key == 'Control') {
|
||||
this.replay();
|
||||
} else if (event.key == 'Enter') {
|
||||
this.submit(event);
|
||||
}
|
||||
}
|
||||
|
||||
playTarget() {
|
||||
playCounter += 1;
|
||||
// console.log('playing with counter', playCounter)
|
||||
playSentence(convertAsciiSentenceToMorse(this.target), playCounter);
|
||||
}
|
||||
|
||||
stopGame() {
|
||||
this.stopCurrentPlaying();
|
||||
this.wordInput.value = '';
|
||||
this.statusElement.textContent = 'Press Start to begin.';
|
||||
this.wordInput.removeEventListener('keyup', this.inputListener);
|
||||
this.submitButton.removeEventListener('click', this.submit);
|
||||
this.resetButton.removeEventListener('click', this.resetButtonListener);
|
||||
this.wordInput.setAttribute('disabled', 'disabled');
|
||||
this.submitButton.setAttribute('disabled', 'disabled');
|
||||
this.resetButton.setAttribute('disabled', 'disabled');
|
||||
}
|
||||
}
|
||||
|
||||
var currentGame;
|
||||
|
||||
var playListeningGameButton = document.getElementById("playListeningGame");
|
||||
|
||||
async function playListeningGame() {
|
||||
// Check if there's a currentGame already. If there is, stop it!
|
||||
if (currentGame) {
|
||||
currentGame.stopGame();
|
||||
}
|
||||
|
||||
const wordInput = document.getElementById('wordInput');
|
||||
const status = document.getElementById('status');
|
||||
const submitButton = document.getElementById('submitButton');
|
||||
const resetButton = document.getElementById('resetButton');
|
||||
|
||||
currentGame = new ListeningGame(wordInput, status, submitButton, resetButton);
|
||||
|
||||
currentGame.startNewGame();
|
||||
|
||||
playListeningGameButton.removeEventListener('click', playListeningGame);
|
||||
playListeningGameButton.addEventListener('click', stopListeningGame);
|
||||
playListeningGameButton.textContent = 'Stop';
|
||||
}
|
||||
|
||||
async function stopListeningGame() {
|
||||
if (currentGame) {
|
||||
// Stop current game
|
||||
currentGame.stopGame();
|
||||
}
|
||||
|
||||
playListeningGameButton.removeEventListener('click', stopListeningGame);
|
||||
playListeningGameButton.addEventListener('click', playListeningGame);
|
||||
playListeningGameButton.textContent = 'Start';
|
||||
}
|
||||
|
||||
playListeningGameButton.addEventListener('click', playListeningGame);
|
||||
|
||||
class InputGame {
|
||||
constructor(signalButton, startOverButton, targetDisplay, inputDisplay, inputStatus) {
|
||||
this.signalButton = signalButton;
|
||||
this.startOverButton = startOverButton;
|
||||
this.targetDisplay = targetDisplay;
|
||||
this.inputDisplay = inputDisplay;
|
||||
this.inputStatus = inputStatus;
|
||||
|
||||
this.target = '';
|
||||
|
||||
// Stack for keeping track of dots and dashes that make up letter
|
||||
this.dotAndDashStack = [];
|
||||
// Stack for keeping track of letters that make up word
|
||||
this.letterStack = [];
|
||||
|
||||
this.lastKeyDownTime = 0;
|
||||
this.lastKeyUpTime = 0;
|
||||
this.letterTimeout = null;
|
||||
this.spaceTimeout = null;
|
||||
|
||||
this.matchFound = false;
|
||||
|
||||
// Keep track of where the spacebar is to prevent duplicate keydowns when you hold it down.
|
||||
this.spacebarDown = false;
|
||||
// Keep track of if the tap key is down or not to prevent weird state issues when restarting game.
|
||||
// this.keyIsDown = false;
|
||||
|
||||
this.documentKeydownListener = this.documentKeydownListener.bind(this);
|
||||
this.documentKeyupListener = this.documentKeyupListener.bind(this);
|
||||
this.buttonMousedownListener = this.buttonMousedownListener.bind(this);
|
||||
this.buttonMouseupListener = this.buttonMouseupListener.bind(this);
|
||||
this.startOver = this.startOver.bind(this);
|
||||
this.handleLetterTimeout = this.handleLetterTimeout.bind(this);
|
||||
this.handleSpaceTimeout = this.handleSpaceTimeout.bind(this);
|
||||
|
||||
document.addEventListener('keydown', this.documentKeydownListener);
|
||||
document.addEventListener('keyup', this.documentKeyupListener);
|
||||
this.signalButton.addEventListener('mousedown', this.buttonMousedownListener);
|
||||
this.signalButton.addEventListener('mouseup', this.buttonMouseupListener);
|
||||
this.signalButton.addEventListener('touchstart', this.buttonMousedownListener);
|
||||
this.signalButton.addEventListener('touchend', this.buttonMouseupListener);
|
||||
this.startOverButton.addEventListener('click', this.startOver);
|
||||
}
|
||||
|
||||
startNewGame() {
|
||||
this.matchFound = false;
|
||||
this.startOver();
|
||||
// Update speed based on difficulty.
|
||||
updateSpeed();
|
||||
// Get target word
|
||||
this.target = getTarget();
|
||||
// console.log('target: ', this.target);
|
||||
// Update target display with the new target
|
||||
this.targetDisplay.textContent = 'Target: ' + this.target;
|
||||
this.inputDisplay.textContent = '';
|
||||
this.inputStatus.textContent = '';
|
||||
|
||||
this.signalButton.removeAttribute('disabled');
|
||||
this.startOverButton.removeAttribute('disabled');
|
||||
// Focus on the tap button
|
||||
this.signalButton.focus();
|
||||
|
||||
// Start listening
|
||||
if (!audioContextInitialized) {
|
||||
initializeAudioContext();
|
||||
}
|
||||
}
|
||||
|
||||
keyDown() {
|
||||
if (this.matchFound) {
|
||||
// console.log('match found! doing nothing on keydown')
|
||||
return;
|
||||
}
|
||||
startNotePlaying();
|
||||
const currentTime = Date.now();
|
||||
// Update the marker for the last signal ending
|
||||
this.lastKeyDownTime = currentTime;
|
||||
// Get the total silence time since we last had a signal
|
||||
const silenceDelta = currentTime - this.lastKeyUpTime;
|
||||
this.handleSilence(silenceDelta);
|
||||
// We also want to clear any pending intervals so we don't duplicate them.
|
||||
clearTimeout(this.letterTimeout);
|
||||
clearTimeout(this.spaceTimeout);
|
||||
}
|
||||
|
||||
keyUp() {
|
||||
if (this.matchFound) {
|
||||
this.startNewGame();
|
||||
return;
|
||||
}
|
||||
// console.log('keyup!');
|
||||
stopNotePlaying();
|
||||
const currentTime = Date.now();
|
||||
// Update the marker for the last silence ending
|
||||
this.lastKeyUpTime = currentTime;
|
||||
// Get the total signal time since we last had silence
|
||||
const signalDelta = currentTime - this.lastKeyDownTime;
|
||||
this.handleSignal(signalDelta);
|
||||
|
||||
// TODO: start timer
|
||||
this.letterTimeout = setTimeout(this.handleLetterTimeout, LETTER_BREAK);
|
||||
this.spaceTimeout = setTimeout(this.handleSpaceTimeout, WORD_BREAK);
|
||||
}
|
||||
|
||||
handleLetterTimeout() {
|
||||
this.handleSilence(LETTER_BREAK);
|
||||
}
|
||||
|
||||
handleSpaceTimeout() {
|
||||
this.handleSilence(WORD_BREAK)
|
||||
}
|
||||
|
||||
handleSignal(signalDelta) {
|
||||
// console.log('signalDelta: ', signalDelta)
|
||||
// See if it's a dot or a dash
|
||||
if (signalDelta < DASH_TIME) {
|
||||
this.dotAndDashStack.push('.');
|
||||
} else {
|
||||
this.dotAndDashStack.push('-');
|
||||
}
|
||||
}
|
||||
|
||||
handleSilence(silenceDelta) {
|
||||
// If there's no input yet, don't do anything
|
||||
if (this.dotAndDashStack.length == 0 && this.letterStack.length == 0) {
|
||||
return;
|
||||
}
|
||||
// console.log('silenceDelta: ', silenceDelta, 'LETTER_BREAK: ', LETTER_BREAK);
|
||||
// If we have at least a letter break, try to add a new character if we have any dots or dashes
|
||||
if (silenceDelta >= LETTER_BREAK && this.dotAndDashStack.length != 0) {
|
||||
// TODO: handle letter being done.
|
||||
const currentLetterCombo = this.dotAndDashStack.join('');
|
||||
if (currentLetterCombo in REVERSE_MORSE_MAP) {
|
||||
this.letterStack.push(REVERSE_MORSE_MAP[currentLetterCombo]);
|
||||
} else {
|
||||
// Push a question mark
|
||||
this.letterStack.push('?');
|
||||
}
|
||||
// Clear current stack.
|
||||
this.dotAndDashStack = [];
|
||||
}
|
||||
// If we have more than a word break, we may also want to add a space after doing the above.
|
||||
// We may want to do this without dots and dashes (e.g. the timeout), but only if the last char
|
||||
// isn't a space
|
||||
if (silenceDelta >= WORD_BREAK &&
|
||||
this.letterStack.length != 0 &&
|
||||
this.letterStack[this.letterStack.length - 1] != ' ') {
|
||||
this.letterStack.push(' ');
|
||||
}
|
||||
// Update the display.
|
||||
this.inputDisplay.textContent = this.letterStack.join('');
|
||||
this.checkForMatch();
|
||||
}
|
||||
|
||||
documentKeydownListener(event) {
|
||||
event.preventDefault();
|
||||
// console.log('document keydown');
|
||||
if (event.key == ' ' && !this.spacebarDown) {
|
||||
// console.log('sending keydown');
|
||||
this.spacebarDown = true;
|
||||
this.keyDown();
|
||||
} else if (event.key == 'Control') {
|
||||
this.startOver();
|
||||
}
|
||||
}
|
||||
|
||||
documentKeyupListener(event) {
|
||||
event.preventDefault();
|
||||
if (this.matchFound) {
|
||||
this.spacebarDown = false;
|
||||
this.startNewGame();
|
||||
return;
|
||||
}
|
||||
// console.log('document keyup');
|
||||
// console.log(this);
|
||||
if (event.key == ' ') {
|
||||
this.spacebarDown = false;
|
||||
this.keyUp();
|
||||
}
|
||||
}
|
||||
|
||||
buttonMousedownListener(event) {
|
||||
event.preventDefault();
|
||||
// console.log('button mousedown');
|
||||
// console.log(this);
|
||||
this.keyDown();
|
||||
}
|
||||
|
||||
buttonMouseupListener(event) {
|
||||
event.preventDefault();
|
||||
// console.log('button mouseup');
|
||||
// console.log(this);
|
||||
this.keyUp();
|
||||
}
|
||||
|
||||
startOver(event) {
|
||||
if (event) {
|
||||
event.preventDefault();
|
||||
}
|
||||
if (this.matchFound) {
|
||||
this.startNewGame();
|
||||
return;
|
||||
}
|
||||
this.inputDisplay.textContent = '';
|
||||
this.inputStatus.textContent = '';
|
||||
this.dotAndDashStack = [];
|
||||
this.letterStack = [];
|
||||
this.lastKeyDownTime = 0;
|
||||
this.lastKeyUpTime = 0;
|
||||
|
||||
clearTimeout(this.letterTimeout);
|
||||
clearTimeout(this.spaceTimeout);
|
||||
}
|
||||
|
||||
checkForMatch() {
|
||||
// console.log('checking for match');
|
||||
// console.log('target: \'' + this.target + '\'');
|
||||
// console.log('this.letterStack.join(\'\'): \'' + this.letterStack.join('') + '\'');
|
||||
// console.log(this.letterStack.join('') == this.target);
|
||||
if (this.letterStack.join('') == this.target) {
|
||||
// console.log('match!');
|
||||
// Clear intervals
|
||||
clearTimeout(this.letterTimeout);
|
||||
clearTimeout(this.spaceTimeout);
|
||||
|
||||
// Show message
|
||||
this.inputStatus.textContent = 'You got it! Press any key or click either button to start a new round.';
|
||||
this.matchFound = true;
|
||||
}
|
||||
}
|
||||
|
||||
stopGame() {
|
||||
this.startOver();
|
||||
this.targetDisplay.textContent = 'Press Start to begin.';
|
||||
this.inputStatus.textContent = '';
|
||||
document.removeEventListener('keydown', this.documentKeydownListener);
|
||||
document.removeEventListener('keyup', this.documentKeyupListener);
|
||||
this.signalButton.removeEventListener('mousedown', this.buttonMousedownListener);
|
||||
this.signalButton.removeEventListener('mouseup', this.buttonMouseupListener);
|
||||
this.signalButton.removeEventListener('touchstart', this.buttonMousedownListener);
|
||||
this.signalButton.removeEventListener('touchend', this.buttonMouseupListener);
|
||||
this.startOverButton.removeEventListener('click', this.startOver);
|
||||
this.signalButton.setAttribute('disabled', 'disabled');
|
||||
this.startOverButton.setAttribute('disabled', 'disabled');
|
||||
}
|
||||
}
|
||||
|
||||
var playInputGameButton = document.getElementById("playInputGame");
|
||||
|
||||
async function playInputGame() {
|
||||
// TODO: check if there's a currentGame already. If there is, stop it!
|
||||
if (currentGame) {
|
||||
currentGame.stopGame();
|
||||
}
|
||||
|
||||
const signalButton = document.getElementById('signalButton');
|
||||
const startOverButton = document.getElementById('startOverButton');
|
||||
const targetDisplay = document.getElementById('targetDisplay');
|
||||
const inputDisplay = document.getElementById('inputDisplay');
|
||||
const inputStatus = document.getElementById('inputStatus');
|
||||
|
||||
currentGame = new InputGame(signalButton, startOverButton, targetDisplay, inputDisplay, inputStatus);
|
||||
|
||||
currentGame.startNewGame();
|
||||
|
||||
playInputGameButton.removeEventListener('click', playInputGame);
|
||||
playInputGameButton.addEventListener('click', stopInputGame);
|
||||
playInputGameButton.textContent = 'Stop';
|
||||
}
|
||||
|
||||
async function stopInputGame() {
|
||||
if (currentGame) {
|
||||
// Stop current game
|
||||
currentGame.stopGame();
|
||||
}
|
||||
|
||||
playInputGameButton.removeEventListener('click', stopInputGame);
|
||||
playInputGameButton.addEventListener('click', playInputGame);
|
||||
playInputGameButton.textContent = 'Start';
|
||||
}
|
||||
|
||||
playInputGameButton.addEventListener('click', playInputGame);
|
||||
|
||||
// For iOS, you need a touch event before you can play audio!
|
||||
var initializeAudioOnTouch = function() {
|
||||
if (!audioContextInitialized) {
|
||||
initializeAudioContext();
|
||||
}
|
||||
document.removeEventListener('touchend', initializeAudioOnTouch);
|
||||
}
|
||||
document.addEventListener('touchend', initializeAudioOnTouch);
|
935
morse-code_files/style.css
Normal file
935
morse-code_files/style.css
Normal file
@ -0,0 +1,935 @@
|
||||
/* Reset */
|
||||
|
||||
/* Removed sub from this so that subscript and superscript still do what they should */
|
||||
html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video {
|
||||
border: 0;
|
||||
font-size: 100%;
|
||||
font: inherit;
|
||||
vertical-align: baseline;
|
||||
margin: 0;
|
||||
padding: 0
|
||||
}
|
||||
|
||||
article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section {
|
||||
display: block
|
||||
}
|
||||
|
||||
body {
|
||||
line-height: 1
|
||||
}
|
||||
|
||||
blockquote, q {
|
||||
quotes: none
|
||||
}
|
||||
|
||||
blockquote:before, blockquote:after, q:before, q:after {
|
||||
content: none
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0
|
||||
}
|
||||
|
||||
*, *:before, *:after {
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
|
||||
/* Clearfix */
|
||||
|
||||
.clearfix:after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
/* Icons */
|
||||
|
||||
@font-face {
|
||||
font-family: 'icons';
|
||||
src: url('../fonts/icons.eot');
|
||||
src: url('../fonts/icons.eot#iefix') format('embedded-opentype'), url('../fonts/icons.woff') format('woff'), url('../fonts/icons.ttf') format('truetype'), url('../fonts/icons.svg#icons') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
[class^="icon-"]:before, [class*=" icon-"]:before {
|
||||
font-family: "icons";
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
speak: none;
|
||||
display: inline-block;
|
||||
text-decoration: inherit;
|
||||
text-align: center;
|
||||
font-variant: normal;
|
||||
text-transform: none;
|
||||
line-height: 1em;
|
||||
}
|
||||
|
||||
.icon-facebook:before {
|
||||
content: '\e802';
|
||||
}
|
||||
|
||||
.icon-facebook-squared:before {
|
||||
content: '\e800';
|
||||
}
|
||||
|
||||
.icon-twitter:before {
|
||||
content: '\e801';
|
||||
}
|
||||
|
||||
.icon-twitter-1:before {
|
||||
content: '\e804';
|
||||
}
|
||||
|
||||
.icon-facebook-circled:before {
|
||||
content: '\e805';
|
||||
}
|
||||
|
||||
.icon-twitter-circled:before {
|
||||
content: '\e806';
|
||||
}
|
||||
|
||||
.icon-facebook-rect:before {
|
||||
content: '\e803';
|
||||
}
|
||||
|
||||
|
||||
/* Spacing */
|
||||
|
||||
.post h1, h3, h4, h5, p, pre {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
/* We don't want sublists to have additional margins. Looks bad when unnested */
|
||||
#post-body ul, #post-list li, #post-body ol {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
/* Base */
|
||||
|
||||
html, body {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
font: 16px/1 "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
color: #222;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
text-rendering: optimizeLegibility;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 30px;
|
||||
letter-spacing: -1px;
|
||||
color: #222;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font: italic 19px/1.3em Georgia, serif;
|
||||
color: #222;
|
||||
}
|
||||
|
||||
.profile #wrapper {
|
||||
padding: 60px 40px 0px;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.profile #header {
|
||||
margin-bottom: 20px;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.profile #avatar {
|
||||
display: inline-block;
|
||||
width: 140px;
|
||||
height: 140px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.profile h1 {
|
||||
font-weight: 400;
|
||||
letter-spacing: 0px;
|
||||
font-size: 20px;
|
||||
color: #222;
|
||||
}
|
||||
|
||||
.profile h2 {
|
||||
font-size: 20px;
|
||||
font-weight: 300;
|
||||
color: #222;
|
||||
margin-top: 10px;
|
||||
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
nav.main-nav {
|
||||
padding: 20px 20px 0;
|
||||
background: #fff;
|
||||
background: rgba(255, 255, 255, .90);
|
||||
margin: 0 auto;
|
||||
text-align: right;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
nav.main-nav a {
|
||||
top: 8px;
|
||||
right: 6px;
|
||||
padding: 8px 12px;
|
||||
color: #5badf0;
|
||||
font-size: 16px;
|
||||
line-height: 1.35;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
nav.main-nav a.cta {
|
||||
background: #5badf0;
|
||||
color: #fff;
|
||||
margin-left: 12px;
|
||||
}
|
||||
@media (max-width: 700px) {
|
||||
nav.main-nav {
|
||||
padding: 20px 10px 0 0;
|
||||
background: #fff;
|
||||
background: rgba(255, 255, 255, .90);
|
||||
margin: 0 auto;
|
||||
text-align: right;
|
||||
z-index: 100;
|
||||
}
|
||||
nav.main-nav a {
|
||||
top: 8px;
|
||||
right: 6px;
|
||||
padding: 8px 8px;
|
||||
color: #5badf0;
|
||||
line-height: 1.35;
|
||||
border-radius: 3px;
|
||||
}
|
||||
}
|
||||
@media (max-width: 324px) {
|
||||
nav.main-nav a.cta {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
#wrapper {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 60px 40px 100px 40px;
|
||||
}
|
||||
|
||||
#wrapper.home {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 0px 40px 20px 40px;
|
||||
}
|
||||
|
||||
.home #avatar {
|
||||
float: right;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
|
||||
/* Typography */
|
||||
|
||||
|
||||
/*Accent color*/
|
||||
|
||||
a, #title, #post-list a:hover, #title:hover {
|
||||
text-decoration: none;
|
||||
color: #5badf0;
|
||||
color: #5694f1;
|
||||
}
|
||||
|
||||
p a {
|
||||
color: #5694f1;
|
||||
}
|
||||
|
||||
|
||||
/*Transitions*/
|
||||
|
||||
a, #post-nav a, #post-list a {
|
||||
-webkit-transition: all 0.15s ease;
|
||||
-moz-transition: all 0.15s ease;
|
||||
-ms-transition: all 0.15s ease;
|
||||
-o-transition: all 0.15s ease;
|
||||
transition: all 0.15s ease;
|
||||
}
|
||||
|
||||
ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
/*
|
||||
Remove this so that lists are normal?
|
||||
See the "reading this in the future" footnotes
|
||||
*/
|
||||
/* li {
|
||||
list-style-position: inside;
|
||||
} */
|
||||
|
||||
ul>li {
|
||||
list-style-type: circle;
|
||||
}
|
||||
|
||||
|
||||
/* Line Height */
|
||||
|
||||
#post-body, p {
|
||||
line-height: 1.7;
|
||||
}
|
||||
#post-body p > a {
|
||||
word-break: break-word;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
b, strong {
|
||||
font-weight: 500;
|
||||
color: #1E2025;
|
||||
}
|
||||
|
||||
em, i {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
#title {
|
||||
display: inline-block;
|
||||
line-height: 100%;
|
||||
font-weight: 500;
|
||||
font-size: 19px;
|
||||
margin: 0;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
.description {
|
||||
float: right;
|
||||
font: italic 14px/1.4em Georgia, serif;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.home h1 {
|
||||
font-size: 30px;
|
||||
letter-spacing: -1px;
|
||||
color: #222;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.home h2 {
|
||||
font: italic 19px/1.3em Georgia, serif;
|
||||
color: #222;
|
||||
}
|
||||
|
||||
.post header {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.post h1 {
|
||||
margin-bottom: 20px;
|
||||
color: #222;
|
||||
font: 300 32px/1.4em "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
.post h2 {
|
||||
margin-bottom: 20px;
|
||||
font: 300 24px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
color: #111;
|
||||
}
|
||||
|
||||
.post h2.headline {
|
||||
font: normal 13px/1.5em "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
margin: -5px 0 0 0;
|
||||
color: #333;
|
||||
font-size: 13px;
|
||||
letter-spacing: 1px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.post h2.headline .tags {
|
||||
font: normal 13px/1.5em "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
margin: -5px 0 40px 0;
|
||||
color: #b2b9be;
|
||||
font-size: 13px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 2px;
|
||||
margin-top: 5px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
#post-list h2 {
|
||||
font: normal 17px/1.5em "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
color: #333;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
h3, h4, h5 {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 20px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 15px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 13px;
|
||||
font-weight: bold;
|
||||
color: #222;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
p.small {
|
||||
color: #222;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
display: block;
|
||||
text-align: center;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
padding-left: 15px;
|
||||
border-left: 3px solid #eee;
|
||||
}
|
||||
|
||||
hr {
|
||||
display: block;
|
||||
border: none;
|
||||
height: 1px;
|
||||
margin: 40px auto;
|
||||
background: #eee;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
margin: 40px 0;
|
||||
border-collapse: collapse;
|
||||
font-size: 13px;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
th, td {
|
||||
text-align: left;
|
||||
padding-right: 20px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
table td, td {
|
||||
border-spacing: none;
|
||||
border-style: solid;
|
||||
padding: 10px 15px;
|
||||
border-width: 1px 0 0 0;
|
||||
}
|
||||
|
||||
tr>td {
|
||||
border-top: 1px solid #eaeaea;
|
||||
}
|
||||
|
||||
tr:nth-child(odd)>td {
|
||||
background: #fcfcfc;
|
||||
}
|
||||
|
||||
thead th, th {
|
||||
text-align: left;
|
||||
padding: 10px 15px;
|
||||
height: 20px;
|
||||
font-size: 13px;
|
||||
font-weight: bold;
|
||||
color: #444;
|
||||
border-bottom: 1px solid #dadadc;
|
||||
cursor: default;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
img {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
video {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
|
||||
/* Made with Cactus Badge */
|
||||
|
||||
#badge {
|
||||
position: absolute;
|
||||
bottom: 8px;
|
||||
right: 8px;
|
||||
height: 48px;
|
||||
width: 48px;
|
||||
}
|
||||
|
||||
|
||||
/*=========================================
|
||||
Post List
|
||||
=========================================== */
|
||||
|
||||
#post-list, #archive-list {
|
||||
padding-left: 0px;
|
||||
}
|
||||
|
||||
#post-list li, #archive-list li {
|
||||
list-style-type: none;
|
||||
border: 1px solid #333;
|
||||
padding: 10px;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
#post-list li:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
#post-list a {
|
||||
color: #333;
|
||||
display: block;
|
||||
font: bold 19px/1.0 "Helvetica Neue", helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
#post-list .dates {
|
||||
font: 300 17px/1.8 "Helvetica Neue", helvetica, Arial, sans-serif;
|
||||
color: #222;
|
||||
}
|
||||
|
||||
#post-list-footer {
|
||||
border-top: 1px solid #eee;
|
||||
margin-top: 20px;
|
||||
padding-top: 100px;
|
||||
}
|
||||
|
||||
#archive-link {
|
||||
display: inline-block;
|
||||
font-size: 13px;
|
||||
font-weight: bold;
|
||||
border-radius: 4px;
|
||||
padding: 3px 10px 6px;
|
||||
box-shadow: 0 0 0 1px hsla(207, 83%, 80%, 1);
|
||||
}
|
||||
|
||||
#archive-link:hover {
|
||||
background: #5694f1;
|
||||
color: #fff;
|
||||
box-shadow: 0 0 0 1px #5694f1;
|
||||
}
|
||||
|
||||
#archive-link span {
|
||||
position: relative;
|
||||
top: 0;
|
||||
font-size: 17px;
|
||||
}
|
||||
|
||||
#footer {
|
||||
margin-top: 100px;
|
||||
}
|
||||
|
||||
|
||||
/* Post Page */
|
||||
|
||||
#header {
|
||||
}
|
||||
|
||||
.post {
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
#post-meta {
|
||||
font-size: 13px;
|
||||
font-weight: bold;
|
||||
line-height: 1.4;
|
||||
border-top: 1px solid #eee;
|
||||
padding-top: 40px;
|
||||
margin-bottom: 40px;
|
||||
padding-bottom: 40px;
|
||||
margin-top: 40px;
|
||||
color: #444;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
#post-meta div span {
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
display: block;
|
||||
}
|
||||
|
||||
#post-meta div span.dark {
|
||||
color: #1E2025;
|
||||
}
|
||||
|
||||
#post-meta div {
|
||||
margin: 0 25px 0 0;
|
||||
float: left;
|
||||
}
|
||||
|
||||
#sharing {
|
||||
float: right;
|
||||
margin: -2px;
|
||||
}
|
||||
|
||||
#sharing a {
|
||||
font-size: 20px;
|
||||
font-size: 23px;
|
||||
margin-left: 1px;
|
||||
margin-top: 4px;
|
||||
color: #d4d4d4;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
#sharing a:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
|
||||
/* Post Navigation */
|
||||
|
||||
#post-nav {
|
||||
text-align: center;
|
||||
padding-top: 20px;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
#post-nav span {
|
||||
-webkit-transition: all 0.1s linear;
|
||||
-moz-transition: all 0.1s linear;
|
||||
-ms-transition: all 0.1s linear;
|
||||
-o-transition: all 0.1s linear;
|
||||
transition: all 0.1s linear;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#post-nav span.prev {
|
||||
float: left;
|
||||
}
|
||||
|
||||
#post-nav span.next {
|
||||
float: right;
|
||||
}
|
||||
|
||||
#post-nav span .arrow {
|
||||
position: relative;
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
#post-nav span.prev:hover .arrow {
|
||||
left: -4px;
|
||||
}
|
||||
|
||||
#post-nav span.next:hover .arrow {
|
||||
right: -4px;
|
||||
}
|
||||
|
||||
#post-nav span.prev:hover {
|
||||
left: -3px;
|
||||
}
|
||||
|
||||
#post-nav span.next:hover {
|
||||
right: -3px;
|
||||
}
|
||||
|
||||
|
||||
/* Archive */
|
||||
|
||||
h1.archive {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
h2.month {
|
||||
width: 100%;
|
||||
font: bold 13px/1 "Helvetica Neue", helvetica, Arial, sans-serif;
|
||||
text-transform: uppercase;
|
||||
margin-top: 40px;
|
||||
margin-bottom: 10px;
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
#archive-list li:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
#archive-list a {
|
||||
display: block;
|
||||
font: bold 17px/1.7 "Helvetica Neue", helvetica, Arial, sans-serif;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
#archive-list .dates {
|
||||
float: right;
|
||||
position: relative;
|
||||
top: 1px;
|
||||
font: 300 17px/1.7 "Helvetica Neue", helvetica, Arial, sans-serif;
|
||||
color: #222;
|
||||
}
|
||||
|
||||
#archive-list li a:hover, #archive-list li:hover .dates {
|
||||
color: #5694f1;
|
||||
}
|
||||
|
||||
#post-meta img.avatar {
|
||||
height: 36px;
|
||||
width: 36px;
|
||||
float: left;
|
||||
border-radius: 50%;
|
||||
margin-top: 3px;
|
||||
margin-right: 20px;
|
||||
box-shadow: 0 0 0 3px #fff, 0 0 0 4px #eee;
|
||||
}
|
||||
|
||||
#post-list.archive.readmore {
|
||||
margin-top: 100px;
|
||||
}
|
||||
|
||||
#post-list.archive.readmore h3 {
|
||||
font: 400 20px "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
#post-list.archive.readmore a {
|
||||
font: 400 16px/1.6 "Helvetica Neue", helvetica, Arial, sans-serif;
|
||||
color: #5694f1;
|
||||
}
|
||||
|
||||
#post-list.archive.readmore a:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
#post-list.archive.readmore .dates {
|
||||
font: 300 16px/1.6 "Helvetica Neue", helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
#disqus_thread, #ds-thread {
|
||||
margin-top: 100px;
|
||||
}
|
||||
|
||||
#sharing a.facebook {
|
||||
background: #4361b3;
|
||||
}
|
||||
|
||||
#sharing a.twitter {
|
||||
background: #4fafed;
|
||||
}
|
||||
|
||||
#sharing a {
|
||||
font-size: 20px;
|
||||
font-size: 13px;
|
||||
font-weight: bold;
|
||||
color: #fff;
|
||||
padding: 6px 10px;
|
||||
border-radius: 4px;
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
||||
|
||||
/* Media Queries */
|
||||
|
||||
@media screen and (max-width: 540px) {
|
||||
#wrapper {
|
||||
padding: 20px 20px 20px 20px;
|
||||
}
|
||||
#header {
|
||||
margin-bottom: 60px;
|
||||
}
|
||||
.post {
|
||||
margin: 40px 0;
|
||||
}
|
||||
#footer {
|
||||
margin-top: 60px;
|
||||
}
|
||||
#post-list, #archive-list {
|
||||
margin-top: 0;
|
||||
}
|
||||
#post-meta {
|
||||
margin-top: 60px;
|
||||
}
|
||||
#title {
|
||||
font-size: 17px;
|
||||
}
|
||||
#post-list .dates {
|
||||
}
|
||||
#post-list-footer {
|
||||
margin-top: 20px;
|
||||
padding-top: 40px;
|
||||
}
|
||||
h1 {
|
||||
font-size: 26px;
|
||||
}
|
||||
.post h2.headline {
|
||||
font-size: 13px;
|
||||
}
|
||||
.post h1 {
|
||||
font-size: 24px;
|
||||
}
|
||||
.post h2 {
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.archive {
|
||||
margin: 0 0 50px 0;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.archive .post-item {
|
||||
padding: 10px 0px;
|
||||
overflow-x: hidden;
|
||||
white-space:nowrap;
|
||||
}
|
||||
|
||||
.archive .post-time {
|
||||
display: inline-block;
|
||||
width: 60px;
|
||||
margin: 0;
|
||||
color: #222;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
.archive .post-time {
|
||||
margin: 5px 0;
|
||||
width: auto;
|
||||
font-size: 13px;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.archive .post-link {
|
||||
color: #222;
|
||||
}
|
||||
|
||||
.archive .post-item:hover {
|
||||
color: #5694f1;
|
||||
transition: 0.3s ease-out;
|
||||
}
|
||||
.archive .post-item:hover .post-link {
|
||||
color: #5694f1;
|
||||
}
|
||||
|
||||
.fa.fa-heart:hover {
|
||||
color: #ff3356;
|
||||
transition: 0.7s ease-out;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
/* CUSTOM ADDITIONS */
|
||||
|
||||
#social {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
a.symbol {
|
||||
color: #222;
|
||||
font-size: 2rem;
|
||||
text-decoration: none;
|
||||
margin-right: 0.3rem;
|
||||
}
|
||||
|
||||
a.symbol:hover {
|
||||
color: #BCD4DA;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Table of content
|
||||
*/
|
||||
#toc {
|
||||
line-height: 1em;
|
||||
word-wrap: break-word;
|
||||
padding: 8px;
|
||||
padding-left: 16px;
|
||||
padding-bottom: 14px;
|
||||
margin: 0 0 25px 0;
|
||||
display: block;
|
||||
color: #808080;
|
||||
background: #fff;
|
||||
border: none;
|
||||
box-shadow: inset 0 0 0 1px #E4EBF2;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
}
|
||||
#TableOfContents {
|
||||
overflow-x: auto;
|
||||
word-wrap: normal;
|
||||
word-break: break-all;
|
||||
white-space: nowrap;
|
||||
}
|
||||
#TableOfContents ul {
|
||||
list-style-type:none;
|
||||
margin: 0;
|
||||
padding: 0 .5em;
|
||||
}
|
||||
#TableOfContents ul li {
|
||||
list-style-type: none;
|
||||
line-height: 1.7em;
|
||||
}
|
||||
#TableOfContents > ul {
|
||||
padding: 0;
|
||||
}
|
||||
#TableOfContents > ul > li > ul {
|
||||
padding: 0 3em;
|
||||
}
|
||||
#TableOfContents a code{
|
||||
font-family: Menlo, Monaco, Courier;
|
||||
background-color: #fff;
|
||||
font-size: 11px;
|
||||
padding: 2px 3px;
|
||||
font-weight: 100;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* tags page
|
||||
*/
|
||||
|
||||
#wrapper.tags {
|
||||
padding: 0px 40px 20px 40px;
|
||||
}
|
||||
.page-tags {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.page-tags .tags {
|
||||
font: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
margin: 10px 15px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.page-tags .tags a {
|
||||
color: #222;
|
||||
}
|
||||
|
||||
.page-tags .tags:hover a {
|
||||
color: #5694f1;
|
||||
}
|
60
morse-code_files/styles.css
Normal file
60
morse-code_files/styles.css
Normal file
@ -0,0 +1,60 @@
|
||||
.game-container {
|
||||
padding: 10px;
|
||||
border-radius: 36px;
|
||||
box-shadow: 0px 11px 20px 4px #aaa;
|
||||
}
|
||||
|
||||
#wordInput {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.start-button {
|
||||
width: 100px;
|
||||
height: 40px;
|
||||
border-radius: 10px;
|
||||
margin: 10px;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.interaction-button {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
border-radius: 100%;
|
||||
margin: 10px;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.game-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.input {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.display-message {
|
||||
font-size: 20px;
|
||||
text-align: center;
|
||||
min-height: 1.7em;
|
||||
}
|
||||
|
||||
.morse-input {
|
||||
white-space: pre-wrap;
|
||||
border-bottom: 1px solid #aaa;
|
||||
border-radius: 4px;
|
||||
min-height: calc(1.7em + 1px);
|
||||
}
|
||||
|
||||
.button-container {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
#speed-table {
|
||||
max-width: 100%;
|
||||
overflow: scroll;
|
||||
}
|
Reference in New Issue
Block a user