mirror of
https://github.com/monkeytypegame/monkeytype.git
synced 2025-10-06 13:40:16 +08:00
Merge branch 'master' into master
This commit is contained in:
commit
f0ee3fec7c
17 changed files with 963 additions and 190 deletions
|
@ -62,7 +62,7 @@ function isUsernameValid(name) {
|
|||
if (name === null || name === undefined || name === "") return false;
|
||||
if (/miodec/.test(name.toLowerCase())) return false;
|
||||
if (/bitly/.test(name.toLowerCase())) return false;
|
||||
if (name.length > 12) return false;
|
||||
if (name.length > 14) return false;
|
||||
return /^[0-9a-zA-Z_.-]+$/.test(name);
|
||||
}
|
||||
|
||||
|
@ -569,10 +569,15 @@ exports.testCompleted = functions.https.onCall(async (request, response) => {
|
|||
userdata.discordId !== null &&
|
||||
userdata.discordId !== undefined
|
||||
) {
|
||||
console.log(
|
||||
`sending command to the bot to update the role for user ${request.uid} with wpm ${obj.wpm}`
|
||||
);
|
||||
updateDiscordRole(userdata.discordId, Math.round(obj.wpm));
|
||||
if (verified !== false) {
|
||||
console.log(
|
||||
`sending command to the bot to update the role for user ${request.uid} with wpm ${obj.wpm}`
|
||||
);
|
||||
updateDiscordRole(
|
||||
userdata.discordId,
|
||||
Math.round(obj.wpm)
|
||||
);
|
||||
}
|
||||
}
|
||||
returnobj.resultCode = 2;
|
||||
} else {
|
||||
|
@ -1105,9 +1110,11 @@ async function checkLeaderboards(
|
|||
verified,
|
||||
emailVerified
|
||||
) {
|
||||
//lb disable
|
||||
// return {
|
||||
// insertedAt: null,
|
||||
// };
|
||||
//
|
||||
try {
|
||||
if (emailVerified === false)
|
||||
return {
|
||||
|
|
18
functions/package-lock.json
generated
18
functions/package-lock.json
generated
|
@ -1889,9 +1889,9 @@
|
|||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.15",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
|
||||
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
|
||||
"version": "4.17.19",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
|
||||
"integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ=="
|
||||
},
|
||||
"lodash.at": {
|
||||
"version": "4.6.0",
|
||||
|
@ -2855,13 +2855,15 @@
|
|||
"http-parser-js": ">=0.5.1",
|
||||
"safe-buffer": ">=5.1.0",
|
||||
"websocket-extensions": ">=0.1.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"websocket-extensions": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz",
|
||||
"integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"websocket-extensions": {
|
||||
"version": ">=0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz",
|
||||
"integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg=="
|
||||
},
|
||||
"which": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
:root {
|
||||
--roundness: 0.25rem;
|
||||
--font: "Roboto Mono";
|
||||
}
|
||||
|
||||
::placeholder {
|
||||
|
@ -28,7 +29,7 @@ input {
|
|||
padding: 0.5rem;
|
||||
font-size: 1rem;
|
||||
line-height: 1rem;
|
||||
font-family: "Roboto Mono";
|
||||
font-family: var(--font);
|
||||
}
|
||||
|
||||
input[type="color"] {
|
||||
|
@ -83,7 +84,7 @@ body {
|
|||
padding: 0;
|
||||
min-height: 100vh;
|
||||
background: var(--bg-color);
|
||||
font-family: "Roboto Mono";
|
||||
font-family: var(--font);
|
||||
color: var(--main-color);
|
||||
// overflow-x: hidden;
|
||||
}
|
||||
|
@ -326,6 +327,79 @@ a:hover {
|
|||
}
|
||||
}
|
||||
|
||||
#customTextPopupWrapper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.75);
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: 1000;
|
||||
display: grid;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 5rem 0;
|
||||
|
||||
#customTextPopup {
|
||||
background: var(--bg-color);
|
||||
border-radius: var(--roundness);
|
||||
padding: 2rem;
|
||||
display: grid;
|
||||
gap: 1rem;
|
||||
width: 60vw;
|
||||
|
||||
textarea {
|
||||
background: var(--bg-color);
|
||||
padding: 1rem;
|
||||
color: var(--main-color);
|
||||
border: none;
|
||||
outline: none;
|
||||
font-size: 1rem;
|
||||
font-family: var(--font);
|
||||
width: 100%;
|
||||
border-radius: var(--roundness);
|
||||
resize: vertical;
|
||||
height: 200px;
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.inputs {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 1rem;
|
||||
align-items: center;
|
||||
justify-items: center;
|
||||
}
|
||||
|
||||
.check {
|
||||
input {
|
||||
margin: 0 !important;
|
||||
cursor: pointer;
|
||||
width: 0;
|
||||
height: 0;
|
||||
display: none;
|
||||
|
||||
&~.customTextRandomCheckbox {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
background: rgba(0, 0, 0, .1);
|
||||
border-radius: 2px;
|
||||
box-shadow: 0 0 0 4px rgba(0, 0, 0, .1);
|
||||
display: inline-block;
|
||||
margin: 0 .5rem 0 .25rem;
|
||||
transition: .25s;
|
||||
}
|
||||
|
||||
&:checked~.customTextRandomCheckbox {
|
||||
background: var(--main-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#customThemeShareWrapper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
@ -470,7 +544,7 @@ a:hover {
|
|||
border: none;
|
||||
outline: none;
|
||||
font-size: 1rem;
|
||||
font-family: "Roboto Mono";
|
||||
font-family: var(--font);
|
||||
width: 100%;
|
||||
border-radius: var(--roundness);
|
||||
resize: vertical;
|
||||
|
@ -498,7 +572,7 @@ a:hover {
|
|||
border: none;
|
||||
outline: none;
|
||||
font-size: 1rem;
|
||||
font-family: "Roboto Mono";
|
||||
font-family: var(--font);
|
||||
width: 100%;
|
||||
border-radius: var(--roundness);
|
||||
}
|
||||
|
@ -1140,6 +1214,26 @@ key {
|
|||
}
|
||||
}
|
||||
|
||||
#capsWarning {
|
||||
background: var(--main-color);
|
||||
color: var(--bg-color);
|
||||
display: table;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 66vh;
|
||||
transform: translateX(-50%) translateY(-50%);
|
||||
padding: 1rem;
|
||||
border-radius: var(--roundness);
|
||||
/* margin-top: 1rem; */
|
||||
transition: .25s;
|
||||
z-index: 999;
|
||||
pointer-events: none;
|
||||
|
||||
i {
|
||||
margin-right: .5rem;
|
||||
}
|
||||
}
|
||||
|
||||
#wordsInput {
|
||||
height: 0;
|
||||
padding: 0;
|
||||
|
@ -1688,7 +1782,7 @@ key {
|
|||
text-align: left;
|
||||
border: 0;
|
||||
background: 0;
|
||||
font-family: "Roboto Mono";
|
||||
font-family: var(--font);
|
||||
|
||||
&:first-child {
|
||||
margin-right: 0.5rem;
|
||||
|
@ -1718,12 +1812,13 @@ key {
|
|||
.tabContent {
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
max-height: 0px;
|
||||
// max-height: 0px;
|
||||
// max-height: 100vh;
|
||||
|
||||
// transition: max-height .5s ease-in-out;
|
||||
&.reveal {
|
||||
max-height: 100vh;
|
||||
}
|
||||
// &.reveal {
|
||||
// max-height: 100vh;
|
||||
// }
|
||||
|
||||
.text {
|
||||
align-self: center;
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<title>Monkey Type</title>
|
||||
<link rel="stylesheet" href="css/fa.css">
|
||||
<link rel="stylesheet" href="css/balloon.css">
|
||||
<link rel="stylesheet" href="css/style.css?v=40">
|
||||
<link rel="stylesheet" href="css/style.css?v=45">
|
||||
<link rel="stylesheet" href="themes/serika_dark.css" id="currentTheme">
|
||||
<link id="favicon" rel="shortcut icon" href="fav.png">
|
||||
<link rel="shortcut icon" href="fav.png">
|
||||
|
@ -43,6 +43,20 @@
|
|||
<div class="button">ok</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="customTextPopupWrapper" class="hidden">
|
||||
<div id="customTextPopup" action="">
|
||||
<textarea class="textarea" placeholder="Custom text"></textarea>
|
||||
<div class="inputs">
|
||||
<label class="check"><input type="checkbox">
|
||||
<div class="customTextRandomCheckbox"></div>Random
|
||||
</label>
|
||||
<label class="wordcount"><input type="number" value="1" min="1" max="10000">
|
||||
Word count
|
||||
</label>
|
||||
</div>
|
||||
<div class="button">ok</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="tagsWrapper" class="hidden">
|
||||
<div id="tagsEdit" action="" tagid="">
|
||||
<div class="title"></div>
|
||||
|
@ -535,6 +549,9 @@
|
|||
<div id="timerWrapper">
|
||||
<div id="timer"></div>
|
||||
</div>
|
||||
<div id="capsWarning" class="hidden">
|
||||
<i class="fas fa-lock"></i>Caps Lock
|
||||
</div>
|
||||
<div id="centerContent" class="hidden">
|
||||
<div id="top">
|
||||
<div class="logo">
|
||||
|
@ -980,12 +997,14 @@
|
|||
<div class="button off" tabindex="0" onclick="this.blur();">off</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section maxConfidence">
|
||||
<h1>max confidence</h1>
|
||||
<div class="text">When enabled, you will not be able to go back to previous words to fix mistakes.</div>
|
||||
<div class="section confidenceMode">
|
||||
<h1>confidence mode</h1>
|
||||
<div class="text">When enabled, you will not be able to go back to previous words to fix mistakes. When turned
|
||||
up to the max, you won't be able to backspace at all.</div>
|
||||
<div class="buttons">
|
||||
<div class="button on" tabindex="0" onclick="this.blur();">on</div>
|
||||
<div class="button off" tabindex="0" onclick="this.blur();">off</div>
|
||||
<div class="button" confidenceMode="on" tabindex="0" onclick="this.blur();">on</div>
|
||||
<div class="button" confidenceMode="off" tabindex="0" onclick="this.blur();">off</div>
|
||||
<div class="button" confidenceMode="max" tabindex="0" onclick="this.blur();">max</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section stopOnError">
|
||||
|
@ -1194,44 +1213,44 @@
|
|||
<button tab="custom" class="tab">custom</button>
|
||||
</div>
|
||||
<div class="tabContainer">
|
||||
<div tabContent="custom" class="tabContent section customTheme">
|
||||
<div tabContent="custom" class="tabContent section customTheme hidden">
|
||||
<label class="text">background</label>
|
||||
<span class="colorPicker">
|
||||
<label for="--bg-color">#e2b714</label>
|
||||
<input type="color" value="" id="--bg-color">
|
||||
<label for="--bg-color">#000000</label>
|
||||
<input type="color" value="#000000" id="--bg-color">
|
||||
</span>
|
||||
<label class="text">main</label>
|
||||
<span class="colorPicker">
|
||||
<label for="--main-color">#e2b714</label>
|
||||
<input type="color" value="" id="--main-color">
|
||||
<label for="--main-color">#000000</label>
|
||||
<input type="color" value="#000000" id="--main-color">
|
||||
</span>
|
||||
<label class="text">caret</label>
|
||||
<span class="colorPicker">
|
||||
<label for="--caret-color">#e2b714</label>
|
||||
<input type="color" value="" id="--caret-color">
|
||||
<label for="--caret-color">#000000</label>
|
||||
<input type="color" value="#000000" id="--caret-color">
|
||||
</span>
|
||||
<label class="text">sub</label>
|
||||
<span class="colorPicker">
|
||||
<label for="--sub-color">#e2b714</label>
|
||||
<input type="color" value="" id="--sub-color">
|
||||
<label for="--sub-color">#000000</label>
|
||||
<input type="color" value="#000000" id="--sub-color">
|
||||
</span>
|
||||
<label class="text">text</label>
|
||||
<span class="colorPicker">
|
||||
<label for="--text-color">#e2b714</label>
|
||||
<input type="color" value="" id="--text-color">
|
||||
<label for="--text-color">#000000</label>
|
||||
<input type="color" value="#000000" id="--text-color">
|
||||
</span>
|
||||
|
||||
<span class="spacer"></span>
|
||||
|
||||
<label class="text">error</label>
|
||||
<span class="colorPicker">
|
||||
<label for="--error-color">#e2b714</label>
|
||||
<input type="color" value="" id="--error-color">
|
||||
<label for="--error-color">#000000</label>
|
||||
<input type="color" value="#000000" id="--error-color">
|
||||
</span>
|
||||
<label class="text">extra error</label>
|
||||
<span class="colorPicker">
|
||||
<label for="--error-extra-color">#e2b714</label>
|
||||
<input type="color" value="" id="--error-extra-color">
|
||||
<label for="--error-extra-color">#000000</label>
|
||||
<input type="color" value="#000000" id="--error-extra-color">
|
||||
</span>
|
||||
|
||||
<p>colorful mode</p>
|
||||
|
@ -1239,14 +1258,14 @@
|
|||
<label class="text">error</label>
|
||||
<span class="colorPicker">
|
||||
<!-- Change variable names here -->
|
||||
<label for="--colorful-error-color">#e2b714</label>
|
||||
<input type="color" value="" id="--colorful-error-color">
|
||||
<label for="--colorful-error-color">#000000</label>
|
||||
<input type="color" value="#000000" id="--colorful-error-color">
|
||||
</span>
|
||||
<label class="text">extra error</label>
|
||||
<span class="colorPicker">
|
||||
<!-- Change variable names here -->
|
||||
<label for="--colorful-error-extra-color">#e2b714</label>
|
||||
<input type="color" value="" id="--colorful-error-extra-color">
|
||||
<label for="--colorful-error-extra-color">#000000</label>
|
||||
<input type="color" value="#000000" id="--colorful-error-extra-color">
|
||||
</span>
|
||||
<div style="grid-column: 3/5;display:grid;gap:1rem;grid-auto-flow: column;">
|
||||
<div class="button" id="shareCustomThemeButton">share</div>
|
||||
|
@ -1516,7 +1535,7 @@
|
|||
|
||||
<div id="bottom">
|
||||
<div class="keyTips">
|
||||
<key>tab</key> and <key>enter</key> / <key>space</key> - restart test<br>
|
||||
<key>tab</key> and <key>enter</key> - restart test<br>
|
||||
<key>esc</key> - command line
|
||||
</div>
|
||||
<div>
|
||||
|
@ -1555,17 +1574,17 @@
|
|||
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>
|
||||
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.min.js"></script> -->
|
||||
<script src="js/chart.js"></script>
|
||||
<script src="js/chartjs-plugin-trendline.js?v=41"></script>
|
||||
<script src="js/chartjs-plugin-trendline.js?v=45"></script>
|
||||
<script src="js/chartjs-plugin-annotation.js"></script>
|
||||
<script src="js/html2canvas.js"></script>
|
||||
<script src="js/words.js?v=41"></script>
|
||||
<script src="js/layouts.js?v=41"></script>
|
||||
<script src="js/db.js?v=41"></script>
|
||||
<script src="js/userconfig.js?v=41"></script>
|
||||
<script src="js/commandline.js?v=41"></script>
|
||||
<script src="js/leaderboards.js?v=41"></script>
|
||||
<script src="js/settings.js?v=41"></script>
|
||||
<script src="js/account.js?v=41"></script>
|
||||
<script src="js/script.js?v=41"></script>
|
||||
<script src="js/words.js?v=45"></script>
|
||||
<script src="js/layouts.js?v=45"></script>
|
||||
<script src="js/db.js?v=45"></script>
|
||||
<script src="js/userconfig.js?v=45"></script>
|
||||
<script src="js/commandline.js?v=45"></script>
|
||||
<script src="js/leaderboards.js?v=45"></script>
|
||||
<script src="js/settings.js?v=45"></script>
|
||||
<script src="js/account.js?v=45"></script>
|
||||
<script src="js/script.js?v=45"></script>
|
||||
|
||||
</html>
|
|
@ -111,7 +111,7 @@ function signUp() {
|
|||
return;
|
||||
} else if (d.data === -2) {
|
||||
showNotification(
|
||||
"Name cannot contain special characters or contain more than 12 characters. Can include _ . and -",
|
||||
"Name cannot contain special characters or contain more than 14 characters. Can include _ . and -",
|
||||
8000
|
||||
);
|
||||
$(".pageLogin .preloader").addClass("hidden");
|
||||
|
|
|
@ -51,6 +51,15 @@ let commands = {
|
|||
showCommandLine();
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "changeConfidenceMode",
|
||||
display: "Change confidence mode...",
|
||||
subgroup: true,
|
||||
exec: () => {
|
||||
currentCommands.push(commandsConfidenceMode);
|
||||
showCommandLine();
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "toggleSmoothCaret",
|
||||
display: "Toggle smooth caret",
|
||||
|
@ -95,13 +104,6 @@ let commands = {
|
|||
toggleFreedomMode();
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "toggleMaxConfidence",
|
||||
display: "Toggle max confidence",
|
||||
exec: () => {
|
||||
toggleMaxConfidence();
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "toggleBlindMode",
|
||||
display: "Toggle blind mode",
|
||||
|
@ -556,6 +558,33 @@ let commandsTimeConfig = {
|
|||
],
|
||||
};
|
||||
|
||||
let commandsConfidenceMode = {
|
||||
title: "Change confidence mode...",
|
||||
list: [
|
||||
{
|
||||
id: "changeConfidenceModeOff",
|
||||
display: "off",
|
||||
exec: () => {
|
||||
setConfidenceMode("off");
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "changeConfidenceModeOn",
|
||||
display: "on",
|
||||
exec: () => {
|
||||
setConfidenceMode("on");
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "changeConfidenceModeMax",
|
||||
display: "max",
|
||||
exec: () => {
|
||||
setConfidenceMode("max");
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
let commandsFontSize = {
|
||||
title: "Change font size...",
|
||||
list: [
|
||||
|
@ -648,7 +677,7 @@ $.getJSON("themes/list.json", function (data) {
|
|||
data.forEach((theme) => {
|
||||
commandsThemes.list.push({
|
||||
id: "changeTheme" + capitalizeFirstLetter(theme.name),
|
||||
display: theme.name.replace("_", " "),
|
||||
display: theme.name.replace(/_/g, " "),
|
||||
hover: () => {
|
||||
previewTheme(theme.name);
|
||||
},
|
||||
|
@ -685,7 +714,7 @@ if (Object.keys(words).length > 0) {
|
|||
if (language === "english_10k") return;
|
||||
commandsLanguages.list.push({
|
||||
id: "changeLanguage" + capitalizeFirstLetter(language),
|
||||
display: language.replace("_", " "),
|
||||
display: language.replace(/_/g, " "),
|
||||
exec: () => {
|
||||
changeLanguage(language);
|
||||
restartTest();
|
||||
|
@ -721,7 +750,7 @@ if (Object.keys(layouts).length > 0) {
|
|||
Object.keys(layouts).forEach((layout) => {
|
||||
commandsLayouts.list.push({
|
||||
id: "changeLayout" + capitalizeFirstLetter(layout),
|
||||
display: layout.replace("_", " "),
|
||||
display: layout.replace(/_/g, " "),
|
||||
exec: () => {
|
||||
changeLayout(layout);
|
||||
restartTest();
|
||||
|
@ -888,7 +917,7 @@ $(document).keydown((e) => {
|
|||
$(".suggestions").outerHeight() / 2 +
|
||||
$($(".entry")[0]).outerHeight();
|
||||
$(".suggestions").scrollTop(scroll);
|
||||
console.log(`scrolling to ${scroll}`);
|
||||
// console.log(`scrolling to ${scroll}`);
|
||||
try {
|
||||
let list = currentCommands[currentCommands.length - 1];
|
||||
$.each(list.list, (index, obj) => {
|
||||
|
|
|
@ -34,5 +34,40 @@ const layouts = {
|
|||
"uU","iİ","eE","aA","üÜ","tT","kK","mM","lL","yY","şŞ",
|
||||
"jJ","öÖ","vV","cC","çÇ","zZ","sS","bB",".:",",;",
|
||||
" "
|
||||
],
|
||||
norman: [
|
||||
"`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
|
||||
"qQ","wW","dD","fF","kK","jJ","uU","rR","lL",";:","[{","]}","\\|",
|
||||
"aA","sS","eE","tT","gG","yY","nN","iI","oO","hH","'\"",
|
||||
"zZ","xX","cC","vV","bB","pP","mM",",<",".>","/?",
|
||||
" "
|
||||
],
|
||||
halmak: [
|
||||
"`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
|
||||
"wW","lL","rR","bB","zZ",";:","qQ","uU","dD","jJ","[{","]}","\\|",
|
||||
"sS","hH","nN","tT",",<",".>","aA","eE","oO","iI","'\"",
|
||||
"fF","mM","vV","cC","/?","gG","pP","xX","kK","yY",
|
||||
" "
|
||||
],
|
||||
QGMLWB: [
|
||||
"`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
|
||||
"qQ","gG","mM","lL","wW","bB","yY","uU","vV",";:","[{","]}","\\|",
|
||||
"dD","sS","tT","nN","rR","iI","aA","eE","oO","hH","'\"",
|
||||
"zZ","xX","cC","fF","jJ","kK","pP",",<",".>","/?",
|
||||
" "
|
||||
],
|
||||
QGMLWY: [
|
||||
"`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
|
||||
"qQ","gG","mM","lL","wW","yY","fF","uU","bB",";:","[{","]}","\\|",
|
||||
"dD","sS","tT","nN","rR","iI","aA","eE","oO","hH","'\"",
|
||||
"zZ","xX","cC","vV","jJ","kK","pP",",<",".>","/?",
|
||||
" "
|
||||
],
|
||||
qwpr: [
|
||||
"`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
|
||||
"qQ","wW","pP","rR","fF","yY","uU","kK","lL",";:","[{","]}","\\|",
|
||||
"aA","sS","dD","tT","gG","hH","nN","iI","oO","eE","'\"",
|
||||
"zZ","xX","cC","vV","bB","jJ","mM",",<",".>","/?",
|
||||
" "
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
let wordsList = [];
|
||||
let currentWordIndex = 0;
|
||||
let currentWordElementIndex = 0;
|
||||
let inputHistory = [];
|
||||
let currentInput = "";
|
||||
let time = 0;
|
||||
|
@ -42,6 +43,8 @@ let keypressStats = {
|
|||
};
|
||||
|
||||
let customText = "The quick brown fox jumps over the lazy dog".split(" ");
|
||||
let customTextIsRandom = false;
|
||||
let customTextWordCount = 1;
|
||||
let randomQuote = null;
|
||||
|
||||
const testCompleted = firebase.functions().httpsCallable("testCompleted");
|
||||
|
@ -260,6 +263,7 @@ function initWords() {
|
|||
testActive = false;
|
||||
wordsList = [];
|
||||
currentWordIndex = 0;
|
||||
currentWordElementIndex = 0;
|
||||
accuracyStats = {
|
||||
correct: 0,
|
||||
incorrect: 0,
|
||||
|
@ -299,27 +303,46 @@ function initWords() {
|
|||
language = words[config.language];
|
||||
}
|
||||
|
||||
if (config.mode == "time" || config.mode == "words") {
|
||||
if (
|
||||
config.mode == "time" ||
|
||||
config.mode == "words" ||
|
||||
(config.mode == "custom" && customTextIsRandom)
|
||||
) {
|
||||
// let wordsBound = config.mode == "time" ? 60 : config.words;
|
||||
let wordsBound = 60;
|
||||
if (config.showAllLines && config.mode != "time") {
|
||||
wordsBound = config.words;
|
||||
if (config.showAllLines) {
|
||||
if (config.mode === "custom") {
|
||||
wordsBound = customTextWordCount;
|
||||
} else if (config.mode != "time") {
|
||||
wordsBound = config.words;
|
||||
}
|
||||
} else {
|
||||
if (config.mode === "words" && config.words < wordsBound) {
|
||||
wordsBound = config.words;
|
||||
}
|
||||
if (config.mode == "custom" && customTextWordCount < wordsBound) {
|
||||
wordsBound = customTextWordCount;
|
||||
}
|
||||
}
|
||||
let wordset = language;
|
||||
if (config.mode == "custom") {
|
||||
wordset = customText;
|
||||
}
|
||||
for (let i = 0; i < wordsBound; i++) {
|
||||
randomWord = language[Math.floor(Math.random() * language.length)];
|
||||
randomWord = wordset[Math.floor(Math.random() * wordset.length)];
|
||||
previousWord = wordsList[i - 1];
|
||||
previousWord2 = wordsList[i - 2];
|
||||
while (
|
||||
randomWord == previousWord ||
|
||||
randomWord == previousWord2 ||
|
||||
(!config.punctuation && randomWord == "I") ||
|
||||
randomWord.indexOf(" ") > -1
|
||||
) {
|
||||
randomWord = language[Math.floor(Math.random() * language.length)];
|
||||
if (config.mode == "custom" && wordset.length < 3) {
|
||||
randomWord = wordset[Math.floor(Math.random() * wordset.length)];
|
||||
} else {
|
||||
while (
|
||||
randomWord == previousWord ||
|
||||
randomWord == previousWord2 ||
|
||||
(!config.punctuation && randomWord == "I") ||
|
||||
randomWord.indexOf(" ") > -1
|
||||
) {
|
||||
randomWord = wordset[Math.floor(Math.random() * wordset.length)];
|
||||
}
|
||||
}
|
||||
if (config.punctuation && config.mode != "custom") {
|
||||
randomWord = punctuateWord(previousWord, randomWord, i, wordsBound);
|
||||
|
@ -557,7 +580,7 @@ function updateActiveElement() {
|
|||
// document.querySelectorAll("#words .word")[currentWordIndex].classList.add("active");
|
||||
try {
|
||||
let activeWord = document.querySelectorAll("#words .word")[
|
||||
currentWordIndex
|
||||
currentWordElementIndex
|
||||
];
|
||||
activeWord.classList.add("active");
|
||||
activeWord.classList.remove("error");
|
||||
|
@ -568,17 +591,13 @@ function updateActiveElement() {
|
|||
} catch (e) {}
|
||||
}
|
||||
|
||||
function compareInput(wrdIndex, input, showError) {
|
||||
function compareInput(showError) {
|
||||
// let wrdAtIndex = $("#words .word")[wrdIndex];
|
||||
let input = currentInput;
|
||||
let wordAtIndex;
|
||||
let currentWord;
|
||||
if (wrdIndex === null) {
|
||||
wordAtIndex = document.querySelector("#words .word.active");
|
||||
currentWord = wordsList[currentWordIndex];
|
||||
} else {
|
||||
wordAtIndex = document.querySelectorAll("#words .word")[wrdIndex];
|
||||
currentWord = wordsList[wrdIndex];
|
||||
}
|
||||
wordAtIndex = document.querySelector("#words .word.active");
|
||||
currentWord = wordsList[currentWordIndex];
|
||||
// while (wordAtIndex.firstChild) {
|
||||
// wordAtIndex.removeChild(wordAtIndex.firstChild);
|
||||
// }
|
||||
|
@ -590,7 +609,13 @@ function compareInput(wrdIndex, input, showError) {
|
|||
// $(letterElems[i]).removeClass('incorrect').addClass('correct');
|
||||
} else {
|
||||
if (config.difficulty == "master") {
|
||||
if (!resultVisible) showResult(true);
|
||||
if (!resultVisible) {
|
||||
inputHistory.push(currentInput);
|
||||
document
|
||||
.querySelector("#words .word.active")
|
||||
.setAttribute("input", currentInput);
|
||||
showResult(true);
|
||||
}
|
||||
if (!afkDetected) {
|
||||
let testNow = Date.now();
|
||||
let testSeconds = roundTo2((testNow - testStart) / 1000);
|
||||
|
@ -623,9 +648,6 @@ function compareInput(wrdIndex, input, showError) {
|
|||
wordAtIndex.innerHTML = ret;
|
||||
|
||||
let lastindex = currentWordIndex;
|
||||
if (wrdIndex !== null) {
|
||||
lastindex = wrdIndex;
|
||||
}
|
||||
|
||||
if (
|
||||
(currentWord == input ||
|
||||
|
@ -661,7 +683,7 @@ function showTimer() {
|
|||
},
|
||||
250
|
||||
);
|
||||
} else if (config.timerStyle === "text" && config.mode === "time") {
|
||||
} else if (config.timerStyle === "text") {
|
||||
// let op = 0.25;
|
||||
// if (
|
||||
// $("#timerNumber").hasClass("timerSub") ||
|
||||
|
@ -783,9 +805,18 @@ function updateTimer() {
|
|||
config.mode === "quote"
|
||||
) {
|
||||
if (config.timerStyle === "bar") {
|
||||
let percent = Math.floor(
|
||||
((currentWordIndex + 1) / wordsList.length) * 100
|
||||
);
|
||||
let outof = wordsList.length;
|
||||
if (config.mode === "words") {
|
||||
outof = config.words;
|
||||
}
|
||||
if (config.mode === "custom") {
|
||||
if (customTextIsRandom) {
|
||||
outof = customTextWordCount;
|
||||
} else {
|
||||
outof = customText.length;
|
||||
}
|
||||
}
|
||||
let percent = Math.floor(((currentWordIndex + 1) / outof) * 100);
|
||||
$("#timer")
|
||||
.stop(true, true)
|
||||
.animate(
|
||||
|
@ -799,6 +830,13 @@ function updateTimer() {
|
|||
if (config.mode === "words") {
|
||||
outof = config.words;
|
||||
}
|
||||
if (config.mode === "custom") {
|
||||
if (customTextIsRandom) {
|
||||
outof = customTextWordCount;
|
||||
} else {
|
||||
outof = customText.length;
|
||||
}
|
||||
}
|
||||
$("#timerNumber").html(`${inputHistory.length}/${outof}`);
|
||||
// $("#timerNumber").html(config.time - time);
|
||||
}
|
||||
|
@ -1045,6 +1083,10 @@ function countChars() {
|
|||
let spaces = 0;
|
||||
let correctspaces = 0;
|
||||
for (let i = 0; i < inputHistory.length; i++) {
|
||||
if (inputHistory[i] === currentInput) {
|
||||
//last word that was not finished
|
||||
continue;
|
||||
}
|
||||
if (inputHistory[i] == wordsList[i]) {
|
||||
//the word is correct
|
||||
correctWordChars += wordsList[i].length;
|
||||
|
@ -1113,6 +1155,11 @@ function calculateStats() {
|
|||
let wpm = roundTo2(
|
||||
((chars.correctWordChars + chars.correctSpaces) * (60 / testSeconds)) / 5
|
||||
);
|
||||
console.log(
|
||||
`pre-spacegate ${roundTo2(
|
||||
((chars.correctWordChars + chars.spaces) * (60 / testSeconds)) / 5
|
||||
)} (current ${wpm})`
|
||||
);
|
||||
let wpmraw = roundTo2(
|
||||
((chars.allCorrectChars +
|
||||
chars.spaces +
|
||||
|
@ -1584,7 +1631,7 @@ function showResult(difficultyFailed = false) {
|
|||
testType += " " + config.words;
|
||||
}
|
||||
if (config.mode != "custom") {
|
||||
testType += "<br>" + config.language.replace("_", " ");
|
||||
testType += "<br>" + config.language.replace(/_/g, " ");
|
||||
}
|
||||
if (config.punctuation) {
|
||||
testType += "<br>punctuation";
|
||||
|
@ -1651,26 +1698,26 @@ function showResult(difficultyFailed = false) {
|
|||
|
||||
wpmOverTimeChart.update({ duration: 0 });
|
||||
swapElements($("#words"), $("#result"), 250, () => {
|
||||
if (config.blindMode) {
|
||||
$.each($("#words .word"), (i, word) => {
|
||||
let input = inputHistory[i];
|
||||
if (input == undefined) input = currentInput;
|
||||
compareInput(i, input, true);
|
||||
if (inputHistory[i] != wordsList[i]) {
|
||||
highlightBadWord(i, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let remove = false;
|
||||
$.each($("#words .word"), (i, obj) => {
|
||||
if (remove) {
|
||||
$(obj).remove();
|
||||
} else {
|
||||
$(obj).removeClass("hidden");
|
||||
if ($(obj).hasClass("active")) remove = true;
|
||||
}
|
||||
});
|
||||
$("#words").empty();
|
||||
// if (config.blindMode) {
|
||||
// $.each($("#words .word"), (i, word) => {
|
||||
// let input = inputHistory[i];
|
||||
// if (input == undefined) input = currentInput;
|
||||
// compareInput(i, input, true);
|
||||
// if (inputHistory[i] != wordsList[i]) {
|
||||
// highlightBadWord(i, true);
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// let remove = false;
|
||||
// $.each($("#words .word"), (i, obj) => {
|
||||
// if (remove) {
|
||||
// $(obj).remove();
|
||||
// } else {
|
||||
// $(obj).removeClass("hidden");
|
||||
// if ($(obj).hasClass("active")) remove = true;
|
||||
// }
|
||||
// });
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1685,6 +1732,7 @@ function restartTest(withSameWordset = false) {
|
|||
testActive = false;
|
||||
hideLiveWpm();
|
||||
hideTimer();
|
||||
$("#showWordHistoryButton").removeClass("loaded");
|
||||
keypressPerSecond = [];
|
||||
currentKeypressCount = 0;
|
||||
errorsPerSecond = [];
|
||||
|
@ -1714,7 +1762,7 @@ function restartTest(withSameWordset = false) {
|
|||
if (resultVisible) {
|
||||
if (config.randomTheme) {
|
||||
randomiseTheme();
|
||||
showNotification(config.theme.replace("_", " "), 1500);
|
||||
showNotification(config.theme.replace(/_/g, " "), 1500);
|
||||
}
|
||||
$("#words").stop(true, true).animate(
|
||||
{
|
||||
|
@ -1762,6 +1810,7 @@ function restartTest(withSameWordset = false) {
|
|||
sameWordset = true;
|
||||
testActive = false;
|
||||
currentWordIndex = 0;
|
||||
currentWordElementIndex = 0;
|
||||
accuracyStats = {
|
||||
correct: 0,
|
||||
incorrect: 0,
|
||||
|
@ -2124,6 +2173,13 @@ function toggleResultWordsDisplay() {
|
|||
//show
|
||||
$("#wordsTitle").css("opacity", 1).removeClass("hidden").slideDown(250);
|
||||
|
||||
if (!$("#showWordHistoryButton").hasClass("loaded")) {
|
||||
$("#words").html(
|
||||
`<div class="preloader"><i class="fas fa-fw fa-spin fa-circle-notch"></i></div>`
|
||||
);
|
||||
loadWordsHistory();
|
||||
}
|
||||
|
||||
let newHeight = $("#words")
|
||||
.removeClass("hidden")
|
||||
.css("height", "auto")
|
||||
|
@ -2167,6 +2223,48 @@ function toggleResultWordsDisplay() {
|
|||
}
|
||||
}
|
||||
|
||||
async function loadWordsHistory() {
|
||||
$("#words").empty();
|
||||
inputHistory.forEach((input, index) => {
|
||||
if (input === "") return;
|
||||
let wordEl = `<div class='word' input='${input}'>`;
|
||||
if (input !== wordsList[index]) {
|
||||
wordEl = `<div class='word error' input='${input}'>`;
|
||||
}
|
||||
|
||||
let loop;
|
||||
if (input.length > wordsList[index].length) {
|
||||
//input is longer - extra characters possible (loop over input)
|
||||
loop = input.length;
|
||||
} else {
|
||||
//input is shorter or equal (loop over word list)
|
||||
loop = wordsList[index].length;
|
||||
}
|
||||
|
||||
for (let c = 0; c < loop; c++) {
|
||||
// input.forEach((inputLetter, inputLetterIndex) => {
|
||||
if (wordsList[index][c] !== undefined) {
|
||||
if (input[c] === wordsList[index][c]) {
|
||||
wordEl +=
|
||||
'<letter class="correct">' + wordsList[index][c] + "</letter>";
|
||||
} else {
|
||||
if (input[c] === currentInput || input[c] === undefined) {
|
||||
wordEl += "<letter>" + wordsList[index][c] + "</letter>";
|
||||
} else {
|
||||
wordEl +=
|
||||
'<letter class="incorrect">' + wordsList[index][c] + "</letter>";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
wordEl += '<letter class="incorrect extra">' + input[c] + "</letter>";
|
||||
}
|
||||
}
|
||||
wordEl += "</div>";
|
||||
$("#words").append(wordEl);
|
||||
});
|
||||
$("#showWordHistoryButton").addClass("loaded");
|
||||
}
|
||||
|
||||
function flipTestColors(tf) {
|
||||
if (tf) {
|
||||
$("#words").addClass("flipped");
|
||||
|
@ -2265,6 +2363,29 @@ function updateTestModesNotice() {
|
|||
);
|
||||
}
|
||||
|
||||
if (config.confidenceMode === "on") {
|
||||
$(".pageTest #testModesNotice").append(
|
||||
`<div><i class="fas fa-backspace"></i>confidence</div>`
|
||||
);
|
||||
}
|
||||
if (config.confidenceMode === "max") {
|
||||
$(".pageTest #testModesNotice").append(
|
||||
`<div><i class="fas fa-backspace"></i>max confidence</div>`
|
||||
);
|
||||
}
|
||||
|
||||
if (config.stopOnError) {
|
||||
$(".pageTest #testModesNotice").append(
|
||||
`<div><i class="fas fa-hand-paper"></i>stop on error</div>`
|
||||
);
|
||||
}
|
||||
|
||||
if (config.layout !== "default") {
|
||||
$(".pageTest #testModesNotice").append(
|
||||
`<div><i class="fas fa-keyboard"></i>${config.layout}</div>`
|
||||
);
|
||||
}
|
||||
|
||||
tagsString = "";
|
||||
// $.each($('.pageSettings .section.tags .tagsList .tag'), (index, tag) => {
|
||||
// if($(tag).children('.active').attr('active') === 'true'){
|
||||
|
@ -2397,6 +2518,78 @@ function tagsEdit() {
|
|||
}
|
||||
}
|
||||
|
||||
function showCapsWarning() {
|
||||
if ($("#capsWarning").hasClass("hidden")) {
|
||||
$("#capsWarning").removeClass("hidden");
|
||||
}
|
||||
}
|
||||
|
||||
function hideCapsWarning() {
|
||||
if (!$("#capsWarning").hasClass("hidden")) {
|
||||
$("#capsWarning").addClass("hidden");
|
||||
}
|
||||
}
|
||||
|
||||
function showCustomTextPopup() {
|
||||
if ($("#customTextPopupWrapper").hasClass("hidden")) {
|
||||
$("#customTextPopupWrapper")
|
||||
.stop(true, true)
|
||||
.css("opacity", 0)
|
||||
.removeClass("hidden")
|
||||
.animate({ opacity: 1 }, 100, (e) => {
|
||||
$("#customTextPopup textarea").val(customText.join(" "));
|
||||
$("#customTextPopup .wordcount input").val(customTextWordCount);
|
||||
$("#customTextPopup textarea").focus();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function hideCustomTextPopup() {
|
||||
if (!$("#customTextPopupWrapper").hasClass("hidden")) {
|
||||
$("#customTextPopupWrapper")
|
||||
.stop(true, true)
|
||||
.css("opacity", 1)
|
||||
.animate(
|
||||
{
|
||||
opacity: 0,
|
||||
},
|
||||
100,
|
||||
(e) => {
|
||||
$("#customTextPopupWrapper").addClass("hidden");
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$("#customTextPopupWrapper").click((e) => {
|
||||
if ($(e.target).attr("id") === "customTextPopupWrapper") {
|
||||
hideCustomTextPopup();
|
||||
}
|
||||
});
|
||||
|
||||
$("#customTextPopup .button").click((e) => {
|
||||
let text = $("#customTextPopup textarea").val();
|
||||
text = text.trim();
|
||||
text = text.replace(/[\n\r\t ]/gm, " ");
|
||||
text = text.replace(/ +/gm, " ");
|
||||
text = text.split(" ");
|
||||
if (text.length >= 10000) {
|
||||
showNotification("Custom text cannot be longer than 10000 words.", 4000);
|
||||
changeMode("time");
|
||||
text = "The quick brown fox jumped over the lazy dog".split(" ");
|
||||
} else {
|
||||
customText = text;
|
||||
customTextIsRandom = $("#customTextPopup .check input").prop("checked");
|
||||
// if (customTextIsRandom && customText.length < 3) {
|
||||
// showNotification("Random custom text requires at least 3 words", 4000);
|
||||
// customTextIsRandom = false;
|
||||
// }
|
||||
customTextWordCount = $("#customTextPopup .wordcount input").val();
|
||||
restartTest();
|
||||
}
|
||||
hideCustomTextPopup();
|
||||
});
|
||||
|
||||
$(document).on("click", "#top .logo", (e) => {
|
||||
changePage("test");
|
||||
});
|
||||
|
@ -2447,8 +2640,9 @@ $(document).on("click", "#top .config .time .text-button", (e) => {
|
|||
});
|
||||
|
||||
$(document).on("click", "#top .config .customText .text-button", (e) => {
|
||||
changeCustomText();
|
||||
restartTest();
|
||||
// changeCustomText();
|
||||
// restartTest();
|
||||
showCustomTextPopup();
|
||||
});
|
||||
|
||||
$(document).on("click", "#top .config .punctuationMode .text-button", (e) => {
|
||||
|
@ -2653,6 +2847,7 @@ $(document).keypress(function (event) {
|
|||
clearIntervals();
|
||||
hideCaret();
|
||||
testActive = false;
|
||||
inputHistory.push(currentInput);
|
||||
showResult();
|
||||
}
|
||||
}
|
||||
|
@ -2677,12 +2872,25 @@ $(document).keypress(function (event) {
|
|||
}
|
||||
currentKeypressCount++;
|
||||
|
||||
if (config.stopOnError && !thisCharCorrect) return;
|
||||
if (config.stopOnError && !thisCharCorrect) {
|
||||
if (config.difficulty == "master") {
|
||||
showResult(true);
|
||||
if (!afkDetected) {
|
||||
let testNow = Date.now();
|
||||
let testSeconds = roundTo2((testNow - testStart) / 1000);
|
||||
incompleteTestSeconds += testSeconds;
|
||||
restartCount++;
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
currentInput += event["key"];
|
||||
setFocus(true);
|
||||
activeWordTopBeforeJump = activeWordTop;
|
||||
compareInput(null, currentInput, !config.blindMode);
|
||||
compareInput(!config.blindMode);
|
||||
// let newActiveTop = $("#words .word.active").position().top;
|
||||
|
||||
// console.time("offcheck1");
|
||||
|
@ -2702,6 +2910,15 @@ $(document).keypress(function (event) {
|
|||
|
||||
$(document).keydown((event) => {
|
||||
keypressStats.duration.current = performance.now();
|
||||
if ($("#wordsInput").is(":focus")) {
|
||||
try {
|
||||
if (event.originalEvent.getModifierState("CapsLock")) {
|
||||
showCapsWarning();
|
||||
} else {
|
||||
hideCapsWarning();
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
});
|
||||
|
||||
$(document).keyup((event) => {
|
||||
|
@ -2755,7 +2972,8 @@ $(document).keydown((event) => {
|
|||
) {
|
||||
return;
|
||||
} else {
|
||||
if (config.maxConfidence) return;
|
||||
if (config.confidenceMode === "on" || config.confidenceMode === "max")
|
||||
return;
|
||||
if (event["ctrlKey"] || event["altKey"]) {
|
||||
currentInput = "";
|
||||
inputHistory.pop();
|
||||
|
@ -2763,19 +2981,18 @@ $(document).keydown((event) => {
|
|||
currentInput = inputHistory.pop();
|
||||
}
|
||||
currentWordIndex--;
|
||||
currentWordElementIndex--;
|
||||
updateActiveElement();
|
||||
compareInput(null, currentInput, !config.blindMode);
|
||||
compareInput(!config.blindMode);
|
||||
}
|
||||
} else {
|
||||
// if ($($(".word")[currentWordIndex - 1]).hasClass("hidden")) {
|
||||
// return;
|
||||
// }
|
||||
if (config.confidenceMode === "max") return;
|
||||
if (event["ctrlKey"]) {
|
||||
currentInput = "";
|
||||
} else {
|
||||
currentInput = currentInput.substring(0, currentInput.length - 1);
|
||||
}
|
||||
compareInput(null, currentInput, !config.blindMode);
|
||||
compareInput(!config.blindMode);
|
||||
}
|
||||
// currentKeypressCount++;
|
||||
if (config.keymapMode === "react") {
|
||||
|
@ -2796,13 +3013,15 @@ $(document).keydown((event) => {
|
|||
// let currentTop = Math.floor($($("#words .word")[currentWordIndex]).position().top);
|
||||
// let nextTop = Math.floor($($("#words .word")[currentWordIndex + 1]).position().top);
|
||||
let currentTop = Math.floor(
|
||||
document.querySelectorAll("#words .word")[currentWordIndex].offsetTop
|
||||
document.querySelectorAll("#words .word")[currentWordElementIndex]
|
||||
.offsetTop
|
||||
);
|
||||
let nextTop;
|
||||
try {
|
||||
nextTop = Math.floor(
|
||||
document.querySelectorAll("#words .word")[currentWordIndex + 1]
|
||||
.offsetTop
|
||||
document.querySelectorAll("#words .word")[
|
||||
currentWordElementIndex + 1
|
||||
].offsetTop
|
||||
);
|
||||
} catch (e) {
|
||||
nextTop = 0;
|
||||
|
@ -2819,7 +3038,7 @@ $(document).keydown((event) => {
|
|||
|
||||
let toHide = [];
|
||||
let wordElements = $("#words .word");
|
||||
for (let i = 0; i < currentWordIndex + 1; i++) {
|
||||
for (let i = 0; i < currentWordElementIndex + 1; i++) {
|
||||
if ($(wordElements[i]).hasClass("hidden")) continue;
|
||||
// let forWordTop = Math.floor($(wordElements[i]).position().top);
|
||||
let forWordTop = Math.floor(wordElements[i].offsetTop);
|
||||
|
@ -2828,28 +3047,44 @@ $(document).keydown((event) => {
|
|||
toHide.push($($("#words .word")[i]));
|
||||
}
|
||||
}
|
||||
toHide.forEach((el) => el.addClass("hidden"));
|
||||
toHide.forEach((el) => el.remove());
|
||||
currentWordElementIndex -= toHide.length;
|
||||
}
|
||||
currentTestLine++;
|
||||
}
|
||||
}
|
||||
// }
|
||||
if (config.blindMode) $("#words .word.active letter").addClass("correct");
|
||||
document
|
||||
.querySelector("#words .word.active")
|
||||
.setAttribute("input", currentInput);
|
||||
// document
|
||||
// .querySelector("#words .word.active")
|
||||
// .setAttribute("input", currentInput);
|
||||
if (currentWord == currentInput) {
|
||||
inputHistory.push(currentInput);
|
||||
currentInput = "";
|
||||
currentWordIndex++;
|
||||
currentWordElementIndex++;
|
||||
updateActiveElement();
|
||||
updateCaretPosition();
|
||||
currentKeypressCount++;
|
||||
} else if (!config.stopOnError) {
|
||||
} else {
|
||||
if (config.stopOnError) {
|
||||
if (config.difficulty == "expert" || config.difficulty == "master") {
|
||||
showResult(true);
|
||||
if (!afkDetected) {
|
||||
let testNow = Date.now();
|
||||
let testSeconds = roundTo2((testNow - testStart) / 1000);
|
||||
incompleteTestSeconds += testSeconds;
|
||||
restartCount++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
inputHistory.push(currentInput);
|
||||
highlightBadWord(currentWordIndex, !config.blindMode);
|
||||
highlightBadWord(currentWordElementIndex, !config.blindMode);
|
||||
currentInput = "";
|
||||
currentWordIndex++;
|
||||
currentWordElementIndex++;
|
||||
if (currentWordIndex == wordsList.length) {
|
||||
showResult();
|
||||
return;
|
||||
|
|
|
@ -4,7 +4,7 @@ function updateSettingsPage() {
|
|||
themesEl.append(
|
||||
`<div class="theme button" theme='${theme.name}' style="color:${
|
||||
theme.textColor
|
||||
};background:${theme.bgColor}">${theme.name.replace("_", " ")}</div>`
|
||||
};background:${theme.bgColor}">${theme.name.replace(/_/g, " ")}</div>`
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -60,7 +60,6 @@ function updateSettingsPage() {
|
|||
setSettingsButton("flipTestColors", config.flipTestColors);
|
||||
setSettingsButton("discordDot", config.showDiscordDot);
|
||||
setSettingsButton("colorfulMode", config.colorfulMode);
|
||||
setSettingsButton("maxConfidence", config.maxConfidence);
|
||||
setSettingsButton("randomTheme", config.randomTheme);
|
||||
setSettingsButton("stopOnError", config.stopOnError);
|
||||
setSettingsButton("showAllLines", config.showAllLines);
|
||||
|
@ -76,6 +75,7 @@ function updateSettingsPage() {
|
|||
setActiveTimerOpacityButton();
|
||||
setActiveThemeTab();
|
||||
setCustomThemeInputs();
|
||||
setActiveConfidenceModeButton();
|
||||
|
||||
setActiveKeymapModeButton();
|
||||
setActiveKeymapLayoutButton();
|
||||
|
@ -430,6 +430,20 @@ function updateDiscordSettingsSection() {
|
|||
}
|
||||
}
|
||||
|
||||
function setActiveConfidenceModeButton() {
|
||||
let cm = config.confidenceMode;
|
||||
$(".pageSettings .section.confidenceMode .buttons .button").removeClass(
|
||||
"active"
|
||||
);
|
||||
$(
|
||||
`.pageSettings .section.confidenceMode .buttons .button[confidenceMode='${cm}']`
|
||||
).addClass("active");
|
||||
if (cm !== "off") {
|
||||
config.freedomMode = false;
|
||||
setSettingsButton("freedomMode", config.freedomMode);
|
||||
}
|
||||
}
|
||||
|
||||
//smooth caret
|
||||
$(".pageSettings .section.smoothCaret .buttons .button.on").click((e) => {
|
||||
setSmoothCaret(true);
|
||||
|
@ -506,31 +520,42 @@ $(".pageSettings .section.freedomMode .buttons .button.on").click((e) => {
|
|||
saveConfigToCookie();
|
||||
// showNotification('Freedom mode on', 1000);
|
||||
setSettingsButton("freedomMode", config.freedomMode);
|
||||
setSettingsButton("maxConfidence", config.maxConfidence);
|
||||
config.confidenceMode = "off";
|
||||
setActiveConfidenceModeButton();
|
||||
});
|
||||
$(".pageSettings .section.freedomMode .buttons .button.off").click((e) => {
|
||||
setFreedomMode(false);
|
||||
saveConfigToCookie();
|
||||
// showNotification('Freedom mode off', 1000);
|
||||
setSettingsButton("freedomMode", config.freedomMode);
|
||||
setSettingsButton("maxConfidence", config.maxConfidence);
|
||||
});
|
||||
|
||||
//max confidence
|
||||
$(".pageSettings .section.maxConfidence .buttons .button.on").click((e) => {
|
||||
setMaxConfidence(true);
|
||||
saveConfigToCookie();
|
||||
// showNotification('Max confidence on', 1000);
|
||||
setSettingsButton("freedomMode", config.freedomMode);
|
||||
setSettingsButton("maxConfidence", config.maxConfidence);
|
||||
});
|
||||
$(".pageSettings .section.maxConfidence .buttons .button.off").click((e) => {
|
||||
setMaxConfidence(false);
|
||||
saveConfigToCookie();
|
||||
// showNotification('Max confidence off', 1000);
|
||||
setSettingsButton("freedomMode", config.freedomMode);
|
||||
setSettingsButton("maxConfidence", config.maxConfidence);
|
||||
});
|
||||
// //max confidence
|
||||
// $(".pageSettings .section.maxConfidence .buttons .button.on").click((e) => {
|
||||
// setMaxConfidence(true);
|
||||
// saveConfigToCookie();
|
||||
// // showNotification('Max confidence on', 1000);
|
||||
// setSettingsButton("freedomMode", config.freedomMode);
|
||||
// setSettingsButton("maxConfidence", config.maxConfidence);
|
||||
// });
|
||||
// $(".pageSettings .section.maxConfidence .buttons .button.off").click((e) => {
|
||||
// setMaxConfidence(false);
|
||||
// saveConfigToCookie();
|
||||
// // showNotification('Max confidence off', 1000);
|
||||
// setSettingsButton("freedomMode", config.freedomMode);
|
||||
// setSettingsButton("maxConfidence", config.maxConfidence);
|
||||
// });
|
||||
|
||||
//confidence
|
||||
$(document).on(
|
||||
"click",
|
||||
".pageSettings .section.confidenceMode .button",
|
||||
(e) => {
|
||||
let confidence = $(e.currentTarget).attr("confidenceMode");
|
||||
setConfidenceMode(confidence);
|
||||
setActiveConfidenceModeButton();
|
||||
}
|
||||
);
|
||||
|
||||
//keytips
|
||||
$(".pageSettings .section.keyTips .buttons .button.on").click((e) => {
|
||||
|
@ -811,13 +836,24 @@ $(".tab").click((e) => {
|
|||
if ($target.attr("tab") == "preset") {
|
||||
setCustomTheme(false);
|
||||
applyCustomThemeColors();
|
||||
$('[tabContent="custom"]').removeClass("reveal");
|
||||
$('[tabContent="preset"]').addClass("reveal");
|
||||
// $('[tabContent="custom"]').removeClass("reveal");
|
||||
// $('[tabContent="preset"]').addClass("reveal");
|
||||
swapElements(
|
||||
$('.pageSettings [tabContent="custom"]'),
|
||||
$('.pageSettings [tabContent="preset"]'),
|
||||
250
|
||||
);
|
||||
} else {
|
||||
setCustomTheme(true);
|
||||
applyCustomThemeColors();
|
||||
$('[tabContent="preset"]').removeClass("reveal");
|
||||
$('[tabContent="custom"]').addClass("reveal");
|
||||
swapElements(
|
||||
$('.pageSettings [tabContent="preset"]'),
|
||||
$('.pageSettings [tabContent="custom"]'),
|
||||
250
|
||||
);
|
||||
|
||||
// $('[tabContent="preset"]').removeClass("reveal");
|
||||
// $('[tabContent="custom"]').addClass("reveal");
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ let defaultConfig = {
|
|||
flipTestColors: false,
|
||||
layout: "default",
|
||||
showDiscordDot: true,
|
||||
maxConfidence: false,
|
||||
confidenceMode: "off",
|
||||
timerStyle: "bar",
|
||||
colorfulMode: true,
|
||||
randomTheme: false,
|
||||
|
@ -134,7 +134,7 @@ function applyConfig(configObj) {
|
|||
setFlipTestColors(configObj.flipTestColors, true);
|
||||
setDiscordDot(configObj.hideDiscordDot, true);
|
||||
setColorfulMode(configObj.colorfulMode, true);
|
||||
setMaxConfidence(configObj.maxConfidence, true);
|
||||
setConfidenceMode(configObj.confidenceMode, true);
|
||||
setTimerStyle(configObj.timerStyle, true);
|
||||
setTimerColor(configObj.timerColor, true);
|
||||
setTimerOpacity(configObj.timerOpacity, true);
|
||||
|
@ -243,6 +243,7 @@ function toggleStopOnError() {
|
|||
soe = false;
|
||||
}
|
||||
config.stopOnError = soe;
|
||||
updateTestModesNotice();
|
||||
saveConfigToCookie();
|
||||
}
|
||||
|
||||
|
@ -251,6 +252,7 @@ function setStopOnError(soe, nosave) {
|
|||
soe = false;
|
||||
}
|
||||
config.stopOnError = soe;
|
||||
updateTestModesNotice();
|
||||
if (!nosave) saveConfigToCookie();
|
||||
}
|
||||
|
||||
|
@ -495,51 +497,52 @@ function setFreedomMode(freedom, nosave) {
|
|||
freedom = false;
|
||||
}
|
||||
config.freedomMode = freedom;
|
||||
if (config.freedomMode && config.maxConfidence) {
|
||||
config.maxConfidence = false;
|
||||
if (config.freedomMode && config.confidenceMode !== "off") {
|
||||
config.confidenceMode = "off";
|
||||
}
|
||||
if (!nosave) saveConfigToCookie();
|
||||
}
|
||||
|
||||
function toggleFreedomMode() {
|
||||
config.freedomMode = !config.freedomMode;
|
||||
if (config.freedomMode && config.maxConfidence) {
|
||||
config.maxConfidence = false;
|
||||
if (config.freedomMode && config.confidenceMode !== "off") {
|
||||
config.confidenceMode = false;
|
||||
}
|
||||
saveConfigToCookie();
|
||||
}
|
||||
|
||||
//max confidence
|
||||
function toggleMaxConfidence() {
|
||||
// console.log(config.maxConfidence)
|
||||
mc = !config.maxConfidence;
|
||||
if (mc == undefined) {
|
||||
mc = false;
|
||||
function setConfidenceMode(cm, nosave) {
|
||||
if (cm == undefined) {
|
||||
cm = "off";
|
||||
}
|
||||
config.maxConfidence = mc;
|
||||
if (config.freedomMode && config.maxConfidence) {
|
||||
config.freedomMode = false;
|
||||
}
|
||||
// console.log(config.maxConfidence);
|
||||
saveConfigToCookie();
|
||||
}
|
||||
|
||||
function setMaxConfidence(mc, nosave) {
|
||||
if (mc == undefined) {
|
||||
mc = false;
|
||||
}
|
||||
config.maxConfidence = mc;
|
||||
if (config.freedomMode && config.maxConfidence) {
|
||||
config.confidenceMode = cm;
|
||||
if (config.freedomMode && config.confidenceMode !== "off") {
|
||||
config.freedomMode = false;
|
||||
}
|
||||
updateTestModesNotice();
|
||||
if (!nosave) saveConfigToCookie();
|
||||
}
|
||||
|
||||
function previewTheme(name) {
|
||||
if (
|
||||
(testActive || resultVisible) &&
|
||||
(config.theme === "nausea" || config.theme === "round_round_baby")
|
||||
)
|
||||
return;
|
||||
if (resultVisible && (name === "nausea" || name === "round_round_baby"))
|
||||
return;
|
||||
$("#currentTheme").attr("href", `themes/${name}.css`);
|
||||
}
|
||||
|
||||
function setTheme(name, nosave) {
|
||||
if (
|
||||
(testActive || resultVisible) &&
|
||||
(config.theme === "nausea" || config.theme === "round_round_baby")
|
||||
) {
|
||||
return;
|
||||
}
|
||||
if (resultVisible && (name === "nausea" || name === "round_round_baby"))
|
||||
return;
|
||||
config.theme = name;
|
||||
$(".keymap-key").attr("style", "");
|
||||
$("#currentTheme").attr("href", `themes/${name}.css`);
|
||||
|
@ -558,7 +561,7 @@ function setTheme(name, nosave) {
|
|||
|
||||
function randomiseTheme() {
|
||||
var randomList = themesList.filter(function (theme) {
|
||||
return theme.name != "nausea";
|
||||
return theme.name != "nausea" && theme.name != "round_round_baby";
|
||||
});
|
||||
let randomtheme = randomList[Math.floor(Math.random() * randomList.length)];
|
||||
setTheme(randomtheme.name, true);
|
||||
|
@ -671,6 +674,7 @@ function changeLayout(layout, nosave) {
|
|||
layout = "qwerty";
|
||||
}
|
||||
config.layout = layout;
|
||||
updateTestModesNotice();
|
||||
if (!nosave) saveConfigToCookie();
|
||||
}
|
||||
|
||||
|
|
|
@ -4346,4 +4346,207 @@ const words = {
|
|||
"problema",
|
||||
"preoccuparsi",
|
||||
],
|
||||
norwegian: [
|
||||
"i",
|
||||
"og",
|
||||
"det",
|
||||
"om",
|
||||
"er",
|
||||
"til",
|
||||
"en",
|
||||
"av",
|
||||
"på",
|
||||
"for",
|
||||
"at",
|
||||
"å",
|
||||
"med",
|
||||
"de",
|
||||
"har",
|
||||
"den",
|
||||
"ikke",
|
||||
"et",
|
||||
"om",
|
||||
"fra",
|
||||
"var",
|
||||
"han",
|
||||
"men",
|
||||
"seg",
|
||||
"vil",
|
||||
"jeg",
|
||||
"kan",
|
||||
"ble",
|
||||
"vil",
|
||||
"skal",
|
||||
"sier",
|
||||
"etter",
|
||||
"så",
|
||||
"år",
|
||||
"også",
|
||||
"hun",
|
||||
"dette",
|
||||
"ved",
|
||||
"da",
|
||||
"blir",
|
||||
"nå",
|
||||
"ut",
|
||||
"være",
|
||||
"hadde",
|
||||
"over",
|
||||
"mot",
|
||||
"eller",
|
||||
"to",
|
||||
"må",
|
||||
"går",
|
||||
"få",
|
||||
"andre",
|
||||
"opp",
|
||||
"sin",
|
||||
"når",
|
||||
"du",
|
||||
"bare",
|
||||
"alle",
|
||||
"ha",
|
||||
"enn",
|
||||
"mer",
|
||||
"denne",
|
||||
"selv",
|
||||
"noe",
|
||||
"mange",
|
||||
"inn",
|
||||
"bli",
|
||||
"noen",
|
||||
"vært",
|
||||
"får",
|
||||
"før",
|
||||
"der",
|
||||
"man",
|
||||
"kroner",
|
||||
"nye",
|
||||
"dag",
|
||||
"ting",
|
||||
"flere",
|
||||
"fikk",
|
||||
"første",
|
||||
"under",
|
||||
"slik",
|
||||
"siden",
|
||||
"mye",
|
||||
"dårlig",
|
||||
"kommer",
|
||||
"både",
|
||||
"kunne",
|
||||
"meg",
|
||||
"mellom",
|
||||
"hva",
|
||||
"tre",
|
||||
"her",
|
||||
"store",
|
||||
"mener",
|
||||
"ingen",
|
||||
"dem",
|
||||
"oss",
|
||||
"hele",
|
||||
"sine",
|
||||
"siste",
|
||||
"gang",
|
||||
"skulle",
|
||||
"hans",
|
||||
"ta",
|
||||
"helt",
|
||||
"godt",
|
||||
"sammen",
|
||||
"sa",
|
||||
"kom",
|
||||
"håper",
|
||||
"hvor",
|
||||
"nok",
|
||||
"hjemme",
|
||||
"alt",
|
||||
"blant",
|
||||
"tid",
|
||||
"sitt",
|
||||
"ville",
|
||||
"uten",
|
||||
"blitt",
|
||||
"igjen",
|
||||
"tidligere",
|
||||
"fått",
|
||||
"rundt",
|
||||
"ny",
|
||||
"samme",
|
||||
"mens",
|
||||
"annet",
|
||||
"gjennom",
|
||||
"disse",
|
||||
"litt",
|
||||
"stor",
|
||||
"står",
|
||||
"gjør",
|
||||
"gå",
|
||||
"ser",
|
||||
"gjøre",
|
||||
"gikk",
|
||||
"folk",
|
||||
"ned",
|
||||
"ham",
|
||||
"se",
|
||||
"hvis",
|
||||
"derfor",
|
||||
"gamle",
|
||||
"fire",
|
||||
"fordi",
|
||||
"mest",
|
||||
"god",
|
||||
"tar",
|
||||
"tilbake",
|
||||
"gir",
|
||||
"barn",
|
||||
"like",
|
||||
"neste",
|
||||
"gi",
|
||||
"kanskje",
|
||||
"langt",
|
||||
"tatt",
|
||||
"del",
|
||||
"bedre",
|
||||
"komme",
|
||||
"saken",
|
||||
"ønsker",
|
||||
"tror",
|
||||
"viser",
|
||||
"først",
|
||||
"måtte",
|
||||
"aldri",
|
||||
"side",
|
||||
"ligger",
|
||||
"si",
|
||||
"min",
|
||||
"hvordan",
|
||||
"hos",
|
||||
"tok",
|
||||
"bør",
|
||||
"beste",
|
||||
"vår",
|
||||
"grunn",
|
||||
"hver",
|
||||
"sett",
|
||||
"vel",
|
||||
"gjort",
|
||||
"land",
|
||||
"allerede",
|
||||
"frem",
|
||||
"heller",
|
||||
"gode",
|
||||
"vet",
|
||||
"jo",
|
||||
"tiden",
|
||||
"begge",
|
||||
"finnes",
|
||||
"foto",
|
||||
"fram",
|
||||
"plass",
|
||||
"mennesker",
|
||||
"gjorde",
|
||||
"mine",
|
||||
]
|
||||
};
|
||||
|
|
11
public/themes/deku.css
Normal file
11
public/themes/deku.css
Normal file
|
@ -0,0 +1,11 @@
|
|||
:root {
|
||||
--bg-color: #058B8C;
|
||||
--main-color: #b63530;
|
||||
--caret-color: #b63530;
|
||||
--sub-color: #255458;
|
||||
--text-color: #F7F2EA;
|
||||
--error-color: #b63530;
|
||||
--error-extra-color: #530e0e;
|
||||
--colorful-error-color: #ddca1f;
|
||||
--colorful-error-extra-color: #8f8610;
|
||||
}
|
15
public/themes/ishtar.css
Normal file
15
public/themes/ishtar.css
Normal file
|
@ -0,0 +1,15 @@
|
|||
:root {
|
||||
--bg-color: #202020;
|
||||
--main-color: #91170c;
|
||||
--caret-color: #c58940;
|
||||
--sub-color: #847869;
|
||||
--text-color: #fae1c3;
|
||||
--error-color: #bb1e10;
|
||||
--error-extra-color: #791717;
|
||||
--colorful-error-color: #c5da33;
|
||||
--colorful-error-extra-color: #849224;
|
||||
}
|
||||
|
||||
#top .logo .bottom {
|
||||
color: #fae1c3;
|
||||
}
|
|
@ -43,6 +43,11 @@
|
|||
"bgColor": "#323437",
|
||||
"textColor": "#e2b714"
|
||||
},
|
||||
{
|
||||
"name": "round_round_baby",
|
||||
"bgColor": "#323437",
|
||||
"textColor": "#e2b714"
|
||||
},
|
||||
{
|
||||
"name": "bushido",
|
||||
"bgColor": "#414755",
|
||||
|
@ -302,5 +307,25 @@
|
|||
"name": "watermelon",
|
||||
"bgColor": "#1F4437",
|
||||
"textColor": "#B74B53"
|
||||
},
|
||||
{
|
||||
"name": "menthol",
|
||||
"bgColor": "#00c18c",
|
||||
"textColor": "#ffffff"
|
||||
},
|
||||
{
|
||||
"name": "ishtar",
|
||||
"bgColor": "#fae1c3",
|
||||
"textColor": "#bb1e10"
|
||||
},
|
||||
{
|
||||
"name": "mashu",
|
||||
"bgColor": "#2b2b2c",
|
||||
"textColor": "#76689a"
|
||||
},
|
||||
{
|
||||
"name": "deku",
|
||||
"bgColor": "#058B8C",
|
||||
"textColor": "#F7F2EA"
|
||||
}
|
||||
]
|
11
public/themes/mashu.css
Normal file
11
public/themes/mashu.css
Normal file
|
@ -0,0 +1,11 @@
|
|||
:root {
|
||||
--bg-color: #2b2b2c;
|
||||
--main-color: #76689a;
|
||||
--caret-color: #76689a;
|
||||
--sub-color: #d8a0a6;
|
||||
--text-color: #d8a0a6;
|
||||
--error-color: #d8a0a6;
|
||||
--error-extra-color: #e9e0d2;
|
||||
--colorful-error-color: #e9e0d2;
|
||||
--colorful-error-extra-color: #e9e0d2;
|
||||
}
|
11
public/themes/menthol.css
Normal file
11
public/themes/menthol.css
Normal file
|
@ -0,0 +1,11 @@
|
|||
:root {
|
||||
--bg-color: #00c18c;
|
||||
--main-color: #ffffff;
|
||||
--caret-color: #99fdd8;
|
||||
--sub-color: #186544;
|
||||
--text-color: #ffffff;
|
||||
--error-color: #e03c3c;
|
||||
--error-extra-color: #b12525;
|
||||
--colorful-error-color: #e03c3c;
|
||||
--colorful-error-extra-color: #b12525;
|
||||
}
|
35
public/themes/round_round_baby.css
Normal file
35
public/themes/round_round_baby.css
Normal file
|
@ -0,0 +1,35 @@
|
|||
:root {
|
||||
--bg-color: #323437;
|
||||
--main-color: #e2b714;
|
||||
--caret-color: #e2b714;
|
||||
--sub-color: #646669;
|
||||
--text-color: #d1d0c5;
|
||||
--error-color: #ca4754;
|
||||
--error-extra-color: #7e2a33;
|
||||
--colorful-error-color: #ca4754;
|
||||
--colorful-error-extra-color: #7e2a33;
|
||||
}
|
||||
|
||||
|
||||
@keyframes woah {
|
||||
0% {
|
||||
transform: rotateZ(0deg);
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: rotateZ(180deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotateZ(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#middle {
|
||||
animation: woah 5s infinite linear;
|
||||
}
|
||||
|
||||
body {
|
||||
overflow: hidden;
|
||||
}
|
Loading…
Add table
Reference in a new issue