diff --git a/public/css/style.scss b/public/css/style.scss index cca1e9fca..773d29e0b 100644 --- a/public/css/style.scss +++ b/public/css/style.scss @@ -1043,7 +1043,7 @@ key { &.fontSize .buttons{ grid-template-columns: 1fr 1fr 1fr 1fr; } - &.themes, &.languages{ + &.themes, &.languages, &.layouts{ grid-template-columns: 1fr; grid-template-areas: "title" "buttons"; @@ -1054,7 +1054,7 @@ key { display: grid; grid-template-columns: 1fr 1fr 1fr 1fr; gap: .5rem; - .theme, .language{ + .theme, .language, .layout{ color: var(--text-color); cursor: pointer; transition: .25s; @@ -1226,7 +1226,7 @@ key { background: var(--main-color); } } - &.languages{ + &.languages, &.layouts{ grid-template-columns: repeat(4,1fr); grid-auto-flow: unset; } diff --git a/public/index.html b/public/index.html index 457e6bb72..3c828c3d3 100644 --- a/public/index.html +++ b/public/index.html @@ -360,6 +360,12 @@
+ +
+

layouts

+
+
+

theme

@@ -597,6 +603,7 @@ + diff --git a/public/js/commandline.js b/public/js/commandline.js index b94730b42..db9bfb6f0 100644 --- a/public/js/commandline.js +++ b/public/js/commandline.js @@ -114,6 +114,15 @@ let commands = { showCommandLine(); } }, + { + id: "changeLayout", + display: "Change layout...", + subgroup: true, + exec: () => { + currentCommands.push(commandsLayouts); + showCommandLine(); + } + }, { id: "changeFontSize", display: "Change font size...", @@ -473,6 +482,32 @@ if (Object.keys(words).length > 0) { }) } +let commandsLayouts = { + title: "Change layout...", + list: [ + { + id: "couldnotload", + display: "Could not load the layouts list :(" + } + ] +}; + + +if (Object.keys(layouts).length > 0) { + commandsLayouts.list = []; + Object.keys(layouts).forEach(layout => { + commandsLayouts.list.push({ + id: "changeLayout" + capitalizeFirstLetter(layout), + display: layout.replace('_', ' '), + exec: () => { + changeLayout(layout); + restartTest(); + saveConfigToCookie(); + } + }) + }) +} + $("#commandLine input").keyup((e) => { if (e.keyCode == 38 || e.keyCode == 40 || e.keyCode == 13) return; updateSuggestedCommands(); diff --git a/public/js/layouts.js b/public/js/layouts.js new file mode 100644 index 000000000..067bed010 --- /dev/null +++ b/public/js/layouts.js @@ -0,0 +1,23 @@ +const layouts = { + qwerty: [ + "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+", + "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","[{","]}","\\|", + "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";:","'\"", + "zZ","xX","cC","vV","bB","nN","mM",",<",".>","/?", + " " + ], + dvorak: [ + "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0(","[{","]}", + "'\"",",<",".>","pP","yY","fF","gG","cC","rR","lL","/?","=+","\\|", + "aA","oO","eE","uU","iI","dD","hH","tT","nN","sS","-_", + ";:","qQ","jJ","kK","xX","bB","mM","wW","vV","zZ", + " " + ], + colemak:[ + "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+", + "qQ","wW","fF","pP","gG","jJ","lL","uU","yY",";:","[{","]}","\\|", + "aA","rR","sS","tT","dD","hH","nN","eE","iI","oO","'\"", + "zZ","xX","cC","vV","bB","Kk","mM",",<",".>","/?", + " " + ] +} \ No newline at end of file diff --git a/public/js/script.js b/public/js/script.js index 7ed47a03b..cc6bdcc84 100644 --- a/public/js/script.js +++ b/public/js/script.js @@ -145,6 +145,33 @@ function initWords() { showWords(); } +function emulateLayout(event){ + if (config.layout == "qwerty") + return event; + let layoutMap = layouts[config.layout]; + let qwertyMap = layouts["qwerty"]; + + let mapIndex; + let newKey; + let shift = false; + for (let i = 0; i < qwertyMap.length; i++) { + const key = qwertyMap[i]; + let keyIndex = key.indexOf(event.key); + if (keyIndex != -1){ + mapIndex = i; + shift = keyIndex; + } + } + + newKey = layoutMap[mapIndex][shift]; + event.keyCode = newKey.charCodeAt(0); + event.charCode = newKey.charCodeAt(0); + event.which = newKey.charCodeAt(0); + event.code = `key${newKey}`; + event.key = newKey; + return event; +} + function punctuateWord(previousWord, currentWord, index, maxindex){ let word = currentWord; @@ -1197,6 +1224,7 @@ $(document).mousemove(function(event) { //keypresses for the test, using different method to be more responsive $(document).keypress(function(event) { + event = emulateLayout(event); if (!$("#wordsInput").is(":focus")) return; if (event["keyCode"] == 13) return; if (event["keyCode"] == 32) return; diff --git a/public/js/settings.js b/public/js/settings.js index ca12298bb..9aeab1cd3 100644 --- a/public/js/settings.js +++ b/public/js/settings.js @@ -7,9 +7,15 @@ function updateSettingsPage(){ let langEl = $(".pageSettings .section.languages .buttons").empty(); Object.keys(words).forEach(language => { - langEl.append(`
${language.replace('_', ' ')}
`); + langEl.append(`
${language.replace('_', ' ')}
`); }) + let layoutEl = $(".pageSettings .section.layouts .buttons").empty(); + Object.keys(layouts).forEach(layout => { + layoutEl.append(`
${layout.replace('_', ' ')}
`); + }); + + setSettingsButton('smoothCaret', config.smoothCaret); setSettingsButton('quickTab', config.quickTab); setSettingsButton('liveWpm', config.showLiveWpm); @@ -23,6 +29,7 @@ function updateSettingsPage(){ setActiveThemeButton(); setActiveLanguageButton(); + setActiveLayoutButton(); setActiveFontSizeButton(); setActiveDifficultyButton(); setActiveCaretStyleButton(); @@ -41,6 +48,11 @@ function setActiveThemeButton() { $(`.pageSettings .section.themes .theme[theme=${config.theme}]`).addClass('active'); } +function setActiveLayoutButton(){ + $(`.pageSettings .section.layouts .layout`).removeClass('active'); + $(`.pageSettings .section.layouts .layout[layout=${config.layout}]`).addClass('active'); +} + function setActiveFontSizeButton() { $(`.pageSettings .section.fontSize .buttons .button`).removeClass('active'); $(`.pageSettings .section.fontSize .buttons .button[fontsize=`+config.fontSize+`]`).addClass('active'); @@ -185,6 +197,16 @@ $(document).on("click",".pageSettings .section.languages .language", (e) => { setActiveLanguageButton(); }) +//layouts +$(document).on("click",".pageSettings .section.layouts .layout", (e) => { + console.log("clicked") + let layout = $(e.currentTarget).attr('layout'); + changeLayout(layout); + showNotification('Layout changed', 1000); + restartTest(); + setActiveLayoutButton(); +}) + //fontsize $(document).on("click",".pageSettings .section.fontSize .button", (e) => { let fontSize = $(e.currentTarget).attr('fontsize'); diff --git a/public/js/userconfig.js b/public/js/userconfig.js index 17f508f26..4f338d98d 100644 --- a/public/js/userconfig.js +++ b/public/js/userconfig.js @@ -17,7 +17,8 @@ let config = { blindMode: false, quickEnd: false, caretStyle: "default", - flipTestColors: false + flipTestColors: false, + layout:"qwerty" } //cookies @@ -44,6 +45,7 @@ function loadConfigFromCookie() { changeWordCount(newConfig.words,true); changeMode(newConfig.mode,true); changeLanguage(newConfig.language,true); + changeLayout(newConfig.layout, true); changeFontSize(newConfig.fontSize,true); setFreedomMode(newConfig.freedomMode,true); setCaretStyle(newConfig.caretStyle,true); @@ -356,6 +358,22 @@ function changeLanguage(language, nosave) { if(!nosave) saveConfigToCookie(); } +function changeLayout(layout, nosave){ + if (layout == null || layout == undefined){ + layout = "qwerty" + } + + config.layout = layout; + try{ + firebase.analytics().logEvent('changedLanguage', { + language: language + }); + }catch(e){ + console.log("Analytics unavailable"); + } + if(!nosave) saveConfigToCookie(); +} + function changeFontSize(fontSize, nosave) { if (fontSize == null || fontSize == undefined) { fontSize = 1;