diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 000000000..29ee12dca --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +layouts.js \ No newline at end of file diff --git a/public/css/style.scss b/public/css/style.scss index 50c690d26..e7dbe343d 100644 --- a/public/css/style.scss +++ b/public/css/style.scss @@ -1,7 +1,7 @@ @import url("https://fonts.googleapis.com/css?family=Roboto+Mono&display=swap"); :root { - --roundness: .25rem; + --roundness: 0.25rem; } ::placeholder { @@ -23,9 +23,9 @@ input { outline: none; border: none; border-radius: var(--roundness); - background: rgba(0, 0, 0, .1); + background: rgba(0, 0, 0, 0.1); color: var(--text-color); - padding: .5rem; + padding: 0.5rem; font-size: 1rem; line-height: 1rem; font-family: "Roboto Mono"; @@ -52,7 +52,7 @@ input[type="color"]::-webkit-color-swatch { .colorPicker { text-align: center; will-change: transform; - transition: transform .2s ease-in-out; + transition: transform 0.2s ease-in-out; overflow: hidden; border-radius: var(--roundness); @@ -105,7 +105,7 @@ html { /* Handle */ ::-webkit-scrollbar-thumb { background: var(--sub-color); - transition: .25s; + transition: 0.25s; border-radius: 2px !important; } @@ -127,7 +127,7 @@ a:hover { position: fixed; background: var(--main-color); color: var(--bg-color); - padding: .5rem 1rem; + padding: 0.5rem 1rem; border-radius: var(--roundness); left: 50%; z-index: 9999; @@ -186,7 +186,8 @@ a:hover { display: grid; gap: 2rem; grid-template-rows: 3rem auto; - grid-template-areas: "title buttons" + grid-template-areas: + "title buttons" "tables tables"; grid-template-columns: 1fr 1fr; @@ -199,7 +200,7 @@ a:hover { .title { font-size: 2rem; line-height: 2rem; - margin-bottom: .5rem; + margin-bottom: 0.5rem; } .tables { @@ -208,7 +209,7 @@ a:hover { gap: 1rem; grid-template-columns: 1fr 1fr; margin-bottom: 2rem; - font-size: .8rem; + font-size: 0.8rem; .titleAndTable { display: grid; @@ -243,7 +244,7 @@ a:hover { } td { - padding: .25rem .5rem; + padding: 0.25rem 0.5rem; &.me { color: var(--main-color); @@ -253,7 +254,7 @@ a:hover { thead { color: var(--sub-color); - font-size: .75rem; + font-size: 0.75rem; td { background: var(--bg-color); @@ -267,7 +268,7 @@ a:hover { color: var(--text-color); tr:nth-child(odd) td { - background: rgba(0, 0, 0, .1); + background: rgba(0, 0, 0, 0.1); } } @@ -302,7 +303,6 @@ a:hover { } } - #tagsWrapper { width: 100%; height: 100%; @@ -380,7 +380,6 @@ a:hover { } } - #versionHistoryWrapper { width: 100%; height: 100%; @@ -416,7 +415,8 @@ a:hover { .release { display: grid; - grid-template-areas: "title date" + grid-template-areas: + "title date" "body body"; .title { @@ -531,7 +531,7 @@ a:hover { color: var(--sub-color); .fas { - margin-right: .5rem; + margin-right: 0.5rem; } &:last-child { @@ -576,7 +576,7 @@ a:hover { background: black; /* background: #0f0f0f; */ /* background: red; */ - // transition: 1s linear; + // transition: 1s linear; z-index: -1; } @@ -662,15 +662,14 @@ a:hover { } &.block { - width: .7em; + width: 0.7em; margin-left: 0.25em; border-radius: 0; z-index: -1; } &.outline { - @extend #caret, - .block; + @extend #caret, .block; background: transparent; border: 1px solid var(--caret-color); } @@ -708,7 +707,6 @@ a:hover { } @keyframes caretFlash { - 0%, 100% { opacity: 0; @@ -725,7 +723,7 @@ a:hover { color: var(--sub-color); display: grid; grid-auto-flow: column; - gap: .5rem; + gap: 0.5rem; // margin-bottom: -0.4rem; width: fit-content; width: -moz-fit-content; @@ -736,15 +734,15 @@ a:hover { position: relative; &::after { - transition: .25s; - width: .5rem; - height: .5rem; + transition: 0.25s; + width: 0.5rem; + height: 0.5rem; content: ""; position: absolute; background: var(--main-color); border-radius: 1rem; - top: .25rem; - right: .25rem; + top: 0.25rem; + right: 0.25rem; border: 2px solid var(--bg-color); } @@ -766,10 +764,10 @@ a:hover { } .text { - font-size: .65rem; - line-height: .65rem; + font-size: 0.65rem; + line-height: 0.65rem; align-self: center; - margin-left: .25rem; + margin-left: 0.25rem; } &:hover { @@ -798,8 +796,7 @@ a:hover { } #top { - grid-template-areas: - "logo menu config"; + grid-template-areas: "logo menu config"; line-height: 2.3rem; font-size: 2.3rem; /* text-align: center; */ @@ -827,7 +824,7 @@ a:hover { .bottom { margin-left: -0.15rem; color: var(--main-color); - transition: .25s; + transition: 0.25s; cursor: pointer; } } @@ -927,12 +924,12 @@ key { color: var(--bg-color); background-color: var(--sub-color); /* font-weight: bold; */ - padding: .1rem .3rem; + padding: 0.1rem 0.3rem; margin: 3px 0; border-radius: 0.1rem; display: inline-block; - font-size: .7rem; - line-height: .7rem; + font-size: 0.7rem; + line-height: 0.7rem; } #bottom { @@ -949,7 +946,7 @@ key { .version { opacity: 0; - transition: .25s; + transition: 0.25s; &:hover { cursor: pointer; @@ -993,7 +990,7 @@ key { .stats { display: grid; - column-gap: .5rem; + column-gap: 0.5rem; justify-content: center; align-items: center; grid-template-areas: @@ -1004,9 +1001,8 @@ key { "leaderboards leaderboards" "testType infoAndTags"; - .group { - margin-bottom: .5rem; + margin-bottom: 0.5rem; .top { color: var(--sub-color); @@ -1072,7 +1068,7 @@ key { .infoAndTags { display: grid; - gap: .5rem; + gap: 0.5rem; align-self: baseline; grid-area: infoAndTags; color: var(--sub-color); @@ -1095,21 +1091,21 @@ key { font-size: 3rem; line-height: 3rem; display: flex; - margin-top: -.5rem; + margin-top: -0.5rem; .crownWrapper { width: 1.7rem; overflow: hidden; height: 1.7rem; - margin-left: .5rem; - margin-top: .98rem; + margin-left: 0.5rem; + margin-top: 0.98rem; .crown { - font-size: .7rem; + font-size: 0.7rem; line-height: 1.7rem; background: var(--main-color); color: var(--bg-color); - border-radius: .6rem; + border-radius: 0.6rem; text-align: center; align-self: center; width: 1.7rem; @@ -1142,7 +1138,6 @@ key { } } - #wordsInput { height: 0; padding: 0; @@ -1154,7 +1149,7 @@ key { #wordsTitle { color: var(--sub-color); - margin-left: .25rem; + margin-left: 0.25rem; margin-top: 1rem; display: none; } @@ -1212,7 +1207,6 @@ key { } } - #words.flipped.colorfulMode .word.error, #words.colorfulMode .word.error { border-bottom: 2px solid var(--colorful-error-color); @@ -1250,7 +1244,6 @@ key { } } - #middle { .pageTest { #testModesNotice { @@ -1262,11 +1255,11 @@ key { margin-bottom: 1.25rem; height: 1rem; line-height: 1rem; - transition: .125s; + transition: 0.125s; justify-content: center; .fas { - margin-right: .5rem; + margin-right: 0.5rem; } } } @@ -1283,7 +1276,7 @@ key { } .word { - margin: .25rem; + margin: 0.25rem; color: var(--sub-color); display: flex; // transition: 0.25s; @@ -1298,13 +1291,13 @@ key { background: var(--sub-color); color: var(--bg-color); /* background: red; */ - padding: .5rem; + padding: 0.5rem; /* left: .5rem; */ - margin-left: -.5rem; - margin-top: -.5rem; + margin-left: -0.5rem; + margin-top: -0.5rem; border-radius: var(--roundness); // box-shadow: 0 0 10px rgba(0,0,0,.25); - transition: .25s; + transition: 0.25s; text-shadow: none; } } @@ -1312,19 +1305,19 @@ key { #words.size125 .word { line-height: 1.25rem; font-size: 1.25rem; - margin: .31rem; + margin: 0.31rem; } #words.size15 .word { line-height: 1.5rem; font-size: 1.5rem; - margin: .37rem; + margin: 0.37rem; } #words.size2 .word { line-height: 2rem; font-size: 2rem; - margin: .5rem; + margin: 0.5rem; } .word.error { @@ -1332,11 +1325,10 @@ key { border-bottom: 2px solid var(--error-color); text-shadow: 1px 0px 0px var(--bg-color), // 2px 0px 0px var(--bg-color), - -1px 0px 0px var(--bg-color), + -1px 0px 0px var(--bg-color), // -2px 0px 0px var(--bg-color), - 0px 1px 0px var(--bg-color), - 1px 1px 0px var(--bg-color), - -1px 1px 0px var(--bg-color); + 0px 1px 0px var(--bg-color), + 1px 1px 0px var(--bg-color), -1px 1px 0px var(--bg-color); } // .word letter { @@ -1380,11 +1372,12 @@ key { .side { display: grid; - gap: .5rem; + gap: 0.5rem; justify-content: center; &.login { - grid-template-areas: "title forgotButton" + grid-template-areas: + "title forgotButton" "form form"; .title { @@ -1393,15 +1386,15 @@ key { #forgotPasswordButton { grid-area: forgotButton; - font-size: .5rem; - line-height: .5rem; + font-size: 0.5rem; + line-height: 0.5rem; height: fit-content; align-self: center; justify-self: right; - padding: .25rem 0; + padding: 0.25rem 0; color: var(--sub-color); cursor: pointer; - transition: .25s; + transition: 0.25s; &:hover { color: var(--main-color); @@ -1424,18 +1417,18 @@ key { height: 0; display: none; - &~.customCheckbox { + & ~ .customCheckbox { width: 12px; height: 12px; - background: rgba(0, 0, 0, .1); + background: rgba(0, 0, 0, 0.1); border-radius: 2px; - box-shadow: 0 0 0 4px rgba(0, 0, 0, .1); + box-shadow: 0 0 0 4px rgba(0, 0, 0, 0.1); display: inline-block; - margin: 0 .5rem 0 .25rem; - transition: .25s; + margin: 0 0.5rem 0 0.25rem; + transition: 0.25s; } - &:checked~.customCheckbox { + &:checked ~ .customCheckbox { background: var(--main-color); } } @@ -1446,7 +1439,7 @@ key { form { display: grid; - gap: .5rem; + gap: 0.5rem; width: 100%; } @@ -1457,7 +1450,7 @@ key { font-size: 2rem; transform: translate(-50%, -50%); color: var(--main-color); - transition: .25s; + transition: 0.25s; } } @@ -1467,7 +1460,7 @@ key { .section { display: grid; - gap: .5rem; + gap: 0.5rem; h1 { font-size: 1rem; @@ -1507,7 +1500,8 @@ key { .section { display: grid; // gap: .5rem; - grid-template-areas: "title title" + grid-template-areas: + "title title" "text buttons"; grid-template-columns: 2fr 1fr; column-gap: 2rem; @@ -1516,7 +1510,7 @@ key { &.customTheme { grid-template-columns: 1fr 1fr 1fr 1fr; justify-items: stretch; - gap: .5rem 2rem; + gap: 0.5rem 2rem; & p { grid-area: unset; @@ -1552,7 +1546,7 @@ key { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; - gap: .5rem; + gap: 0.5rem; grid-area: buttons; } @@ -1592,7 +1586,7 @@ key { .tagsList { display: grid; - gap: .5rem; + gap: 0.5rem; .tag { display: grid; @@ -1631,14 +1625,14 @@ key { } .addTagButton { - margin-top: .5rem; + margin-top: 0.5rem; color: var(--text-color); cursor: pointer; - transition: .25s; - padding: .2rem .5rem; + transition: 0.25s; + padding: 0.2rem 0.5rem; border-radius: var(--roundness); - background: rgba(0, 0, 0, .1); + background: rgba(0, 0, 0, 0.1); text-align: center; -webkit-user-select: none; display: grid; @@ -1668,10 +1662,11 @@ key { &.languages, &.layouts { grid-template-columns: 1fr; - grid-template-areas: "title" + grid-template-areas: + "title" "tabs" "buttons"; - gap: .5rem; + gap: 0.5rem; .tabs { grid-area: tabs; @@ -1681,7 +1676,7 @@ key { .tab { will-change: color; - transition: .2s ease-in-out color; + transition: 0.2s ease-in-out color; outline: 0; cursor: pointer; padding: 0; @@ -1693,7 +1688,7 @@ key { font-family: "Roboto Mono"; &:first-child { - margin-right: .5rem; + margin-right: 0.5rem; } &.active, @@ -1708,7 +1703,7 @@ key { grid-auto-flow: dense; display: grid; grid-template-columns: 1fr 1fr 1fr 1fr; - gap: .5rem; + gap: 0.5rem; } } } @@ -1744,10 +1739,10 @@ key { // background: var(--sub-color); color: var(--sub-color); width: fit-content; - padding: .5rem; + padding: 0.5rem; border-radius: var(--roundness); cursor: pointer; - transition: .25s; + transition: 0.25s; float: right; &:hover { @@ -1755,7 +1750,7 @@ key { } .fas { - margin-right: .5rem; + margin-right: 0.5rem; } } @@ -1794,14 +1789,14 @@ key { &.history { .loadMoreButton { - background: rgba(0, 0, 0, .1); + background: rgba(0, 0, 0, 0.1); color: var(--text-color); text-align: center; - padding: .5rem; + padding: 0.5rem; border-radius: var(--roundness); cursor: pointer; - -webkit-transition: .25s; - transition: .25s; + -webkit-transition: 0.25s; + transition: 0.25s; -webkit-user-select: none; display: -ms-grid; display: grid; @@ -1849,12 +1844,12 @@ key { color: var(--text-color); td { - padding: .5rem .25rem; + padding: 0.5rem 0.25rem; } thead { color: var(--sub-color); - font-size: .75rem; + font-size: 0.75rem; } tbody tr:nth-child(odd) td { @@ -1862,12 +1857,12 @@ key { } td.infoIcons span { - margin: 0 .1rem; + margin: 0 0.1rem; } } #resultEditTags { - transition: .25s; + transition: 0.25s; } #resultEditTags:hover { @@ -1887,7 +1882,7 @@ key { height: fit-content; height: -moz-fit-content; display: grid; - gap: .25rem; + gap: 0.25rem; color: var(--sub-color); line-height: 1rem; font-size: 1rem; @@ -1899,13 +1894,13 @@ key { gap: 1rem; .button { - background: rgba(0, 0, 0, .1); + background: rgba(0, 0, 0, 0.1); color: var(--text-color); text-align: center; - padding: .5rem; + padding: 0.5rem; border-radius: var(--roundness); cursor: pointer; - transition: .25s; + transition: 0.25s; -webkit-user-select: none; display: grid; align-content: center; @@ -1934,7 +1929,7 @@ key { position: fixed; font-size: 3rem; color: var(--sub-color); - opacity: .25; + opacity: 0.25; z-index: -1; &.tl { @@ -1969,11 +1964,11 @@ key { .button { color: var(--text-color); cursor: pointer; - transition: .25s; - padding: .4rem; + transition: 0.25s; + padding: 0.4rem; border-radius: var(--roundness); - background: rgba(0, 0, 0, .1); + background: rgba(0, 0, 0, 0.1); text-align: center; -webkit-user-select: none; // display: grid; @@ -1984,7 +1979,7 @@ key { .fas, .far { - margin-right: .5rem; + margin-right: 0.5rem; } &.active { @@ -2035,20 +2030,20 @@ key { } @media only screen and (max-width: 800px) { - #centerContent { #top { - grid-template-areas: "logo config" + grid-template-areas: + "logo config" "menu config"; } #menu { - gap: .5rem; - font-size: .8rem; - line-height: .8rem; + gap: 0.5rem; + font-size: 0.8rem; + line-height: 0.8rem; .icon-button { - padding: .25rem; + padding: 0.25rem; } } } @@ -2057,10 +2052,8 @@ key { #commandLineInput { width: 500px !important; } - } - @media only screen and (max-width: 650px) { .pageSettings .section { grid-template-columns: 1fr; @@ -2078,4 +2071,65 @@ key { #commandLineInput { width: 400px !important; } -} \ No newline at end of file +} + +.keymap { + display: grid; + grid-template-rows: 1fr 1fr 1fr 1fr; + justify-content: center; + white-space: nowrap; + height: 140px; +} + +.row { + height: 2rem; +} + +.keymap-key { + display: flex; + background-color: var(--bg-color); + color: var(--sub-color); + border-radius: 0.25rem; + border: 0.1rem solid var(--sub-color); + text-align: center; + justify-content: center; + align-items: center; + margin: 0.1rem; +} + +.hidden-key { + opacity: 0; +} + +.r1 { + display: grid; + grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 2fr; + opacity: 0; +} + +.r2 { + display: grid; + grid-template-columns: 1.5fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1.5fr; +} + +.r3 { + display: grid; + grid-template-columns: 1.75fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1.75fr; +} + +.r4 { + display: grid; + grid-template-columns: 2.25fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 2.75fr; +} + +.r5 { + display: grid; + grid-template-columns: 1.25fr 1.25fr 1.25fr 6.25fr 1.25fr 1.25fr 1.25fr 1.25fr; +} + +.active-key { + color: var(--bg-color); + background-color: var(--main-color); + border-radius: 0.25rem; + border: 0.1rem solid var(--main-color); +} diff --git a/public/index.html b/public/index.html index 652622efe..81e38f7f5 100644 --- a/public/index.html +++ b/public/index.html @@ -700,6 +700,204 @@
60
123
+ +
+
+
+ ` +
+
+ 1 +
+
+ 2 +
+
+ 3 +
+
+ 4 +
+
+ 5 +
+
+ 6 +
+
+ 7 +
+
+ 8 +
+
+ 9 +
+
+ 0 +
+
+ - +
+
+ = +
+
+ delete +
+
+
+
+ +
+
+ q +
+
+ w +
+
+ e +
+
+ r +
+
+ t +
+
+ y +
+
+ u +
+
+ i +
+
+ o +
+
+ p +
+
+ [ +
+
+ ] +
+
+ \ +
+
+
+
+ +
+
+ a +
+
+ s +
+
+ d +
+
+ f +
+
+ g +
+
+ h +
+
+ j +
+
+ k +
+
+ l +
+
+ ; +
+
+ ' +
+
+ +
+
+
+
+ +
+
+ z +
+
+ x +
+
+ c +
+
+ v +
+
+ b +
+
+ n +
+
+ m +
+
+ , +
+
+ . +
+
+ / +
+
+ +
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
@@ -873,7 +1071,7 @@
-

layout override

+

layout

@@ -1077,6 +1275,19 @@
hide
+
+

keymap

+
Displays your current layout while taking a test.
+
+
show
+
hide
+
+
+

key tips

Shows the keybind tips at the bottom of the page.
diff --git a/public/js/commandline.js b/public/js/commandline.js index 895fd124c..c8f4a8bc8 100644 --- a/public/js/commandline.js +++ b/public/js/commandline.js @@ -73,6 +73,29 @@ let commands = { saveConfigToCookie(); }, }, + { + id: "toggleKeymap", + display: "Toggle keymap display", + exec: () => { + config.keymap = !config.keymap; + console.log(`keymap ${config.keymap}`); + if (config.keymap) { + showKeymap(); + } else { + hideKeymap(); + } + saveConfigToCookie(); + }, + }, + { + id: "changeKeymapLayout", + display: "Change keymap layout...", + subgroup: true, + exec: () => { + currentCommands.push(commandsKeymapLayouts); + showCommandLine(); + }, + }, { id: "toggleTimerBar", display: "Toggle timer display", @@ -686,6 +709,33 @@ if (Object.keys(layouts).length > 0) { }); } +let commandsKeymapLayouts = { + title: "Change keymap layout...", + list: [ + { + id: "couldnotload", + display: "Could not load the layouts list :(", + }, + ], +}; + +if (Object.keys(layouts).length > 0) { + commandsKeymapLayouts.list = []; + Object.keys(layouts).forEach((layout) => { + if (layout.toString() != "default") { + commandsKeymapLayouts.list.push({ + id: "changeLayout" + capitalizeFirstLetter(layout), + display: layout.replace("_", " "), + exec: () => { + changeKeymapLayout(layout); + restartTest(); + saveConfigToCookie(); + }, + }); + } + }); +} + $("#commandLine input").keyup((e) => { if (e.keyCode == 38 || e.keyCode == 40 || e.keyCode == 13) return; updateSuggestedCommands(); diff --git a/public/js/script.js b/public/js/script.js index fe9efab5c..a37733227 100644 --- a/public/js/script.js +++ b/public/js/script.js @@ -522,8 +522,24 @@ function showWords() { .css("overflow", "hidden"); } + if ($(".active-key") != undefined) { + $(".active-key").removeClass("active-key"); + } + + var currentKey = wordsList[currentWordIndex] + .substring(currentInput.length, currentInput.length + 1) + .toString() + .toUpperCase(); + + var highlightKey = `#Key${currentKey}`; + + $(highlightKey).addClass("active-key"); + updateActiveElement(); updateCaretPosition(); + if (config.keymap) { + changeKeymapLayout(config.keymapLayout); + } } function updateActiveElement() { @@ -544,6 +560,7 @@ function updateActiveElement() { // activeWordTop = $("#words .word.active").position().top; activeWordTop = document.querySelector("#words .active").offsetTop; + updateHighlightedKey(); } catch (e) {} } @@ -805,6 +822,67 @@ function startCaretAnimation() { $("#caret").css("animation-name", "caretFlash"); } +function hideKeymap() { + $(".keymap").addClass("hidden"); +} + +function showKeymap() { + $(".keymap").removeClass("hidden"); +} + +function updateHighlightedKey() { + if ($(".active-key") != undefined) { + $(".active-key").removeClass("active-key"); + } + + var currentKey = wordsList[currentWordIndex] + .substring(currentInput.length, currentInput.length + 1) + .toString() + .toUpperCase(); + + switch (currentKey) { + case "\\": + case "|": + var highlightKey = "#KeyBackslash"; + break; + case "}": + case "]": + var highlightKey = "#KeyRightBracket"; + break; + case "{": + case "[": + var highlightKey = "#KeyLeftBracket"; + break; + case '"': + case "'": + var highlightKey = "#KeyQuote"; + break; + case ":": + case ";": + var highlightKey = "#KeySemicolon"; + break; + case "<": + case ",": + var highlightKey = "#KeyComma"; + break; + case ">": + case ".": + var highlightKey = "#KeyPeriod"; + break; + case "?": + case "/": + var highlightKey = "#KeySlash"; + break; + case "": + var highlightKey = "#KeySpace"; + break; + default: + var highlightKey = `#Key${currentKey}`; + } + + $(highlightKey).addClass("active-key"); +} + function updateCaretPosition() { // return; if ($("#words").hasClass("hidden")) return; @@ -996,6 +1074,7 @@ function showResult(difficultyFailed = false) { hideCaret(); hideLiveWpm(); hideTimer(); + hideKeymap(); testInvalid = false; let stats = calculateStats(); if (stats === undefined) { @@ -1520,6 +1599,7 @@ function restartTest(withSameWordset = false) { testActive = false; hideLiveWpm(); hideTimer(); + hideKeymap(); keypressPerSecond = []; currentKeypressCount = 0; errorsPerSecond = []; @@ -1605,6 +1685,9 @@ function restartTest(withSameWordset = false) { currentInput = ""; showWords(); } + if (config.keymap) { + showKeymap(); + } $("#result").addClass("hidden"); $("#testModesNotice").css({ opacity: 1, @@ -1657,6 +1740,7 @@ function restartTest(withSameWordset = false) { ); } ); + // $(".active-key").classList.remove("active-key"); } function focusWords() { @@ -2522,6 +2606,8 @@ $(document).keypress(function (event) { activeWordJumped = true; } // console.timeEnd("offcheck2"); + + updateHighlightedKey(); updateCaretPosition(); }); @@ -2603,6 +2689,7 @@ $(document).keydown((event) => { compareInput(null, currentInput, !config.blindMode); } // currentKeypressCount++; + updateHighlightedKey(); updateCaretPosition(); } //space @@ -2662,6 +2749,7 @@ $(document).keydown((event) => { inputHistory.push(currentInput); currentInput = ""; currentWordIndex++; + updateHighlightedKey(); updateActiveElement(); updateCaretPosition(); currentKeypressCount++; diff --git a/public/js/settings.js b/public/js/settings.js index 7aa6634cc..7002d07fb 100644 --- a/public/js/settings.js +++ b/public/js/settings.js @@ -34,12 +34,25 @@ function updateSettingsPage() { ); }); + let keymapEl = $(".pageSettings .section.keymap-layouts .buttons").empty(); + Object.keys(layouts).forEach((layout) => { + if (layout.toString() != "default") { + keymapEl.append( + `
${layout.replace( + "_", + " " + )}
` + ); + } + }); + refreshTagsSettingsSection(); setSettingsButton("smoothCaret", config.smoothCaret); setSettingsButton("quickTab", config.quickTab); setSettingsButton("liveWpm", config.showLiveWpm); setSettingsButton("timerBar", config.showTimerBar); + setSettingsButton("keymap-toggle", config.keymap); setSettingsButton("keyTips", config.showKeyTips); setSettingsButton("freedomMode", config.freedomMode); setSettingsButton("blindMode", config.blindMode); @@ -55,6 +68,7 @@ function updateSettingsPage() { setActiveThemeButton(); setActiveLanguageButton(); setActiveLayoutButton(); + setActiveKeymapLayoutButton(); setActiveFontSizeButton(); setActiveDifficultyButton(); setActiveCaretStyleButton(); @@ -208,6 +222,13 @@ function setActiveLayoutButton() { ); } +function setActiveKeymapLayoutButton() { + $(`.pageSettings .section.keymap-layouts .layout`).removeClass("active"); + $( + `.pageSettings .section.keymap-layouts .layout[layout=${config.keymapLayout}]` + ).addClass("active"); +} + function setActiveFontSizeButton() { $(`.pageSettings .section.fontSize .buttons .button`).removeClass("active"); $( @@ -447,6 +468,37 @@ $(".pageSettings .section.timerBar .buttons .button.off").click((e) => { setSettingsButton("timerBar", config.showTimerBar); }); +//keymap +$(".pageSettings .section.keymap-toggle .buttons .button.on").click((e) => { + config.keymap = true; + saveConfigToCookie(); + // showNotification('Keymap on', 1000); + setSettingsButton("keymap-toggle", config.keymap); + $(".keymap-layouts").removeClass("hidden"); +}); +$(".pageSettings .section.keymap-toggle .buttons .button.off").click((e) => { + config.keymap = false; + saveConfigToCookie(); + // showNotification('Keymap off', 1000); + setSettingsButton("keymap-toggle", config.keymap); + $(".keymap-layouts").addClass("hidden"); +}); + +if (config.keymap) $(".keymap-layouts").removeClass("hidden"); + +//keymap layouts +$(document).on( + "click", + ".pageSettings .section.keymap-layouts .layout", + (e) => { + let layout = $(e.currentTarget).attr("layout"); + changeKeymapLayout(layout); + // showNotification('Keymap Layout changed', 1000); + restartTest(); + setActiveKeymapLayoutButton(); + } +); + //freedom mode $(".pageSettings .section.freedomMode .buttons .button.on").click((e) => { setFreedomMode(true); diff --git a/public/js/userconfig.js b/public/js/userconfig.js index 005e1134d..5f0d28e40 100644 --- a/public/js/userconfig.js +++ b/public/js/userconfig.js @@ -40,6 +40,8 @@ let defaultConfig = { timerOpacity: "0.25", stopOnError: false, showAllLines: false, + keymap: false, + keymapLayout: "qwerty", }; let cookieConfig = null; @@ -669,6 +671,78 @@ function changeLayout(layout, nosave) { if (!nosave) saveConfigToCookie(); } +function changeKeymapLayout(layout, nosave) { + if (layout == null || layout == undefined) { + layout = "qwerty"; + } + config.keymapLayout = layout; + if (!nosave) saveConfigToCookie(); + // layouts[layout].forEach((x) => { + // console.log(x); + // }); + + var toReplace = layouts[layout].slice(13, 47); + var _ = toReplace.splice(12, 1); + var count = 0; + + $(".letter") + .map(function () { + if ( + !this.parentElement.classList.contains("hidden-key") && + !this.classList.contains("hidden-key") + ) { + if (count < toReplace.length) { + var key = toReplace[count].charAt(0); + this.innerHTML = key; + + switch (key) { + case "\\": + case "|": + this.parentElement.id = "KeyBackslash"; + break; + case "}": + case "]": + this.parentElement.id = "KeyRightBracket"; + break; + case "{": + case "[": + this.parentElement.id = "KeyLeftBracket"; + break; + case '"': + case "'": + this.parentElement.id = "KeyQuote"; + break; + case ":": + case ";": + this.parentElement.id = "KeySemicolon"; + break; + case "<": + case ",": + this.parentElement.id = "KeyComma"; + break; + case ">": + case ".": + this.parentElement.id = "KeyPeriod"; + break; + case "?": + case "/": + this.parentElement.id = "KeySlash"; + break; + case "": + this.parentElement.id = "KeySpace"; + break; + default: + this.parentElement.id = `Key${key.toUpperCase()}`; + } + } + count++; + } + }) + .get(); + + // console.log(all.join()); +} + function changeFontSize(fontSize, nosave) { if (fontSize == null || fontSize == undefined) { fontSize = 1;