{"id":3217,"date":"2026-06-09T14:15:34","date_gmt":"2026-06-09T12:15:34","guid":{"rendered":"https:\/\/fotografeer.nl\/?p=3217"},"modified":"2026-06-15T19:03:25","modified_gmt":"2026-06-15T17:03:25","slug":"rehab-typing-test","status":"publish","type":"post","link":"https:\/\/fotografeer.nl\/?p=3217","title":{"rendered":"Rehab &#8211; Typing Test &#8211; v0.9"},"content":{"rendered":"\n<script>\n    var altDown = false;\n    var kar = \"\";\n    var _buffer = null;\n    var urls = [];\n    var lang = \"\";\n    var country = \"\";\n    var originalText = \"\";\n    var mode = \"Simple\";\n    var punctuation = \".?!,;:-\u2013\u2014()[]{}'\" + '\"';  \/\/ Punctuation marks\n    var space = \" \"; \/\/ Space\n    var numbers = \"0123456789\"; \/\/ Numbers\n    var speci = \"#$%&*+\/<=>@^_`|~\\\\\u00b0\u00a3\u20ac\u00a5\u00a2\"; \/\/ Special characters exculding punctuation marks\n    var time = 0;\n    var accuracy = 0;\n    var cps = 0;\n    var cpm = 0;\n    var numberOfKeysPressed = 0;\n    var correctKeysPressed = 0;\n    var isShift = false;\n    var oldUpCode = '';\n    var cursorPosition = 1;\n    var beforeCursor = \"\";\n    var atCursor = \"\";\n    var afterCursor = \"\";\n    var disabled = false;\n    var veld = document.getElementById('veld');\n    const apiurl = \"https:\/\/api.github.com\/repos\/dsnpevl\/rehabilitation.typing.test\/git\/trees\/main?recursive=1\";\n    const raw = \"https:\/\/raw.githubusercontent.com\/dsnpevl\/rehabilitation.typing.test\/refs\/heads\/main\/\";\n    const digitsOnly = string => [...string].every(c => '0123456789'.includes(c));\n    audioCtx = new(window.AudioContext || window.webkitAudioContext)(); \n    document.addEventListener(\"keyup\", upKey);\n    document.addEventListener(\"keydown\", downKey);\n    window.addEventListener(\"load\", (event) => {\n            \/\/ Load the URLs for the text content from the github trees API.\n            getData();\n            \/\/ Wait a short while and then press F1 (select Simple) and F5 (display text)\n            setTimeout(() => {pressF1(); pressF5();}, 300);\n            setTimeout(() => {autoComplete(); updateVeld(cursorPosition);}, 600);\n            setTimeout(() => {if (window.mobileAndTabletCheck()) {\n                 tekst.innerHTML = \"<b>This application is <br\/>aimed at typist using<br\/> a physical keyboard<br\/>on a PC or labtop.<br\/>It is not suited for<br\/>mobile phones<br\/>or tablets!<\/b>\"\n                 source.innerHTML = \"<b>Mobile Phone and Tablet not supported!<\/b>\";\n            }} , 1200);\n    });\n\n    function upKey(key)\n    {\n        if (key.getModifierState(\"NumLock\")) {\n                \/\/ debug.textContent = debug.textContent + \"NumLock: is ON\";\n                numLock = true;\n        }\n        if (!key.getModifierState(\"NumLock\")) {\n                \/\/ debug.textContent = debug.textContent + \"NumLock: is OFF\";\n                numLock = false;\n        }\n\n        if (key.key == \"Alt\") {\n            key.preventDefault();\n            debug.textContent = \"ALT is UP \" + kar + \"-\" + digitsOnly(kar) + \"-\"\n            if (kar.length > 0) {\n                \/\/ Increase the total number of keys pressed.\n                numberOfKeysPressed = numberOfKeysPressed + 1;\n                if (digitsOnly(kar)) {\n                    const altCode = kar\n                    \/\/ 1. Maak er het getal van, e.g. \"0128\" -> 128  \n                    const byteWaarde = parseInt(altCode, 10); \n                    \/\/ 2. Plaats de byte in een Uint8Array (byte-buffer)\n                    const byteBuffer = new Uint8Array([byteWaarde]);\n                    \/\/ 3. Decodeer de buffer expliciet als windows-1252\n                    const decoder = new TextDecoder('windows-1252');\n                    const letter = decoder.decode(byteBuffer);\n                    debug.textContent = debug.textContent + \"ALT is UP \" + kar + \"-\" + byteWaarde + \":\" + letter + \"=\" + atCursor + \" - \";\n\n                    if (atCursor != letter) {\n                        \/\/ Wrong character was pressed on keyboard! Keep yellow cursor at same spot.\n                        \/\/ Sound warning and display wanted character in bold and red.\n                        updateError();\n                        beepError();\n                    } else {\n                        \/\/ Count the number of correct keys pressed\n                        correctKeysPressed = correctKeysPressed + 1;\n                        \/\/ Move the cursor to the next character.\n                        cursorPosition = cursorPosition + 1;\n                        \/\/ Refresh the text\n                        updateVeld(cursorPosition);\n                    }\n                }\n            }\n            kar = \"\";\n            altDown = false;\n            tekst.focus();\n        }\n    }\n\n    function downKey(key)\n    {\n        \/\/ Get the original tekst inside the text area\n        tekst = document.getElementById(\"tekst\");\n        originalText = tekst.textContent.trim();\n\n        \/\/ Prevent unwanted scrolling to bottom when pressing space bar\n        \/\/ Source - https:\/\/stackoverflow.com\/a\/43054031\n        \/\/ Posted by lhavCoder, modified by community. See post 'Timeline' for change history\n        \/\/ Retrieved 2026-06-03, License - CC BY-SA 3.0\n        key.preventDefault();\n        if (key.keyCode == 32 && key.target == document.body) {\n            key.preventDefault();\n        }\n\n        \/\/ Function Keys F1, F2 and F3\n        if (key.code == \"F1\") {\n            key.preventDefault();\n            pressF1();\n            return;\n        }\n        if (key.code == \"F2\") {\n            key.preventDefault();\n            pressF2();\n            return;\n        }\n        if (key.code == \"F3\") {\n            key.preventDefault();\n            pressF3();\n            return;\n        }\n        if (key.code == \"F4\") {\n            key.preventDefault();\n            pressF4();\n            return;\n        }\n        if (key.code == \"F5\") {\n            key.preventDefault();\n            setTimeout(() => {pressF5();}, 300);\n            setTimeout(() => {autoComplete(); updateVeld(cursorPosition);}, 600);\n            return;\n        }\n        if (key.code == \"F6\" ||\n            key.code == \"F7\" ||\n            key.code == \"F8\" ||\n            key.code == \"F9\" ||\n            key.code == \"F10\") {\n                key.preventDefault();\n                toggleButton(document.getElementById(key.code));\n            return;\n        }\n        if (key.code == \"F11\") {\n            key.preventDefault();\n            var veldEl = document.getElementById(\"veld\");\n            var offset = veldEl.offsetHeight;\n            veldEl.scroll({top: offset, behavior: 'smooth'});\n            return;\n        }\n        if (key.code == \"F12\") {\n            key.preventDefault();\n            var veldEl = document.getElementById(\"veld\");\n            veldEl.scroll({top: 0, behavior: 'smooth'});\n            return;\n        }\n\n        \/\/ Get Special keys (e.g. Shift, Windows key, CTRL, ALT, ALT GR, FN\n        \/\/ key.altKey\n        \/\/ key.ctrlKey\n        \/\/ key.metaKey\n        \/\/ key.repeat\n        \/\/ key.isComposing\n\n        \/\/ Backspace\n        if (key.key == \"Backspace\") {\n            \/\/ TODO add removal of character and adapt cursor position\n            return;\n        }\n        \/\/ Shift\n        if (key.key == \"Shift\") {\n            return;\n        }\n        \/\/ Ctrl\n        if (key.key == \"Control\") { \n            return;\n        }\n        \/\/ Meta (Window key or Command key on Mac)\n        if (key.key == \"Meta\") { \n            return;\n        }\n        if (!key.getModifierState(\"NumLock\")) {\n                debug.textContent = debug.textContent + \"NumLock: is OFF\";\n                numLock = false;\n        }\n\n        debug.textContent = debug.textContent + \"2 downKey - \";\n        \/\/ Alt\n        if (key.key == \"Alt\") {\n                key.preventDefault();\n                debug.textContent = \"ALT is DOWN - \";\n                altDown = true;\n            return;\n        }\n\n        \/\/ Alt Gr\n        if (key.key == \"AltGraph\") { \n            return;\n        }\n        \/\/ Dead? e.g. \" followed by space on locales that generate umlaut characters by typing\n        \/\/ a double quote followed by a character like a, u, i (e.g. Dutch, German) \n        if (key.key == \"Dead\") { \n            return;\n        }\n        \/\/ Alt + Numeric keypad numbers 0-9.\n        if (altDown) {\n           debug.textContent = debug.textContent + \"Key code: \" + key.code + \" - \";\n           if (key.code.includes(\"Numpad\")) {\n                kar = kar + key.key;\n                debug.textContent = debug.textContent + \"Alt + \" + kar + \" - \";\n           }\n           return;\n        }\n        if (key.key == \"Dead\") { \n            return;\n        }\n              \n        \/\/ Update the text field.\n        updateVeld(cursorPosition);\n\n        var scroll = scrollNow(beforeCursor + atCursor);\n\/\/        debug.textContent = debug.textContent + \" Scroll \" + scroll;\n        if (scroll) {\n            var veldEl = document.getElementById(\"veld\");\n            var offset = veldEl.offsetHeight;\n            veldEl.scroll({top: offset, behavior: 'smooth'});\n        }\n\n \n        \/\/ Count the complete number of keys pressed (disregard special keys like shift, alt, etc.)\n        numberOfKeysPressed = numberOfKeysPressed + 1;\n\n        \/\/ Check if correct character was pressed on keyboard depending on the mode.\n        \/\/ Allow for case-insensitive check if Caps (F7) button is active\n        debug.textContent = \"Check correct character -\" + atCursor + \"-\" + atCursor.charCodeAt(0) + \"-\" + key.key + \"-\" + key.keyCode + \"-\" + afterCursor.charCodeAt(0) + \"-\";\n\n        if (atCursor.charCodeAt(0) == 160 && afterCursor.charCodeAt(0) == 32) {\n          debug.textContent = debug.textContent + originalText + \" - \";\n\n           debug.textContent = debug.textContent + \" Adjust tekst - \";\n           tekst.innerHTML = '<span style=\"color: green\">' + beforeCursor + '<\/span><span style=\"background-color: yellow; color: blue;\"><b> <\/b><\/span><span style=\"color: blue;\">' + afterCursor.substring(1,afterCursor.length) + '<\/span>';\n           originalText = tekst.textContent;\n           updateVeld(cursorPosition);\n\n           debug.textContent = debug.textContent + \"Removed '&nbsp; ' from: \" + originalText + \" - \";\n        }\n\n        if ((!document.getElementById(\"F7\").disabled && atCursor.toLowerCase() != key.key.toLowerCase()) || (document.getElementById(\"F7\").disabled && atCursor != key.key)) {\n            \/\/ Wrong character was pressed on keyboard! Keep yellow cursor at same spot.\n            \/\/ Sound warning and display wanted character in bold and red.\n            updateError();\n            beepError();\n            return;\n        }\n\n        debug.textContent = debug.textContent + \"correct character found-\" + atCursor + \"-\" + key.key + \"- \";\n\n        \/\/ Count the number of correct keys pressed\n        correctKeysPressed = correctKeysPressed + 1;\n\n        \/\/ Get the start time when first correct key is pressed.\n        if (correctKeysPressed == 1) {\n            \/\/ Get the time the user entered the first character\n            start = new Date().getTime();\n            \/\/ Hide results (like duration and accuracy)\n            hideResults();\n        }\n        \/\/ If there is nothing below the cursor, you've reached the end of the text\n        if (atCursor === \"\" || cursorPosition > tekst.textContent.length) {\n            showResults();\n            return;\n        }\n\n        \/\/ Update debug area\n        \/\/ updateDebug(key);\n \n        \/\/ Move the cursor to the next character.\n        cursorPosition = cursorPosition + 1;\n \n        \/\/ Refresh the text\n        updateVeld(cursorPosition);\n\n        \/\/ If next character is a space check for auto wrap\n        if (atCursor === \" \") {\n            debug.textContent = debug.textContent + \"NEXTCHAR:-\" + atCursor + \"-\" + afterCursor.charAt(0) +  \"- \";\n            lineSpace = lineNumber(beforeCursor + atCursor);\n            debug.textContent = debug.textContent+ \"Line \" + lineSpace + \"-\";\n            lineNext = lineNumber(beforeCursor + atCursor + afterCursor.replace(\/ .*\/,''));\n            debug.textContent = debug.textContent + lineNext + \" - \";\n            if (lineNext > lineSpace) {\n               debug.textContent = debug.textContent + \" Adjust tekst - \";\n               atCursor = String.fromCharCode(160) + \" \";\n               tekst.innerHTML = '<span style=\"color: green\">' + beforeCursor + '<\/span><span style=\"background-color: yellow; color: blue;\"><b>' + atCursor + '<\/b><\/span><span style=\"color: blue;\">' + afterCursor + '<\/span>';\n               originalText = tekst.textContent;\n            } \n        }\n\n        \/\/ Autocomplete according to selected autocomplete buttons (F6-F10)\n        autoComplete();\n\n        \/\/ Refresh the text\n        updateVeld(cursorPosition);\n\n        \/\/ If there is nothing below the cursor, you've reached the end of the text\n        if (atCursor === \"\" || cursorPosition > tekst.textContent.length) {\n            showResults();\n        }\n\n        originalText = replaces(originalText);\n        \/\/ Put focus on the text\n        tekst.focus();\n    }\n\n    function toggleButton(el)\n    {\n      if (el.disabled) {\n        el.disabled = false;\n      } else {\n        el.disabled = true;\n      }\n      tekst.focus();\n    }\n\n    function pressF1()\n    {\n          debug.textContent = debug.textContent + \" - F1 key was pressed - \";\n          document.getElementById(\"F1\").disabled = false;\n          document.getElementById(\"F2\").disabled = true;\n          document.getElementById(\"F3\").disabled = true;\n          document.getElementById(\"F4\").disabled = true;\n          document.getElementById(\"F5\").disabled = true;\n          document.getElementById(\"F6\").disabled = false;\n          document.getElementById(\"F7\").disabled = false;\n          document.getElementById(\"F8\").disabled = false;\n          document.getElementById(\"F9\").disabled = false;\n          document.getElementById(\"F10\").disabled = false;\n          tekst.focus();\n          mode = \"Simple\";\n    }\n    \n    function pressF2()\n    {\n          debug.textContent = debug.textContent + \" - F2 key was pressed - \";\n          document.getElementById(\"F1\").disabled = true;\n          document.getElementById(\"F2\").disabled = false;\n          document.getElementById(\"F3\").disabled = true;\n          document.getElementById(\"F4\").disabled = true;\n          document.getElementById(\"F5\").disabled = true;\n          document.getElementById(\"F6\").disabled = false;\n          document.getElementById(\"F7\").disabled = true;\n          document.getElementById(\"F8\").disabled = false;\n          document.getElementById(\"F9\").disabled = false;\n          document.getElementById(\"F10\").disabled = true;\n          tekst.focus();\n          mode = \"Intermediate\";\n   }\n\n    function pressF3()\n    {\n          debug.textContent = debug.textContent + \" - F3 key was pressed - \";\n          document.getElementById(\"F1\").disabled = true;\n          document.getElementById(\"F2\").disabled = true;\n          document.getElementById(\"F3\").disabled = false;\n          document.getElementById(\"F4\").disabled = true;\n          document.getElementById(\"F5\").disabled = true;\n          document.getElementById(\"F6\").disabled = true;\n          document.getElementById(\"F7\").disabled = true;\n          document.getElementById(\"F8\").disabled = true;\n          document.getElementById(\"F9\").disabled = false;\n          document.getElementById(\"F10\").disabled = true;\n          tekst.focus();\n          mode = \"Advanced\";\n    }\n\n    function pressF4()\n    {\n          debug.textContent = debug.textContent + \" - F4 key was pressed - \";\n          document.getElementById(\"F1\").disabled = true;\n          document.getElementById(\"F2\").disabled = true;\n          document.getElementById(\"F3\").disabled = true;\n          document.getElementById(\"F4\").disabled = false;\n          document.getElementById(\"F5\").disabled = true;\n          document.getElementById(\"F6\").disabled = true;\n          document.getElementById(\"F7\").disabled = true;\n          document.getElementById(\"F8\").disabled = true;\n          document.getElementById(\"F9\").disabled = true;\n          document.getElementById(\"F10\").disabled = true;\n          tekst.focus();\n          mode = \"Type Test\";\n    }\n\n    function pressF5()\n    {\n            \/\/ Hide Debug area\n            document.getElementById(\"debug\").style.visibility = 'hidden';\n            document.getElementById(\"debug\").style.maxHeight = \"0px\";\n\n            debug.textContent = debug.textContent + \" - F5 key was pressed - \";\n\n            \/\/ Determine the document's language (e.g. en) and country (e.g. GB)\n            \/\/ from locale (e.g. en-GB); Then get the matching URLs.\n            var locale = document.documentElement.lang.split(\"-\");\n            var substr = '\/' + locale[0] + '\/';\n            \/\/ Select text difficulty level\n            if (!document.getElementById(\"F1\").disabled) {\n                substr = substr + 'F1\/';\n            }\n            if (!document.getElementById(\"F2\").disabled) {\n                substr = substr + 'F2\/';\n            }\n            if (!document.getElementById(\"F3\").disabled) {\n                substr = substr + 'F3\/';\n            }\n            if (!document.getElementById(\"F4\").disabled) {\n                substr = substr + 'F4\/';\n            }\n\n            var langURLs = urls.filter(str => str.includes(substr));\n            \/\/ for debugging\n            \/\/ var langURLs = urls.filter(str => str.includes(\"specialcharacters.txt\"));\n\n            \/\/ Pseudo random number to select one of the langues specific URLs\n            var n = Math.floor(Math.random() * langURLs.length);\n            \/\/ Retrieve the text\n            getText(langURLs[n]);\n            \/\/ Reset the text\n            cursorPosition = 1;\n            start = 0;\n            end = 0;\n            time = 0;\n            accuracy = 0;\n            cps = 0;\n            cpm = 0;\n            numberOfKeysPressed = 0;\n            correctKeysPressed = 0;\n            \/\/ Make sure the scroll position is a the top of the text\n            document.getElementById(\"veld\").scroll({top: 0, behavior: 'smooth'});\n    }\n\n    function moveCursorToBegin() {\n        alert(\"moveCursorToBegin\");\n        const input = document.getElementById('tekst');\n        \/\/ Focus on the input\n        input.focus();\n        \/\/ Set the cursor to the end\n        input.setSelectionRange(1, 1);\n    }\n\n    function moveCursorToEnd() {\n        alert(\"moveCursorToEnd\");\n        const input = document.getElementById('tekst');\n        const length = input.value.length;\n        \/\/ Focus on the input\n        input.focus();\n        \/\/ Set the cursor to the end\n        input.setSelectionRange(length, length);\n    }\n\n    \/\/ See: https:\/\/stackoverflow.com\/questions\/879152\/how-do-i-make-javascript-beep\n    function beepAutoComplete() {\n        beep(350, 0, 0.01, 100);\n    }\n\n    function beepError() {\n        beep(400, 3, 0.03, 168);\n    }\n\n    \/\/ See: https:\/\/stackoverflow.com\/questions\/879152\/how-do-i-make-javascript-beep\n    \/\/ Beep with a given\n    \/\/ - Frequency in Hz\n    \/\/ - Type of waveform (0: sine, 1: square, 2: sawtooth, 3 triangle)\n    \/\/ - Volume - TODO what is the unit?\n    \/\/ - Duration in milliseconds\n    function beep(frequency, type, volume, duration) {\n        var oscillator = audioCtx.createOscillator();\n        var gainNode = audioCtx.createGain();\n\n        oscillator.connect(gainNode);\n        gainNode.connect(audioCtx.destination);\n\n        gainNode.gain.value = volume;\n        oscillator.frequency.value = frequency;\n        oscillator.type = type;\n\n        oscillator.start();\n\n        setTimeout(\n            function() {\n                oscillator.stop();\n            },\n            duration\n        );\n    }\n\n    \/\/ Update the text in the text field.\n    function updateVeld(cur) {\n        debug.textContent = debug.textContent + \"updateVeld cur \" + cur + \" - \";\n        \/\/ Get the characters before, at and after the current cursor position\n        beforeCursor = originalText.substring(0, cur - 1);\n        atCursor = originalText.substring((cur - 1), cur);\n        afterCursor =  originalText.substring(cur, originalText.length);\n        tekst.innerHTML = '<span style=\"color: green\">' + beforeCursor + '<\/span><span style=\"background-color: yellow; color: blue;\"><b>' + atCursor + '<\/b><\/span><span style=\"color: blue;\">' + afterCursor + '<\/span>';\n    }\n\n    function updateError(cur) {\n            tekst.innerHTML = '<span style=\"color: green\">' + beforeCursor.substring(0, (beforeCursor.length)) + '<\/span>' +'<span style=\"background-color: yellow; color: red\"><b>' + atCursor + '<\/b><\/span>' + afterCursor;\n    }\n\n\n    \/\/ Hide Duration, Accuray, Char\/s, Char\/min\n    function hideResults() {\n            document.getElementById(\"duration\").style.visibility = 'hidden';\n            document.getElementById(\"accuracy\").style.visibility = 'hidden';\n            document.getElementById(\"cps\").style.visibility = 'hidden';\n            document.getElementById(\"cpm\").style.visibility = 'hidden';\n    }\n\n    \/\/ Show Duration, Accuray, Char\/s, Char\/min\n    function showResults() {\n            debug.textContent = debug.textContent + \" 1 showResults \" + correctKeysPressed + \"\/\" + numberOfKeysPressed + \" - \";\n            end = new Date().getTime();\n            time = (end - start) \/ 1000;\n            accuracy = (correctKeysPressed \/ numberOfKeysPressed) * 100;\n            cps = numberOfKeysPressed \/ time;\n            cpm = cps * 60;\n            debug.textContent = debug.textContent + \" 2 showResults time \" + time + \"=\" + end + \"-\" + start + \" - \";\n            \/\/ Source - https:\/\/stackoverflow.com\/a\/11832950\n            \/\/ Posted by Brian Ustas, modified by community. See post 'Timeline' for change history\n            \/\/ Retrieved 2026-06-03, License - CC BY-SA 4.0\n            accuracy = Math.round((accuracy + Number.EPSILON) * 100) \/ 100;\n            time = Math.round((time + Number.EPSILON) * 100) \/ 100;\n            cps = Math.round((cps + Number.EPSILON) * 100) \/ 100;\n            cpm = Math.round(cpm);\n            document.getElementById(\"duration\").innerHTML = \"Duration <b style='color:green'>\" + time + \"<\/b> s \";\n            document.getElementById(\"accuracy\").innerHTML = \"Accuracy <b style='color:green'>\" + accuracy + \"<\/b> % \";\n            document.getElementById(\"cps\").innerHTML = \"Char\/second <b style='color:green'>\" + cps + \"<\/b>\";\n            document.getElementById(\"cpm\").innerHTML = \"Char\/minute <b style='color:green'>\" + cpm + \"<\/b>\";\n             \/\/ show duration and accuracy, characters per seconds and chars per minute\n             document.getElementById(\"duration\").style.visibility = 'visible';\n             document.getElementById(\"accuracy\").style.visibility = 'visible';\n             document.getElementById(\"cps\").style.visibility = 'visible';\n             document.getElementById(\"cpm\").style.visibility = 'visible';\n    }\n\n    \/\/ Auto-Complete special characters depending on selected mode.\n    \/\/ TODO Add functionality for the different autocomplete setting: \n    \/\/ TODO Punctuation, Caps, Numbers, Special Character and Space\n    function autoComplete() {\n        debug.textContent = debug.textContent + \" auto complete '\" + atCursor + \"' - \";\n        \/\/ Punctuation auto-complete when toggle button for F5 is active\n        if (!document.getElementById(\"F6\").disabled && punctuation.includes(atCursor)) complete();\n\n        \/\/ Capital characters auto-complete when toggle button for F6 is active\n        \/\/ Basically typing becomes case insensitive (is already handled in main script)\n\n        \/\/ Numbers auto-complete when toggle button for F7 is active\n        if (!document.getElementById(\"F8\").disabled && numbers.includes(atCursor)) complete();\n\n        \/\/ Special Characters auto-complete when toggle button for F8 is active\n        if (!document.getElementById(\"F9\").disabled && speci.includes(atCursor)) complete();\n\n        \/\/ Space auto-complete when toggle button for F8 is active\n        if (atCursor == String.fromCharCode(160)) {\n            atCursor = \" \";\n        }\n        if (!document.getElementById(\"F10\").disabled && space.includes(atCursor)) complete();\n\n    }\n\n    function complete() {\n        debug.textContent = debug.textContent + \"Complete '\" + atCursor + \"' - \";\n        cursorPosition = cursorPosition + 1;\n        if (cursorPosition > tekst.textContent.length) return;\n        \/\/ call this again to make sure consequtive occurences are also handled.\n        beepAutoComplete(); \/\/ to indicate auto-complete\n        beforeCursor = originalText.substring(0, cursorPosition -1);\n        atCursor = originalText.substring(cursorPosition - 1, cursorPosition);\n        afterCursor =  originalText.substring(cursorPosition, originalText.length);\n        debug.textContent = debug.textContent + \"Moved cursor to \" + cursorPosition + \" - '\" + atCursor + \"' - \";\n        autoComplete();\n    }\n\n    \/\/ F1-F10 mouse clicks\n    function hover(fKey) {\n        disabledOrigin = document.getElementById(fKey).disabled;\n        \/\/ debug.textContent='hover ' + fKey + '-' + disabledOrigin;\n        document.getElementById(fKey).disabled = false;\n        document.getElementById(fKey).style.background='orange';\n    }\n\n\/\/        debug.textContent='2 click ' + fKey + '-' + document.getElementById(fKey).disabled;\n\n    function clickFunction(fKey) {\n        debug.textContent='click ' + fKey + '-' + document.getElementById(fKey).disabled;\n        if (fKey == \"F1\") {\n            pressF1();\n            disabledOrigin = false;\n        } else if (fKey == \"F2\") {\n            pressF2();\n            disabledOrigin = false;\n        } else if (fKey == \"F3\") {\n            pressF3();\n            disabledOrigin = false;\n        } else if (fKey == \"F4\") {\n            pressF4();\n            disabledOrigin = false;\n        } else if (fKey == \"F5\") {\n            setTimeout(() => {autoComplete(); updateVeld(cursorPosition);}, 600);\n        } else {\n            document.getElementById(fKey).disabled = disabledOrigin;\n            toggleButton(document.getElementById(fKey));\n            disabledOrigin = document.getElementById(fKey).disabled;\n        }\n        document.getElementById(fKey).disabled = disabledOrigin;\n        document.getElementById(fKey).style.background='';\n    }\n\n    function leave(fKey) {\n        debug.textContent='leave ' + fKey + '-' + document.getElementById(fKey).disabled;\n        document.getElementById(fKey).disabled = disabledOrigin;\n        document.getElementById(fKey).style.background='';\n    }\n\n    function updateDebug(pressedKey) {\n        \/\/ debug.textContent = pressedKey.which + \"-\" + pressedKey.key + \"-\" + atCursor;\n        debug.textContent = \"-\" + beforeCursor +  \"-\" + atCursor + \"-\" + afterCursor + \"-\" + pressedKey.key + \"-\" + beforeCursor.slice(-1) + \"-\" + pressedKey.code + \"-\" + document.getElementById(\"F6\").disabled;\n    }\n\n\n\/\/ Read text from a given URL.\nfunction getText(url) {\n\/*\n    \/\/ Debug\n    firstLine = \"# Debug tekst voor auto wrap testen\";\n    secondLine = \"Vrijwilligerswerk is onbetaald werk dat u doet voor een organisatie of de maatschappij. Het is belangrijk dat dit werk niet de plek inneemt van een betaalde baan. U kiest er altijd zelf voor en het is nooit verplicht om bijvoorbeeld een uitkering te behouden.\";\n    source.innerHTML = '<i>' + firstLine.substring(2, firstLine.length) + '<\/i>';\n    originalText = secondLine;\n    updateVeld(cursorPosition);\n    return;\n*\/\n    \/\/ read text from URL location\n    var request = new XMLHttpRequest();\n    request.open('GET', url, true);\n    request.send(null);\n    request.onreadystatechange = function () {\n        debug.textContent = debug.textContent + url + \" - readyState: \" + request.readyState + \",  status: \" + request.status + \", content type: \" + request.getResponseHeader('Content-Type') + ' locale ' + document.documentElement.lang + \" - \";\n        if (request.readyState === 4 && request.status === 200) {\n        \/\/ if ((request.readyState === 3 || request.readyState === 4) && request.status === 200) {\n\n            var type = request.getResponseHeader('Content-Type');\n            if (type.indexOf(\"text\") !== 1) {\n                lines = request.responseText.split(\/\\r\\n|\\r|\\n\/);\n                firstLine = lines[0];\n                secondLine = lines[1];\n                if (firstLine.startsWith(\"#\")) {\n                    source.innerHTML = '<i>' + firstLine.substring(2, firstLine.length) + '<\/i>';\n                    originalText = secondLine;\n                } else {\n                    source.innerHTML = '<i>Source not specified<\/i>';\n                    originalText = request.responseText;\n                }\n                debug.textContent = debug.textContent + \" UpdateVeld - \";\n                updateVeld(cursorPosition);\n            } else {\n                tekst.innerHTML = '<span style=\"color: red\"><b>Unexpected content type ' + request.getResponseHeader('Content-Type') + ' for URL ' + url + '<\/b><\/span>';\n            }\n        } else {\n            tekst.innerHTML = '<span style=\"color: red\"><b>Unable to retrieve text from URL ' + url + ' Status: ' + request.status + ' readyState: ' + request.readyState + '<\/b><\/span>';\n        }\n    }\n}\n\n\n    function lineNumber(textIncludingCursor) {\n        var el = document.getElementById(\"veld\");\n        if (_buffer == null) {\n            _buffer = document.createElement('tekst');\n            _buffer.style.border = 'none';\n            _buffer.style.height = '0';\n            _buffer.style.overflow = 'hidden';\n            _buffer.style.padding = '0';\n            _buffer.style.position = 'absolute';\n            _buffer.style.left = '0';\n            _buffer.style.top = '0';\n            _buffer.style.zIndex = '-1';\n            document.body.appendChild(_buffer);\n        }\n        _buffer.value = el.value;\n        _buffer.innerHTML = el.innerHTML;\n\n        var newCodeElement = null;\n        var element = _buffer.querySelectorAll('code').forEach(element => {\n             newCodeElement = element;\n        })\n        newCodeElement.textContent = textIncludingCursor;\n\n        var positionInfo = el.getBoundingClientRect();\n        var height = positionInfo.height;\n        var width = positionInfo.width;\n        var cs = window.getComputedStyle(el);\n        var pl = parseInt(cs.paddingLeft);\n        var pr = parseInt(cs.paddingRight);\n        var pb = parseInt(cs.paddingBottom);\n        var pt = parseInt(cs.paddingTop);\n        var lh = parseInt(cs.lineHeight);\n\n        \/\/ Copy content width.\n        _buffer.style.width = (el.clientWidth - pl - pr) + 'px';\n\n        \/\/ Copy content width.\n        _buffer.style.width = (width - pl - pr) + 'px';\n\n        var bufResult = Math.floor(_buffer.scrollHeight \/ lh);\n        \/\/ var divResult = Math.floor(el.scrollHeight \/ lh);\n        return bufResult;\n    }\n\n    function scrollNow(textIncludingCursor) {\n        var line = lineNumber(textIncludingCursor);\n\n        if (line == 0) result = 1;\n        if (line > 7) {\n            return true;\n        }\n        return false;\n    }\n\n    function addUrl(location) {\n        urls.push(location);\n    }\n\n    async function getData() {\n        try {\n            const response = await fetch(apiurl);\n            if (!response.ok) {\n               throw new Error(`Response status: ${response.status}`);\n            }\n\n            const result = await response.json();\n            result.tree.forEach((item) => {\n                if (item.type === \"blob\") {\n                    addUrl(raw + item.path);\n                }\n            })\n        } catch (error) {\n            debug.textContent = debug.textContent + \" getData error: \" + error.message;\n        }\n    }\n\n    \/\/ Source - https:\/\/stackoverflow.com\/a\/11381730\n    \/\/ Posted by Michael Zaporozhets, modified by community. See post 'Timeline' for change history\n    \/\/ Retrieved 2026-06-11, License - CC BY-SA 4.0\n    window.mobileCheck = function() {\n        let check = false;\n        (function(a){if(\/(android|bb\\d+|meego).+mobile|avantgo|bada\\\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\\\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\\.(browser|link)|vodafone|wap|windows ce|xda|xiino\/i.test(a)||\/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\\-(n|u)|c55\\\/|capi|ccwa|cdm\\-|cell|chtm|cldc|cmd\\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\\-s|devi|dica|dmob|do(c|p)o|ds(12|\\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\\-|_)|g1 u|g560|gene|gf\\-5|g\\-mo|go(\\.w|od)|gr(ad|un)|haie|hcit|hd\\-(m|p|t)|hei\\-|hi(pt|ta)|hp( i|ip)|hs\\-c|ht(c(\\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\\-(20|go|ma)|i230|iac( |\\-|\\\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\\\/)|klon|kpt |kwc\\-|kyo(c|k)|le(no|xi)|lg( g|\\\/(k|l|u)|50|54|\\-[a-w])|libw|lynx|m1\\-w|m3ga|m50\\\/|ma(te|ui|xo)|mc(01|21|ca)|m\\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\\-2|po(ck|rt|se)|prox|psio|pt\\-g|qa\\-a|qc(07|12|21|32|60|\\-[2-7]|i\\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\\\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\\-|oo|p\\-)|sdk\\\/|se(c(\\-|0|1)|47|mc|nd|ri)|sgh\\-|shar|sie(\\-|m)|sk\\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\\-|v\\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\\-|tdg\\-|tel(i|m)|tim\\-|t\\-mo|to(pl|sh)|ts(70|m\\-|m3|m5)|tx\\-9|up(\\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\\-|your|zeto|zte\\-\/i.test(a.substr(0,4))) check = true;})(navigator.userAgent||navigator.vendor||window.opera);\n    return check;\n    };\n\n\/\/ Source - https:\/\/stackoverflow.com\/a\/11381730\n\/\/ Posted by Michael Zaporozhets, modified by community. See post 'Timeline' for change history\n\/\/ Retrieved 2026-06-11, License - CC BY-SA 4.0\nwindow.mobileAndTabletCheck = function() {\n  let check = false;\n  (function(a){if(\/(android|bb\\d+|meego).+mobile|avantgo|bada\\\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\\\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk\/i.test(a)||\/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\\-(n|u)|c55\\\/|capi|ccwa|cdm\\-|cell|chtm|cldc|cmd\\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\\-s|devi|dica|dmob|do(c|p)o|ds(12|\\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\\-|_)|g1 u|g560|gene|gf\\-5|g\\-mo|go(\\.w|od)|gr(ad|un)|haie|hcit|hd\\-(m|p|t)|hei\\-|hi(pt|ta)|hp( i|ip)|hs\\-c|ht(c(\\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\\-(20|go|ma)|i230|iac( |\\-|\\\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\\\/)|klon|kpt |kwc\\-|kyo(c|k)|le(no|xi)|lg( g|\\\/(k|l|u)|50|54|\\-[a-w])|libw|lynx|m1\\-w|m3ga|m50\\\/|ma(te|ui|xo)|mc(01|21|ca)|m\\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\\-2|po(ck|rt|se)|prox|psio|pt\\-g|qa\\-a|qc(07|12|21|32|60|\\-[2-7]|i\\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\\\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\\-|oo|p\\-)|sdk\\\/|se(c(\\-|0|1)|47|mc|nd|ri)|sgh\\-|shar|sie(\\-|m)|sk\\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\\-|v\\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\\-|tdg\\-|tel(i|m)|tim\\-|t\\-mo|to(pl|sh)|ts(70|m\\-|m3|m5)|tx\\-9|up(\\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\\-|your|zeto|zte\\-\/i.test(a.substr(0,4))) check = true;})(navigator.userAgent||navigator.vendor||window.opera);\n  return check;\n};\n\nfunction replaceNbsps(str) {\n  var re = new RegExp((String.fromCharCode(160)), \"g\");\n  return str.replace(re, \" \");\n}\n  <\/script>\n\n<div id=\"veld\" style=\"width:730px; height:300px; background-color:lightblue;  overflow: scroll; padding-right: 3px; padding-left: 3px; line-height:30px;\">\n\n<code id=\"tekst\" contenteditable=\"false\" style=\"font-size:26px; line-height:30px;\">\n  <span id=\"blauw\" style=\"color: blue\"><i>Text is loading...<\/i><\/span>\n<\/code>\n<\/div>\n<div align=\"center\">\n    <span id=\"source\" style=\"font-size:10px;\"><i>source<\/i><\/span>\n<\/div>\n<div>\n    <span id=\"duration\" style=\"font-size: 20px\">Duration: <b style=\"color:red\">0<\/b> s<\/span>&nbsp;\n    <span id=\"accuracy\" style=\"font-size: 20px\">Accuracy: <b style=\"color:red\">0<\/b> %<\/span>&nbsp;\n    <span id=\"cps\" style=\"font-size: 20px\">Char\/second: <b style=\"color:red\">0<\/b><\/span>&nbsp;\n    <span id=\"cpm\" style=\"font-size: 20px\">Char\/minute: <b style=\"color:red\">0<\/b><\/span>\n<\/div>\n  <p>\n    Autocomplete Presets and Text Refresh<br>\n    <button id=\"F1\" type=\"button\" onmouseover=\"hover('F1')\" onmouseleave=\"leave('F1')\" onclick=\"clickFunction('F1');\" disabled=\"\">Simple(F1)<\/button> \n    <button id=\"F2\" type=\"button\" onmouseover=\"hover('F2')\" onmouseleave=\"leave('F2')\" onclick=\"clickFunction('F2');\" disabled=\"\">Intermediate(F2)<\/button> \n    <button id=\"F3\" type=\"button\" onmouseover=\"hover('F3')\" onmouseleave=\"leave('F3')\" onclick=\"clickFunction('F3');\" disabled=\"\">Advanced(F3)<\/button>\n    <button id=\"F4\" type=\"button\" onmouseover=\"hover('F4')\" onmouseleave=\"leave('F4')\" onclick=\"clickFunction('F4');\" disabled=\"\">Type Test(F4)<\/button>\n    <button id=\"F5\" type=\"button\" onmouseover=\"hover('F5')\" onmouseleave=\"leave('F5')\" onclick=\"pressF5();clickFunction('F5');\" disabled=\"\">Refresh(F5)<\/button>\n    <br>Autocomplete settings<br>\n    <button id=\"F6\" type=\"button\" onmouseover=\"hover('F6')\" onmouseleave=\"leave('F6')\" onclick=\"clickFunction('F6')\" disabled=\"\">Punctuation(F6)<\/button>\n    <button id=\"F7\" type=\"button\" onmouseover=\"hover('F7')\" onmouseleave=\"leave('F7')\" onclick=\"clickFunction('F7')\" disabled=\"\">Caps(F7)<\/button>\n    <button id=\"F8\" type=\"button\" onmouseover=\"hover('F8')\" onmouseleave=\"leave('F8')\" onclick=\"clickFunction('F8')\" disabled=\"\">Numbers(F8)<\/button>\n    <button id=\"F9\" type=\"button\" onmouseover=\"hover('F9')\" onmouseleave=\"leave('F9')\" onclick=\"clickFunction('F9')\" disabled=\"\">Special Chars(F9)<\/button>\n    <button id=\"F10\" type=\"button\" onmouseover=\"hover('F10')\" onmouseleave=\"leave('F10')\" onclick=\"clickFunction('F10')\" disabled=\"\">Space(F10)<\/button>\n  <\/p>\n\n<div>\n  <p id=\"debug\">Debug area<\/p>\n<div><\/div><\/div>\n\n\n<style>.kb-table-of-content-nav.kb-table-of-content-id3217_30550b-38 .kb-table-of-content-wrap{padding-top:var(--global-kb-spacing-sm, 1.5rem);padding-right:var(--global-kb-spacing-sm, 1.5rem);padding-bottom:var(--global-kb-spacing-sm, 1.5rem);padding-left:var(--global-kb-spacing-sm, 1.5rem);}.kb-table-of-content-nav.kb-table-of-content-id3217_30550b-38 .kb-table-of-contents-title-wrap{padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;}.kb-table-of-content-nav.kb-table-of-content-id3217_30550b-38 .kb-table-of-contents-title{font-weight:regular;font-style:normal;}.kb-table-of-content-nav.kb-table-of-content-id3217_30550b-38 .kb-table-of-content-wrap .kb-table-of-content-list{font-weight:regular;font-style:normal;margin-top:var(--global-kb-spacing-sm, 1.5rem);margin-right:0px;margin-bottom:0px;margin-left:0px;}<\/style>\n\n\n<h2 class=\"wp-block-heading\">Manual<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Quick Start<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Select the difficulty level (F1 &#8211; F4) with the function keys or mouse buttons: <strong>Simple (F1)<\/strong>, <strong>Intermediate (F2)<\/strong>, <strong>Advanced (F3)<\/strong> or <strong>Type Test (F4)<\/strong>.<\/li>\n\n\n\n<li>Select <strong>Refresh (F5)<\/strong> to show a text from the selected difficulty level.<\/li>\n\n\n\n<li>The default difficulty level is the <strong>Simple (F1)<\/strong> mode.<\/li>\n\n\n\n<li>Note the yellow cursor in the top left corner of the text area.<\/li>\n\n\n\n<li>Type the characters you see at the cursor.<\/li>\n\n\n\n<li>If you&#8217;ve typed the correct chararcter the cursor wil advance to the next character.<\/li>\n\n\n\n<li>If you&#8217;ve typed a wrong character the cursor will stay in place, the expected character shows up in bold red. If your sound is enabled, you will also hear a short faint beep.<\/li>\n\n\n\n<li>The <strong>Simple (F1)<\/strong> level only focusses one typing the correct letter of the alphabet.<\/li>\n\n\n\n<li>No need to type spaces, digits or special characters. They will be autocompleted.<\/li>\n\n\n\n<li>No need to use Shift or Caps Lock. Uppercase is ignored.<\/li>\n\n\n\n<li>The results like duration, accuracy, characters\/second and characters\/minute will be displayed once you completed typing the text. During typing they are hidden.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Design Principles<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">This typing test is designed for people who need to relearn typing during a medical rehabilitation process, e.g. due to loss of fine motor skills in one or both hands caused by physical trauma or neurological damage. Several auto-complete options help avoiding key combinations and far key stretches to match typist&#8217;s current typing abbilities.<br>But in the Type Test mode all auto-completion is switched off and it becomes another regular online typing test.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Prerequisites<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>As with most typing tests, best results can be achieved when using a PC with a relative large screen, a physical keyboard and mouse. This typing test is not supported on mobile phones or tablets.<\/li>\n\n\n\n<li>Your browser needs to have Javascript enabled for this to work.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Features<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Duration, accuracy and typing speed are displayed when typing a text is completed<\/li>\n\n\n\n<li>Presets (F1-F4), Refresh (F5) and Auto-complete settings (F6-F10)<\/li>\n\n\n\n<li>4 preset modes with different levels of difficulties\n<ul class=\"wp-block-list\">\n<li>Simple (F1)<\/li>\n\n\n\n<li>Intermediate (F2)<\/li>\n\n\n\n<li>Advanced (F3)<\/li>\n\n\n\n<li>Type Text (F4)<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Presets (F1-F4) selection with the corresponding function key or mouse click<\/li>\n\n\n\n<li>A refresh option to load the next (randomly chosen) text: Refresh (F5)<\/li>\n\n\n\n<li>Refresh (F5) triggering on page load, with F5 key and by mouse click<\/li>\n\n\n\n<li>5 auto-complete settings that can be toggled by function keys or mouse clicks\n<ul class=\"wp-block-list\">\n<li>Punctuation (F6)<\/li>\n\n\n\n<li>Caps (F7)<\/li>\n\n\n\n<li>Numbers (F8)<\/li>\n\n\n\n<li>Special Characters (F9)<\/li>\n\n\n\n<li>Space (F10)<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Auto-complete settings (F6-F10) toggle with the corresponding function key or mouse click<\/li>\n\n\n\n<li>Faint audio-beep when character is auto-completed<\/li>\n\n\n\n<li>A slightly louder beep if the wrong character is typed<\/li>\n\n\n\n<li>Cursor doesn&#8217;t move and the expected character is shown in bold red if the wrong character is typed<\/li>\n\n\n\n<li>Auto-scroll for text that is larger than the visible text field when cursor gets near the end of the visible part<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Text Field<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The text field displays the text to be typed. Note the yellow cursor in the top left corner. It is not blinking. It indicates the next character to type. If characters are auto-completed the cursor will move to the next character to type.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"424\" src=\"https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/TextField-1024x424.jpg\" alt=\"\" class=\"wp-image-3966\" style=\"aspect-ratio:2.415086049273303;width:413px;height:auto\" srcset=\"https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/TextField-1024x424.jpg 1024w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/TextField-300x124.jpg 300w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/TextField-768x318.jpg 768w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/TextField-1536x636.jpg 1536w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/TextField.jpg 1629w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">If the wrong character is typed, the cursor stays in place and the expected character will be displayed bold red until the correct character is typed. The remaining text will turn black instead of blue. Correctly typed text will become green. If audio is enabled an error beep will sound.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"846\" height=\"146\" src=\"https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/wrongCharacter.jpg\" alt=\"\" class=\"wp-image-3967\" style=\"aspect-ratio:5.794417414713732;width:406px;height:auto\" srcset=\"https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/wrongCharacter.jpg 846w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/wrongCharacter-300x52.jpg 300w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/wrongCharacter-768x133.jpg 768w\" sizes=\"auto, (max-width: 846px) 100vw, 846px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Results <\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">Display Values<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">When the page is first loaded the results are shown with values 0 in red, because no typing occured yet.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"47\" src=\"https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/Results0-1024x47.jpg\" alt=\"\" class=\"wp-image-3975\" style=\"aspect-ratio:21.791044776119403;width:436px;height:auto\" srcset=\"https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/Results0-1024x47.jpg 1024w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/Results0-300x14.jpg 300w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/Results0-768x35.jpg 768w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/Results0.jpg 1184w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">During typing this line will disappear. When the last character in the text is typed results are calculated and displayed again, this time in green.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"36\" src=\"https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/ResultsGreen-1024x36.jpg\" alt=\"\" class=\"wp-image-3976\" style=\"aspect-ratio:28.44155914607752;width:569px;height:auto\" srcset=\"https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/ResultsGreen-1024x36.jpg 1024w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/ResultsGreen-300x10.jpg 300w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/ResultsGreen-768x27.jpg 768w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/ResultsGreen.jpg 1497w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h5 class=\"wp-block-heading\">Duration<\/h5>\n\n\n\n<p class=\"wp-block-paragraph\">When the first correct key press is detected a start time (<math xmlns=\"http:\/\/www.w3.org\/1998\/Math\/MathML\"><mrow><mi>s<\/mi><\/mrow> <mn><\/mn> <\/math>) is set. When the last character in the text is typed a end time (<math xmlns=\"http:\/\/www.w3.org\/1998\/Math\/MathML\"><mrow><mi>e<\/mi><\/mrow> <mn><\/mn> <\/math>) is set. The duration (<math xmlns=\"http:\/\/www.w3.org\/1998\/Math\/MathML\"><mrow><mi>d<\/mi><\/mrow> <mn><\/mn> <\/math>) is the end time minus the start time (in milliseconds) divided by 1000 to convert to seconds.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><math xmlns=\"http:\/\/www.w3.org\/1998\/Math\/MathML\">\n<mrow>\n    <mi>d<\/mi>\n    <mo>=<\/mo>\n    <mfrac>\n        <mrow>\n            <mo>(<\/mo><mi>e<\/mi><mo>\u2212<\/mo><mi>s<\/mi><mo>)<\/mo>\n        <\/mrow>\n        <mrow><mi>1000<\/mi><\/mrow>\n    <\/mfrac>\n<\/mrow>\n<\/math><\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Accuracy<\/h5>\n\n\n\n<p class=\"wp-block-paragraph\">The accuracy percentage (<math xmlns=\"http:\/\/www.w3.org\/1998\/Math\/MathML\"> <mrow><mi>a<\/mi><\/mrow> <mn><\/mn> <\/math>) is calculated from the number of correct pressed keys (<math xmlns=\"http:\/\/www.w3.org\/1998\/Math\/MathML\"><mrow><mi>c<\/mi><\/mrow> <mn><\/mn> <\/math>) divided by the total number of pressed keys (<math xmlns=\"http:\/\/www.w3.org\/1998\/Math\/MathML\"><mrow><mi>t<\/mi><\/mrow> <mn><\/mn> <\/math>) mutiplied by hundred.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><math xmlns=\"http:\/\/www.w3.org\/1998\/Math\/MathML\"><mrow><msup><mi>a<\/mi><mn><\/mn><\/msup><mo>=<\/mo><mo>(<\/mo><mfrac><mrow><mi>c<\/mi><mn><\/mn><\/mrow><mrow><mi>t<\/mi><mn><\/mn><\/mrow><\/mfrac><mo>)<\/mo><msrow><mo>\u00d7<\/mo><\/msrow><mn>100<\/mn><\/mrow><\/math><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Note that autocompleted characters are not counted. Only key presses contribute to the accuracy calculation.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Characters per Second<\/h5>\n\n\n\n<p class=\"wp-block-paragraph\">The charaters per second (<math xmlns=\"http:\/\/www.w3.org\/1998\/Math\/MathML\"><mrow><mi>cps<\/mi><\/mrow><\/math>) are calculated from the total number of pressed keys (<math xmlns=\"http:\/\/www.w3.org\/1998\/Math\/MathML\"><mrow><mi>t<\/mi><\/mrow><\/math>) divided by the duration (<math xmlns=\"http:\/\/www.w3.org\/1998\/Math\/MathML\"><mrow><mi>d<\/mi><\/mrow><\/math>).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><math xmlns=\"http:\/\/www.w3.org\/1998\/Math\/MathML\"><mrow><mi>cps<\/mi><mo>=<\/mo><mfrac><mrow><mi>t<\/mi><\/mrow><mrow><mi>d<\/mi><\/mrow><\/mfrac><\/mrow><\/math><\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Characters per Minute<\/h5>\n\n\n\n<p class=\"wp-block-paragraph\">The charaters per minute (<math xmlns=\"http:\/\/www.w3.org\/1998\/Math\/MathML\"><mrow><mi>cpm<\/mi><\/mrow><\/math>) are the characters per second (<math xmlns=\"http:\/\/www.w3.org\/1998\/Math\/MathML\"><mrow><mi>cps<\/mi><\/mrow><\/math>) times 60.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><math xmlns=\"http:\/\/www.w3.org\/1998\/Math\/MathML\"><mrow>\n        <mi>cpm<\/mi>\n        <mo>=<\/mo>\n        <mi>cps<\/mi>\n        <mo>\u00d7<\/mo>\n        <mi>60<\/mi>\n    <\/mrow>\n<\/math><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Preset Buttons<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Use F1 &#8211; F4 to select a auto-complete preset and set the text difficulty level. If you hover the mouse over any of the buttons the background colour will turn orange.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"90\" src=\"https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/06\/afbeelding-19-1024x90.png\" alt=\"\" class=\"wp-image-4302\" style=\"aspect-ratio:11.376623827515592;width:444px;height:auto\" srcset=\"https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/06\/afbeelding-19-1024x90.png 1024w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/06\/afbeelding-19-300x26.png 300w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/06\/afbeelding-19-768x67.png 768w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/06\/afbeelding-19.png 1303w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">If you click the button background colour will become (or stay) dark blue. The presets not selected will become light blue.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"87\" src=\"https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/06\/afbeelding-18-1024x87.png\" alt=\"\" class=\"wp-image-4300\" style=\"aspect-ratio:11.771029341470479;width:447px;height:auto\" srcset=\"https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/06\/afbeelding-18-1024x87.png 1024w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/06\/afbeelding-18-300x25.png 300w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/06\/afbeelding-18-768x65.png 768w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/06\/afbeelding-18.png 1308w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">Simple (F1)<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">All auto-complete options are on.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"206\" src=\"https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/SimpleF1-1024x206.jpg\" alt=\"\" class=\"wp-image-3944\" style=\"aspect-ratio:4.97105869703143;width:547px;height:auto\" srcset=\"https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/SimpleF1-1024x206.jpg 1024w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/SimpleF1-300x60.jpg 300w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/SimpleF1-768x154.jpg 768w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/SimpleF1-1536x309.jpg 1536w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/SimpleF1.jpg 1602w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"> The typist only needs to worry about pressing the key with the correct character from the alphabet and can disregard uppercase. <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"307\" src=\"https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/keyboardSimpleF1-1024x307.jpg\" alt=\"\" class=\"wp-image-3943\"\/ style=\"object-position: 14% 50%;\" srcset=\"https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/keyboardSimpleF1-1024x307.jpg 1024w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/keyboardSimpleF1-300x90.jpg 300w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/keyboardSimpleF1-768x230.jpg 768w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/keyboardSimpleF1-1536x461.jpg 1536w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/keyboardSimpleF1-2048x614.jpg 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">Intermediate (F2)<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The Caps (F7) and Space (F10) auto-complete options are off.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"206\" src=\"https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/IntermediateF2-1024x206.jpg\" alt=\"\" class=\"wp-image-3945\" style=\"aspect-ratio:4.97105869703143;width:557px;height:auto\" srcset=\"https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/IntermediateF2-1024x206.jpg 1024w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/IntermediateF2-300x60.jpg 300w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/IntermediateF2-768x154.jpg 768w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/IntermediateF2-1536x309.jpg 1536w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/IntermediateF2.jpg 1606w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">This means that the typist must also use the Shift key (or Caps Lock) for capital characters in the text and the Space Bar for Space.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"307\" src=\"https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/keyboardIntermediateF2-1-1024x307.jpg\" alt=\"\" class=\"wp-image-3947\" srcset=\"https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/keyboardIntermediateF2-1-1024x307.jpg 1024w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/keyboardIntermediateF2-1-300x90.jpg 300w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/keyboardIntermediateF2-1-768x230.jpg 768w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/keyboardIntermediateF2-1-1536x461.jpg 1536w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/keyboardIntermediateF2-1-2048x614.jpg 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">Advanced (F3)<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Except for Special Chars (F9), all auto-complete options are off.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"201\" src=\"https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/AdvancedF3-1024x201.jpg\" alt=\"\" class=\"wp-image-3952\" style=\"aspect-ratio:5.094800258609572;width:545px;height:auto\" srcset=\"https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/AdvancedF3-1024x201.jpg 1024w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/AdvancedF3-300x59.jpg 300w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/AdvancedF3-768x151.jpg 768w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/AdvancedF3-1536x302.jpg 1536w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/AdvancedF3.jpg 1604w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">This means the typist needs to type punctuation, capitals, numbers and spaces.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"307\" src=\"https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/keyboardAdvancedF3-1024x307.jpg\" alt=\"\" class=\"wp-image-3953\" srcset=\"https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/keyboardAdvancedF3-1024x307.jpg 1024w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/keyboardAdvancedF3-300x90.jpg 300w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/keyboardAdvancedF3-768x230.jpg 768w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/keyboardAdvancedF3-1536x461.jpg 1536w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/keyboardAdvancedF3-2048x614.jpg 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">Type Text (F4)<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">All auto-complete options are off.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"207\" src=\"https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/TypeTextF4-1024x207.jpg\" alt=\"\" class=\"wp-image-3958\" style=\"aspect-ratio:4.946916681944413;width:534px;height:auto\" srcset=\"https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/TypeTextF4-1024x207.jpg 1024w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/TypeTextF4-300x61.jpg 300w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/TypeTextF4-768x156.jpg 768w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/TypeTextF4-1536x311.jpg 1536w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/TypeTextF4.jpg 1605w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The typist must use any key combination required to display the correct and case-sensitive character from the text.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"307\" src=\"https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/keyboardTypeTextF4-1024x307.jpg\" alt=\"\" class=\"wp-image-3956\" srcset=\"https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/keyboardTypeTextF4-1024x307.jpg 1024w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/keyboardTypeTextF4-300x90.jpg 300w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/keyboardTypeTextF4-768x230.jpg 768w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/keyboardTypeTextF4-1536x461.jpg 1536w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/keyboardTypeTextF4-2048x614.jpg 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Characters that don&#8217;t apear on the keyboard can be displayed by using key combinations like &lt;Alt&gt; + &lt;numbers on numeric keypad&gt;. (Make sure Num Lock is on.) See <a href=\"https:\/\/support.microsoft.com\/en-US\/Word\/insert-ascii-or-unicode-latin-based-symbols-and-characters\">https:\/\/support.microsoft.com\/en-US\/Word\/insert-ascii-or-unicode-latin-based-symbols-and-characters<\/a>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"307\" src=\"https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/keyboardAltNumericKeyPad-1024x307.jpg\" alt=\"\" class=\"wp-image-3957\" srcset=\"https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/keyboardAltNumericKeyPad-1024x307.jpg 1024w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/keyboardAltNumericKeyPad-300x90.jpg 300w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/keyboardAltNumericKeyPad-768x230.jpg 768w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/keyboardAltNumericKeyPad-1536x461.jpg 1536w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/keyboardAltNumericKeyPad-2048x614.jpg 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><em>Example:<\/em> <strong>&lt;Alt&gt; + 0176<\/strong> will display a degree sign \u00b0<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Techniques like &#8220;chained dead keys&#8221;, combining characters and compose keys can also be used to create characters not available on the keyboard. This might differ between keyboard layouts and OS locales. Search for more info online.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Refresh (F5) Button<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Press the F5 function key or click the Refresh button to jump to another text. The button background colour will stay light blue.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Auto-complete Buttons<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The Preset Buttons will select some of the auto-complete buttons to a desired combination. Regardless of the Preset you can toggle the auto-complete buttons by using F6 &#8211; F10 function keys or using the mouse to click the buttons. This allows you to choose your own combination of auto-complete options.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"98\" src=\"https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/AutocompleteToggle-1024x98.jpg\" alt=\"\" class=\"wp-image-3959\" style=\"aspect-ratio:10.448472978185029;width:543px;height:auto\" srcset=\"https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/AutocompleteToggle-1024x98.jpg 1024w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/AutocompleteToggle-300x29.jpg 300w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/AutocompleteToggle-768x74.jpg 768w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/AutocompleteToggle-1536x147.jpg 1536w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/07\/AutocompleteToggle.jpg 1604w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">Punctuation (F6) button<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">When displayed with a dark blue background, the auto-complete option for Punctuaton is switched on. No need to type punctuation characters like <strong>.?!,;:-\u2013\u2014()[]{}'&#8221;<\/strong>. They are auto-completed and the cursor moves to the next character.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Caps (F7) button<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">When displayed with a dark blue background, the auto-complete option for Captial Chararacters  is switched on. The typing becomes cases-insensitive. This means that the typist doesn&#8217;t have to use the key combination Shift + &lt;character key&gt; and only has to type the lower-case characters. It will be automatically converted to upper-case where needed in the text.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Numbers (F8) button<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">When displayed with a dark blue background, the auto-complete option for Numbers is switched on. No need to type the numbers 0123456789. They are auto-completed and the cursor moves to the next character.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Special Chars (F9) button<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">When displayed with a dark blue background, the auto-complete option for Special Characters is switched on. No need to type special characters like #$%^&amp;*_+`|\\\u00b0\u00a3. They are auto-completed and the cursor moves to the next character. More special characters may be added over time.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Space (F10) button<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">When displayed with a dark blue background, the auto-complete option for Space is switched on. No need to use the space bar. Spaces are auto-completed and the cursor moves to the next character.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Scroll Text<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Sometimes the text that needs to be typed is a bit longer and takes up more space than is visible in the text field. You can scroll it using the scrollbar on the right of the text field. Or the scroll wheel of you mouse while hovering over the text field. Allthough manual scrolling is not really needed.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"459\" src=\"https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/06\/TextFieldScroll-1024x459.jpg\" alt=\"\" class=\"wp-image-4003\" style=\"aspect-ratio:2.230937651437629;width:506px;height:auto\" srcset=\"https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/06\/TextFieldScroll-1024x459.jpg 1024w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/06\/TextFieldScroll-300x134.jpg 300w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/06\/TextFieldScroll-768x344.jpg 768w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/06\/TextFieldScroll-1536x688.jpg 1536w, https:\/\/fotografeer.nl\/wp-content\/uploads\/2026\/06\/TextFieldScroll.jpg 1645w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">Auto Scroll<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Auto-scroll applies for text that is larger than the visible text field when the cursor gets near the end of the visible part. The text is automatically scrolled to the bottom to reveal the next part of the text to the typist, allowing uninterrupted typing experience.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Scroll Down (F11)<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">For a scrollable text the F11 function key can be used to jump to the bottom.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Scroll Up (F12)<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">For a scrollable text that has been scrolled down, the F12 function key can be used to jump back to the top.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Change History<\/h2>\n\n\n\n<h3 class=\"wp-block-heading has-theme-palette-7-color has-text-color has-link-color wp-elements-b20079bdd45b93bfe6adf88276221715\">V1.0<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li class=\"has-theme-palette-7-color has-text-color has-link-color wp-elements-555df60daa6ee261cdbb640d4c14a9a7\">TODO: First release and public availability<\/li>\n<\/ul>\n\n\n\n<h5 class=\"wp-block-heading has-theme-palette-7-color has-text-color has-link-color wp-elements-ad8195de7607424f53441d0185619417\">Fixed issues in this version<\/h5>\n\n\n\n<ul class=\"wp-block-list\">\n<li class=\"has-theme-palette-7-color has-text-color has-link-color wp-elements-ef55897a231eff025d0cda2b4ebf22cd\"><s><em>When clicking refresh, text is not scrolled to the top<\/em><\/s><\/li>\n\n\n\n<li class=\"has-theme-palette-7-color has-text-color has-link-color wp-elements-b8a62569b985dc755756ba10442586ee\"><s><em>The degree sign &#8220;\u00b0&#8221; is not auto-completed. (Alt + 0176 on numeric keypad.)<\/em><\/s><\/li>\n\n\n\n<li class=\"has-theme-palette-7-color has-text-color has-link-color wp-elements-25bb9e4d8c77c5db0de07e122af7a329\"><s><em>trading.txt is too long for proper scrolling.<\/em><\/s><\/li>\n\n\n\n<li class=\"has-theme-palette-7-color has-text-color has-link-color wp-elements-33ae7f9dd9de8d9aabcb7c4d54e05376\"><s><em>budget.txt is too long for proper scrolling.<\/em><\/s><\/li>\n\n\n\n<li class=\"has-theme-palette-7-color has-text-color has-link-color wp-elements-23d4447f13e46db6a307af17671230cf\"><s><em>health.txt might be too long for proper scrolling.<\/em><\/s><\/li>\n\n\n\n<li class=\"has-theme-palette-7-color has-text-color has-link-color wp-elements-b21d468fc9cd206a59927a05aed22d05\"><s><em>In preset mode F2 with Caps auto-complete swithed off, uppercase is still ignored.<\/em><\/s><\/li>\n\n\n\n<li class=\"has-theme-palette-7-color has-text-color has-link-color wp-elements-85eef22946badb0cc72a26e53e17e0c1\"><s><em>Missing extensive manual<\/em><\/s>.<\/li>\n\n\n\n<li class=\"has-theme-palette-7-color has-text-color has-link-color wp-elements-4665a9aca5a23cfb84aa5d083fde3486\"><s><em>Education.txt is to long for proper scrolling.<\/em><\/s><\/li>\n\n\n\n<li class=\"has-theme-palette-7-color has-text-color has-link-color wp-elements-d45a766608fc4bdf4f8308dc90a4e5a0\"><s><em>When punctuation auto-complete is on, the last period is not auto-completed.<\/em><\/s><\/li>\n\n\n\n<li class=\"has-theme-palette-7-color has-text-color has-link-color wp-elements-ee6eae91fb4b3ff0bf7bcaad25c4e6ea\"><em><s>Doesn&#8217;t work on tablet and mobile phone. Show warning if detected.<\/s><\/em><\/li>\n\n\n\n<li class=\"has-theme-palette-7-color has-text-color has-link-color wp-elements-88ac045647d23bc1ea6868409339d76d\"><strong><em>Alt code (e.g. Alt + 0128 =&gt; \u20ac) don&#8217;t work!<\/em><\/strong><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">v0.9<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Development and beta test version<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Known issues<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Only tested on Firefox 151.0.2 (64 bits)  and<br>Microsoft Edge 149.0.4022.69 (Offici\u00eble build) (64-bits) browsers<\/li>\n\n\n\n<li>When space auto-complete is off, cursor is not shown at the end of line before wrapping.<\/li>\n\n\n\n<li>When multiple succesive characters are auto-completed the sound increases in volume. Especially when there are 10 or more of these.<\/li>\n\n\n\n<li>Occasionally typing freezes. Not clear what causes this. Wasn&#8217;t able to reproduce.<\/li>\n\n\n\n<li>Green outlined keys in images in manual may not be entirely correct.<\/li>\n\n\n\n<li>A lot of special characters like umlaut, accent circonflex are not yet supported.<\/li>\n\n\n\n<li>Ocassionly, text isn&#8217;t shown on page load. Then select difficulty (F1- F4) en Refresh (F5).<\/li>\n\n\n\n<li>Backspace not supported (yet). No need?<\/li>\n\n\n\n<li>When the end of the word is at the edge of the right border of the text field pressing space will make the text jump around a bit. Leave in this version.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Disclaimer<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">THIS PROGRAM IS PROVIDED &#8220;AS IS&#8221;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THIS SOFTWARE OR THE USE OR OTHER DEALINGS IN THIS PROGRAM.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>If you need to relearn typing due to physical trauma or neurological damage try this type test. It features several auto-complete options that avoid key combinations and far key stretches to help your medical rehabilitation in  a step-by-step fashion.<\/p>\n","protected":false},"author":2,"featured_media":3943,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_kad_post_transparent":"","_kad_post_title":"","_kad_post_layout":"","_kad_post_sidebar_id":"","_kad_post_content_style":"","_kad_post_vertical_padding":"","_kad_post_feature":"","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"_kad_post_classname":"","footnotes":""},"categories":[176],"tags":[178,180,172,162],"class_list":["post-3217","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-revalidation___en","tag-medical-rehabilitation","tag-rehab","tag-test","tag-typing"],"lang":"en","translations":{"en":3217,"nl":4157},"pll_sync_post":{},"_links":{"self":[{"href":"https:\/\/fotografeer.nl\/index.php?rest_route=\/wp\/v2\/posts\/3217","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fotografeer.nl\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fotografeer.nl\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fotografeer.nl\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/fotografeer.nl\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3217"}],"version-history":[{"count":709,"href":"https:\/\/fotografeer.nl\/index.php?rest_route=\/wp\/v2\/posts\/3217\/revisions"}],"predecessor-version":[{"id":4484,"href":"https:\/\/fotografeer.nl\/index.php?rest_route=\/wp\/v2\/posts\/3217\/revisions\/4484"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/fotografeer.nl\/index.php?rest_route=\/wp\/v2\/media\/3943"}],"wp:attachment":[{"href":"https:\/\/fotografeer.nl\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3217"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fotografeer.nl\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3217"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fotografeer.nl\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3217"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}